feat(notifications): login service notifications

This commit is contained in:
x032205
2025-09-16 01:36:53 -04:00
parent 4431fe687d
commit 55eceb725c
3 changed files with 32 additions and 3 deletions

View File

@@ -773,7 +773,8 @@ export const registerRoutes = async (
orgDAL,
totpService,
orgMembershipDAL,
auditLogService
auditLogService,
notificationService
});
const passwordService = authPaswordServiceFactory({
tokenService,

View File

@@ -14,6 +14,8 @@ import { getServerCfg } from "@app/services/super-admin/super-admin-service";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TokenType } from "../auth-token/auth-token-types";
import { TNotificationServiceFactory } from "../notification/notification-service";
import { NotificationType } from "../notification/notification-types";
import { TOrgDALFactory } from "../org/org-dal";
import { getDefaultOrgMembershipRole } from "../org/org-role-fns";
import { TOrgMembershipDALFactory } from "../org-membership/org-membership-dal";
@@ -47,6 +49,7 @@ type TAuthLoginServiceFactoryDep = {
totpService: Pick<TTotpServiceFactory, "verifyUserTotp" | "verifyWithUserRecoveryCode">;
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
orgMembershipDAL: TOrgMembershipDALFactory;
notificationService: Pick<TNotificationServiceFactory, "createUserNotifications">;
};
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
@@ -57,7 +60,8 @@ export const authLoginServiceFactory = ({
orgDAL,
orgMembershipDAL,
totpService,
auditLogService
auditLogService,
notificationService
}: TAuthLoginServiceFactoryDep) => {
/*
* Private
@@ -71,6 +75,16 @@ export const authLoginServiceFactory = ({
if (!isDeviceSeen) {
const newDeviceList = devices.concat([{ ip, userAgent }]);
await userDAL.updateById(user.id, { devices: JSON.stringify(newDeviceList) }, tx);
await notificationService.createUserNotifications([
{
userId: user.id,
type: NotificationType.LOGIN_FROM_NEW_DEVICE,
title: "Login From New Device",
body: `A new device with IP **${ip}** and User Agent **${userAgent}** has logged into your account.`
}
]);
if (user.email) {
await smtpService.sendMail({
template: SmtpTemplates.NewDeviceJoin,
@@ -563,6 +577,18 @@ export const authLoginServiceFactory = ({
.filter(Boolean) as string[];
if (adminEmails.length > 0) {
await notificationService.createUserNotifications(
orgAdmins
.filter((admin) => admin.user.id !== user.id)
.map((admin) => ({
userId: admin.user.id,
orgId: organizationId,
type: NotificationType.ADMIN_SSO_BYPASS,
title: "Security Alert: Admin SSO Bypass",
body: `The org admin **${user.email}** has bypassed enforced SSO login.`
}))
);
await smtpService.sendMail({
recipients: adminEmails,
subjectLine: "Security Alert: Admin SSO Bypass",

View File

@@ -6,7 +6,9 @@ export enum NotificationType {
SECRET_CHANGE_POLICY_BYPASSED = "secret-change-policy-bypassed",
SECRET_ROTATION_FAILED = "secret-rotation-failed",
SECRET_SCANNING_SECRETS_DETECTED = "secret-scanning-secrets-detected",
SECRET_SCANNING_SCAN_FAILED = "secret-scanning-scan-failed"
SECRET_SCANNING_SCAN_FAILED = "secret-scanning-scan-failed",
LOGIN_FROM_NEW_DEVICE = "login-from-new-device",
ADMIN_SSO_BYPASS = "admin-sso-bypass"
}
export interface TCreateUserNotificationDTO {