| import { Schema, model, Document, Types } from 'mongoose'; |
|
|
| |
| export enum ActivityAction { |
| |
| LOGIN = 'login', |
| LOGOUT = 'logout', |
| SIGNUP = 'signup', |
| PASSWORD_CHANGE = 'password_change', |
| PASSWORD_RESET = 'password_reset', |
| |
| |
| PROFILE_UPDATE = 'profile_update', |
| PROFILE_PHOTO_UPLOAD = 'profile_photo_upload', |
| LOCATION_UPDATE = 'location_update', |
| |
| |
| EVENT_CREATE = 'event_create', |
| EVENT_UPDATE = 'event_update', |
| EVENT_DELETE = 'event_delete', |
| EVENT_JOIN = 'event_join', |
| EVENT_LEAVE = 'event_leave', |
| EVENT_CHECKIN = 'event_checkin', |
| EVENT_VIEW = 'event_view', |
| EVENT_SEARCH = 'event_search', |
| |
| |
| FORM_CREATE = 'form_create', |
| FORM_UPDATE = 'form_update', |
| FORM_DELETE = 'form_delete', |
| FORM_SUBMIT = 'form_submit', |
| FORM_VIEW = 'form_view', |
| FORM_EXPORT = 'form_export', |
| |
| |
| TRAINER_VERIFY = 'trainer_verify', |
| TRAINER_REJECT = 'trainer_reject', |
| ORG_VERIFY = 'organization_verify', |
| ORG_REJECT = 'organization_reject', |
| |
| |
| DOCUMENT_UPLOAD = 'document_upload', |
| DOCUMENT_VIEW = 'document_view', |
| |
| |
| ANALYTICS_VIEW = 'analytics_view', |
| REPORT_EXPORT = 'report_export', |
| |
| |
| API_ERROR = 'api_error', |
| UNAUTHORIZED_ACCESS = 'unauthorized_access' |
| } |
|
|
| export enum ActivityCategory { |
| AUTH = 'authentication', |
| PROFILE = 'profile', |
| EVENT = 'event', |
| FORM = 'form', |
| VERIFICATION = 'verification', |
| ANALYTICS = 'analytics', |
| SYSTEM = 'system' |
| } |
|
|
| interface IActivityMetadata { |
| |
| ipAddress?: string; |
| userAgent?: string; |
| device?: string; |
| browser?: string; |
| |
| |
| eventId?: Types.ObjectId; |
| formId?: Types.ObjectId; |
| organizationId?: Types.ObjectId; |
| trainerId?: Types.ObjectId; |
| |
| |
| changes?: Record<string, any>; |
| errorMessage?: string; |
| statusCode?: number; |
| |
| |
| location?: { |
| type: "Point"; |
| coordinates: [number, number]; |
| }; |
| |
| |
| duration?: number; |
| method?: string; |
| endpoint?: string; |
| queryParams?: Record<string, any>; |
| responseSize?: number; |
| } |
|
|
| export interface IUserActivity extends Document { |
| user: Types.ObjectId; |
| action: ActivityAction; |
| category: ActivityCategory; |
| description: string; |
| metadata: IActivityMetadata; |
| timestamp: Date; |
| sessionId?: string; |
| success: boolean; |
| createdAt: Date; |
| } |
|
|
| const UserActivitySchema = new Schema<IUserActivity>({ |
| user: { |
| type: Schema.Types.ObjectId, |
| ref: 'User', |
| required: true, |
| index: true |
| }, |
| |
| action: { |
| type: String, |
| enum: Object.values(ActivityAction), |
| required: true, |
| index: true |
| }, |
| |
| category: { |
| type: String, |
| enum: Object.values(ActivityCategory), |
| required: true, |
| index: true |
| }, |
| |
| description: { |
| type: String, |
| required: true |
| }, |
| |
| metadata: { |
| ipAddress: String, |
| userAgent: String, |
| device: String, |
| browser: String, |
| |
| eventId: { |
| type: Schema.Types.ObjectId, |
| ref: 'Event' |
| }, |
| formId: { |
| type: Schema.Types.ObjectId, |
| ref: 'Form' |
| }, |
| organizationId: { |
| type: Schema.Types.ObjectId, |
| ref: 'User' |
| }, |
| trainerId: { |
| type: Schema.Types.ObjectId, |
| ref: 'User' |
| }, |
| |
| changes: Schema.Types.Mixed, |
| errorMessage: String, |
| statusCode: Number, |
| |
| location: { |
| type: { |
| type: String, |
| enum: ['Point'] |
| }, |
| coordinates: [Number] |
| }, |
| |
| duration: Number, |
| method: String, |
| endpoint: String, |
| queryParams: Schema.Types.Mixed, |
| responseSize: Number |
| }, |
| |
| timestamp: { |
| type: Date, |
| default: Date.now, |
| index: true |
| }, |
| |
| sessionId: { |
| type: String, |
| index: true |
| }, |
| |
| success: { |
| type: Boolean, |
| default: true, |
| index: true |
| } |
| }, { |
| timestamps: { createdAt: true, updatedAt: false } |
| }); |
|
|
| |
| UserActivitySchema.index({ user: 1, timestamp: -1 }); |
| UserActivitySchema.index({ user: 1, category: 1, timestamp: -1 }); |
| UserActivitySchema.index({ user: 1, action: 1, timestamp: -1 }); |
| UserActivitySchema.index({ sessionId: 1, timestamp: -1 }); |
| UserActivitySchema.index({ 'metadata.eventId': 1 }); |
| UserActivitySchema.index({ 'metadata.formId': 1 }); |
|
|
| |
| UserActivitySchema.index({ timestamp: 1 }, { expireAfterSeconds: 63072000 }); |
|
|
| export default model<IUserActivity>('UserActivity', UserActivitySchema); |