137 lines
2.8 KiB
JavaScript
137 lines
2.8 KiB
JavaScript
import mongoose from 'mongoose';
|
|
|
|
const SessionSchema = new mongoose.Schema(
|
|
{
|
|
userId: {
|
|
type: mongoose.Schema.Types.ObjectId,
|
|
ref: 'User',
|
|
required: true,
|
|
index: true,
|
|
},
|
|
steamId: {
|
|
type: String,
|
|
required: true,
|
|
index: true,
|
|
},
|
|
token: {
|
|
type: String,
|
|
required: true,
|
|
unique: true,
|
|
},
|
|
refreshToken: {
|
|
type: String,
|
|
required: true,
|
|
unique: true,
|
|
},
|
|
ip: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
userAgent: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
device: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
browser: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
os: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
location: {
|
|
country: { type: String, default: null },
|
|
city: { type: String, default: null },
|
|
region: { type: String, default: null },
|
|
},
|
|
isActive: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
lastActivity: {
|
|
type: Date,
|
|
default: Date.now,
|
|
},
|
|
expiresAt: {
|
|
type: Date,
|
|
required: true,
|
|
index: { expires: 0 }, // TTL index - automatically delete expired sessions
|
|
},
|
|
},
|
|
{
|
|
timestamps: true,
|
|
}
|
|
);
|
|
|
|
// Index for cleaning up old sessions
|
|
SessionSchema.index({ createdAt: 1 });
|
|
SessionSchema.index({ userId: 1, isActive: 1 });
|
|
|
|
// Method to mark session as inactive
|
|
SessionSchema.methods.deactivate = async function () {
|
|
this.isActive = false;
|
|
return this.save();
|
|
};
|
|
|
|
// Method to update last activity
|
|
SessionSchema.methods.updateActivity = async function () {
|
|
this.lastActivity = Date.now();
|
|
return this.save();
|
|
};
|
|
|
|
// Static method to clean up inactive sessions for a user
|
|
SessionSchema.statics.cleanupUserSessions = async function (userId, keepCurrent = null) {
|
|
const query = {
|
|
userId,
|
|
isActive: false,
|
|
};
|
|
|
|
if (keepCurrent) {
|
|
query._id = { $ne: keepCurrent };
|
|
}
|
|
|
|
return this.deleteMany(query);
|
|
};
|
|
|
|
// Static method to get active sessions for a user
|
|
SessionSchema.statics.getActiveSessions = async function (userId) {
|
|
return this.find({
|
|
userId,
|
|
isActive: true,
|
|
expiresAt: { $gt: new Date() },
|
|
}).sort({ lastActivity: -1 });
|
|
};
|
|
|
|
// Static method to revoke all sessions except current
|
|
SessionSchema.statics.revokeAllExcept = async function (userId, currentSessionId) {
|
|
return this.updateMany(
|
|
{
|
|
userId,
|
|
_id: { $ne: currentSessionId },
|
|
isActive: true,
|
|
},
|
|
{
|
|
$set: { isActive: false },
|
|
}
|
|
);
|
|
};
|
|
|
|
// Static method to revoke all sessions
|
|
SessionSchema.statics.revokeAll = async function (userId) {
|
|
return this.updateMany(
|
|
{
|
|
userId,
|
|
isActive: true,
|
|
},
|
|
{
|
|
$set: { isActive: false },
|
|
}
|
|
);
|
|
};
|
|
|
|
export default mongoose.model('Session', SessionSchema);
|