diff --git a/src/modules/domains/domains.controller.ts b/src/modules/domains/domains.controller.ts index c1f769af9..93f0ead3c 100644 --- a/src/modules/domains/domains.controller.ts +++ b/src/modules/domains/domains.controller.ts @@ -27,6 +27,7 @@ import { DomainsService } from './domains.service'; export class DomainController { constructor(private domainsService: DomainsService) {} + /** Create a new domain for a group */ @Post() @AuditLog('create-domain') @Scopes('group-{groupId}:write-domain-*') @@ -37,6 +38,7 @@ export class DomainController { return this.domainsService.createDomain(groupId, data); } + /** Get domains for a group */ @Get() @Scopes('group-{groupId}:read-domain-*') async getAll( @@ -56,15 +58,17 @@ export class DomainController { }); } + /** Read a domain for a group */ @Get(':id') @Scopes('group-{groupId}:read-domain-{id}') async get( @Param('groupId', ParseIntPipe) groupId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.domainsService.getDomain(groupId, Number(id)); + return this.domainsService.getDomain(groupId, id); } + /** Delete a domain for a group */ @Delete(':id') @AuditLog('delete-domain') @Scopes('group-{groupId}:delete-domain-{id}') @@ -72,9 +76,10 @@ export class DomainController { @Param('groupId', ParseIntPipe) groupId: number, @Param('id', ParseIntPipe) id: number, ): Promise> { - return this.domainsService.deleteDomain(groupId, Number(id)); + return this.domainsService.deleteDomain(groupId, id); } + /** Verify a domain using TXT record */ @Post(':id/verify/txt') @AuditLog('verify-domain-txt') @Scopes('group-{groupId}:write-domain-{id}') @@ -84,11 +89,12 @@ export class DomainController { ): Promise> { return this.domainsService.verifyDomain( groupId, - Number(id), + id, DOMAIN_VERIFICATION_TXT, ); } + /** Verify a domain using HTML file upload */ @Post(':id/verify/html') @AuditLog('verify-domain-html') @Scopes('group-{groupId}:write-domain-{id}') @@ -98,7 +104,7 @@ export class DomainController { ): Promise> { return this.domainsService.verifyDomain( groupId, - Number(id), + id, DOMAIN_VERIFICATION_HTML, ); } diff --git a/src/modules/domains/domains.module.ts b/src/modules/domains/domains.module.ts index 6f6897722..18e3332c6 100644 --- a/src/modules/domains/domains.module.ts +++ b/src/modules/domains/domains.module.ts @@ -10,5 +10,6 @@ import { DomainsService } from './domains.service'; imports: [PrismaModule, TokensModule, DnsModule, ConfigModule], controllers: [DomainController], providers: [DomainsService], + exports: [DomainsService], }) export class DomainsModule {} diff --git a/src/modules/domains/domains.service.ts b/src/modules/domains/domains.service.ts index af27a0a4a..711d2e388 100644 --- a/src/modules/domains/domains.service.ts +++ b/src/modules/domains/domains.service.ts @@ -8,7 +8,6 @@ import { ConfigService } from '@nestjs/config'; import type { Prisma } from '@prisma/client'; import { Domain } from '@prisma/client'; import got from 'got'; -import { Configuration } from '../../config/configuration.interface'; import { URL } from 'url'; import { DOMAIN_NOT_FOUND, @@ -20,7 +19,10 @@ import { DnsService } from '../../providers/dns/dns.service'; import { Expose } from '../../providers/prisma/prisma.interface'; import { PrismaService } from '../../providers/prisma/prisma.service'; import { TokensService } from '../../providers/tokens/tokens.service'; -import { DOMAIN_VERIFICATION_TXT } from './domains.constants'; +import { + DOMAIN_VERIFICATION_HTML, + DOMAIN_VERIFICATION_TXT, +} from './domains.constants'; import { DomainVerificationMethods } from './domains.interface'; @Injectable() @@ -46,7 +48,7 @@ export class DomainsService { ) ) throw new BadRequestException(INVALID_DOMAIN); - const verificationCode = this.tokensService.generateUuid(); + const verificationCode = await this.tokensService.generateRandomString(); const currentProfilePicture = await this.prisma.group.findUnique({ where: { id: groupId }, select: { profilePictureUrl: true }, @@ -88,14 +90,18 @@ export class DomainsService { }, ): Promise[]> { const { skip, take, cursor, where, orderBy } = params; - const domains = await this.prisma.domain.findMany({ - skip, - take, - cursor, - where: { ...where, group: { id: groupId } }, - orderBy, - }); - return domains.map((group) => this.prisma.expose(group)); + try { + const domains = await this.prisma.domain.findMany({ + skip, + take, + cursor, + where: { ...where, group: { id: groupId } }, + orderBy, + }); + return domains.map((group) => this.prisma.expose(group)); + } catch (error) { + return []; + } } async getDomain(groupId: number, id: number): Promise> { @@ -111,7 +117,7 @@ export class DomainsService { async verifyDomain( groupId: number, id: number, - method: DomainVerificationMethods, + method?: DomainVerificationMethods, ): Promise> { const domain = await this.prisma.domain.findUnique({ where: { id }, @@ -119,21 +125,24 @@ export class DomainsService { if (!domain) throw new NotFoundException(DOMAIN_NOT_FOUND); if (domain.groupId !== groupId) throw new UnauthorizedException(UNAUTHORIZED_RESOURCE); - if (method === DOMAIN_VERIFICATION_TXT) { + + if (method === DOMAIN_VERIFICATION_TXT || !method) { const txtRecords = await this.dnsService.lookup(domain.domain, 'TXT'); if (JSON.stringify(txtRecords).includes(domain.verificationCode)) { await this.prisma.domain.update({ where: { id }, data: { isVerified: true }, }); - } else throw new BadRequestException(DOMAIN_NOT_VERIFIED); - } else { + } else if (method) throw new BadRequestException(DOMAIN_NOT_VERIFIED); + } + + if (method === DOMAIN_VERIFICATION_HTML || !method) { let verified = false; try { const { body } = await got( - `http://${domain.domain}/.well-known/${this.configService.get< - Configuration['meta']['domainVerificationFile'] - >('meta.domainVerificationFile' ?? 'staart-verify.txt')}`, + `http://${domain.domain}/.well-known/${this.configService.get( + 'meta.domainVerificationFile' ?? 'staart-verify.txt', + )}`, ); verified = body.includes(domain.verificationCode); } catch (error) {} @@ -142,7 +151,7 @@ export class DomainsService { where: { id }, data: { isVerified: true }, }); - } else throw new BadRequestException(DOMAIN_NOT_VERIFIED); + } else if (method) throw new BadRequestException(DOMAIN_NOT_VERIFIED); } return domain; }