UNPKG

@xrengine/server-core

Version:

Shared components for XREngine server

226 lines (201 loc) 6.07 kB
import { BadRequest } from '@feathersjs/errors' import { Id, NullableId, Params, ServiceMethods } from '@feathersjs/feathers' import appRootPath from 'app-root-path' import * as path from 'path' import * as pug from 'pug' import { Application } from '../../../declarations' import config from '../../appconfig' import Paginated from '../../types/PageObject' import { getLink, sendEmail, sendSms } from '../auth-management/auth-management.utils' import { IdentityProvider } from '../identity-provider/identity-provider.class' interface Data {} interface ServiceOptions {} const emailAccountTemplatesPath = path.join(appRootPath.path, 'packages', 'server-core', 'email-templates', 'account') export class Magiclink implements ServiceMethods<Data> { app: Application options: ServiceOptions docs: any constructor(options: ServiceOptions = {}, app: Application) { this.options = options this.app = app } async setup() {} /** * A function which find magic link and display it * * @param params * @returns {@Array} all magic link */ async find(params?: Params): Promise<Data[] | Paginated<Data>> { return [] } /** * A function which find specific magic link by id * * @param id of specific magic link * @param params * @returns {@Object} contains id of magic link and message */ async get(id: Id, params?: Params): Promise<Data> { return { id, text: `A new message with ID: ${id}!` } } /** * A function which is used to update magic link * * @param id * @param data which will be used for updating magic link * @param params * @returns updated data */ async update(id: NullableId, data: Data, params?: Params): Promise<Data> { return data } /** * A function which is used to update magic link * * @param id * @param data used to update * @param params * @returns data */ async patch(id: NullableId, data: Data, params?: Params): Promise<Data> { return data } /** * A function which is used to remove magic link * * @param id of magic link used to remove data * @param params * @returns id */ async remove(id: NullableId, params?: Params): Promise<Data> { return { id } } /** * A function used to sent an email * * @param toEmail email of reciever * @param token generated token * @param type of login * @param identityProvider of user * @param subscriptionId optional subscription ID * @returns {@function} sent email */ async sendEmail( toEmail: string, token: string, type: 'connection' | 'login', identityProvider: IdentityProvider, subscriptionId?: string ): Promise<void> { const hashLink = getLink(type, token, subscriptionId ?? '') let subscription let username if (subscriptionId != null) { subscription = await this.app.service('subscription' as any).find({ id: subscriptionId }) if (subscription.total === 0) { throw new BadRequest('Invalid subscription') } const subscriptionUser = await this.app.service('user').get(subscription.data[0].userId) username = subscriptionUser.name } const templatePath = subscriptionId == null ? path.join(emailAccountTemplatesPath, 'magiclink-email.pug') : path.join(emailAccountTemplatesPath, 'magiclink-email-subscription.pug') const compiledHTML = pug.compileFile(templatePath)({ logo: config.client.logo, title: config.client.title, hashLink, username: username }) const mailSender = config.email.from const email = { from: mailSender, to: toEmail, subject: config.email.subject.login, html: compiledHTML } return await sendEmail(this.app, email) } /** * A function which used to send sms * * @param mobile of receiver user * @param token generated token * @param type of login * @returns {@function} send sms */ async sendSms(mobile: string, token: string, type: 'connection' | 'login'): Promise<void> { const hashLink = getLink(type, token, '') const templatePath = path.join(emailAccountTemplatesPath, 'magiclink-sms.pug') const compiledHTML = pug .compileFile(templatePath)({ title: config.client.title, hashLink }) .replace(/&amp;/g, '&') // Text message links can't have HTML escaped ampersands. const sms = { mobile, text: compiledHTML } return await sendSms(this.app, sms) } /** * A function which is used to create magic link * * @param data used create magic link * @param params contain user info * @returns creted data */ async create(data: any, params?: Params): Promise<Data> { const identityProviderService = this.app.service('identity-provider') // check magiclink type let token = '' if (data.type === 'email') token = data.email else if (data.type === 'sms') token = data.mobile let identityProvider const identityProviders = ( (await identityProviderService.find({ query: { token: token, type: data.type } })) as any ).data if (identityProviders.length === 0) { identityProvider = await identityProviderService.create( { token: token, type: data.type, accountIdentifier: token }, params ) } else { identityProvider = identityProviders[0] } if (identityProvider) { const loginToken = await this.app.service('login-token').create({ identityProviderId: identityProvider.id }) if (data.type === 'email') { await this.sendEmail( data.email, loginToken.token, data.userId ? 'connection' : 'login', identityProvider, data.subscriptionId ) } else if (data.type === 'sms') { await this.sendSms(data.mobile, loginToken.token, data.userId ? 'connection' : 'login') } } return data } }