mirror of
https://github.com/docmost/docmost.git
synced 2025-11-18 19:41:26 +10:00
fix: enforce SSO in invitation signups (#1258)
This commit is contained in:
@ -6,3 +6,16 @@ export function validateSsoEnforcement(workspace: Workspace) {
|
||||
throw new BadRequestException('This workspace has enforced SSO login.');
|
||||
}
|
||||
}
|
||||
|
||||
export function validateAllowedEmail(userEmail: string, workspace: Workspace) {
|
||||
const emailParts = userEmail.split('@');
|
||||
const emailDomain = emailParts[1].toLowerCase();
|
||||
if (
|
||||
workspace.emailDomains?.length > 0 &&
|
||||
!workspace.emailDomains.includes(emailDomain)
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`The email domain "${emailDomain}" is not approved for this workspace.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,10 +180,13 @@ export class WorkspaceController {
|
||||
@Public()
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('invites/info')
|
||||
async getInvitationById(@Body() dto: InvitationIdDto, @Req() req: any) {
|
||||
async getInvitationById(
|
||||
@Body() dto: InvitationIdDto,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return this.workspaceInvitationService.getInvitationById(
|
||||
dto.invitationId,
|
||||
req.raw.workspaceId,
|
||||
workspace,
|
||||
);
|
||||
}
|
||||
|
||||
@ -253,12 +256,12 @@ export class WorkspaceController {
|
||||
@Post('invites/accept')
|
||||
async acceptInvite(
|
||||
@Body() acceptInviteDto: AcceptInviteDto,
|
||||
@Req() req: any,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
@Res({ passthrough: true }) res: FastifyReply,
|
||||
) {
|
||||
const authToken = await this.workspaceInvitationService.acceptInvitation(
|
||||
acceptInviteDto,
|
||||
req.raw.workspaceId,
|
||||
workspace,
|
||||
);
|
||||
|
||||
res.setCookie('authToken', authToken, {
|
||||
|
||||
@ -28,6 +28,10 @@ import { InjectQueue } from '@nestjs/bullmq';
|
||||
import { QueueJob, QueueName } from '../../../integrations/queue/constants';
|
||||
import { Queue } from 'bullmq';
|
||||
import { EnvironmentService } from '../../../integrations/environment/environment.service';
|
||||
import {
|
||||
validateAllowedEmail,
|
||||
validateSsoEnforcement,
|
||||
} from '../../auth/auth.util';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceInvitationService {
|
||||
@ -63,19 +67,19 @@ export class WorkspaceInvitationService {
|
||||
return result;
|
||||
}
|
||||
|
||||
async getInvitationById(invitationId: string, workspaceId: string) {
|
||||
async getInvitationById(invitationId: string, workspace: Workspace) {
|
||||
const invitation = await this.db
|
||||
.selectFrom('workspaceInvitations')
|
||||
.select(['id', 'email', 'createdAt'])
|
||||
.where('id', '=', invitationId)
|
||||
.where('workspaceId', '=', workspaceId)
|
||||
.where('workspaceId', '=', workspace.id)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!invitation) {
|
||||
throw new NotFoundException('Invitation not found');
|
||||
}
|
||||
|
||||
return invitation;
|
||||
return { ...invitation, enforceSso: workspace.enforceSso };
|
||||
}
|
||||
|
||||
async getInvitationTokenById(invitationId: string, workspaceId: string) {
|
||||
@ -169,12 +173,12 @@ export class WorkspaceInvitationService {
|
||||
}
|
||||
}
|
||||
|
||||
async acceptInvitation(dto: AcceptInviteDto, workspaceId: string) {
|
||||
async acceptInvitation(dto: AcceptInviteDto, workspace: Workspace) {
|
||||
const invitation = await this.db
|
||||
.selectFrom('workspaceInvitations')
|
||||
.selectAll()
|
||||
.where('id', '=', dto.invitationId)
|
||||
.where('workspaceId', '=', workspaceId)
|
||||
.where('workspaceId', '=', workspace.id)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!invitation) {
|
||||
@ -185,6 +189,9 @@ export class WorkspaceInvitationService {
|
||||
throw new BadRequestException('Invalid invitation token');
|
||||
}
|
||||
|
||||
validateSsoEnforcement(workspace);
|
||||
validateAllowedEmail(invitation.email, workspace);
|
||||
|
||||
let newUser: User;
|
||||
|
||||
try {
|
||||
@ -197,7 +204,7 @@ export class WorkspaceInvitationService {
|
||||
password: dto.password,
|
||||
role: invitation.role,
|
||||
invitedById: invitation.invitedById,
|
||||
workspaceId: workspaceId,
|
||||
workspaceId: workspace.id,
|
||||
},
|
||||
trx,
|
||||
);
|
||||
@ -205,7 +212,7 @@ export class WorkspaceInvitationService {
|
||||
// add user to default group
|
||||
await this.groupUserRepo.addUserToDefaultGroup(
|
||||
newUser.id,
|
||||
workspaceId,
|
||||
workspace.id,
|
||||
trx,
|
||||
);
|
||||
|
||||
@ -215,7 +222,7 @@ export class WorkspaceInvitationService {
|
||||
.selectFrom('groups')
|
||||
.select(['id', 'name'])
|
||||
.where('groups.id', 'in', invitation.groupIds)
|
||||
.where('groups.workspaceId', '=', workspaceId)
|
||||
.where('groups.workspaceId', '=', workspace.id)
|
||||
.execute();
|
||||
|
||||
if (validGroups && validGroups.length > 0) {
|
||||
@ -256,7 +263,7 @@ export class WorkspaceInvitationService {
|
||||
// notify the inviter
|
||||
const invitedByUser = await this.userRepo.findById(
|
||||
invitation.invitedById,
|
||||
workspaceId,
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
if (invitedByUser) {
|
||||
@ -273,7 +280,9 @@ export class WorkspaceInvitationService {
|
||||
}
|
||||
|
||||
if (this.environmentService.isCloud()) {
|
||||
await this.billingQueue.add(QueueJob.STRIPE_SEATS_SYNC, { workspaceId });
|
||||
await this.billingQueue.add(QueueJob.STRIPE_SEATS_SYNC, {
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
return this.tokenService.generateAccessToken(newUser);
|
||||
|
||||
Submodule apps/server/src/ee updated: 70eb45eaec...4d1b0a17d3
Reference in New Issue
Block a user