From b646c1d5414ac161dcd1ecfe4f4a8ff4a408d6c9 Mon Sep 17 00:00:00 2001 From: kennyg37 Date: Mon, 7 Oct 2024 14:00:18 +0200 Subject: [PATCH 1/3] fixing google authentication issues and creating some useful mutations --- src/models/AuthUser.ts | 5 +++++ src/resolvers/loginUserResolver.ts | 30 +++++++++++++++++++++++++ src/schema/updateUserTypeDefs.ts | 1 + src/utils/controllers/userController.ts | 17 ++++++++++---- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/models/AuthUser.ts b/src/models/AuthUser.ts index b4a8b552..b69aa90f 100644 --- a/src/models/AuthUser.ts +++ b/src/models/AuthUser.ts @@ -28,6 +28,11 @@ const userSchema = new Schema( type: String, enum: ["male", "female", "other"], }, + authMethod: { + type: String, + enum: ["google", "local"], + default: "local", + }, isActive: { type: Boolean, default: true, diff --git a/src/resolvers/loginUserResolver.ts b/src/resolvers/loginUserResolver.ts index b2d104f0..bdd343cc 100644 --- a/src/resolvers/loginUserResolver.ts +++ b/src/resolvers/loginUserResolver.ts @@ -340,6 +340,36 @@ export const loggedUserResolvers: any = { return wasEdited; }, + async updateUserSelf( + _: any, + { ID, editUserInput: { firstname, lastname, gender, code, country, telephone, picture } }: any, + ctx: any + ) { + if (!ctx.currentUser) { + throw new AuthenticationError('You must be logged in'); + } + if (ctx.currentUser._id !== ID) { + throw new AuthenticationError('You are only authorized to update your own account.'); + } + + const updateFields: any = {}; + if (firstname) updateFields.firstname = firstname; + if (lastname) updateFields.lastname = lastname; + if (gender) updateFields.gender = gender; + if (code) updateFields.code = code; + if (country) updateFields.country = country; + if (telephone) updateFields.telephone = telephone; + if (picture) updateFields.picture = picture; + + const wasEdited = ( + await LoggedUserModel.updateOne( + { _id: ctx.currentUser._id }, + { $set: updateFields } + ) + ).modifiedCount; + + return wasEdited > 0; + }, assignRoleToUser: async ( _: any, diff --git a/src/schema/updateUserTypeDefs.ts b/src/schema/updateUserTypeDefs.ts index c6ead23d..3687ea22 100644 --- a/src/schema/updateUserTypeDefs.ts +++ b/src/schema/updateUserTypeDefs.ts @@ -28,6 +28,7 @@ export const updateUserTypeDefs = gql` createUser(userInput: UserInput): User! deleteUser(ID: ID!): Boolean updateUser(ID:ID!, editUserInput:EditUserInput): Boolean + updateUserSelf(ID:ID!, editUserInput: EditUserInput): Boolean } `; diff --git a/src/utils/controllers/userController.ts b/src/utils/controllers/userController.ts index 41b455d9..8ab01625 100644 --- a/src/utils/controllers/userController.ts +++ b/src/utils/controllers/userController.ts @@ -14,7 +14,6 @@ export const findOrCreateUser = async (token: any) => { } } const googleUser = await verifyAuthToken(token); - //check existance of user user = await checkIfUserExists(googleUser?.email); return user ? user : createNewUser(googleUser); @@ -37,7 +36,7 @@ const checkIfUserExists = async (email: any) => await LoggedUserModel.findOne({ email }).exec(); const createNewUser = async (googleUser: any) => { - const { given_name, family_name, email, picture, isActive } = googleUser; + const { given_name, family_name, email, picture } = googleUser; const superAdminEmail = process.env.SUPER_ADMIN_EMAIL; const adminEmail = process.env.ADMIN_EMAIL; const applicantRole = await RoleModel.findOne({ roleName: 'applicant' }); @@ -78,15 +77,25 @@ const createNewUser = async (googleUser: any) => { ? adminRole?._id || createAdminRole() : applicantRole?._id || createApplicantRole(); + // Fallback values for fields missing in Google data const user = { firstname: given_name, lastname: family_name, email, - picture, + picture: picture || process.env.DEFAULT_AVATAR, role: roleId, - isActive, + code: '+250', + password: 'GOOGLE_SIGN_IN', + country: ' ', + telephone: '', + gender: 'other', + authMethod: 'google', + isActive: true, + isVerified: false, + isEmailVerified: true, createdAt: new Date().toISOString(), }; + const newUser = await new LoggedUserModel(user).save(); const userWithRole = await LoggedUserModel.findById(newUser._id).populate( 'role', From 99ce4bc39ea6ca32da1b01c0c4400128c6833cd7 Mon Sep 17 00:00:00 2001 From: kennyg37 Date: Tue, 8 Oct 2024 11:40:04 +0200 Subject: [PATCH 2/3] adding search by filter querry and further authentication rules --- src/resolvers/loginUserResolver.ts | 13 +++++++++++++ src/schema/loggedUser.ts | 23 +++++++++++++++++++++++ src/schema/updateUserTypeDefs.ts | 1 - src/utils/controllers/userController.ts | 2 +- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/resolvers/loginUserResolver.ts b/src/resolvers/loginUserResolver.ts index bdd343cc..76584808 100644 --- a/src/resolvers/loginUserResolver.ts +++ b/src/resolvers/loginUserResolver.ts @@ -51,6 +51,19 @@ export const loggedUserResolvers: any = { const role = await RoleModel.findOne({ _id: user?.role }); return role; }, + getByFilter: async (_: any, { filter }: { filter: any }) => { + const filterQuery: any = {}; + for (const key in filter) { + if (filter[key] !== undefined && filter[key] !== null) { + filterQuery[key] = filter[key]; + } + } + if (Object.keys(filterQuery).length === 0) { + throw new Error("No filter criteria provided."); + } + const users = await LoggedUserModel.find(filterQuery); + return users; + } }, Mutation: { async createUser_Logged( diff --git a/src/schema/loggedUser.ts b/src/schema/loggedUser.ts index 3be3bfbe..a9ab4e3d 100644 --- a/src/schema/loggedUser.ts +++ b/src/schema/loggedUser.ts @@ -12,6 +12,7 @@ export const LoggedUserSchema = gql` picture: String country: String gender: String + authMethod: String telephone: String password: String token: String! @@ -37,6 +38,16 @@ export const LoggedUserSchema = gql` country: String role: String } + input EditUserSelfInput_Logged { + firstname: String + lastname: String + email: String + password: String + code: String + telephone: String + gender: String + country: String + } input EditUserInput_Logged { firstname: String lastname: String @@ -45,10 +56,21 @@ export const LoggedUserSchema = gql` email: String } + input UserFilterInput { + email: String + firstName: String + lastName: String + country: String + telephone: String + gender: String + authMethod: String + isActive: Boolean + } type Query { user_Logged(ID: ID!): User_Logged! getUsers_Logged(amount: Int): [User_Logged] checkUserRole(email: String): Role! + getByFilter(filter: UserFilterInput!): [User_Logged]! } type Mutation { @@ -59,5 +81,6 @@ export const LoggedUserSchema = gql` updateUser_Logged(ID: ID!, editUserInput: EditUserInput_Logged): Boolean assignRoleToUser(ID: ID!, roleID: ID!): User_Logged updateUserStatus(ID: ID!): Boolean + updateUserSelf(ID: ID!, editUserInput: EditUserSelfInput_Logged): Boolean } `; \ No newline at end of file diff --git a/src/schema/updateUserTypeDefs.ts b/src/schema/updateUserTypeDefs.ts index 3687ea22..c6ead23d 100644 --- a/src/schema/updateUserTypeDefs.ts +++ b/src/schema/updateUserTypeDefs.ts @@ -28,7 +28,6 @@ export const updateUserTypeDefs = gql` createUser(userInput: UserInput): User! deleteUser(ID: ID!): Boolean updateUser(ID:ID!, editUserInput:EditUserInput): Boolean - updateUserSelf(ID:ID!, editUserInput: EditUserInput): Boolean } `; diff --git a/src/utils/controllers/userController.ts b/src/utils/controllers/userController.ts index 8ab01625..f2be4b8d 100644 --- a/src/utils/controllers/userController.ts +++ b/src/utils/controllers/userController.ts @@ -86,7 +86,7 @@ const createNewUser = async (googleUser: any) => { role: roleId, code: '+250', password: 'GOOGLE_SIGN_IN', - country: ' ', + country: '', telephone: '', gender: 'other', authMethod: 'google', From 841c68c1f2b0bf1a8e6440f712c97e411beaf89f Mon Sep 17 00:00:00 2001 From: kennyg37 Date: Thu, 10 Oct 2024 13:31:03 +0200 Subject: [PATCH 3/3] adding functionalities to the created resolvers --- src/index.ts | 4 +++- src/resolvers/loginUserResolver.ts | 8 ++++---- src/schema/loggedUser.ts | 1 - 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 05c4da22..ecfca7e8 100755 --- a/src/index.ts +++ b/src/index.ts @@ -119,7 +119,9 @@ const server = new ApolloServer({ let authToken = null; let currentUser = null; try { - authToken = req.headers.authorization; + authToken = req.headers.authorization && req.headers.authorization.startsWith("Bearer ") + ? req.headers.authorization.split(" ")[1] + : req.headers.authorization; if (authToken) { //find or create User currentUser = await findOrCreateUser(authToken); diff --git a/src/resolvers/loginUserResolver.ts b/src/resolvers/loginUserResolver.ts index 76584808..b0963c0d 100644 --- a/src/resolvers/loginUserResolver.ts +++ b/src/resolvers/loginUserResolver.ts @@ -10,6 +10,7 @@ import { generateAutoGeneratedPassword } from '../utils/passwordAutoGenerate'; import { sendEmailTemplate, sendUserCredentials } from '../helpers/bulkyMails'; import { userModel } from '../models/user'; import { sessionModel } from '../models/session'; +import { string } from 'joi'; const FrontendUrl = process.env.FRONTEND_URL @@ -355,13 +356,12 @@ export const loggedUserResolvers: any = { async updateUserSelf( _: any, - { ID, editUserInput: { firstname, lastname, gender, code, country, telephone, picture } }: any, - ctx: any - ) { + { ID, editUserInput: { firstname, lastname, gender, code, country, telephone, picture } }: any, ctx: any) { + if (!ctx.currentUser) { throw new AuthenticationError('You must be logged in'); } - if (ctx.currentUser._id !== ID) { + if (ctx.currentUser._id.toString() !== ID) { throw new AuthenticationError('You are only authorized to update your own account.'); } diff --git a/src/schema/loggedUser.ts b/src/schema/loggedUser.ts index a9ab4e3d..69ef8104 100644 --- a/src/schema/loggedUser.ts +++ b/src/schema/loggedUser.ts @@ -42,7 +42,6 @@ export const LoggedUserSchema = gql` firstname: String lastname: String email: String - password: String code: String telephone: String gender: String