diff --git a/.env.example b/.env.example deleted file mode 100644 index 0a48e9f..0000000 --- a/.env.example +++ /dev/null @@ -1,13 +0,0 @@ -PORT= ******************************** -APP_ENV= ******************************** -PDN_DB_NAME= ***************************** -DEV_DB_HOST= ******************************** -DEV_DB_PORT= ******************************** -DEV_DB_USER= ******************************** -DEV_DB_PASS= ***************************** -DEV_DB_TYPE= ******************************* - -PDN_DB_HOST= ******************************** -PDN_DB_PORT= ******************************** -PDN_DB_USER= ******************************** -PDN_DB_PASS= ******************************** \ No newline at end of file diff --git a/package.json b/package.json index 84a5b11..b434d0f 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,9 @@ "jsend": "^1.1.0", "morgan": "^1.10.0", "nodemon": "^3.1.0", + "passport": "^0.7.0", + "passport-facebook": "^3.0.0", + "passport-google-oauth20": "^2.0.0", "pg": "^8.11.5", "reflect-metadata": "^0.2.2", "source-map-support": "^0.5.21", @@ -57,6 +60,9 @@ "@types/jsend": "^1.0.32", "@types/morgan": "^1.9.9", "@types/node": "^20.12.7", + "@types/passport": "^1.0.16", + "@types/passport-facebook": "^3.0.3", + "@types/passport-google-oauth20": "^2.0.14", "@types/reflect-metadata": "^0.1.0", "@types/supertest": "^6.0.2", "@types/winston": "^2.4.4", @@ -75,4 +81,4 @@ "typescript": "^5.4.5", "typescript-eslint": "^7.7.1" } -} \ No newline at end of file +} diff --git a/src/controllers/authController.ts b/src/controllers/authController.ts index 209a350..a98cece 100644 --- a/src/controllers/authController.ts +++ b/src/controllers/authController.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import { User } from '../entities/User';; +import { User } from '../entities/User'; import bcrypt from 'bcrypt'; import { getRepository } from 'typeorm'; diff --git a/src/controllers/facebook.auth.ts b/src/controllers/facebook.auth.ts new file mode 100644 index 0000000..e00fd6d --- /dev/null +++ b/src/controllers/facebook.auth.ts @@ -0,0 +1,38 @@ +import { getRepository } from 'typeorm'; +import { User } from '../entities/user.auth'; + +async function findUserAccountIdProvider(accountId: string, provider: string): Promise { + try { + const userRepository = getRepository(User); + + const user = await userRepository.findOne({ + where: { + accountId: accountId, + provider: provider, + }, + }); + + if (user === null) { + return undefined; + } + + return user as User; + } catch (error) { + console.error('Error finding user:', error); + return undefined; + } + } +const accountId = 'your_account_id'; +const provider = 'facebook'; + +findUserAccountIdProvider(accountId, provider) + .then((user) => { + if (user) { + console.log('User found:', user); + } else { + console.log('User not found'); + } + }) + .catch((error) => { + console.error('Error:', error); + }); diff --git a/src/entities/User.ts b/src/entities/User.ts index 2d0557f..2ab958c 100644 --- a/src/entities/User.ts +++ b/src/entities/User.ts @@ -11,6 +11,15 @@ import { @Entity() @Unique(['email']) export class User { + save() { + throw new Error('Method not implemented.'); + } + static create(arg0: { accountId: string; name: string; provider: string; }): User | PromiseLike | null { + throw new Error('Method not implemented.'); + } + static findOne(arg0: { accountId: any; provider: string; }) { + throw new Error('Method not implemented.'); + } @PrimaryGeneratedColumn('uuid') @IsNotEmpty() id!: string; @@ -66,4 +75,20 @@ import { @UpdateDateColumn() updatedAt!: Date; + + @Column({ nullable: true }) + @IsString() + accountId?: string; + + @Column({ nullable: true }) + @IsString() + name?: string; + + @Column({ nullable: true }) + @IsString() + photoURL?: string; + + @Column({ nullable: true }) + @IsString() + provider?: string; } \ No newline at end of file diff --git a/src/entities/user.auth.ts b/src/entities/user.auth.ts new file mode 100644 index 0000000..d8270bb --- /dev/null +++ b/src/entities/user.auth.ts @@ -0,0 +1,22 @@ +import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from 'typeorm'; + +@Entity() +export class User extends BaseEntity { + @PrimaryGeneratedColumn('uuid') + id: string | undefined; + + @Column({ type: 'text', nullable: true, unique: true }) + email: string | undefined; + + @Column({ type: 'text', nullable: true }) + accountId: string | undefined; + + @Column({ type: 'text', nullable: true }) + name!: string; + + @Column({ type: 'text', nullable: true }) + photoURL: string | undefined; + + @Column({ type: 'text', nullable: true }) + provider: string | undefined; +} diff --git a/src/index.ts b/src/index.ts index 55443f6..0589776 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,17 @@ import express, { Request, Response } from 'express'; import cors from 'cors'; -import dotenv from 'dotenv'; import router from './routes'; import { addDocumentation } from './startups/docs'; import 'reflect-metadata'; +import { passportConfig } from './middlewares/auth'; +import dotenv from 'dotenv'; +dotenv.config(); import { CustomError, errorHandler } from './middlewares/errorHandler'; import morgan from 'morgan'; import { dbConnection } from './startups/dbConnection'; +import passport from 'passport'; dotenv.config(); export const app = express(); @@ -32,6 +35,18 @@ dbConnection(); const morganFormat = ':method :url :status :response-time ms - :res[content-length]'; app.use(morgan(morganFormat)); +//passport +passportConfig(); + +//Google OAuth routes +app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] })); + +app.get('/auth/google/callback', + passport.authenticate('google', { failureRedirect: '/login' }), + (req, res) => { + res.redirect('/profile'); + } +); export const server = app.listen(port, () => { console.log(`[server]: Server is running at http://localhost:${port}`); }); \ No newline at end of file diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts new file mode 100644 index 0000000..bbe7180 --- /dev/null +++ b/src/middlewares/auth.ts @@ -0,0 +1,21 @@ +import passport from 'passport'; +import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; + +export function passportConfig() { + const clientID = process.env.GOOGLE_CLIENT_ID; + const clientSecret = process.env.GOOGLE_CLIENT_SECRET; + + if (!clientID || !clientSecret) { + throw new Error('Google client ID or client secret is missing.'); + } + + passport.use(new GoogleStrategy({ + clientID, + clientSecret, + callbackURL: "/auth/google/callback" + }, + (accessToken, refreshToken, profile, done) => { + done(null, profile); + } + )); +}