Log IP addresses used during registration

Closes #836
This commit is contained in:
наб 2025-07-13 06:15:45 +02:00
parent 5dd32123a3
commit 132c25b271
No known key found for this signature in database
GPG key ID: BCFD0B018D2658F1
3 changed files with 54 additions and 1 deletions

View file

@ -37,4 +37,10 @@ export class MiUserPending {
nullable: true,
})
public reason: string;
@Column('varchar', {
length: 128,
nullable: true,
})
public requestOriginIp: string | null;
}

View file

@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import * as argon2 from 'argon2';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket, MiMeta } from '@/models/_.js';
import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository, MiRegistrationTicket, MiMeta, UserIpsRepository } from '@/models/_.js';
import type { Config } from '@/config.js';
import { CaptchaService } from '@/core/CaptchaService.js';
import { IdService } from '@/core/IdService.js';
@ -46,6 +46,9 @@ export class SignupApiService {
@Inject(DI.registrationTicketsRepository)
private registrationTicketsRepository: RegistrationTicketsRepository,
@Inject(DI.userIpsRepository)
private userIpsRepository: UserIpsRepository,
private userEntityService: UserEntityService,
private idService: IdService,
private captchaService: CaptchaService,
@ -213,6 +216,7 @@ export class SignupApiService {
username: username,
password: hash,
reason: reason,
requestOriginIp: this.meta.enableIpLogging ? request.ip : null,
});
const link = `${this.config.url}/signup-complete/${code}`;
@ -249,6 +253,10 @@ export class SignupApiService {
});
}
if (this.meta.enableIpLogging) {
this.logIp(request.ip, null, account.id);
}
const moderators = await this.roleService.getModerators();
for (const moderator of moderators) {
@ -282,6 +290,10 @@ export class SignupApiService {
});
}
if (this.meta.enableIpLogging) {
this.logIp(request.ip, null, account.id);
}
return {
...res,
token: secret,
@ -332,6 +344,15 @@ export class SignupApiService {
});
}
if (pendingUser.requestOriginIp) {
this.logIp(pendingUser.requestOriginIp, this.idService.parse(pendingUser.id).date, account.id);
}
// The sign-up request and the confirmation may've come from different addresses: log both
if (this.meta.enableIpLogging) {
this.logIp(request.ip, null, account.id);
}
if (this.meta.approvalRequiredForSignup) {
if (pendingUser.email) {
this.emailService.sendEmail(pendingUser.email, 'Approval pending',
@ -359,4 +380,16 @@ export class SignupApiService {
throw new FastifyReplyError(400, String(err), err);
}
}
@bindThis
private logIp(ip: string, ipDate: Date | null, userId: MiLocalUser['id']) {
try {
this.userIpsRepository.createQueryBuilder().insert().values({
createdAt: ipDate ?? new Date(),
userId,
ip,
}).orIgnore(true).execute();
} catch {
}
}
}