Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
♻️ Use frontendUrl from meta config
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Dec 1, 2020
1 parent 91d388e commit f8eb9ca
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 61 deletions.
11 changes: 5 additions & 6 deletions src/config/configuration.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ import { ApiKeyAuth, BasicAuth } from '@elastic/elasticsearch/lib/pool';
import Stripe from 'stripe';

export interface Configuration {
/**
* Frontend URL (Staart UI or compatible app)
* Used for redirects and links in emails
*/
frontendUrl: string;

/** Project name and other metadata */
meta: {
/**
* Frontend URL (Staart UI or compatible app)
* Used for redirects and links in emails
*/
frontendUrl: string;
/**
* Title cased application name
* Used as the "Issuer" in MFA TOTP and in SMS OTPs
Expand Down
2 changes: 1 addition & 1 deletion src/config/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ const bool = (val: string | undefined, bool: boolean): boolean =>

/** Central configuration object */
const configuration: Configuration = {
frontendUrl: process.env.FRONTEND_URL ?? 'http://localhost:3000',
meta: {
frontendUrl: process.env.FRONTEND_URL ?? 'http://localhost:3000',
appName: process.env.APP_NAME ?? 'Staart',
domainVerificationFile:
process.env.DOMAIN_VERIFICATION_FILE ??
Expand Down
67 changes: 31 additions & 36 deletions src/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
Injectable,
NotFoundException,
UnauthorizedException,
UnprocessableEntityException,
UnprocessableEntityException
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Authenticator } from '@otplib/core';
Expand All @@ -18,6 +18,7 @@ import { authenticator } from 'otplib';
import qrcode from 'qrcode';
import randomColor from 'randomcolor';
import { UAParser } from 'ua-parser-js';
import { Configuration } from '../../config/configuration.interface';
import {
COMPROMISED_PASSWORD,
EMAIL_USER_CONFLICT,
Expand All @@ -33,7 +34,7 @@ import {
SESSION_NOT_FOUND,
UNVERIFIED_EMAIL,
UNVERIFIED_LOCATION,
USER_NOT_FOUND,
USER_NOT_FOUND
} from '../../errors/errors.constants';
import { safeEmail } from '../../helpers/safe-email';
import { GeolocationService } from '../../providers/geolocation/geolocation.service';
Expand All @@ -48,7 +49,7 @@ import {
LOGIN_ACCESS_TOKEN,
MERGE_ACCOUNTS_TOKEN,
MULTI_FACTOR_TOKEN,
PASSWORD_RESET_TOKEN,
PASSWORD_RESET_TOKEN
} from '../../providers/tokens/tokens.constants';
import { TokensService } from '../../providers/tokens/tokens.service';
import { TwilioService } from '../../providers/twilio/twilio.service';
Expand All @@ -58,12 +59,16 @@ import {
AccessTokenClaims,
MfaTokenPayload,
TokenResponse,
TotpTokenResponse,
TotpTokenResponse
} from './auth.interface';

@Injectable()
export class AuthService {
authenticator: Authenticator;
private authenticator: Authenticator;
private securityConfig = this.configService.get<Configuration['security']>(
'security',
);
private metaConfig = this.configService.get<Configuration['meta']>('meta');

constructor(
private prisma: PrismaService,
Expand All @@ -77,8 +82,8 @@ export class AuthService {
) {
this.authenticator = authenticator.create({
window: [
this.configService.get<number>('security.totpWindowPast') ?? 0,
this.configService.get<number>('security.totpWindowFuture') ?? 0,
this.securityConfig.totpWindowPast,
this.securityConfig.totpWindowFuture,
],
});
}
Expand Down Expand Up @@ -208,9 +213,9 @@ export class AuthService {
data: {
name: emailDetails.user.name,
days: 7,
link: `${this.configService.get<string>(
'frontendUrl',
)}/auth/link/verify-email?token=${this.tokensService.signJwt(
link: `${
this.metaConfig.frontendUrl
}/auth/link/verify-email?token=${this.tokensService.signJwt(
EMAIL_VERIFY_TOKEN,
{ id: emailDetails.id },
'7d',
Expand Down Expand Up @@ -352,9 +357,9 @@ export class AuthService {
data: {
name: emailDetails.user.name,
minutes: 30,
link: `${this.configService.get<string>(
'frontendUrl',
)}/auth/link/reset-password?token=${this.tokensService.signJwt(
link: `${
this.metaConfig.frontendUrl
}/auth/link/reset-password?token=${this.tokensService.signJwt(
PASSWORD_RESET_TOKEN,
{ id: emailDetails.user.id },
'30m',
Expand Down Expand Up @@ -423,9 +428,7 @@ export class AuthService {
data: {
name: result.user.name,
group: group.name,
link: `${this.configService.get<string>('frontendUrl')}/groups/${
group.id
}`,
link: `${this.metaConfig.frontendUrl}/groups/${group.id}`,
},
});
}
Expand Down Expand Up @@ -481,9 +484,7 @@ export class AuthService {
data: {
name: user.name,
locationName,
link: `${this.configService.get<string>(
'frontendUrl',
)}/users/${id}/sessions`,
link: `${this.metaConfig.frontendUrl}/users/${id}/sessions`,
},
});
}
Expand All @@ -496,13 +497,13 @@ export class AuthService {
private async getAccessToken(user: User): Promise<string> {
const scopes = await this.getScopes(user);
const payload: AccessTokenClaims = {
sub: `acct:${user.id}@${this.configService.get('security.issuerDomain')}`,
sub: `acct:${user.id}@${this.securityConfig.issuerDomain}`,
scopes,
};
return this.tokensService.signJwt(
LOGIN_ACCESS_TOKEN,
payload,
this.configService.get<string>('security.accessTokenExpiry'),
this.securityConfig.accessTokenExpiry,
);
}

Expand Down Expand Up @@ -564,9 +565,9 @@ export class AuthService {
minutes: parseInt(
this.configService.get<string>('security.mfaTokenExpiry') ?? '',
),
link: `${this.configService.get<string>(
'frontendUrl',
)}/auth/link/login%2Ftoken?token=${this.tokensService.signJwt(
link: `${
this.metaConfig.frontendUrl
}/auth/link/login%2Ftoken?token=${this.tokensService.signJwt(
EMAIL_MFA_TOKEN,
{ id: user.id },
'30m',
Expand Down Expand Up @@ -625,9 +626,9 @@ export class AuthService {
name: user.name,
locationName,
minutes: 30,
link: `${this.configService.get<string>(
'frontendUrl',
)}/auth/link/reset-password?token=${this.tokensService.signJwt(
link: `${
this.metaConfig.frontendUrl
}/auth/link/reset-password?token=${this.tokensService.signJwt(
APPROVE_SUBNET_TOKEN,
{ id },
'30m',
Expand All @@ -643,18 +644,12 @@ export class AuthService {
ignorePwnedPassword: boolean,
): Promise<string> {
if (!ignorePwnedPassword) {
if (!this.configService.get<boolean>('security.passwordPwnedCheck'))
return await hash(
password,
this.configService.get<number>('security.saltRounds') ?? 10,
);
if (!this.securityConfig.passwordPwnedCheck)
return await hash(password, this.securityConfig.saltRounds ?? 10);
if (!(await this.pwnedService.isPasswordSafe(password)))
throw new BadRequestException(COMPROMISED_PASSWORD);
}
return await hash(
password,
this.configService.get<number>('security.saltRounds') ?? 10,
);
return await hash(password, this.securityConfig.saltRounds ?? 10);
}

async getScopes(user: User): Promise<string[]> {
Expand Down
7 changes: 4 additions & 3 deletions src/modules/memberships/memberships.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ import { ApiKeysService } from '../api-keys/api-keys.service';
import { AuthService } from '../auth/auth.service';
import { GroupsService } from '../groups/groups.service';
import { CreateMembershipInput } from './memberships.interface';
import { Configuration } from '../../config/configuration.interface';

@Injectable()
export class MembershipsService {
private metaConfig = this.configService.get<Configuration['meta']>('meta');

constructor(
private prisma: PrismaService,
private auth: AuthService,
Expand Down Expand Up @@ -183,9 +186,7 @@ export class MembershipsService {
data: {
name: user.name,
group: result.group.name,
link: `${this.configService.get<string>(
'frontendUrl',
)}/groups/${groupId}`,
link: `${this.metaConfig.frontendUrl}/groups/${groupId}`,
},
});
return this.prisma.expose<Membership>(result);
Expand Down
14 changes: 5 additions & 9 deletions src/modules/stripe/stripe.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Stripe from 'stripe';
import { Configuration } from '../../config/configuration.interface';
import {
BILLING_ACCOUNT_CREATED_CONFLICT,
BILLING_NOT_FOUND,
Expand All @@ -22,6 +23,7 @@ import { PrismaService } from '../../providers/prisma/prisma.service';
export class StripeService {
stripe: Stripe;
logger = new Logger(StripeService.name);
private metaConfig = this.configService.get<Configuration['meta']>('meta');

constructor(
private configService: ConfigService,
Expand Down Expand Up @@ -83,9 +85,7 @@ export class StripeService {
const stripeId = await this.stripeId(groupId);
return this.stripe.billingPortal.sessions.create({
customer: stripeId,
return_url: `${this.configService.get<string>(
'frontendUrl',
)}/groups/${groupId}`,
return_url: `${this.metaConfig.frontendUrl}/groups/${groupId}`,
});
}

Expand Down Expand Up @@ -186,12 +186,8 @@ export class StripeService {
payment_method_types: this.configService.get<
Array<Stripe.Checkout.SessionCreateParams.PaymentMethodType>
>('payments.paymentMethodTypes') ?? ['card'],
success_url: `${this.configService.get<string>(
'frontendUrl',
)}/groups/${groupId}`,
cancel_url: `${this.configService.get<string>(
'frontendUrl',
)}/groups/${groupId}`,
success_url: `${this.metaConfig.frontendUrl}/groups/${groupId}`,
cancel_url: `${this.metaConfig.frontendUrl}/groups/${groupId}`,
};
if (mode === 'subscription')
data.line_items = [{ quantity: 1, price: planId }];
Expand Down
16 changes: 10 additions & 6 deletions src/modules/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ConfigService } from '@nestjs/config';
import type { Prisma } from '@prisma/client';
import { User } from '@prisma/client';
import { compare } from 'bcrypt';
import { Configuration } from '../../config/configuration.interface';
import {
CURRENT_PASSWORD_REQUIRED,
INVALID_CREDENTIALS,
Expand All @@ -23,6 +24,11 @@ import { PasswordUpdateInput } from './users.interface';

@Injectable()
export class UsersService {
private metaConfig = this.configService.get<Configuration['meta']>('meta');
private securityConfig = this.configService.get<Configuration['security']>(
'security',
);

constructor(
private prisma: PrismaService,
private auth: AuthService,
Expand Down Expand Up @@ -113,18 +119,16 @@ export class UsersService {
});
if (!user) throw new NotFoundException(USER_NOT_FOUND);
if (user.id === userId) throw new NotFoundException(USER_NOT_FOUND);
const minutes = parseInt(
this.configService.get<string>('security.mergeUsersTokenExpiry') ?? '',
);
const minutes = this.securityConfig.mergeUsersTokenExpiry;
this.email.send({
to: `"${user.name}" <${user.prefersEmail.email}>`,
template: 'auth/mfa-code',
data: {
name: user.name,
minutes,
link: `${this.configService.get<string>(
'frontendUrl',
)}/auth/link/merge-accounts?token=${this.tokensService.signJwt(
link: `${
this.metaConfig.frontendUrl
}/auth/link/merge-accounts?token=${this.tokensService.signJwt(
MERGE_ACCOUNTS_TOKEN,
{ baseUserId: userId, mergeUserId: user.id },
`${minutes}m`,
Expand Down

0 comments on commit f8eb9ca

Please sign in to comment.