backend/services/module-accounts/account.resolver.ts
2025-05-14 21:45:16 +02:00

172 lines
7.9 KiB
TypeScript

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<AccountModel> {
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<FirebaseTokenResult> {
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<SimpleResult> {
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<AccountModel> {
// const model = new AccountModel();
// return signinGeneric(model, AccountTypeEnum.user, input, ctx);
// }
@Mutation(() => AccountModel)
@Authorized()
async updateMe(@Arg('input') input: EditAccountInput, @Ctx() ctx: ApolloContext): Promise<AccountModel> {
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<AccountModel> {
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<AccountModel> {
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<SimpleResult> {
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<AccountModel> {
const account = new AccountModel();
const result = await FirebaseAuth.getInstance().linkWithEmailPassword(input);
return editOneGeneric(account, result.localId, { ...otherInfo, email: result.email, types: [AccountTypeEnum.user] }, ctx);
}
}