1+ import { AuthenticationError } from 'apollo-server-errors'
2+ import mongoose from 'mongoose'
3+
4+ import jwt from 'jsonwebtoken' ;
5+ import { generateTokenUserExists } from '../helpers/user.helpers' ;
6+ import { sendEmail } from '../utils/sendEmail' ;
7+ import { verifyOtpToken } from '../utils/2WayAuthentication' ;
8+ import { GraphQLError } from 'graphql' ;
9+ import { User } from '../models/user' ;
10+
11+ interface Enable2FAInput {
12+ email : string
13+ }
14+
15+ interface Disable2FAInput {
16+ email : string
17+ }
18+
19+ const SECRET : string = process . env . SECRET ?? 'test_secret'
20+ const resolvers = {
21+ Mutation : {
22+ enableTwoFactorAuth : async ( _ : any , { email } : Enable2FAInput ) => {
23+ try {
24+ const UserModel = mongoose . model ( 'User' )
25+ const user = await UserModel . findOne ( { email } )
26+
27+ if ( ! user ) {
28+ throw new Error ( 'User not found' )
29+ }
30+
31+ if ( user . twoFactorAuth ) {
32+ // 2FA is already enabled for this user
33+ return 'Two-factor authentication is already enabled for this user.'
34+ }
35+
36+ user . twoFactorAuth = true
37+
38+ await user . save ( )
39+
40+
41+ await sendEmail (
42+ email ,
43+ ' Two-Factor Authentication enabled ' ,
44+ 'Two-Factor Authentication has been enabled on your account next time . You will be asked to verify your account with an OTP code' ,
45+ null ,
46+ process . env . ADMIN_EMAIL ,
47+ process . env . ADMIN_PASS
48+ )
49+ return 'Two-factor authentication enabled.'
50+ } catch ( error ) {
51+ console . error ( 'Enable 2FA Error:' , error )
52+ // Add this for more detailed error logging
53+ throw new Error ( 'Failed to enable two-factor authentication' )
54+ }
55+ } ,
56+ disableTwoFactorAuth : async ( _ : any , { email } : Disable2FAInput ) => {
57+ try {
58+ const UserModel = mongoose . model ( 'User' )
59+ const user = await UserModel . findOne ( { email } )
60+
61+ if ( ! user ) {
62+ throw new Error ( 'User not found' )
63+ }
64+
65+ // Disable 2FA by clearing the secret and one-time code
66+ user . twoFactorSecret = null
67+ user . twoFactorAuth = false
68+ user . oneTimeCode = null
69+
70+ await user . save ( )
71+
72+ return 'Two-factor authentication disabled.'
73+ } catch ( error ) {
74+ throw new Error ( 'Failed to disable two-factor authentication' )
75+ }
76+ } ,
77+
78+
79+ loginWithTwoFactorAuthentication : async (
80+ _ : any ,
81+ { id, email, otp, TwoWayVerificationToken } : { id ?: string ; email ?: string ; otp : string ; TwoWayVerificationToken : string }
82+ ) => {
83+
84+ // Verify OTP
85+ const isValidOtp = verifyOtpToken ( TwoWayVerificationToken , otp ) ;
86+
87+ if ( ! isValidOtp ) {
88+ throw new GraphQLError ( 'Invalid OTP. Please try again.' ) ;
89+ }
90+
91+ // Fetch user by either ID or email
92+ let user : any ;
93+ if ( id ) {
94+ user = await User . findById ( id ) ;
95+ } else if ( email ) {
96+ user = await User . findOne ( { email } ) ;
97+ }
98+
99+ // Check if user was found
100+ if ( ! user ) {
101+ throw new GraphQLError ( 'User not found.' ) ;
102+ }
103+
104+ // Generate JWT token
105+ const token = jwt . sign (
106+ { userId : user . _id , role : user . _doc ?. role || 'user' } ,
107+ SECRET ,
108+ { expiresIn : '2h' }
109+ ) ;
110+
111+
112+
113+ return {
114+ token,
115+ user : user . toJSON ( ) ,
116+
117+ message : 'Logged in successfully' ,
118+ } ;
119+ } ,
120+
121+ } ,
122+ } ;
123+
124+
125+ export default resolvers
0 commit comments