Skip to content

Commit 0a4217f

Browse files
ft(admin dashboard): Time user joined to an Organisation
1 parent 0812f0a commit 0a4217f

File tree

3 files changed

+83
-70
lines changed

3 files changed

+83
-70
lines changed

src/resolvers/profileResolver.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,24 @@ const profileResolvers: any = {
4545
RoleOfUser.TTL,
4646
],
4747
},
48-
}).populate({
49-
path: 'team',
50-
strictPopulate: false,
51-
populate: {
52-
path: 'cohort',
48+
})
49+
.select('id email role status createdAt updatedAt')
50+
.populate({
51+
path: 'team',
5352
strictPopulate: false,
5453
populate: {
55-
path: 'program',
54+
path: 'cohort',
5655
strictPopulate: false,
5756
populate: {
58-
path: 'organization',
57+
path: 'program',
5958
strictPopulate: false,
59+
populate: {
60+
path: 'organization',
61+
strictPopulate: false,
62+
},
6063
},
6164
},
62-
},
63-
})
65+
})
6466
return users
6567
},
6668
async getAllRoles() {

src/resolvers/userResolver.ts

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import { EmailPattern } from '../utils/validation.utils'
3737
import { Context } from './../context'
3838
import { UserInputError } from 'apollo-server'
3939
import { encodeOtpToToken, generateOtp } from '../utils/2WayAuthentication'
40-
import jwt from 'jsonwebtoken'
40+
import jwt from 'jsonwebtoken'
4141
import nonTraineeTemplate from '../utils/templates/nonTraineeTemplate'
4242
const octokit = new Octokit({ auth: `${process.env.Org_Repo_Access}` })
4343

@@ -115,7 +115,7 @@ export async function loginsCount(organizationName: any, recentLocation: any) {
115115
const resolvers: any = {
116116
Query: {
117117
async getOrganizations(_: any, __: any, context: Context) {
118-
; (await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
118+
;(await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
119119

120120
return Organization.find()
121121
},
@@ -169,7 +169,7 @@ const resolvers: any = {
169169
{ organisation, username }: any,
170170
context: Context
171171
) {
172-
; (await checkUserLoggedIn(context))([
172+
;(await checkUserLoggedIn(context))([
173173
RoleOfUser.ADMIN,
174174
RoleOfUser.COORDINATOR,
175175
'trainee',
@@ -181,7 +181,7 @@ const resolvers: any = {
181181
name: organisation,
182182
})
183183
if (!organisationExists)
184-
throw new Error('This Organization doesn\'t exist')
184+
throw new Error("This Organization doesn't exist")
185185

186186
organisation = organisationExists.gitHubOrganisation
187187

@@ -329,9 +329,16 @@ const resolvers: any = {
329329
invitation.status = 'accepted'
330330
await invitation.save()
331331
}
332-
if(user.role !=='trainee'){
333-
const content = nonTraineeTemplate( user.email,password,org.name)
334-
sendEmail(user.email,'Login Details',content,process.env.FRONTEND_LINK, process.env.ADMIN_EMAIL, process.env.ADMIN_PASS)
332+
if (user.role !== 'trainee') {
333+
const content = nonTraineeTemplate(user.email, password, org.name)
334+
sendEmail(
335+
user.email,
336+
'Login Details',
337+
content,
338+
process.env.FRONTEND_LINK,
339+
process.env.ADMIN_EMAIL,
340+
process.env.ADMIN_PASS
341+
)
335342
}
336343

337344
const newProfile = await Profile.create({
@@ -377,14 +384,14 @@ const resolvers: any = {
377384
context: any
378385
) {
379386
// Check organization validity
380-
const org = await checkLoggedInOrganization(orgToken);
381-
const { clientIpAdress } = context;
387+
const org = await checkLoggedInOrganization(orgToken)
388+
const { clientIpAdress } = context
382389
if (!org) {
383390
throw new GraphQLError('Organization not found', {
384391
extensions: { code: 'InvalidOrganization' },
385-
});
392+
})
386393
}
387-
394+
388395
// Find user with populated fields
389396
const user: any = await User.findOne({ email }).populate({
390397
path: 'cohort',
@@ -400,30 +407,30 @@ const resolvers: any = {
400407
strictPopulate: false,
401408
},
402409
},
403-
});
404-
410+
})
411+
405412
// Check if user exists
406413
if (!user) {
407414
throw new GraphQLError('Invalid credentials', {
408415
extensions: { code: 'AccountNotFound' },
409-
});
416+
})
410417
}
411-
418+
412419
// Check if account is active
413420
if (user.status?.status !== 'active') {
414421
throw new GraphQLError(
415422
`Account is ${user.status?.status}. Contact admin.`,
416423
{
417424
extensions: { code: 'AccountInactive' },
418425
}
419-
);
426+
)
420427
}
421-
428+
422429
// Check if two-factor authentication is enabled
423430
if (user.twoFactorAuth) {
424-
const otp = generateOtp(); // Generate OTP
425-
const TwoWayVerificationToken = encodeOtpToToken(otp, email); // Encode OTP
426-
431+
const otp = generateOtp() // Generate OTP
432+
const TwoWayVerificationToken = encodeOtpToToken(otp, email) // Encode OTP
433+
427434
// Send email with OTP
428435
await sendEmail(
429436
email,
@@ -432,55 +439,55 @@ const resolvers: any = {
432439
null,
433440
process.env.ADMIN_EMAIL,
434441
process.env.ADMIN_PASS
435-
);
436-
442+
)
443+
437444
// Save the Two-Way Verification Token to the database
438-
user.TwoWayVerificationToken = TwoWayVerificationToken;
439-
await user.save();
440-
445+
user.TwoWayVerificationToken = TwoWayVerificationToken
446+
await user.save()
447+
441448
// Return a response without exposing the token
442449
return {
443450
message: 'Check your email for the OTP code.',
444451
otpRequired: true,
445452
user: { id: user._id },
446-
};
453+
}
447454
} else {
448455
// Verify password if 2FA is not enabled
449-
const passwordMatch = await user?.checkPass(password);
456+
const passwordMatch = await user?.checkPass(password)
450457
if (!passwordMatch) {
451458
throw new GraphQLError('Invalid credentials', {
452459
extensions: { code: 'InvalidCredential' },
453-
});
460+
})
454461
}
455-
462+
456463
// Generate token for authenticated user
457464
const token = jwt.sign(
458465
{ userId: user._id, role: user._doc?.role || 'user' },
459466
SECRET,
460467
{ expiresIn: '2h' }
461-
);
462-
463-
const geoData = await logGeoActivity(user, clientIpAdress); // Log activity
464-
465-
const organizationName = user.organizations[0];
468+
)
469+
470+
const geoData = await logGeoActivity(user, clientIpAdress) // Log activity
471+
472+
const organizationName = user.organizations[0]
466473
if (organizationName) {
467474
const location =
468475
geoData && geoData.city && geoData.country_name
469476
? `${geoData.city}-${geoData.country_name}`
470-
: null;
471-
await loginsCount(organizationName, location);
477+
: null
478+
await loginsCount(organizationName, location)
472479
}
473-
480+
474481
// Return token and user data
475482
return {
476483
token,
477484
user: user.toJSON(),
478485
geoData,
479486
otpRequired: false,
480-
};
487+
}
481488
}
482489
},
483-
490+
484491
async deleteUser(_: any, { input }: any, context: { userId: any }) {
485492
const requester = await User.findById(context.userId)
486493
if (!requester) {
@@ -563,9 +570,9 @@ const resolvers: any = {
563570
]
564571
const org = await checkLoggedInOrganization(orgToken)
565572
const roleExists = allRoles.includes(name)
566-
if (!roleExists) throw new Error('This role doesn\'t exist')
573+
if (!roleExists) throw new Error("This role doesn't exist")
567574
const userExists = await User.findById(id)
568-
if (!userExists) throw new Error('User doesn\'t exist')
575+
if (!userExists) throw new Error("User doesn't exist")
569576

570577
const getAllUsers = await User.find({
571578
role: RoleOfUser.ADMIN,
@@ -802,7 +809,7 @@ const resolvers: any = {
802809
context: Context
803810
) {
804811
// check if requester is super admin
805-
; (await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
812+
;(await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
806813
const orgExists = await Organization.findOne({ name: name })
807814
if (action == 'approve') {
808815
if (!orgExists) {
@@ -872,7 +879,7 @@ const resolvers: any = {
872879
context: Context
873880
) {
874881
// the below commented line help to know if the user is an superAdmin to perform an action of creating an organization
875-
; (await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
882+
;(await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
876883
if (action == 'new') {
877884
const orgExists = await Organization.findOne({ name: name })
878885
if (orgExists) {
@@ -937,7 +944,7 @@ const resolvers: any = {
937944
{ name, gitHubOrganisation }: any,
938945
context: Context
939946
) {
940-
; (await checkUserLoggedIn(context))([
947+
;(await checkUserLoggedIn(context))([
941948
RoleOfUser.ADMIN,
942949
RoleOfUser.SUPER_ADMIN,
943950
])
@@ -1030,15 +1037,15 @@ const resolvers: any = {
10301037
},
10311038

10321039
async deleteOrganization(_: any, { id }: any, context: Context) {
1033-
; (await checkUserLoggedIn(context))([
1040+
;(await checkUserLoggedIn(context))([
10341041
RoleOfUser.ADMIN,
10351042
RoleOfUser.SUPER_ADMIN,
10361043
])
10371044

10381045
const organizationExists = await Organization.findOne({ _id: id })
10391046

10401047
if (!organizationExists)
1041-
throw new Error('This Organization doesn\'t exist')
1048+
throw new Error("This Organization doesn't exist")
10421049
await Cohort.deleteMany({ organization: id })
10431050
await Team.deleteMany({ organization: id })
10441051
await Phase.deleteMany({ organization: id })
@@ -1116,7 +1123,7 @@ const resolvers: any = {
11161123
if (password === confirmPassword) {
11171124
const user: any = await User.findOne({ email })
11181125
if (!user) {
1119-
throw new Error('User doesn\'t exist! ')
1126+
throw new Error("User doesn't exist! ")
11201127
}
11211128
user.password = password
11221129
await user.save()
@@ -1136,7 +1143,7 @@ const resolvers: any = {
11361143
if (newPassword === confirmPassword) {
11371144
const user: any = await User.findById(userId)
11381145
if (!user) {
1139-
throw new Error('User doesn\'t exist! ')
1146+
throw new Error("User doesn't exist! ")
11401147
}
11411148

11421149
if (bcrypt.compareSync(currentPassword, user.password)) {

src/schema/index.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ const Schema = gql`
8080
emailNotifications: Boolean!
8181
status: StatusType
8282
ratings: [Rating]
83-
twoFactorAuth:Boolean!
84-
TwoWayVerificationToken:String
83+
twoFactorAuth: Boolean!
84+
TwoWayVerificationToken: String
85+
createdAt: String
86+
updatedAt: String
8587
}
8688
input RegisterInput {
8789
email: String!
@@ -149,16 +151,15 @@ const Schema = gql`
149151
user: User
150152
}
151153
type LoginResponse {
152-
token: String!
153-
user: User!
154-
message: String!
155-
}
154+
token: String!
155+
user: User!
156+
message: String!
157+
}
156158
type Login {
157159
token: String
158160
user: User
159-
message:String
160-
otpRequired:Boolean
161-
161+
message: String
162+
otpRequired: Boolean
162163
}
163164
type OrgLogin {
164165
token: String
@@ -192,7 +193,7 @@ const Schema = gql`
192193
description: String
193194
}
194195
195-
type Rating {
196+
type Rating {
196197
id: ID!
197198
user: User!
198199
sprint: Int!
@@ -314,10 +315,13 @@ const Schema = gql`
314315
}
315316
316317
type Mutation {
317-
enableTwoFactorAuth(email: String!): String
318+
enableTwoFactorAuth(email: String!): String
318319
# //TwoWayVerificationToken: String!
319-
disableTwoFactorAuth(email: String!): String
320-
loginWithTwoFactorAuthentication(email: String!, otp: String!): LoginResponse!
320+
disableTwoFactorAuth(email: String!): String
321+
loginWithTwoFactorAuthentication(
322+
email: String!
323+
otp: String!
324+
): LoginResponse!
321325
createUserRole(name: String!): UserRole!
322326
uploadResume(userId: ID!, resume: String!): Profile
323327
dropTTLUser(email: String!, reason: String!): String!

0 commit comments

Comments
 (0)