mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
feat(api): defer registration phone verification to community joins (#1709)
This commit is contained in:
1 parent
7e1ca9ed6a
commit
d7b2e67c35
39 files changed
+1000
-32
No files matched your search
@@ -2,7 +2,15 @@
|
||||
|
||||
import {AdminACLs} from '@fluxer/constants/src/AdminACLs';
|
||||
import {APIErrorCodes} from '@fluxer/constants/src/ApiErrorCodes';
|
||||
import {SuspiciousActivityFlags, UserFlags} from '@fluxer/constants/src/UserConstants';
|
||||
import {
|
||||
ADMIN_PHONE_TOGGLE_CLEARABLE_FLAGS,
|
||||
ALL_SUSPICIOUS_ACTIVITY_FLAGS,
|
||||
DEFERRABLE_PHONE_FLAGS,
|
||||
DEFERRED_PHONE_ON_COMMUNITY_JOIN,
|
||||
imposePhoneRequirements,
|
||||
SuspiciousActivityFlags,
|
||||
UserFlags,
|
||||
} from '@fluxer/constants/src/UserConstants';
|
||||
import {ValidationErrorCodes} from '@fluxer/constants/src/ValidationErrorCodes';
|
||||
import {AccessDeniedError} from '@fluxer/errors/src/domains/core/AccessDeniedError';
|
||||
import {InputValidationError} from '@fluxer/errors/src/domains/core/InputValidationError';
|
||||
@@ -31,6 +39,7 @@ import * as AuthMfa from '../../auth/AuthMfa';
|
||||
import * as AuthSession from '../../auth/AuthSession';
|
||||
import * as AuthUtility from '../../auth/AuthUtility';
|
||||
import {createPasswordResetToken, createUserID, type UserID} from '../../BrandedTypes';
|
||||
import type {UserRow} from '../../database/types/UserTypes';
|
||||
import {Logger} from '../../Logger';
|
||||
import type {IRiskHistoryRepository} from '../../risk/HistoricalOutcomeRepository';
|
||||
import type {HistoricalOutcomeCode} from '../../risk/RiskHistoryTypes';
|
||||
@@ -406,11 +415,14 @@ export class AdminUserSecurityService {
|
||||
if (!user) {
|
||||
throw new UnknownUserError();
|
||||
}
|
||||
const updatedUser = await userRepository.patchUpsert(
|
||||
userId,
|
||||
{has_verified_phone: data.has_verified_phone},
|
||||
user.toRow(),
|
||||
);
|
||||
const phonePatch: Partial<UserRow> = {has_verified_phone: data.has_verified_phone};
|
||||
if (data.has_verified_phone) {
|
||||
const clearedFlags = (user.suspiciousActivityFlags ?? 0) & ~ADMIN_PHONE_TOGGLE_CLEARABLE_FLAGS;
|
||||
if (clearedFlags !== (user.suspiciousActivityFlags ?? 0)) {
|
||||
phonePatch.suspicious_activity_flags = clearedFlags;
|
||||
}
|
||||
}
|
||||
const updatedUser = await userRepository.patchUpsert(userId, phonePatch, user.toRow());
|
||||
await updatePropagator.propagateUserUpdate({userId, oldUser: user, updatedUser});
|
||||
await auditService.createAuditLog({
|
||||
adminUserId,
|
||||
@@ -418,7 +430,15 @@ export class AdminUserSecurityService {
|
||||
targetId: BigInt(userId),
|
||||
action: 'update_has_verified_phone',
|
||||
auditLogReason,
|
||||
metadata: new Map([['has_verified_phone', String(data.has_verified_phone)]]),
|
||||
metadata: new Map(
|
||||
phonePatch.suspicious_activity_flags === undefined
|
||||
? [['has_verified_phone', String(data.has_verified_phone)]]
|
||||
: [
|
||||
['has_verified_phone', String(data.has_verified_phone)],
|
||||
['suspicious_activity_flags_before', String(user.suspiciousActivityFlags ?? 0)],
|
||||
['suspicious_activity_flags_after', String(phonePatch.suspicious_activity_flags)],
|
||||
],
|
||||
),
|
||||
});
|
||||
return {
|
||||
user: await mapUserToAdminResponse(updatedUser, cacheService, acls),
|
||||
@@ -438,15 +458,24 @@ export class AdminUserSecurityService {
|
||||
if (!user) {
|
||||
throw new UnknownUserError();
|
||||
}
|
||||
const currentFlags = user.suspiciousActivityFlags ?? 0;
|
||||
const keepsDeferral =
|
||||
(currentFlags & DEFERRED_PHONE_ON_COMMUNITY_JOIN) !== 0 &&
|
||||
(data.flags & DEFERRABLE_PHONE_FLAGS) !== 0 &&
|
||||
(data.flags & DEFERRABLE_PHONE_FLAGS) === (currentFlags & DEFERRABLE_PHONE_FLAGS);
|
||||
const newFlags = keepsDeferral ? data.flags | DEFERRED_PHONE_ON_COMMUNITY_JOIN : data.flags;
|
||||
const updatedUser = await userRepository.patchUpsert(
|
||||
userId,
|
||||
{
|
||||
suspicious_activity_flags: data.flags,
|
||||
suspicious_activity_flags: newFlags,
|
||||
},
|
||||
user.toRow(),
|
||||
);
|
||||
await updatePropagator.propagateUserUpdate({userId, oldUser: user, updatedUser: updatedUser});
|
||||
if ((user.suspiciousActivityFlags ?? 0) !== data.flags && data.flags !== 0) {
|
||||
if (
|
||||
(currentFlags & ALL_SUSPICIOUS_ACTIVITY_FLAGS) !== (newFlags & ALL_SUSPICIOUS_ACTIVITY_FLAGS) &&
|
||||
(newFlags & ALL_SUSPICIOUS_ACTIVITY_FLAGS) !== 0
|
||||
) {
|
||||
await this.recordRiskOutcomes(userId, ['challenged'], 'admin_update_suspicious_activity_flags');
|
||||
}
|
||||
await auditService.createAuditLog({
|
||||
@@ -600,7 +629,7 @@ export class AdminUserSecurityService {
|
||||
throw new UnknownUserError();
|
||||
}
|
||||
const currentFlags = user.suspiciousActivityFlags ?? 0;
|
||||
const newFlags = (currentFlags | addMask) & ~removeMask;
|
||||
const newFlags = imposePhoneRequirements(currentFlags, addMask) & ~removeMask;
|
||||
const updatedUser = await userRepository.patchUpsert(
|
||||
userId,
|
||||
{suspicious_activity_flags: newFlags},
|
||||
|
||||
@@ -43,6 +43,7 @@ export class AdminGuildMembershipService {
|
||||
throw new UnknownUserError();
|
||||
}
|
||||
await guildService.members.addUserToGuild({
|
||||
skipRiskGate: true,
|
||||
userId,
|
||||
guildId,
|
||||
sendJoinMessage: true,
|
||||
@@ -83,6 +84,7 @@ export class AdminGuildMembershipService {
|
||||
try {
|
||||
const userId = createUserID(userIdBigInt);
|
||||
await guildService.members.addUserToGuild({
|
||||
skipRiskGate: true,
|
||||
userId,
|
||||
guildId,
|
||||
sendJoinMessage: false,
|
||||
|
||||
Reference in new issue
Block a user