/** * MongoShrimp — Shrimp + Mongoose 装配体(无 HTTP 层) * * 提供: * - 默认 Mongoose Schema(User / Role / OperationLog),子类可覆盖 * - Mongoose Model 工厂 + 缓存 * - 默认 CRUD / Module 工厂,绑定 MongoShrimpCrud * - mongoose.connect + onDbConnected 钩子 * - initDefaultData 默认角色/用户播种 * * 不知道:express / jwt / 任何 HTTP 概念。 * 上层把 HTTP 装到这之上,见 main/expmon.ts 的 ShrimpServer。 */ import mongoose, { Schema, Model } from "mongoose" import { Shrimp } from "../Shrimp/Shrimp" import { UserModule, RoleModule } from "../Shrimp/UserRoleModule" import { OperationLogModule } from "../Shrimp/OperationLogModule" import type { ShrimpCrud } from "../Shrimp/ShrimpCrud" import { IUser, IRole, IOperationLog, WithId } from "../IShrimpType" import { MongoShrimpCrud } from "./MongoShrimpCrud" export const UserSchema = new Schema({ username: { type: String, required: true }, password: { type: String, required: true }, nickname: { type: String, default: "" }, roleId: { type: [Schema.Types.ObjectId], ref: "Role", default: [] }, active: { type: Boolean, default: true }, }, { timestamps: true }) export const RoleSchema = new Schema({ name: { type: String, required: true }, description: { type: String, default: "" }, isSuperAdmin: { type: Boolean, default: false }, powers: { type: [String], default: [] }, }, { timestamps: true }) export const OperationLogSchema = new Schema({ operatorId: { type: String, default: null }, ip: { type: String, default: "" }, method: { type: String, required: true }, args: { type: String, default: "" }, success: { type: Boolean, default: true }, errorMsg: { type: String, default: "" }, createdAt: { type: Number, default: () => Date.now() }, }, { timestamps: false }) export class MongoShrimp extends Shrimp { userModule: UserModule roleModule: RoleModule operationLogModule: OperationLogModule protected _userModel?: Model protected _roleModel?: Model protected _operationLogModel?: Model constructor(mongodbUri: string = "mongodb://localhost:27017/shrimp") { super() const userCrud = this.createUserCrud() const roleCrud = this.createRoleCrud() const operationLogCrud = this.createOperationLogCrud() this.userModule = this.createUserModule(userCrud) this.roleModule = this.createRoleModule(roleCrud) this.operationLogModule = this.createOperationLogModule(operationLogCrud) mongoose.connect(mongodbUri).then(() => { console.log(mongodbUri + " MongoDB connected") this.onDbConnected() }) } // ============== 可覆盖的 Schema 工厂 ============== protected createUserSchema(): mongoose.Schema { return UserSchema } protected createRoleSchema(): mongoose.Schema { return RoleSchema } protected createOperationLogSchema(): mongoose.Schema { return OperationLogSchema } protected getUserModel(): Model { if (!this._userModel) { this._userModel = mongoose.model("shrimp_users", this.createUserSchema()) } return this._userModel } protected getRoleModel(): Model { if (!this._roleModel) { this._roleModel = mongoose.model("shrimp_roles", this.createRoleSchema()) } return this._roleModel } protected getOperationLogModel(): Model { if (!this._operationLogModel) { this._operationLogModel = mongoose.model("shrimp_operation_logs", this.createOperationLogSchema()) } return this._operationLogModel } // ============== 可覆盖的 Crud 工厂 ============== protected createUserCrud(): MongoShrimpCrud> { return new MongoShrimpCrud>(this.getUserModel()) } protected createRoleCrud(): MongoShrimpCrud> { return new MongoShrimpCrud>(this.getRoleModel()) } protected createOperationLogCrud(): MongoShrimpCrud> { return new MongoShrimpCrud>(this.getOperationLogModel()) } // ============== 可覆盖的 Module 工厂 ============== protected createUserModule(dataSource: ShrimpCrud>): UserModule { return new UserModule(this, dataSource) } protected createRoleModule(dataSource: ShrimpCrud>): RoleModule { return new RoleModule(this, dataSource) } protected createOperationLogModule(dataSource: ShrimpCrud>): OperationLogModule { return new OperationLogModule(this.userModule, dataSource) } // ============== 启动钩子 ============== protected async onDbConnected(): Promise { } /** 初始化默认数据(如默认角色、用户),子类可覆盖 */ protected async initDefaultData(name: string = "Administrator", description: string = "System administrator with all permissions"): Promise { const result = await this.userModule.dataSource.list({ limit: 1 }) if (result.total > 0) return console.log("初始化默认数据") const adminRole = await this.roleModule.dataSource.add({ name: name, description: description, isSuperAdmin: true, powers: [], createdAt: Date.now(), updatedAt: Date.now(), }) await this.userModule.add({ username: "admin", password: "admin", nickname: "Administrator", roleId: [adminRole._id], active: true, createdAt: Date.now(), updatedAt: Date.now(), }) } }