diff --git a/src/index.ts b/src/index.ts index 42c19077..3741a802 100755 --- a/src/index.ts +++ b/src/index.ts @@ -145,7 +145,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) { currentUser = await findOrCreateUser(authToken); diff --git a/src/models/AuthUser.ts b/src/models/AuthUser.ts index ed8eca8c..52ab58e6 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", + }, applicationPhase: { type: String, enum: ["Applied", "Interviewed", "Accepted", "Enrolled"], diff --git a/src/resolvers/loginUserResolver.ts b/src/resolvers/loginUserResolver.ts index 108f9294..e1783128 100644 --- a/src/resolvers/loginUserResolver.ts +++ b/src/resolvers/loginUserResolver.ts @@ -53,6 +53,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( @@ -384,6 +397,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.toString() !== 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, { ID, roleID }: { ID: string; roleID: string }, diff --git a/src/schema/loggedUser.ts b/src/schema/loggedUser.ts index d0aee40e..4e9242d6 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! @@ -53,6 +54,15 @@ export const LoggedUserSchema = gql` role: String applicationPhase: String } + input EditUserSelfInput_Logged { + firstname: String + lastname: String + email: String + code: String + telephone: String + gender: String + country: String + } input EditUserInput_Logged { firstname: String lastname: String @@ -68,10 +78,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]! getCohort(id: ID!): cohort getAllCohorts: [cohort!]! } @@ -84,6 +105,7 @@ 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 updateApplicationPhase(userID: ID!, newPhase: String!, cohortID: ID): User_Logged } `; \ No newline at end of file diff --git a/src/utils/controllers/userController.ts b/src/utils/controllers/userController.ts index 41b455d9..f2be4b8d 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',