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

Commit 2c892e8

Browse files
✨ Add approve subnet endpoint
1 parent 24afea0 commit 2c892e8

3 files changed

Lines changed: 41 additions & 10 deletions

File tree

src/modules/auth/auth.controller.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
TotpLoginDto,
1212
VerifyEmailDto,
1313
} from './auth.dto';
14+
import { TokenResponse } from './auth.interface';
1415
import { AuthService } from './auth.service';
1516
import { Public } from './public.decorator';
1617

@@ -29,7 +30,7 @@ export class AuthController {
2930
@Body() data: LoginDto,
3031
@Ip() ip: string,
3132
@Headers('User-Agent') userAgent: string,
32-
): Promise<{ accessToken: string }> {
33+
): Promise<TokenResponse> {
3334
return this.authService.login(
3435
ip,
3536
userAgent,
@@ -62,7 +63,7 @@ export class AuthController {
6263
@Ip() ip: string,
6364
@Headers('User-Agent') userAgent: string,
6465
@Body('token') refreshToken: string,
65-
): Promise<{ accessToken: string }> {
66+
): Promise<TokenResponse> {
6667
return this.authService.refresh(ip, userAgent, refreshToken);
6768
}
6869

@@ -76,6 +77,20 @@ export class AuthController {
7677
return this.authService.logout(refreshToken);
7778
}
7879

80+
@Post('approve-subnet')
81+
@RateLimit({
82+
points: 5,
83+
duration: 60,
84+
errorMessage: 'Wait for 60 seconds before trying to logout again',
85+
})
86+
async approveSubnet(
87+
@Ip() ip: string,
88+
@Headers('User-Agent') userAgent: string,
89+
@Body('token') token: string,
90+
): Promise<TokenResponse> {
91+
return this.authService.approveSubnet(ip, userAgent, token);
92+
}
93+
7994
@Post('resend-email-verification')
8095
@RateLimit({
8196
points: 1,
@@ -131,7 +146,7 @@ export class AuthController {
131146
@Body() data: TotpLoginDto,
132147
@Ip() ip: string,
133148
@Headers('User-Agent') userAgent: string,
134-
): Promise<{ accessToken: string }> {
149+
): Promise<TokenResponse> {
135150
return this.authService.loginWithTotp(ip, userAgent, data.token, data.code);
136151
}
137152
}

src/modules/auth/auth.interface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ export interface AccessTokenClaims {
66
scopes: string[];
77
}
88

9+
export interface TokenResponse {
10+
accessToken: string;
11+
refreshToken: string;
12+
}
13+
914
export interface AccessTokenParsed {
1015
id: number;
1116
scopes: string[];

src/modules/auth/auth.service.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@ import { JwtService } from '@nestjs/jwt';
1313
import { Authenticator } from '@otplib/core';
1414
import { emails, users } from '@prisma/client';
1515
import { compare, hash } from 'bcrypt';
16+
import anonymize from 'ip-anonymize';
1617
import { authenticator } from 'otplib';
1718
import qrcode from 'qrcode';
1819
import { safeEmail } from 'src/helpers/safe-email';
20+
import { ApprovedSubnetsService } from '../approved-subnets/approved-subnets.service';
1921
import { EmailService } from '../email/email.service';
22+
import { GeolocationService } from '../geolocation/geolocation.service';
2023
import { Expose } from '../prisma/prisma.interface';
2124
import { PrismaService } from '../prisma/prisma.service';
2225
import { PwnedService } from '../pwned/pwned.service';
2326
import {
27+
APPROVE_SUBNET_TOKEN,
2428
EMAIL_VERIFY_TOKEN,
2529
PASSWORD_RESET_TOKEN,
2630
TWO_FACTOR_TOKEN,
27-
APPROVE_SUBNET_TOKEN,
2831
} from '../tokens/tokens.constants';
2932
import { TokensService } from '../tokens/tokens.service';
3033
import { RegisterDto } from './auth.dto';
31-
import { AccessTokenClaims } from './auth.interface';
32-
import anonymize from 'ip-anonymize';
33-
import { GeolocationService } from '../geolocation/geolocation.service';
34-
import { ApprovedSubnetsService } from '../approved-subnets/approved-subnets.service';
34+
import { AccessTokenClaims, TokenResponse } from './auth.interface';
3535

3636
@Injectable()
3737
export class AuthService {
@@ -184,7 +184,11 @@ export class AuthService {
184184
return { queued: true };
185185
}
186186

187-
async refresh(ipAddress: string, userAgent: string, token: string) {
187+
async refresh(
188+
ipAddress: string,
189+
userAgent: string,
190+
token: string,
191+
): Promise<TokenResponse> {
188192
if (!token) throw new UnprocessableEntityException();
189193
const session = await this.prisma.sessions.findFirst({
190194
where: { token },
@@ -215,6 +219,13 @@ export class AuthService {
215219
});
216220
}
217221

222+
async approveSubnet(ipAddress: string, userAgent: string, token: string) {
223+
if (!token) throw new UnprocessableEntityException();
224+
const id = this.tokensService.verify<number>(APPROVE_SUBNET_TOKEN, token);
225+
await this.approvedSubnetsService.approveNewSubnet(id, ipAddress);
226+
return this.loginResponse(ipAddress, userAgent, id);
227+
}
228+
218229
/** Get the two-factor authentication QR code */
219230
async getTotpQrCode(userId: number) {
220231
const secret = randomStringGenerator();
@@ -359,7 +370,7 @@ export class AuthService {
359370
ipAddress: string,
360371
userAgent: string,
361372
id: number,
362-
) {
373+
): Promise<TokenResponse> {
363374
const token = randomStringGenerator();
364375
await this.prisma.sessions.create({
365376
data: { token, ipAddress, userAgent, user: { connect: { id } } },

0 commit comments

Comments
 (0)