feat(reception): Add activity logging, session metadata and org-selection UI (backend and frontend)
This commit is contained in:
@@ -259,6 +259,83 @@ export class LoginSessionManager {
|
||||
ok: false
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Get all sessions for the current user
|
||||
this.typedRouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_GetUserSessions>(
|
||||
'getUserSessions',
|
||||
async (requestArg) => {
|
||||
const jwt = await this.receptionRef.jwtManager.verifyJWTAndGetData(requestArg.jwt);
|
||||
if (!jwt) {
|
||||
throw new plugins.typedrequest.TypedResponseError('Invalid JWT');
|
||||
}
|
||||
|
||||
// Get the current session's refresh token to identify the current session
|
||||
const currentRefreshToken = jwt.data.refreshToken;
|
||||
|
||||
// Get all sessions for this user
|
||||
const sessions = await this.CLoginSession.getInstances({
|
||||
'data.userId': jwt.data.userId,
|
||||
'data.invalidated': false,
|
||||
});
|
||||
|
||||
return {
|
||||
sessions: sessions.map((session) => ({
|
||||
id: session.id,
|
||||
deviceId: session.data.deviceId || 'unknown',
|
||||
deviceName: session.data.deviceInfo?.deviceName || 'Unknown Device',
|
||||
browser: session.data.deviceInfo?.browser || 'Unknown Browser',
|
||||
os: session.data.deviceInfo?.os || 'Unknown OS',
|
||||
ip: session.data.deviceInfo?.ip || 'Unknown',
|
||||
lastActive: session.data.lastActive || session.data.createdAt || Date.now(),
|
||||
createdAt: session.data.createdAt || Date.now(),
|
||||
isCurrent: session.data.refreshToken === currentRefreshToken,
|
||||
})),
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Revoke a specific session
|
||||
this.typedRouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_RevokeSession>(
|
||||
'revokeSession',
|
||||
async (requestArg) => {
|
||||
const jwt = await this.receptionRef.jwtManager.verifyJWTAndGetData(requestArg.jwt);
|
||||
if (!jwt) {
|
||||
throw new plugins.typedrequest.TypedResponseError('Invalid JWT');
|
||||
}
|
||||
|
||||
// Get the session to revoke
|
||||
const sessionToRevoke = await this.CLoginSession.getInstance({
|
||||
id: requestArg.sessionId,
|
||||
'data.userId': jwt.data.userId, // Ensure user can only revoke their own sessions
|
||||
});
|
||||
|
||||
if (!sessionToRevoke) {
|
||||
throw new plugins.typedrequest.TypedResponseError('Session not found');
|
||||
}
|
||||
|
||||
// Don't allow revoking the current session via this method
|
||||
if (sessionToRevoke.data.refreshToken === jwt.data.refreshToken) {
|
||||
throw new plugins.typedrequest.TypedResponseError(
|
||||
'Cannot revoke current session. Use logout instead.'
|
||||
);
|
||||
}
|
||||
|
||||
await sessionToRevoke.invalidate();
|
||||
|
||||
// Log the activity
|
||||
await this.receptionRef.activityLogManager.logActivity(
|
||||
jwt.data.userId,
|
||||
'session_revoked',
|
||||
`Revoked session on ${sessionToRevoke.data.deviceInfo?.deviceName || 'unknown device'}`
|
||||
);
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user