import { ApolloError } from 'apollo-server-lambda'; import { Resolver, Query, Ctx, Authorized, Mutation, Arg } from 'type-graphql'; import { ApolloContext } from '@seed/interfaces/context'; import { editOneGeneric } from '@seed/graphql/BaseService'; import { signinAnonymous, signinGeneric } from './services/AccountService'; import AccountModel, { EditAccountInput } from '@src/accounts/account.model'; import { AccountTypeEnum } from '@src/accounts/account.components'; import { FirebaseTokenResult, SimpleResult } from '@seed/interfaces/components'; import { ResetPasswordInput, NewEmailInput, NewPasswordInput, LoginInput, LinkEmailInput } from './account.components'; import Firebase from '@seed/services/auth/FirebaseService'; import { sendEmail } from '@seed/services/email/EmailService'; import { AvailableTranslation } from '@src/__components/components'; import FirebaseAuth from '@seed/services/auth/FirebaseAuthService'; import { newError } from '@seed/helpers/Error'; @Resolver(AccountModel) export default class AccountBaseResolver { /* ███████╗██╗███████╗██╗ ██████╗ ███████╗ ██╔════╝██║██╔════╝██║ ██╔══██╗██╔════╝ █████╗ ██║█████╗ ██║ ██║ ██║███████╗ ██╔══╝ ██║██╔══╝ ██║ ██║ ██║╚════██║ ██║ ██║███████╗███████╗██████╔╝███████║ ╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚══════╝ */ /* ██████╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗ ██╔═══██╗██║ ██║██╔════╝██╔══██╗╚██╗ ██╔╝ ██║ ██║██║ ██║█████╗ ██████╔╝ ╚████╔╝ ██║▄▄ ██║██║ ██║██╔══╝ ██╔══██╗ ╚██╔╝ ╚██████╔╝╚██████╔╝███████╗██║ ██║ ██║ ╚══▀▀═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ */ @Query(() => AccountModel) @Authorized() async me(@Ctx() ctx: ApolloContext): Promise { return ctx.ctx.user as AccountModel; } /* * Auth side */ @Query(() => FirebaseTokenResult) async login( @Ctx() ctx: ApolloContext, @Arg('creds', { nullable: true }) creds?: LoginInput, @Arg('refreshToken', { nullable: true }) refreshToken?: string, ): Promise { if (creds) { const account = new AccountModel(); await account.getOne({ email: creds.email }, null); return FirebaseAuth.getInstance().loginWithEmailPassword(creds); } if (refreshToken) return FirebaseAuth.getInstance().loginWithRefreshToken(refreshToken); return signinAnonymous(ctx); } @Query(() => SimpleResult) async magicLink(@Arg('input') input: ResetPasswordInput, @Ctx() ctx: ApolloContext): Promise { const account = new AccountModel(); try { await account.getOne({ email: input.email }, null); const magicLink = await Firebase.getInstance().getMagicLink(input.email); await sendEmail('magicLink', account.language, account.email, { ...account, magicLink }); } catch (error) { throw error; } return { message: 'sent' }; } /* ███╗ ███╗██╗ ██╗████████╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗ ████╗ ████║██║ ██║╚══██╔══╝██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗██╔════╝ ██╔████╔██║██║ ██║ ██║ ███████║ ██║ ██║ ██║██████╔╝███████╗ ██║╚██╔╝██║██║ ██║ ██║ ██╔══██║ ██║ ██║ ██║██╔══██╗╚════██║ ██║ ╚═╝ ██║╚██████╔╝ ██║ ██║ ██║ ██║ ╚██████╔╝██║ ██║███████║ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ */ /* * Account side */ // @Mutation(() => AccountModel) // async register(@Arg('input') input: NewAccountInput, @Ctx() ctx: ApolloContext): Promise { // const model = new AccountModel(); // return signinGeneric(model, AccountTypeEnum.user, input, ctx); // } @Mutation(() => AccountModel) @Authorized() async updateMe(@Arg('input') input: EditAccountInput, @Ctx() ctx: ApolloContext): Promise { const model = new AccountModel(); return editOneGeneric(model, ctx.ctx.user._id, input, ctx); } @Mutation(() => AccountModel) @Authorized() async updateMeEmail(@Arg('input') input: NewEmailInput, @Ctx() ctx: ApolloContext): Promise { const currentUser = ctx.ctx.user as AccountModel; try { await Firebase.getInstance().updateEmail({ uid: currentUser._id, email: input.newEmail }); return editOneGeneric(currentUser, currentUser._id, { email: input.newEmail }, ctx); } catch (error) { throw error; } } @Mutation(() => AccountModel) @Authorized() async updateMePassword(@Arg('input') input: NewPasswordInput, @Ctx() ctx: ApolloContext): Promise { const currentUser = ctx.ctx.user as AccountModel; if (input.newPassword != input.newPasswordConfirmation) throw newError(2006); try { // Check old password FirebaseAuth.getInstance().loginWithEmailPassword({ email: currentUser.email, password: input.oldPassword, }); } catch (error) { throw newError(20060); } try { await Firebase.getInstance().updatePassword({ uid: currentUser._id, password: input.newPassword }); return currentUser; } catch (error) { throw error; } } @Mutation(() => SimpleResult) async resetPassword(@Arg('input') input: ResetPasswordInput, @Ctx() ctx: ApolloContext): Promise { const account = new AccountModel(); try { await account.getOne({ email: input.email }, null); const resetPasswordLink = await Firebase.getInstance().getResetPasswordLink(input.email); await sendEmail('resetPassword', account.language, account.email, { ...account, resetPasswordLink }); } catch (error) { throw error; } return { message: 'sent' }; } @Mutation(() => AccountModel) @Authorized('public') async registerGuest( @Arg('input') input: LinkEmailInput, @Arg('otherInfo') otherInfo: EditAccountInput, @Ctx() ctx: ApolloContext, ): Promise { const account = new AccountModel(); const result = await FirebaseAuth.getInstance().linkWithEmailPassword(input); return editOneGeneric(account, result.localId, { ...otherInfo, email: result.email, types: [AccountTypeEnum.user] }, ctx); } }