sinProject-Inc/talk

View on GitHub
src/lib/auth/sign_in_log_repository_prisma.ts

Summary

Maintainability
C
1 day
Test Coverage
import { AppSettingRepositoryPrisma } from '$lib/app/app_setting_repository_prisma'
import { SettingKey } from '$lib/app/setting_key'
import type { PrismaClient, SignInLog } from '@prisma/client'
import type { Email } from './email'
import type { IPAddress } from './ip_address'
import type { SignInLogRepository } from './sign_in_log_repository'

export class SignInLogRepositoryPrisma implements SignInLogRepository {
    public constructor(private readonly _prisma_client: PrismaClient) {}

    private async _consecutive_fail_by_ip_address(
        ip_address: IPAddress,
        period_sec: number,
        count: number
    ): Promise<boolean> {
        const result = await this._prisma_client.signInLog.findMany({
            where: {
                created_at: { gte: new Date(Date.now() - period_sec * 1000) },
                ip_address: ip_address.address,
            },
            orderBy: { created_at: 'desc' },
            take: count,
        })

        const consecutive_fail = result.filter((log) => !log.success).length >= count

        return consecutive_fail
    }

    private async _consecutive_fail_by_email(
        email: Email,
        period_sec: number,
        count: number
    ): Promise<boolean> {
        const result = await this._prisma_client.signInLog.findMany({
            where: {
                created_at: { gte: new Date(Date.now() - period_sec * 1000) },
                account: email.address,
            },
            orderBy: { created_at: 'desc' },
            take: count,
        })

        const consecutive_fail = result.filter((log) => !log.success).length >= count

        return consecutive_fail
    }

    public async consecutive_fail(ip_address: IPAddress, email: Email): Promise<boolean> {
        const app_setting_repository = new AppSettingRepositoryPrisma(this._prisma_client)
        const consecutive_fail_period_sec = await app_setting_repository.get_number(
            SettingKey.consecutive_fail_period_sec
        )
        const consecutive_fail_count = await app_setting_repository.get_number(
            SettingKey.consecutive_fail_count
        )

        const consecutive_fail_by_ip_address = await this._consecutive_fail_by_ip_address(
            ip_address,
            consecutive_fail_period_sec,
            consecutive_fail_count
        )
        const consecutive_fail_by_email = await this._consecutive_fail_by_email(
            email,
            consecutive_fail_period_sec,
            consecutive_fail_count
        )

        return consecutive_fail_by_ip_address || consecutive_fail_by_email
    }

    public async save(ip_address: IPAddress, email: Email, success: boolean): Promise<SignInLog> {
        const sign_in_log = await this._prisma_client.signInLog.create({
            data: {
                ip_address: ip_address.address,
                account: email.address,
                success,
            },
        })

        return sign_in_log
    }
}