backend/src/tokens/tokens.service.ts   A
last analyzed

Complexity

Total Complexity 10
Complexity/F 2.5

Size

Lines of Code 75
Function Count 4

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 96.88%

Importance

Changes 0
Metric Value
eloc 59
dl 0
loc 75
ccs 31
cts 32
cp 0.9688
rs 10
c 0
b 0
f 0
wmc 10
mnd 6
bc 6
fnc 4
bpm 1.5
cpm 2.5
noi 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
A TokensService.revokeAllForUser 0 3 1
A TokensService.findOne 0 7 2
A TokensService.consume 0 18 4
A TokensService.create 0 27 3
1 11
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
2 11
import { InjectRepository } from '@nestjs/typeorm';
3 11
import { Repository } from 'typeorm';
4 11
import { Token } from './entities/token.entity/token.entity';
5
6 11
const DEFAULT_MAX_USES = 10;
7 11
const DEFAULT_EXPIRATION_HOURS = 24;
8
9
@Injectable()
10 11
export class TokensService {
11
  constructor(
12
    @InjectRepository(Token)
13 14
    private readonly tokenRepository: Repository<Token>,
14
  ) {}
15
16
  async create(userId: string): Promise<Token> {
17 2
    const existingTokens = await this.tokenRepository.find({
18
      where: { customerId: userId },
19
    });
20 5
    const existingTokensRemainingUses = existingTokens.filter((token) => token.remainingUses > 0);
21
22 3
    if (existingTokens.length >= 5 && existingTokensRemainingUses.length > 0) {
23 1
      throw new BadRequestException(
24
        'Maximum number of tokens reached. Please consume an existing token before creating a new one.',
25
      );
26
    }
27
28 1
    if (existingTokens.length >= 5) {
29
      throw new BadRequestException('Maximum number of tokens reached');
30
    }
31
32 1
    const expiresAt = new Date();
33 1
    expiresAt.setHours(expiresAt.getHours() + DEFAULT_EXPIRATION_HOURS);
34 1
    const token = this.tokenRepository.create({
35
      customerId: userId,
36
      remainingUses: DEFAULT_MAX_USES,
37
      maxUses: DEFAULT_MAX_USES,
38
      expiresAt: expiresAt,
39
    });
40
41 1
    return this.tokenRepository.save(token);
42
  }
43
44
  async consume(id: string): Promise<Token> {
45 4
    const token = await this.tokenRepository.findOne({ where: { id } });
46
47 4
    if (!token) {
48 1
      throw new NotFoundException('Token not found');
49
    }
50
51 3
    if (token.remainingUses <= 0) {
52 1
      throw new BadRequestException('Token has no remaining uses');
53
    }
54
55 3
    if (token.expiresAt && token.expiresAt < new Date()) {
56 1
      throw new BadRequestException('Token has expired');
57
    }
58
59 1
    token.remainingUses--;
60 1
    return this.tokenRepository.save(token);
61
  }
62
63
  async findOne(id: string): Promise<Token> {
64 2
    const token = await this.tokenRepository.findOne({ where: { id } });
65 2
    if (!token) {
66 1
      throw new NotFoundException('Token not found');
67
    }
68 1
    return token;
69
  }
70
71
  revokeAllForUser(githubId: any) {
72 1
    return this.tokenRepository.delete({ customerId: githubId });
73
  }
74
}
75