From 4ee3a06b7cc1e05fbc8e4a900f0b9210a0dd765a Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 00:44:52 -0400 Subject: [PATCH 01/10] :construction: some ia progress to set the google 0auth --- api/google_manager.py | 155 ++++++++++++++++++ api/main.py | 5 + .../auth/login/login.component.html | 4 +- .../components/auth/login/login.component.ts | 7 +- 4 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 api/google_manager.py diff --git a/api/google_manager.py b/api/google_manager.py new file mode 100644 index 0000000..06721dc --- /dev/null +++ b/api/google_manager.py @@ -0,0 +1,155 @@ +import datetime +import os +import logging +from dotenv import load_dotenv +from fastapi import FastAPI, HTTPException, Request +from fastapi.responses import JSONResponse, RedirectResponse +import httpx +from fastapi.middleware.cors import CORSMiddleware +from motor.motor_asyncio import AsyncIOMotorClient +from bson import ObjectId +from user_manager import UserManager + +# Configuration de logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +load_dotenv() + +app = FastAPI() + +mongo_client = AsyncIOMotorClient(os.getenv("url")) +db = mongo_client["shipfast"] + +google_client_id = os.getenv("google_client_id") +google_client_secret = os.getenv("google_client_secret") +google_redirect_uri = os.getenv("google_redirect_uri") + +# En local +origins = ["http://localhost:4200"] + +# En production +# origins = ["https://ship-faster.netlify.app"] + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +def serialize_doc(doc): + """Convert MongoDB document to serializable format""" + if isinstance(doc, ObjectId): + return str(doc) + if isinstance(doc, dict): + return {k: serialize_doc(v) for k, v in doc.items()} + if isinstance(doc, list): + return [serialize_doc(i) for i in doc] + return doc + +class GoogleManager: + def __init__(self, db): + self.db = db + self.user_manager = UserManager(db) + + async def save_google_user(self, user_data): + try: + # Vérifiez si l'utilisateur existe déjà par email + existing_user = await self.db.users.find_one({"email": user_data["email"]}) + if existing_user: + logger.info("Email already registered: %s", user_data["email"]) + raise HTTPException( + status_code=400, + detail="Email already registered.", + ) + + creation_date = datetime.datetime.utcnow() + user_data["come_from"] = "google" + user_data["creation_month"] = creation_date.strftime("%B") + user_data["creation_year"] = creation_date.year + + # Insérez l'utilisateur dans la base de données + result = await self.db.users.insert_one(user_data) + logger.info("User created with ID: %s", result.inserted_id) + + return JSONResponse( + content={"message": "Google user created successfully"} + ) + except Exception as e: + logger.error("Error saving Google user: %s", str(e)) + raise HTTPException( + status_code=500, + detail=f"Error saving Google user: {str(e)}" + ) + + async def google_user_info(self, access_token: str): + user_info_url = "https://www.googleapis.com/oauth2/v1/userinfo" + headers = { + "Authorization": f"Bearer {access_token}" + } + async with httpx.AsyncClient() as client: + user_info_response = await client.get(user_info_url, headers=headers) + + user_info = user_info_response.json() + + # Préparer les données utilisateur + user_data = { + "username": user_info.get("email"), + "name": user_info.get("name"), + "email": user_info.get("email"), + "google_id": user_info.get("id"), + "picture": user_info.get("picture"), + "locale": user_info.get("locale") + } + + # Enregistrer l'utilisateur dans la base de données + user_created = await self.save_google_user(user_data) + + return serialize_doc(user_data) + +# Initialisation de GoogleManager +google_manager_instance = GoogleManager(db) + +@app.get("/api/google-login") +async def google_login(): + google_auth_endpoint = "https://accounts.google.com/o/oauth2/v2/auth" + params = { + "client_id": google_client_id, + "response_type": "code", + "redirect_uri": google_redirect_uri, + "scope": "openid email profile", + "access_type": "offline", + "prompt": "consent" + } + url = f"{google_auth_endpoint}?{'&'.join([f'{key}={value}' for key, value in params.items()])}" + return RedirectResponse(url) + +@app.get("/api/google-callback") +async def google_callback(request: Request): + code = request.query_params.get('code') + token_url = "https://oauth2.googleapis.com/token" + + token_data = { + "code": code, + "client_id": google_client_id, + "client_secret": google_client_secret, + "redirect_uri": google_redirect_uri, + "grant_type": "authorization_code" + } + + headers = {'Content-Type': 'application/x-www-form-urlencoded'} + async with httpx.AsyncClient() as client: + token_response = await client.post(token_url, data=token_data, headers=headers) + + token_response_json = token_response.json() + access_token = token_response_json.get("access_token") + id_token = token_response_json.get("id_token") + + if not access_token or not id_token: + raise HTTPException(status_code=400, detail="Failed to obtain access token from Google") + + user_data = await google_manager_instance.google_user_info(access_token) + + return JSONResponse(content=user_data) diff --git a/api/main.py b/api/main.py index fd5b5e5..ee6f0cc 100644 --- a/api/main.py +++ b/api/main.py @@ -7,17 +7,22 @@ from pydantic import BaseModel from motor.motor_asyncio import AsyncIOMotorClient from github_manager import app as github_manager +from google_manager import app as google_manager load_dotenv() app = FastAPI() app.include_router(github_manager.router) +app.include_router(google_manager.router) mongo_client = AsyncIOMotorClient(os.getenv("url")) db = mongo_client["shipfast"] github_client_id = os.getenv("github_client_id") github_client_secret = os.getenv("github_client_secret") +google_client_id = os.getenv("google_client_id") +google_client_secret = os.getenv("google_client_secret") +google_redirect_uri = os.getenv("google_redirect_uri") user_manager = UserManager(db) diff --git a/app/src/app/components/auth/login/login.component.html b/app/src/app/components/auth/login/login.component.html index b40f20f..45bfb3d 100644 --- a/app/src/app/components/auth/login/login.component.html +++ b/app/src/app/components/auth/login/login.component.html @@ -11,11 +11,11 @@ Apple logo - - diff --git a/app/src/app/components/auth/login/login.component.ts b/app/src/app/components/auth/login/login.component.ts index ad3e11b..8bd8ddd 100644 --- a/app/src/app/components/auth/login/login.component.ts +++ b/app/src/app/components/auth/login/login.component.ts @@ -63,11 +63,16 @@ export class LoginComponent { }, 100); } - openLogin() { + githubAuth() { const url = `${environment.apiUrl}/api/github-login` window.location.href = url; } + googleAuth() { + const url = `${environment.apiUrl}/api/google-login` + window.location.href = url; + } + localUser(data: any) { this.name = data.name; this.username = data.username; From 109a25b206c049299479e0b14d2edce82f1e36f5 Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 01:02:16 -0400 Subject: [PATCH 02/10] :sparkles: update saved infos --- api/google_manager.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/api/google_manager.py b/api/google_manager.py index 06721dc..142604c 100644 --- a/api/google_manager.py +++ b/api/google_manager.py @@ -96,12 +96,10 @@ async def google_user_info(self, access_token: str): # Préparer les données utilisateur user_data = { - "username": user_info.get("email"), "name": user_info.get("name"), "email": user_info.get("email"), - "google_id": user_info.get("id"), - "picture": user_info.get("picture"), - "locale": user_info.get("locale") + "come_from": "google", + "verified_email": user_info.get("verified_email"), } # Enregistrer l'utilisateur dans la base de données From 5c8e8797288ca531d3b250c7d67f121e742a7f15 Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 18:24:00 -0400 Subject: [PATCH 03/10] :construction: try to do the same we do for github with google accounts --- app/src/app/app-routing.module.ts | 5 +++ app/src/app/app.module.ts | 4 +- .../components/auth/login/login.component.ts | 2 +- .../auth/signup/signup.component.ts | 3 +- .../username-creation.component.ts | 3 +- .../home/header/header.component.ts | 8 +--- .../github-portal/github-portal.component.ts | 2 +- .../google-portal.component.html | 3 ++ .../google-portal/google-portal.component.ts | 43 +++++++++++++++++++ .../display-profile.component.ts | 4 +- app/src/app/guard/no-auth.guard.ts | 2 +- app/src/app/guard/profile.guard.ts | 2 +- .../{ => auth}/auth-github.service.ts | 2 +- .../app/services/auth/auth-google.service.ts | 21 +++++++++ .../app/services/{ => auth}/auth.service.ts | 6 +-- .../app/services/{ => auth}/token.service.ts | 0 16 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 app/src/app/components/portal/google-portal/google-portal.component.html create mode 100644 app/src/app/components/portal/google-portal/google-portal.component.ts rename app/src/app/services/{ => auth}/auth-github.service.ts (95%) create mode 100644 app/src/app/services/auth/auth-google.service.ts rename app/src/app/services/{ => auth}/auth.service.ts (82%) rename app/src/app/services/{ => auth}/token.service.ts (100%) diff --git a/app/src/app/app-routing.module.ts b/app/src/app/app-routing.module.ts index 0127801..05ee960 100644 --- a/app/src/app/app-routing.module.ts +++ b/app/src/app/app-routing.module.ts @@ -8,6 +8,7 @@ import { NoAuthGuard } from './guard/no-auth.guard'; import { UsernameCreationComponent } from './components/auth/username-creation/username-creation.component'; import { GithubPortalComponent } from './components/portal/github-portal/github-portal.component'; import { ProfileComponent } from './components/profile/profile/profile.component'; +import { GooglePortalComponent } from './components/portal/google-portal/google-portal.component'; const routes: Routes = [ { @@ -18,6 +19,10 @@ const routes: Routes = [ path: 'github-portal', component: GithubPortalComponent, }, + { + path: 'google-portal', + component: GooglePortalComponent, + }, { path: 'auth', children: [ diff --git a/app/src/app/app.module.ts b/app/src/app/app.module.ts index fff22b8..2ae445f 100644 --- a/app/src/app/app.module.ts +++ b/app/src/app/app.module.ts @@ -13,6 +13,7 @@ import { ProfileComponent } from './components/profile/profile/profile.component import { UsernameCreationComponent } from './components/auth/username-creation/username-creation.component'; import { GithubPortalComponent } from './components/portal/github-portal/github-portal.component'; import { EditProfileComponent } from './components/profile/edit-profile/edit-profile.component'; +import { GooglePortalComponent } from './components/portal/google-portal/google-portal.component'; @NgModule({ declarations: [ @@ -25,7 +26,8 @@ import { EditProfileComponent } from './components/profile/edit-profile/edit-pro GithubPortalComponent, ProfileComponent, DisplayProfileComponent, - EditProfileComponent + EditProfileComponent, + GooglePortalComponent ], imports: [ BrowserModule, diff --git a/app/src/app/components/auth/login/login.component.ts b/app/src/app/components/auth/login/login.component.ts index 8bd8ddd..3a914f9 100644 --- a/app/src/app/components/auth/login/login.component.ts +++ b/app/src/app/components/auth/login/login.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { AuthService } from 'src/app/services/auth.service'; import { AuthReceiveLoginUser } from 'src/app/models/login-user.model'; +import { AuthService } from 'src/app/services/auth/auth.service'; import { environment } from 'src/environments/environment.development'; @Component({ diff --git a/app/src/app/components/auth/signup/signup.component.ts b/app/src/app/components/auth/signup/signup.component.ts index 81fa794..1e8cca4 100644 --- a/app/src/app/components/auth/signup/signup.component.ts +++ b/app/src/app/components/auth/signup/signup.component.ts @@ -1,8 +1,7 @@ import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Router } from '@angular/router'; import { AuthCreateUser } from 'src/app/models/create-user.model'; -import { AuthService } from 'src/app/services/auth.service'; +import { AuthService } from 'src/app/services/auth/auth.service'; import { environment } from 'src/environments/environment.development'; @Component({ diff --git a/app/src/app/components/auth/username-creation/username-creation.component.ts b/app/src/app/components/auth/username-creation/username-creation.component.ts index 1a014b3..268d485 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.ts +++ b/app/src/app/components/auth/username-creation/username-creation.component.ts @@ -1,8 +1,7 @@ import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { ActivatedRoute } from '@angular/router'; import { GithubUser } from 'src/app/models/github-user.model'; -import { AuthGithubService } from 'src/app/services/auth-github.service'; +import { AuthGithubService } from 'src/app/services/auth/auth-github.service'; @Component({ selector: 'app-username-creation', diff --git a/app/src/app/components/home/header/header.component.ts b/app/src/app/components/home/header/header.component.ts index aecf6a8..ef3e072 100644 --- a/app/src/app/components/home/header/header.component.ts +++ b/app/src/app/components/home/header/header.component.ts @@ -1,9 +1,5 @@ import { Component } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { BehaviorSubject, Subscription } from 'rxjs'; -import { GithubUser } from 'src/app/models/github-user.model'; -import { AuthGithubService } from 'src/app/services/auth-github.service'; -import { AuthService } from 'src/app/services/auth.service'; +import { Subscription } from 'rxjs'; import { MenuBurgerService } from 'src/app/services/menu-burger.service'; @Component({ @@ -27,8 +23,6 @@ export class HeaderComponent { private menuSubscription: Subscription; constructor( - private authGithub: AuthGithubService, - private route: ActivatedRoute, private menuService: MenuBurgerService ) { diff --git a/app/src/app/components/portal/github-portal/github-portal.component.ts b/app/src/app/components/portal/github-portal/github-portal.component.ts index 06790b9..0bc8e8f 100644 --- a/app/src/app/components/portal/github-portal/github-portal.component.ts +++ b/app/src/app/components/portal/github-portal/github-portal.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { AuthGithubService } from 'src/app/services/auth-github.service'; +import { AuthGithubService } from 'src/app/services/auth/auth-github.service'; @Component({ selector: 'app-github-portal', diff --git a/app/src/app/components/portal/google-portal/google-portal.component.html b/app/src/app/components/portal/google-portal/google-portal.component.html new file mode 100644 index 0000000..aeeb65a --- /dev/null +++ b/app/src/app/components/portal/google-portal/google-portal.component.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts new file mode 100644 index 0000000..63391aa --- /dev/null +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -0,0 +1,43 @@ +import { Component } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { AuthGoogleService } from 'src/app/services/auth/auth-google.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-google-portal', + templateUrl: './google-portal.component.html', + styles: [ + ] +}) +export class GooglePortalComponent { + username: string = localStorage.getItem('username') || ''; + + constructor( + private authGoogle: AuthGoogleService, + private route: ActivatedRoute, + private router: Router + ) { } + + onGoogleLogin() { + this.authGoogle.googleLogin().subscribe(response => { + // Ici, vous pouvez gérer la redirection vers l'URL de Google, si nécessaire. + // Par exemple, redirigez l'utilisateur vers la page de connexion Google. + window.location.href = response.url; // Redirection vers Google login + }); + } + + ngOnInit() { + this.route.queryParams.subscribe(params => { + const code = params['code']; + if (code) { + this.authGoogle.googleCallback(code).subscribe(data => { + // Gérer la réponse et rediriger l'utilisateur vers la page d'accueil ou une autre page. + console.log('User info:', data); + // Par exemple, rediriger vers la page d'accueil après connexion. + this.router.navigate(['/home']); + }); + } + }); + } + +} diff --git a/app/src/app/components/profile/display-profile/display-profile.component.ts b/app/src/app/components/profile/display-profile/display-profile.component.ts index 7635ca6..26858c2 100644 --- a/app/src/app/components/profile/display-profile/display-profile.component.ts +++ b/app/src/app/components/profile/display-profile/display-profile.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; -import { AuthGithubService } from 'src/app/services/auth-github.service'; -import { AuthService } from 'src/app/services/auth.service'; +import { AuthGithubService } from 'src/app/services/auth/auth-github.service'; +import { AuthService } from 'src/app/services/auth/auth.service'; import { EditService } from 'src/app/services/edit.service'; @Component({ diff --git a/app/src/app/guard/no-auth.guard.ts b/app/src/app/guard/no-auth.guard.ts index fc73eff..f3df14c 100644 --- a/app/src/app/guard/no-auth.guard.ts +++ b/app/src/app/guard/no-auth.guard.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router'; import { Observable } from 'rxjs'; -import { AuthenticationService } from '../services/token.service'; +import { AuthenticationService } from '../services/auth/token.service'; @Injectable({ providedIn: 'root', diff --git a/app/src/app/guard/profile.guard.ts b/app/src/app/guard/profile.guard.ts index 5abb171..99f2449 100644 --- a/app/src/app/guard/profile.guard.ts +++ b/app/src/app/guard/profile.guard.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; -import { AuthenticationService } from '../services/token.service'; +import { AuthenticationService } from '../services/auth/token.service'; @Injectable({ providedIn: 'root', diff --git a/app/src/app/services/auth-github.service.ts b/app/src/app/services/auth/auth-github.service.ts similarity index 95% rename from app/src/app/services/auth-github.service.ts rename to app/src/app/services/auth/auth-github.service.ts index 445a8cc..8c3c7d9 100644 --- a/app/src/app/services/auth-github.service.ts +++ b/app/src/app/services/auth/auth-github.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; -import { GithubUser } from '../models/github-user.model'; +import { GithubUser } from '../../models/github-user.model'; import { environment } from 'src/environments/environment.development'; @Injectable({ diff --git a/app/src/app/services/auth/auth-google.service.ts b/app/src/app/services/auth/auth-google.service.ts new file mode 100644 index 0000000..865dc00 --- /dev/null +++ b/app/src/app/services/auth/auth-google.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { environment } from 'src/environments/environment.development'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthGoogleService { + constructor(private http: HttpClient) { } + + googleLogin(): Observable { + const url = `${environment.apiUrl}/api/google-login`; + return this.http.get(url, { observe: 'response', responseType: 'json' as 'json' }); + } + + googleCallback(code: string): Observable { + const url = `${environment.apiUrl}/api/google-callback?code=${code}`; + return this.http.get(url); + } +} \ No newline at end of file diff --git a/app/src/app/services/auth.service.ts b/app/src/app/services/auth/auth.service.ts similarity index 82% rename from app/src/app/services/auth.service.ts rename to app/src/app/services/auth/auth.service.ts index 3415ed6..c04c7ab 100644 --- a/app/src/app/services/auth.service.ts +++ b/app/src/app/services/auth/auth.service.ts @@ -1,10 +1,10 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; -import { AuthCreateUser } from '../models/create-user.model'; -import { AuthReceiveLoginUser, AuthSendLoginUser } from '../models/login-user.model'; -import { UserProfile } from '../models/user-info.model'; import { environment } from 'src/environments/environment.development'; +import { AuthCreateUser } from 'src/app/models/create-user.model'; +import { AuthReceiveLoginUser, AuthSendLoginUser } from 'src/app/models/login-user.model'; +import { UserProfile } from 'src/app/models/user-info.model'; @Injectable({ providedIn: 'root' diff --git a/app/src/app/services/token.service.ts b/app/src/app/services/auth/token.service.ts similarity index 100% rename from app/src/app/services/token.service.ts rename to app/src/app/services/auth/token.service.ts From d7657ca5fcba89555d958136586ba82de4f343f0 Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 20:03:54 -0400 Subject: [PATCH 04/10] :sparkles: pass by front end to create a google user now --- api/google_manager.py | 36 +++++++------- .../google-portal/google-portal.component.ts | 48 ++++++++++++++----- .../app/services/auth/auth-google.service.ts | 2 +- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/api/google_manager.py b/api/google_manager.py index 142604c..300b5b3 100644 --- a/api/google_manager.py +++ b/api/google_manager.py @@ -39,6 +39,7 @@ allow_headers=["*"], ) + def serialize_doc(doc): """Convert MongoDB document to serializable format""" if isinstance(doc, ObjectId): @@ -49,6 +50,7 @@ def serialize_doc(doc): return [serialize_doc(i) for i in doc] return doc + class GoogleManager: def __init__(self, db): self.db = db @@ -74,21 +76,16 @@ async def save_google_user(self, user_data): result = await self.db.users.insert_one(user_data) logger.info("User created with ID: %s", result.inserted_id) - return JSONResponse( - content={"message": "Google user created successfully"} - ) + return JSONResponse(content={"message": "Google user created successfully"}) except Exception as e: logger.error("Error saving Google user: %s", str(e)) raise HTTPException( - status_code=500, - detail=f"Error saving Google user: {str(e)}" + status_code=500, detail=f"Error saving Google user: {str(e)}" ) async def google_user_info(self, access_token: str): user_info_url = "https://www.googleapis.com/oauth2/v1/userinfo" - headers = { - "Authorization": f"Bearer {access_token}" - } + headers = {"Authorization": f"Bearer {access_token}"} async with httpx.AsyncClient() as client: user_info_response = await client.get(user_info_url, headers=headers) @@ -107,9 +104,11 @@ async def google_user_info(self, access_token: str): return serialize_doc(user_data) + # Initialisation de GoogleManager google_manager_instance = GoogleManager(db) + @app.get("/api/google-login") async def google_login(): google_auth_endpoint = "https://accounts.google.com/o/oauth2/v2/auth" @@ -119,34 +118,37 @@ async def google_login(): "redirect_uri": google_redirect_uri, "scope": "openid email profile", "access_type": "offline", - "prompt": "consent" + "prompt": "consent", } url = f"{google_auth_endpoint}?{'&'.join([f'{key}={value}' for key, value in params.items()])}" return RedirectResponse(url) -@app.get("/api/google-callback") -async def google_callback(request: Request): - code = request.query_params.get('code') + +@app.get("/api/google-portal") +async def google_portal(request: Request): + code = request.query_params.get("code") token_url = "https://oauth2.googleapis.com/token" - + token_data = { "code": code, "client_id": google_client_id, "client_secret": google_client_secret, "redirect_uri": google_redirect_uri, - "grant_type": "authorization_code" + "grant_type": "authorization_code", } - headers = {'Content-Type': 'application/x-www-form-urlencoded'} + headers = {"Content-Type": "application/x-www-form-urlencoded"} async with httpx.AsyncClient() as client: token_response = await client.post(token_url, data=token_data, headers=headers) - + token_response_json = token_response.json() access_token = token_response_json.get("access_token") id_token = token_response_json.get("id_token") if not access_token or not id_token: - raise HTTPException(status_code=400, detail="Failed to obtain access token from Google") + raise HTTPException( + status_code=400, detail="Failed to obtain access token from Google" + ) user_data = await google_manager_instance.google_user_info(access_token) diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts index 63391aa..fffaca2 100644 --- a/app/src/app/components/portal/google-portal/google-portal.component.ts +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -26,18 +26,42 @@ export class GooglePortalComponent { }); } - ngOnInit() { - this.route.queryParams.subscribe(params => { - const code = params['code']; - if (code) { - this.authGoogle.googleCallback(code).subscribe(data => { - // Gérer la réponse et rediriger l'utilisateur vers la page d'accueil ou une autre page. - console.log('User info:', data); - // Par exemple, rediriger vers la page d'accueil après connexion. - this.router.navigate(['/home']); - }); - } - }); + ngOnInit(): void { + localStorage.setItem('come_from', 'google'); + + + if (!localStorage.getItem('token')) { + this.route.queryParams.subscribe(params => { + const code = params['code']; + console.log(code); + + if (code) { + this.authGoogle.googleCallback(code).subscribe((data: any) => { + console.log(data); + + // localStorage.setItem('token', data); + // localStorage.setItem('access_token', data); + + // this.authGithub.githubToken(data).subscribe((tokenData: any) => { + // this.authGithub.getGithubUserInfo(tokenData.login).subscribe((userInfo: any) => { + // if (!userInfo.username || userInfo.username == '') { + // localStorage.setItem('catch_him', 'true'); + // window.location.href = 'username-creation'; + // } else { + // window.location.href = userInfo.username; + // localStorage.setItem('username', userInfo.username); + // this.username = userInfo.username; + // } + // }, + // (error) => { + // localStorage.setItem('catch_him', 'true'); + // window.location.href = 'username-creation'; + // }); + // }); + }); + } + }); + } } } diff --git a/app/src/app/services/auth/auth-google.service.ts b/app/src/app/services/auth/auth-google.service.ts index 865dc00..5f5eab7 100644 --- a/app/src/app/services/auth/auth-google.service.ts +++ b/app/src/app/services/auth/auth-google.service.ts @@ -15,7 +15,7 @@ export class AuthGoogleService { } googleCallback(code: string): Observable { - const url = `${environment.apiUrl}/api/google-callback?code=${code}`; + const url = `${environment.apiUrl}/api/google-portal?code=${code}`; return this.http.get(url); } } \ No newline at end of file From ffe9a8b6b3c67e58d6c0bc6455880c05ecfb0d96 Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 21:17:27 -0400 Subject: [PATCH 05/10] :contruction: username creation update and google portal avancements --- .../username-creation.component.html | 8 ++- .../username-creation.component.ts | 72 +++++++++++-------- .../google-portal/google-portal.component.ts | 5 ++ 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/app/src/app/components/auth/username-creation/username-creation.component.html b/app/src/app/components/auth/username-creation/username-creation.component.html index 5a9a24a..b08a411 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.html +++ b/app/src/app/components/auth/username-creation/username-creation.component.html @@ -4,7 +4,13 @@ - + +
+ {{failure}} +
+
+ +
diff --git a/app/src/app/components/auth/username-creation/username-creation.component.ts b/app/src/app/components/auth/username-creation/username-creation.component.ts index 268d485..3f68e55 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.ts +++ b/app/src/app/components/auth/username-creation/username-creation.component.ts @@ -16,6 +16,7 @@ export class UsernameCreationComponent { warning!: string connected: boolean = false loader: boolean = false + failure!: string constructor( private formBuilder: FormBuilder, @@ -58,42 +59,54 @@ export class UsernameCreationComponent { proceedWithUsernameCreation(username: string) { this.username = username const access_token = localStorage.getItem('token'); + const origin = localStorage.getItem('come_from'); if (access_token) { - if (localStorage.getItem('access_token')) { - this.authGithub.githubToken(access_token!).subscribe((data: any) => { + if (origin == 'github') { + this.githubProceed(access_token) + } - this.localUser(data) - this.connected = true; - - const userData: GithubUser = { - username: this.createUsernameForm.value.username.toLowerCase(), - github_username: data.login, - name: data.name || '', - email: data.email || '', - come_from: 'github', - location: data.location || '', - blog: data.blog || '', - twitter_username: data.twitter_username || '', - }; - - this.authGithub.saveGithubUser(userData).subscribe( - (data: any) => { - localStorage.setItem('catch_him', 'false'); - localStorage.setItem('warning', 'false'); - window.location.href = this.username - }, - (error: any) => { - console.error(error); - const errorMessage = error.error?.detail || 'An error occurred'; - this.error = errorMessage; - } - ) - }) + if (origin == 'google') { + console.log('let us cook babe'); } + } else { + this.failure = "An error occurred"; + this.loader = false } } + githubProceed(access_token: string) { + this.authGithub.githubToken(access_token!).subscribe((data: any) => { + + this.localUser(data) + this.connected = true; + + const userData: GithubUser = { + username: this.createUsernameForm.value.username.toLowerCase(), + github_username: data.login, + name: data.name || '', + email: data.email || '', + come_from: 'github', + location: data.location || '', + blog: data.blog || '', + twitter_username: data.twitter_username || '', + }; + + this.authGithub.saveGithubUser(userData).subscribe( + (data: any) => { + localStorage.setItem('catch_him', 'false'); + localStorage.setItem('warning', 'false'); + window.location.href = this.username + }, + (error: any) => { + console.error(error); + const errorMessage = error.error?.detail || 'An error occurred'; + this.error = errorMessage; + } + ) + }) + } + localUser(data: any) { localStorage.setItem('username', this.createUsernameForm.value.username.toLowerCase()); localStorage.setItem('github_username', data.login); @@ -101,7 +114,6 @@ export class UsernameCreationComponent { localStorage.setItem('email', data.email); localStorage.setItem('come_from', 'github'); localStorage.setItem('location', data.location); - localStorage.setItem('blog', 'blog'); localStorage.setItem('twitter_username', data.twitter_username); } } \ No newline at end of file diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts index fffaca2..e0373a9 100644 --- a/app/src/app/components/portal/google-portal/google-portal.component.ts +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -38,6 +38,11 @@ export class GooglePortalComponent { if (code) { this.authGoogle.googleCallback(code).subscribe((data: any) => { console.log(data); + + if (!data.username || data.username == '') { + localStorage.setItem('catch_him', 'true'); + window.location.href = 'username-creation'; + } // localStorage.setItem('token', data); // localStorage.setItem('access_token', data); From 13dfb98a0e4fe5595131a48b9258d3de42ed4d1c Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 22:39:27 -0400 Subject: [PATCH 06/10] :construction: token is given when u log in with google --- api/google_manager.py | 48 +++++++++++++------ .../username-creation.component.ts | 6 ++- .../google-portal/google-portal.component.ts | 29 ++++------- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/api/google_manager.py b/api/google_manager.py index 300b5b3..49aafb4 100644 --- a/api/google_manager.py +++ b/api/google_manager.py @@ -1,6 +1,7 @@ import datetime import os import logging +import jwt from dotenv import load_dotenv from fastapi import FastAPI, HTTPException, Request from fastapi.responses import JSONResponse, RedirectResponse @@ -50,23 +51,28 @@ def serialize_doc(doc): return [serialize_doc(i) for i in doc] return doc - class GoogleManager: def __init__(self, db): self.db = db - self.user_manager = UserManager(db) + self.user_manager = UserManager(db) # Initialise le gestionnaire utilisateur - async def save_google_user(self, user_data): + async def save_or_login_google_user(self, user_data): try: # Vérifiez si l'utilisateur existe déjà par email existing_user = await self.db.users.find_one({"email": user_data["email"]}) + if existing_user: logger.info("Email already registered: %s", user_data["email"]) - raise HTTPException( - status_code=400, - detail="Email already registered.", - ) - + + # Générer un JWT pour l'utilisateur existant + token_data = {"sub": existing_user["email"]} + expires = datetime.timedelta(days=30) + access_token = self.user_manager.create_jwt_token(existing_user, expires) + + # Retournez les informations de l'utilisateur existant avec le token de session + return {"user": serialize_doc(existing_user), "access_token": access_token} + + # Si l'utilisateur n'existe pas, créez un nouveau compte creation_date = datetime.datetime.utcnow() user_data["come_from"] = "google" user_data["creation_month"] = creation_date.strftime("%B") @@ -76,16 +82,26 @@ async def save_google_user(self, user_data): result = await self.db.users.insert_one(user_data) logger.info("User created with ID: %s", result.inserted_id) - return JSONResponse(content={"message": "Google user created successfully"}) + # Générer un JWT pour le nouvel utilisateur + token_data = {"sub": user_data["email"]} + expires = datetime.timedelta(days=30) + access_token = self.user_manager.create_jwt_token(token_data, expires) + + # Retournez les informations du nouvel utilisateur avec le token de session + return {"user": user_data, "access_token": access_token} except Exception as e: logger.error("Error saving Google user: %s", str(e)) raise HTTPException( - status_code=500, detail=f"Error saving Google user: {str(e)}" + status_code=500, + detail=f"Error saving Google user: {str(e)}" ) + @app.get("/api/google-test") async def google_user_info(self, access_token: str): user_info_url = "https://www.googleapis.com/oauth2/v1/userinfo" - headers = {"Authorization": f"Bearer {access_token}"} + headers = { + "Authorization": f"Bearer {access_token}" + } async with httpx.AsyncClient() as client: user_info_response = await client.get(user_info_url, headers=headers) @@ -99,10 +115,11 @@ async def google_user_info(self, access_token: str): "verified_email": user_info.get("verified_email"), } - # Enregistrer l'utilisateur dans la base de données - user_created = await self.save_google_user(user_data) + # Enregistrer ou connecter l'utilisateur + user = await self.save_or_login_google_user(user_data) + + return serialize_doc(user) - return serialize_doc(user_data) # Initialisation de GoogleManager @@ -152,4 +169,5 @@ async def google_portal(request: Request): user_data = await google_manager_instance.google_user_info(access_token) - return JSONResponse(content=user_data) + # Retournez les informations utilisateur avec le token de session + return JSONResponse(content=user_data) \ No newline at end of file diff --git a/app/src/app/components/auth/username-creation/username-creation.component.ts b/app/src/app/components/auth/username-creation/username-creation.component.ts index 3f68e55..0b04140 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.ts +++ b/app/src/app/components/auth/username-creation/username-creation.component.ts @@ -67,7 +67,7 @@ export class UsernameCreationComponent { } if (origin == 'google') { - console.log('let us cook babe'); + this.googleProceed(access_token) } } else { this.failure = "An error occurred"; @@ -107,6 +107,10 @@ export class UsernameCreationComponent { }) } + googleProceed(access_token: string) { + console.log('let us cook babe'); + } + localUser(data: any) { localStorage.setItem('username', this.createUsernameForm.value.username.toLowerCase()); localStorage.setItem('github_username', data.login); diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts index e0373a9..922a82c 100644 --- a/app/src/app/components/portal/google-portal/google-portal.component.ts +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -39,30 +39,17 @@ export class GooglePortalComponent { this.authGoogle.googleCallback(code).subscribe((data: any) => { console.log(data); - if (!data.username || data.username == '') { + localStorage.setItem('token', data.access_token); + localStorage.setItem('access_token', data.access_token); + + if (!data.user.username || data.user.username == '') { localStorage.setItem('catch_him', 'true'); window.location.href = 'username-creation'; + } else { + window.location.href = data.user.username; + localStorage.setItem('username', data.user.username); + this.username = data.user.username; } - - // localStorage.setItem('token', data); - // localStorage.setItem('access_token', data); - - // this.authGithub.githubToken(data).subscribe((tokenData: any) => { - // this.authGithub.getGithubUserInfo(tokenData.login).subscribe((userInfo: any) => { - // if (!userInfo.username || userInfo.username == '') { - // localStorage.setItem('catch_him', 'true'); - // window.location.href = 'username-creation'; - // } else { - // window.location.href = userInfo.username; - // localStorage.setItem('username', userInfo.username); - // this.username = userInfo.username; - // } - // }, - // (error) => { - // localStorage.setItem('catch_him', 'true'); - // window.location.href = 'username-creation'; - // }); - // }); }); } }); From 3e4cab77c2995656a19788df427bd39b5ff05c7f Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Sun, 11 Aug 2024 23:27:02 -0400 Subject: [PATCH 07/10] :bug: try to understand why we can't get infos about the user from his jwt token --- api/google_manager.py | 51 ++++++++++++++++--- .../username-creation.component.ts | 28 +++++++++- .../app/services/auth/auth-google.service.ts | 5 ++ 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/api/google_manager.py b/api/google_manager.py index 49aafb4..3961028 100644 --- a/api/google_manager.py +++ b/api/google_manager.py @@ -1,7 +1,6 @@ import datetime import os import logging -import jwt from dotenv import load_dotenv from fastapi import FastAPI, HTTPException, Request from fastapi.responses import JSONResponse, RedirectResponse @@ -96,17 +95,34 @@ async def save_or_login_google_user(self, user_data): detail=f"Error saving Google user: {str(e)}" ) - @app.get("/api/google-test") async def google_user_info(self, access_token: str): + # Vérifier si le token est toujours valide + token_info_url = f"https://oauth2.googleapis.com/tokeninfo?access_token={access_token}" + async with httpx.AsyncClient() as client: + token_info_response = await client.get(token_info_url) + + logger.info(f"Token info response status: {token_info_response.status_code}") + logger.info(f"Token info response body: {token_info_response.text}") + + if token_info_response.status_code != 200: + raise HTTPException(status_code=401, detail="Invalid or expired access token") + + # Continuer à utiliser le jeton pour récupérer les informations de l'utilisateur user_info_url = "https://www.googleapis.com/oauth2/v1/userinfo" headers = { "Authorization": f"Bearer {access_token}" } async with httpx.AsyncClient() as client: user_info_response = await client.get(user_info_url, headers=headers) + + logger.info(f"User info response status: {user_info_response.status_code}") + logger.info(f"User info response body: {user_info_response.text}") + if user_info_response.status_code != 200: + raise HTTPException(status_code=401, detail="Unauthorized request to Google API") + user_info = user_info_response.json() - + # Préparer les données utilisateur user_data = { "name": user_info.get("name"), @@ -121,10 +137,25 @@ async def google_user_info(self, access_token: str): return serialize_doc(user) - # Initialisation de GoogleManager google_manager_instance = GoogleManager(db) +@app.get("/api/google-token") +async def google_token_handler(request: Request): + access_token = request.query_params.get("access_token") + if not access_token: + raise HTTPException(status_code=400, detail="Access token is required") + + try: + user_data = await google_manager_instance.google_user_info(access_token) + return JSONResponse(content=user_data) + except HTTPException as e: + logger.error(f"Failed to handle token: {e.detail}") + raise e + except Exception as e: + logger.error(f"Unexpected error: {str(e)}") + raise HTTPException(status_code=500, detail="Internal Server Error") + @app.get("/api/google-login") async def google_login(): @@ -144,6 +175,9 @@ async def google_login(): @app.get("/api/google-portal") async def google_portal(request: Request): code = request.query_params.get("code") + if not code: + raise HTTPException(status_code=400, detail="Authorization code not provided") + token_url = "https://oauth2.googleapis.com/token" token_data = { @@ -159,15 +193,20 @@ async def google_portal(request: Request): token_response = await client.post(token_url, data=token_data, headers=headers) token_response_json = token_response.json() + + if token_response.status_code != 200: + raise HTTPException(status_code=token_response.status_code, detail="Failed to obtain access token from Google") + access_token = token_response_json.get("access_token") id_token = token_response_json.get("id_token") if not access_token or not id_token: raise HTTPException( - status_code=400, detail="Failed to obtain access token from Google" + status_code=400, detail="Failed to obtain valid tokens from Google" ) + # Utilisez uniquement le jeton d'accès reçu pour valider et obtenir les infos utilisateur user_data = await google_manager_instance.google_user_info(access_token) # Retournez les informations utilisateur avec le token de session - return JSONResponse(content=user_data) \ No newline at end of file + return JSONResponse(content=user_data) diff --git a/app/src/app/components/auth/username-creation/username-creation.component.ts b/app/src/app/components/auth/username-creation/username-creation.component.ts index 0b04140..80dcef6 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.ts +++ b/app/src/app/components/auth/username-creation/username-creation.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { GithubUser } from 'src/app/models/github-user.model'; import { AuthGithubService } from 'src/app/services/auth/auth-github.service'; +import { AuthGoogleService } from 'src/app/services/auth/auth-google.service'; @Component({ selector: 'app-username-creation', @@ -21,6 +22,7 @@ export class UsernameCreationComponent { constructor( private formBuilder: FormBuilder, private authGithub: AuthGithubService, + private authGoogle: AuthGoogleService ) { this.createUsernameForm = this.formBuilder.group({ username: ['', [Validators.required, Validators.pattern(/^[A-Za-z]+$/)]], @@ -108,12 +110,34 @@ export class UsernameCreationComponent { } googleProceed(access_token: string) { - console.log('let us cook babe'); + this.authGoogle.googleToken(access_token!).subscribe((data: any) => { + + this.localUser(data.user); // Enregistre les informations de l'utilisateur dans le localStorage + this.connected = true; + + const userData: GithubUser = { + username: this.createUsernameForm.value.username.toLowerCase(), + github_username: data.user.github_username, // ou un autre identifiant pertinent + name: data.user.name || '', + email: data.user.email || '', + come_from: 'google', + location: data.user.location || '', + blog: data.user.blog || '', + twitter_username: data.user.twitter_username || '', + }; + + console.log(data); + }, (error: any) => { + console.error(error); + this.failure = "Failed to retrieve user data from Google."; + this.loader = false; + }); } + localUser(data: any) { localStorage.setItem('username', this.createUsernameForm.value.username.toLowerCase()); - localStorage.setItem('github_username', data.login); + if (data.login) localStorage.setItem('github_username', data.login); localStorage.setItem('name', data.name); localStorage.setItem('email', data.email); localStorage.setItem('come_from', 'github'); diff --git a/app/src/app/services/auth/auth-google.service.ts b/app/src/app/services/auth/auth-google.service.ts index 5f5eab7..351b901 100644 --- a/app/src/app/services/auth/auth-google.service.ts +++ b/app/src/app/services/auth/auth-google.service.ts @@ -18,4 +18,9 @@ export class AuthGoogleService { const url = `${environment.apiUrl}/api/google-portal?code=${code}`; return this.http.get(url); } + + googleToken(access_token: string): Observable { + const url = `${environment.apiUrl}/api/google-token`; + return this.http.get(url, { params: { access_token } }); + } } \ No newline at end of file From 7745dd89e6ad74e9de9226d8cfdfafb9417890ae Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Mon, 12 Aug 2024 00:25:34 -0400 Subject: [PATCH 08/10] :sparkles: now we can sign up with google and get token --- api/google_manager.py | 52 +++++++++++------ .../username-creation.component.ts | 58 +++++++++++-------- .../google-portal/google-portal.component.ts | 13 ++++- app/src/app/models/google-user.model.ts | 9 +++ .../app/services/auth/auth-google.service.ts | 11 ++-- 5 files changed, 94 insertions(+), 49 deletions(-) create mode 100644 app/src/app/models/google-user.model.ts diff --git a/api/google_manager.py b/api/google_manager.py index 3961028..806ddae 100644 --- a/api/google_manager.py +++ b/api/google_manager.py @@ -1,6 +1,7 @@ import datetime import os import logging +from typing import Optional from dotenv import load_dotenv from fastapi import FastAPI, HTTPException, Request from fastapi.responses import JSONResponse, RedirectResponse @@ -9,6 +10,7 @@ from motor.motor_asyncio import AsyncIOMotorClient from bson import ObjectId from user_manager import UserManager +from pydantic import BaseModel # Configuration de logging logging.basicConfig(level=logging.INFO) @@ -39,6 +41,15 @@ allow_headers=["*"], ) +class GoogleUser(BaseModel): + username: Optional[str] + name: str + email: str + come_from: str + verified_email: str + creation_month: str + creation_year: str + def serialize_doc(doc): """Convert MongoDB document to serializable format""" @@ -78,8 +89,8 @@ async def save_or_login_google_user(self, user_data): user_data["creation_year"] = creation_date.year # Insérez l'utilisateur dans la base de données - result = await self.db.users.insert_one(user_data) - logger.info("User created with ID: %s", result.inserted_id) + # result = await self.db.users.insert_one(user_data) + # logger.info("User created with ID: %s", result.inserted_id) # Générer un JWT pour le nouvel utilisateur token_data = {"sub": user_data["email"]} @@ -140,22 +151,6 @@ async def google_user_info(self, access_token: str): # Initialisation de GoogleManager google_manager_instance = GoogleManager(db) -@app.get("/api/google-token") -async def google_token_handler(request: Request): - access_token = request.query_params.get("access_token") - if not access_token: - raise HTTPException(status_code=400, detail="Access token is required") - - try: - user_data = await google_manager_instance.google_user_info(access_token) - return JSONResponse(content=user_data) - except HTTPException as e: - logger.error(f"Failed to handle token: {e.detail}") - raise e - except Exception as e: - logger.error(f"Unexpected error: {str(e)}") - raise HTTPException(status_code=500, detail="Internal Server Error") - @app.get("/api/google-login") async def google_login(): @@ -210,3 +205,24 @@ async def google_portal(request: Request): # Retournez les informations utilisateur avec le token de session return JSONResponse(content=user_data) + +@app.post("/api/google-save-user") +async def save_user(user: GoogleUser): + print(user) + try: + # Convertir le modèle en dictionnaire + user_data = user.dict() + print(user_data) + + # Insérer l'utilisateur dans la base de données + result = await db.users.insert_one(user_data) + logger.info("User created with ID: %s", result.inserted_id) + + # Retourner une réponse JSON avec l'ID de l'utilisateur inséré + return JSONResponse(content={"id": str(result.inserted_id)}, status_code=201) + except Exception as e: + logger.error("Error saving user: %s", str(e)) + raise HTTPException( + status_code=500, + detail=f"Error saving user: {str(e)}" + ) \ No newline at end of file diff --git a/app/src/app/components/auth/username-creation/username-creation.component.ts b/app/src/app/components/auth/username-creation/username-creation.component.ts index 80dcef6..ecd1941 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.ts +++ b/app/src/app/components/auth/username-creation/username-creation.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { GithubUser } from 'src/app/models/github-user.model'; +import { GoogleUser } from 'src/app/models/google-user.model'; import { AuthGithubService } from 'src/app/services/auth/auth-github.service'; import { AuthGoogleService } from 'src/app/services/auth/auth-google.service'; @@ -63,13 +64,16 @@ export class UsernameCreationComponent { const access_token = localStorage.getItem('token'); const origin = localStorage.getItem('come_from'); + console.log(origin); + + if (access_token) { if (origin == 'github') { this.githubProceed(access_token) } if (origin == 'google') { - this.googleProceed(access_token) + this.googleProceed() } } else { this.failure = "An error occurred"; @@ -78,6 +82,7 @@ export class UsernameCreationComponent { } githubProceed(access_token: string) { + localStorage.setItem('username', this.username); this.authGithub.githubToken(access_token!).subscribe((data: any) => { this.localUser(data) @@ -109,29 +114,34 @@ export class UsernameCreationComponent { }) } - googleProceed(access_token: string) { - this.authGoogle.googleToken(access_token!).subscribe((data: any) => { - - this.localUser(data.user); // Enregistre les informations de l'utilisateur dans le localStorage - this.connected = true; - - const userData: GithubUser = { - username: this.createUsernameForm.value.username.toLowerCase(), - github_username: data.user.github_username, // ou un autre identifiant pertinent - name: data.user.name || '', - email: data.user.email || '', - come_from: 'google', - location: data.user.location || '', - blog: data.user.blog || '', - twitter_username: data.user.twitter_username || '', - }; - - console.log(data); - }, (error: any) => { - console.error(error); - this.failure = "Failed to retrieve user data from Google."; - this.loader = false; - }); + googleProceed() { + localStorage.setItem('username', this.username); + console.log(localStorage); + + const userData: GoogleUser = { + username: this.createUsernameForm.value.username.toLowerCase(), + name: localStorage.getItem('name') || '', + email: localStorage.getItem('email') || '', + come_from: localStorage.getItem('come_from') || '', + verified_email: localStorage.getItem('verified_email') || 'false', + creation_month: localStorage.getItem('creation_month') || '', + creation_year: localStorage.getItem('creation_year') || '', + }; + + console.log(userData); + + this.authGoogle.saveGoogleUser(userData).subscribe( + (data: any) => { + localStorage.setItem('catch_him', 'false'); + localStorage.setItem('warning', 'false'); + window.location.href = this.username + }, + (error: any) => { + console.error(error); + const errorMessage = error.error?.detail || 'An error occurred'; + this.error = errorMessage; + } + ) } diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts index 922a82c..2616da1 100644 --- a/app/src/app/components/portal/google-portal/google-portal.component.ts +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -15,7 +15,6 @@ export class GooglePortalComponent { constructor( private authGoogle: AuthGoogleService, private route: ActivatedRoute, - private router: Router ) { } onGoogleLogin() { @@ -29,7 +28,6 @@ export class GooglePortalComponent { ngOnInit(): void { localStorage.setItem('come_from', 'google'); - if (!localStorage.getItem('token')) { this.route.queryParams.subscribe(params => { const code = params['code']; @@ -44,6 +42,17 @@ export class GooglePortalComponent { if (!data.user.username || data.user.username == '') { localStorage.setItem('catch_him', 'true'); + + console.log(data); + + localStorage.setItem('name', data.user.name); + localStorage.setItem('email', data.user.email); + localStorage.setItem('come_from', 'google'); + localStorage.setItem('verified_email', data.user.verified_email); + localStorage.setItem('creation_month', data.user.creation_month); + localStorage.setItem('creation_year', data.user.creation_year); + + window.location.href = 'username-creation'; } else { window.location.href = data.user.username; diff --git a/app/src/app/models/google-user.model.ts b/app/src/app/models/google-user.model.ts new file mode 100644 index 0000000..e28204c --- /dev/null +++ b/app/src/app/models/google-user.model.ts @@ -0,0 +1,9 @@ +export interface GoogleUser { + username ?: string; + name: string; + email: string; + come_from: string; + verified_email: string; + creation_month: string; + creation_year: string; +} \ No newline at end of file diff --git a/app/src/app/services/auth/auth-google.service.ts b/app/src/app/services/auth/auth-google.service.ts index 351b901..c78ce24 100644 --- a/app/src/app/services/auth/auth-google.service.ts +++ b/app/src/app/services/auth/auth-google.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { environment } from 'src/environments/environment.development'; +import { GoogleUser } from 'src/app/models/google-user.model'; @Injectable({ providedIn: 'root' @@ -9,6 +10,11 @@ import { environment } from 'src/environments/environment.development'; export class AuthGoogleService { constructor(private http: HttpClient) { } + saveGoogleUser(user: GoogleUser): Observable { + const url = `${environment.apiUrl}/api/google-save-user`; + return this.http.post(url, user); + } + googleLogin(): Observable { const url = `${environment.apiUrl}/api/google-login`; return this.http.get(url, { observe: 'response', responseType: 'json' as 'json' }); @@ -18,9 +24,4 @@ export class AuthGoogleService { const url = `${environment.apiUrl}/api/google-portal?code=${code}`; return this.http.get(url); } - - googleToken(access_token: string): Observable { - const url = `${environment.apiUrl}/api/google-token`; - return this.http.get(url, { params: { access_token } }); - } } \ No newline at end of file From 3bfb2d4edb88849e6e931812cda8ae3968e4f893 Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Mon, 12 Aug 2024 00:34:56 -0400 Subject: [PATCH 09/10] :bug: bug null values in profile resolved --- .../username-creation.component.ts | 6 --- .../google-portal/google-portal.component.ts | 5 -- .../display-profile.component.ts | 52 +++++++++++-------- 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/app/src/app/components/auth/username-creation/username-creation.component.ts b/app/src/app/components/auth/username-creation/username-creation.component.ts index ecd1941..e86e86b 100644 --- a/app/src/app/components/auth/username-creation/username-creation.component.ts +++ b/app/src/app/components/auth/username-creation/username-creation.component.ts @@ -64,9 +64,6 @@ export class UsernameCreationComponent { const access_token = localStorage.getItem('token'); const origin = localStorage.getItem('come_from'); - console.log(origin); - - if (access_token) { if (origin == 'github') { this.githubProceed(access_token) @@ -116,7 +113,6 @@ export class UsernameCreationComponent { googleProceed() { localStorage.setItem('username', this.username); - console.log(localStorage); const userData: GoogleUser = { username: this.createUsernameForm.value.username.toLowerCase(), @@ -128,8 +124,6 @@ export class UsernameCreationComponent { creation_year: localStorage.getItem('creation_year') || '', }; - console.log(userData); - this.authGoogle.saveGoogleUser(userData).subscribe( (data: any) => { localStorage.setItem('catch_him', 'false'); diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts index 2616da1..d521945 100644 --- a/app/src/app/components/portal/google-portal/google-portal.component.ts +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -31,19 +31,14 @@ export class GooglePortalComponent { if (!localStorage.getItem('token')) { this.route.queryParams.subscribe(params => { const code = params['code']; - console.log(code); if (code) { this.authGoogle.googleCallback(code).subscribe((data: any) => { - console.log(data); - localStorage.setItem('token', data.access_token); localStorage.setItem('access_token', data.access_token); if (!data.user.username || data.user.username == '') { localStorage.setItem('catch_him', 'true'); - - console.log(data); localStorage.setItem('name', data.user.name); localStorage.setItem('email', data.user.email); diff --git a/app/src/app/components/profile/display-profile/display-profile.component.ts b/app/src/app/components/profile/display-profile/display-profile.component.ts index 26858c2..08dd0f4 100644 --- a/app/src/app/components/profile/display-profile/display-profile.component.ts +++ b/app/src/app/components/profile/display-profile/display-profile.component.ts @@ -11,17 +11,17 @@ import { EditService } from 'src/app/services/edit.service'; }) export class DisplayProfileComponent { edit: boolean | undefined - name: string = localStorage.getItem('name') || "" - username: string = localStorage.getItem('username') || "" - email: string = localStorage.getItem('email') || "" - come_from: string = localStorage.getItem('come_from') || "" - location: string = localStorage.getItem('location') || "" - blog: string = localStorage.getItem('blog') || "" - github_username: string = localStorage.getItem('github_username') || "" - twitter_username: string = localStorage.getItem('twitter_username') || "" - about: string = localStorage.getItem('about') || "" - creation_month: string = localStorage.getItem('creation_month') || "" - creation_year: string = localStorage.getItem('creation_year') || "" + name: string = this.getLocalStorageItem('name') || "" + username: string = this.getLocalStorageItem('username') || "" + email: string = this.getLocalStorageItem('email') || "" + come_from: string = this.getLocalStorageItem('come_from') || "" + location: string = this.getLocalStorageItem('location') || "" + blog: string = this.getLocalStorageItem('blog') || "" + github_username: string = this.getLocalStorageItem('github_username') || "" + twitter_username: string = this.getLocalStorageItem('twitter_username') || "" + about: string = this.getLocalStorageItem('about') || "" + creation_month: string = this.getLocalStorageItem('creation_month') || "" + creation_year: string = this.getLocalStorageItem('creation_year') || "" arobase: string = "@" loaded: boolean = false @@ -93,7 +93,7 @@ export class DisplayProfileComponent { localStorage.setItem('username', data.username); localStorage.setItem('name', data.name); localStorage.setItem('email', data.email); - localStorage.setItem('come_from', 'github'); + localStorage.setItem('come_from', data.come_from); localStorage.setItem('location', data.location); localStorage.setItem('blog', data.blog); localStorage.setItem('twitter_username', data.twitter_username); @@ -105,16 +105,22 @@ export class DisplayProfileComponent { } setVariables(data: any) { - this.name = data.name; - this.username = data.username; - this.email = data.email; - this.come_from = data.come_from; - this.location = data.location; - this.blog = data.blog; - this.twitter_username = data.twitter_username; - this.github_username = data.github_username; - this.about = data.about; - this.creation_month = data.creation_month; - this.creation_year = data.creation_year; + this.name = data.name || this.name; + this.username = data.username || this.username; + this.email = data.email || this.email; + this.come_from = data.come_from || this.come_from; + this.location = data.location || this.location; + this.blog = data.blog || this.blog; + this.twitter_username = data.twitter_username || this.twitter_username; + this.github_username = data.github_username || this.github_username; + this.about = data.about || this.about; + this.creation_month = data.creation_month || this.creation_month; + this.creation_year = data.creation_year || this.creation_year; + } + + private getLocalStorageItem(key: string): string { + // Récupère l'élément de localStorage et retourne une valeur par défaut si non trouvé + const value = localStorage.getItem(key); + return value !== null ? value : ""; } } \ No newline at end of file From 9d08074ca04a14d7d93341f4c08e52766a450165 Mon Sep 17 00:00:00 2001 From: Mathis Zerari Date: Mon, 12 Aug 2024 00:37:32 -0400 Subject: [PATCH 10/10] :fire: remove unused elements --- app/src/app/app-routing.module.ts | 2 +- .../components/portal/google-portal/google-portal.component.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/app/app-routing.module.ts b/app/src/app/app-routing.module.ts index 05ee960..87863ce 100644 --- a/app/src/app/app-routing.module.ts +++ b/app/src/app/app-routing.module.ts @@ -1,5 +1,5 @@ import { NgModule } from '@angular/core'; -import { RouterModule, Routes, ActivatedRoute } from '@angular/router'; +import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './components/home/home/home.component'; import { SignupComponent } from './components/auth/signup/signup.component'; import { ProfileGuard } from './guard/profile.guard'; diff --git a/app/src/app/components/portal/google-portal/google-portal.component.ts b/app/src/app/components/portal/google-portal/google-portal.component.ts index d521945..4fedfe4 100644 --- a/app/src/app/components/portal/google-portal/google-portal.component.ts +++ b/app/src/app/components/portal/google-portal/google-portal.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { AuthGoogleService } from 'src/app/services/auth/auth-google.service'; -import { Router } from '@angular/router'; @Component({ selector: 'app-google-portal',