Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/resolvers/profileResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { sendEmail } from '../utils/sendEmail'
import Cohort from '../models/cohort.model'
import Team from '../models/team.model'
import mongoose, { ObjectId } from 'mongoose'
import { fetchTraineeAttendance } from './attendance.resolvers'
import Ticket from '../models/ticket.model'

const profileResolvers: any = {
Query: {
Expand Down Expand Up @@ -163,7 +165,23 @@ const profileResolvers: any = {
})
.exec()

return traineesInSameTeam
const traineeWithAttendance = await Promise.all(
traineesInSameTeam.map(async (trainee) => {
const objectId = new mongoose.Types.ObjectId(trainee.id)
const traineeTickets = await Ticket.find({
assignee: objectId,
status: 'open',
})
const { allPhasesAverage } = await fetchTraineeAttendance(trainee.id)
return {
traineeInfo: trainee,
attendance: allPhasesAverage,
numOfTickets: traineeTickets.length,
}
})
)

return traineeWithAttendance
},
},
Profile: {
Expand Down
103 changes: 55 additions & 48 deletions src/resolvers/userResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { EmailPattern } from '../utils/validation.utils'
import { Context } from './../context'
import { UserInputError } from 'apollo-server'
import { encodeOtpToToken, generateOtp } from '../utils/2WayAuthentication'
import jwt from 'jsonwebtoken'
import jwt from 'jsonwebtoken'
import nonTraineeTemplate from '../utils/templates/nonTraineeTemplate'
const octokit = new Octokit({ auth: `${process.env.Org_Repo_Access}` })

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

return Organization.find()
},
Expand Down Expand Up @@ -169,7 +169,7 @@ const resolvers: any = {
{ organisation, username }: any,
context: Context
) {
; (await checkUserLoggedIn(context))([
;(await checkUserLoggedIn(context))([
RoleOfUser.ADMIN,
RoleOfUser.COORDINATOR,
'trainee',
Expand All @@ -181,7 +181,7 @@ const resolvers: any = {
name: organisation,
})
if (!organisationExists)
throw new Error('This Organization doesn\'t exist')
throw new Error("This Organization doesn't exist")

organisation = organisationExists.gitHubOrganisation

Expand Down Expand Up @@ -329,9 +329,16 @@ const resolvers: any = {
invitation.status = 'accepted'
await invitation.save()
}
if(user.role !=='trainee'){
const content = nonTraineeTemplate( user.email,password,org.name)
sendEmail(user.email,'Login Details',content,process.env.FRONTEND_LINK, process.env.ADMIN_EMAIL, process.env.ADMIN_PASS)
if (user.role !== 'trainee') {
const content = nonTraineeTemplate(user.email, password, org.name)
sendEmail(
user.email,
'Login Details',
content,
process.env.FRONTEND_LINK,
process.env.ADMIN_EMAIL,
process.env.ADMIN_PASS
)
}

const newProfile = await Profile.create({
Expand Down Expand Up @@ -377,14 +384,14 @@ const resolvers: any = {
context: any
) {
// Check organization validity
const org = await checkLoggedInOrganization(orgToken);
const { clientIpAdress } = context;
const org = await checkLoggedInOrganization(orgToken)
const { clientIpAdress } = context
if (!org) {
throw new GraphQLError('Organization not found', {
extensions: { code: 'InvalidOrganization' },
});
})
}

// Find user with populated fields
const user: any = await User.findOne({ email }).populate({
path: 'cohort',
Expand All @@ -400,30 +407,30 @@ const resolvers: any = {
strictPopulate: false,
},
},
});
})

// Check if user exists
if (!user) {
throw new GraphQLError('Invalid credentials', {
extensions: { code: 'AccountNotFound' },
});
})
}

// Check if account is active
if (user.status?.status !== 'active') {
throw new GraphQLError(
`Account is ${user.status?.status}. Contact admin.`,
{
extensions: { code: 'AccountInactive' },
}
);
)
}

// Check if two-factor authentication is enabled
if (user.twoFactorAuth) {
const otp = generateOtp(); // Generate OTP
const TwoWayVerificationToken = encodeOtpToToken(otp, email); // Encode OTP
const otp = generateOtp() // Generate OTP
const TwoWayVerificationToken = encodeOtpToToken(otp, email) // Encode OTP

// Send email with OTP
await sendEmail(
email,
Expand All @@ -432,55 +439,55 @@ const resolvers: any = {
null,
process.env.ADMIN_EMAIL,
process.env.ADMIN_PASS
);
)

// Save the Two-Way Verification Token to the database
user.TwoWayVerificationToken = TwoWayVerificationToken;
await user.save();
user.TwoWayVerificationToken = TwoWayVerificationToken
await user.save()

// Return a response without exposing the token
return {
message: 'Check your email for the OTP code.',
otpRequired: true,
user: { id: user._id },
};
}
} else {
// Verify password if 2FA is not enabled
const passwordMatch = await user?.checkPass(password);
const passwordMatch = await user?.checkPass(password)
if (!passwordMatch) {
throw new GraphQLError('Invalid credentials', {
extensions: { code: 'InvalidCredential' },
});
})
}

// Generate token for authenticated user
const token = jwt.sign(
{ userId: user._id, role: user._doc?.role || 'user' },
SECRET,
{ expiresIn: '2h' }
);
const geoData = await logGeoActivity(user, clientIpAdress); // Log activity
const organizationName = user.organizations[0];
)

const geoData = await logGeoActivity(user, clientIpAdress) // Log activity

