Spaces:
Running
Running
Download src/models/User.js from AndreaNotes1/auth-app-api: direct link, hf CLI and curl.
- Browser
- Download file 2.69 kB
-
https://huggingface.co/spaces/AndreaNotes1/auth-app-api/resolve/main/src/models/User.js
- Command line
-
hf download hf://spaces/AndreaNotes1/auth-app-api/src/models/User.js
-
curl -L -o User.js https://huggingface.co/spaces/AndreaNotes1/auth-app-api/resolve/main/src/models/User.js
2.69 kB
| const mongoose = require("mongoose"); | |
| const bcrypt = require("bcryptjs"); | |
| const enrolledCourseSchema = new mongoose.Schema( | |
| { | |
| course: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true }, | |
| order: { type: mongoose.Schema.Types.ObjectId, ref: "Order", required: true }, | |
| accessGrantedAt: { type: Date, default: Date.now }, | |
| }, | |
| { _id: false } | |
| ); | |
| const userSchema = new mongoose.Schema( | |
| { | |
| name: { type: String, required: true, trim: true, maxlength: 120 }, | |
| email: { | |
| type: String, | |
| required: true, | |
| unique: true, | |
| lowercase: true, | |
| trim: true, | |
| maxlength: 254, | |
| index: true, | |
| }, | |
| passwordHash: { type: String, required: true, select: false }, | |
| role: { type: String, enum: ["user", "admin"], default: "user" }, | |
| // Access-control / session-security bookkeeping | |
| tokenVersion: { type: Number, default: 0 }, // bump to invalidate all issued JWTs | |
| activeRefreshTokens: { | |
| // store only the jti + expiry, never the raw token, so a leaked DB | |
| // dump can't be replayed as a session | |
| type: [ | |
| { | |
| jti: String, | |
| expiresAt: Date, | |
| userAgent: String, | |
| ip: String, | |
| }, | |
| ], | |
| default: [], | |
| select: false, | |
| }, | |
| // Brute-force protection | |
| failedLoginAttempts: { type: Number, default: 0, select: false }, | |
| lockUntil: { type: Date, default: null, select: false }, | |
| enrolledCourses: { type: [enrolledCourseSchema], default: [] }, | |
| isActive: { type: Boolean, default: true }, | |
| }, | |
| { timestamps: true } | |
| ); | |
| userSchema.methods.setPassword = async function setPassword(plainPassword) { | |
| const salt = await bcrypt.genSalt(12); | |
| this.passwordHash = await bcrypt.hash(plainPassword, salt); | |
| }; | |
| userSchema.methods.comparePassword = function comparePassword(plainPassword) { | |
| return bcrypt.compare(plainPassword, this.passwordHash); | |
| }; | |
| userSchema.methods.isLocked = function isLocked() { | |
| return !!(this.lockUntil && this.lockUntil > Date.now()); | |
| }; | |
| userSchema.methods.hasAccessToCourse = function hasAccessToCourse(courseId) { | |
| return this.enrolledCourses.some((ec) => ec.course.toString() === courseId.toString()); | |
| }; | |
| userSchema.methods.toSafeJSON = function toSafeJSON() { | |
| return { | |
| id: this._id, | |
| name: this.name, | |
| email: this.email, | |
| role: this.role, | |
| enrolledCourses: this.enrolledCourses.map((ec) => ({ | |
| course: ec.course, | |
| order: ec.order, | |
| accessGrantedAt: ec.accessGrantedAt, | |
| })), | |
| createdAt: this.createdAt, | |
| }; | |
| }; | |
| module.exports = mongoose.model("User", userSchema); | |