mirror of
https://github.com/docmost/docmost.git
synced 2026-05-15 21:24:09 +08:00
feat(EE): MFA implementation (#1381)
* feat(EE): MFA implementation for enterprise edition - Add TOTP-based two-factor authentication - Add backup codes support - Add MFA enforcement at workspace level - Add MFA setup and challenge UI pages - Support MFA for login and password reset flows - Add MFA validation for secure pages * fix types * remove unused object * sync * remove unused type * sync * refactor: rename MFA enabled field to is_enabled * sync
This commit is contained in:
@@ -29,7 +29,8 @@ import WorkspaceAbilityFactory from '../../casl/abilities/workspace-ability.fact
|
||||
import {
|
||||
WorkspaceCaslAction,
|
||||
WorkspaceCaslSubject,
|
||||
} from '../../casl/interfaces/workspace-ability.type';import { FastifyReply } from 'fastify';
|
||||
} from '../../casl/interfaces/workspace-ability.type';
|
||||
import { FastifyReply } from 'fastify';
|
||||
import { EnvironmentService } from '../../../integrations/environment/environment.service';
|
||||
import { CheckHostnameDto } from '../dto/check-hostname.dto';
|
||||
import { RemoveWorkspaceUserDto } from '../dto/remove-workspace-user.dto';
|
||||
@@ -257,17 +258,27 @@ export class WorkspaceController {
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
@Res({ passthrough: true }) res: FastifyReply,
|
||||
) {
|
||||
const authToken = await this.workspaceInvitationService.acceptInvitation(
|
||||
const result = await this.workspaceInvitationService.acceptInvitation(
|
||||
acceptInviteDto,
|
||||
workspace,
|
||||
);
|
||||
|
||||
res.setCookie('authToken', authToken, {
|
||||
if (result.requiresLogin) {
|
||||
return {
|
||||
requiresLogin: true,
|
||||
};
|
||||
}
|
||||
|
||||
res.setCookie('authToken', result.authToken, {
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
expires: this.environmentService.getCookieExpiresIn(),
|
||||
secure: this.environmentService.isHttps(),
|
||||
});
|
||||
|
||||
return {
|
||||
requiresLogin: false,
|
||||
};
|
||||
}
|
||||
|
||||
@Public()
|
||||
|
||||
@@ -14,4 +14,8 @@ export class UpdateWorkspaceDto extends PartialType(CreateWorkspaceDto) {
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
enforceSso: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
enforceMfa: boolean;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,14 @@ export class WorkspaceInvitationService {
|
||||
}
|
||||
}
|
||||
|
||||
async acceptInvitation(dto: AcceptInviteDto, workspace: Workspace) {
|
||||
async acceptInvitation(
|
||||
dto: AcceptInviteDto,
|
||||
workspace: Workspace,
|
||||
): Promise<{
|
||||
authToken?: string;
|
||||
requiresLogin?: boolean;
|
||||
message?: string;
|
||||
}> {
|
||||
const invitation = await this.db
|
||||
.selectFrom('workspaceInvitations')
|
||||
.selectAll()
|
||||
@@ -289,7 +296,14 @@ export class WorkspaceInvitationService {
|
||||
});
|
||||
}
|
||||
|
||||
return this.tokenService.generateAccessToken(newUser);
|
||||
if (workspace.enforceMfa) {
|
||||
return {
|
||||
requiresLogin: true,
|
||||
};
|
||||
}
|
||||
|
||||
const authToken = await this.tokenService.generateAccessToken(newUser);
|
||||
return { authToken };
|
||||
}
|
||||
|
||||
async resendInvitation(
|
||||
|
||||
Reference in New Issue
Block a user