const organizationName = user.organizations[0]
if (organizationName) {
const location =
geoData && geoData.city && geoData.country_name
? `${geoData.city}-${geoData.country_name}`
: null;
await loginsCount(organizationName, location);
: null
await loginsCount(organizationName, location)
}

// Return token and user data
return {
token,
user: user.toJSON(),
geoData,
otpRequired: false,
};
}
}
},

async deleteUser(_: any, { input }: any, context: { userId: any }) {
const requester = await User.findById(context.userId)
if (!requester) {
Expand Down Expand Up @@ -563,9 +570,9 @@ const resolvers: any = {
]
const org = await checkLoggedInOrganization(orgToken)
const roleExists = allRoles.includes(name)
if (!roleExists) throw new Error('This role doesn\'t exist')
if (!roleExists) throw new Error("This role doesn't exist")
const userExists = await User.findById(id)
if (!userExists) throw new Error('User doesn\'t exist')
if (!userExists) throw new Error("User doesn't exist")

const getAllUsers = await User.find({
role: RoleOfUser.ADMIN,
Expand Down Expand Up @@ -802,7 +809,7 @@ const resolvers: any = {
context: Context
) {
// check if requester is super admin
; (await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
;(await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
const orgExists = await Organization.findOne({ name: name })
if (action == 'approve') {
if (!orgExists) {
Expand Down Expand Up @@ -872,7 +879,7 @@ const resolvers: any = {
context: Context
) {
// the below commented line help to know if the user is an superAdmin to perform an action of creating an organization
; (await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
;(await checkUserLoggedIn(context))([RoleOfUser.SUPER_ADMIN])
if (action == 'new') {
const orgExists = await Organization.findOne({ name: name })
if (orgExists) {
Expand Down Expand Up @@ -937,7 +944,7 @@ const resolvers: any = {
{ name, gitHubOrganisation }: any,
context: Context
) {
; (await checkUserLoggedIn(context))([
;(await checkUserLoggedIn(context))([
RoleOfUser.ADMIN,
RoleOfUser.SUPER_ADMIN,
])
Expand Down Expand Up @@ -1030,15 +1037,15 @@ const resolvers: any = {
},

async deleteOrganization(_: any, { id }: any, context: Context) {
; (await checkUserLoggedIn(context))([
;(await checkUserLoggedIn(context))([
RoleOfUser.ADMIN,
RoleOfUser.SUPER_ADMIN,
])

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

if (!organizationExists)
throw new Error('This Organization doesn\'t exist')
throw new Error("This Organization doesn't exist")
await Cohort.deleteMany({ organization: id })
await Team.deleteMany({ organization: id })
await Phase.deleteMany({ organization: id })
Expand Down Expand Up @@ -1116,7 +1123,7 @@ const resolvers: any = {
if (password === confirmPassword) {
const user: any = await User.findOne({ email })
if (!user) {
throw new Error('User doesn\'t exist! ')
throw new Error("User doesn't exist! ")
}
user.password = password
await user.save()
Expand All @@ -1136,7 +1143,7 @@ const resolvers: any = {
if (newPassword === confirmPassword) {
const user: any = await User.findById(userId)
if (!user) {
throw new Error('User doesn\'t exist! ')
throw new Error("User doesn't exist! ")
}

if (bcrypt.compareSync(currentPassword, user.password)) {
Expand Down
36 changes: 22 additions & 14 deletions src/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ const Schema = gql`
emailNotifications: Boolean!
status: StatusType
ratings: [Rating]
twoFactorAuth:Boolean!
TwoWayVerificationToken:String
twoFactorAuth: Boolean!
TwoWayVerificationToken: String
}
input RegisterInput {
email: String!
Expand Down Expand Up @@ -149,16 +149,15 @@ const Schema = gql`
user: User
}
type LoginResponse {
token: String!
user: User!
message: String!
}
token: String!
user: User!
message: String!
}
type Login {
token: String
user: User
message:String
otpRequired:Boolean

message: String
otpRequired: Boolean
}
type OrgLogin {
token: String
Expand Down Expand Up @@ -192,7 +191,7 @@ const Schema = gql`
description: String
}

type Rating {
type Rating {
id: ID!
user: User!
sprint: Int!
Expand Down Expand Up @@ -271,10 +270,16 @@ const Schema = gql`
createdAt: String
}

type TTLTrainee {
traineeInfo: User
attendance: String
numOfTickets: Int
}

type Query {
getAllUsers(orgToken: String): [User]
getAllTTLUsers(orgToken: String): [User]
getTTLTrainees(orgToken: String): [User]
getTTLTrainees(orgToken: String): [TTLTrainee]
getUsers(orgToken: String): [User]
getAllCoordinators(orgToken: String): [User]
getProfile: Profile
Expand Down Expand Up @@ -314,10 +319,13 @@ const Schema = gql`
}

type Mutation {
enableTwoFactorAuth(email: String!): String
enableTwoFactorAuth(email: String!): String
# //TwoWayVerificationToken: String!
disableTwoFactorAuth(email: String!): String
loginWithTwoFactorAuthentication(email: String!, otp: String!): LoginResponse!
disableTwoFactorAuth(email: String!): String
loginWithTwoFactorAuthentication(
email: String!
otp: String!
): LoginResponse!
createUserRole(name: String!): UserRole!
uploadResume(userId: ID!, resume: String!): Profile
dropTTLUser(email: String!, reason: String!): String!
Expand Down
Loading