add office-aware passport policies and alert lifecycle
Enforce geofenced location evidence for passport challenges and extend admin alerting so mobile devices can review, dismiss, and act on real org and security events.
This commit is contained in:
@@ -14,6 +14,36 @@ export class UserInvitationManager {
|
||||
|
||||
public CUserInvitation = plugins.smartdata.setDefaultManagerForDoc(this, UserInvitation);
|
||||
|
||||
private async emitOrganizationAlert(optionsArg: {
|
||||
organizationId: string;
|
||||
eventType: string;
|
||||
severity: plugins.idpInterfaces.data.TAlertSeverity;
|
||||
title: string;
|
||||
body: string;
|
||||
actorUserId: string;
|
||||
relatedEntityId?: string;
|
||||
relatedEntityType?: string;
|
||||
}) {
|
||||
await this.receptionRef.alertManager.createAlertsForEvent({
|
||||
category: 'admin',
|
||||
organizationId: optionsArg.organizationId,
|
||||
eventType: optionsArg.eventType,
|
||||
severity: optionsArg.severity,
|
||||
title: optionsArg.title,
|
||||
body: optionsArg.body,
|
||||
actorUserId: optionsArg.actorUserId,
|
||||
relatedEntityId: optionsArg.relatedEntityId,
|
||||
relatedEntityType: optionsArg.relatedEntityType,
|
||||
});
|
||||
}
|
||||
|
||||
private async getOrganizationName(organizationIdArg: string) {
|
||||
const organization = await this.receptionRef.organizationmanager.COrganization.getInstance({
|
||||
id: organizationIdArg,
|
||||
});
|
||||
return organization?.data.name || 'this organization';
|
||||
}
|
||||
|
||||
constructor(receptionRefArg: Reception) {
|
||||
this.receptionRef = receptionRefArg;
|
||||
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
@@ -85,11 +115,24 @@ export class UserInvitationManager {
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
// Send invitation email
|
||||
await this.sendInvitationEmail(invitation, requestArg.organizationId);
|
||||
// Send invitation email
|
||||
await this.sendInvitationEmail(invitation, requestArg.organizationId);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
await this.emitOrganizationAlert({
|
||||
organizationId: requestArg.organizationId,
|
||||
eventType: 'org_invitation_created',
|
||||
severity: 'low',
|
||||
title: 'Organization invitation created',
|
||||
body: `${user.data.email} invited ${email} to ${await this.getOrganizationName(
|
||||
requestArg.organizationId
|
||||
)}.`,
|
||||
actorUserId: user.id,
|
||||
relatedEntityId: invitation.id,
|
||||
relatedEntityType: 'invitation',
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
invitation: await invitation.createSavableObject(),
|
||||
isNew,
|
||||
};
|
||||
@@ -189,6 +232,17 @@ export class UserInvitationManager {
|
||||
await invitation.regenerateToken();
|
||||
await this.sendInvitationEmail(invitation, requestArg.organizationId);
|
||||
|
||||
await this.emitOrganizationAlert({
|
||||
organizationId: requestArg.organizationId,
|
||||
eventType: 'org_invitation_resent',
|
||||
severity: 'low',
|
||||
title: 'Organization invitation resent',
|
||||
body: `${user.data.email} resent an invitation to ${invitation.data.email}.`,
|
||||
actorUserId: user.id,
|
||||
relatedEntityId: invitation.id,
|
||||
relatedEntityType: 'invitation',
|
||||
});
|
||||
|
||||
return { success: true, message: 'Invitation resent.' };
|
||||
}
|
||||
)
|
||||
@@ -231,10 +285,12 @@ export class UserInvitationManager {
|
||||
|
||||
await role.delete();
|
||||
|
||||
// Remove org from user's connectedOrgs
|
||||
const memberUser = await this.receptionRef.userManager.CUser.getInstance({
|
||||
const removedUser = await this.receptionRef.userManager.CUser.getInstance({
|
||||
id: requestArg.userId,
|
||||
});
|
||||
|
||||
// Remove org from user's connectedOrgs
|
||||
const memberUser = removedUser;
|
||||
if (memberUser && memberUser.data.connectedOrgs) {
|
||||
memberUser.data.connectedOrgs = memberUser.data.connectedOrgs.filter(
|
||||
orgId => orgId !== requestArg.organizationId
|
||||
@@ -242,6 +298,19 @@ export class UserInvitationManager {
|
||||
await memberUser.save();
|
||||
}
|
||||
|
||||
await this.emitOrganizationAlert({
|
||||
organizationId: requestArg.organizationId,
|
||||
eventType: 'org_member_removed',
|
||||
severity: 'high',
|
||||
title: 'Organization member removed',
|
||||
body: `${user.data.email} removed ${removedUser?.data?.email || requestArg.userId} from ${await this.getOrganizationName(
|
||||
requestArg.organizationId
|
||||
)}.`,
|
||||
actorUserId: user.id,
|
||||
relatedEntityId: requestArg.userId,
|
||||
relatedEntityType: 'user',
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
)
|
||||
@@ -283,6 +352,20 @@ export class UserInvitationManager {
|
||||
role.data.roles = requestArg.roles;
|
||||
await role.save();
|
||||
|
||||
const updatedUser = await this.receptionRef.userManager.CUser.getInstance({
|
||||
id: requestArg.userId,
|
||||
});
|
||||
await this.emitOrganizationAlert({
|
||||
organizationId: requestArg.organizationId,
|
||||
eventType: 'org_member_roles_updated',
|
||||
severity: 'high',
|
||||
title: 'Organization member roles updated',
|
||||
body: `${user.data.email} changed roles for ${updatedUser?.data?.email || requestArg.userId} to ${requestArg.roles.join(', ')}.`,
|
||||
actorUserId: user.id,
|
||||
relatedEntityId: requestArg.userId,
|
||||
relatedEntityType: 'user',
|
||||
});
|
||||
|
||||
return { success: true, role: await role.createSavableObject() };
|
||||
}
|
||||
)
|
||||
@@ -332,6 +415,20 @@ export class UserInvitationManager {
|
||||
}
|
||||
await currentUserRole.save();
|
||||
|
||||
const newOwner = await this.receptionRef.userManager.CUser.getInstance({
|
||||
id: requestArg.newOwnerId,
|
||||
});
|
||||
await this.emitOrganizationAlert({
|
||||
organizationId: requestArg.organizationId,
|
||||
eventType: 'org_ownership_transferred',
|
||||
severity: 'critical',
|
||||
title: 'Organization ownership transferred',
|
||||
body: `${user.data.email} transferred ownership to ${newOwner?.data?.email || requestArg.newOwnerId}.`,
|
||||
actorUserId: user.id,
|
||||
relatedEntityId: requestArg.newOwnerId,
|
||||
relatedEntityType: 'user',
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user