UNPKG

yekonga-server

Version:
831 lines (706 loc) 36.9 kB
// @ts-nocheck /*global Yekonga, serverLibrary */ const GraphQLScalarType = serverLibrary.GraphQLScalarType; const OAuth2Client = serverLibrary.OAuth2Client; const bcrypt = serverLibrary.bcrypt; const config = Yekonga.Config; const jwt = serverLibrary.jwt; const H = Yekonga.Helper; const userCollection = Yekonga.Helper.getCollectionByName("users"); const profileCollection = Yekonga.Helper.getCollectionByName("profiles"); const DefaultResolvers = require('../defaultResolver'); const ignoreFind = { beforeFind: false, afterFind: false }; const hiddenToken = "token"; const hiddenOtpCode = "otpCode"; const hiddenPassword = "password"; const hiddenFields = [hiddenPassword, hiddenOtpCode]; const resolvers = { URL: DefaultResolvers.URL, Profile: { profileUrl: async function(data, params, context) { var images = []; var values = (Array.isArray(data.profileUrl)) ? data.profileUrl : (data.profileUrl ? [data.profileUrl] : []); var defaultImage = Yekonga.Helper.getBaseUrl(`img/avatar-placeholder.jpg`); for (const val of values) { if (val && val.trim() != '') { if (val.trim().substr(0, 4) == 'http' || val.trim().substr(0, 2) == '//') { images.push(val); } else { images.push(Yekonga.Helper.getBaseUrl(`uploads/${val}`)); } } else { images.push(defaultImage); } } return (Array.isArray(data.profileUrl)) ? images : ((images.length) ? images.pop() : defaultImage); }, }, Query: { profile: async function(parent, params, context) { const { req } = context || {}; var userId = null; if (req && req.Yekonga.Auth) { userId = req.Yekonga.Auth.userId; } var user = await Yekonga.Model.User.findOne({ userId }, null, true); if (!user) { throw new Yekonga.Error.Authentication('Unauthorized'); } return await Yekonga.Helper.getLoginData({ user, profileId: null, isAdmin: false, Client: req.Yekonga.Client }); }, }, Mutation: { login: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; if (typeof Yekonga.CloudService.Auth.customLogin == 'function') { return Yekonga.CloudService.Auth.customLogin(_, params, context); } const salt = bcrypt.genSaltSync(Yekonga.Config.authentication.saltRound); const { auth, headers } = context; const { input } = params; var body = input; var key = "username"; if(H.isUsernameIdentifier()) { key = 'username'; } else if(H.isEmail(body.username) && H.isEmailIdentifier()){ key = "email"; } else if(H.isPhone(body.username) && H.isPhoneIdentifier()){ key = "phone"; } else if(H.isPhone(body.username) && H.isWhatsappIdentifier()){ key = "whatsapp"; } body.type = (body.type) ? body.type : 'pass'; if (Yekonga.CloudService.Auth.beforeLogin) { var beforeData = await Yekonga.CloudService.Auth.beforeLogin({input: body, body, ...context}); if (beforeData) { body = beforeData; } else if (beforeData === false) { throw new Yekonga.Error.Authentication('Rejected by before login'); } } var user = await Yekonga.Helper.attemptLogin({ key, value: body.username, password: body.password, type: body.type, Client: req.Yekonga.Client, }); if (user && !user.error) { if (Yekonga.CloudService.Auth.afterLogin) { var afterData = await Yekonga.CloudService.Auth.afterLogin({user, ...context}); if (afterData) { user = afterData; } } return user; } else if (user && user.error) { // console.log(user); throw new Yekonga.Error.Authentication(user.error.message); } throw new Yekonga.Error.Authentication('Wrong credential'); }, socialLogin: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; if (typeof Yekonga.CloudService.Auth.customSocialLogin == 'function') { return Yekonga.CloudService.Auth.customSocialLogin(_, params, context); } const { input } = params; var body = input; var user = null; var isRegistration = false; if (Yekonga.CloudService.Auth.beforeLogin) { var beforeData = await Yekonga.CloudService.Auth.beforeLogin({body, input: body, ...context}); if (beforeData) { body = beforeData; } else if (beforeData === false) { throw new Yekonga.Error.Authentication('Rejected by before login'); } } var ticket = null; const client = new OAuth2Client({ clientId: Yekonga.Config.googleClientId, clientSecret: Yekonga.Config.googleClientSecret, redirectUri: '', }); if(!H.isEmpty(body.tokenId)) { ticket = await client.verifyIdToken({ idToken: body.tokenId, audience: Yekonga.Config.googleClientId }); } else if(!H.isEmpty(body.accessToken)) { client.setCredentials({ access_token: body.accessToken }) ticket = await client.request({ url: 'https://www.googleapis.com/oauth2/v3/userinfo' }) if(ticket.data) ticket = ticket.data; } const payload = (ticket && ticket.getPayload)? ticket.getPayload(): ticket; if (payload && payload.email_verified && payload.email) { if(H.isUsernameIdentifier()) { user = await Yekonga.Model.User.findOne({ username: payload.email }, ignoreFind, true); } else if(H.isEmailIdentifier()) { user = await Yekonga.Model.User.findOne({ email: payload.email }, ignoreFind, true); } if (!user) { let otpBody = { email: payload.email, firstName: payload.given_name, lastName: payload.family_name, profileUrl: payload.picture, status: 'active' } otpBody['emailVerifiedAt'] = Yekonga.Helper.getTimestamp(); otpBody['isEmailVerified'] = true; user = await Yekonga.Helper.createUser(otpBody); isRegistration = true; } if (user && !user.error) { user = await Yekonga.Helper.getLoginData({ user, profileId: null, isAdmin: false, Client: req.Yekonga.Client }); if (user.isBanned) { throw new Yekonga.Error.Authentication(`You banned to access ${Yekonga.Config.appName}`); } if (Yekonga.CloudService.Auth.afterLogin) { var afterData = await Yekonga.CloudService.Auth.afterLogin({user, ...context}); if (afterData) { user = afterData; } } if (isRegistration && user) { let _subject = `${Yekonga.Config.appName} Registration`; let _html = await Yekonga.Cloud.run('googleAccountContentEmail', user); let _text = await Yekonga.Cloud.run('googleAccountContentSMS', user); var profileId = null; var senderName = null; if(req && req.Yekonga && req.Yekonga.fixedProfile) { profileId = req.Yekonga.fixedProfile; var config = await Yekonga.Cloud.profileConfig(profileId); senderName = (config)? config.smsSenderName: null; } Yekonga.Helper.notify(user, { title: _subject, text: _text, html: _html, profileId: profileId, senderName: senderName, }); } return user; } else if (user && user.error) { throw new Yekonga.Error.Authentication(user.error.message); } } throw new Yekonga.Error.Authentication('Wrong credential'); }, otp: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; var { input, type } = params; if (typeof Yekonga.CloudService.Auth.customOtp == 'function') { return Yekonga.CloudService.Auth.customOtp(_, params, context); } var body = {}; var response = { status: false, success: false, message: "User does not exists" }; if (!input || (input && input.username && input.username.trim() == '')) throw new Yekonga.Error.Authentication('Phone or email required'); if (type) type = `${type}`.toLowerCase(); var isRegistration = false; var appName = Yekonga.Config.appName; var user = null; var key = 'username'; if(H.isUsernameIdentifier()) { if(H.isEmail(input.username)) { if(!type) type = 'email'; } else if(H.isPhone(input.username)) { if(!type) type = 'phone'; } body[key] = input.username; } else if(H.isEmail(input.username) && H.isEmailIdentifier()) { if(!type) type = 'email'; key = 'email'; body[key] = input.username; } else if(H.isPhone(input.username) && H.isPhoneIdentifier()) { if(!type) type = 'phone'; key = 'phone'; body[key] = H.formatPhone(input.username); } else if(H.isPhone(input.username) && H.isWhatsappIdentifier()) { if(!type) type = 'whatsapp'; key = 'whatsapp'; body[key] = H.formatPhone(input.username); } else if(!type) { type = 'phone'; } if (Yekonga.CloudService.Auth.beforeOtp) { var beforeData = await Yekonga.CloudService.Auth.beforeOtp({body, input: body, ...context}); if (beforeData) { body = beforeData; } else if (beforeData === false) { throw new Yekonga.Error.Authentication('Rejected by before OTP'); } } if(body[key]) { user = await Yekonga.Model.User.findOne(body, ignoreFind, true); if (!user && Yekonga.Config.registerUserOnOtp) { body.role = "user"; body.status = "active"; if(H.isUsernameIdentifier()) { body.usernameType = type; } user = await Yekonga.Helper.createUser(body); if (user) isRegistration = true; } } if (user) { if (user.isBanned) { throw new Yekonga.Error.Authentication(`You banned to access ${Yekonga.Config.appName}`); } user = await Yekonga.Helper.sendOtp(user, type, {req, res}); if (user) { if (Yekonga.CloudService.Auth.afterOtp) { var afterData = await Yekonga.CloudService.Auth.afterOtp({ user, ...context }); if (afterData) { response = afterData; } } response.status = true; response.success = true; response.message = 'Message sent'; } else if (response && response.error) { throw new Yekonga.Error.Authentication(response.error.message); } } return response; }, contactOTP: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; var { input, type } = params; if (type) type = `${type}`.toLowerCase(); var body = {}; var userId = null; var otpCodeLength = 4; var response = { status: false, success: false, message: "User does not exists" }; if (req && req.Yekonga.Auth) { userId = req.Yekonga.Auth.userId; } if (H.isEmpty(userId) || !input || (input && !( H.isNotEmpty(input.email) || H.isNotEmpty(input.phone) || H.isNotEmpty(input.whatsapp) ))) throw new Yekonga.Error.Authentication('Phone, email or whatsapp required'); var user = await Yekonga.Model.User.findOne({ userId }, null, true); if (user) { if (user.isBanned) { throw new Yekonga.Error.Authentication(`You banned to access ${Yekonga.Config.appName}`); } if(type == 'email' && H.isEmail(input.email) && !H.isEmailIdentifier()) { body.email = input.email; body.isEmailVerified = false; body.emailVerifyCode = H.isEmpty(user.emailVerifyCode)? user.emailVerifyCode: H.getRandomInt(otpCodeLength); body.emailVerifiedAt = (user.emailVerifiedAt)? user.emailVerifiedAt: null; } else if(type == 'phone' && H.isPhone(input.phone) && !H.isPhoneIdentifier()) { body.phone = H.formatPhone(input.phone); body.isPhoneVerified = false; body.phoneVerifyCode = H.isEmpty(user.phoneVerifyCode)? user.phoneVerifyCode: H.getRandomInt(otpCodeLength); body.phoneVerifiedAt = (user.phoneVerifiedAt)? user.phoneVerifiedAt: null; } else if(type == 'whatsapp' && H.isPhone(input.whatsapp) && !H.isWhatsappIdentifier()) { body.whatsapp = H.formatPhone(input.whatsapp); body.isWhatsappVerified = false; body.whatsappVerifyCode = H.isEmpty(user.whatsappVerifyCode)? user.whatsappVerifyCode: H.getRandomInt(otpCodeLength); body.whatsappVerifiedAt = (user.whatsappVerifiedAt)? user.whatsappVerifiedAt: null; } await Yekonga.Model.User.update(body, { userId: user.userId }, null, true); response.status = true; response.success = true; response.message = 'Message sent'; } return response; }, contactVerify: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; var { input, type } = params; if (type) type = `${type}`.toLowerCase(); var body = {}; var userId = null; var response = { status: false, success: false, message: "User does not exists" }; var timestamp = H.getTimestamp(); if (req && req.Yekonga.Auth) { userId = req.Yekonga.Auth.userId; } if (H.isEmpty(userId) || !input || (input && !( H.isNotEmpty(input.email) || H.isNotEmpty(input.phone) || H.isNotEmpty(input.whatsapp) ))) throw new Yekonga.Error.Authentication('Phone, email or whatsapp required'); var user = await Yekonga.Model.User.findOne({ userId }, null, true); if (user) { if (user.isBanned) { throw new Yekonga.Error.Authentication(`You banned to access ${Yekonga.Config.appName}`); } if(type == 'email' && H.isEmail(input.email)) { if(user.emailVerifyCode === input.password) { body.isEmailVerified = true; body.emailVerifyCode = null; body.emailVerifiedAt = timestamp; } } else if(type == 'phone' && H.isPhone(input.phone)) { if(user.emailVerifyCode === input.password) { body.isPhoneVerified = true; body.phoneVerifyCode = null; body.phoneVerifiedAt = timestamp; } } else if(type == 'whatsapp' && H.isPhone(input.whatsapp)) { if(user.whatsappVerifyCode === input.password) { body.isWhatsappVerified = true; body.whatsappVerifyCode = null; body.whatsappVerifiedAt = timestamp; } } await Yekonga.Model.User.update(body, { userId: user.userId }, null, true); response.status = true; response.success = true; response.message = 'Message sent'; } return response; }, registration: async function(_, params, context) { let response = { status: false, success: false, message: "User does not exists" }; if(!context) context = { req: {}, res: {}} const { req, res } = context; if (typeof Yekonga.CloudService.Auth.customRegistration == 'function') { return Yekonga.CloudService.Auth.customRegistration(_, params, context); } const { input } = params; var body = input; if (!body.password) body.password = "12345678"; if (body.phone) body.phone = H.formatPhone(body.phone); if (body.phone && body.phone.trim() == '') body.phone = null; body.status = "active"; if (Yekonga.CloudService.Auth.beforeRegistration) { var beforeData = await Yekonga.CloudService.Auth.beforeRegistration({body, ...context}); if (beforeData) { body = beforeData; } } var user = null; if (typeof body.phone != "undefined" && !H.isPhone(body.phone)) { throw new Yekonga.Error.Authentication("Invalid phone number"); } else if (typeof body.email != "undefined" && !H.isEmail(body.email)) { throw new Yekonga.Error.Authentication("Invalid email"); } else if (typeof body.username != "undefined" && body.username && body.username.trim() != "") { throw new Yekonga.Error.Authentication("Invalid email"); } if (!user && body.email && body.email.trim() != '') user = await Yekonga.Model.User.findOne({ email: body.email }, ignoreFind, true); if (!user && body.phone && body.phone.trim() != '') user = await Yekonga.Model.User.findOne({ phone: body.phone }, ignoreFind, true); if (!user && body.username && body.username.trim() != '') user = await Yekonga.Model.User.findOne({ username: body.username }, ignoreFind, true); if (!user) { var password = body.password; body.role = (body.role) ? body.role : 'user'; body.password = Yekonga.Helper.bcryptPassword(password); body.otpCode = Yekonga.Helper.getRandomInt(4); body.otpCreatedAt = Yekonga.Helper.getTimestamp(); user = await Yekonga.Model.User.create(body, { params: { input: body } }, true); // console.log('====> create', user); if (user && user.data) user = user.data; if (Array.isArray(user)) user = user.pop(); user = await Yekonga.Helper.attemptLogin({ key: 'userId', value: user.userId, password, type: "registration", Client: req.Client, }); // console.log('====> login', user); if (user && user.error) { throw new Yekonga.Error.Authentication(user.error.message); } else if (user) { let _subject = `${Yekonga.Config.appName} Registration`; let _html = await Yekonga.Cloud.run('registrationContentEmail', user); let _text = await Yekonga.Cloud.run('registrationContentSMS', user); let _whatsapp = await Yekonga.Cloud.run('registrationContentWhatsapp', user); var profileId = null; var senderName = null; if(req && req.Yekonga && req.Yekonga.fixedProfile) { profileId = req.Yekonga.fixedProfile; var config = await Yekonga.Cloud.profileConfig(profileId); senderName = (config)? config.smsSenderName: null; } Yekonga.Helper.notify(user, { title: _subject, text: _text, html: _html, whatsapp: _whatsapp, profileId: profileId, senderName: senderName, }); let _subject2 = `Your verification code`; let _html2 = await Yekonga.Cloud.run('otpContentEmail', user); let _text2 = await Yekonga.Cloud.run('otpContentSMS', user); let _whatsapp2 = await Yekonga.Cloud.run('otpContentWhatsapp', user); Yekonga.Helper.notify(user, { title: _subject2, text: _text2, html: _html2, whatsapp: _whatsapp2, profileId: profileId, senderName: senderName, }); response.status = true; response.success = true; response.message = 'Message sent'; } if (Yekonga.CloudService.Auth.afterRegistration) { var afterData = await Yekonga.CloudService.Auth.afterRegistration({user, input, ...context}); if (afterData) { user = afterData; } } // return response; return user; } else if (user && user.error) { throw new Yekonga.Error.Authentication(user.error.message); } throw new Yekonga.Error.Forbidden('User exists'); }, resetPassword: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; if (typeof Yekonga.CloudService.Auth.customResetPassword == 'function') { return Yekonga.CloudService.Auth.customResetPassword(_, params, context); } var body = {}; const { input } = params; var response = { status: false, success: false, message: "User does not exists" }; if (!input || (input && input.username && input.username.trim() == '')) throw new Yekonga.Error.Authentication('Phone or email required'); let key = H.isEmail(input.username) ? 'email' : 'phone'; body[key] = (key == 'phone') ? Yekonga.Helper.formatPhone(input.username) : input.username; if (Yekonga.CloudService.Auth.beforeResetPassword) { var beforeData = await Yekonga.CloudService.Auth.beforeResetPassword({body, input: body, ...context}); if (beforeData) { body = beforeData; } } let user = await Yekonga.Model.User.findOne(body, ignoreFind, true); if (user) { let otpCodeLength = 4; let otpCode = (user.otpCode && user.otpCode.length == otpCodeLength) ? user.otpCode : H.getRandomInt(otpCodeLength); let otpCreatedAt = H.getTimestamp(); let otpBody = { otpCode, otpCreatedAt } let result = await Yekonga.Model.User.update(otpBody, { userId: user.userId }, ignoreFind, true); if (result && (!result.error && result.affectedCount)) { let _subject = `Your single-use code`; let _html = await Yekonga.Cloud.run('resetPasswordContentEmail', user); let _text = await Yekonga.Cloud.run('resetPasswordContentSMS', user); let _whatsapp = await Yekonga.Cloud.run('resetPasswordContentWhatsapp', user); var profileId = null; var senderName = null; if(req && req.Yekonga && req.Yekonga.fixedProfile) { profileId = req.Yekonga.fixedProfile; var config = await Yekonga.Cloud.profileConfig(profileId); senderName = (config)? config.smsSenderName: null; } Yekonga.Helper.notify(user, { title: _subject, text: _text, html: _html, whatsapp: _whatsapp, profileId: profileId, senderName: senderName, }); if (Yekonga.CloudService.Auth.afterResetPassword) { var afterData = await Yekonga.CloudService.Auth.afterResetPassword({ otpCode, otpCreatedAt, userId: user.userId }, input); if (afterData) { response = afterData; } } response.status = true; response.success = true; response.message = 'Message sent'; } else if (response && response.error) { throw new Yekonga.Error.Authentication(response.error.message); } } return response; }, changePassword: async function(_, params, context) { if(!context) context = { req: {}, res: {}} const { req, res } = context; if (typeof Yekonga.CloudService.Auth.customChangePassword == 'function') { return Yekonga.CloudService.Auth.customChangePassword(_, params, context); } const { input } = params; var body = {}; var response = { error: true, success: false, message: 'Invalid email or phone' } let key = H.isEmail(input.username) ? 'email' : 'phone'; body[key] = (key == 'phone') ? Yekonga.Helper.formatPhone(input.username) : input.username; if (Yekonga.CloudService.Auth.beforeChangePassword) { var beforeData = await Yekonga.CloudService.Auth.beforeChangePassword({body, input: body, ...context}); if (beforeData) { body = beforeData; } } let user = await Yekonga.Model.User.findOne(body, {}, true); if (user) { if (user.token == input.token) { if (input.password == input.passwordConfirmed) { let result = await Yekonga.Model.User.update({ token: null, password: Yekonga.Helper.bcryptPassword(input.password), }, { userId: user.userId }, {}, true); response.error = false; response.success = true; response.message = 'Password changed success'; } } } if (Yekonga.CloudService.Auth.afterChangePassword) { var afterData = await Yekonga.CloudService.Auth.afterChangePassword({user, input, ...context}); if (afterData) { response = afterData; } } return response; }, profile: async function(_, params, context) { if(!context) context = { req: {}, res: {} } const { req, res } = context || {}; const { input } = params; var userId = null; var profileId = null; if (req && req.Yekonga && req.Yekonga.Auth) { userId = req.Yekonga.Auth.userId; profileId = req.Yekonga.Auth.profileId; } var body = {}; var processKeys = ['password', 'profileUrl']; for (const key in input) { if (input.hasOwnProperty(key)) { const value = input[key]; if (processKeys.includes(key)) { if (value && key == 'password') { body[key] = Yekonga.Helper.bcryptPassword(value); } else if (value) { body[key] = H.saveFile(value); } } else { body[key] = value; } } } if (body.phone) body.phone = H.formatPhone(body.phone); if (body.phone == '') body.phone = null; if (Yekonga.CloudService.Auth.beforeProfile) { var beforeData = await Yekonga.CloudService.Auth.beforeProfile({body, input: body, ...context}); if (beforeData) { body = beforeData; } } var user = await Yekonga.Model.User.findOne({ userId }, null, true); if (user) { user = await Yekonga.Model.User.update(body, { userId }, null, true); if (Array.isArray(user)) user = user.pop(); if (user && user.data) user = user.data; user = await Yekonga.Model.User.findOne({ userId }, {}, true); if (user && user.error) { throw new Yekonga.Error.Authentication(user.error.message); } if (Yekonga.CloudService.Auth.afterProfile) { var afterData = await Yekonga.CloudService.Auth.afterProfile({user, input, ...context}); if (afterData) { user = afterData; } } return await Yekonga.Helper.getLoginData({ user, profileId: null, isAdmin: false, Client: req.Yekonga.Client }); } else if (user && user.error) { throw new Yekonga.Error.Authentication(user.error.message); } throw new Yekonga.Error.Forbidden('User not found'); }, switchAccount: async function(_, params, context) { const { req, res, Auth } = context || {}; const tokenPayload = (params.token)? H.decodeToken(params.token): req.Yekonga.tokenPayload; var userId = null; var profileId = (params.profileId) ? params.profileId : null; var user = null; var isAdmin = ((Auth && Auth.isAdmin) || (tokenPayload && !H.isEmpty(tokenPayload.adminId))); // console.log(tokenPayload); if(tokenPayload && H.isNotEmpty(tokenPayload.adminId)) { userId = H.isNotEmpty(params.userId) ? params.userId: tokenPayload.adminId; } else { userId = Auth? Auth.userId: null; } if(Auth || (tokenPayload && tokenPayload.adminId)) { var userProfiles = await Yekonga.Model.Profile.find({ userId }, true); var addedUserProfiles = await Yekonga.Model.ProfileUser.find({ userId }, true); profileIds = [ ...userProfiles.map(e=>`${e.profileId}`), ...addedUserProfiles.map(e=>`${e.profileId}`), ]; if(!profileId) { profileId = profileIds.at(0); } if ((H.isNotEmpty(profileId) && profileIds.includes(profileId)) || (Auth && Auth.isAdmin) || (tokenPayload && tokenPayload.adminId)) { var asUser = await Yekonga.Model.User.findOne({ userId: { equalTo: userId } }, true); var adminId = (tokenPayload && H.isNotEmpty(tokenPayload.adminId)) ? tokenPayload.adminId : ((Auth && Auth.isAdmin) ? Auth.userId : null); if (asUser) { if (Yekonga.CloudService.Auth.beforeLogin) { var beforeData = await Yekonga.CloudService.Auth.beforeLogin({body:asUser, input: asUser, ...context}); if (beforeData) { asUser = beforeData; } else if (beforeData === false) { throw new Yekonga.Error.Authentication('Rejected by before login'); } } asUser = await H.getLoginData({ user: asUser, profileId, isAdmin: isAdmin, Client: req.Yekonga.Client, }); var payloadToken = { domain: req.Yekonga.Client.origin, userId: asUser.userId, profileId: asUser.profileId, adminId: adminId, }; asUser.loginAsUser = (!H.isEmpty(adminId)); asUser.token = H.getToken(payloadToken); if (Yekonga.CloudService.Auth.afterLogin) { var afterData = await Yekonga.CloudService.Auth.afterLogin({user: asUser, ...context}); if (afterData) { asUser = afterData; } } user = asUser; } } } return user; }, }, } module.exports = resolvers;