Skip to content

Commit 9fbb702

Browse files
committed
fix resetPassword and changeUserPassword
1 parent 0864e35 commit 9fbb702

File tree

7 files changed

+115
-98
lines changed

7 files changed

+115
-98
lines changed

src/helpers/generateRandomPassword.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ export default function generateRandomPassword(length = 8) {
44
return generator.generate({
55
length,
66
numbers: true,
7+
symbols: true,
78
});
89
}

src/helpers/isAssignedToProgramOrCohort.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { IOrganization, Organization } from '../models/organization.model'
44
import Program from '../models/program.model'
55
import { RoleOfUser, User, UserInterface } from '../models/user'
66

7-
export default async function isAssigned(user: UserInterface, org: IOrganization) {
7+
export default async function isAssignedToAnEntity(user: UserInterface, org: IOrganization) {
88
const orgUserData = user.organizations.find(data=>data.orgId.toString()===org._id.toString())
99
if(!orgUserData){
1010
throw new GraphQLError(`User ${user.email} is not part of ${org.name}`,{

src/resolvers/userResolver.ts

Lines changed: 96 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { GraphQLError } from 'graphql'
55
// import * as jwt from 'jsonwebtoken'
66
import { JwtPayload, verify } from 'jsonwebtoken'
77
import generateRandomPassword from '../helpers/generateRandomPassword'
8-
import isAssigned from '../helpers/isAssignedToProgramOrCohort'
8+
import isAssignedToAnEntity from '../helpers/isAssignedToProgramOrCohort'
99
import { checkloginAttepmts } from '../helpers/logintracker'
1010
import { checkLoggedInOrganization, isPartOfOrganization } from '../helpers/organization.helper'
1111
import {
@@ -42,6 +42,11 @@ const SECRET: string = process.env.SECRET as string
4242
export type OrganizationType = InstanceType<typeof Organization>
4343
export type UserType = InstanceType<typeof User>
4444

45+
enum ACTION_ENUM{
46+
APPROVE='approve',
47+
REJECT='reject'
48+
}
49+
4550
async function logGeoActivity(user: UserInterface,org: IOrganization,clientIpAdress?: string) {
4651
const response = await fetch(`https://ipapi.co/${clientIpAdress}/json/`)
4752
const geoData = await response.json()
@@ -362,17 +367,15 @@ const resolvers: any = {
362367

363368
async loginUser(
364369
_: any,
365-
{ loginInput: { email, password, orgToken } }: any,
370+
{ email, password, orgToken }: {email: string, password: string, orgToken: string},
366371
context: Context
367372
) {
373+
validateEmail(email, "Please enter a valid email address")
368374
const { clientIpAdress } = context
369-
370375
// get the organization if someone logs in
371376
const org: InstanceType<typeof Organization> =
372377
await checkLoggedInOrganization(orgToken)
373-
374378
const user: any = await User.findOne({ email })
375-
376379
if (!user) {
377380
throw new GraphQLError(`User ${email} does not exist`, {
378381
extensions: {
@@ -411,18 +414,21 @@ const resolvers: any = {
411414
})
412415
}
413416

414-
await isAssigned(user,org)
417+
await isAssignedToAnEntity(user,org)
415418

416419
const token = generateToken(user._id, orgUserData.role)
417420
const data = {
418421
token: token,
419-
user: user,
422+
user: user.toJSON(),
420423
geoData,
421424
}
422425
return data
423426
},
424427

425428
async deleteUser(_: any, { userId, reason , orgToken}: {userId: string, reason?: string, orgToken: string}, context: Context) {
429+
if(reason){
430+
validateStringField(reason, "Please provide a valid reason")
431+
}
426432
const org = await checkLoggedInOrganization(orgToken)
427433
const {user} = (await checkUserLoggedIn(org,context))([RoleOfUser.ADMIN, RoleOfUser.SUPER_ADMIN])
428434
if (!user) {
@@ -569,42 +575,41 @@ const resolvers: any = {
569575
},
570576

571577
//This section is to make org name login to be case insensitive
572-
async loginOrg(_: any, { name }: { name: String }) {
573-
const organization: any = await Organization.findOne({
574-
name: { $regex: new RegExp('^' + name + '$', 'i') },
575-
})
576-
577-
if (!organization) {
578-
throw new GraphQLError(
579-
`We do not recognize this organization ${name}`,
580-
{
581-
extensions: {
582-
code: 'UserInputError',
583-
},
584-
}
585-
)
586-
}
587-
if (organization.status == ORG_STATUS.PENDING) {
588-
throw new GraphQLError('Your organization is not approved yet', {
589-
extensions: {
590-
code: 'UserInputError',
591-
},
592-
})
593-
}
594-
if (organization.status == ORG_STATUS.REJECTED) {
595-
throw new GraphQLError('Your organization was not approved', {
596-
extensions: {
597-
code: 'UserInputError',
598-
},
599-
})
600-
}
601-
const token = generateTokenOrganization(organization.name)
602-
const data = {
603-
token: token,
604-
organization: organization.toJSON(),
605-
}
606-
return data
607-
},
578+
async loginOrg(_: any, { name }: { name: String }) {
579+
const organization: any = await Organization.findOne({
580+
name: { $regex: new RegExp('^' + name + '$', 'i') },
581+
})
582+
if (!organization) {
583+
throw new GraphQLError(
584+
`We do not recognize this organization ${name}`,
585+
{
586+
extensions: {
587+
code: 'FORBIDDEN',
588+
},
589+
}
590+
)
591+
}
592+
if (organization.status == ORG_STATUS.PENDING) {
593+
throw new GraphQLError('Your organization is not approved yet', {
594+
extensions: {
595+
code: 'FORBIDDEN',
596+
},
597+
})
598+
}
599+
if (organization.status == ORG_STATUS.REJECTED) {
600+
throw new GraphQLError('Your organization was not approved', {
601+
extensions: {
602+
code: 'FORBIDDEN',
603+
},
604+
})
605+
}
606+
const token = generateTokenOrganization(organization.name)
607+
const data = {
608+
token: token,
609+
organization: organization.toJSON(),
610+
}
611+
return data
612+
},
608613

609614
// end of making org name to be case insensitive
610615

@@ -716,13 +721,13 @@ const resolvers: any = {
716721

717722
return {
718723
message: 'Organization registration request sent successfully',
719-
org: newOrg
724+
org: newOrg.toJSON()
720725
}
721726
},
722727

723728
async RegisterNewOrganization(
724729
_: any,
725-
{ organizationInput: { name }, action , orgToken}: { organizationInput: {name: string, email: string}, action: 'approve' | 'reject', orgToken: string},
730+
{ name, action , orgToken}: { name: string, action: ACTION_ENUM, orgToken: string},
726731
context: Context
727732
) {
728733
validateStringField(name, "Please enter a valid organization name")
@@ -737,7 +742,7 @@ const resolvers: any = {
737742
}
738743
})
739744
}
740-
if(action === "approve"){
745+
if(action === ACTION_ENUM.APPROVE){
741746
if(orgExists.status === ORG_STATUS.ACTIVE){
742747
throw new GraphQLError("Organization is already active",{
743748
extensions: {
@@ -747,7 +752,7 @@ const resolvers: any = {
747752
}
748753
const admin = (orgExists as any).admin[0]
749754
const password = generateRandomPassword()
750-
admin.password = bcrypt.hash(password, 10)
755+
admin.password = hashSync(password, 10)
751756
await admin.save()
752757
orgExists.status = ORG_STATUS.ACTIVE
753758
await orgExists.save()
@@ -763,9 +768,7 @@ const resolvers: any = {
763768
process.env.ADMIN_EMAIL,
764769
process.env.ADMIN_PASS
765770
)
766-
}
767-
768-
if(action === "reject"){
771+
}else if(action === ACTION_ENUM.REJECT){
769772
if(orgExists.status === ORG_STATUS.REJECTED){
770773
throw new GraphQLError("Organization was already rejected",{
771774
extensions: {
@@ -779,13 +782,19 @@ const resolvers: any = {
779782
await sendEmail(
780783
admin.email,
781784
'Organization Request rejected notice',
782-
organizationRejectedTemplate(admin.name),
785+
organizationRejectedTemplate(orgExists.name),
783786
process.env.FRONTEND_LINK || 'link',
784787
process.env.ADMIN_EMAIL,
785788
process.env.ADMIN_PASS
786789
)
790+
}else{
791+
throw new GraphQLError("Invalid action, Please approve or reject an organization",{
792+
extensions: {
793+
code: "USER_INPUT_ERROR"
794+
}
795+
})
787796
}
788-
return orgExists
797+
return orgExists.toJSON()
789798
},
790799

791800
async addOrganization(
@@ -807,6 +816,15 @@ const resolvers: any = {
807816
},
808817
})
809818
}
819+
820+
const userExists = await User.findOne({email})
821+
if (userExists) {
822+
throw new GraphQLError(`Account ${userExists.email} is already taken`, {
823+
extensions: {
824+
code: 'FORBIDDEN',
825+
},
826+
})
827+
}
810828
const password: string = generateRandomPassword()
811829
const newOrg = await Organization.create({
812830
name,
@@ -832,6 +850,7 @@ const resolvers: any = {
832850
await admin.save()
833851
newOrg.admin = [admin._id]
834852
await newOrg.save()
853+
await newOrg.populate('admin')
835854

836855
// send the requester an email with his password
837856
const content = organizationCreatedTemplate(org.name, email, password)
@@ -846,7 +865,7 @@ const resolvers: any = {
846865
process.env.ADMIN_PASS
847866
)
848867

849-
return org
868+
return org.toJSON()
850869
},
851870

852871
async updateGithubOrganisation(
@@ -855,17 +874,15 @@ const resolvers: any = {
855874
context: Context
856875
) {
857876
validateStringField(gitHubOrganisation, "Please enter a valid organization githubOrganization")
858-
859877
const org = await checkLoggedInOrganization(orgToken)
860878
;(await checkUserLoggedIn(org, context))([
861879
RoleOfUser.ADMIN,
862880
RoleOfUser.SUPER_ADMIN,
863881
])
864-
865882
org.gitHubOrganisation = gitHubOrganisation
866883
await org.save()
867884
await org.populate('admin')
868-
return org
885+
return org.toJSON()
869886
},
870887

871888
async addActiveRepostoOrganization(_: any, { repoUrl, orgToken}: {repoUrl: string, orgToken: string}, context: Context) {
@@ -885,7 +902,7 @@ const resolvers: any = {
885902
org.activeRepos.push(repoUrl)
886903
await org.save()
887904

888-
return org
905+
return org.toJSON()
889906
},
890907

891908
async deleteActiveRepostoOrganization(_: any, { repoUrl, orgToken}: {repoUrl: string, orgToken: string}, context: Context) {
@@ -907,7 +924,7 @@ const resolvers: any = {
907924

908925
await org.save()
909926

910-
return org
927+
return org.toJSON()
911928
},
912929

913930
async deleteOrganization(_: any, { orgId, orgToken }: {orgId: string, orgToken: string}, context: Context) {
@@ -934,20 +951,20 @@ const resolvers: any = {
934951
// role: { $ne: RoleOfUser.SUPER_ADMIN },
935952
// })
936953
organizationExists.isDeleted = true
937-
return organizationExists
954+
await organizationExists.save()
955+
return organizationExists.toJSON()
938956
},
939957

940-
async forgotPassword(_: any, { email }: any) {
958+
async forgotPassword(_: any, { email }: { email: string }) {
959+
validateEmail(email, "Please provide a valid email")
941960
const userExists: any = await User.findOne({ email })
942-
943961
if (!userExists) {
944962
throw new GraphQLError("No such user found",{
945963
extensions: {
946964
code: "USER_NOT_FOUND"
947965
}
948966
})
949967
}
950-
951968
const token: any = generateTokenUserExists(email)
952969
const newToken: any = token.replaceAll('.', '*')
953970
const webLink = `${process.env.FRONTEND_LINK}/forgot-password/${newToken}`
@@ -970,27 +987,22 @@ const resolvers: any = {
970987

971988
async updateEmailNotifications(_: any, { orgToken }: { orgToken: string}, context: Context) {
972989
const org = await checkLoggedInOrganization(orgToken)
973-
const { user } = (await checkUserLoggedIn(org, context))(Object.values(RoleOfUser))
974-
975-
const orgUserData = isPartOfOrganization(user, org)
990+
const { user, orgUserData } = (await checkUserLoggedIn(org, context))(Object.values(RoleOfUser))
976991
orgUserData.emailNotifications = !orgUserData.emailNotifications
977992
await user.save()
978993

979994
return {
980-
message: 'updated successful'
995+
message: 'updated successfully'
981996
}
982997
},
983998

984999
async updatePushNotifications(_: any, { orgToken}: {orgToken: string}, context: Context) {
9851000
const org = await checkLoggedInOrganization(orgToken)
986-
const { user } = (await checkUserLoggedIn(org, context))(Object.values(RoleOfUser))
987-
988-
const orgUserData = isPartOfOrganization(user, org)
1001+
const { user, orgUserData } = (await checkUserLoggedIn(org, context))(Object.values(RoleOfUser))
9891002
orgUserData.pushNotifications = !orgUserData.pushNotifications
9901003
await user.save()
991-
9921004
return {
993-
message: 'updated successful'
1005+
message: 'updated successfully'
9941006
}
9951007
},
9961008

@@ -1016,7 +1028,7 @@ const resolvers: any = {
10161028
}
10171029
})
10181030
}
1019-
user.password = hashSync(password, 10)
1031+
user.password = password
10201032
await user.save()
10211033

10221034
return {
@@ -1041,17 +1053,19 @@ const resolvers: any = {
10411053
})
10421054
}
10431055

1044-
if (!compareSync(currentPassword, user.password)) {
1045-
throw new GraphQLError("Incorrect credentials",{
1046-
extensions: {
1047-
code: "FORBIDDEN"
1048-
}
1049-
})
1050-
}
1051-
user.password = hashSync(newPassword, 10)
1052-
await user.save()
1053-
return 'Your password was reset successfully! '
1056+
if (!compareSync(currentPassword, user.password)) {
1057+
throw new GraphQLError("Incorrect credentials", {
1058+
extensions: {
1059+
code: "FORBIDDEN"
1060+
}
1061+
})
1062+
}
1063+
user.password = newPassword
1064+
await user.save()
1065+
return {
1066+
message: 'Your password was reset successfully! '
10541067
}
1068+
}
10551069
},
10561070
}
10571071

0 commit comments

Comments
 (0)