import ServerDocumentMixin from"../backend/server-document.mjs";import BaseUser from"../../../common/documents/user.mjs";import sessions from"../../sessions.mjs";import{createPassword}from"../../core/auth.mjs";import{USER_ROLES}from"../../../common/constants.mjs";export default class User extends(ServerDocumentMixin(BaseUser)){static _migrationRegistry=[...super._migrationRegistry,{fn:migratePlainTextPassword,version:12}];get sessions(){return sessions.getUserSessions(this.id)}get sockets(){const e=[];for(let s of config.sockets.values())s.userId===this.id&&e.push(s);return e}get isActive(){return!!this.id&&(game.active&&game.activity&&this.id in game.activity.users)}async _preCreate(e,s,t){await this.#e();if(!1===await super._preCreate(e,s,t))return!1;const{hash:r,salt:a}=createPassword(this.password);this.updateSource({password:r,passwordSalt:a})}_onCreate(e,s,t){super._onCreate(e,s,t),game.users.push(this),delete e.password,delete e.passwordSalt}async _preUpdate(e,s,t){await this.#e();if(!1===await super._preUpdate(e,s,t))return!1;if("password"in e){const{hash:s,salt:t}=createPassword(e.password);e.password=s,e.passwordSalt=t,sessions.deactivateUserSession(this.id)}if("role"in e&&(this.role>t.role||e.role>t.role))throw new Error("You are not authorized to perform this role change.");const r=CONST.USER_ROLES.GAMEMASTER;if("role"in e&&e.role<r&&this.role===r&&!game.users.find((e=>e.role===r&&e.id!==this.id)))throw new Error("You may not demote the only Gamemaster user within the World.")}_onUpdate(e,s,t){super._onUpdate(e,s,t),db.User.get(this.id).then((e=>game.users.findSplice((e=>e.id===this.id),e))),delete e.password,delete e.passwordSalt}async _preDelete(e,s){const t=CONST.USER_ROLES.GAMEMASTER;if(this.role===t&&!game.users.find((e=>e.role===t&&e.id!==this.id)))throw new Error("You may not delete the only Gamemaster user within the World.");await super._preDelete(e,s)}async _onDelete(e,s){const{logger:t}=global;super._onDelete(e,s),game.users.findSplice((e=>e.id===this.id));const r=await db.Setting.find({user:this.id});if(r.length){const e=db.Setting.sublevel.db.batch();r.forEach((s=>s.batchDelete(e))),await e.write(),t.info(`Deleted ${r.length} Settings scoped to User [${this.id}]: [${r.map((e=>e.key)).join(", ")}]`)}}async#e(){if((await User.find({name:this.name})).find((e=>e.id!==this.id)))throw new Error(`User names must be unique, the name ${this.name} is already taken`)}static async dump(e={}){const s=await super.dump(e);return s.forEach((e=>{delete e.password,delete e.passwordSalt})),s.sort(User.#s),s}static fromSource(e,{safe:s=!1,...t}={}){const r=super.fromSource(e,t);return s&&r.updateSource({password:"",passwordSalt:""}),r}static async find(e={},s={}){const t=await super.find(e,s);return t.sort(User.#s),t}static async getUsers(){const e=await User.find({}),s=game.activity.users;for(const t of e){if(!t.id)continue;const e=s[t.id]||{};t.viewedScene=e.sceneId||null}return game.users=e}static#s(e,s){const t=e.role>=USER_ROLES.ASSISTANT?e.role:1,r=s.role>=USER_ROLES.ASSISTANT?s.role:1;return t!==r?r-t:e.name.compare(s.name)}}function migratePlainTextPassword(e){if("passwordSalt"in e)return!1;const{hash:s,salt:t}=createPassword(e.password||"");return e.password=s,e.paswordSalt=t,!0}