najm-auth 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of najm-auth might be problematic. Click here for more details.
- package/dist/index.mjs +2998 -12
- package/dist/shared/index.d.ts +0 -4
- package/package.json +5 -6
- package/dist/index.js +0 -12
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,2998 @@
|
|
|
1
|
-
var ns=Object.defineProperty;var os=(e,t)=>{for(var a in t)ns(e,a,{get:t[a],enumerable:!0,configurable:!0,set:(i)=>t[a]=()=>i})};var n=function(e,t,a,i){var l=arguments.length,c=l<3?t:i===null?i=Object.getOwnPropertyDescriptor(t,a):i,d;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")c=Reflect.decorate(e,t,a,i);else for(var E=e.length-1;E>=0;E--)if(d=e[E])c=(l<3?d(c):l>3?d(t,a,c):d(t,a))||c;return l>3&&c&&Object.defineProperty(t,a,c),c},u=(e,t)=>(a,i)=>t(a,i,e),r=(e,t)=>{if(typeof Reflect==="object"&&typeof Reflect.metadata==="function")return Reflect.metadata(e,t)};import{Injectable as cs}from"najm-api";import Fe from"bcrypt";class J{constructor(){}async hashPassword(e){if(!e)return null;if(typeof e!=="string"||e.trim().length===0)return null;return Fe.hash(e,10)}async comparePassword(e,t){return Fe.compare(e,t)}}J=n([cs(),r("design:paramtypes",[])],J);import{setCookie as us,Injectable as ps,deleteCookie as ls}from"najm-api";import ms from"timestring";class G{setRefreshCookie(e){let t=ms(process.env.REFRESH_EXPIRES_IN,"s");us("refreshToken",e,{httpOnly:!1,sameSite:"Lax",maxAge:t,path:"/api/auth/refresh"})}clearRefreshCookie(){ls("refreshToken",{httpOnly:!1,sameSite:"Lax",path:"/api/auth/refresh",maxAge:0})}}G=n([ps()],G);import{Controller as Ds,Get as He,Post as We,Params as Qs,Body as Xe,User as Zs,t as ne}from"najm-api";import{t as ct}from"najm-api";import{Injectable as Ws,getCurrentLanguage as Xs}from"najm-api";import{rolesTable as U,usersTable as y,permissionsTable as Ve,rolePermissionsTable as be}from"@/database/schema";import{eq as T,ne as ys}from"drizzle-orm";import{Repository as ds}from"najm-api";class M{getUser(){return{id:y.id,email:y.email,emailVerified:y.emailVerified,image:y.image,status:y.status,roleId:y.roleId,role:U.name,createdAt:y.createdAt,updatedAt:y.updatedAt}}async getAll(){let e=await this.db.select(this.getUser()).from(y).leftJoin(U,T(y.roleId,U.id));return Promise.all(e.map(async(t)=>({...t,permissions:await this.getUserPermissions(t.id)})))}async getById(e){let[t]=await this.db.select(this.getUser()).from(y).leftJoin(U,T(y.roleId,U.id)).where(T(y.id,e)).limit(1);if(!t)return t;return{...t,permissions:await this.getUserPermissions(t.id)}}async getByEmail(e){let[t]=await this.db.select(this.getUser()).from(y).leftJoin(U,T(y.roleId,U.id)).where(T(y.email,e));return t}async create(e){let[t]=await this.db.insert(y).values(e).returning();return t}async update(e,t){let[a]=await this.db.update(y).set(t).where(T(y.id,e)).returning();return a}async delete(e){let[t]=await this.db.delete(y).where(T(y.id,e)).returning();return t}async deleteAll(){let e=await this.db.select({id:U.id}).from(U).where(T(U.name,"admin")).limit(1);if(e.length===0)return await this.db.delete(y).returning();return await this.db.delete(y).where(ys(y.roleId,e[0].id)).returning()}async getRoleNameById(e){let[t]=await this.db.select({roleName:U.name}).from(y).leftJoin(U,T(y.roleId,U.id)).where(T(y.id,e));return t.roleName}async getUserPassword(e){let[t]=await this.db.select({id:y.id,email:y.email,password:y.password}).from(y).where(T(y.email,e)).limit(1);return t.password}async getUserPermissions(e){let[t]=await this.db.select({roleId:y.roleId}).from(y).where(T(y.id,e)).limit(1);if(!t||!t.roleId)return[];return(await this.db.select({name:Ve.name}).from(be).leftJoin(Ve,T(be.permissionId,Ve.id)).where(T(be.roleId,t.roleId))).map((i)=>i.name).filter((i)=>i)}}M=n([ds()],M);import{Injectable as hs,t as j}from"najm-api";import{parseSchema as gs}from"@/shared";import{userSchema as fs}from"@/lib/validations";class C{userRepository;encryptionService;constructor(e,t){this.userRepository=e;this.encryptionService=t}async validateCreateUser(e){return gs(fs,e)}async isEmailExists(e){return!!await this.userRepository.getByEmail(e)}async isPasswordValid(e,t){return!!await this.encryptionService.comparePassword(e,t)}async isUserExist(e){return!!await this.userRepository.getById(e)}async checkUserIdIsUnique(e){if(!e)return;if(await this.userRepository.getById(e))throw new Error(j("users.errors.idExists"))}async isCorrectPass(e){return e&&typeof e==="string"&&e.trim().length>0}async hasRole(e,t){let a=await this.userRepository.getRoleNameById(e);if(!a)throw Error(j("auth.errors.accessDenied"));if(!t.some((l)=>a.toLowerCase()===l.toLowerCase()))throw Error(j("auth.errors.accessDenied"));return!0}async checkUserExistsByEmail(e){let t=await this.userRepository.getByEmail(e);if(!t)throw new Error(j("auth.errors.invalidCredentials"));return t}async checkUserExists(e){let t=await this.isUserExist(e);if(!t)throw new Error(j("users.errors.notFound"));return t}async checkEmailUnique(e,t=null){if(!e)return;let a=await this.userRepository.getByEmail(e);if(a&&a.id!==t)throw new Error(j("auth.errors.emailExists"))}async checkEmailExists(e){let t=await this.userRepository.getByEmail(e);if(!t)throw new Error(j("users.errors.notFound"));return t}async checkPasswordValid(e,t){if(!await this.isPasswordValid(e,t))throw new Error(j("auth.errors.invalidCredentials"))}}C=n([hs(),r("design:paramtypes",[typeof M==="undefined"?Object:M,typeof J==="undefined"?Object:J])],C);import{Injectable as Vs,setLanguage as bs,getCurrentLanguage as _s,Transactional as $s}from"najm-api";import{rolesTable as P}from"@/database/schema";import{eq as ke}from"drizzle-orm";import{Repository as ws}from"najm-api";class H{async getAll(){return await this.db.select().from(P)}async getById(e){let[t]=await this.db.select().from(P).where(ke(P.id,e));return t}async getByName(e){let[t]=await this.db.select().from(P).where(ke(P.name,e));return t}async create(e){let[t]=await this.db.insert(P).values(e).returning();return t}async update(e,t){let[a]=await this.db.update(P).set(t).where(ke(P.id,e)).returning();return a}async delete(e){let[t]=await this.db.delete(P).where(ke(P.id,e)).returning();return t}}H=n([ws()],H);import{Injectable as xs,t as Te}from"najm-api";import{parseSchema as vs}from"@/shared";import{roleSchema as ks}from"@/lib/validations";class K{roleRepository;constructor(e){this.roleRepository=e}async validateCreateRole(e){return vs(ks,e)}async isRoleNameExists(e){return!!await this.roleRepository.getByName(e)}async isRoleIdExists(e){return!!await this.roleRepository.getById(e)}async checkNameUnique(e,t=null){if(!e)return;let a=await this.roleRepository.getByName(e);if(a&&a.id!==t)throw new Error(Te("roles.errors.exists"))}async checkRoleExists(e){if(!await this.isRoleIdExists(e))throw new Error(Te("roles.errors.notFound"))}async checkRoleExistsByName(e){if(!await this.isRoleNameExists(e))throw new Error(Te("roles.errors.notFound"))}async checkAdminRoleExists(){let e=await this.roleRepository.getByName("admin");if(!e)throw new Error(Te("users.errors.adminRoleNotFound"));return e}}K=n([xs(),r("design:paramtypes",[typeof H==="undefined"?Object:H])],K);import{Injectable as st,Headers as ze,createGuard as rt,GuardParams as Ns,Ctx as et}from"najm-api";import{tokensTable as se,usersTable as g,rolesTable as re,permissionsTable as _e,rolePermissionsTable as $e}from"@/database/schema";import{eq as I}from"drizzle-orm";import{Repository as Ts}from"najm-api";class O{async storeRefreshToken(e){return await this.db.insert(se).values(e).onConflictDoUpdate({target:se.userId,set:{token:e.token,expiresAt:e.expiresAt}}).returning()}async getRefreshToken(e){let[t]=await this.db.select().from(se).where(I(se.userId,e));return t?.token}async revokeToken(e){let[t]=await this.db.delete(se).where(I(se.userId,e)).returning();return t}async isUserExists(e){let[t]=await this.db.select({id:g.id}).from(g).where(I(g.id,e)).limit(1);return!!t}async getRoleNameById(e){let[t]=await this.db.select({roleName:re.name}).from(g).leftJoin(re,I(g.roleId,re.id)).where(I(g.id,e)).limit(1);return t?.roleName}async getUserPermissions(e){let[t]=await this.db.select({roleId:g.roleId}).from(g).where(I(g.id,e)).limit(1);if(!t||!t.roleId)return[];return(await this.db.select({name:_e.name}).from($e).leftJoin(_e,I($e.permissionId,_e.id)).where(I($e.roleId,t.roleId))).map((i)=>i.name).filter((i)=>i)}async getUser(e){let[t]=await this.db.select({id:g.id,email:g.email,status:g.status,roleId:g.roleId,roleName:re.name,createdAt:g.createdAt,updatedAt:g.updatedAt}).from(g).leftJoin(re,I(g.roleId,re.id)).where(I(g.id,e)).limit(1);return t?{...t,role:t.roleName}:null}}O=n([Ts()],O);import{t as ae}from"najm-api";import{getCookie as Ss,Injectable as Es}from"najm-api";import Se from"jsonwebtoken";import{jwtDecode as Us}from"jwt-decode";import Rs from"timestring";class A{tokenRepository;accessSecretKey=process.env.JWT_ACCESS_SECRET;accessExpiresIn=process.env.ACCESS_EXPIRES_IN;refreshSecretKey=process.env.JWT_REFRESH_SECRET;refreshExpiresIn=process.env.REFRESH_EXPIRES_IN;constructor(e){this.tokenRepository=e}extractAccessToken(e){if(e&&e.startsWith("Bearer"))return e.split(" ")[1];throw new Error(ae("auth.errors.tokenMissing"))}verifyAccessToken(e){try{return Se.verify(e,this.accessSecretKey)}catch(t){throw new Error(ae("auth.errors.tokenVerificationFailed"))}}verifyRefreshToken(e){try{return Se.verify(e,this.refreshSecretKey).userId}catch(t){throw new Error(ae("auth.errors.tokenVerificationFailed"))}}async getUserIdByAccessToken(e){let t=this.extractAccessToken(e),i=this.verifyAccessToken(t).userId;if(!await this.tokenRepository.isUserExists(i))throw new Error(ae("users.errors.notFound"));return i}async storeRefreshToken(e,t){let a=Rs(this.refreshExpiresIn,"s"),i={userId:e,token:t,expiresAt:new Date(Date.now()+a*1000).toISOString()};await this.tokenRepository.storeRefreshToken(i)}getTokenExpire(e){return Us(e).exp}generateAccessToken(e){let t={expiresIn:this.accessExpiresIn};return Se.sign(e,this.accessSecretKey,t)}generateRefreshToken(e){let t={expiresIn:this.refreshExpiresIn};return Se.sign(e,this.refreshSecretKey,t)}async generateTokens(e){let t={userId:e},a=await this.generateAccessToken(t),i=await this.generateRefreshToken(t),l=this.getTokenExpire(a),c=this.getTokenExpire(i);return await this.storeRefreshToken(e,i),{accessToken:a,refreshToken:i,accessTokenExpiresAt:l,refreshTokenExpiresAt:c}}async refreshTokens(){let e=Ss("refreshToken"),t=this.verifyRefreshToken(e);if(!await this.tokenRepository.isUserExists(t))throw new Error(ae("users.errors.notFound"));let i=await this.tokenRepository.getRefreshToken(t);if(e!=i)throw new Error(ae("auth.errors.refreshTokenInvalid"));return await this.generateTokens(t)}async revokeToken(e){return await this.tokenRepository.revokeToken(e)}async getUserPermissions(e){if(!e)return;let t=await this.getUserIdByAccessToken(e);return await this.tokenRepository.getUserPermissions(t)}async getUserRole(e){if(!e)return;let t=await this.getUserIdByAccessToken(e);return await this.tokenRepository.getRoleNameById(t)}async getUser(e){if(!e)return;let t=await this.getUserIdByAccessToken(e),a=await this.tokenRepository.getUser(t);if(!a)return null;return a}async storeUserInCache(e,t){let a=t.get("user");if(a)return a;let i=await this.getUser(e);if(i)t.set("user",i);return i}}A=n([Es(),r("design:paramtypes",[typeof O==="undefined"?Object:O])],A);var f={ADMIN:"admin",PRINCIPAL:"principal",ACCOUNTING:"accounting",SECRETARY:"secretary",TEACHER:"teacher",STUDENT:"student",PARENT:"parent"},tt={ADMINISTRATORS:[f.ADMIN,f.PRINCIPAL],FINANCIAL:[f.ADMIN,f.ACCOUNTING],STAFF:[f.ADMIN,f.PRINCIPAL,f.ACCOUNTING,f.SECRETARY,f.TEACHER],END_USERS:[f.STUDENT,f.PARENT],ALL:[f.ADMIN,f.PRINCIPAL,f.ACCOUNTING,f.SECRETARY,f.TEACHER,f.STUDENT,f.PARENT]};class Ee{isInGroup(e,t){return t.includes(e?.toLowerCase())}isAdministrator(e){return this.isInGroup(e,tt.ADMINISTRATORS)}isStaff(e){return this.isInGroup(e,tt.STAFF)}hasAnyRole(e,t){return t.includes(e?.toLowerCase())}hasExactRole(e,t){return e?.toLowerCase()===t?.toLowerCase()}}Ee=n([st()],Ee);class q{roleChecker;tokenService;constructor(e,t){this.roleChecker=e;this.tokenService=t}async isAuth(e,t){return!!await this.tokenService.storeUserInCache(e,t)}async hasRoles(e,t,a){try{let i=await this.tokenService.storeUserInCache(e,t);if(!i?.role)return!1;let l=Array.isArray(a)?a:[a];return this.roleChecker.hasAnyRole(i.role,l)}catch{return!1}}}n([u(0,ze("authorization")),u(1,et()),r("design:type",Function),r("design:paramtypes",[Object,Object]),r("design:returntype",Object)],q.prototype,"isAuth",null),n([u(0,ze("authorization")),u(1,et()),u(2,Ns()),r("design:type",Function),r("design:paramtypes",[Object,Object,Object]),r("design:returntype",Object)],q.prototype,"hasRoles",null),q=n([st(),r("design:paramtypes",[typeof Ee==="undefined"?Object:Ee,typeof A==="undefined"?Object:A])],q);var ie=()=>V("admin"),Ra=()=>V("principal"),Na=()=>V("accounting"),Ka=()=>V("secretary"),Aa=()=>V("teacher"),Ba=()=>V("parent"),Pa=()=>V("student"),Ia=()=>V("admin","principal"),Va=()=>V("admin","accounting"),ba=()=>V("admin","principal","accounting","secretary","teacher"),_a=rt(q,"isAuth"),V=(...e)=>rt(q,"hasRoles")(...e);import{Controller as As,Get as at,Post as Bs,Put as Ps,Delete as Is,Params as Je,Body as it,t as pe}from"najm-api";import{Injectable as Ks}from"najm-api";class B{roleRepository;roleValidator;constructor(e,t){this.roleRepository=e;this.roleValidator=t}async getAll(){return await this.roleRepository.getAll()}async getById(e){return await this.roleValidator.checkRoleExists(e),await this.roleRepository.getById(e)}async getByName(e){return await this.roleRepository.getByName(e)}async create(e){return await this.roleValidator.validateCreateRole(e),await this.roleValidator.checkNameUnique(e.name),await this.roleRepository.create(e)}async update(e,t){return await this.roleValidator.checkRoleExists(e),await this.roleValidator.checkNameUnique(t.name,e),await this.roleRepository.update(e,t)}async delete(e){return await this.roleValidator.checkRoleExists(e),await this.roleRepository.delete(e)}async seedDefaultRoles(e){let t=[];for(let i of e)if(!await this.roleValidator.isRoleNameExists(i.name))t.push(i);return await Promise.all(t.map((i)=>this.roleRepository.create(i)))}async getRoleIdByName(e){return(await this.getByName(e))?.id}}B=n([Ks(),r("design:paramtypes",[typeof H==="undefined"?Object:H,typeof K==="undefined"?Object:K])],B);class le{roleService;constructor(e){this.roleService=e}async getRoles(){return{data:await this.roleService.getAll(),message:pe("roles.success.retrieved"),status:"success"}}async getRole(e){return{data:await this.roleService.getById(e),message:pe("roles.success.retrieved"),status:"success"}}async createRole(e){return{data:await this.roleService.create(e),message:pe("roles.success.created"),status:"success"}}async updateRole(e,t){return{data:await this.roleService.update(e,t),message:pe("roles.success.updated"),status:"success"}}async deleteRole(e){return{data:await this.roleService.delete(e),message:pe("roles.success.deleted"),status:"success"}}}n([at(),ie(),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],le.prototype,"getRoles",null),n([at("/:id"),ie(),u(0,Je("id")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],le.prototype,"getRole",null),n([Bs(),ie(),u(0,it()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],le.prototype,"createRole",null),n([Ps("/:id"),ie(),u(0,Je("id")),u(1,it()),r("design:type",Function),r("design:paramtypes",[Object,Object]),r("design:returntype",Promise)],le.prototype,"updateRole",null),n([Is("/:id"),ie(),u(0,Je("id")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],le.prototype,"deleteRole",null),le=n([As("/roles"),r("design:paramtypes",[typeof B==="undefined"?Object:B])],le);import{nanoid as Js}from"nanoid";import{clean as Ms}from"@/shared";class W{roleValidator;roleService;userRepository;userValidator;encryptionService;constructor(e,t,a,i,l){this.roleValidator=e;this.roleService=t;this.userRepository=a;this.userValidator=i;this.encryptionService=l}sanitizeUser(e){if(!e)return e;let{password:t,...a}=e;return a}sanitizeUsers(e){return e.map((t)=>this.sanitizeUser(t))}async resolveUserRole(e,t){if(e)return await this.roleValidator.checkRoleExists(e),e;if(t){let i=await this.roleService.getByName(t);if(i)return i.id;throw new Error(`Role '${t}' not found`)}return(await this.roleService.getByName("Student")).id}async getAll(){let e=await this.userRepository.getAll();return this.sanitizeUsers(e)}async getById(e){await this.userValidator.checkUserExists(e);let t=await this.userRepository.getById(e);return this.sanitizeUser(t)}async getByEmail(e){let t=await this.userValidator.checkUserExistsByEmail(e);return this.sanitizeUser(t)}async create(e){let{id:t,email:a,image:i,emailVerified:l,password:c,roleId:d,role:E}=e,ue=t||Js(5),ss=c||"12345678";await this.userValidator.checkEmailUnique(e.email),await this.userValidator.checkUserIdIsUnique(t);let rs=await this.encryptionService.hashPassword(ss),as=await this.resolveUserRole(d,E),qe={id:ue,email:a,image:i,password:rs,roleId:as,emailVerified:l,status:"pending"};await this.userValidator.validateCreateUser(qe);let is=await this.userRepository.create(qe);return this.sanitizeUser(is)}async update(e,t){let{password:a,image:i}=t;await this.userValidator.checkUserExists(e),await this.userValidator.checkEmailUnique(t.email,e);let l=await this.userRepository.getById(e),c=await this.encryptionService.hashPassword(a),d={...t,image:i,...c&&{password:c}},E=Ms(d),ue=await this.userRepository.update(e,E);return this.sanitizeUser(ue)}async delete(e){await this.userValidator.checkUserExists(e);let t=await this.userRepository.delete(e);return this.sanitizeUser(t)}async deleteAll(){let e=await this.userRepository.deleteAll();return this.sanitizeUsers(e)}async getRoleName(e){return await this.userValidator.checkUserExists(e),await this.userRepository.getRoleNameById(e)}async getPassword(e){return await this.userValidator.checkUserExistsByEmail(e),await this.userRepository.getUserPassword(e)}async assignRole(e,t,a){await this.userValidator.checkUserExists(e);let i=await this.resolveUserRole(t,a),l=await this.userRepository.update(e,{roleId:i});return this.sanitizeUser(l)}async removeRole(e){await this.userValidator.checkUserExists(e);let t=await this.userRepository.update(e,{roleId:null});return this.sanitizeUser(t)}async seedAdminUser(){let t=await this.roleValidator.checkAdminRoleExists(),a=await this.userRepository.getByEmail("admin@admin.com");if(a)await this.delete(a.id);let i=await this.create({id:"USR00",name:"System Administrator",email:"admin@admin.com",password:"12345678",image:null,roleId:t.id,status:"active",emailVerified:!0});return this.sanitizeUser(i)}async updateLang(e){return bs(e),e}async getLang(){return _s()}}n([$s(),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],W.prototype,"create",null),W=n([Vs(),r("design:paramtypes",[typeof K==="undefined"?Object:K,typeof B==="undefined"?Object:B,typeof M==="undefined"?Object:M,typeof C==="undefined"?Object:C,typeof J==="undefined"?Object:J])],W);import{Controller as Cs,Get as me,Post as Me,Put as Hs,Delete as Ce,Params as X,Body as nt,t as R}from"najm-api";import{isAdmin as b,isAuth as ot}from"@/roles/RoleGuards";class ye{userService;constructor(e){this.userService=e}async getUsers(){return{data:await this.userService.getAll(),message:R("users.success.retrieved"),status:"success"}}async getLang(){return{data:{language:await this.userService.getLang()},message:R("users.success.retrieved"),status:"success"}}async updateLang(e){return{data:await this.userService.updateLang(e),message:R("users.success.updated"),status:"success"}}async getUser(e){return{data:await this.userService.getById(e),message:R("users.success.retrieved"),status:"success"}}async getByEmail(e){return{data:await this.userService.getByEmail(e),message:R("users.success.retrieved"),status:"success"}}async getRole(e){return{data:await this.userService.getRoleName(e),message:R("users.success.retrieved"),status:"success"}}async create(e){return{data:await this.userService.create(e),message:R("users.success.created"),status:"success"}}async update(e,t){return{data:await this.userService.update(e,t),message:R("users.success.updated"),status:"success"}}async delete(e){return{data:await this.userService.delete(e),message:R("users.success.deleted"),status:"success"}}async deleteAll(){return{data:await this.userService.deleteAll(),message:R("users.success.allDeleted"),status:"success"}}async assignRole(e,t){return await this.userService.assignRole(e,t),{message:R("users.success.updated"),status:"success"}}async removeRole(e){return await this.userService.removeRole(e),{message:R("users.success.updated"),status:"success"}}}n([me(),b(),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],ye.prototype,"getUsers",null),n([me("/lang"),ot(),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],ye.prototype,"getLang",null),n([Me("/lang/:language"),ot(),u(0,X("language")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"updateLang",null),n([me("/:id"),b(),u(0,X("id")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"getUser",null),n([me("/email/:email"),b(),u(0,X("email")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"getByEmail",null),n([me("/role/:userId"),b(),u(0,X("userId")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"getRole",null),n([Me(),b(),u(0,nt()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"create",null),n([Hs("/:id"),b(),u(0,X("id")),u(1,nt()),r("design:type",Function),r("design:paramtypes",[Object,Object]),r("design:returntype",Promise)],ye.prototype,"update",null),n([Ce("/:id"),b(),u(0,X("id")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"delete",null),n([Ce(),b(),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],ye.prototype,"deleteAll",null),n([Me("/assign/:userId/:roleId"),b(),u(0,X("userId")),u(1,X("roleId")),r("design:type",Function),r("design:paramtypes",[Object,Object]),r("design:returntype",Promise)],ye.prototype,"assignRole",null),n([Ce("/remove/:userId"),b(),u(0,X("userId")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ye.prototype,"removeRole",null),ye=n([Cs("/users"),r("design:paramtypes",[typeof W==="undefined"?Object:W])],ye);class F{tokenService;userService;userValidator;cookieService;constructor(e,t,a,i){this.tokenService=e;this.userService=t;this.userValidator=a;this.cookieService=i}async registerUser(e){return await this.userService.create(e)}async loginUser(e){let{email:t,password:a}=e;if(!t||!a)throw new Error(ct("auth.errors.invalidCredentials"));let i=await this.userService.getPassword(t),{id:l}=await this.userService.getByEmail(t);await this.userValidator.checkPasswordValid(a,i);let c=await this.tokenService.generateTokens(l);return this.cookieService.setRefreshCookie(c.refreshToken),c}async refreshTokens(){let e=await this.tokenService.refreshTokens();return this.cookieService.setRefreshCookie(e.refreshToken),e}async logoutUser(e){return await this.userValidator.checkUserExists(e),await this.tokenService.revokeToken(e),this.cookieService.clearRefreshCookie(),{data:null,message:ct("auth.success.logout")}}async getUserProfile(e){let t=Xs();return{...e,language:t}}async forgotPassword(e){}}F=n([Ws(),r("design:paramtypes",[typeof A==="undefined"?Object:A,typeof W==="undefined"?Object:W,typeof C==="undefined"?Object:C,typeof G==="undefined"?Object:G])],F);import{isAuth as ut}from"@/roles/RoleGuards";class de{authService;constructor(e){this.authService=e}async registerUser(e){return{data:await this.authService.registerUser(e),message:ne("auth.success.register"),status:"success"}}async loginUser(e){return{data:await this.authService.loginUser(e),message:ne("auth.success.login"),status:"success"}}async refreshTokens(){return{data:await this.authService.refreshTokens(),message:ne("auth.success.tokenRefreshed"),status:"success"}}async logoutUser(e){return{data:await this.authService.logoutUser(e),message:ne("auth.success.logout"),status:"success"}}async userProfile(e){return{data:await this.authService.getUserProfile(e),message:ne("users.success.retrieved"),status:"success"}}async forgotPassword(e){return{data:await this.authService.forgotPassword(e.email),message:ne("auth.success.passwordReset"),status:"success"}}}n([We("/register"),u(0,Xe()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],de.prototype,"registerUser",null),n([We("/login"),u(0,Xe()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],de.prototype,"loginUser",null),n([He("/refresh"),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],de.prototype,"refreshTokens",null),n([He("/logout/:id"),u(0,Qs("id")),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],de.prototype,"logoutUser",null),n([He("/me"),ut(),u(0,Zs()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],de.prototype,"userProfile",null),n([We("/forgot-password"),ut(),u(0,Xe()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],de.prototype,"forgotPassword",null),de=n([Ds("/auth"),r("design:paramtypes",[typeof F==="undefined"?Object:F])],de);var Ue={userType:{values:["admin","teacher","student","parent"],translationKey:"enums.userType"},userStatus:{values:["active","inactive","pending"],translationKey:"enums.userStatus"},tokenStatus:{values:["active","revoked","expired"],translationKey:"enums.tokenStatus"},tokenType:{values:["access","refresh"],translationKey:"enums.tokenType"},fileStatus:{values:["active","deleted","archived"],translationKey:"enums.fileStatus"},gender:{values:["M","F"],translationKey:"common.gender"},studentStatus:{values:["active","inactive","graduated","transferred"],translationKey:"students.status"},teacherStatus:{values:["active","inactive","onLeave"],translationKey:"teachers.status"},employmentType:{values:["fullTime","partTime","contract","temporary"],translationKey:"teachers.employmentType"},relationshipType:{values:["father","mother","guardian","stepparent","grandparent","other"],translationKey:"parents.relationships"},semester:{values:["spring","summer","fall","winter"],translationKey:"academic.semester"},classStatus:{values:["active","completed","cancelled"],translationKey:"classes.status"},sectionStatus:{values:["active","inactive","archived"],translationKey:"sections.status"},language:{values:["en","fr","ar","es"],translationKey:"common.languages"},enrollmentStatus:{values:["enrolled","completed","dropped","failed"],translationKey:"enrollments.status"},assignmentStatus:{values:["active","completed","cancelled"],translationKey:"assignments.status"},calendarSystem:{values:["SEMESTER","TRIMESTER","QUARTER"],translationKey:"settings.calendarSystem"},assessmentType:{values:["quiz","assignment","project","participation","test","presentation"],translationKey:"assessments.type"},assessmentStatus:{values:["scheduled","active","completed","cancelled"],translationKey:"assessments.status"},submissionType:{values:["online","paper","presentation","practical","discussion"],translationKey:"assessments.submissionType"},examType:{values:["midterm","final","standardized"],translationKey:"exams.type"},examSecurity:{values:["low","medium","high"],translationKey:"exams.security"},examStatus:{values:["scheduled","active","completed","cancelled","rescheduled"],translationKey:"exams.status"},gradeStatus:{values:["graded","pending","draft","reviewed"],translationKey:"grades.status"},attendanceStatus:{values:["present","absent","late","excused"],translationKey:"attendance.status"},proficiencyLevel:{values:["beginner","intermediate","advanced","expert"],translationKey:"common.proficiencyLevel"},dayOfWeek:{values:["monday","tuesday","wednesday","thursday","friday","saturday","sunday"],translationKey:"common.days"},alertType:{values:["academic","attendance","behavioral","health","system","announcement","reminder","emergency"],translationKey:"alerts.type"},alertPriority:{values:["low","medium","high","critical"],translationKey:"alerts.priority"},alertStatus:{values:["active","acknowledged","resolved","dismissed"],translationKey:"alerts.status"},feeTypeStatus:{values:["active","inactive","archived"],translationKey:"fees.typeStatus"},feeCategory:{values:["tuition","registration","transport","cafeteria","books","sports","uniform","technology","fieldtrip","other"],translationKey:"feeTypes.category"},paymentType:{values:["recurring","oneTime"],translationKey:"payments.type"},schedule:{values:["monthly","quarterly","semester","annually","oneTime"],translationKey:"fees.schedule"},feeStatus:{values:["pending","partiallyPaid","paid","overdue"],translationKey:"fees.status"},feeInstallmentStatus:{values:["pending","partiallyPaid","paid","overdue"],translationKey:"fees.installmentStatus"},paymentMethod:{values:["cash","bankTransfer","check","creditCard","debitCard","online","mobilePayment"],translationKey:"payments.methods"},paymentStatus:{values:["completed","pending","failed","refunded"],translationKey:"payments.status"},eventType:{values:["academic","sports","cultural","holiday","exam","meeting","workshop","fieldtrip","ceremony","conference","other"],translationKey:"events.type"},eventStatus:{values:["scheduled","ongoing","completed","cancelled","postponed"],translationKey:"events.status"},eventVisibility:{values:["public","private","teachers","students","parents","staff"],translationKey:"events.visibility"},participantType:{values:["student","teacher","parent","staff"],translationKey:"events.participantType"},expenseCategory:{values:["salary","utilities","maintenance","supplies","equipment","transport","food","security","cleaning","insurance","rent","tax","marketing","training","technology","miscellaneous"],translationKey:"expenses.categories"},expenseStatus:{values:["pending","approved","paid","rejected","cancelled"],translationKey:"expenses.status"},trackerMode:{values:["tracking","gprs","sms","sleepTime","sleepShock","sleepDeep"],translationKey:"tracker.mode"},driverStatus:{values:["active","inactive","onLeave","suspended"],translationKey:"transport.driverStatus"},vehicleStatus:{values:["active","inactive","maintenance","retired"],translationKey:"transport.vehicleStatus"},vehicleType:{values:["sedan","minibus","fullbus","shuttle"],translationKey:"transport.vehicleType"},vehicleDocumentType:{values:["insurance","registration","inspection","emission","license"],translationKey:"transport.documentType"},busStatus:{values:["active","inactive","maintenance","retired"],translationKey:"transport.busStatus"},refuelStatus:{values:["pending","completed","cancelled"],translationKey:"transport.refuelStatus"},fuelType:{values:["gasoline","diesel","electric","hybrid","lpg","cng"],translationKey:"transport.fuelType"},maintenanceType:{values:["scheduled","repair","inspection","oilChange","filterChange","other"],translationKey:"transport.maintenanceType"},maintenanceStatus:{values:["scheduled","inProgress","completed","cancelled","overdue"],translationKey:"transport.maintenanceStatus"},maritalStatus:{values:["single","married","divorced","widowed","separated"],translationKey:"parents.maritalStatus"}},Ji=(e)=>Ue[e],Mi=(e)=>Ue[e]?.values||[];import{z as s}from"zod";import{z as js}from"zod";var o=(e)=>{let t=Ue[e]?.values;if(!t)throw new Error(`Enum ${e} not found`);return js.enum(t)},Xi=o("userType"),pt=o("userStatus"),Di=o("tokenStatus"),Qi=o("tokenType"),Zi=o("fileStatus"),he=o("gender"),lt=o("studentStatus"),mt=o("teacherStatus"),yt=o("employmentType"),dt=o("relationshipType"),ji=o("semester"),Li=o("classStatus"),ht=o("sectionStatus"),gt=o("language"),Yi=o("enrollmentStatus"),Gi=o("assignmentStatus"),ft=o("calendarSystem"),wt=o("assessmentType"),xt=o("assessmentStatus"),Oi=o("submissionType"),vt=o("examType"),qi=o("examSecurity"),kt=o("examStatus"),Tt=o("gradeStatus"),De=o("attendanceStatus"),Fi=o("proficiencyLevel"),zi=o("dayOfWeek"),St=o("alertType"),Et=o("alertPriority"),Ut=o("alertStatus"),Rt=o("feeTypeStatus"),Nt=o("paymentType"),Kt=o("schedule"),At=o("feeStatus"),Bt=o("feeInstallmentStatus"),ge=o("paymentMethod"),Pt=o("paymentStatus"),It=o("eventType"),Vt=o("eventStatus"),bt=o("eventVisibility"),_t=o("participantType"),$t=o("expenseCategory"),Jt=o("expenseStatus"),en=o("trackerMode"),Mt=o("driverStatus"),Ct=o("vehicleStatus"),Ht=o("vehicleType"),tn=o("vehicleDocumentType"),sn=o("busStatus"),Wt=o("refuelStatus"),Xt=o("fuelType"),rn=o("maintenanceType"),an=o("maintenanceStatus"),nn=o("maritalStatus");var h=s.preprocess((e)=>e??"",s.string().min(1,"ID is required")),m=s.string().min(1,"ID cannot be empty").nullish().optional(),oe=s.string().email("Invalid email format").or(s.literal("")),z=s.string().regex(/^[\+]?[1-9][\d]{0,15}$/,"Invalid phone number"),D=s.string().min(2,"Name must be at least 2 characters").max(100,"Name too long"),x=s.string().regex(/^(\d{4}-\d{2}-\d{2}|\d{2}\/\d{2}\/\d{4}|\d{2}-\d{2}-\d{2}|\d{2}-\d{2}-\d{4})$/,"Date must be in YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MM-YY, or DD-MM-YYYY format"),Q=s.string().regex(/^\d{4}-\d{2}-\d{2}$/,"Date must be in YYYY-MM-DD format").nullable().optional(),Re=s.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/,"Time must be in HH:MM format").optional().nullable(),Qe=s.string().min(8,"CIN must be at least 8 characters").max(20,"CIN too long"),Ne=s.string().max(500,"Address too long").optional(),Ze=s.string().min(9,"Academic year is required").regex(/^\d{4}-\d{4}$/,"Academic year must be in YYYY-YYYY format"),p=()=>{let e=(i)=>{return Object.assign(i,{positive:(c="Must be positive")=>e(i.refine((d)=>d>0,{message:c})),min:(c,d)=>e(i.refine((E)=>E>=c,{message:d||`Must be at least ${c}`})),max:(c,d)=>e(i.refine((E)=>E<=c,{message:d||`Cannot exceed ${c}`})),int:(c="Must be an integer")=>e(i.refine((d)=>Number.isInteger(d),{message:c}))})},t=(i)=>{if(i===null||i===void 0||Number.isNaN(i))return!1;if(typeof i==="number")return!0;if(typeof i==="string"){let l=i.trim();return l!==""&&!isNaN(Number(l))}return!1},a=s.any().refine(t,{message:"Must be a valid number"}).transform((i)=>typeof i==="string"?Number(i):i);return e(a)},pn=s.object({id:m,username:D.max(50).optional(),email:oe,password:s.string().min(8,"Password must be at least 8 characters"),roleId:m,roleName:D.max(50).optional(),lastLogin:Q,image:s.union([s.string(),s.instanceof(File),s.undefined()]).optional(),emailVerified:s.boolean().default(!1),status:pt,createdAt:Q}),ln=s.object({id:m,name:D.max(50),description:s.string().max(255,"Description too long").optional(),createdAt:Q}),Ls=s.object({id:m,classId:h,sectionId:h,studentCode:s.string(),name:D,email:oe,phone:z.nullish(),address:Ne,dateOfBirth:Q,gender:he,enrollmentDate:x,medicalConditions:s.string().max(1000,"Medical conditions description too long").nullish().optional(),previousSchool:s.string().max(500,"Previous school name too long").optional().nullable(),image:s.union([s.string(),s.instanceof(File),s.null()]).optional(),status:lt.default("active")}),Ys=s.object({id:m,name:D,email:oe.optional(),phone:z,gender:he.optional(),address:Ne,dateOfBirth:Q,cin:Qe,occupation:s.string().max(100,"Occupation too long").optional(),nationality:s.string().max(100,"Nationality too long").optional(),maritalStatus:s.string().max(50,"Marital status too long").optional(),relationshipType:dt,image:s.union([s.string(),s.instanceof(File),s.null()]).optional(),isEmergencyContact:s.boolean().optional().default(!1),financialResponsibility:s.boolean().optional().default(!1)}),mn=s.object({id:m,name:D,email:oe,cin:Qe,phone:z,address:Ne,gender:he.optional(),licenseNumber:s.string().min(5,"License number must be at least 5 characters").max(20,"License number too long"),licenseType:s.string().max(10,"License type too long"),licenseExpiry:x,hireDate:x,salary:p().positive("Salary must be positive").optional(),yearsOfExperience:p().int().min(0,"Years of experience must be non-negative").optional(),emergencyContact:D.optional(),emergencyPhone:z.optional(),image:s.union([s.string(),s.instanceof(File),s.null()]).optional(),status:Mt.default("active"),notes:s.string().max(1000,"Notes too long").optional().nullable()}),Gs=s.object({id:m,name:D,cin:Qe,email:oe,phone:z,address:Ne,gender:he.optional(),emergencyContact:D.optional(),emergencyPhone:z,status:mt.default("active"),image:s.union([s.string(),s.instanceof(File),s.null()]).optional()}),Os=s.object({specialization:s.string().max(100,"Specialization too long").optional(),yearsOfExperience:p().int().min(0,"Years of experience must be non-negative").optional(),salary:p().positive("Salary must be positive").optional(),hireDate:x,bankAccount:s.coerce.string().max(100,{message:"Bank account too long"}).optional(),employmentType:yt.optional(),workloadHours:p().int().min(0,"Workload hours must be non-negative").max(60,"Workload hours cannot exceed 60").optional(),academicDegrees:s.string().max(500,"Academic degrees description too long").optional()}),qs=s.object({classId:s.string().min(1,"Class is required"),sectionIds:s.array(s.string()).min(1,"At least one section is required"),subjectIds:s.array(s.string()).min(1,"At least one subject is required"),academicYear:s.string().optional()}),Fs=s.object({assignments:s.array(qs).min(1,"At least one parent is required")}),yn=s.object({...Gs.shape,...Os.shape,...Fs.shape}),dn=s.object({id:m,name:s.string().min(2,"Fee type name must be at least 2 characters").max(100,"Fee type name too long"),description:s.string().max(500,"Description too long").optional().nullable(),category:s.string(),amount:p().positive("Amount must be greater than 0").max(1e5,"Amount too large"),paymentType:Nt.default("recurring"),status:Rt.default("active").optional()}),zs=s.object({id:m,studentId:h,feeTypeId:h,academicYear:Ze.optional(),status:At.optional(),schedule:Kt,baseAmount:p().positive("Base amount must be positive").optional(),grossAmount:p().positive("Gross amount must be positive").optional(),netAmount:p().optional(),paidAmount:p().min(0,"Paid amount cannot be negative").optional(),discountAmount:p().min(0,"Discount cannot be negative").optional(),discountReason:s.string().max(500,"Discount reason too long").optional().nullable(),assignedBy:m.nullable(),notes:s.string().max(1000,"Notes too long").optional().nullable()}),Dt=zs.omit({studentId:!0}),hn=s.object({studentId:h,fees:s.array(Dt).min(1,"At least one fee is required")}),gn=s.object({feeId:m,number:p().int().min(1,"Installment must be at least 1"),dueDate:x,amount:p().positive("Amount must be greater than 0").max(1e5,"Amount too large"),paidAmount:p().min(0,"Paid amount cannot be negative").max(1e5,"Amount too large").optional(),status:Bt.optional()}),fn=s.object({studentId:m,amount:p().positive("Amount must be greater than 0").max(1e5,"Amount too large").optional(),paymentMethod:ge,paymentDate:x,checkNumber:s.preprocess((e)=>e===""?null:e,s.string().max(50,"Check number too long").optional().nullable()),checkDueDate:s.preprocess((e)=>e===""?null:e,Q.nullable()),transactionRef:s.preprocess((e)=>e===""?null:e,s.string().max(100,"Transaction reference too long").optional().nullable()),receiptNumber:s.preprocess((e)=>e===""?null:e,s.string().max(50,"Receipt number too long").optional().nullable()),status:Pt.default("completed"),processedBy:m,notes:s.preprocess((e)=>e===""?null:e,s.string().max(1000,"Notes too long").optional().nullable()),allocations:s.array(s.object({feeId:m,number:s.number().int().positive("Installment must be a positive number"),amount:p().positive("Amount must be greater than 0")})).optional().nullable()}),wn=s.object({paymentId:s.string().min(1,"Payment ID is required"),feeId:s.string().min(1,"Fee ID is required"),installmentId:s.string().optional(),amount:s.number().positive("Amount must be positive"),type:s.enum(["fee","installment"]).default("installment"),notes:s.string().optional()}),er=s.object({parents:s.array(Ys).optional().default([])}),tr=s.object({fees:s.array(Dt).min(1,"At least one fee is required")}),xn=s.object({...Ls.shape,...er.shape,...tr.shape}),vn=s.object({id:m,code:s.string().min(2,"Subject code must be at least 2 characters").max(10,"Subject code too long"),name:s.string().min(2,"Subject name must be at least 2 characters").max(100,"Subject name too long"),description:s.string().max(500,"Description too long").optional(),gradeLevel:p().int().min(1).max(12).optional()}),kn=s.object({id:m,classId:h,name:s.string().min(1,"Section name is required").max(10,"Section name too long"),maxStudents:p().int().min(1,"Max students must be at least 1").max(100,"Max students cannot exceed 100").default(30),roomNumber:p().max(1e4,"Room number too long").optional(),status:ht.default("active")}),Tn=s.object({id:m,name:s.string().min(1,"Class name is required").max(50,"Class name too long"),description:s.string().max(500,"Description too long").optional(),academicYear:Ze,level:s.string().min(1,"Class level is required")}),Sn=s.object({studentId:h,teacherId:h,subjectId:h,sectionId:h,date:x,status:De.default("present"),notes:s.string().max(500,"Notes too long").optional()}),sr=s.object({classId:h,sectionId:h,subjectId:h,teacherId:h,teacherAssignmentId:m,title:s.string().min(3,"Title must be at least 3 characters").max(200,"Title too long"),description:s.string().max(1000,"Description too long").optional().nullable(),type:wt.default("quiz"),date:x,duration:p().int().min(1,"Duration must be at least 1 minute").max(480,"Duration cannot exceed 8 hours"),totalMarks:p().positive("Total marks must be greater than 0").max(1000,"Total marks cannot exceed 1000"),passingMarks:p().min(0,"Passing marks must be non-negative").max(1000,"Passing marks cannot exceed 1000"),instructions:s.string().max(2000,"Instructions too long").optional().nullable(),status:xt.default("scheduled"),assessmentId:m}),En=s.object({assessments:s.array(sr).min(1,"At least one assessment is required").max(50,"Cannot create more than 50 assessments at once")}),Un=s.object({assessmentId:h,teacherId:h,subjectId:h,sectionId:h,studentId:h,gradeId:h,assessmentTitle:s.string().min(3,"Assessment title must be at least 3 characters").max(200,"Assessment title too long").optional(),marksObtained:p().min(0,"Marks obtained must be non-negative").max(1000,"Marks obtained cannot exceed 1000"),feedback:s.string().max(1000,"Feedback too long").optional().nullable(),status:Tt.default("graded")}),Rn=s.object({classId:m,sectionId:h,subjectId:h,teacherId:h,examId:h,teacherAssignmentId:h,title:s.string().min(3,"Title must be at least 3 characters").max(200,"Title too long"),description:s.string().max(1000,"Description too long").optional().nullable(),type:vt.default("midterm"),date:x,startTime:Re,endTime:Re,duration:p().int().min(30,"Exam duration must be at least 30 minutes").max(480,"Duration cannot exceed 8 hours"),totalMarks:p().positive("Total marks must be greater than 0").max(1000,"Total marks cannot exceed 1000"),passingMarks:p().min(0,"Passing marks must be non-negative").max(1000,"Passing marks cannot exceed 1000"),roomNumber:p().max(50,"Room number too long").optional().nullable(),allowedMaterials:s.string().max(500,"Allowed materials description too long").optional().nullable(),instructions:s.string().max(2000,"Instructions too long").optional().nullable(),status:kt.default("scheduled")}),Nn=s.object({title:s.string().min(3,"Title must be at least 3 characters").max(200,"Title too long"),content:s.string().min(10,"Content must be at least 10 characters").max(5000,"Content too long"),authorId:m,targetAudience:s.enum(["all","students","teachers","parents","class"]),classId:m,isPublished:s.boolean().default(!1),publishDate:s.string().datetime("Invalid publish date").optional(),expiryDate:s.string().datetime("Invalid expiry date").optional()}),Kn=s.object({type:St,title:s.string().min(3,"Title must be at least 3 characters").max(200,"Title too long"),message:s.string().min(10,"Message must be at least 10 characters").max(2000,"Message too long"),priority:Et.default("medium"),status:Ut.default("active"),studentId:m,teacherId:m,classId:m,subjectId:m,targetAudience:s.enum(["all","students","teachers","parents"]).optional(),authorId:m,isRead:s.boolean().default(!1)}),An=s.object({title:s.string().min(3,"Title must be at least 3 characters").max(200,"Title too long"),description:s.string().max(5000,"Description too long").optional().nullable(),type:It,startDate:x,endDate:x,startTime:Re,endTime:Re,location:s.string().max(200,"Location too long").optional().nullable(),venue:s.string().max(200,"Venue too long").optional().nullable(),organizerId:m,classId:m.nullable(),sectionId:m.nullable(),visibility:bt.default("public"),status:Vt.default("scheduled"),capacity:p().int().positive("Capacity must be positive").optional().nullable(),registrationRequired:s.boolean().default(!1),registrationDeadline:Q.nullable(),attachments:s.any().optional().nullable(),notes:s.string().max(2000,"Notes too long").optional().nullable()}),Bn=s.object({eventId:m,participantId:m,participantType:_t,attendanceStatus:De.optional().nullable(),notes:s.string().max(500,"Notes too long").optional().nullable()}),Pn=s.object({id:m,category:$t,title:s.string().min(3,"Title must be at least 3 characters").max(200,"Title too long"),amount:p().positive("Amount must be greater than 0").max(1e7,"Amount too large"),expenseDate:x,paymentMethod:ge.optional().nullable(),paymentDate:Q.nullable(),vendor:s.string().max(200,"Vendor name too long").optional().nullable(),invoiceNumber:s.string().max(100,"Invoice number too long").optional().nullable(),receiptNumber:s.string().max(100,"Receipt number too long").optional().nullable(),checkNumber:s.string().max(50,"Check number too long").optional().nullable(),transactionRef:s.string().max(100,"Transaction reference too long").optional().nullable(),status:Jt.default("pending"),notes:s.string().max(1000,"Notes too long").optional().nullable()}),In=s.object({action:s.enum(["approve","reject"]),rejectionReason:s.string().min(10,"Rejection reason must be at least 10 characters").max(1000,"Rejection reason too long").optional().nullable()}),Vn=s.object({paymentMethod:ge,paymentDate:x,checkNumber:s.string().max(50,"Check number too long").optional().nullable(),transactionRef:s.string().max(100,"Transaction reference too long").optional().nullable(),notes:s.string().max(1000,"Notes too long").optional().nullable()}),bn=s.object({id:m,name:s.string().min(2,"Vehicle name must be at least 2 characters").max(100,"Vehicle name too long"),brand:s.string().min(2,"Brand must be at least 2 characters").max(100,"Brand too long"),model:s.string().min(2,"Model must be at least 2 characters").max(100,"Model too long"),year:p().int().min(1900,"Year must be after 1900").max(new Date().getFullYear()+1,"Year cannot be in future"),type:Ht.default("fullbus"),capacity:p().int().min(1,"Capacity must be at least 1").max(200,"Capacity cannot exceed 200"),licensePlate:s.string().min(2,"License plate must be at least 2 characters").max(50,"License plate too long"),driverId:m.nullable(),image:s.string().max(500,"Image path too long").optional().nullable().default("novehicle.png"),purchaseDate:Q.nullable(),purchasePrice:p().min(0,"Purchase price must be non-negative").max(1e7,"Purchase price too large").optional().nullable(),initialMileage:p().min(0,"Initial mileage must be non-negative").max(1e7,"Initial mileage too large").optional().nullable(),currentMileage:p().min(0,"Current mileage must be non-negative").max(1e7,"Current mileage too large").optional().nullable(),status:Ct.default("active"),notes:s.string().max(1000,"Notes too long").optional().nullable()}),_n=s.object({id:m,busId:m,refuelDate:x,quantity:p().positive("Quantity must be greater than 0").max(1e4,"Quantity too large"),unitPrice:p().positive("Unit price must be greater than 0").max(1e5,"Unit price too large"),totalCost:p().positive("Total cost must be greater than 0").max(1e7,"Total cost too large").optional(),fuelType:Xt.default("diesel"),odometer:p().min(0,"Odometer must be non-negative").max(1e7,"Odometer value too large").optional().nullable(),fuelStation:s.string().max(200,"Fuel station name too long").optional().nullable(),invoiceNumber:s.string().max(100,"Invoice number too long").optional().nullable(),paymentMethod:ge.optional().nullable(),paidBy:m.nullable(),status:Wt.default("completed"),notes:s.string().max(1000,"Notes too long").optional().nullable()}),$n=s.object({schoolName:s.string().min(2,"School name must be at least 2 characters").max(200,"School name too long"),schoolAddress:s.string().max(500,"School address too long").optional(),schoolPhone:z,schoolEmail:oe,schoolWebsite:s.string().url("Must be a valid URL").max(255,"School website URL too long").optional(),schoolLogo:s.string().url("Must be a valid image URL").max(255,"School logo URL too long").optional(),currentAcademicYear:Ze,gradingScale:s.any().optional(),attendanceRequirement:p().min(0,"Attendance requirement must be non-negative").max(100,"Attendance requirement cannot exceed 100").default(75),maxClassSize:p().int("Max class size must be an integer").min(1,"Max class size must be at least 1").max(200,"Max class size cannot exceed 200").default(34),minimumPassingGrade:p().min(0,"Minimum passing grade must be non-negative").max(100,"Minimum passing grade cannot exceed 100").default(60),defaultExamDuration:p().int("Default exam duration must be in minutes").min(15,"Exam duration must be at least 15 minutes").max(480,"Exam duration cannot exceed 480 minutes").default(120),calendarSystem:ft.default("SEMESTER"),startMonth:s.string().default("september"),endMonth:s.string().default("june"),academicAlerts:s.boolean().default(!0),attendanceAlerts:s.boolean().default(!0),eventAlerts:s.boolean().default(!0),homeworkAlerts:s.boolean().default(!0),feesReminder:s.boolean().default(!0),feesOverdueAlerts:s.boolean().default(!0),emailNotifications:s.boolean().default(!0),smsNotifications:s.boolean().default(!1),parentNotifications:s.boolean().default(!0),lowGradeAlerts:s.boolean().default(!0),allowLateSubmission:s.boolean().default(!0),examResultsAlerts:s.boolean().default(!0),disciplinaryAlerts:s.boolean().default(!0),achievementAlerts:s.boolean().default(!0),maintenanceNotifications:s.boolean().default(!0),twoFactorEnabled:s.boolean().default(!1),sessionTimeout:s.string().regex(/^\d{1,4}$/,"Session timeout must be a number between 1-9999 minutes").default("60"),passwordRequireSymbols:s.boolean().default(!0),loginNotifications:s.boolean().default(!0),parentAccessEnabled:s.boolean().default(!0),teacherAccessEnabled:s.boolean().default(!0),studentAccessEnabled:s.boolean().default(!0),timeZone:s.string().min(1,"Time zone is required").default("UTC"),language:gt.default("en"),theme:s.enum(["light","dark","system"]).default("system"),dateFormat:s.enum(["YYYY-MM-DD","MM/DD/YYYY","DD/MM/YYYY","DD-MM-YY","DD-MM-YYYY"]).default("MM/DD/YYYY"),timeFormat:s.enum(["12","24"]).default("12"),currency:s.string().length(3,"Currency must be a 3-letter ISO code").regex(/^[A-Z]{3}$/,"Currency must be uppercase ISO code").default("USD"),gradingPeriods:p().int("Grading periods must be an integer").min(1,"Grading periods must be at least 1").max(12,"Grading periods cannot exceed 12").default(4),schoolStartTime:s.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/,"Invalid start time format (HH:MM)").default("08:00"),schoolEndTime:s.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/,"Invalid end time format (HH:MM)").default("15:00"),lunchBreakDuration:p().int("Lunch break duration must be in minutes").min(15,"Lunch break must be at least 15 minutes").max(120,"Lunch break cannot exceed 120 minutes").default(30),maintenanceMode:s.boolean().default(!1),autoBackup:s.boolean().default(!0)}),Jn=s.object({id:m}),Mn=s.object({page:p().int().min(1).default(1),limit:p().int().min(1).max(100).default(10)}),Cn=s.object({dateFrom:x,dateTo:x});import{permissionsTable as w,rolePermissionsTable as S,rolesTable as fe}from"@/database/schema";import{eq as N,and as Qt}from"drizzle-orm";import{Repository as rr}from"najm-api";class _{async getAll(){return await this.db.select().from(w)}async getById(e){let[t]=await this.db.select().from(w).where(N(w.id,e));return t}async getByName(e){let[t]=await this.db.select().from(w).where(N(w.name,e));return t}async create(e){let[t]=await this.db.insert(w).values(e).returning();return t}async update(e,t){let[a]=await this.db.update(w).set(t).where(N(w.id,e)).returning();return a}async delete(e){let[t]=await this.db.delete(w).where(N(w.id,e)).returning();return t}async getPermissionsByRole(e){return await this.db.select({id:w.id,name:w.name,description:w.description,resource:w.resource,action:w.action}).from(S).leftJoin(w,N(S.permissionId,w.id)).where(N(S.roleId,e))}async getRolesByPermission(e){return await this.db.select({id:fe.id,name:fe.name,description:fe.description}).from(S).leftJoin(fe,N(S.roleId,fe.id)).where(N(S.permissionId,e))}async assignPermissionToRole(e,t){let[a]=await this.db.insert(S).values({roleId:e,permissionId:t}).returning();return a}async removePermissionFromRole(e,t){let[a]=await this.db.delete(S).where(Qt(N(S.roleId,e),N(S.permissionId,t))).returning();return a}async checkRoleHasPermission(e,t){let[a]=await this.db.select().from(S).where(Qt(N(S.roleId,e),N(S.permissionId,t)));return!!a}async deleteAll(){return await this.db.delete(S),await this.db.delete(w).returning()}}_=n([rr()],_);import{createGuard as ar,Injectable as ir,GuardParams as nr,Headers as or,Ctx as cr}from"najm-api";class ee{tokenService;constructor(e){this.tokenService=e}async getUserPermissions(e){let t=await this.tokenService.getUserPermissions(e);if(!t||!Array.isArray(t))return null;return t}checkPermissionMatch(e,t){if(e.includes(t))return!0;let[a,i]=t.split(":");if(a&&i){if(e.includes(`${a}:*`))return!0;if(e.includes(`*:${i}`))return!0}if(e.includes("*:*"))return!0;return!1}async hasPermission(e,t,a){await this.tokenService.storeUserInCache(e,t);let i=await this.getUserPermissions(e);if(!i)return!1;return this.checkPermissionMatch(i,a)}}n([u(0,or("authorization")),u(1,cr()),u(2,nr()),r("design:type",Function),r("design:paramtypes",[Object,Object,Object]),r("design:returntype",Object)],ee.prototype,"hasPermission",null),ee=n([ir(),r("design:paramtypes",[typeof A==="undefined"?Object:A])],ee);var ur=(...e)=>ar(ee,"hasPermission")(...e);import{Controller as dr,Get as Ae,Post as Zt,Put as hr,Delete as je,Params as Z,Body as jt,t as $}from"najm-api";import{Injectable as yr}from"najm-api";import{Injectable as pr,t as Ke}from"najm-api";import{parseSchema as lr}from"@/shared";import{z as we}from"zod";var mr=we.object({name:we.string().min(1,"Permission name is required"),description:we.string().optional(),resource:we.string().min(1,"Resource is required"),action:we.string().min(1,"Action is required")});class L{permissionRepository;roleValidator;constructor(e,t){this.permissionRepository=e;this.roleValidator=t}async validateCreatePermission(e){return lr(mr,e)}async isPermissionExists(e){return!!await this.permissionRepository.getById(e)}async isPermissionNameExists(e){return!!await this.permissionRepository.getByName(e)}async checkPermissionExists(e){let t=await this.isPermissionExists(e);if(!t)throw new Error(Ke("permissions.errors.notFound"));return t}async checkPermissionExistsByName(e){let t=await this.isPermissionNameExists(e);if(!t)throw new Error(Ke("permissions.errors.notFound"));return t}async checkPermissionNameUnique(e,t=null){if(!e)return;let a=await this.permissionRepository.getByName(e);if(a&&a.id!==t)throw new Error(Ke("permissions.errors.nameExists"))}async checkRoleExists(e){return await this.roleValidator.checkRoleExists(e)}async checkRoleExistsByName(e){return await this.roleValidator.checkRoleExistsByName(e)}async checkRoleHasPermission(e,t){if(await this.roleValidator.checkRoleExists(e),await this.checkPermissionExists(t),await this.permissionRepository.checkRoleHasPermission(e,t))throw new Error(Ke("permissions.errors.roleAlreadyHasPermission"))}}L=n([pr(),r("design:paramtypes",[typeof _==="undefined"?Object:_,typeof K==="undefined"?Object:K])],L);class Y{permissionRepository;permissionValidator;roleService;constructor(e,t,a){this.permissionRepository=e;this.permissionValidator=t;this.roleService=a}async getAll(){return await this.permissionRepository.getAll()}async getById(e){return await this.permissionValidator.checkPermissionExists(e),await this.permissionRepository.getById(e)}async getByName(e){return await this.permissionRepository.getByName(e)}async getByResource(e){return await this.permissionRepository.getAll().then((t)=>t.filter((a)=>a.resource===e))}async create(e){return await this.permissionValidator.validateCreatePermission(e),await this.permissionValidator.checkPermissionNameUnique(e.name),await this.permissionRepository.create(e)}async update(e,t){return await this.permissionValidator.checkPermissionExists(e),await this.permissionValidator.checkPermissionNameUnique(t.name,e),await this.permissionRepository.update(e,t)}async delete(e){return await this.permissionValidator.checkPermissionExists(e),await this.permissionRepository.delete(e)}async getPermissionsByRole(e){return await this.permissionRepository.getPermissionsByRole(e)}async getRolesByPermission(e){return await this.permissionValidator.checkPermissionExists(e),await this.permissionRepository.getRolesByPermission(e)}async assignPermissionToRole(e,t){return await this.permissionValidator.checkRoleHasPermission(e,t),await this.permissionRepository.assignPermissionToRole(e,t)}async removePermissionFromRole(e,t){return await this.permissionRepository.removePermissionFromRole(e,t)}async seedDefaultPermissions(e){let t=[];for(let a of e)try{let i=await this.create(a);t.push(i)}catch(i){continue}return t}async seedDefaultRolePermissions(e){let t=[];for(let{roleName:a,permissions:i}of e)try{await this.permissionValidator.checkRoleExistsByName(a);let l=await this.roleService.getByName(a);for(let c of i)try{await this.permissionValidator.checkPermissionExistsByName(c);let d=await this.getByName(c);await this.permissionValidator.checkRoleHasPermission(l.id,d.id),await this.assignPermissionToRole(l.id,d.id),t.push({role:a,permission:c})}catch(d){continue}}catch(l){continue}return t}async deleteAll(){return await this.permissionRepository.deleteAll()}}Y=n([yr(),r("design:paramtypes",[typeof _==="undefined"?Object:_,typeof L==="undefined"?Object:L,typeof B==="undefined"?Object:B])],Y);import{isAdmin as Lt}from"@/roles/RoleGuards";class ce{permissionService;constructor(e){this.permissionService=e}async getPermissions(){return{data:await this.permissionService.getAll(),message:$("permissions.success.retrieved"),status:"success"}}async getPermission(e){return{data:await this.permissionService.getById(e),message:$("permissions.success.retrieved"),status:"success"}}async create(e){return{data:await this.permissionService.create(e),message:$("permissions.success.created"),status:"success"}}async update(e,t){return{data:await this.permissionService.update(e,t),message:$("permissions.success.updated"),status:"success"}}async delete(e){return{data:await this.permissionService.delete(e),message:$("permissions.success.deleted"),status:"success"}}async getByRole(e){return{data:await this.permissionService.getPermissionsByRole(e),message:$("permissions.success.retrieved"),status:"success"}}async getRolesByPermission(e){return{data:await this.permissionService.getRolesByPermission(e),message:$("permissions.success.retrieved"),status:"success"}}async assignToRole(e,t){return{data:await this.permissionService.assignPermissionToRole(e,t),message:$("permissions.success.assigned"),status:"success"}}async removeFromRole(e,t){return{data:await this.permissionService.removePermissionFromRole(e,t),message:$("permissions.success.removed"),status:"success"}}async deleteAll(){return{data:await this.permissionService.deleteAll(),message:$("permissions.success.allDeleted"),status:"success"}}}n([Ae(),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],ce.prototype,"getPermissions",null),n([Ae("/:id"),u(0,Z("id")),r("design:type",Function),r("design:paramtypes",[String]),r("design:returntype",Promise)],ce.prototype,"getPermission",null),n([Zt(),u(0,jt()),r("design:type",Function),r("design:paramtypes",[Object]),r("design:returntype",Promise)],ce.prototype,"create",null),n([hr("/:id"),u(0,Z("id")),u(1,jt()),r("design:type",Function),r("design:paramtypes",[String,Object]),r("design:returntype",Promise)],ce.prototype,"update",null),n([je("/:id"),u(0,Z("id")),r("design:type",Function),r("design:paramtypes",[String]),r("design:returntype",Promise)],ce.prototype,"delete",null),n([Ae("/role/:roleId"),u(0,Z("roleId")),r("design:type",Function),r("design:paramtypes",[String]),r("design:returntype",Promise)],ce.prototype,"getByRole",null),n([Ae("/roles/:permissionId"),u(0,Z("permissionId")),r("design:type",Function),r("design:paramtypes",[String]),r("design:returntype",Promise)],ce.prototype,"getRolesByPermission",null),n([Zt("/assign/:roleId/:permissionId"),u(0,Z("roleId")),u(1,Z("permissionId")),r("design:type",Function),r("design:paramtypes",[String,String]),r("design:returntype",Promise)],ce.prototype,"assignToRole",null),n([je("/remove/:roleId/:permissionId"),u(0,Z("roleId")),u(1,Z("permissionId")),r("design:type",Function),r("design:paramtypes",[String,String]),r("design:returntype",Promise)],ce.prototype,"removeFromRole",null),n([je(),Lt(),r("design:type",Function),r("design:paramtypes",[]),r("design:returntype",Promise)],ce.prototype,"deleteAll",null),ce=n([dr("/permissions"),Lt(),r("design:paramtypes",[typeof Y==="undefined"?Object:Y])],ce);import*as Yt from"fs/promises";import*as Le from"path";import gr from"lodash.isempty";import{sql as v}from"drizzle-orm";var fr=Le.join(process.cwd(),"avatars"),Ao=async(e,t)=>{try{return await e.parseAsync(t)}catch(a){let l=(a.issues||a.errors||[]).map((c)=>`${c.path.join(".")}: ${c.message}`).join("; ");throw new Error(l)}},Bo=(e)=>{let t={};for(let[a,i]of Object.entries(e))if(i!==null&&i!==void 0&&i!=="")t[a]=i;return t},Po=async(e)=>{try{let t=Le.join(fr,e),a=await Yt.readFile(t);return new File([a],e,{type:"image/png"})}catch(t){return null}},Gt=(e)=>{if(!e)return null;let t;if(e instanceof Date)t=e;else if(typeof e==="string")t=new Date(e);else return null;if(isNaN(t.getTime()))return null;return t.toISOString().split("T")[0]};function Io(e){if(!e)return null;let t=Gt(e);if(!t)return null;let a=new Date(t),i=new Date,l=i.getFullYear()-a.getFullYear(),c=i.getMonth()-a.getMonth();if(c<0||c===0&&i.getDate()<a.getDate())l--;return l}function Vo(e){if(!e)return null;let t=Gt(e);if(!t)return null;let a=new Date(t),i=new Date,l=i.getFullYear()-a.getFullYear(),c=i.getMonth()-a.getMonth();if(c<0||c===0&&i.getDate()<a.getDate())l--;return l}function bo(e,t){let a={};for(let i of t)if(e[i]!==void 0)a[i]=e[i];return a}var _o=gr;function $o(e,t){let i=Object.entries(e).flatMap(([c,d])=>[v.raw(`'${c}'`),d]),l=v`json_agg(json_build_object(${v.join(i,v`, `)})`;if(t)l=v`${l} ORDER BY ${t}`;return l=v`${l})`,v`COALESCE(${l}, '[]'::json)`}function Jo(e,t,a,i){let c=Object.entries(e).flatMap(([E,ue])=>[v.raw(`'${E}'`),ue]),d=v`
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjXFxhdXRoXFxFbmNyeXB0aW9uU2VydmljZS50cyIsICJzcmNcXGF1dGhcXENvb2tpZVNlcnZpY2UudHMiLCAic3JjXFxhdXRoXFxBdXRoQ29udHJvbGxlci50cyIsICJzcmNcXGF1dGhcXEF1dGhTZXJ2aWNlLnRzIiwgInNyY1xcdXNlcnNcXFVzZXJSZXBvc2l0b3J5LnRzIiwgInNyY1xcdXNlcnNcXFVzZXJWYWxpZGF0b3IudHMiLCAic3JjXFx1c2Vyc1xcVXNlclNlcnZpY2UudHMiLCAic3JjXFxyb2xlc1xcUm9sZVJlcG9zaXRvcnkudHMiLCAic3JjXFxyb2xlc1xcUm9sZVZhbGlkYXRvci50cyIsICJzcmNcXHJvbGVzXFxSb2xlR3VhcmRzLnRzIiwgInNyY1xcdG9rZW5zXFxUb2tlblJlcG9zaXRvcnkudHMiLCAic3JjXFx0b2tlbnNcXFRva2VuU2VydmljZS50cyIsICJzcmNcXHJvbGVzXFxSb2xlQ29udHJvbGxlci50cyIsICJzcmNcXHJvbGVzXFxSb2xlU2VydmljZS50cyIsICJzcmNcXHVzZXJzXFxVc2VyQ29udHJvbGxlci50cyIsICJzcmNcXGxpYlxcRU5VTVMudHMiLCAic3JjXFxsaWJcXHZhbGlkYXRpb25zLnRzIiwgInNyY1xcbGliXFxab2RFbnVtLnRzIiwgInNyY1xccGVybWlzc2lvbnNcXFBlcm1pc3Npb25SZXBvc2l0b3J5LnRzIiwgInNyY1xccGVybWlzc2lvbnNcXFBlcm1pc3Npb25HdWFyZHMudHMiLCAic3JjXFxwZXJtaXNzaW9uc1xcUGVybWlzc2lvbkNvbnRyb2xsZXIudHMiLCAic3JjXFxwZXJtaXNzaW9uc1xcUGVybWlzc2lvblNlcnZpY2UudHMiLCAic3JjXFxwZXJtaXNzaW9uc1xcUGVybWlzc2lvblZhbGlkYXRvci50cyIsICJzcmNcXHNoYXJlZFxcaW5kZXgudHMiLCAic3JjXFxkYXRhYmFzZVxcZGIudHMiLCAic3JjXFxkYXRhYmFzZVxcc2NoZW1hXFxpbmRleC50cyIsICJzcmNcXGRhdGFiYXNlXFxzY2hlbWFcXFBnRW51bS50cyIsICJzcmNcXHBsdWdpbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICJcbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICduYWptLWFwaSc7XG5pbXBvcnQgYmNyeXB0IGZyb20gJ2JjcnlwdCdcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEVuY3J5cHRpb25TZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IoKSB7IH1cblxuICBhc3luYyBoYXNoUGFzc3dvcmQocGFzc3dvcmQpIHtcbiAgICBpZiAoIXBhc3N3b3JkKSByZXR1cm4gbnVsbDtcbiAgICBpZiAodHlwZW9mIHBhc3N3b3JkICE9PSAnc3RyaW5nJyB8fCBwYXNzd29yZC50cmltKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGJjcnlwdC5oYXNoKHBhc3N3b3JkLCAxMCk7XG4gIH1cblxuICBhc3luYyBjb21wYXJlUGFzc3dvcmQocGFzc3dvcmQsIGhhc2hlZFBhc3N3b3JkKSB7XG4gICAgcmV0dXJuIGJjcnlwdC5jb21wYXJlKHBhc3N3b3JkLCBoYXNoZWRQYXNzd29yZCk7XG4gIH1cblxufVxuIiwKICAgICJcbmltcG9ydCB7IHNldENvb2tpZSwgSW5qZWN0YWJsZSwgZGVsZXRlQ29va2llIH0gZnJvbSAnbmFqbS1hcGknO1xuaW1wb3J0IHRpbWVzdHJpbmcgZnJvbSAndGltZXN0cmluZyc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBDb29raWVTZXJ2aWNlIHtcblxuICBzZXRSZWZyZXNoQ29va2llKHJlZnJlc2hUb2tlbikge1xuICAgIGNvbnN0IG1heEFnZSA9IHRpbWVzdHJpbmcocHJvY2Vzcy5lbnYuUkVGUkVTSF9FWFBJUkVTX0lOLCAncycpOyAgLy8vICcxeSdcbiAgICBzZXRDb29raWUoJ3JlZnJlc2hUb2tlbicsIHJlZnJlc2hUb2tlbiwge1xuICAgICAgaHR0cE9ubHk6IGZhbHNlLFxuICAgICAgc2FtZVNpdGU6ICdMYXgnLFxuICAgICAgbWF4QWdlLFxuICAgICAgcGF0aDogJy9hcGkvYXV0aC9yZWZyZXNoJyxcbiAgICB9KVxuICB9XG5cbiAgY2xlYXJSZWZyZXNoQ29va2llKCk6IHZvaWQge1xuICAgIGRlbGV0ZUNvb2tpZSgncmVmcmVzaFRva2VuJywge1xuICAgICAgaHR0cE9ubHk6IGZhbHNlLFxuICAgICAgc2FtZVNpdGU6ICdMYXgnLFxuICAgICAgcGF0aDogJy9hcGkvYXV0aC9yZWZyZXNoJyxcbiAgICAgIG1heEFnZTogMFxuICAgIH0pO1xuICB9XG5cblxufVxuIiwKICAgICJpbXBvcnQgeyBDb250cm9sbGVyLCBHZXQsIFBvc3QsIFBhcmFtcywgQm9keSwgVXNlciwgdCB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9BdXRoU2VydmljZSc7XG5pbXBvcnQgeyBpc0F1dGggfSBmcm9tICdAL3JvbGVzL1JvbGVHdWFyZHMnO1xuXG5cbkBDb250cm9sbGVyKCcvYXV0aCcpXG5leHBvcnQgY2xhc3MgQXV0aENvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGF1dGhTZXJ2aWNlOiBBdXRoU2VydmljZSkgeyB9XG5cbiAgQFBvc3QoJy9yZWdpc3RlcicpXG4gIGFzeW5jIHJlZ2lzdGVyVXNlcihAQm9keSgpIGJvZHkpIHtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5hdXRoU2VydmljZS5yZWdpc3RlclVzZXIoYm9keSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBtZXNzYWdlOiB0KCdhdXRoLnN1Y2Nlc3MucmVnaXN0ZXInKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBQb3N0KCcvbG9naW4nKVxuICBhc3luYyBsb2dpblVzZXIoQEJvZHkoKSBib2R5KSB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuYXV0aFNlcnZpY2UubG9naW5Vc2VyKGJvZHkpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgbWVzc2FnZTogdCgnYXV0aC5zdWNjZXNzLmxvZ2luJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBAR2V0KCcvcmVmcmVzaCcpXG4gIGFzeW5jIHJlZnJlc2hUb2tlbnMoKSB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuYXV0aFNlcnZpY2UucmVmcmVzaFRva2VucygpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgbWVzc2FnZTogdCgnYXV0aC5zdWNjZXNzLnRva2VuUmVmcmVzaGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBAR2V0KCcvbG9nb3V0LzppZCcpXG4gIGFzeW5jIGxvZ291dFVzZXIoQFBhcmFtcygnaWQnKSBpZCkge1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmF1dGhTZXJ2aWNlLmxvZ291dFVzZXIoaWQpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgbWVzc2FnZTogdCgnYXV0aC5zdWNjZXNzLmxvZ291dCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cblxuICBAR2V0KCcvbWUnKVxuICBAaXNBdXRoKClcbiAgYXN5bmMgdXNlclByb2ZpbGUoQFVzZXIoKSB1c2VyKSB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuYXV0aFNlcnZpY2UuZ2V0VXNlclByb2ZpbGUodXNlcik7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBtZXNzYWdlOiB0KCd1c2Vycy5zdWNjZXNzLnJldHJpZXZlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQFBvc3QoJy9mb3Jnb3QtcGFzc3dvcmQnKVxuICBAaXNBdXRoKClcbiAgYXN5bmMgZm9yZ290UGFzc3dvcmQoQEJvZHkoKSBib2R5KSB7XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuYXV0aFNlcnZpY2UuZm9yZ290UGFzc3dvcmQoYm9keS5lbWFpbCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBtZXNzYWdlOiB0KCdhdXRoLnN1Y2Nlc3MucGFzc3dvcmRSZXNldCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG59IiwKICAgICJpbXBvcnQgeyB0IH0gZnJvbSAnbmFqbS1hcGknO1xuaW1wb3J0IHsgSW5qZWN0YWJsZSwgZ2V0Q3VycmVudExhbmd1YWdlIH0gZnJvbSAnbmFqbS1hcGknO1xuaW1wb3J0IHsgVXNlclNlcnZpY2UsIFVzZXJWYWxpZGF0b3IgfSBmcm9tICcuLi91c2Vycyc7XG5pbXBvcnQgeyBUb2tlblNlcnZpY2UgfSBmcm9tICcuLi90b2tlbnMnO1xuaW1wb3J0IHsgQ29va2llU2VydmljZSB9IGZyb20gJy4vQ29va2llU2VydmljZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdXRoU2VydmljZSB7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB0b2tlblNlcnZpY2U6IFRva2VuU2VydmljZSxcbiAgICBwcml2YXRlIHVzZXJTZXJ2aWNlOiBVc2VyU2VydmljZSxcbiAgICBwcml2YXRlIHVzZXJWYWxpZGF0b3I6IFVzZXJWYWxpZGF0b3IsXG4gICAgcHJpdmF0ZSBjb29raWVTZXJ2aWNlOiBDb29raWVTZXJ2aWNlLFxuICApIHsgfVxuXG4gIGFzeW5jIHJlZ2lzdGVyVXNlcihib2R5KSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMudXNlclNlcnZpY2UuY3JlYXRlKGJvZHkpXG4gIH1cblxuICBhc3luYyBsb2dpblVzZXIoYm9keSkge1xuICAgIGNvbnN0IHsgZW1haWwsIHBhc3N3b3JkIH0gPSBib2R5O1xuXG4gICAgaWYgKCFlbWFpbCB8fCAhcGFzc3dvcmQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcih0KCdhdXRoLmVycm9ycy5pbnZhbGlkQ3JlZGVudGlhbHMnKSlcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZ1Bhc3N3b3JkID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5nZXRQYXNzd29yZChlbWFpbCk7XG4gICAgY29uc3QgeyBpZCB9ID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5nZXRCeUVtYWlsKGVtYWlsKTtcbiAgICBhd2FpdCB0aGlzLnVzZXJWYWxpZGF0b3IuY2hlY2tQYXNzd29yZFZhbGlkKHBhc3N3b3JkLCBleGlzdGluZ1Bhc3N3b3JkKTtcblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnRva2VuU2VydmljZS5nZW5lcmF0ZVRva2VucyhpZCk7XG4gICAgdGhpcy5jb29raWVTZXJ2aWNlLnNldFJlZnJlc2hDb29raWUoZGF0YS5yZWZyZXNoVG9rZW4pXG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICBhc3luYyByZWZyZXNoVG9rZW5zKCkge1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnRva2VuU2VydmljZS5yZWZyZXNoVG9rZW5zKCk7XG4gICAgdGhpcy5jb29raWVTZXJ2aWNlLnNldFJlZnJlc2hDb29raWUoZGF0YS5yZWZyZXNoVG9rZW4pO1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgYXN5bmMgbG9nb3V0VXNlcih1c2VySWQpIHtcbiAgICBhd2FpdCB0aGlzLnVzZXJWYWxpZGF0b3IuY2hlY2tVc2VyRXhpc3RzKHVzZXJJZCk7XG4gICAgYXdhaXQgdGhpcy50b2tlblNlcnZpY2UucmV2b2tlVG9rZW4odXNlcklkKTtcbiAgICB0aGlzLmNvb2tpZVNlcnZpY2UuY2xlYXJSZWZyZXNoQ29va2llKCk7XG4gICAgcmV0dXJuIHsgZGF0YTogbnVsbCwgbWVzc2FnZTogdCgnYXV0aC5zdWNjZXNzLmxvZ291dCcpIH07XG4gIH1cblxuICBhc3luYyBnZXRVc2VyUHJvZmlsZSh1c2VyRGF0YSkge1xuICAgIGNvbnN0IGxhbmcgPSBnZXRDdXJyZW50TGFuZ3VhZ2UoKTtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udXNlckRhdGEsXG4gICAgICBsYW5ndWFnZTogbGFuZyxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZm9yZ290UGFzc3dvcmQoZW1haWwpIHtcblxuICB9XG59XG5cblxuIiwKICAgICJcbmltcG9ydCB7IHJvbGVzVGFibGUsIHVzZXJzVGFibGUsIHBlcm1pc3Npb25zVGFibGUsIHJvbGVQZXJtaXNzaW9uc1RhYmxlIH0gZnJvbSAnQC9kYXRhYmFzZS9zY2hlbWEnO1xuaW1wb3J0IHsgZXEsIG5lIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuaW1wb3J0IHsgUmVwb3NpdG9yeSxEQiB9IGZyb20gJ25ham0tYXBpJztcblxuQFJlcG9zaXRvcnkoKVxuZXhwb3J0IGNsYXNzIFVzZXJSZXBvc2l0b3J5IHtcbiAgZGVjbGFyZSBkYjogREI7XG5cbiAgcHJpdmF0ZSBnZXRVc2VyKCkge1xuICAgIHJldHVybiB7XG4gICAgICBpZDogdXNlcnNUYWJsZS5pZCxcbiAgICAgIGVtYWlsOiB1c2Vyc1RhYmxlLmVtYWlsLFxuICAgICAgZW1haWxWZXJpZmllZDogdXNlcnNUYWJsZS5lbWFpbFZlcmlmaWVkLFxuICAgICAgaW1hZ2U6IHVzZXJzVGFibGUuaW1hZ2UsXG4gICAgICBzdGF0dXM6IHVzZXJzVGFibGUuc3RhdHVzLFxuICAgICAgcm9sZUlkOiB1c2Vyc1RhYmxlLnJvbGVJZCxcbiAgICAgIHJvbGU6IHJvbGVzVGFibGUubmFtZSxcbiAgICAgIGNyZWF0ZWRBdDogdXNlcnNUYWJsZS5jcmVhdGVkQXQsXG4gICAgICB1cGRhdGVkQXQ6IHVzZXJzVGFibGUudXBkYXRlZEF0LFxuICAgIH07XG4gIH1cblxuICBhc3luYyBnZXRBbGwoKSB7XG4gICAgY29uc3QgYWxsVXNlcnMgPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuc2VsZWN0KHRoaXMuZ2V0VXNlcigpKVxuICAgICAgLmZyb20odXNlcnNUYWJsZSlcbiAgICAgIC5sZWZ0Sm9pbihyb2xlc1RhYmxlLCBlcSh1c2Vyc1RhYmxlLnJvbGVJZCwgcm9sZXNUYWJsZS5pZCkpO1xuXG4gICAgLy8gQWRkIHBlcm1pc3Npb25zIHRvIGVhY2ggdXNlclxuICAgIHJldHVybiBQcm9taXNlLmFsbChhbGxVc2Vycy5tYXAoYXN5bmMgKHVzZXIpID0+ICh7XG4gICAgICAuLi51c2VyLFxuICAgICAgcGVybWlzc2lvbnM6IGF3YWl0IHRoaXMuZ2V0VXNlclBlcm1pc3Npb25zKHVzZXIuaWQpXG4gICAgfSkpKTtcbiAgfVxuXG4gIGFzeW5jIGdldEJ5SWQoaWQpIHtcbiAgICBjb25zdCBbdXNlcl0gPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuc2VsZWN0KHRoaXMuZ2V0VXNlcigpKVxuICAgICAgLmZyb20odXNlcnNUYWJsZSlcbiAgICAgIC5sZWZ0Sm9pbihyb2xlc1RhYmxlLCBlcSh1c2Vyc1RhYmxlLnJvbGVJZCwgcm9sZXNUYWJsZS5pZCkpXG4gICAgICAud2hlcmUoZXEodXNlcnNUYWJsZS5pZCwgaWQpKVxuICAgICAgLmxpbWl0KDEpO1xuXG4gICAgaWYgKCF1c2VyKSByZXR1cm4gdXNlcjtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi51c2VyLFxuICAgICAgcGVybWlzc2lvbnM6IGF3YWl0IHRoaXMuZ2V0VXNlclBlcm1pc3Npb25zKHVzZXIuaWQpXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGdldEJ5RW1haWwoZW1haWwpIHtcbiAgICBjb25zdCBbZXhpc3RpbmdVc2VyXSA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3QodGhpcy5nZXRVc2VyKCkpXG4gICAgICAuZnJvbSh1c2Vyc1RhYmxlKVxuICAgICAgLmxlZnRKb2luKHJvbGVzVGFibGUsIGVxKHVzZXJzVGFibGUucm9sZUlkLCByb2xlc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcSh1c2Vyc1RhYmxlLmVtYWlsLCBlbWFpbCkpO1xuICAgIHJldHVybiBleGlzdGluZ1VzZXI7XG4gIH1cblxuXG4gIGFzeW5jIGNyZWF0ZShkYXRhKSB7XG4gICAgY29uc3QgW25ld1VzZXJdID0gYXdhaXQgdGhpcy5kYi5pbnNlcnQodXNlcnNUYWJsZSkudmFsdWVzKGRhdGEpLnJldHVybmluZygpO1xuICAgIHJldHVybiBuZXdVc2VyO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlKGlkLCBkYXRhKSB7XG4gICAgY29uc3QgW3VwZGF0ZWRVc2VyXSA9IGF3YWl0IHRoaXMuZGIudXBkYXRlKHVzZXJzVGFibGUpLnNldChkYXRhKS53aGVyZShlcSh1c2Vyc1RhYmxlLmlkLCBpZCkpLnJldHVybmluZygpO1xuICAgIHJldHVybiB1cGRhdGVkVXNlcjtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZShpZCkge1xuICAgIGNvbnN0IFtkZWxldGVkVXNlcl0gPSBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh1c2Vyc1RhYmxlKS53aGVyZShlcSh1c2Vyc1RhYmxlLmlkLCBpZCkpLnJldHVybmluZygpO1xuICAgIHJldHVybiBkZWxldGVkVXNlcjtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZUFsbCgpIHtcbiAgICBjb25zdCBhZG1pblJvbGUgPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuc2VsZWN0KHsgaWQ6IHJvbGVzVGFibGUuaWQgfSlcbiAgICAgIC5mcm9tKHJvbGVzVGFibGUpXG4gICAgICAud2hlcmUoZXEocm9sZXNUYWJsZS5uYW1lLCAnYWRtaW4nKSlcbiAgICAgIC5saW1pdCgxKTtcblxuICAgIGlmIChhZG1pblJvbGUubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zdCBkZWxldGVkVXNlcnMgPSBhd2FpdCB0aGlzLmRiLmRlbGV0ZSh1c2Vyc1RhYmxlKS5yZXR1cm5pbmcoKTtcbiAgICAgIHJldHVybiBkZWxldGVkVXNlcnM7XG4gICAgfVxuICAgIGNvbnN0IGRlbGV0ZWRVc2VycyA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5kZWxldGUodXNlcnNUYWJsZSlcbiAgICAgIC53aGVyZShuZSh1c2Vyc1RhYmxlLnJvbGVJZCwgYWRtaW5Sb2xlWzBdLmlkKSlcbiAgICAgIC5yZXR1cm5pbmcoKTtcblxuICAgIHJldHVybiBkZWxldGVkVXNlcnM7XG4gIH1cblxuICBhc3luYyBnZXRSb2xlTmFtZUJ5SWQodXNlcklkKSB7XG4gICAgY29uc3QgW3JvbGVdID0gYXdhaXQgdGhpcy5kYi5zZWxlY3Qoe1xuICAgICAgcm9sZU5hbWU6IHJvbGVzVGFibGUubmFtZVxuICAgIH0pXG4gICAgICAuZnJvbSh1c2Vyc1RhYmxlKVxuICAgICAgLmxlZnRKb2luKHJvbGVzVGFibGUsIGVxKHVzZXJzVGFibGUucm9sZUlkLCByb2xlc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcSh1c2Vyc1RhYmxlLmlkLCB1c2VySWQpKVxuXG4gICAgcmV0dXJuIHJvbGUucm9sZU5hbWVcbiAgfVxuXG4gIGFzeW5jIGdldFVzZXJQYXNzd29yZChlbWFpbCkge1xuICAgIGNvbnN0IFt1c2VyXSA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3Qoe1xuICAgICAgICBpZDogdXNlcnNUYWJsZS5pZCxcbiAgICAgICAgZW1haWw6IHVzZXJzVGFibGUuZW1haWwsXG4gICAgICAgIHBhc3N3b3JkOiB1c2Vyc1RhYmxlLnBhc3N3b3JkXG4gICAgICB9KVxuICAgICAgLmZyb20odXNlcnNUYWJsZSlcbiAgICAgIC53aGVyZShlcSh1c2Vyc1RhYmxlLmVtYWlsLCBlbWFpbCkpXG4gICAgICAubGltaXQoMSk7XG4gICAgcmV0dXJuIHVzZXIucGFzc3dvcmQ7XG4gIH1cblxuICBhc3luYyBnZXRVc2VyUGVybWlzc2lvbnModXNlcklkKSB7XG4gICAgY29uc3QgW3VzZXJdID0gYXdhaXQgdGhpcy5kYlxuICAgICAgLnNlbGVjdCh7IHJvbGVJZDogdXNlcnNUYWJsZS5yb2xlSWQgfSlcbiAgICAgIC5mcm9tKHVzZXJzVGFibGUpXG4gICAgICAud2hlcmUoZXEodXNlcnNUYWJsZS5pZCwgdXNlcklkKSlcbiAgICAgIC5saW1pdCgxKTtcblxuICAgIGlmICghdXNlciB8fCAhdXNlci5yb2xlSWQpIHJldHVybiBbXTtcblxuICAgIGNvbnN0IHVzZXJQZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3Qoe1xuICAgICAgICBuYW1lOiBwZXJtaXNzaW9uc1RhYmxlLm5hbWUsXG4gICAgICB9KVxuICAgICAgLmZyb20ocm9sZVBlcm1pc3Npb25zVGFibGUpXG4gICAgICAubGVmdEpvaW4ocGVybWlzc2lvbnNUYWJsZSwgZXEocm9sZVBlcm1pc3Npb25zVGFibGUucGVybWlzc2lvbklkLCBwZXJtaXNzaW9uc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcShyb2xlUGVybWlzc2lvbnNUYWJsZS5yb2xlSWQsIHVzZXIucm9sZUlkKSk7XG5cbiAgICByZXR1cm4gdXNlclBlcm1pc3Npb25zLm1hcChwID0+IHAubmFtZSkuZmlsdGVyKG5hbWUgPT4gbmFtZSk7XG4gIH1cblxufSIsCiAgICAiaW1wb3J0IHsgSW5qZWN0YWJsZSwgdCB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IFVzZXJSZXBvc2l0b3J5IH0gZnJvbSAnLi9Vc2VyUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBFbmNyeXB0aW9uU2VydmljZSB9IGZyb20gJy4uL2F1dGgnO1xuaW1wb3J0IHsgcGFyc2VTY2hlbWEgfSBmcm9tICdAL3NoYXJlZCc7XG5pbXBvcnQgeyB1c2VyU2NoZW1hIH0gZnJvbSAnQC9saWIvdmFsaWRhdGlvbnMnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVXNlclZhbGlkYXRvciB7XG4gICBjb25zdHJ1Y3RvcihcbiAgICAgIHByaXZhdGUgdXNlclJlcG9zaXRvcnk6IFVzZXJSZXBvc2l0b3J5LFxuICAgICAgcHJpdmF0ZSBlbmNyeXB0aW9uU2VydmljZTogRW5jcnlwdGlvblNlcnZpY2UsXG4gICApIHsgfVxuXG4gICBhc3luYyB2YWxpZGF0ZUNyZWF0ZVVzZXIoZGF0YSkge1xuICAgICAgcmV0dXJuIHBhcnNlU2NoZW1hKHVzZXJTY2hlbWEsIGRhdGEpO1xuICAgfVxuXG4gICBhc3luYyBpc0VtYWlsRXhpc3RzKGVtYWlsKSB7XG4gICAgICBjb25zdCBleGlzdGluZ1VzZXIgPSBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldEJ5RW1haWwoZW1haWwpO1xuICAgICAgcmV0dXJuICEhZXhpc3RpbmdVc2VyXG4gICB9XG5cbiAgIGFzeW5jIGlzUGFzc3dvcmRWYWxpZChwYXNzd29yZCwgaGFzaGVkUGFzc3dvcmQpIHtcbiAgICAgIGNvbnN0IGlzUGFzc3dvcmRWYWxpZCA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuY29tcGFyZVBhc3N3b3JkKHBhc3N3b3JkLCBoYXNoZWRQYXNzd29yZCk7XG4gICAgICByZXR1cm4gISFpc1Bhc3N3b3JkVmFsaWRcbiAgIH1cblxuICAgYXN5bmMgaXNVc2VyRXhpc3QoaWQpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nVXNlciA9IGF3YWl0IHRoaXMudXNlclJlcG9zaXRvcnkuZ2V0QnlJZChpZCk7XG4gICAgICByZXR1cm4gISFleGlzdGluZ1VzZXJcbiAgIH1cblxuICAgYXN5bmMgY2hlY2tVc2VySWRJc1VuaXF1ZShpZCkge1xuICAgICAgaWYgKCFpZCkgcmV0dXJuO1xuICAgICAgY29uc3QgZXhpc3RpbmdVc2VyID0gYXdhaXQgdGhpcy51c2VyUmVwb3NpdG9yeS5nZXRCeUlkKGlkKTtcbiAgICAgIGlmIChleGlzdGluZ1VzZXIpIHtcbiAgICAgICAgIHRocm93IG5ldyBFcnJvcih0KCd1c2Vycy5lcnJvcnMuaWRFeGlzdHMnKSk7XG4gICAgICB9XG4gICB9XG5cbiAgIGFzeW5jIGlzQ29ycmVjdFBhc3MocGFzc3dvcmQpIHtcbiAgICAgIHJldHVybiBwYXNzd29yZCAmJlxuICAgICAgICAgdHlwZW9mIHBhc3N3b3JkID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgcGFzc3dvcmQudHJpbSgpLmxlbmd0aCA+IDA7XG4gICB9XG5cbiAgIGFzeW5jIGhhc1JvbGUodXNlcklkLCByb2xlcykge1xuICAgICAgY29uc3Qgcm9sZU5hbWUgPSBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldFJvbGVOYW1lQnlJZCh1c2VySWQpO1xuXG4gICAgICBpZiAoIXJvbGVOYW1lKSB7XG4gICAgICAgICB0aHJvdyBFcnJvcih0KCdhdXRoLmVycm9ycy5hY2Nlc3NEZW5pZWQnKSlcbiAgICAgIH1cblxuICAgICAgY29uc3QgaGFzUm9sZSA9IHJvbGVzLnNvbWUoXG4gICAgICAgICBpdGVtID0+IHJvbGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IGl0ZW0udG9Mb3dlckNhc2UoKVxuICAgICAgKVxuXG4gICAgICBpZiAoIWhhc1JvbGUpIHtcbiAgICAgICAgIHRocm93IEVycm9yKHQoJ2F1dGguZXJyb3JzLmFjY2Vzc0RlbmllZCcpKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZVxuXG4gICB9XG5cbiAgIC8vPT09PT09PT09PT09PT09PT09PT09PT0gdGhyb3cgZXJyb3JzXG5cbiAgIGFzeW5jIGNoZWNrVXNlckV4aXN0c0J5RW1haWwoZW1haWwpIHtcbiAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldEJ5RW1haWwoZW1haWwpO1xuICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IodCgnYXV0aC5lcnJvcnMuaW52YWxpZENyZWRlbnRpYWxzJykpXG4gICAgICB9XG4gICAgICByZXR1cm4gdXNlclxuICAgfVxuXG4gICBhc3luYyBjaGVja1VzZXJFeGlzdHMoaWQpIHtcbiAgICAgIGNvbnN0IHVzZXJFeGlzdHMgPSBhd2FpdCB0aGlzLmlzVXNlckV4aXN0KGlkKTtcbiAgICAgIGlmICghdXNlckV4aXN0cykge1xuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHQoJ3VzZXJzLmVycm9ycy5ub3RGb3VuZCcpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1c2VyRXhpc3RzO1xuICAgfVxuXG5cbiAgIGFzeW5jIGNoZWNrRW1haWxVbmlxdWUoZW1haWwsIGV4Y2x1ZGVJZCA9IG51bGwpIHtcbiAgICAgIGlmICghZW1haWwpIHJldHVybjtcbiAgICAgIGNvbnN0IGV4aXN0aW5nVXNlciA9IGF3YWl0IHRoaXMudXNlclJlcG9zaXRvcnkuZ2V0QnlFbWFpbChlbWFpbCk7XG4gICAgICBpZiAoZXhpc3RpbmdVc2VyICYmIGV4aXN0aW5nVXNlci5pZCAhPT0gZXhjbHVkZUlkKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IodCgnYXV0aC5lcnJvcnMuZW1haWxFeGlzdHMnKSk7XG4gICAgICB9XG4gICB9XG5cbiAgIGFzeW5jIGNoZWNrRW1haWxFeGlzdHMoZW1haWwpIHtcbiAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldEJ5RW1haWwoZW1haWwpO1xuICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICB0aHJvdyBuZXcgRXJyb3IodCgndXNlcnMuZXJyb3JzLm5vdEZvdW5kJykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHVzZXI7XG4gICB9XG5cbiAgIGFzeW5jIGNoZWNrUGFzc3dvcmRWYWxpZChwYXNzd29yZCwgaGFzaGVkUGFzc3dvcmQpIHtcbiAgICAgIGNvbnN0IGlzUGFzc3dvcmRWYWxpZCA9IGF3YWl0IHRoaXMuaXNQYXNzd29yZFZhbGlkKHBhc3N3b3JkLCBoYXNoZWRQYXNzd29yZCk7XG4gICAgICBpZiAoIWlzUGFzc3dvcmRWYWxpZCkge1xuICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHQoJ2F1dGguZXJyb3JzLmludmFsaWRDcmVkZW50aWFscycpKVxuICAgICAgfVxuICAgfVxuXG59IiwKICAgICJpbXBvcnQgeyBJbmplY3RhYmxlLCBzZXRMYW5ndWFnZSwgZ2V0Q3VycmVudExhbmd1YWdlLCBUcmFuc2FjdGlvbmFsIH0gZnJvbSAnbmFqbS1hcGknO1xuaW1wb3J0IHsgVXNlclJlcG9zaXRvcnkgfSBmcm9tICcuL1VzZXJSZXBvc2l0b3J5JztcbmltcG9ydCB7IFVzZXJWYWxpZGF0b3IgfSBmcm9tICcuL1VzZXJWYWxpZGF0b3InO1xuaW1wb3J0IHsgUm9sZVNlcnZpY2UsIFJvbGVWYWxpZGF0b3IgfSBmcm9tICcuLi9yb2xlcyc7XG5pbXBvcnQgeyBFbmNyeXB0aW9uU2VydmljZSB9IGZyb20gJy4uL2F1dGgnO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkJztcbmltcG9ydCB7IGNsZWFuIH0gZnJvbSAnQC9zaGFyZWQnO1xuXG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBVc2VyU2VydmljZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcm9sZVZhbGlkYXRvcjogUm9sZVZhbGlkYXRvcixcbiAgICBwcml2YXRlIHJvbGVTZXJ2aWNlOiBSb2xlU2VydmljZSxcbiAgICBwcml2YXRlIHVzZXJSZXBvc2l0b3J5OiBVc2VyUmVwb3NpdG9yeSxcbiAgICBwcml2YXRlIHVzZXJWYWxpZGF0b3I6IFVzZXJWYWxpZGF0b3IsXG4gICAgcHJpdmF0ZSBlbmNyeXB0aW9uU2VydmljZTogRW5jcnlwdGlvblNlcnZpY2UsXG4gICkgeyB9XG5cbiAgcHJpdmF0ZSBzYW5pdGl6ZVVzZXIodXNlcikge1xuICAgIGlmICghdXNlcikgcmV0dXJuIHVzZXI7XG4gICAgY29uc3QgeyBwYXNzd29yZCwgLi4uc2FuaXRpemVkVXNlciB9ID0gdXNlcjtcbiAgICByZXR1cm4gc2FuaXRpemVkVXNlcjtcbiAgfVxuXG4gIHByaXZhdGUgc2FuaXRpemVVc2Vycyh1c2Vycykge1xuICAgIHJldHVybiB1c2Vycy5tYXAodXNlciA9PiB0aGlzLnNhbml0aXplVXNlcih1c2VyKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlc29sdmVVc2VyUm9sZShyb2xlSWQsIHJvbGVOYW1lKSB7XG5cbiAgICBpZiAocm9sZUlkKSB7XG4gICAgICBhd2FpdCB0aGlzLnJvbGVWYWxpZGF0b3IuY2hlY2tSb2xlRXhpc3RzKHJvbGVJZCk7XG4gICAgICByZXR1cm4gcm9sZUlkO1xuICAgIH1cblxuICAgIGlmIChyb2xlTmFtZSkge1xuICAgICAgY29uc3Qgcm9sZUJ5TmFtZSA9IGF3YWl0IHRoaXMucm9sZVNlcnZpY2UuZ2V0QnlOYW1lKHJvbGVOYW1lKTtcbiAgICAgIGlmIChyb2xlQnlOYW1lKSB7XG4gICAgICAgIHJldHVybiByb2xlQnlOYW1lLmlkO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSb2xlICcke3JvbGVOYW1lfScgbm90IGZvdW5kYCk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVmYXVsdFJvbGUgPSBhd2FpdCB0aGlzLnJvbGVTZXJ2aWNlLmdldEJ5TmFtZSgnU3R1ZGVudCcpO1xuICAgIHJldHVybiBkZWZhdWx0Um9sZS5pZDtcbiAgfVxuXG4gIGFzeW5jIGdldEFsbCgpIHtcbiAgICBjb25zdCB1c2VycyA9IGF3YWl0IHRoaXMudXNlclJlcG9zaXRvcnkuZ2V0QWxsKCk7XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVVc2Vycyh1c2Vycyk7XG4gIH1cblxuICBhc3luYyBnZXRCeUlkKGlkKSB7XG4gICAgYXdhaXQgdGhpcy51c2VyVmFsaWRhdG9yLmNoZWNrVXNlckV4aXN0cyhpZCk7XG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMudXNlclJlcG9zaXRvcnkuZ2V0QnlJZChpZCk7XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVVc2VyKHVzZXIpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QnlFbWFpbChlbWFpbCkge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnVzZXJWYWxpZGF0b3IuY2hlY2tVc2VyRXhpc3RzQnlFbWFpbChlbWFpbCk7XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVVc2VyKHVzZXIpO1xuICB9XG5cbiAgQFRyYW5zYWN0aW9uYWwoKVxuICBhc3luYyBjcmVhdGUoZGF0YSkge1xuICAgIGNvbnN0IHsgaWQsIGVtYWlsLCBpbWFnZSwgZW1haWxWZXJpZmllZCwgcGFzc3dvcmQsIHJvbGVJZCwgcm9sZSB9ID0gZGF0YTtcbiAgICBsZXQgdXNlcklkID0gaWQgfHwgbmFub2lkKDUpO1xuICAgIGxldCBwYXNzID0gcGFzc3dvcmQgfHwgJzEyMzQ1Njc4JztcblxuICAgIGF3YWl0IHRoaXMudXNlclZhbGlkYXRvci5jaGVja0VtYWlsVW5pcXVlKGRhdGEuZW1haWwpO1xuICAgIGF3YWl0IHRoaXMudXNlclZhbGlkYXRvci5jaGVja1VzZXJJZElzVW5pcXVlKGlkKTtcblxuICAgIGNvbnN0IGhhc2hlZFBhc3N3b3JkID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5oYXNoUGFzc3dvcmQocGFzcyk7XG4gICAgY29uc3QgcmVzb2x2ZWRSb2xlSWQgPSBhd2FpdCB0aGlzLnJlc29sdmVVc2VyUm9sZShyb2xlSWQsIHJvbGUpO1xuXG4gICAgY29uc3QgdXNlckRldGFpbHMgPSB7XG4gICAgICBpZDogdXNlcklkLFxuICAgICAgZW1haWwsXG4gICAgICBpbWFnZSxcbiAgICAgIHBhc3N3b3JkOiBoYXNoZWRQYXNzd29yZCxcbiAgICAgIHJvbGVJZDogcmVzb2x2ZWRSb2xlSWQsXG4gICAgICBlbWFpbFZlcmlmaWVkLFxuICAgICAgc3RhdHVzOiAncGVuZGluZydcbiAgICB9O1xuXG4gICAgYXdhaXQgdGhpcy51c2VyVmFsaWRhdG9yLnZhbGlkYXRlQ3JlYXRlVXNlcih1c2VyRGV0YWlscyk7XG4gICAgY29uc3QgbmV3VXNlciA9IGF3YWl0IHRoaXMudXNlclJlcG9zaXRvcnkuY3JlYXRlKHVzZXJEZXRhaWxzKTtcblxuICAgIHJldHVybiB0aGlzLnNhbml0aXplVXNlcihuZXdVc2VyKTtcblxuXG4gIH1cblxuICBhc3luYyB1cGRhdGUoaWQsIGRhdGEpIHtcblxuICAgIGNvbnN0IHsgcGFzc3dvcmQsIGltYWdlIH0gPSBkYXRhO1xuXG4gICAgYXdhaXQgdGhpcy51c2VyVmFsaWRhdG9yLmNoZWNrVXNlckV4aXN0cyhpZCk7XG4gICAgYXdhaXQgdGhpcy51c2VyVmFsaWRhdG9yLmNoZWNrRW1haWxVbmlxdWUoZGF0YS5lbWFpbCwgaWQpO1xuXG4gICAgY29uc3QgY3VycmVudFVzZXIgPSBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldEJ5SWQoaWQpO1xuICAgIGNvbnN0IGhhc2hlZFBhc3N3b3JkID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5oYXNoUGFzc3dvcmQocGFzc3dvcmQpO1xuXG4gICAgY29uc3QgdXBkYXRlRGF0YSA9IHtcbiAgICAgIC4uLmRhdGEsXG4gICAgICBpbWFnZSxcbiAgICAgIC4uLihoYXNoZWRQYXNzd29yZCAmJiB7IHBhc3N3b3JkOiBoYXNoZWRQYXNzd29yZCB9KVxuICAgIH07XG5cbiAgICBjb25zdCBjbGVhbmVkVXBkYXRlRGF0YSA9IGNsZWFuKHVwZGF0ZURhdGEpO1xuICAgIGNvbnN0IHVwZGF0ZWRVc2VyID0gYXdhaXQgdGhpcy51c2VyUmVwb3NpdG9yeS51cGRhdGUoaWQsIGNsZWFuZWRVcGRhdGVEYXRhKTtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZVVzZXIodXBkYXRlZFVzZXIpO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlKGlkKSB7XG4gICAgYXdhaXQgdGhpcy51c2VyVmFsaWRhdG9yLmNoZWNrVXNlckV4aXN0cyhpZCk7XG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMudXNlclJlcG9zaXRvcnkuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZVVzZXIodXNlcik7XG4gIH1cblxuICBhc3luYyBkZWxldGVBbGwoKSB7XG4gICAgY29uc3QgZGVsZXRlZFVzZXJzID0gYXdhaXQgdGhpcy51c2VyUmVwb3NpdG9yeS5kZWxldGVBbGwoKTtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZVVzZXJzKGRlbGV0ZWRVc2Vycyk7XG4gIH1cblxuICBhc3luYyBnZXRSb2xlTmFtZShpZCkge1xuICAgIGF3YWl0IHRoaXMudXNlclZhbGlkYXRvci5jaGVja1VzZXJFeGlzdHMoaWQpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldFJvbGVOYW1lQnlJZChpZCk7XG4gIH1cblxuICBhc3luYyBnZXRQYXNzd29yZChlbWFpbCkge1xuICAgIGF3YWl0IHRoaXMudXNlclZhbGlkYXRvci5jaGVja1VzZXJFeGlzdHNCeUVtYWlsKGVtYWlsKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy51c2VyUmVwb3NpdG9yeS5nZXRVc2VyUGFzc3dvcmQoZW1haWwpO1xuICB9XG5cbiAgYXN5bmMgYXNzaWduUm9sZShpZCwgcm9sZUlkLCByb2xlTmFtZT8pIHtcbiAgICBhd2FpdCB0aGlzLnVzZXJWYWxpZGF0b3IuY2hlY2tVc2VyRXhpc3RzKGlkKTtcbiAgICBjb25zdCByZXNvbHZlZFJvbGVJZCA9IGF3YWl0IHRoaXMucmVzb2x2ZVVzZXJSb2xlKHJvbGVJZCwgcm9sZU5hbWUpO1xuICAgIGNvbnN0IHVwZGF0ZWRVc2VyID0gYXdhaXQgdGhpcy51c2VyUmVwb3NpdG9yeS51cGRhdGUoaWQsIHsgcm9sZUlkOiByZXNvbHZlZFJvbGVJZCB9KTtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZVVzZXIodXBkYXRlZFVzZXIpO1xuICB9XG5cbiAgYXN5bmMgcmVtb3ZlUm9sZShpZCkge1xuICAgIGF3YWl0IHRoaXMudXNlclZhbGlkYXRvci5jaGVja1VzZXJFeGlzdHMoaWQpO1xuICAgIGNvbnN0IHVwZGF0ZWRVc2VyID0gYXdhaXQgdGhpcy51c2VyUmVwb3NpdG9yeS51cGRhdGUoaWQsIHsgcm9sZUlkOiBudWxsIH0pO1xuICAgIHJldHVybiB0aGlzLnNhbml0aXplVXNlcih1cGRhdGVkVXNlcik7XG4gIH1cblxuICBhc3luYyBzZWVkQWRtaW5Vc2VyKCkge1xuICAgIGNvbnN0IGVtYWlsID0gJ2FkbWluQGFkbWluLmNvbSc7XG4gICAgY29uc3QgYWRtaW5Sb2xlID0gYXdhaXQgdGhpcy5yb2xlVmFsaWRhdG9yLmNoZWNrQWRtaW5Sb2xlRXhpc3RzKCk7XG5cbiAgICBjb25zdCBleGlzdGluZ1VzZXIgPSBhd2FpdCB0aGlzLnVzZXJSZXBvc2l0b3J5LmdldEJ5RW1haWwoZW1haWwpO1xuXG4gICAgaWYgKGV4aXN0aW5nVXNlcikge1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGUoZXhpc3RpbmdVc2VyLmlkKTtcbiAgICB9XG5cbiAgICBjb25zdCBuZXdBZG1pblVzZXIgPSBhd2FpdCB0aGlzLmNyZWF0ZSh7XG4gICAgICBpZDogJ1VTUjAwJyxcbiAgICAgIG5hbWU6ICdTeXN0ZW0gQWRtaW5pc3RyYXRvcicsXG4gICAgICBlbWFpbCxcbiAgICAgIHBhc3N3b3JkOiAnMTIzNDU2NzgnLFxuICAgICAgaW1hZ2U6bnVsbCxcbiAgICAgIHJvbGVJZDogYWRtaW5Sb2xlLmlkLFxuICAgICAgc3RhdHVzOiAnYWN0aXZlJyxcbiAgICAgIGVtYWlsVmVyaWZpZWQ6IHRydWVcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLnNhbml0aXplVXNlcihuZXdBZG1pblVzZXIpO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlTGFuZyhsYW5ndWFnZSkge1xuICAgIHNldExhbmd1YWdlKGxhbmd1YWdlKVxuICAgIHJldHVybiBsYW5ndWFnZVxuICB9XG5cbiAgYXN5bmMgZ2V0TGFuZygpIHtcbiAgICByZXR1cm4gZ2V0Q3VycmVudExhbmd1YWdlKCk7XG4gIH1cblxufSIsCiAgICAiXG5cbmltcG9ydCB7IHJvbGVzVGFibGUgfSBmcm9tICdAL2RhdGFiYXNlL3NjaGVtYSc7XG5pbXBvcnQgeyBlcSB9IGZyb20gJ2RyaXp6bGUtb3JtJztcbmltcG9ydCB7IFJlcG9zaXRvcnksIERCIH0gZnJvbSAnbmFqbS1hcGknO1xuXG5AUmVwb3NpdG9yeSgpXG5leHBvcnQgY2xhc3MgUm9sZVJlcG9zaXRvcnkge1xuXG4gIGRlY2xhcmUgZGI6IERCO1xuXG4gIGFzeW5jIGdldEFsbCgpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5kYi5zZWxlY3QoKS5mcm9tKHJvbGVzVGFibGUpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QnlJZChpZDpzdHJpbmcpIHtcbiAgICBjb25zdCBbZXhpc3RpbmdSb2xlXSA9IGF3YWl0IHRoaXMuZGIuc2VsZWN0KCkuZnJvbShyb2xlc1RhYmxlKS53aGVyZShlcShyb2xlc1RhYmxlLmlkLCBpZCkpO1xuICAgIHJldHVybiBleGlzdGluZ1JvbGU7XG4gIH1cblxuICBhc3luYyBnZXRCeU5hbWUobmFtZTpzdHJpbmcpIHtcbiAgICBjb25zdCBbZXhpc3RpbmdSb2xlXSA9IGF3YWl0IHRoaXMuZGIuc2VsZWN0KCkuZnJvbShyb2xlc1RhYmxlKS53aGVyZShlcShyb2xlc1RhYmxlLm5hbWUsIG5hbWUpKTtcbiAgICByZXR1cm4gZXhpc3RpbmdSb2xlXG4gIH1cblxuICBhc3luYyBjcmVhdGUoZGF0YSkge1xuICAgIGNvbnN0IFtuZXdSb2xlXSA9IGF3YWl0IHRoaXMuZGIuaW5zZXJ0KHJvbGVzVGFibGUpLnZhbHVlcyhkYXRhKS5yZXR1cm5pbmcoKTtcbiAgICByZXR1cm4gbmV3Um9sZVxuICB9XG5cbiAgYXN5bmMgdXBkYXRlKGlkLCBkYXRhKSB7XG4gICAgY29uc3QgW3VwZGF0ZWRSb2xlXSA9IGF3YWl0IHRoaXMuZGIudXBkYXRlKHJvbGVzVGFibGUpXG4gICAgICAuc2V0KGRhdGEpXG4gICAgICAud2hlcmUoZXEocm9sZXNUYWJsZS5pZCwgaWQpKVxuICAgICAgLnJldHVybmluZygpO1xuXG4gICAgICByZXR1cm4gdXBkYXRlZFJvbGVcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZShpZCkge1xuICAgIGNvbnN0IFtkZWxldGVkUm9sZV0gPSBhd2FpdCB0aGlzLmRiLmRlbGV0ZShyb2xlc1RhYmxlKVxuICAgICAgLndoZXJlKGVxKHJvbGVzVGFibGUuaWQsIGlkKSlcbiAgICAgIC5yZXR1cm5pbmcoKTtcbiAgICAgIHJldHVybiBkZWxldGVkUm9sZVxuICB9XG59XG4iLAogICAgImltcG9ydCB7IEluamVjdGFibGUsIHQgfSBmcm9tICduYWptLWFwaSc7XG5pbXBvcnQgeyBSb2xlUmVwb3NpdG9yeSB9IGZyb20gJy4vUm9sZVJlcG9zaXRvcnknO1xuaW1wb3J0IHsgcGFyc2VTY2hlbWEgfSBmcm9tICdAL3NoYXJlZCc7XG5pbXBvcnQgeyByb2xlU2NoZW1hIH0gZnJvbSAnQC9saWIvdmFsaWRhdGlvbnMnO1xuXG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSb2xlVmFsaWRhdG9yIHtcbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSByb2xlUmVwb3NpdG9yeTogUm9sZVJlcG9zaXRvcnksXG4gICAgKSB7IH1cblxuICAgIGFzeW5jIHZhbGlkYXRlQ3JlYXRlUm9sZShkYXRhKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVNjaGVtYShyb2xlU2NoZW1hLCBkYXRhKTtcbiAgICB9XG5cbiAgICBhc3luYyBpc1JvbGVOYW1lRXhpc3RzKHJvbGVOYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdSb2xlID0gYXdhaXQgdGhpcy5yb2xlUmVwb3NpdG9yeS5nZXRCeU5hbWUocm9sZU5hbWUpO1xuICAgICAgICByZXR1cm4gISFleGlzdGluZ1JvbGU7XG4gICAgfVxuXG4gICAgYXN5bmMgaXNSb2xlSWRFeGlzdHMoaWQ6IHN0cmluZykge1xuICAgICAgICBjb25zdCBleGlzdGluZ1JvbGUgPSBhd2FpdCB0aGlzLnJvbGVSZXBvc2l0b3J5LmdldEJ5SWQoaWQpO1xuICAgICAgICByZXR1cm4gISFleGlzdGluZ1JvbGU7XG4gICAgfVxuXG4gICAgYXN5bmMgY2hlY2tOYW1lVW5pcXVlKHJvbGVOYW1lOiBzdHJpbmcsIGV4Y2x1ZGVJZCA9IG51bGwpIHtcbiAgICAgICAgaWYgKCFyb2xlTmFtZSkgcmV0dXJuO1xuICAgICAgICBjb25zdCBleGlzdGluZ1JvbGUgPSBhd2FpdCB0aGlzLnJvbGVSZXBvc2l0b3J5LmdldEJ5TmFtZShyb2xlTmFtZSk7XG5cbiAgICAgICAgaWYgKGV4aXN0aW5nUm9sZSAmJiBleGlzdGluZ1JvbGUuaWQgIT09IGV4Y2x1ZGVJZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHQoJ3JvbGVzLmVycm9ycy5leGlzdHMnKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBjaGVja1JvbGVFeGlzdHMoaWQ6IHN0cmluZykge1xuICAgICAgICBjb25zdCByb2xlSWRFeGlzdHMgPSBhd2FpdCB0aGlzLmlzUm9sZUlkRXhpc3RzKGlkKTtcbiAgICAgICAgaWYgKCFyb2xlSWRFeGlzdHMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0KCdyb2xlcy5lcnJvcnMubm90Rm91bmQnKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBjaGVja1JvbGVFeGlzdHNCeU5hbWUocm9sZU5hbWU6IHN0cmluZykge1xuICAgICAgICBjb25zdCByb2xlTmFtZUV4aXN0cyA9IGF3YWl0IHRoaXMuaXNSb2xlTmFtZUV4aXN0cyhyb2xlTmFtZSk7XG4gICAgICAgIGlmICghcm9sZU5hbWVFeGlzdHMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0KCdyb2xlcy5lcnJvcnMubm90Rm91bmQnKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBjaGVja0FkbWluUm9sZUV4aXN0cygpIHtcbiAgICAgICAgY29uc3QgYWRtaW5Sb2xlID0gYXdhaXQgdGhpcy5yb2xlUmVwb3NpdG9yeS5nZXRCeU5hbWUoJ2FkbWluJyk7XG4gICAgICAgIGlmICghYWRtaW5Sb2xlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodCgndXNlcnMuZXJyb3JzLmFkbWluUm9sZU5vdEZvdW5kJykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhZG1pblJvbGU7XG4gICAgfVxufSIsCiAgICAiaW1wb3J0IHsgSW5qZWN0YWJsZSwgSGVhZGVycywgY3JlYXRlR3VhcmQsIEd1YXJkUGFyYW1zLCBDdHggfSBmcm9tIFwibmFqbS1hcGlcIjtcbmltcG9ydCB7IFRva2VuU2VydmljZSB9IGZyb20gXCIuLi90b2tlbnNcIjtcblxuLy8gPT09PT09PT09PT09IENPTlNUQU5UUyA9PT09PT09PT09PT0gLy9cblxuZXhwb3J0IGNvbnN0IFJPTEVTID0ge1xuICBBRE1JTjogJ2FkbWluJyxcbiAgUFJJTkNJUEFMOiAncHJpbmNpcGFsJyxcbiAgQUNDT1VOVElORzogJ2FjY291bnRpbmcnLFxuICBTRUNSRVRBUlk6ICdzZWNyZXRhcnknLFxuICBURUFDSEVSOiAndGVhY2hlcicsXG4gIFNUVURFTlQ6ICdzdHVkZW50JyxcbiAgUEFSRU5UOiAncGFyZW50Jyxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBjb25zdCBST0xFX0dST1VQUyA9IHtcbiAgQURNSU5JU1RSQVRPUlM6IFtST0xFUy5BRE1JTiwgUk9MRVMuUFJJTkNJUEFMXSxcbiAgRklOQU5DSUFMOiBbUk9MRVMuQURNSU4sIFJPTEVTLkFDQ09VTlRJTkddLFxuICBTVEFGRjogW1JPTEVTLkFETUlOLCBST0xFUy5QUklOQ0lQQUwsIFJPTEVTLkFDQ09VTlRJTkcsIFJPTEVTLlNFQ1JFVEFSWSwgUk9MRVMuVEVBQ0hFUl0sXG4gIEVORF9VU0VSUzogW1JPTEVTLlNUVURFTlQsIFJPTEVTLlBBUkVOVF0sXG4gIEFMTDogW1JPTEVTLkFETUlOLCBST0xFUy5QUklOQ0lQQUwsIFJPTEVTLkFDQ09VTlRJTkcsIFJPTEVTLlNFQ1JFVEFSWSwgUk9MRVMuVEVBQ0hFUiwgUk9MRVMuU1RVREVOVCwgUk9MRVMuUEFSRU5UXSxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIFJvbGUgPSB0eXBlb2YgUk9MRVNba2V5b2YgdHlwZW9mIFJPTEVTXTtcbmV4cG9ydCB0eXBlIFJvbGVHcm91cCA9IHR5cGVvZiBST0xFX0dST1VQU1trZXlvZiB0eXBlb2YgUk9MRV9HUk9VUFNdO1xuXG4vLyA9PT09PT09PT09PT0gUk9MRSBDSEVDS0VSIChJbmplY3RhYmxlIGZvciBTZXJ2aWNlcykgPT09PT09PT09PT09IC8vXG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSb2xlQ2hlY2tlciB7XG4gIGlzSW5Hcm91cCh1c2VyUm9sZSwgZ3JvdXA6IHJlYWRvbmx5IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGdyb3VwLmluY2x1ZGVzKHVzZXJSb2xlPy50b0xvd2VyQ2FzZSgpKTtcbiAgfVxuXG4gIGlzQWRtaW5pc3RyYXRvcih1c2VyUm9sZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzSW5Hcm91cCh1c2VyUm9sZSwgUk9MRV9HUk9VUFMuQURNSU5JU1RSQVRPUlMpO1xuICB9XG5cbiAgaXNTdGFmZih1c2VyUm9sZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzSW5Hcm91cCh1c2VyUm9sZSwgUk9MRV9HUk9VUFMuU1RBRkYpO1xuICB9XG5cbiAgaGFzQW55Um9sZSh1c2VyUm9sZSwgcm9sZXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHJvbGVzLmluY2x1ZGVzKHVzZXJSb2xlPy50b0xvd2VyQ2FzZSgpKTtcbiAgfVxuXG4gIGhhc0V4YWN0Um9sZSh1c2VyUm9sZSwgcmVxdWlyZWRSb2xlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHVzZXJSb2xlPy50b0xvd2VyQ2FzZSgpID09PSByZXF1aXJlZFJvbGU/LnRvTG93ZXJDYXNlKCk7XG4gIH1cblxufVxuXG4vLyA9PT09PT09PT09PT0gUk9MRSBHVUFSRFMgKEluamVjdGFibGUgZm9yIERlY29yYXRvcnMpID09PT09PT09PT09PSAvL1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgUm9sZUd1YXJkcyB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcm9sZUNoZWNrZXI6IFJvbGVDaGVja2VyLFxuICAgIHByaXZhdGUgdG9rZW5TZXJ2aWNlOiBUb2tlblNlcnZpY2VcbiAgKSB7IH1cblxuICBhc3luYyBpc0F1dGgoQEhlYWRlcnMoJ2F1dGhvcml6YXRpb24nKSBhdXRoLCBAQ3R4KCkgY3R4KSB7XG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMudG9rZW5TZXJ2aWNlLnN0b3JlVXNlckluQ2FjaGUoYXV0aCwgY3R4KTtcbiAgICByZXR1cm4gISF1c2VyO1xuICB9XG5cbiAgYXN5bmMgaGFzUm9sZXMoQEhlYWRlcnMoJ2F1dGhvcml6YXRpb24nKSBhdXRoLCBAQ3R4KCkgY3R4LCBAR3VhcmRQYXJhbXMoKSByb2xlcykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy50b2tlblNlcnZpY2Uuc3RvcmVVc2VySW5DYWNoZShhdXRoLCBjdHgpO1xuICAgICAgaWYgKCF1c2VyPy5yb2xlKSByZXR1cm4gZmFsc2U7XG4gICAgICBjb25zdCByb2xlQXJyYXkgPSBBcnJheS5pc0FycmF5KHJvbGVzKSA/IHJvbGVzIDogW3JvbGVzXTtcbiAgICAgIHJldHVybiB0aGlzLnJvbGVDaGVja2VyLmhhc0FueVJvbGUodXNlci5yb2xlLCByb2xlQXJyYXkpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT0gRVhQT1JURUQgR1VBUkQgREVDT1JBVE9SUyA9PT09PT09PT09PT0gLy9cblxuZXhwb3J0IGNvbnN0IGlzQWRtaW4gPSAoKSA9PiBSb2xlKCdhZG1pbicpO1xuZXhwb3J0IGNvbnN0IGlzUHJpbmNpcGFsID0gKCkgPT4gUm9sZSgncHJpbmNpcGFsJyk7XG5leHBvcnQgY29uc3QgaXNBY2NvdW50aW5nID0gKCkgPT4gUm9sZSgnYWNjb3VudGluZycpO1xuZXhwb3J0IGNvbnN0IGlzU2VjcmV0YXJ5ID0gKCkgPT4gUm9sZSgnc2VjcmV0YXJ5Jyk7XG5leHBvcnQgY29uc3QgaXNUZWFjaGVyID0gKCkgPT4gUm9sZSgndGVhY2hlcicpO1xuZXhwb3J0IGNvbnN0IGlzUGFyZW50ID0gKCkgPT4gUm9sZSgncGFyZW50Jyk7XG5leHBvcnQgY29uc3QgaXNTdHVkZW50ID0gKCkgPT4gUm9sZSgnc3R1ZGVudCcpO1xuZXhwb3J0IGNvbnN0IGlzQWRtaW5pc3RyYXRvciA9ICgpID0+IFJvbGUoJ2FkbWluJywgJ3ByaW5jaXBhbCcpO1xuZXhwb3J0IGNvbnN0IGlzRmluYW5jaWFsID0gKCkgPT4gUm9sZSgnYWRtaW4nLCAnYWNjb3VudGluZycpO1xuZXhwb3J0IGNvbnN0IGlzU3RhZmYgPSAoKSA9PiBSb2xlKCdhZG1pbicsICdwcmluY2lwYWwnLCAnYWNjb3VudGluZycsICdzZWNyZXRhcnknLCAndGVhY2hlcicpO1xuZXhwb3J0IGNvbnN0IGlzQXV0aCA9IGNyZWF0ZUd1YXJkKFJvbGVHdWFyZHMsICdpc0F1dGgnKTtcblxuZXhwb3J0IGNvbnN0IFJvbGUgPSAoLi4ucm9sZXMpID0+IGNyZWF0ZUd1YXJkKFJvbGVHdWFyZHMsICdoYXNSb2xlcycpKC4uLnJvbGVzKTtcbiIsCiAgICAiXG5pbXBvcnQgeyB0b2tlbnNUYWJsZSwgdXNlcnNUYWJsZSwgcm9sZXNUYWJsZSwgcGVybWlzc2lvbnNUYWJsZSwgcm9sZVBlcm1pc3Npb25zVGFibGUgfSBmcm9tICdAL2RhdGFiYXNlL3NjaGVtYSc7XG5pbXBvcnQgeyBlcSB9IGZyb20gJ2RyaXp6bGUtb3JtJztcbmltcG9ydCB7IFJlcG9zaXRvcnksIERCIH0gZnJvbSAnbmFqbS1hcGknO1xuXG5AUmVwb3NpdG9yeSgpXG5leHBvcnQgY2xhc3MgVG9rZW5SZXBvc2l0b3J5IHtcbiAgZGVjbGFyZSBkYjogREI7XG5cbiAgYXN5bmMgc3RvcmVSZWZyZXNoVG9rZW4odG9rZW5EYXRhOiB7IHVzZXJJZDogc3RyaW5nOyB0b2tlbjogc3RyaW5nOyBleHBpcmVzQXQ6IHN0cmluZyB9KSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZGJcbiAgICAgIC5pbnNlcnQodG9rZW5zVGFibGUpXG4gICAgICAudmFsdWVzKHRva2VuRGF0YSlcbiAgICAgIC5vbkNvbmZsaWN0RG9VcGRhdGUoe1xuICAgICAgICB0YXJnZXQ6IHRva2Vuc1RhYmxlLnVzZXJJZCxcbiAgICAgICAgc2V0OiB7XG4gICAgICAgICAgdG9rZW46IHRva2VuRGF0YS50b2tlbixcbiAgICAgICAgICBleHBpcmVzQXQ6IHRva2VuRGF0YS5leHBpcmVzQXQsXG4gICAgICAgIH1cbiAgICAgIH0pLnJldHVybmluZygpO1xuICB9XG5cbiAgYXN5bmMgZ2V0UmVmcmVzaFRva2VuKHVzZXJJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW3Rva2VuXSA9IGF3YWl0IHRoaXMuZGIuc2VsZWN0KCkuZnJvbSh0b2tlbnNUYWJsZSkud2hlcmUoZXEodG9rZW5zVGFibGUudXNlcklkLCB1c2VySWQpKTtcbiAgICByZXR1cm4gdG9rZW4/LnRva2VuO1xuICB9XG5cbiAgYXN5bmMgcmV2b2tlVG9rZW4odXNlcklkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBbZGVsZXRlZFRva2VuXSA9IGF3YWl0IHRoaXMuZGIuZGVsZXRlKHRva2Vuc1RhYmxlKS53aGVyZShlcSh0b2tlbnNUYWJsZS51c2VySWQsIHVzZXJJZCkpLnJldHVybmluZygpO1xuICAgIHJldHVybiBkZWxldGVkVG9rZW47XG4gIH1cblxuICBhc3luYyBpc1VzZXJFeGlzdHModXNlcklkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBbdXNlcl0gPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuc2VsZWN0KHsgaWQ6IHVzZXJzVGFibGUuaWQgfSlcbiAgICAgIC5mcm9tKHVzZXJzVGFibGUpXG4gICAgICAud2hlcmUoZXEodXNlcnNUYWJsZS5pZCwgdXNlcklkKSlcbiAgICAgIC5saW1pdCgxKTtcbiAgICByZXR1cm4gISF1c2VyO1xuICB9XG5cbiAgYXN5bmMgZ2V0Um9sZU5hbWVCeUlkKHVzZXJJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW3JvbGVdID0gYXdhaXQgdGhpcy5kYi5zZWxlY3Qoe1xuICAgICAgcm9sZU5hbWU6IHJvbGVzVGFibGUubmFtZVxuICAgIH0pXG4gICAgICAuZnJvbSh1c2Vyc1RhYmxlKVxuICAgICAgLmxlZnRKb2luKHJvbGVzVGFibGUsIGVxKHVzZXJzVGFibGUucm9sZUlkLCByb2xlc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcSh1c2Vyc1RhYmxlLmlkLCB1c2VySWQpKVxuICAgICAgLmxpbWl0KDEpO1xuXG4gICAgcmV0dXJuIHJvbGU/LnJvbGVOYW1lO1xuICB9XG5cbiAgYXN5bmMgZ2V0VXNlclBlcm1pc3Npb25zKHVzZXJJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW3VzZXJdID0gYXdhaXQgdGhpcy5kYlxuICAgICAgLnNlbGVjdCh7IHJvbGVJZDogdXNlcnNUYWJsZS5yb2xlSWQgfSlcbiAgICAgIC5mcm9tKHVzZXJzVGFibGUpXG4gICAgICAud2hlcmUoZXEodXNlcnNUYWJsZS5pZCwgdXNlcklkKSlcbiAgICAgIC5saW1pdCgxKTtcblxuICAgIGlmICghdXNlciB8fCAhdXNlci5yb2xlSWQpIHJldHVybiBbXTtcblxuICAgIGNvbnN0IHVzZXJQZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3Qoe1xuICAgICAgICBuYW1lOiBwZXJtaXNzaW9uc1RhYmxlLm5hbWUsXG4gICAgICB9KVxuICAgICAgLmZyb20ocm9sZVBlcm1pc3Npb25zVGFibGUpXG4gICAgICAubGVmdEpvaW4ocGVybWlzc2lvbnNUYWJsZSwgZXEocm9sZVBlcm1pc3Npb25zVGFibGUucGVybWlzc2lvbklkLCBwZXJtaXNzaW9uc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcShyb2xlUGVybWlzc2lvbnNUYWJsZS5yb2xlSWQsIHVzZXIucm9sZUlkKSk7XG5cbiAgICByZXR1cm4gdXNlclBlcm1pc3Npb25zLm1hcChwID0+IHAubmFtZSkuZmlsdGVyKG5hbWUgPT4gbmFtZSk7XG4gIH1cblxuICBhc3luYyBnZXRVc2VyKHVzZXJJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW3VzZXJdID0gYXdhaXQgdGhpcy5kYlxuICAgICAgLnNlbGVjdCh7XG4gICAgICAgIGlkOiB1c2Vyc1RhYmxlLmlkLFxuICAgICAgICBlbWFpbDogdXNlcnNUYWJsZS5lbWFpbCxcbiAgICAgICAgc3RhdHVzOiB1c2Vyc1RhYmxlLnN0YXR1cyxcbiAgICAgICAgcm9sZUlkOiB1c2Vyc1RhYmxlLnJvbGVJZCxcbiAgICAgICAgcm9sZU5hbWU6IHJvbGVzVGFibGUubmFtZSxcbiAgICAgICAgY3JlYXRlZEF0OiB1c2Vyc1RhYmxlLmNyZWF0ZWRBdCxcbiAgICAgICAgdXBkYXRlZEF0OiB1c2Vyc1RhYmxlLnVwZGF0ZWRBdCxcbiAgICAgIH0pXG4gICAgICAuZnJvbSh1c2Vyc1RhYmxlKVxuICAgICAgLmxlZnRKb2luKHJvbGVzVGFibGUsIGVxKHVzZXJzVGFibGUucm9sZUlkLCByb2xlc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcSh1c2Vyc1RhYmxlLmlkLCB1c2VySWQpKVxuICAgICAgLmxpbWl0KDEpO1xuXG4gICAgcmV0dXJuIHVzZXIgPyB7IC4uLnVzZXIsIHJvbGU6IHVzZXIucm9sZU5hbWUgfSA6IG51bGw7XG4gIH1cbn0iLAogICAgImltcG9ydCB7IHQgfSBmcm9tICduYWptLWFwaSc7XG5pbXBvcnQgeyBnZXRDb29raWUsIEluamVjdGFibGUsIEN0eCwgSGVhZGVycyB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCBqd3QgZnJvbSAnanNvbndlYnRva2VuJ1xuaW1wb3J0IHsgand0RGVjb2RlIH0gZnJvbSAnand0LWRlY29kZSc7XG5pbXBvcnQgeyBUb2tlblJlcG9zaXRvcnkgfSBmcm9tICcuL1Rva2VuUmVwb3NpdG9yeSc7XG5pbXBvcnQgdGltZXN0cmluZyBmcm9tICd0aW1lc3RyaW5nJztcblxuaW50ZXJmYWNlIEp3dFBheWxvYWQge1xuICB1c2VySWQ6IHN0cmluZztcbiAgZXhwPzogbnVtYmVyO1xuICBpYXQ/OiBudW1iZXI7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBUb2tlblNlcnZpY2Uge1xuXG4gIHByaXZhdGUgYWNjZXNzU2VjcmV0S2V5ID0gcHJvY2Vzcy5lbnYuSldUX0FDQ0VTU19TRUNSRVQ7XG4gIHByaXZhdGUgYWNjZXNzRXhwaXJlc0luID0gcHJvY2Vzcy5lbnYuQUNDRVNTX0VYUElSRVNfSU47XG4gIHByaXZhdGUgcmVmcmVzaFNlY3JldEtleSA9IHByb2Nlc3MuZW52LkpXVF9SRUZSRVNIX1NFQ1JFVDtcbiAgcHJpdmF0ZSByZWZyZXNoRXhwaXJlc0luID0gcHJvY2Vzcy5lbnYuUkVGUkVTSF9FWFBJUkVTX0lOO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdG9rZW5SZXBvc2l0b3J5OiBUb2tlblJlcG9zaXRvcnlcbiAgKSB7IH1cblxuICAvLz09PT0gVmFsaWRhdGUgdG9rZW5zXG5cbiAgZXh0cmFjdEFjY2Vzc1Rva2VuKGF1dGhvcml6YXRpb24pIHtcbiAgICBpZiAoYXV0aG9yaXphdGlvbiAmJiBhdXRob3JpemF0aW9uLnN0YXJ0c1dpdGgoJ0JlYXJlcicpKSB7XG4gICAgICByZXR1cm4gYXV0aG9yaXphdGlvbi5zcGxpdCgnICcpWzFdXG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcih0KCdhdXRoLmVycm9ycy50b2tlbk1pc3NpbmcnKSlcbiAgfVxuXG4gIHZlcmlmeUFjY2Vzc1Rva2VuKHRva2VuOiBzdHJpbmcpOiBKd3RQYXlsb2FkIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGp3dC52ZXJpZnkodG9rZW4sIHRoaXMuYWNjZXNzU2VjcmV0S2V5KSBhcyBKd3RQYXlsb2FkO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IodCgnYXV0aC5lcnJvcnMudG9rZW5WZXJpZmljYXRpb25GYWlsZWQnKSlcbiAgICB9XG4gIH1cblxuICB2ZXJpZnlSZWZyZXNoVG9rZW4odG9rZW46IHN0cmluZyk6IHN0cmluZyB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGRlY29kZWQgPSBqd3QudmVyaWZ5KHRva2VuLCB0aGlzLnJlZnJlc2hTZWNyZXRLZXkpIGFzIEp3dFBheWxvYWQ7XG4gICAgICByZXR1cm4gZGVjb2RlZC51c2VySWQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcih0KCdhdXRoLmVycm9ycy50b2tlblZlcmlmaWNhdGlvbkZhaWxlZCcpKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldFVzZXJJZEJ5QWNjZXNzVG9rZW4oaGVhZGVyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5leHRyYWN0QWNjZXNzVG9rZW4oaGVhZGVyKTtcbiAgICBjb25zdCBkZWNvZGVkVG9rZW4gPSB0aGlzLnZlcmlmeUFjY2Vzc1Rva2VuKHRva2VuKTtcbiAgICBjb25zdCB1c2VySWQgPSBkZWNvZGVkVG9rZW4udXNlcklkO1xuICAgIGNvbnN0IHVzZXJFeGlzdHMgPSBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5pc1VzZXJFeGlzdHModXNlcklkKTtcblxuICAgIGlmICghdXNlckV4aXN0cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHQoJ3VzZXJzLmVycm9ycy5ub3RGb3VuZCcpKVxuICAgIH1cblxuICAgIHJldHVybiB1c2VySWQ7XG4gIH1cblxuICAvLz09PSBHZW5lcmF0ZSB0b2tlbnNcblxuICBhc3luYyBzdG9yZVJlZnJlc2hUb2tlbih1c2VySWQsIHJlZnJlc2hUb2tlbikge1xuICAgIGNvbnN0IGV4cGlyZUluU2Vjb25kID0gdGltZXN0cmluZyh0aGlzLnJlZnJlc2hFeHBpcmVzSW4sICdzJyk7XG4gICAgY29uc3QgdG9rZW5EYXRhID0ge1xuICAgICAgdXNlcklkLFxuICAgICAgdG9rZW46IHJlZnJlc2hUb2tlbixcbiAgICAgIGV4cGlyZXNBdDogbmV3IERhdGUoRGF0ZS5ub3coKSArIGV4cGlyZUluU2Vjb25kICogMTAwMCkudG9JU09TdHJpbmcoKVxuICAgIH1cbiAgICBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5zdG9yZVJlZnJlc2hUb2tlbih0b2tlbkRhdGEpO1xuICB9XG5cbiAgZ2V0VG9rZW5FeHBpcmUodG9rZW4pOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBqd3REZWNvZGUodG9rZW4pLmV4cFxuICB9XG5cbiAgZ2VuZXJhdGVBY2Nlc3NUb2tlbihkYXRhOiB7IHVzZXJJZDogc3RyaW5nIH0pOiBzdHJpbmcge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB7IGV4cGlyZXNJbjogdGhpcy5hY2Nlc3NFeHBpcmVzSW4gfSBhcyBhbnk7XG4gICAgcmV0dXJuIGp3dC5zaWduKGRhdGEsIHRoaXMuYWNjZXNzU2VjcmV0S2V5LCBvcHRpb25zKTtcbiAgfVxuXG4gIGdlbmVyYXRlUmVmcmVzaFRva2VuKGRhdGE6IHsgdXNlcklkOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHsgZXhwaXJlc0luOiB0aGlzLnJlZnJlc2hFeHBpcmVzSW4gfSBhcyBhbnk7XG4gICAgcmV0dXJuIGp3dC5zaWduKGRhdGEsIHRoaXMucmVmcmVzaFNlY3JldEtleSwgb3B0aW9ucyk7XG4gIH1cblxuICBhc3luYyBnZW5lcmF0ZVRva2Vucyh1c2VySWQpIHtcbiAgICBjb25zdCB0b2tlbkRhdGEgPSB7IHVzZXJJZCB9XG4gICAgY29uc3QgYWNjZXNzVG9rZW4gPSBhd2FpdCB0aGlzLmdlbmVyYXRlQWNjZXNzVG9rZW4odG9rZW5EYXRhKTtcbiAgICBjb25zdCByZWZyZXNoVG9rZW4gPSBhd2FpdCB0aGlzLmdlbmVyYXRlUmVmcmVzaFRva2VuKHRva2VuRGF0YSk7XG4gICAgY29uc3QgYWNjZXNzVG9rZW5FeHBpcmVzQXQgPSB0aGlzLmdldFRva2VuRXhwaXJlKGFjY2Vzc1Rva2VuKTtcbiAgICBjb25zdCByZWZyZXNoVG9rZW5FeHBpcmVzQXQgPSB0aGlzLmdldFRva2VuRXhwaXJlKHJlZnJlc2hUb2tlbik7XG4gICAgYXdhaXQgdGhpcy5zdG9yZVJlZnJlc2hUb2tlbih1c2VySWQsIHJlZnJlc2hUb2tlbik7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWNjZXNzVG9rZW4sXG4gICAgICByZWZyZXNoVG9rZW4sXG4gICAgICBhY2Nlc3NUb2tlbkV4cGlyZXNBdCxcbiAgICAgIHJlZnJlc2hUb2tlbkV4cGlyZXNBdCxcbiAgICB9XG4gIH1cblxuICBhc3luYyByZWZyZXNoVG9rZW5zKCkge1xuICAgIGNvbnN0IG5ld1JlZnJlc2hUb2tlbiA9IGdldENvb2tpZSgncmVmcmVzaFRva2VuJyk7XG4gICAgY29uc3QgdXNlcklkID0gdGhpcy52ZXJpZnlSZWZyZXNoVG9rZW4obmV3UmVmcmVzaFRva2VuKTtcbiAgICBjb25zdCB1c2VyRXhpc3RzID0gYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkuaXNVc2VyRXhpc3RzKHVzZXJJZCk7XG5cbiAgICBpZiAoIXVzZXJFeGlzdHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcih0KCd1c2Vycy5lcnJvcnMubm90Rm91bmQnKSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RvcmVkUmVmcmVzaFRva2VuID0gYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkuZ2V0UmVmcmVzaFRva2VuKHVzZXJJZClcblxuICAgIGlmIChuZXdSZWZyZXNoVG9rZW4gIT0gc3RvcmVkUmVmcmVzaFRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IodCgnYXV0aC5lcnJvcnMucmVmcmVzaFRva2VuSW52YWxpZCcpKVxuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZW5lcmF0ZVRva2Vucyh1c2VySWQpXG4gIH1cblxuICBhc3luYyByZXZva2VUb2tlbih1c2VySWQpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkucmV2b2tlVG9rZW4odXNlcklkKVxuICB9XG5cbiAgYXN5bmMgZ2V0VXNlclBlcm1pc3Npb25zKGF1dGgpIHtcbiAgICBpZiAoIWF1dGgpIHJldHVybjtcbiAgICBjb25zdCB1c2VySWQgPSBhd2FpdCB0aGlzLmdldFVzZXJJZEJ5QWNjZXNzVG9rZW4oYXV0aCk7XG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5nZXRVc2VyUGVybWlzc2lvbnModXNlcklkKTtcbiAgICByZXR1cm4gcGVybWlzc2lvbnM7XG4gIH1cblxuICBhc3luYyBnZXRVc2VyUm9sZShhdXRoKSB7XG4gICAgaWYgKCFhdXRoKSByZXR1cm47XG4gICAgY29uc3QgdXNlcklkID0gYXdhaXQgdGhpcy5nZXRVc2VySWRCeUFjY2Vzc1Rva2VuKGF1dGgpO1xuICAgIGNvbnN0IHJvbGVOYW1lID0gYXdhaXQgdGhpcy50b2tlblJlcG9zaXRvcnkuZ2V0Um9sZU5hbWVCeUlkKHVzZXJJZCk7XG4gICAgcmV0dXJuIHJvbGVOYW1lO1xuICB9XG5cbiAgYXN5bmMgZ2V0VXNlcihhdXRoKSB7XG4gICAgaWYgKCFhdXRoKSByZXR1cm47XG4gICAgY29uc3QgdXNlcklkID0gYXdhaXQgdGhpcy5nZXRVc2VySWRCeUFjY2Vzc1Rva2VuKGF1dGgpO1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnRva2VuUmVwb3NpdG9yeS5nZXRVc2VyKHVzZXJJZCk7XG4gICAgaWYgKCF1c2VyKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdXNlcjtcbiAgfVxuXG4gIGFzeW5jIHN0b3JlVXNlckluQ2FjaGUoYXV0aCwgY3R4KSB7XG4gICAgY29uc3QgY2FjaGVkVXNlciA9IGN0eC5nZXQoJ3VzZXInKTtcbiAgICBpZiAoY2FjaGVkVXNlcikgcmV0dXJuIGNhY2hlZFVzZXI7XG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuZ2V0VXNlcihhdXRoKTtcbiAgICBpZiAodXNlcikge1xuICAgICAgY3R4LnNldCgndXNlcicsIHVzZXIpO1xuICAgIH1cbiAgICByZXR1cm4gdXNlcjtcbiAgfVxuXG59IiwKICAgICJpbXBvcnQgeyBDb250cm9sbGVyLCBHZXQsIFBvc3QsIFB1dCwgRGVsZXRlLCBQYXJhbXMsIEJvZHksdCwgVXNlciB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IFJvbGVTZXJ2aWNlIH0gZnJvbSAnLi9Sb2xlU2VydmljZSc7XG5pbXBvcnQgeyBpc0FkbWluIH0gZnJvbSAnLi9Sb2xlR3VhcmRzJztcblxuQENvbnRyb2xsZXIoJy9yb2xlcycpXG5leHBvcnQgY2xhc3MgUm9sZUNvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJvbGVTZXJ2aWNlOiBSb2xlU2VydmljZSxcbiAgKSB7IH1cblxuICBAR2V0KClcbiAgQGlzQWRtaW4oKVxuICBhc3luYyBnZXRSb2xlcygpIHtcbiAgICBjb25zdCByb2xlcyA9IGF3YWl0IHRoaXMucm9sZVNlcnZpY2UuZ2V0QWxsKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHJvbGVzLFxuICAgICAgbWVzc2FnZTogdCgncm9sZXMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBHZXQoJy86aWQnKVxuICBAaXNBZG1pbigpXG4gIGFzeW5jIGdldFJvbGUoQFBhcmFtcygnaWQnKSBpZCkge1xuICAgIGNvbnN0IHJvbGUgPSBhd2FpdCB0aGlzLnJvbGVTZXJ2aWNlLmdldEJ5SWQoaWQpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiByb2xlLFxuICAgICAgbWVzc2FnZTogdCgncm9sZXMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBQb3N0KClcbiAgQGlzQWRtaW4oKVxuICBhc3luYyBjcmVhdGVSb2xlKEBCb2R5KCkgYm9keSkge1xuICAgIGNvbnN0IG5ld1JvbGUgPSBhd2FpdCB0aGlzLnJvbGVTZXJ2aWNlLmNyZWF0ZShib2R5KTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogbmV3Um9sZSxcbiAgICAgIG1lc3NhZ2U6IHQoJ3JvbGVzLnN1Y2Nlc3MuY3JlYXRlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQFB1dCgnLzppZCcpXG4gIEBpc0FkbWluKClcbiAgYXN5bmMgdXBkYXRlUm9sZShAUGFyYW1zKCdpZCcpIGlkLCBAQm9keSgpIGJvZHkpIHtcbiAgICBjb25zdCB1cGRhdGVkUm9sZSA9IGF3YWl0IHRoaXMucm9sZVNlcnZpY2UudXBkYXRlKGlkLCBib2R5KTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogdXBkYXRlZFJvbGUsXG4gICAgICBtZXNzYWdlOiB0KCdyb2xlcy5zdWNjZXNzLnVwZGF0ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBEZWxldGUoJy86aWQnKVxuICBAaXNBZG1pbigpXG4gIGFzeW5jIGRlbGV0ZVJvbGUoQFBhcmFtcygnaWQnKSBpZCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucm9sZVNlcnZpY2UuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogcmVzdWx0LFxuICAgICAgbWVzc2FnZTogdCgncm9sZXMuc3VjY2Vzcy5kZWxldGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cbn0iLAogICAgIlxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IFJvbGVSZXBvc2l0b3J5IH0gZnJvbSAnLi9Sb2xlUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBSb2xlVmFsaWRhdG9yIH0gZnJvbSAnLi9Sb2xlVmFsaWRhdG9yJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFJvbGVTZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByb2xlUmVwb3NpdG9yeTogUm9sZVJlcG9zaXRvcnksXG4gICAgcHJpdmF0ZSByb2xlVmFsaWRhdG9yOiBSb2xlVmFsaWRhdG9yXG4gICkgeyB9XG5cbiAgYXN5bmMgZ2V0QWxsKCkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvbGVSZXBvc2l0b3J5LmdldEFsbCgpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QnlJZChpZCkge1xuICAgIGF3YWl0IHRoaXMucm9sZVZhbGlkYXRvci5jaGVja1JvbGVFeGlzdHMoaWQpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvbGVSZXBvc2l0b3J5LmdldEJ5SWQoaWQpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QnlOYW1lKG5hbWUpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5yb2xlUmVwb3NpdG9yeS5nZXRCeU5hbWUobmFtZSk7XG4gIH1cblxuICBhc3luYyBjcmVhdGUoZGF0YSkge1xuICAgIGF3YWl0IHRoaXMucm9sZVZhbGlkYXRvci52YWxpZGF0ZUNyZWF0ZVJvbGUoZGF0YSk7XG4gICAgYXdhaXQgdGhpcy5yb2xlVmFsaWRhdG9yLmNoZWNrTmFtZVVuaXF1ZShkYXRhLm5hbWUpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvbGVSZXBvc2l0b3J5LmNyZWF0ZShkYXRhKTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZShpZCwgZGF0YSkge1xuICAgIGF3YWl0IHRoaXMucm9sZVZhbGlkYXRvci5jaGVja1JvbGVFeGlzdHMoaWQpO1xuICAgIGF3YWl0IHRoaXMucm9sZVZhbGlkYXRvci5jaGVja05hbWVVbmlxdWUoZGF0YS5uYW1lLCBpZCk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucm9sZVJlcG9zaXRvcnkudXBkYXRlKGlkLCBkYXRhKTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZShpZCkge1xuICAgIGF3YWl0IHRoaXMucm9sZVZhbGlkYXRvci5jaGVja1JvbGVFeGlzdHMoaWQpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvbGVSZXBvc2l0b3J5LmRlbGV0ZShpZCk7XG4gIH1cblxuICBhc3luYyBzZWVkRGVmYXVsdFJvbGVzKGRlZmF1bHRSb2xlcykge1xuXG4gICAgY29uc3Qgcm9sZXNUb0NyZWF0ZSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCByb2xlIG9mIGRlZmF1bHRSb2xlcykge1xuICAgICAgY29uc3QgZXhpc3RzID0gYXdhaXQgdGhpcy5yb2xlVmFsaWRhdG9yLmlzUm9sZU5hbWVFeGlzdHMocm9sZS5uYW1lKTtcbiAgICAgIGlmICghZXhpc3RzKSB7XG4gICAgICAgIHJvbGVzVG9DcmVhdGUucHVzaChyb2xlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjcmVhdGVkUm9sZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHJvbGVzVG9DcmVhdGUubWFwKHJvbGUgPT4gdGhpcy5yb2xlUmVwb3NpdG9yeS5jcmVhdGUocm9sZSkpXG4gICAgKTtcblxuICAgIHJldHVybiBjcmVhdGVkUm9sZXM7XG4gIH1cblxuICBhc3luYyBnZXRSb2xlSWRCeU5hbWUobmFtZSkge1xuICAgIGNvbnN0IHRlYWNoZXJSb2xlID0gYXdhaXQgdGhpcy5nZXRCeU5hbWUobmFtZSk7XG4gICAgcmV0dXJuIHRlYWNoZXJSb2xlPy5pZDtcbiAgfVxuXG5cbn0iLAogICAgImltcG9ydCB7IENvbnRyb2xsZXIsIEdldCwgUG9zdCwgUHV0LCBEZWxldGUsIFBhcmFtcywgQm9keSwgdCB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IFVzZXJTZXJ2aWNlIH0gZnJvbSAnLi9Vc2VyU2VydmljZSc7XG5cbmltcG9ydCB7IGlzQWRtaW4sIGlzQXV0aCB9IGZyb20gJ0Avcm9sZXMvUm9sZUd1YXJkcyc7XG5cbkBDb250cm9sbGVyKCcvdXNlcnMnKVxuZXhwb3J0IGNsYXNzIFVzZXJDb250cm9sbGVyIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSB1c2VyU2VydmljZTogVXNlclNlcnZpY2UpIHsgfVxuXG4gIEBHZXQoKVxuICBAaXNBZG1pbigpIFxuICBhc3luYyBnZXRVc2VycygpIHtcbiAgICBjb25zdCB1c2VycyA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZ2V0QWxsKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHVzZXJzLFxuICAgICAgbWVzc2FnZTogdCgndXNlcnMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBHZXQoJy9sYW5nJylcbiAgQGlzQXV0aCgpIFxuICBhc3luYyBnZXRMYW5nKCkge1xuICAgIGNvbnN0IGxhbmd1YWdlID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS5nZXRMYW5nKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHsgbGFuZ3VhZ2UgfSxcbiAgICAgIG1lc3NhZ2U6IHQoJ3VzZXJzLnN1Y2Nlc3MucmV0cmlldmVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBAUG9zdCgnL2xhbmcvOmxhbmd1YWdlJylcbiAgQGlzQXV0aCgpIFxuICBhc3luYyB1cGRhdGVMYW5nKEBQYXJhbXMoJ2xhbmd1YWdlJykgbGFuZ3VhZ2UpIHtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy51c2VyU2VydmljZS51cGRhdGVMYW5nKGxhbmd1YWdlKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YSxcbiAgICAgIG1lc3NhZ2U6IHQoJ3VzZXJzLnN1Y2Nlc3MudXBkYXRlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQEdldCgnLzppZCcpXG4gIEBpc0FkbWluKCkgXG4gIGFzeW5jIGdldFVzZXIoQFBhcmFtcygnaWQnKSBpZCkge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldEJ5SWQoaWQpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiB1c2VyLFxuICAgICAgbWVzc2FnZTogdCgndXNlcnMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBHZXQoJy9lbWFpbC86ZW1haWwnKVxuICBAaXNBZG1pbigpXG4gIGFzeW5jIGdldEJ5RW1haWwoQFBhcmFtcygnZW1haWwnKSBlbWFpbCkge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmdldEJ5RW1haWwoZW1haWwpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiB1c2VyLFxuICAgICAgbWVzc2FnZTogdCgndXNlcnMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG5cbiAgQEdldCgnL3JvbGUvOnVzZXJJZCcpXG4gIEBpc0FkbWluKCkgXG4gIGFzeW5jIGdldFJvbGUoQFBhcmFtcygndXNlcklkJykgdXNlcklkKSB7XG4gICAgY29uc3Qgcm9sZSA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZ2V0Um9sZU5hbWUodXNlcklkKTtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiByb2xlLFxuICAgICAgbWVzc2FnZTogdCgndXNlcnMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBQb3N0KClcbiAgQGlzQWRtaW4oKSBcbiAgYXN5bmMgY3JlYXRlKEBCb2R5KCkgYm9keSkge1xuICAgIGNvbnN0IG5ld1VzZXIgPSBhd2FpdCB0aGlzLnVzZXJTZXJ2aWNlLmNyZWF0ZShib2R5KTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogbmV3VXNlcixcbiAgICAgIG1lc3NhZ2U6IHQoJ3VzZXJzLnN1Y2Nlc3MuY3JlYXRlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQFB1dCgnLzppZCcpXG4gIEBpc0FkbWluKCkgXG4gIGFzeW5jIHVwZGF0ZShAUGFyYW1zKCdpZCcpIGlkLCBAQm9keSgpIGJvZHkpIHtcbiAgICBjb25zdCB1cGRhdGVkVXNlciA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UudXBkYXRlKGlkLCBib2R5KTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogdXBkYXRlZFVzZXIsXG4gICAgICBtZXNzYWdlOiB0KCd1c2Vycy5zdWNjZXNzLnVwZGF0ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBEZWxldGUoJy86aWQnKVxuICBAaXNBZG1pbigpIFxuICBhc3luYyBkZWxldGUoQFBhcmFtcygnaWQnKSBpZCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogcmVzdWx0LFxuICAgICAgbWVzc2FnZTogdCgndXNlcnMuc3VjY2Vzcy5kZWxldGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBARGVsZXRlKClcbiAgQGlzQWRtaW4oKSBcbiAgYXN5bmMgZGVsZXRlQWxsKCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudXNlclNlcnZpY2UuZGVsZXRlQWxsKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHJlc3VsdCxcbiAgICAgIG1lc3NhZ2U6IHQoJ3VzZXJzLnN1Y2Nlc3MuYWxsRGVsZXRlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQFBvc3QoJy9hc3NpZ24vOnVzZXJJZC86cm9sZUlkJylcbiAgQGlzQWRtaW4oKSBcbiAgYXN5bmMgYXNzaWduUm9sZShAUGFyYW1zKCd1c2VySWQnKSB1c2VySWQsIEBQYXJhbXMoJ3JvbGVJZCcpIHJvbGVJZCkge1xuICAgIGF3YWl0IHRoaXMudXNlclNlcnZpY2UuYXNzaWduUm9sZSh1c2VySWQsIHJvbGVJZCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbWVzc2FnZTogdCgndXNlcnMuc3VjY2Vzcy51cGRhdGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBARGVsZXRlKCcvcmVtb3ZlLzp1c2VySWQnKVxuICBAaXNBZG1pbigpIFxuICBhc3luYyByZW1vdmVSb2xlKEBQYXJhbXMoJ3VzZXJJZCcpIHVzZXJJZCkge1xuICAgIGF3YWl0IHRoaXMudXNlclNlcnZpY2UucmVtb3ZlUm9sZSh1c2VySWQpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2U6IHQoJ3VzZXJzLnN1Y2Nlc3MudXBkYXRlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbn0iLAogICAgImV4cG9ydCBjb25zdCBFTlVNUyA9IHtcclxuICAvLyBDb3JlIFN5c3RlbVxyXG4gIHVzZXJUeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWRtaW4nLCAndGVhY2hlcicsICdzdHVkZW50JywgJ3BhcmVudCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdlbnVtcy51c2VyVHlwZSdcclxuICB9LFxyXG4gIHVzZXJTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydhY3RpdmUnLCAnaW5hY3RpdmUnLCAncGVuZGluZyddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdlbnVtcy51c2VyU3RhdHVzJ1xyXG4gIH0sXHJcbiAgdG9rZW5TdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydhY3RpdmUnLCAncmV2b2tlZCcsICdleHBpcmVkJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2VudW1zLnRva2VuU3RhdHVzJ1xyXG4gIH0sXHJcbiAgdG9rZW5UeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWNjZXNzJywgJ3JlZnJlc2gnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnZW51bXMudG9rZW5UeXBlJ1xyXG4gIH0sXHJcbiAgZmlsZVN0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ2FjdGl2ZScsICdkZWxldGVkJywgJ2FyY2hpdmVkJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2VudW1zLmZpbGVTdGF0dXMnXHJcbiAgfSxcclxuXHJcbiAgLy8gRWR1Y2F0aW9uYWwgU3lzdGVtXHJcbiAgZ2VuZGVyOiB7XHJcbiAgICB2YWx1ZXM6IFsnTScsICdGJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2NvbW1vbi5nZW5kZXInXHJcbiAgfSxcclxuICBzdHVkZW50U3RhdHVzOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWN0aXZlJywgJ2luYWN0aXZlJywgJ2dyYWR1YXRlZCcsICd0cmFuc2ZlcnJlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdzdHVkZW50cy5zdGF0dXMnXHJcbiAgfSxcclxuICB0ZWFjaGVyU3RhdHVzOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWN0aXZlJywgJ2luYWN0aXZlJywgJ29uTGVhdmUnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAndGVhY2hlcnMuc3RhdHVzJyxcclxuICB9LFxyXG4gIGVtcGxveW1lbnRUeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnZnVsbFRpbWUnLCAncGFydFRpbWUnLCAnY29udHJhY3QnLCAndGVtcG9yYXJ5J10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RlYWNoZXJzLmVtcGxveW1lbnRUeXBlJyxcclxuICB9LFxyXG4gIHJlbGF0aW9uc2hpcFR5cGU6IHtcclxuICAgIHZhbHVlczogWydmYXRoZXInLCAnbW90aGVyJywgJ2d1YXJkaWFuJywgJ3N0ZXBwYXJlbnQnLCAnZ3JhbmRwYXJlbnQnLCAnb3RoZXInXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAncGFyZW50cy5yZWxhdGlvbnNoaXBzJ1xyXG4gIH0sXHJcbiAgc2VtZXN0ZXI6IHtcclxuICAgIHZhbHVlczogWydzcHJpbmcnLCAnc3VtbWVyJywgJ2ZhbGwnLCAnd2ludGVyJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2FjYWRlbWljLnNlbWVzdGVyJ1xyXG4gIH0sXHJcbiAgY2xhc3NTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydhY3RpdmUnLCAnY29tcGxldGVkJywgJ2NhbmNlbGxlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdjbGFzc2VzLnN0YXR1cydcclxuICB9LFxyXG4gIHNlY3Rpb25TdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydhY3RpdmUnLCAnaW5hY3RpdmUnLCAnYXJjaGl2ZWQnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnc2VjdGlvbnMuc3RhdHVzJ1xyXG4gIH0sXHJcbiAgbGFuZ3VhZ2U6IHtcclxuICAgIHZhbHVlczogWydlbicsICdmcicsICdhcicsICdlcyddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdjb21tb24ubGFuZ3VhZ2VzJ1xyXG4gIH0sXHJcbiAgZW5yb2xsbWVudFN0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ2Vucm9sbGVkJywgJ2NvbXBsZXRlZCcsICdkcm9wcGVkJywgJ2ZhaWxlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdlbnJvbGxtZW50cy5zdGF0dXMnXHJcbiAgfSxcclxuICBhc3NpZ25tZW50U3RhdHVzOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWN0aXZlJywgJ2NvbXBsZXRlZCcsICdjYW5jZWxsZWQnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnYXNzaWdubWVudHMuc3RhdHVzJ1xyXG4gIH0sXHJcblxyXG4gIGNhbGVuZGFyU3lzdGVtOiB7XHJcbiAgICB2YWx1ZXM6IFsnU0VNRVNURVInLCAnVFJJTUVTVEVSJywgJ1FVQVJURVInXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnc2V0dGluZ3MuY2FsZW5kYXJTeXN0ZW0nXHJcbiAgfSxcclxuXHJcbiAgLy8gQXNzZXNzbWVudCAmIEV4YW1zXHJcbiAgYXNzZXNzbWVudFR5cGU6IHtcclxuICAgIHZhbHVlczogWydxdWl6JywgJ2Fzc2lnbm1lbnQnLCAncHJvamVjdCcsICdwYXJ0aWNpcGF0aW9uJywgJ3Rlc3QnLCAncHJlc2VudGF0aW9uJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2Fzc2Vzc21lbnRzLnR5cGUnXHJcbiAgfSxcclxuICBhc3Nlc3NtZW50U3RhdHVzOiB7XHJcbiAgICB2YWx1ZXM6IFsnc2NoZWR1bGVkJywgJ2FjdGl2ZScsICdjb21wbGV0ZWQnLCAnY2FuY2VsbGVkJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2Fzc2Vzc21lbnRzLnN0YXR1cydcclxuICB9LFxyXG4gIHN1Ym1pc3Npb25UeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnb25saW5lJywgJ3BhcGVyJywgJ3ByZXNlbnRhdGlvbicsICdwcmFjdGljYWwnLCAnZGlzY3Vzc2lvbiddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdhc3Nlc3NtZW50cy5zdWJtaXNzaW9uVHlwZSdcclxuICB9LFxyXG4gIGV4YW1UeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnbWlkdGVybScsICdmaW5hbCcsICdzdGFuZGFyZGl6ZWQnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnZXhhbXMudHlwZSdcclxuICB9LFxyXG4gIGV4YW1TZWN1cml0eToge1xyXG4gICAgdmFsdWVzOiBbJ2xvdycsICdtZWRpdW0nLCAnaGlnaCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdleGFtcy5zZWN1cml0eSdcclxuICB9LFxyXG4gIGV4YW1TdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydzY2hlZHVsZWQnLCAnYWN0aXZlJywgJ2NvbXBsZXRlZCcsICdjYW5jZWxsZWQnLCAncmVzY2hlZHVsZWQnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnZXhhbXMuc3RhdHVzJ1xyXG4gIH0sXHJcbiAgZ3JhZGVTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydncmFkZWQnLCAncGVuZGluZycsICdkcmFmdCcsICdyZXZpZXdlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdncmFkZXMuc3RhdHVzJ1xyXG4gIH0sXHJcbiAgYXR0ZW5kYW5jZVN0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ3ByZXNlbnQnLCAnYWJzZW50JywgJ2xhdGUnLCAnZXhjdXNlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdhdHRlbmRhbmNlLnN0YXR1cydcclxuICB9LFxyXG4gIHByb2ZpY2llbmN5TGV2ZWw6IHtcclxuICAgIHZhbHVlczogWydiZWdpbm5lcicsICdpbnRlcm1lZGlhdGUnLCAnYWR2YW5jZWQnLCAnZXhwZXJ0J10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2NvbW1vbi5wcm9maWNpZW5jeUxldmVsJ1xyXG4gIH0sXHJcbiAgZGF5T2ZXZWVrOiB7XHJcbiAgICB2YWx1ZXM6IFsnbW9uZGF5JywgJ3R1ZXNkYXknLCAnd2VkbmVzZGF5JywgJ3RodXJzZGF5JywgJ2ZyaWRheScsICdzYXR1cmRheScsICdzdW5kYXknXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnY29tbW9uLmRheXMnXHJcbiAgfSxcclxuXHJcbiAgLy8gQWxlcnRzXHJcbiAgYWxlcnRUeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWNhZGVtaWMnLCAnYXR0ZW5kYW5jZScsICdiZWhhdmlvcmFsJywgJ2hlYWx0aCcsICdzeXN0ZW0nLCAnYW5ub3VuY2VtZW50JywgJ3JlbWluZGVyJywgJ2VtZXJnZW5jeSddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdhbGVydHMudHlwZSdcclxuICB9LFxyXG4gIGFsZXJ0UHJpb3JpdHk6IHtcclxuICAgIHZhbHVlczogWydsb3cnLCAnbWVkaXVtJywgJ2hpZ2gnLCAnY3JpdGljYWwnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnYWxlcnRzLnByaW9yaXR5J1xyXG4gIH0sXHJcbiAgYWxlcnRTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydhY3RpdmUnLCAnYWNrbm93bGVkZ2VkJywgJ3Jlc29sdmVkJywgJ2Rpc21pc3NlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdhbGVydHMuc3RhdHVzJ1xyXG4gIH0sXHJcblxyXG4gIC8vIEZlZXMgJiBQYXltZW50c1xyXG4gIGZlZVR5cGVTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydhY3RpdmUnLCAnaW5hY3RpdmUnLCAnYXJjaGl2ZWQnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnZmVlcy50eXBlU3RhdHVzJ1xyXG4gIH0sXHJcbiAgZmVlQ2F0ZWdvcnk6IHtcclxuICAgIHZhbHVlczogWyd0dWl0aW9uJywgJ3JlZ2lzdHJhdGlvbicsICd0cmFuc3BvcnQnLCAnY2FmZXRlcmlhJywgJ2Jvb2tzJywgJ3Nwb3J0cycsICd1bmlmb3JtJywgJ3RlY2hub2xvZ3knLCAnZmllbGR0cmlwJywgJ290aGVyJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2ZlZVR5cGVzLmNhdGVnb3J5J1xyXG4gIH0sXHJcbiAgcGF5bWVudFR5cGU6IHtcclxuICAgIHZhbHVlczogWydyZWN1cnJpbmcnLCAnb25lVGltZSddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdwYXltZW50cy50eXBlJyxcclxuICB9LFxyXG4gIHNjaGVkdWxlOiB7XHJcbiAgICB2YWx1ZXM6IFsnbW9udGhseScsICdxdWFydGVybHknLCAnc2VtZXN0ZXInLCAnYW5udWFsbHknLCAnb25lVGltZSddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdmZWVzLnNjaGVkdWxlJyxcclxuICB9LFxyXG4gIGZlZVN0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ3BlbmRpbmcnLCAncGFydGlhbGx5UGFpZCcsICdwYWlkJywgJ292ZXJkdWUnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnZmVlcy5zdGF0dXMnLFxyXG4gIH0sXHJcbiAgZmVlSW5zdGFsbG1lbnRTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydwZW5kaW5nJywgJ3BhcnRpYWxseVBhaWQnLCAncGFpZCcsICdvdmVyZHVlJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2ZlZXMuaW5zdGFsbG1lbnRTdGF0dXMnLFxyXG4gIH0sXHJcbiAgcGF5bWVudE1ldGhvZDoge1xyXG4gICAgdmFsdWVzOiBbJ2Nhc2gnLCAnYmFua1RyYW5zZmVyJywgJ2NoZWNrJywgJ2NyZWRpdENhcmQnLCAnZGViaXRDYXJkJywgJ29ubGluZScsICdtb2JpbGVQYXltZW50J10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3BheW1lbnRzLm1ldGhvZHMnLFxyXG4gIH0sXHJcbiAgXHJcbiAgcGF5bWVudFN0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ2NvbXBsZXRlZCcsICdwZW5kaW5nJywgJ2ZhaWxlZCcsICdyZWZ1bmRlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdwYXltZW50cy5zdGF0dXMnXHJcbiAgfSxcclxuXHJcbiAgLy8gRXZlbnRzXHJcbiAgZXZlbnRUeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWNhZGVtaWMnLCAnc3BvcnRzJywgJ2N1bHR1cmFsJywgJ2hvbGlkYXknLCAnZXhhbScsICdtZWV0aW5nJywgJ3dvcmtzaG9wJywgJ2ZpZWxkdHJpcCcsICdjZXJlbW9ueScsICdjb25mZXJlbmNlJywgJ290aGVyJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2V2ZW50cy50eXBlJ1xyXG4gIH0sXHJcbiAgZXZlbnRTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydzY2hlZHVsZWQnLCAnb25nb2luZycsICdjb21wbGV0ZWQnLCAnY2FuY2VsbGVkJywgJ3Bvc3Rwb25lZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdldmVudHMuc3RhdHVzJ1xyXG4gIH0sXHJcbiAgZXZlbnRWaXNpYmlsaXR5OiB7XHJcbiAgICB2YWx1ZXM6IFsncHVibGljJywgJ3ByaXZhdGUnLCAndGVhY2hlcnMnLCAnc3R1ZGVudHMnLCAncGFyZW50cycsICdzdGFmZiddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdldmVudHMudmlzaWJpbGl0eSdcclxuICB9LFxyXG4gIHBhcnRpY2lwYW50VHlwZToge1xyXG4gICAgdmFsdWVzOiBbJ3N0dWRlbnQnLCAndGVhY2hlcicsICdwYXJlbnQnLCAnc3RhZmYnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAnZXZlbnRzLnBhcnRpY2lwYW50VHlwZSdcclxuICB9LFxyXG5cclxuICAvLyBFeHBlbnNlc1xyXG4gIGV4cGVuc2VDYXRlZ29yeToge1xyXG4gICAgdmFsdWVzOiBbJ3NhbGFyeScsICd1dGlsaXRpZXMnLCAnbWFpbnRlbmFuY2UnLCAnc3VwcGxpZXMnLCAnZXF1aXBtZW50JywgJ3RyYW5zcG9ydCcsICdmb29kJywgJ3NlY3VyaXR5JywgJ2NsZWFuaW5nJywgJ2luc3VyYW5jZScsICdyZW50JywgJ3RheCcsICdtYXJrZXRpbmcnLCAndHJhaW5pbmcnLCAndGVjaG5vbG9neScsICdtaXNjZWxsYW5lb3VzJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ2V4cGVuc2VzLmNhdGVnb3JpZXMnXHJcbiAgfSxcclxuICBleHBlbnNlU3RhdHVzOiB7XHJcbiAgICB2YWx1ZXM6IFsncGVuZGluZycsICdhcHByb3ZlZCcsICdwYWlkJywgJ3JlamVjdGVkJywgJ2NhbmNlbGxlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdleHBlbnNlcy5zdGF0dXMnXHJcbiAgfSxcclxuXHJcbiAgLy8gVHJhY2tlclxyXG4gIHRyYWNrZXJNb2RlOiB7XHJcbiAgICB2YWx1ZXM6IFsndHJhY2tpbmcnLCAnZ3BycycsICdzbXMnLCAnc2xlZXBUaW1lJywgJ3NsZWVwU2hvY2snLCAnc2xlZXBEZWVwJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RyYWNrZXIubW9kZScsXHJcbiAgfSxcclxuXHJcbiAgLy8gVHJhbnNwb3J0XHJcbiAgZHJpdmVyU3RhdHVzOiB7XHJcbiAgICB2YWx1ZXM6IFsnYWN0aXZlJywgJ2luYWN0aXZlJywgJ29uTGVhdmUnLCAnc3VzcGVuZGVkJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RyYW5zcG9ydC5kcml2ZXJTdGF0dXMnLFxyXG4gIH0sXHJcbiAgdmVoaWNsZVN0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ2FjdGl2ZScsICdpbmFjdGl2ZScsICdtYWludGVuYW5jZScsICdyZXRpcmVkJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RyYW5zcG9ydC52ZWhpY2xlU3RhdHVzJ1xyXG4gIH0sXHJcbiAgdmVoaWNsZVR5cGU6IHtcclxuICAgIHZhbHVlczogWydzZWRhbicsICdtaW5pYnVzJywgJ2Z1bGxidXMnLCAnc2h1dHRsZSddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICd0cmFuc3BvcnQudmVoaWNsZVR5cGUnXHJcbiAgfSxcclxuICB2ZWhpY2xlRG9jdW1lbnRUeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnaW5zdXJhbmNlJywgJ3JlZ2lzdHJhdGlvbicsICdpbnNwZWN0aW9uJywgJ2VtaXNzaW9uJywgJ2xpY2Vuc2UnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAndHJhbnNwb3J0LmRvY3VtZW50VHlwZSdcclxuICB9LFxyXG4gIGJ1c1N0YXR1czoge1xyXG4gICAgdmFsdWVzOiBbJ2FjdGl2ZScsICdpbmFjdGl2ZScsICdtYWludGVuYW5jZScsICdyZXRpcmVkJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RyYW5zcG9ydC5idXNTdGF0dXMnXHJcbiAgfSxcclxuICByZWZ1ZWxTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydwZW5kaW5nJywgJ2NvbXBsZXRlZCcsICdjYW5jZWxsZWQnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAndHJhbnNwb3J0LnJlZnVlbFN0YXR1cydcclxuICB9LFxyXG4gIGZ1ZWxUeXBlOiB7XHJcbiAgICB2YWx1ZXM6IFsnZ2Fzb2xpbmUnLCAnZGllc2VsJywgJ2VsZWN0cmljJywgJ2h5YnJpZCcsICdscGcnLCAnY25nJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RyYW5zcG9ydC5mdWVsVHlwZSdcclxuICB9LFxyXG4gIG1haW50ZW5hbmNlVHlwZToge1xyXG4gICAgdmFsdWVzOiBbJ3NjaGVkdWxlZCcsICdyZXBhaXInLCAnaW5zcGVjdGlvbicsICdvaWxDaGFuZ2UnLCAnZmlsdGVyQ2hhbmdlJywgJ290aGVyJ10sXHJcbiAgICB0cmFuc2xhdGlvbktleTogJ3RyYW5zcG9ydC5tYWludGVuYW5jZVR5cGUnLFxyXG4gIH0sXHJcbiAgbWFpbnRlbmFuY2VTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydzY2hlZHVsZWQnLCAnaW5Qcm9ncmVzcycsICdjb21wbGV0ZWQnLCAnY2FuY2VsbGVkJywgJ292ZXJkdWUnXSxcclxuICAgIHRyYW5zbGF0aW9uS2V5OiAndHJhbnNwb3J0Lm1haW50ZW5hbmNlU3RhdHVzJyxcclxuICB9LFxyXG5cclxuICAvLyBQZXJzb25hbFxyXG4gIG1hcml0YWxTdGF0dXM6IHtcclxuICAgIHZhbHVlczogWydzaW5nbGUnLCAnbWFycmllZCcsICdkaXZvcmNlZCcsICd3aWRvd2VkJywgJ3NlcGFyYXRlZCddLFxyXG4gICAgdHJhbnNsYXRpb25LZXk6ICdwYXJlbnRzLm1hcml0YWxTdGF0dXMnXHJcbiAgfVxyXG59XHJcblxyXG4vLyBIZWxwZXIgZnVuY3Rpb25zXHJcbmV4cG9ydCBjb25zdCBnZXRFbnVtQ29uZmlnID0gKGVudW1LZXkpID0+IEVOVU1TW2VudW1LZXldXHJcbmV4cG9ydCBjb25zdCBnZXRFbnVtVmFsdWVzID0gKGVudW1LZXkpID0+IEVOVU1TW2VudW1LZXldPy52YWx1ZXMgfHwgW10iLAogICAgImltcG9ydCB7IHogfSBmcm9tICd6b2QnO1xuaW1wb3J0IHsgYWxlcnRQcmlvcml0eUVudW0sIGFsZXJ0U3RhdHVzRW51bSwgYWxlcnRUeXBlRW51bSwgYXNzZXNzbWVudFN0YXR1c0VudW0sIGFzc2Vzc21lbnRUeXBlRW51bSwgYXR0ZW5kYW5jZVN0YXR1c0VudW0sIGNhbGVuZGFyU3lzdGVtRW51bSwgZHJpdmVyU3RhdHVzRW51bSwgZW1wbG95bWVudFR5cGVFbnVtLCBldmVudFN0YXR1c0VudW0sIGV2ZW50VHlwZUVudW0sIGV2ZW50VmlzaWJpbGl0eUVudW0sIGV4YW1TdGF0dXNFbnVtLCBleGFtVHlwZUVudW0sIGV4cGVuc2VDYXRlZ29yeUVudW0sIGV4cGVuc2VTdGF0dXNFbnVtLCBmZWVTdGF0dXNFbnVtLCBmZWVUeXBlU3RhdHVzRW51bSwgZnVlbFR5cGVFbnVtLCBnZW5kZXJFbnVtLCBncmFkZVN0YXR1c0VudW0sIGxhbmd1YWdlRW51bSwgcGFydGljaXBhbnRUeXBlRW51bSwgcGF5bWVudE1ldGhvZEVudW0sIGZlZUluc3RhbGxtZW50U3RhdHVzRW51bSwgcGF5bWVudFN0YXR1c0VudW0sIHBheW1lbnRUeXBlRW51bSwgcmVmdWVsU3RhdHVzRW51bSwgcmVsYXRpb25zaGlwVHlwZUVudW0sIHNjaGVkdWxlRW51bSwgc2VjdGlvblN0YXR1c0VudW0sIHN0dWRlbnRTdGF0dXNFbnVtLCB0ZWFjaGVyU3RhdHVzRW51bSwgdXNlclN0YXR1c0VudW0sIHZlaGljbGVTdGF0dXNFbnVtLCB2ZWhpY2xlVHlwZUVudW0gfSBmcm9tICcuL1pvZEVudW0nO1xuXG5jb25zdCByZXF1aXJlZElkID0gei5wcmVwcm9jZXNzKCh2YWwpID0+IHZhbCA/PyBcIlwiLCB6LnN0cmluZygpLm1pbigxLCBcIklEIGlzIHJlcXVpcmVkXCIpKTtcbmNvbnN0IG9wdGlvbmFsSWQgPSB6LnN0cmluZygpLm1pbigxLCBcIklEIGNhbm5vdCBiZSBlbXB0eVwiKS5udWxsaXNoKCkub3B0aW9uYWwoKTtcbmNvbnN0IGVtYWlsRmllbGQgPSB6LnN0cmluZygpLmVtYWlsKCdJbnZhbGlkIGVtYWlsIGZvcm1hdCcpLm9yKHoubGl0ZXJhbChcIlwiKSk7XG5jb25zdCBwaG9uZUZpZWxkID0gei5zdHJpbmcoKS5yZWdleCgvXltcXCtdP1sxLTldW1xcZF17MCwxNX0kLywgJ0ludmFsaWQgcGhvbmUgbnVtYmVyJyk7XG5jb25zdCBuYW1lRmllbGQgPSB6LnN0cmluZygpLm1pbigyLCAnTmFtZSBtdXN0IGJlIGF0IGxlYXN0IDIgY2hhcmFjdGVycycpLm1heCgxMDAsICdOYW1lIHRvbyBsb25nJyk7XG5jb25zdCBkYXRlRmllbGQgPSB6LnN0cmluZygpLnJlZ2V4KC9eKFxcZHs0fS1cXGR7Mn0tXFxkezJ9fFxcZHsyfVxcL1xcZHsyfVxcL1xcZHs0fXxcXGR7Mn0tXFxkezJ9LVxcZHsyfXxcXGR7Mn0tXFxkezJ9LVxcZHs0fSkkLywgJ0RhdGUgbXVzdCBiZSBpbiBZWVlZLU1NLURELCBNTS9ERC9ZWVlZLCBERC9NTS9ZWVlZLCBERC1NTS1ZWSwgb3IgREQtTU0tWVlZWSBmb3JtYXQnKTtcbmNvbnN0IG9wdGlvbmFsRGF0ZUZpZWxkID0gei5zdHJpbmcoKS5yZWdleCgvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9JC8sICdEYXRlIG11c3QgYmUgaW4gWVlZWS1NTS1ERCBmb3JtYXQnKS5udWxsYWJsZSgpLm9wdGlvbmFsKCk7XG5jb25zdCB0aW1lRmllbGQgPSB6LnN0cmluZygpLnJlZ2V4KC9eKFswMV0/WzAtOV18MlswLTNdKTpbMC01XVswLTldJC8sICdUaW1lIG11c3QgYmUgaW4gSEg6TU0gZm9ybWF0Jykub3B0aW9uYWwoKS5udWxsYWJsZSgpO1xuY29uc3QgY2luRmllbGQgPSB6LnN0cmluZygpLm1pbig4LCAnQ0lOIG11c3QgYmUgYXQgbGVhc3QgOCBjaGFyYWN0ZXJzJykubWF4KDIwLCAnQ0lOIHRvbyBsb25nJyk7XG5jb25zdCBhZGRyZXNzRmllbGQgPSB6LnN0cmluZygpLm1heCg1MDAsICdBZGRyZXNzIHRvbyBsb25nJykub3B0aW9uYWwoKTtcbmNvbnN0IGFjYWRlbWljWWVhckZpZWxkID0gei5zdHJpbmcoKS5taW4oOSwgJ0FjYWRlbWljIHllYXIgaXMgcmVxdWlyZWQnKS5yZWdleCgvXlxcZHs0fS1cXGR7NH0kLywgJ0FjYWRlbWljIHllYXIgbXVzdCBiZSBpbiBZWVlZLVlZWVkgZm9ybWF0Jyk7XG5cblxuY29uc3QgbnVtID0gKCkgPT4ge1xuICBjb25zdCBjcmVhdGVDaGFpbmFibGUgPSAoY3VycmVudFNjaGVtYTogei5ab2RUeXBlQW55KTogYW55ID0+IHtcbiAgICBjb25zdCBtZXRob2RzID0ge1xuICAgICAgcG9zaXRpdmU6IChtc2cgPSAnTXVzdCBiZSBwb3NpdGl2ZScpID0+XG4gICAgICAgIGNyZWF0ZUNoYWluYWJsZShjdXJyZW50U2NoZW1hLnJlZmluZSgodmFsOiBudW1iZXIpID0+IHZhbCA+IDAsIHsgbWVzc2FnZTogbXNnIH0pKSxcblxuICAgICAgbWluOiAodmFsdWU6IG51bWJlciwgbXNnPzogc3RyaW5nKSA9PlxuICAgICAgICBjcmVhdGVDaGFpbmFibGUoY3VycmVudFNjaGVtYS5yZWZpbmUoXG4gICAgICAgICAgKHZhbDogbnVtYmVyKSA9PiB2YWwgPj0gdmFsdWUsXG4gICAgICAgICAgeyBtZXNzYWdlOiBtc2cgfHwgYE11c3QgYmUgYXQgbGVhc3QgJHt2YWx1ZX1gIH1cbiAgICAgICAgKSksXG5cbiAgICAgIG1heDogKHZhbHVlOiBudW1iZXIsIG1zZz86IHN0cmluZykgPT5cbiAgICAgICAgY3JlYXRlQ2hhaW5hYmxlKGN1cnJlbnRTY2hlbWEucmVmaW5lKFxuICAgICAgICAgICh2YWw6IG51bWJlcikgPT4gdmFsIDw9IHZhbHVlLFxuICAgICAgICAgIHsgbWVzc2FnZTogbXNnIHx8IGBDYW5ub3QgZXhjZWVkICR7dmFsdWV9YCB9XG4gICAgICAgICkpLFxuXG4gICAgICBpbnQ6IChtc2cgPSAnTXVzdCBiZSBhbiBpbnRlZ2VyJykgPT5cbiAgICAgICAgY3JlYXRlQ2hhaW5hYmxlKGN1cnJlbnRTY2hlbWEucmVmaW5lKFxuICAgICAgICAgICh2YWw6IG51bWJlcikgPT4gTnVtYmVyLmlzSW50ZWdlcih2YWwpLFxuICAgICAgICAgIHsgbWVzc2FnZTogbXNnIH1cbiAgICAgICAgKSlcbiAgICB9O1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oY3VycmVudFNjaGVtYSwgbWV0aG9kcyk7XG4gIH07XG5cbiAgY29uc3QgaXNWYWxpZE51bWJlciA9ICh2YWw6IGFueSkgPT4ge1xuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQgfHwgTnVtYmVyLmlzTmFOKHZhbCkpIHJldHVybiBmYWxzZTtcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHJldHVybiB0cnVlO1xuICAgIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgdHJpbW1lZCA9IHZhbC50cmltKCk7XG4gICAgICByZXR1cm4gdHJpbW1lZCAhPT0gJycgJiYgIWlzTmFOKE51bWJlcih0cmltbWVkKSk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICBjb25zdCBiYXNlU2NoZW1hID0gei5hbnkoKVxuICAgIC5yZWZpbmUoaXNWYWxpZE51bWJlciwgeyBtZXNzYWdlOiAnTXVzdCBiZSBhIHZhbGlkIG51bWJlcicgfSlcbiAgICAudHJhbnNmb3JtKCh2YWwpID0+IHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gTnVtYmVyKHZhbCkgOiB2YWwpO1xuXG4gIHJldHVybiBjcmVhdGVDaGFpbmFibGUoYmFzZVNjaGVtYSk7XG59O1xuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuLy8gVVNFUi1ST0xFIFZBTElEQVRJT04gU0NIRU1BXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG5cbmV4cG9ydCBjb25zdCB1c2VyU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogb3B0aW9uYWxJZCxcbiAgdXNlcm5hbWU6IG5hbWVGaWVsZC5tYXgoNTApLm9wdGlvbmFsKCksXG4gIGVtYWlsOiBlbWFpbEZpZWxkLFxuICBwYXNzd29yZDogei5zdHJpbmcoKS5taW4oOCwgXCJQYXNzd29yZCBtdXN0IGJlIGF0IGxlYXN0IDggY2hhcmFjdGVyc1wiKSxcbiAgcm9sZUlkOiBvcHRpb25hbElkLFxuICByb2xlTmFtZTogbmFtZUZpZWxkLm1heCg1MCkub3B0aW9uYWwoKSxcbiAgbGFzdExvZ2luOiBvcHRpb25hbERhdGVGaWVsZCxcbiAgaW1hZ2U6IHoudW5pb24oW3ouc3RyaW5nKCksIHouaW5zdGFuY2VvZihGaWxlKSwgei51bmRlZmluZWQoKV0pLm9wdGlvbmFsKCksXG4gIGVtYWlsVmVyaWZpZWQ6IHouYm9vbGVhbigpLmRlZmF1bHQoZmFsc2UpLFxuICBzdGF0dXM6IHVzZXJTdGF0dXNFbnVtLFxuICBjcmVhdGVkQXQ6IG9wdGlvbmFsRGF0ZUZpZWxkLFxufSk7XG5cbmV4cG9ydCBjb25zdCByb2xlU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogb3B0aW9uYWxJZCxcbiAgbmFtZTogbmFtZUZpZWxkLm1heCg1MCksXG4gIGRlc2NyaXB0aW9uOiB6LnN0cmluZygpLm1heCgyNTUsIFwiRGVzY3JpcHRpb24gdG9vIGxvbmdcIikub3B0aW9uYWwoKSxcbiAgY3JlYXRlZEF0OiBvcHRpb25hbERhdGVGaWVsZCxcbn0pO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG4vLyBQRU9QTEUgVkFMSURBVElPTiBTQ0hFTUFTXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG5cbmV4cG9ydCBjb25zdCBzdHVkZW50U2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogb3B0aW9uYWxJZCxcbiAgY2xhc3NJZDogcmVxdWlyZWRJZCxcbiAgc2VjdGlvbklkOiByZXF1aXJlZElkLFxuICBzdHVkZW50Q29kZTogei5zdHJpbmcoKSxcbiAgbmFtZTogbmFtZUZpZWxkLFxuICBlbWFpbDogZW1haWxGaWVsZCxcbiAgcGhvbmU6IHBob25lRmllbGQubnVsbGlzaCgpLFxuICBhZGRyZXNzOiBhZGRyZXNzRmllbGQsXG4gIGRhdGVPZkJpcnRoOiBvcHRpb25hbERhdGVGaWVsZCxcbiAgZ2VuZGVyOiBnZW5kZXJFbnVtLFxuICBlbnJvbGxtZW50RGF0ZTogZGF0ZUZpZWxkLFxuICBtZWRpY2FsQ29uZGl0aW9uczogei5zdHJpbmcoKS5tYXgoMTAwMCwgJ01lZGljYWwgY29uZGl0aW9ucyBkZXNjcmlwdGlvbiB0b28gbG9uZycpLm51bGxpc2goKS5vcHRpb25hbCgpLFxuICBwcmV2aW91c1NjaG9vbDogei5zdHJpbmcoKS5tYXgoNTAwLCAnUHJldmlvdXMgc2Nob29sIG5hbWUgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIGltYWdlOiB6LnVuaW9uKFt6LnN0cmluZygpLCB6Lmluc3RhbmNlb2YoRmlsZSksIHoubnVsbCgpXSkub3B0aW9uYWwoKSxcbiAgc3RhdHVzOiBzdHVkZW50U3RhdHVzRW51bS5kZWZhdWx0KCdhY3RpdmUnKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgcGFyZW50U2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogb3B0aW9uYWxJZCxcbiAgbmFtZTogbmFtZUZpZWxkLFxuICBlbWFpbDogZW1haWxGaWVsZC5vcHRpb25hbCgpLFxuICBwaG9uZTogcGhvbmVGaWVsZCxcbiAgZ2VuZGVyOiBnZW5kZXJFbnVtLm9wdGlvbmFsKCksXG4gIGFkZHJlc3M6IGFkZHJlc3NGaWVsZCxcbiAgZGF0ZU9mQmlydGg6IG9wdGlvbmFsRGF0ZUZpZWxkLFxuICBjaW46IGNpbkZpZWxkLFxuICBvY2N1cGF0aW9uOiB6LnN0cmluZygpLm1heCgxMDAsICdPY2N1cGF0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgbmF0aW9uYWxpdHk6IHouc3RyaW5nKCkubWF4KDEwMCwgJ05hdGlvbmFsaXR5IHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgbWFyaXRhbFN0YXR1czogei5zdHJpbmcoKS5tYXgoNTAsICdNYXJpdGFsIHN0YXR1cyB0b28gbG9uZycpLm9wdGlvbmFsKCksXG4gIHJlbGF0aW9uc2hpcFR5cGU6IHJlbGF0aW9uc2hpcFR5cGVFbnVtLFxuICBpbWFnZTogei51bmlvbihbei5zdHJpbmcoKSwgei5pbnN0YW5jZW9mKEZpbGUpLCB6Lm51bGwoKV0pLm9wdGlvbmFsKCksXG4gIGlzRW1lcmdlbmN5Q29udGFjdDogei5ib29sZWFuKCkub3B0aW9uYWwoKS5kZWZhdWx0KGZhbHNlKSxcbiAgZmluYW5jaWFsUmVzcG9uc2liaWxpdHk6IHouYm9vbGVhbigpLm9wdGlvbmFsKCkuZGVmYXVsdChmYWxzZSksXG59KTtcblxuZXhwb3J0IGNvbnN0IGRyaXZlclNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IG9wdGlvbmFsSWQsXG4gIG5hbWU6IG5hbWVGaWVsZCxcbiAgZW1haWw6IGVtYWlsRmllbGQsXG4gIGNpbjogY2luRmllbGQsXG4gIHBob25lOiBwaG9uZUZpZWxkLFxuICBhZGRyZXNzOiBhZGRyZXNzRmllbGQsXG4gIGdlbmRlcjogZ2VuZGVyRW51bS5vcHRpb25hbCgpLFxuICBsaWNlbnNlTnVtYmVyOiB6LnN0cmluZygpLm1pbig1LCAnTGljZW5zZSBudW1iZXIgbXVzdCBiZSBhdCBsZWFzdCA1IGNoYXJhY3RlcnMnKS5tYXgoMjAsICdMaWNlbnNlIG51bWJlciB0b28gbG9uZycpLFxuICBsaWNlbnNlVHlwZTogei5zdHJpbmcoKS5tYXgoMTAsICdMaWNlbnNlIHR5cGUgdG9vIGxvbmcnKSxcbiAgbGljZW5zZUV4cGlyeTogZGF0ZUZpZWxkLFxuICBoaXJlRGF0ZTogZGF0ZUZpZWxkLFxuICBzYWxhcnk6IG51bSgpLnBvc2l0aXZlKCdTYWxhcnkgbXVzdCBiZSBwb3NpdGl2ZScpLm9wdGlvbmFsKCksXG4gIHllYXJzT2ZFeHBlcmllbmNlOiBudW0oKS5pbnQoKS5taW4oMCwgJ1llYXJzIG9mIGV4cGVyaWVuY2UgbXVzdCBiZSBub24tbmVnYXRpdmUnKS5vcHRpb25hbCgpLFxuICBlbWVyZ2VuY3lDb250YWN0OiBuYW1lRmllbGQub3B0aW9uYWwoKSxcbiAgZW1lcmdlbmN5UGhvbmU6IHBob25lRmllbGQub3B0aW9uYWwoKSxcbiAgaW1hZ2U6IHoudW5pb24oW3ouc3RyaW5nKCksIHouaW5zdGFuY2VvZihGaWxlKSwgei5udWxsKCldKS5vcHRpb25hbCgpLFxuICBzdGF0dXM6IGRyaXZlclN0YXR1c0VudW0uZGVmYXVsdCgnYWN0aXZlJyksXG4gIG5vdGVzOiB6LnN0cmluZygpLm1heCgxMDAwLCAnTm90ZXMgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IHRlYWNoZXJQZXJzb25hbFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IG9wdGlvbmFsSWQsXG4gIG5hbWU6IG5hbWVGaWVsZCxcbiAgY2luOiBjaW5GaWVsZCxcbiAgZW1haWw6IGVtYWlsRmllbGQsXG4gIHBob25lOiBwaG9uZUZpZWxkLFxuICBhZGRyZXNzOiBhZGRyZXNzRmllbGQsXG4gIGdlbmRlcjogZ2VuZGVyRW51bS5vcHRpb25hbCgpLFxuICBlbWVyZ2VuY3lDb250YWN0OiBuYW1lRmllbGQub3B0aW9uYWwoKSxcbiAgZW1lcmdlbmN5UGhvbmU6IHBob25lRmllbGQsXG4gIHN0YXR1czogdGVhY2hlclN0YXR1c0VudW0uZGVmYXVsdCgnYWN0aXZlJyksXG4gIGltYWdlOiB6LnVuaW9uKFt6LnN0cmluZygpLCB6Lmluc3RhbmNlb2YoRmlsZSksIHoubnVsbCgpXSkub3B0aW9uYWwoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgdGVhY2hlclByb2Zlc3Npb25hbFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgc3BlY2lhbGl6YXRpb246IHouc3RyaW5nKCkubWF4KDEwMCwgJ1NwZWNpYWxpemF0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgeWVhcnNPZkV4cGVyaWVuY2U6IG51bSgpLmludCgpLm1pbigwLCAnWWVhcnMgb2YgZXhwZXJpZW5jZSBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpLm9wdGlvbmFsKCksXG4gIHNhbGFyeTogbnVtKCkucG9zaXRpdmUoJ1NhbGFyeSBtdXN0IGJlIHBvc2l0aXZlJykub3B0aW9uYWwoKSxcbiAgaGlyZURhdGU6IGRhdGVGaWVsZCxcbmJhbmtBY2NvdW50OiB6LmNvZXJjZVxuICAuc3RyaW5nKClcbiAgLm1heCgxMDAsIHsgbWVzc2FnZTogJ0JhbmsgYWNjb3VudCB0b28gbG9uZycgfSlcbiAgLm9wdGlvbmFsKCksXG4gIGVtcGxveW1lbnRUeXBlOiBlbXBsb3ltZW50VHlwZUVudW0ub3B0aW9uYWwoKSxcbiAgICB3b3JrbG9hZEhvdXJzOiBudW0oKS5pbnQoKS5taW4oMCwgJ1dvcmtsb2FkIGhvdXJzIG11c3QgYmUgbm9uLW5lZ2F0aXZlJykubWF4KDYwLCAnV29ya2xvYWQgaG91cnMgY2Fubm90IGV4Y2VlZCA2MCcpLm9wdGlvbmFsKCksXG4gICAgYWNhZGVtaWNEZWdyZWVzOiB6LnN0cmluZygpLm1heCg1MDAsICdBY2FkZW1pYyBkZWdyZWVzIGRlc2NyaXB0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgYXNzaWdubWVudFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgY2xhc3NJZDogei5zdHJpbmcoKS5taW4oMSwgJ0NsYXNzIGlzIHJlcXVpcmVkJyksXG4gIHNlY3Rpb25JZHM6IHouYXJyYXkoei5zdHJpbmcoKSkubWluKDEsICdBdCBsZWFzdCBvbmUgc2VjdGlvbiBpcyByZXF1aXJlZCcpLFxuICBzdWJqZWN0SWRzOiB6LmFycmF5KHouc3RyaW5nKCkpLm1pbigxLCAnQXQgbGVhc3Qgb25lIHN1YmplY3QgaXMgcmVxdWlyZWQnKSxcbiAgYWNhZGVtaWNZZWFyOiB6LnN0cmluZygpLm9wdGlvbmFsKClcbn0pO1xuXG5leHBvcnQgY29uc3QgYXNzaWdubWVudHNTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGFzc2lnbm1lbnRzOiB6LmFycmF5KGFzc2lnbm1lbnRTY2hlbWEpLm1pbigxLCAnQXQgbGVhc3Qgb25lIHBhcmVudCBpcyByZXF1aXJlZCcpXG59KVxuXG5leHBvcnQgY29uc3QgdGVhY2hlckZ1bGxTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIC4uLnRlYWNoZXJQZXJzb25hbFNjaGVtYS5zaGFwZSxcbiAgLi4udGVhY2hlclByb2Zlc3Npb25hbFNjaGVtYS5zaGFwZSxcbiAgLi4uYXNzaWdubWVudHNTY2hlbWEuc2hhcGUsXG59KTtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuLy8gRkVFUyBWQUxJREFUSU9OIFNDSEVNQVNcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cblxuZXhwb3J0IGNvbnN0IGZlZVR5cGVTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiBvcHRpb25hbElkLFxuICBuYW1lOiB6LnN0cmluZygpLm1pbigyLCAnRmVlIHR5cGUgbmFtZSBtdXN0IGJlIGF0IGxlYXN0IDIgY2hhcmFjdGVycycpLm1heCgxMDAsICdGZWUgdHlwZSBuYW1lIHRvbyBsb25nJyksXG4gIGRlc2NyaXB0aW9uOiB6LnN0cmluZygpLm1heCg1MDAsICdEZXNjcmlwdGlvbiB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgY2F0ZWdvcnk6IHouc3RyaW5nKCksXG4gIGFtb3VudDogbnVtKCkucG9zaXRpdmUoJ0Ftb3VudCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJykubWF4KDFfMDAwXzAwLCAnQW1vdW50IHRvbyBsYXJnZScpLFxuICBwYXltZW50VHlwZTogcGF5bWVudFR5cGVFbnVtLmRlZmF1bHQoJ3JlY3VycmluZycpLFxuICBzdGF0dXM6IGZlZVR5cGVTdGF0dXNFbnVtLmRlZmF1bHQoJ2FjdGl2ZScpLm9wdGlvbmFsKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IGZlZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgaWQ6IG9wdGlvbmFsSWQsXG4gIHN0dWRlbnRJZDogcmVxdWlyZWRJZCxcbiAgZmVlVHlwZUlkOiByZXF1aXJlZElkLFxuICBhY2FkZW1pY1llYXI6IGFjYWRlbWljWWVhckZpZWxkLm9wdGlvbmFsKCksXG4gIHN0YXR1czogZmVlU3RhdHVzRW51bS5vcHRpb25hbCgpLFxuICBzY2hlZHVsZTogc2NoZWR1bGVFbnVtLFxuICBiYXNlQW1vdW50OiBudW0oKS5wb3NpdGl2ZSgnQmFzZSBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZScpLm9wdGlvbmFsKCksXG4gIGdyb3NzQW1vdW50OiBudW0oKS5wb3NpdGl2ZSgnR3Jvc3MgYW1vdW50IG11c3QgYmUgcG9zaXRpdmUnKS5vcHRpb25hbCgpLFxuICBuZXRBbW91bnQ6IG51bSgpLm9wdGlvbmFsKCksXG4gIHBhaWRBbW91bnQ6IG51bSgpLm1pbigwLCAnUGFpZCBhbW91bnQgY2Fubm90IGJlIG5lZ2F0aXZlJykub3B0aW9uYWwoKSxcbiAgZGlzY291bnRBbW91bnQ6IG51bSgpLm1pbigwLCAnRGlzY291bnQgY2Fubm90IGJlIG5lZ2F0aXZlJykub3B0aW9uYWwoKSxcbiAgZGlzY291bnRSZWFzb246IHouc3RyaW5nKCkubWF4KDUwMCwgJ0Rpc2NvdW50IHJlYXNvbiB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgYXNzaWduZWRCeTogb3B0aW9uYWxJZC5udWxsYWJsZSgpLFxuICBub3Rlczogei5zdHJpbmcoKS5tYXgoMTAwMCwgJ05vdGVzIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxufSlcblxuZXhwb3J0IGNvbnN0IGJ1bGtGZWVJdGVtU2NoZW1hID0gZmVlU2NoZW1hLm9taXQoeyBzdHVkZW50SWQ6IHRydWUgfSlcblxuZXhwb3J0IGNvbnN0IGJ1bGtGZWVGb3JtU2NoZW1hID0gei5vYmplY3Qoe1xuICBzdHVkZW50SWQ6IHJlcXVpcmVkSWQsXG4gIGZlZXM6IHouYXJyYXkoYnVsa0ZlZUl0ZW1TY2hlbWEpLm1pbigxLCAnQXQgbGVhc3Qgb25lIGZlZSBpcyByZXF1aXJlZCcpXG59KTtcblxuZXhwb3J0IGNvbnN0IGZlZUluc3RhbGxtZW50U2NoZW1hID0gei5vYmplY3Qoe1xuICBmZWVJZDogb3B0aW9uYWxJZCxcbiAgbnVtYmVyOiBudW0oKS5pbnQoKS5taW4oMSwgJ0luc3RhbGxtZW50IG11c3QgYmUgYXQgbGVhc3QgMScpLFxuICBkdWVEYXRlOiBkYXRlRmllbGQsXG4gIGFtb3VudDogbnVtKCkucG9zaXRpdmUoJ0Ftb3VudCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJykubWF4KDFfMDAwXzAwLCAnQW1vdW50IHRvbyBsYXJnZScpLFxuICBwYWlkQW1vdW50OiBudW0oKS5taW4oMCwgJ1BhaWQgYW1vdW50IGNhbm5vdCBiZSBuZWdhdGl2ZScpLm1heCgxXzAwMF8wMCwgJ0Ftb3VudCB0b28gbGFyZ2UnKS5vcHRpb25hbCgpLFxuICBzdGF0dXM6IGZlZUluc3RhbGxtZW50U3RhdHVzRW51bS5vcHRpb25hbCgpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBmZWVQYXltZW50U2NoZW1hID0gei5vYmplY3Qoe1xuICBzdHVkZW50SWQ6IG9wdGlvbmFsSWQsXG4gIGFtb3VudDogbnVtKCkucG9zaXRpdmUoJ0Ftb3VudCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJykubWF4KDFfMDAwXzAwLCAnQW1vdW50IHRvbyBsYXJnZScpLm9wdGlvbmFsKCksXG4gIHBheW1lbnRNZXRob2Q6IHBheW1lbnRNZXRob2RFbnVtLFxuICBwYXltZW50RGF0ZTogZGF0ZUZpZWxkLFxuICBjaGVja051bWJlcjogei5wcmVwcm9jZXNzKCh2YWwpID0+IHZhbCA9PT0gXCJcIiA/IG51bGwgOiB2YWwsIHouc3RyaW5nKCkubWF4KDUwLCAnQ2hlY2sgbnVtYmVyIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpKSxcbiAgY2hlY2tEdWVEYXRlOiB6LnByZXByb2Nlc3MoKHZhbCkgPT4gdmFsID09PSBcIlwiID8gbnVsbCA6IHZhbCwgb3B0aW9uYWxEYXRlRmllbGQubnVsbGFibGUoKSksXG4gIHRyYW5zYWN0aW9uUmVmOiB6LnByZXByb2Nlc3MoKHZhbCkgPT4gdmFsID09PSBcIlwiID8gbnVsbCA6IHZhbCwgei5zdHJpbmcoKS5tYXgoMTAwLCAnVHJhbnNhY3Rpb24gcmVmZXJlbmNlIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpKSxcbiAgcmVjZWlwdE51bWJlcjogei5wcmVwcm9jZXNzKCh2YWwpID0+IHZhbCA9PT0gXCJcIiA/IG51bGwgOiB2YWwsIHouc3RyaW5nKCkubWF4KDUwLCAnUmVjZWlwdCBudW1iZXIgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCkpLFxuICBzdGF0dXM6IHBheW1lbnRTdGF0dXNFbnVtLmRlZmF1bHQoJ2NvbXBsZXRlZCcpLFxuICBwcm9jZXNzZWRCeTogb3B0aW9uYWxJZCxcbiAgbm90ZXM6IHoucHJlcHJvY2VzcygodmFsKSA9PiB2YWwgPT09IFwiXCIgPyBudWxsIDogdmFsLCB6LnN0cmluZygpLm1heCgxMDAwLCAnTm90ZXMgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCkpLFxuICBhbGxvY2F0aW9uczogei5hcnJheSh6Lm9iamVjdCh7XG4gICAgZmVlSWQ6IG9wdGlvbmFsSWQsXG4gICAgbnVtYmVyOiB6Lm51bWJlcigpLmludCgpLnBvc2l0aXZlKCdJbnN0YWxsbWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyksXG4gICAgYW1vdW50OiBudW0oKS5wb3NpdGl2ZSgnQW1vdW50IG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKVxuICB9KSkub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxufSlcblxuZXhwb3J0IGNvbnN0IHBheW1lbnRBbGxvY2F0aW9uU2NoZW1hID0gei5vYmplY3Qoe1xuICBwYXltZW50SWQ6IHouc3RyaW5nKCkubWluKDEsICdQYXltZW50IElEIGlzIHJlcXVpcmVkJyksXG4gIGZlZUlkOiB6LnN0cmluZygpLm1pbigxLCAnRmVlIElEIGlzIHJlcXVpcmVkJyksXG4gIGluc3RhbGxtZW50SWQ6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgYW1vdW50OiB6Lm51bWJlcigpLnBvc2l0aXZlKCdBbW91bnQgbXVzdCBiZSBwb3NpdGl2ZScpLFxuICB0eXBlOiB6LmVudW0oWydmZWUnLCAnaW5zdGFsbG1lbnQnXSkuZGVmYXVsdCgnaW5zdGFsbG1lbnQnKSxcbiAgbm90ZXM6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgcGFyZW50c1NjaGVtYSA9IHoub2JqZWN0KHtcbiAgcGFyZW50czogei5hcnJheShwYXJlbnRTY2hlbWEpLm9wdGlvbmFsKCkuZGVmYXVsdChbXSlcbn0pXG5cbmV4cG9ydCBjb25zdCBmZWVzU2NoZW1hID0gei5vYmplY3Qoe1xuICBmZWVzOiB6LmFycmF5KGJ1bGtGZWVJdGVtU2NoZW1hKS5taW4oMSwgJ0F0IGxlYXN0IG9uZSBmZWUgaXMgcmVxdWlyZWQnKVxufSlcblxuZXhwb3J0IGNvbnN0IGZ1bGxTdHVkZW50U2NoZW1hID0gei5vYmplY3Qoe1xuICAuLi5zdHVkZW50U2NoZW1hLnNoYXBlLFxuICAuLi5wYXJlbnRzU2NoZW1hLnNoYXBlLFxuICAuLi5mZWVzU2NoZW1hLnNoYXBlXG59KTtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuLy8gU0NIT09MIFNUUlVDVFVSRSBWQUxJREFUSU9OIFNDSEVNQVNcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cblxuZXhwb3J0IGNvbnN0IHN1YmplY3RTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiBvcHRpb25hbElkLFxuICBjb2RlOiB6LnN0cmluZygpLm1pbigyLCAnU3ViamVjdCBjb2RlIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzJykubWF4KDEwLCAnU3ViamVjdCBjb2RlIHRvbyBsb25nJyksXG4gIG5hbWU6IHouc3RyaW5nKCkubWluKDIsICdTdWJqZWN0IG5hbWUgbXVzdCBiZSBhdCBsZWFzdCAyIGNoYXJhY3RlcnMnKS5tYXgoMTAwLCAnU3ViamVjdCBuYW1lIHRvbyBsb25nJyksXG4gIGRlc2NyaXB0aW9uOiB6LnN0cmluZygpLm1heCg1MDAsICdEZXNjcmlwdGlvbiB0b28gbG9uZycpLm9wdGlvbmFsKCksXG4gIGdyYWRlTGV2ZWw6IG51bSgpLmludCgpLm1pbigxKS5tYXgoMTIpLm9wdGlvbmFsKCksXG59KTtcblxuZXhwb3J0IGNvbnN0IHNlY3Rpb25TY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiBvcHRpb25hbElkLFxuICBjbGFzc0lkOiByZXF1aXJlZElkLFxuICBuYW1lOiB6LnN0cmluZygpLm1pbigxLCAnU2VjdGlvbiBuYW1lIGlzIHJlcXVpcmVkJykubWF4KDEwLCAnU2VjdGlvbiBuYW1lIHRvbyBsb25nJyksXG4gIG1heFN0dWRlbnRzOiBudW0oKS5pbnQoKS5taW4oMSwgJ01heCBzdHVkZW50cyBtdXN0IGJlIGF0IGxlYXN0IDEnKS5tYXgoMTAwLCAnTWF4IHN0dWRlbnRzIGNhbm5vdCBleGNlZWQgMTAwJykuZGVmYXVsdCgzMCksXG4gIHJvb21OdW1iZXI6IG51bSgpLm1heCgxMDAwMCwgJ1Jvb20gbnVtYmVyIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgc3RhdHVzOiBzZWN0aW9uU3RhdHVzRW51bS5kZWZhdWx0KCdhY3RpdmUnKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgY2xhc3NTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiBvcHRpb25hbElkLFxuICBuYW1lOiB6LnN0cmluZygpLm1pbigxLCAnQ2xhc3MgbmFtZSBpcyByZXF1aXJlZCcpLm1heCg1MCwgJ0NsYXNzIG5hbWUgdG9vIGxvbmcnKSxcbiAgZGVzY3JpcHRpb246IHouc3RyaW5nKCkubWF4KDUwMCwgJ0Rlc2NyaXB0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgYWNhZGVtaWNZZWFyOiBhY2FkZW1pY1llYXJGaWVsZCxcbiAgbGV2ZWw6IHouc3RyaW5nKCkubWluKDEsICdDbGFzcyBsZXZlbCBpcyByZXF1aXJlZCcpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBhdHRlbmRhbmNlU2NoZW1hID0gei5vYmplY3Qoe1xuICBzdHVkZW50SWQ6IHJlcXVpcmVkSWQsXG4gIHRlYWNoZXJJZDogcmVxdWlyZWRJZCxcbiAgc3ViamVjdElkOiByZXF1aXJlZElkLFxuICBzZWN0aW9uSWQ6IHJlcXVpcmVkSWQsXG4gIGRhdGU6IGRhdGVGaWVsZCxcbiAgc3RhdHVzOiBhdHRlbmRhbmNlU3RhdHVzRW51bS5kZWZhdWx0KCdwcmVzZW50JyksXG4gIG5vdGVzOiB6LnN0cmluZygpLm1heCg1MDAsICdOb3RlcyB0b28gbG9uZycpLm9wdGlvbmFsKCksXG59KVxuXG5leHBvcnQgY29uc3QgYXNzZXNzbWVudFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgY2xhc3NJZDogcmVxdWlyZWRJZCxcbiAgc2VjdGlvbklkOiByZXF1aXJlZElkLFxuICBzdWJqZWN0SWQ6IHJlcXVpcmVkSWQsXG4gIHRlYWNoZXJJZDogcmVxdWlyZWRJZCxcbiAgdGVhY2hlckFzc2lnbm1lbnRJZDogb3B0aW9uYWxJZCxcbiAgdGl0bGU6IHouc3RyaW5nKCkubWluKDMsICdUaXRsZSBtdXN0IGJlIGF0IGxlYXN0IDMgY2hhcmFjdGVycycpLm1heCgyMDAsICdUaXRsZSB0b28gbG9uZycpLFxuICBkZXNjcmlwdGlvbjogei5zdHJpbmcoKS5tYXgoMTAwMCwgJ0Rlc2NyaXB0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICB0eXBlOiBhc3Nlc3NtZW50VHlwZUVudW0uZGVmYXVsdCgncXVpeicpLFxuICBkYXRlOiBkYXRlRmllbGQsXG4gIGR1cmF0aW9uOiBudW0oKS5pbnQoKS5taW4oMSwgJ0R1cmF0aW9uIG11c3QgYmUgYXQgbGVhc3QgMSBtaW51dGUnKS5tYXgoNDgwLCAnRHVyYXRpb24gY2Fubm90IGV4Y2VlZCA4IGhvdXJzJyksXG4gIHRvdGFsTWFya3M6IG51bSgpLnBvc2l0aXZlKCdUb3RhbCBtYXJrcyBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJykubWF4KDEwMDAsICdUb3RhbCBtYXJrcyBjYW5ub3QgZXhjZWVkIDEwMDAnKSxcbiAgcGFzc2luZ01hcmtzOiBudW0oKS5taW4oMCwgJ1Bhc3NpbmcgbWFya3MgbXVzdCBiZSBub24tbmVnYXRpdmUnKS5tYXgoMTAwMCwgJ1Bhc3NpbmcgbWFya3MgY2Fubm90IGV4Y2VlZCAxMDAwJyksXG4gIGluc3RydWN0aW9uczogei5zdHJpbmcoKS5tYXgoMjAwMCwgJ0luc3RydWN0aW9ucyB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgc3RhdHVzOiBhc3Nlc3NtZW50U3RhdHVzRW51bS5kZWZhdWx0KCdzY2hlZHVsZWQnKSxcbiAgYXNzZXNzbWVudElkOiBvcHRpb25hbElkLFxufSlcblxuZXhwb3J0IGNvbnN0IGJ1bGtBc3Nlc3NtZW50U2NoZW1hID0gei5vYmplY3Qoe1xuICBhc3Nlc3NtZW50czogei5hcnJheShhc3Nlc3NtZW50U2NoZW1hKVxuICAgIC5taW4oMSwgJ0F0IGxlYXN0IG9uZSBhc3Nlc3NtZW50IGlzIHJlcXVpcmVkJylcbiAgICAubWF4KDUwLCAnQ2Fubm90IGNyZWF0ZSBtb3JlIHRoYW4gNTAgYXNzZXNzbWVudHMgYXQgb25jZScpLFxufSlcblxuZXhwb3J0IGNvbnN0IGdyYWRlU2NoZW1hID0gei5vYmplY3Qoe1xuICBhc3Nlc3NtZW50SWQ6IHJlcXVpcmVkSWQsXG4gIHRlYWNoZXJJZDogcmVxdWlyZWRJZCxcbiAgc3ViamVjdElkOiByZXF1aXJlZElkLFxuICBzZWN0aW9uSWQ6IHJlcXVpcmVkSWQsXG4gIHN0dWRlbnRJZDogcmVxdWlyZWRJZCxcbiAgZ3JhZGVJZDogcmVxdWlyZWRJZCxcbiAgYXNzZXNzbWVudFRpdGxlOiB6LnN0cmluZygpLm1pbigzLCAnQXNzZXNzbWVudCB0aXRsZSBtdXN0IGJlIGF0IGxlYXN0IDMgY2hhcmFjdGVycycpLm1heCgyMDAsICdBc3Nlc3NtZW50IHRpdGxlIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgbWFya3NPYnRhaW5lZDogbnVtKCkubWluKDAsICdNYXJrcyBvYnRhaW5lZCBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpLm1heCgxMDAwLCAnTWFya3Mgb2J0YWluZWQgY2Fubm90IGV4Y2VlZCAxMDAwJyksXG4gIGZlZWRiYWNrOiB6LnN0cmluZygpLm1heCgxMDAwLCAnRmVlZGJhY2sgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIHN0YXR1czogZ3JhZGVTdGF0dXNFbnVtLmRlZmF1bHQoJ2dyYWRlZCcpLFxufSlcblxuZXhwb3J0IGNvbnN0IGV4YW1TY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGNsYXNzSWQ6IG9wdGlvbmFsSWQsXG4gIHNlY3Rpb25JZDogcmVxdWlyZWRJZCxcbiAgc3ViamVjdElkOiByZXF1aXJlZElkLFxuICB0ZWFjaGVySWQ6IHJlcXVpcmVkSWQsXG4gIGV4YW1JZDogcmVxdWlyZWRJZCxcbiAgdGVhY2hlckFzc2lnbm1lbnRJZDogcmVxdWlyZWRJZCxcbiAgdGl0bGU6IHouc3RyaW5nKCkubWluKDMsICdUaXRsZSBtdXN0IGJlIGF0IGxlYXN0IDMgY2hhcmFjdGVycycpLm1heCgyMDAsICdUaXRsZSB0b28gbG9uZycpLFxuICBkZXNjcmlwdGlvbjogei5zdHJpbmcoKS5tYXgoMTAwMCwgJ0Rlc2NyaXB0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICB0eXBlOiBleGFtVHlwZUVudW0uZGVmYXVsdCgnbWlkdGVybScpLFxuICBkYXRlOiBkYXRlRmllbGQsXG4gIHN0YXJ0VGltZTogdGltZUZpZWxkLFxuICBlbmRUaW1lOiB0aW1lRmllbGQsXG4gIGR1cmF0aW9uOiBudW0oKS5pbnQoKS5taW4oMzAsICdFeGFtIGR1cmF0aW9uIG11c3QgYmUgYXQgbGVhc3QgMzAgbWludXRlcycpLm1heCg0ODAsICdEdXJhdGlvbiBjYW5ub3QgZXhjZWVkIDggaG91cnMnKSxcbiAgdG90YWxNYXJrczogbnVtKCkucG9zaXRpdmUoJ1RvdGFsIG1hcmtzIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKS5tYXgoMTAwMCwgJ1RvdGFsIG1hcmtzIGNhbm5vdCBleGNlZWQgMTAwMCcpLFxuICBwYXNzaW5nTWFya3M6IG51bSgpLm1pbigwLCAnUGFzc2luZyBtYXJrcyBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpLm1heCgxMDAwLCAnUGFzc2luZyBtYXJrcyBjYW5ub3QgZXhjZWVkIDEwMDAnKSxcbiAgcm9vbU51bWJlcjogbnVtKCkubWF4KDUwLCAnUm9vbSBudW1iZXIgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIGFsbG93ZWRNYXRlcmlhbHM6IHouc3RyaW5nKCkubWF4KDUwMCwgJ0FsbG93ZWQgbWF0ZXJpYWxzIGRlc2NyaXB0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICBpbnN0cnVjdGlvbnM6IHouc3RyaW5nKCkubWF4KDIwMDAsICdJbnN0cnVjdGlvbnMgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIHN0YXR1czogZXhhbVN0YXR1c0VudW0uZGVmYXVsdCgnc2NoZWR1bGVkJyksXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG4vLyBBTk5PVU5DRU1FTlQgVkFMSURBVElPTiBTQ0hFTUFcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cblxuZXhwb3J0IGNvbnN0IGFubm91bmNlbWVudFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgdGl0bGU6IHouc3RyaW5nKCkubWluKDMsICdUaXRsZSBtdXN0IGJlIGF0IGxlYXN0IDMgY2hhcmFjdGVycycpLm1heCgyMDAsICdUaXRsZSB0b28gbG9uZycpLFxuICBjb250ZW50OiB6LnN0cmluZygpLm1pbigxMCwgJ0NvbnRlbnQgbXVzdCBiZSBhdCBsZWFzdCAxMCBjaGFyYWN0ZXJzJykubWF4KDUwMDAsICdDb250ZW50IHRvbyBsb25nJyksXG4gIGF1dGhvcklkOiBvcHRpb25hbElkLFxuICB0YXJnZXRBdWRpZW5jZTogei5lbnVtKFsnYWxsJywgJ3N0dWRlbnRzJywgJ3RlYWNoZXJzJywgJ3BhcmVudHMnLCAnY2xhc3MnXSksXG4gIGNsYXNzSWQ6IG9wdGlvbmFsSWQsXG4gIGlzUHVibGlzaGVkOiB6LmJvb2xlYW4oKS5kZWZhdWx0KGZhbHNlKSxcbiAgcHVibGlzaERhdGU6IHouc3RyaW5nKCkuZGF0ZXRpbWUoJ0ludmFsaWQgcHVibGlzaCBkYXRlJykub3B0aW9uYWwoKSxcbiAgZXhwaXJ5RGF0ZTogei5zdHJpbmcoKS5kYXRldGltZSgnSW52YWxpZCBleHBpcnkgZGF0ZScpLm9wdGlvbmFsKCksXG59KVxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG4vLyBBTEVSVCBWQUxJREFUSU9OIFNDSEVNQVxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuXG5leHBvcnQgY29uc3QgYWxlcnRTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHR5cGU6IGFsZXJ0VHlwZUVudW0sXG4gIHRpdGxlOiB6LnN0cmluZygpLm1pbigzLCAnVGl0bGUgbXVzdCBiZSBhdCBsZWFzdCAzIGNoYXJhY3RlcnMnKS5tYXgoMjAwLCAnVGl0bGUgdG9vIGxvbmcnKSxcbiAgbWVzc2FnZTogei5zdHJpbmcoKS5taW4oMTAsICdNZXNzYWdlIG11c3QgYmUgYXQgbGVhc3QgMTAgY2hhcmFjdGVycycpLm1heCgyMDAwLCAnTWVzc2FnZSB0b28gbG9uZycpLFxuICBwcmlvcml0eTogYWxlcnRQcmlvcml0eUVudW0uZGVmYXVsdCgnbWVkaXVtJyksXG4gIHN0YXR1czogYWxlcnRTdGF0dXNFbnVtLmRlZmF1bHQoJ2FjdGl2ZScpLFxuICBzdHVkZW50SWQ6IG9wdGlvbmFsSWQsXG4gIHRlYWNoZXJJZDogb3B0aW9uYWxJZCxcbiAgY2xhc3NJZDogb3B0aW9uYWxJZCxcbiAgc3ViamVjdElkOiBvcHRpb25hbElkLFxuICB0YXJnZXRBdWRpZW5jZTogei5lbnVtKFsnYWxsJywgJ3N0dWRlbnRzJywgJ3RlYWNoZXJzJywgJ3BhcmVudHMnXSkub3B0aW9uYWwoKSxcbiAgYXV0aG9ySWQ6IG9wdGlvbmFsSWQsXG4gIGlzUmVhZDogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSksXG59KTtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuLy8gRVZFTlRTIFZBTElEQVRJT04gU0NIRU1BU1xuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuXG5leHBvcnQgY29uc3QgZXZlbnRTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHRpdGxlOiB6LnN0cmluZygpLm1pbigzLCAnVGl0bGUgbXVzdCBiZSBhdCBsZWFzdCAzIGNoYXJhY3RlcnMnKS5tYXgoMjAwLCAnVGl0bGUgdG9vIGxvbmcnKSxcbiAgZGVzY3JpcHRpb246IHouc3RyaW5nKCkubWF4KDUwMDAsICdEZXNjcmlwdGlvbiB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgdHlwZTogZXZlbnRUeXBlRW51bSxcbiAgc3RhcnREYXRlOiBkYXRlRmllbGQsXG4gIGVuZERhdGU6IGRhdGVGaWVsZCxcbiAgc3RhcnRUaW1lOiB0aW1lRmllbGQsXG4gIGVuZFRpbWU6IHRpbWVGaWVsZCxcbiAgbG9jYXRpb246IHouc3RyaW5nKCkubWF4KDIwMCwgJ0xvY2F0aW9uIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICB2ZW51ZTogei5zdHJpbmcoKS5tYXgoMjAwLCAnVmVudWUgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIG9yZ2FuaXplcklkOiBvcHRpb25hbElkLFxuICBjbGFzc0lkOiBvcHRpb25hbElkLm51bGxhYmxlKCksXG4gIHNlY3Rpb25JZDogb3B0aW9uYWxJZC5udWxsYWJsZSgpLFxuICB2aXNpYmlsaXR5OiBldmVudFZpc2liaWxpdHlFbnVtLmRlZmF1bHQoJ3B1YmxpYycpLFxuICBzdGF0dXM6IGV2ZW50U3RhdHVzRW51bS5kZWZhdWx0KCdzY2hlZHVsZWQnKSxcbiAgY2FwYWNpdHk6IG51bSgpLmludCgpLnBvc2l0aXZlKCdDYXBhY2l0eSBtdXN0IGJlIHBvc2l0aXZlJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICByZWdpc3RyYXRpb25SZXF1aXJlZDogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSksXG4gIHJlZ2lzdHJhdGlvbkRlYWRsaW5lOiBvcHRpb25hbERhdGVGaWVsZC5udWxsYWJsZSgpLFxuICBhdHRhY2htZW50czogei5hbnkoKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIG5vdGVzOiB6LnN0cmluZygpLm1heCgyMDAwLCAnTm90ZXMgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG59KVxuXG5leHBvcnQgY29uc3QgZXZlbnRQYXJ0aWNpcGFudFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgZXZlbnRJZDogb3B0aW9uYWxJZCxcbiAgcGFydGljaXBhbnRJZDogb3B0aW9uYWxJZCxcbiAgcGFydGljaXBhbnRUeXBlOiBwYXJ0aWNpcGFudFR5cGVFbnVtLFxuICBhdHRlbmRhbmNlU3RhdHVzOiBhdHRlbmRhbmNlU3RhdHVzRW51bS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIG5vdGVzOiB6LnN0cmluZygpLm1heCg1MDAsICdOb3RlcyB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbn0pO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG4vLyBFWFBFTlNFUyBWQUxJREFUSU9OIFNDSEVNQVNcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cblxuZXhwb3J0IGNvbnN0IGV4cGVuc2VTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiBvcHRpb25hbElkLFxuICBjYXRlZ29yeTogZXhwZW5zZUNhdGVnb3J5RW51bSxcbiAgdGl0bGU6IHouc3RyaW5nKCkubWluKDMsICdUaXRsZSBtdXN0IGJlIGF0IGxlYXN0IDMgY2hhcmFjdGVycycpLm1heCgyMDAsICdUaXRsZSB0b28gbG9uZycpLFxuICBhbW91bnQ6IG51bSgpLnBvc2l0aXZlKCdBbW91bnQgbXVzdCBiZSBncmVhdGVyIHRoYW4gMCcpLm1heCgxMDAwMDAwMCwgJ0Ftb3VudCB0b28gbGFyZ2UnKSxcbiAgZXhwZW5zZURhdGU6IGRhdGVGaWVsZCxcbiAgcGF5bWVudE1ldGhvZDogcGF5bWVudE1ldGhvZEVudW0ub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICBwYXltZW50RGF0ZTogb3B0aW9uYWxEYXRlRmllbGQubnVsbGFibGUoKSxcbiAgdmVuZG9yOiB6LnN0cmluZygpLm1heCgyMDAsICdWZW5kb3IgbmFtZSB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgaW52b2ljZU51bWJlcjogei5zdHJpbmcoKS5tYXgoMTAwLCAnSW52b2ljZSBudW1iZXIgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIHJlY2VpcHROdW1iZXI6IHouc3RyaW5nKCkubWF4KDEwMCwgJ1JlY2VpcHQgbnVtYmVyIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICBjaGVja051bWJlcjogei5zdHJpbmcoKS5tYXgoNTAsICdDaGVjayBudW1iZXIgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIHRyYW5zYWN0aW9uUmVmOiB6LnN0cmluZygpLm1heCgxMDAsICdUcmFuc2FjdGlvbiByZWZlcmVuY2UgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIHN0YXR1czogZXhwZW5zZVN0YXR1c0VudW0uZGVmYXVsdCgncGVuZGluZycpLFxuICBub3Rlczogei5zdHJpbmcoKS5tYXgoMTAwMCwgJ05vdGVzIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxufSk7XG5cbmV4cG9ydCBjb25zdCBleHBlbnNlQXBwcm92YWxTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGFjdGlvbjogei5lbnVtKFsnYXBwcm92ZScsICdyZWplY3QnXSksXG4gIHJlamVjdGlvblJlYXNvbjogei5zdHJpbmcoKS5taW4oMTAsICdSZWplY3Rpb24gcmVhc29uIG11c3QgYmUgYXQgbGVhc3QgMTAgY2hhcmFjdGVycycpLm1heCgxMDAwLCAnUmVqZWN0aW9uIHJlYXNvbiB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbn0pXG5cbmV4cG9ydCBjb25zdCBleHBlbnNlUGF5bWVudFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgcGF5bWVudE1ldGhvZDogcGF5bWVudE1ldGhvZEVudW0sXG4gIHBheW1lbnREYXRlOiBkYXRlRmllbGQsXG4gIGNoZWNrTnVtYmVyOiB6LnN0cmluZygpLm1heCg1MCwgJ0NoZWNrIG51bWJlciB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgdHJhbnNhY3Rpb25SZWY6IHouc3RyaW5nKCkubWF4KDEwMCwgJ1RyYW5zYWN0aW9uIHJlZmVyZW5jZSB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgbm90ZXM6IHouc3RyaW5nKCkubWF4KDEwMDAsICdOb3RlcyB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbn0pXG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cbi8vIFRSQU5TUE9SVCBWQUxJREFUSU9OIFNDSEVNQVNcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cblxuZXhwb3J0IGNvbnN0IHZlaGljbGVTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGlkOiBvcHRpb25hbElkLFxuICBuYW1lOiB6LnN0cmluZygpLm1pbigyLCAnVmVoaWNsZSBuYW1lIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzJykubWF4KDEwMCwgJ1ZlaGljbGUgbmFtZSB0b28gbG9uZycpLFxuICBicmFuZDogei5zdHJpbmcoKS5taW4oMiwgJ0JyYW5kIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzJykubWF4KDEwMCwgJ0JyYW5kIHRvbyBsb25nJyksXG4gIG1vZGVsOiB6LnN0cmluZygpLm1pbigyLCAnTW9kZWwgbXVzdCBiZSBhdCBsZWFzdCAyIGNoYXJhY3RlcnMnKS5tYXgoMTAwLCAnTW9kZWwgdG9vIGxvbmcnKSxcbiAgeWVhcjogbnVtKCkuaW50KCkubWluKDE5MDAsICdZZWFyIG11c3QgYmUgYWZ0ZXIgMTkwMCcpLm1heChuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCkgKyAxLCAnWWVhciBjYW5ub3QgYmUgaW4gZnV0dXJlJyksXG4gIHR5cGU6IHZlaGljbGVUeXBlRW51bS5kZWZhdWx0KCdmdWxsYnVzJyksXG4gIGNhcGFjaXR5OiBudW0oKS5pbnQoKS5taW4oMSwgJ0NhcGFjaXR5IG11c3QgYmUgYXQgbGVhc3QgMScpLm1heCgyMDAsICdDYXBhY2l0eSBjYW5ub3QgZXhjZWVkIDIwMCcpLFxuICBsaWNlbnNlUGxhdGU6IHouc3RyaW5nKCkubWluKDIsICdMaWNlbnNlIHBsYXRlIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzJykubWF4KDUwLCAnTGljZW5zZSBwbGF0ZSB0b28gbG9uZycpLFxuICBkcml2ZXJJZDogb3B0aW9uYWxJZC5udWxsYWJsZSgpLFxuICBpbWFnZTogei5zdHJpbmcoKS5tYXgoNTAwLCAnSW1hZ2UgcGF0aCB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKS5kZWZhdWx0KCdub3ZlaGljbGUucG5nJyksXG4gIHB1cmNoYXNlRGF0ZTogb3B0aW9uYWxEYXRlRmllbGQubnVsbGFibGUoKSxcbiAgcHVyY2hhc2VQcmljZTogbnVtKCkubWluKDAsICdQdXJjaGFzZSBwcmljZSBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpLm1heCgxMDAwMDAwMCwgJ1B1cmNoYXNlIHByaWNlIHRvbyBsYXJnZScpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgaW5pdGlhbE1pbGVhZ2U6IG51bSgpLm1pbigwLCAnSW5pdGlhbCBtaWxlYWdlIG11c3QgYmUgbm9uLW5lZ2F0aXZlJykubWF4KDEwMDAwMDAwLCAnSW5pdGlhbCBtaWxlYWdlIHRvbyBsYXJnZScpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgY3VycmVudE1pbGVhZ2U6IG51bSgpLm1pbigwLCAnQ3VycmVudCBtaWxlYWdlIG11c3QgYmUgbm9uLW5lZ2F0aXZlJykubWF4KDEwMDAwMDAwLCAnQ3VycmVudCBtaWxlYWdlIHRvbyBsYXJnZScpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbiAgc3RhdHVzOiB2ZWhpY2xlU3RhdHVzRW51bS5kZWZhdWx0KCdhY3RpdmUnKSxcbiAgbm90ZXM6IHouc3RyaW5nKCkubWF4KDEwMDAsICdOb3RlcyB0b28gbG9uZycpLm9wdGlvbmFsKCkubnVsbGFibGUoKSxcbn0pO1xuXG5leHBvcnQgY29uc3QgcmVmdWVsU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogb3B0aW9uYWxJZCxcbiAgYnVzSWQ6IG9wdGlvbmFsSWQsXG4gIHJlZnVlbERhdGU6IGRhdGVGaWVsZCxcbiAgcXVhbnRpdHk6IG51bSgpLnBvc2l0aXZlKCdRdWFudGl0eSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJykubWF4KDEwMDAwLCAnUXVhbnRpdHkgdG9vIGxhcmdlJyksXG4gIHVuaXRQcmljZTogbnVtKCkucG9zaXRpdmUoJ1VuaXQgcHJpY2UgbXVzdCBiZSBncmVhdGVyIHRoYW4gMCcpLm1heCgxMDAwMDAsICdVbml0IHByaWNlIHRvbyBsYXJnZScpLFxuICB0b3RhbENvc3Q6IG51bSgpLnBvc2l0aXZlKCdUb3RhbCBjb3N0IG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKS5tYXgoMTAwMDAwMDAsICdUb3RhbCBjb3N0IHRvbyBsYXJnZScpLm9wdGlvbmFsKCksXG4gIGZ1ZWxUeXBlOiBmdWVsVHlwZUVudW0uZGVmYXVsdCgnZGllc2VsJyksXG4gIG9kb21ldGVyOiBudW0oKS5taW4oMCwgJ09kb21ldGVyIG11c3QgYmUgbm9uLW5lZ2F0aXZlJykubWF4KDEwMDAwMDAwLCAnT2RvbWV0ZXIgdmFsdWUgdG9vIGxhcmdlJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICBmdWVsU3RhdGlvbjogei5zdHJpbmcoKS5tYXgoMjAwLCAnRnVlbCBzdGF0aW9uIG5hbWUgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIGludm9pY2VOdW1iZXI6IHouc3RyaW5nKCkubWF4KDEwMCwgJ0ludm9pY2UgbnVtYmVyIHRvbyBsb25nJykub3B0aW9uYWwoKS5udWxsYWJsZSgpLFxuICBwYXltZW50TWV0aG9kOiBwYXltZW50TWV0aG9kRW51bS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG4gIHBhaWRCeTogb3B0aW9uYWxJZC5udWxsYWJsZSgpLFxuICBzdGF0dXM6IHJlZnVlbFN0YXR1c0VudW0uZGVmYXVsdCgnY29tcGxldGVkJyksXG4gIG5vdGVzOiB6LnN0cmluZygpLm1heCgxMDAwLCAnTm90ZXMgdG9vIGxvbmcnKS5vcHRpb25hbCgpLm51bGxhYmxlKCksXG59KTtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuLy8gU0VUVElOR1MgVkFMSURBVElPTiBTQ0hFTUFcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ly9cblxuZXhwb3J0IGNvbnN0IHNldHRpbmdzU2NoZW1hID0gei5vYmplY3Qoe1xuICAvLyBTY2hvb2wgSW5mb3JtYXRpb25cbiAgc2Nob29sTmFtZTogei5zdHJpbmcoKS5taW4oMiwgJ1NjaG9vbCBuYW1lIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzJykubWF4KDIwMCwgJ1NjaG9vbCBuYW1lIHRvbyBsb25nJyksXG4gIHNjaG9vbEFkZHJlc3M6IHouc3RyaW5nKCkubWF4KDUwMCwgJ1NjaG9vbCBhZGRyZXNzIHRvbyBsb25nJykub3B0aW9uYWwoKSxcbiAgc2Nob29sUGhvbmU6IHBob25lRmllbGQsXG4gIHNjaG9vbEVtYWlsOiBlbWFpbEZpZWxkLFxuICBzY2hvb2xXZWJzaXRlOiB6LnN0cmluZygpLnVybCgnTXVzdCBiZSBhIHZhbGlkIFVSTCcpLm1heCgyNTUsICdTY2hvb2wgd2Vic2l0ZSBVUkwgdG9vIGxvbmcnKS5vcHRpb25hbCgpLCAvLyBOZXdcbiAgc2Nob29sTG9nbzogei5zdHJpbmcoKS51cmwoJ011c3QgYmUgYSB2YWxpZCBpbWFnZSBVUkwnKS5tYXgoMjU1LCAnU2Nob29sIGxvZ28gVVJMIHRvbyBsb25nJykub3B0aW9uYWwoKSwgLy8gTmV3XG4gIGN1cnJlbnRBY2FkZW1pY1llYXI6IGFjYWRlbWljWWVhckZpZWxkLFxuXG4gIC8vIEFjYWRlbWljIFNldHRpbmdzXG4gIGdyYWRpbmdTY2FsZTogei5hbnkoKS5vcHRpb25hbCgpLFxuICBhdHRlbmRhbmNlUmVxdWlyZW1lbnQ6IG51bSgpLm1pbigwLCAnQXR0ZW5kYW5jZSByZXF1aXJlbWVudCBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpLm1heCgxMDAsICdBdHRlbmRhbmNlIHJlcXVpcmVtZW50IGNhbm5vdCBleGNlZWQgMTAwJykuZGVmYXVsdCg3NS4wMCksXG4gIG1heENsYXNzU2l6ZTogbnVtKCkuaW50KCdNYXggY2xhc3Mgc2l6ZSBtdXN0IGJlIGFuIGludGVnZXInKS5taW4oMSwgJ01heCBjbGFzcyBzaXplIG11c3QgYmUgYXQgbGVhc3QgMScpLm1heCgyMDAsICdNYXggY2xhc3Mgc2l6ZSBjYW5ub3QgZXhjZWVkIDIwMCcpLmRlZmF1bHQoMzQpLFxuICBtaW5pbXVtUGFzc2luZ0dyYWRlOiBudW0oKS5taW4oMCwgJ01pbmltdW0gcGFzc2luZyBncmFkZSBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpLm1heCgxMDAsICdNaW5pbXVtIHBhc3NpbmcgZ3JhZGUgY2Fubm90IGV4Y2VlZCAxMDAnKS5kZWZhdWx0KDYwLjAwKSxcbiAgZGVmYXVsdEV4YW1EdXJhdGlvbjogbnVtKCkuaW50KCdEZWZhdWx0IGV4YW0gZHVyYXRpb24gbXVzdCBiZSBpbiBtaW51dGVzJykubWluKDE1LCAnRXhhbSBkdXJhdGlvbiBtdXN0IGJlIGF0IGxlYXN0IDE1IG1pbnV0ZXMnKS5tYXgoNDgwLCAnRXhhbSBkdXJhdGlvbiBjYW5ub3QgZXhjZWVkIDQ4MCBtaW51dGVzJykuZGVmYXVsdCgxMjApLFxuICBjYWxlbmRhclN5c3RlbTogY2FsZW5kYXJTeXN0ZW1FbnVtLmRlZmF1bHQoJ1NFTUVTVEVSJyksXG4gIHN0YXJ0TW9udGg6IHouc3RyaW5nKCkuZGVmYXVsdCgnc2VwdGVtYmVyJyksXG4gIGVuZE1vbnRoOiB6LnN0cmluZygpLmRlZmF1bHQoJ2p1bmUnKSxcblxuICAvLyBOb3RpZmljYXRpb24gU2V0dGluZ3NcbiAgYWNhZGVtaWNBbGVydHM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIGF0dGVuZGFuY2VBbGVydHM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIGV2ZW50QWxlcnRzOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBob21ld29ya0FsZXJ0czogei5ib29sZWFuKCkuZGVmYXVsdCh0cnVlKSxcbiAgZmVlc1JlbWluZGVyOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBmZWVzT3ZlcmR1ZUFsZXJ0czogei5ib29sZWFuKCkuZGVmYXVsdCh0cnVlKSxcbiAgZW1haWxOb3RpZmljYXRpb25zOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBzbXNOb3RpZmljYXRpb25zOiB6LmJvb2xlYW4oKS5kZWZhdWx0KGZhbHNlKSxcbiAgcGFyZW50Tm90aWZpY2F0aW9uczogei5ib29sZWFuKCkuZGVmYXVsdCh0cnVlKSxcbiAgbG93R3JhZGVBbGVydHM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIGFsbG93TGF0ZVN1Ym1pc3Npb246IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIGV4YW1SZXN1bHRzQWxlcnRzOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBkaXNjaXBsaW5hcnlBbGVydHM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIGFjaGlldmVtZW50QWxlcnRzOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBtYWludGVuYW5jZU5vdGlmaWNhdGlvbnM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG5cbiAgLy8gU2VjdXJpdHkgU2V0dGluZ3NcbiAgdHdvRmFjdG9yRW5hYmxlZDogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSksXG4gIHNlc3Npb25UaW1lb3V0OiB6LnN0cmluZygpLnJlZ2V4KC9eXFxkezEsNH0kLywgJ1Nlc3Npb24gdGltZW91dCBtdXN0IGJlIGEgbnVtYmVyIGJldHdlZW4gMS05OTk5IG1pbnV0ZXMnKS5kZWZhdWx0KCc2MCcpLFxuICBwYXNzd29yZFJlcXVpcmVTeW1ib2xzOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBsb2dpbk5vdGlmaWNhdGlvbnM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIHBhcmVudEFjY2Vzc0VuYWJsZWQ6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIHRlYWNoZXJBY2Nlc3NFbmFibGVkOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICBzdHVkZW50QWNjZXNzRW5hYmxlZDogei5ib29sZWFuKCkuZGVmYXVsdCh0cnVlKSxcblxuICAvLyBTeXN0ZW0gUHJlZmVyZW5jZXNcbiAgdGltZVpvbmU6IHouc3RyaW5nKCkubWluKDEsICdUaW1lIHpvbmUgaXMgcmVxdWlyZWQnKS5kZWZhdWx0KCdVVEMnKSxcbiAgbGFuZ3VhZ2U6IGxhbmd1YWdlRW51bS5kZWZhdWx0KCdlbicpLFxuICB0aGVtZTogei5lbnVtKFsnbGlnaHQnLCAnZGFyaycsICdzeXN0ZW0nXSkuZGVmYXVsdCgnc3lzdGVtJyksXG4gIGRhdGVGb3JtYXQ6IHouZW51bShbJ1lZWVktTU0tREQnLCAnTU0vREQvWVlZWScsICdERC9NTS9ZWVlZJywgJ0RELU1NLVlZJywgJ0RELU1NLVlZWVknXSkuZGVmYXVsdCgnTU0vREQvWVlZWScpLCAvLyBBZGp1c3RlZCBkZWZhdWx0IHRvIG1hdGNoIHRhYmxlXG4gIHRpbWVGb3JtYXQ6IHouZW51bShbJzEyJywgJzI0J10pLmRlZmF1bHQoJzEyJyksXG4gIGN1cnJlbmN5OiB6LnN0cmluZygpLmxlbmd0aCgzLCAnQ3VycmVuY3kgbXVzdCBiZSBhIDMtbGV0dGVyIElTTyBjb2RlJykucmVnZXgoL15bQS1aXXszfSQvLCAnQ3VycmVuY3kgbXVzdCBiZSB1cHBlcmNhc2UgSVNPIGNvZGUnKS5kZWZhdWx0KCdVU0QnKSxcblxuICAvLyBBY2FkZW1pYyBDYWxlbmRhciBTZXR0aW5nc1xuICBncmFkaW5nUGVyaW9kczogbnVtKCkuaW50KCdHcmFkaW5nIHBlcmlvZHMgbXVzdCBiZSBhbiBpbnRlZ2VyJykubWluKDEsICdHcmFkaW5nIHBlcmlvZHMgbXVzdCBiZSBhdCBsZWFzdCAxJykubWF4KDEyLCAnR3JhZGluZyBwZXJpb2RzIGNhbm5vdCBleGNlZWQgMTInKS5kZWZhdWx0KDQpLFxuICBzY2hvb2xTdGFydFRpbWU6IHouc3RyaW5nKCkucmVnZXgoL14oWzAxXT9bMC05XXwyWzAtM10pOlswLTVdWzAtOV0kLywgJ0ludmFsaWQgc3RhcnQgdGltZSBmb3JtYXQgKEhIOk1NKScpLmRlZmF1bHQoJzA4OjAwJyksXG4gIHNjaG9vbEVuZFRpbWU6IHouc3RyaW5nKCkucmVnZXgoL14oWzAxXT9bMC05XXwyWzAtM10pOlswLTVdWzAtOV0kLywgJ0ludmFsaWQgZW5kIHRpbWUgZm9ybWF0IChISDpNTSknKS5kZWZhdWx0KCcxNTowMCcpLFxuICBsdW5jaEJyZWFrRHVyYXRpb246IG51bSgpLmludCgnTHVuY2ggYnJlYWsgZHVyYXRpb24gbXVzdCBiZSBpbiBtaW51dGVzJykubWluKDE1LCAnTHVuY2ggYnJlYWsgbXVzdCBiZSBhdCBsZWFzdCAxNSBtaW51dGVzJykubWF4KDEyMCwgJ0x1bmNoIGJyZWFrIGNhbm5vdCBleGNlZWQgMTIwIG1pbnV0ZXMnKS5kZWZhdWx0KDMwKSxcblxuICAvLyBNYWludGVuYW5jZSAmIEJhY2t1cCBTZXR0aW5nc1xuICBtYWludGVuYW5jZU1vZGU6IHouYm9vbGVhbigpLmRlZmF1bHQoZmFsc2UpLFxuICBhdXRvQmFja3VwOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuXG59KTtcblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0vL1xuLy8gVVRJTElUWSBTQ0hFTUFTXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PS8vXG5cbmV4cG9ydCBjb25zdCBpZFBhcmFtU2NoZW1hID0gei5vYmplY3Qoe1xuICBpZDogb3B0aW9uYWxJZCxcbn0pO1xuXG5leHBvcnQgY29uc3QgcGFnaW5hdGlvblNjaGVtYSA9IHoub2JqZWN0KHtcbiAgcGFnZTogbnVtKCkuaW50KCkubWluKDEpLmRlZmF1bHQoMSksXG4gIGxpbWl0OiBudW0oKS5pbnQoKS5taW4oMSkubWF4KDEwMCkuZGVmYXVsdCgxMCksXG59KTtcblxuZXhwb3J0IGNvbnN0IGRhdGVSYW5nZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgZGF0ZUZyb206IGRhdGVGaWVsZCxcbiAgZGF0ZVRvOiBkYXRlRmllbGQsXG59KVxuXG4iLAogICAgIi8vIGxpYi92YWxpZGF0aW9ucy9lbnVtcy5qc1xyXG5pbXBvcnQgeyB6IH0gZnJvbSAnem9kJ1xyXG5pbXBvcnQgeyBFTlVNUyB9IGZyb20gJy4vRU5VTVMnXHJcblxyXG5jb25zdCBjcmVhdGVab2RFbnVtID0gKGVudW1LZXkpID0+IHtcclxuICBjb25zdCB2YWx1ZXMgPSBFTlVNU1tlbnVtS2V5XT8udmFsdWVzXHJcbiAgaWYgKCF2YWx1ZXMpIHRocm93IG5ldyBFcnJvcihgRW51bSAke2VudW1LZXl9IG5vdCBmb3VuZGApXHJcbiAgcmV0dXJuIHouZW51bSh2YWx1ZXMpXHJcbn1cclxuXHJcbi8vIENvcmUgU3lzdGVtXHJcbmV4cG9ydCBjb25zdCB1c2VyVHlwZUVudW0gPSBjcmVhdGVab2RFbnVtKCd1c2VyVHlwZScpXHJcbmV4cG9ydCBjb25zdCB1c2VyU3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3VzZXJTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgdG9rZW5TdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgndG9rZW5TdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgdG9rZW5UeXBlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3Rva2VuVHlwZScpXHJcbmV4cG9ydCBjb25zdCBmaWxlU3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2ZpbGVTdGF0dXMnKVxyXG5cclxuLy8gRWR1Y2F0aW9uYWwgU3lzdGVtXHJcbmV4cG9ydCBjb25zdCBnZW5kZXJFbnVtID0gY3JlYXRlWm9kRW51bSgnZ2VuZGVyJylcclxuZXhwb3J0IGNvbnN0IHN0dWRlbnRTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnc3R1ZGVudFN0YXR1cycpXHJcbmV4cG9ydCBjb25zdCB0ZWFjaGVyU3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3RlYWNoZXJTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgZW1wbG95bWVudFR5cGVFbnVtID0gY3JlYXRlWm9kRW51bSgnZW1wbG95bWVudFR5cGUnKVxyXG5leHBvcnQgY29uc3QgcmVsYXRpb25zaGlwVHlwZUVudW0gPSBjcmVhdGVab2RFbnVtKCdyZWxhdGlvbnNoaXBUeXBlJylcclxuZXhwb3J0IGNvbnN0IHNlbWVzdGVyRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3NlbWVzdGVyJylcclxuZXhwb3J0IGNvbnN0IGNsYXNzU3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2NsYXNzU3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IHNlY3Rpb25TdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnc2VjdGlvblN0YXR1cycpXHJcbmV4cG9ydCBjb25zdCBsYW5ndWFnZUVudW0gPSBjcmVhdGVab2RFbnVtKCdsYW5ndWFnZScpXHJcbmV4cG9ydCBjb25zdCBlbnJvbGxtZW50U3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2Vucm9sbG1lbnRTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgYXNzaWdubWVudFN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdhc3NpZ25tZW50U3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IGNhbGVuZGFyU3lzdGVtRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2NhbGVuZGFyU3lzdGVtJylcclxuXHJcbi8vIEFzc2Vzc21lbnQgJiBFeGFtc1xyXG5leHBvcnQgY29uc3QgYXNzZXNzbWVudFR5cGVFbnVtID0gY3JlYXRlWm9kRW51bSgnYXNzZXNzbWVudFR5cGUnKVxyXG5leHBvcnQgY29uc3QgYXNzZXNzbWVudFN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdhc3Nlc3NtZW50U3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IHN1Ym1pc3Npb25UeXBlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3N1Ym1pc3Npb25UeXBlJylcclxuZXhwb3J0IGNvbnN0IGV4YW1UeXBlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2V4YW1UeXBlJylcclxuZXhwb3J0IGNvbnN0IGV4YW1TZWN1cml0eUVudW0gPSBjcmVhdGVab2RFbnVtKCdleGFtU2VjdXJpdHknKVxyXG5leHBvcnQgY29uc3QgZXhhbVN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdleGFtU3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IGdyYWRlU3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2dyYWRlU3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IGF0dGVuZGFuY2VTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnYXR0ZW5kYW5jZVN0YXR1cycpXHJcbmV4cG9ydCBjb25zdCBwcm9maWNpZW5jeUxldmVsRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3Byb2ZpY2llbmN5TGV2ZWwnKVxyXG5leHBvcnQgY29uc3QgZGF5T2ZXZWVrRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2RheU9mV2VlaycpXHJcblxyXG4vLyBBbGVydHNcclxuZXhwb3J0IGNvbnN0IGFsZXJ0VHlwZUVudW0gPSBjcmVhdGVab2RFbnVtKCdhbGVydFR5cGUnKVxyXG5leHBvcnQgY29uc3QgYWxlcnRQcmlvcml0eUVudW0gPSBjcmVhdGVab2RFbnVtKCdhbGVydFByaW9yaXR5JylcclxuZXhwb3J0IGNvbnN0IGFsZXJ0U3RhdHVzRW51bSA9IGNyZWF0ZVpvZEVudW0oJ2FsZXJ0U3RhdHVzJylcclxuXHJcbi8vIEZlZXMgJiBQYXltZW50c1xyXG5leHBvcnQgY29uc3QgZmVlVHlwZVN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdmZWVUeXBlU3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IHBheW1lbnRUeXBlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3BheW1lbnRUeXBlJylcclxuZXhwb3J0IGNvbnN0IHNjaGVkdWxlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3NjaGVkdWxlJylcclxuZXhwb3J0IGNvbnN0IGZlZVN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdmZWVTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgZmVlSW5zdGFsbG1lbnRTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnZmVlSW5zdGFsbG1lbnRTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgcGF5bWVudE1ldGhvZEVudW0gPSBjcmVhdGVab2RFbnVtKCdwYXltZW50TWV0aG9kJylcclxuZXhwb3J0IGNvbnN0IHBheW1lbnRTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgncGF5bWVudFN0YXR1cycpXHJcblxyXG4vLyBFdmVudHNcclxuZXhwb3J0IGNvbnN0IGV2ZW50VHlwZUVudW0gPSBjcmVhdGVab2RFbnVtKCdldmVudFR5cGUnKVxyXG5leHBvcnQgY29uc3QgZXZlbnRTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnZXZlbnRTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgZXZlbnRWaXNpYmlsaXR5RW51bSA9IGNyZWF0ZVpvZEVudW0oJ2V2ZW50VmlzaWJpbGl0eScpXHJcbmV4cG9ydCBjb25zdCBwYXJ0aWNpcGFudFR5cGVFbnVtID0gY3JlYXRlWm9kRW51bSgncGFydGljaXBhbnRUeXBlJylcclxuXHJcbi8vIEV4cGVuc2VzXHJcbmV4cG9ydCBjb25zdCBleHBlbnNlQ2F0ZWdvcnlFbnVtID0gY3JlYXRlWm9kRW51bSgnZXhwZW5zZUNhdGVnb3J5JylcclxuZXhwb3J0IGNvbnN0IGV4cGVuc2VTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnZXhwZW5zZVN0YXR1cycpXHJcblxyXG4vLyBUcmFja2VyXHJcbmV4cG9ydCBjb25zdCB0cmFja2VyTW9kZUVudW0gPSBjcmVhdGVab2RFbnVtKCd0cmFja2VyTW9kZScpXHJcblxyXG4vLyBUcmFuc3BvcnRcclxuZXhwb3J0IGNvbnN0IGRyaXZlclN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdkcml2ZXJTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgdmVoaWNsZVN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCd2ZWhpY2xlU3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IHZlaGljbGVUeXBlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ3ZlaGljbGVUeXBlJylcclxuZXhwb3J0IGNvbnN0IHZlaGljbGVEb2N1bWVudFR5cGVFbnVtID0gY3JlYXRlWm9kRW51bSgndmVoaWNsZURvY3VtZW50VHlwZScpXHJcbmV4cG9ydCBjb25zdCBidXNTdGF0dXNFbnVtID0gY3JlYXRlWm9kRW51bSgnYnVzU3RhdHVzJylcclxuZXhwb3J0IGNvbnN0IHJlZnVlbFN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdyZWZ1ZWxTdGF0dXMnKVxyXG5leHBvcnQgY29uc3QgZnVlbFR5cGVFbnVtID0gY3JlYXRlWm9kRW51bSgnZnVlbFR5cGUnKVxyXG5leHBvcnQgY29uc3QgbWFpbnRlbmFuY2VUeXBlRW51bSA9IGNyZWF0ZVpvZEVudW0oJ21haW50ZW5hbmNlVHlwZScpXHJcbmV4cG9ydCBjb25zdCBtYWludGVuYW5jZVN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdtYWludGVuYW5jZVN0YXR1cycpXHJcblxyXG4vLyBQZXJzb25hbFxyXG5leHBvcnQgY29uc3QgbWFyaXRhbFN0YXR1c0VudW0gPSBjcmVhdGVab2RFbnVtKCdtYXJpdGFsU3RhdHVzJykiLAogICAgIlxuXG5pbXBvcnQgeyBwZXJtaXNzaW9uc1RhYmxlLCByb2xlUGVybWlzc2lvbnNUYWJsZSwgcm9sZXNUYWJsZSB9IGZyb20gJ0AvZGF0YWJhc2Uvc2NoZW1hJztcbmltcG9ydCB7IGVxLCBhbmQgfSBmcm9tICdkcml6emxlLW9ybSc7XG5pbXBvcnQgeyBSZXBvc2l0b3J5LCBEQiB9IGZyb20gJ25ham0tYXBpJztcblxuQFJlcG9zaXRvcnkoKVxuZXhwb3J0IGNsYXNzIFBlcm1pc3Npb25SZXBvc2l0b3J5IHtcbiAgZGVjbGFyZSBkYjogREI7XG5cbiAgYXN5bmMgZ2V0QWxsKCkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmRiLnNlbGVjdCgpLmZyb20ocGVybWlzc2lvbnNUYWJsZSk7XG4gIH1cblxuICBhc3luYyBnZXRCeUlkKGlkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBbZXhpc3RpbmdQZXJtaXNzaW9uXSA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3QoKVxuICAgICAgLmZyb20ocGVybWlzc2lvbnNUYWJsZSlcbiAgICAgIC53aGVyZShlcShwZXJtaXNzaW9uc1RhYmxlLmlkLCBpZCkpO1xuICAgIHJldHVybiBleGlzdGluZ1Blcm1pc3Npb247XG4gIH1cblxuICBhc3luYyBnZXRCeU5hbWUobmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgW2V4aXN0aW5nUGVybWlzc2lvbl0gPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuc2VsZWN0KClcbiAgICAgIC5mcm9tKHBlcm1pc3Npb25zVGFibGUpXG4gICAgICAud2hlcmUoZXEocGVybWlzc2lvbnNUYWJsZS5uYW1lLCBuYW1lKSk7XG4gICAgcmV0dXJuIGV4aXN0aW5nUGVybWlzc2lvbjtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZShkYXRhKSB7XG4gICAgY29uc3QgW25ld1Blcm1pc3Npb25dID0gYXdhaXQgdGhpcy5kYlxuICAgICAgLmluc2VydChwZXJtaXNzaW9uc1RhYmxlKVxuICAgICAgLnZhbHVlcyhkYXRhKVxuICAgICAgLnJldHVybmluZygpO1xuICAgIHJldHVybiBuZXdQZXJtaXNzaW9uO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlKGlkOiBzdHJpbmcsIGRhdGEpIHtcbiAgICBjb25zdCBbdXBkYXRlZFBlcm1pc3Npb25dID0gYXdhaXQgdGhpcy5kYlxuICAgICAgLnVwZGF0ZShwZXJtaXNzaW9uc1RhYmxlKVxuICAgICAgLnNldChkYXRhKVxuICAgICAgLndoZXJlKGVxKHBlcm1pc3Npb25zVGFibGUuaWQsIGlkKSlcbiAgICAgIC5yZXR1cm5pbmcoKTtcbiAgICByZXR1cm4gdXBkYXRlZFBlcm1pc3Npb247XG4gIH1cblxuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IFtkZWxldGVkUGVybWlzc2lvbl0gPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuZGVsZXRlKHBlcm1pc3Npb25zVGFibGUpXG4gICAgICAud2hlcmUoZXEocGVybWlzc2lvbnNUYWJsZS5pZCwgaWQpKVxuICAgICAgLnJldHVybmluZygpO1xuICAgIHJldHVybiBkZWxldGVkUGVybWlzc2lvbjtcbiAgfVxuXG4gIGFzeW5jIGdldFBlcm1pc3Npb25zQnlSb2xlKHJvbGVJZDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3Qoe1xuICAgICAgICBpZDogcGVybWlzc2lvbnNUYWJsZS5pZCxcbiAgICAgICAgbmFtZTogcGVybWlzc2lvbnNUYWJsZS5uYW1lLFxuICAgICAgICBkZXNjcmlwdGlvbjogcGVybWlzc2lvbnNUYWJsZS5kZXNjcmlwdGlvbixcbiAgICAgICAgcmVzb3VyY2U6IHBlcm1pc3Npb25zVGFibGUucmVzb3VyY2UsXG4gICAgICAgIGFjdGlvbjogcGVybWlzc2lvbnNUYWJsZS5hY3Rpb24sXG4gICAgICB9KVxuICAgICAgLmZyb20ocm9sZVBlcm1pc3Npb25zVGFibGUpXG4gICAgICAubGVmdEpvaW4ocGVybWlzc2lvbnNUYWJsZSwgZXEocm9sZVBlcm1pc3Npb25zVGFibGUucGVybWlzc2lvbklkLCBwZXJtaXNzaW9uc1RhYmxlLmlkKSlcbiAgICAgIC53aGVyZShlcShyb2xlUGVybWlzc2lvbnNUYWJsZS5yb2xlSWQsIHJvbGVJZCkpO1xuICB9XG5cbiAgYXN5bmMgZ2V0Um9sZXNCeVBlcm1pc3Npb24ocGVybWlzc2lvbklkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5kYlxuICAgICAgLnNlbGVjdCh7XG4gICAgICAgIGlkOiByb2xlc1RhYmxlLmlkLFxuICAgICAgICBuYW1lOiByb2xlc1RhYmxlLm5hbWUsXG4gICAgICAgIGRlc2NyaXB0aW9uOiByb2xlc1RhYmxlLmRlc2NyaXB0aW9uLFxuICAgICAgfSlcbiAgICAgIC5mcm9tKHJvbGVQZXJtaXNzaW9uc1RhYmxlKVxuICAgICAgLmxlZnRKb2luKHJvbGVzVGFibGUsIGVxKHJvbGVQZXJtaXNzaW9uc1RhYmxlLnJvbGVJZCwgcm9sZXNUYWJsZS5pZCkpXG4gICAgICAud2hlcmUoZXEocm9sZVBlcm1pc3Npb25zVGFibGUucGVybWlzc2lvbklkLCBwZXJtaXNzaW9uSWQpKTtcbiAgfVxuXG4gIGFzeW5jIGFzc2lnblBlcm1pc3Npb25Ub1JvbGUocm9sZUlkOiBzdHJpbmcsIHBlcm1pc3Npb25JZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW25ld1JvbGVQZXJtaXNzaW9uXSA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5pbnNlcnQocm9sZVBlcm1pc3Npb25zVGFibGUpXG4gICAgICAudmFsdWVzKHsgcm9sZUlkLCBwZXJtaXNzaW9uSWQgfSlcbiAgICAgIC5yZXR1cm5pbmcoKTtcbiAgICByZXR1cm4gbmV3Um9sZVBlcm1pc3Npb247XG4gIH1cblxuICBhc3luYyByZW1vdmVQZXJtaXNzaW9uRnJvbVJvbGUocm9sZUlkOiBzdHJpbmcsIHBlcm1pc3Npb25JZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW2RlbGV0ZWRSb2xlUGVybWlzc2lvbl0gPSBhd2FpdCB0aGlzLmRiXG4gICAgICAuZGVsZXRlKHJvbGVQZXJtaXNzaW9uc1RhYmxlKVxuICAgICAgLndoZXJlKGFuZChlcShyb2xlUGVybWlzc2lvbnNUYWJsZS5yb2xlSWQsIHJvbGVJZCksIGVxKHJvbGVQZXJtaXNzaW9uc1RhYmxlLnBlcm1pc3Npb25JZCwgcGVybWlzc2lvbklkKSkpXG4gICAgICAucmV0dXJuaW5nKCk7XG4gICAgcmV0dXJuIGRlbGV0ZWRSb2xlUGVybWlzc2lvbjtcbiAgfVxuXG4gIGFzeW5jIGNoZWNrUm9sZUhhc1Blcm1pc3Npb24ocm9sZUlkOiBzdHJpbmcsIHBlcm1pc3Npb25JZDogc3RyaW5nKSB7XG4gICAgY29uc3QgW3JvbGVQZXJtaXNzaW9uXSA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5zZWxlY3QoKVxuICAgICAgLmZyb20ocm9sZVBlcm1pc3Npb25zVGFibGUpXG4gICAgICAud2hlcmUoYW5kKGVxKHJvbGVQZXJtaXNzaW9uc1RhYmxlLnJvbGVJZCwgcm9sZUlkKSwgZXEocm9sZVBlcm1pc3Npb25zVGFibGUucGVybWlzc2lvbklkLCBwZXJtaXNzaW9uSWQpKSk7XG4gICAgcmV0dXJuICEhcm9sZVBlcm1pc3Npb247XG4gIH1cblxuICBhc3luYyBkZWxldGVBbGwoKSB7XG4gICAgLy8gRmlyc3QgZGVsZXRlIGFsbCByb2xlLXBlcm1pc3Npb24gcmVsYXRpb25zaGlwc1xuICAgIGF3YWl0IHRoaXMuZGIuZGVsZXRlKHJvbGVQZXJtaXNzaW9uc1RhYmxlKTtcblxuICAgIC8vIFRoZW4gZGVsZXRlIGFsbCBwZXJtaXNzaW9uc1xuICAgIGNvbnN0IGRlbGV0ZWRQZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMuZGJcbiAgICAgIC5kZWxldGUocGVybWlzc2lvbnNUYWJsZSlcbiAgICAgIC5yZXR1cm5pbmcoKTtcblxuICAgIHJldHVybiBkZWxldGVkUGVybWlzc2lvbnM7XG4gIH1cbn0iLAogICAgImltcG9ydCB7IGNyZWF0ZUd1YXJkLCBJbmplY3RhYmxlLCBHdWFyZFBhcmFtcywgSGVhZGVycywgQ3R4IH0gZnJvbSBcIm5ham0tYXBpXCI7XG5pbXBvcnQgeyBUb2tlblNlcnZpY2UgfSBmcm9tIFwiLi4vdG9rZW5zXCI7XG5cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFBlcm1pc3Npb25HdWFyZHMge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRva2VuU2VydmljZTogVG9rZW5TZXJ2aWNlKSB7IH1cblxuICBwcml2YXRlIGFzeW5jIGdldFVzZXJQZXJtaXNzaW9ucyhhdXRoKSB7XG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnRva2VuU2VydmljZS5nZXRVc2VyUGVybWlzc2lvbnMoYXV0aCk7XG4gICAgaWYgKCFwZXJtaXNzaW9ucyB8fCAhQXJyYXkuaXNBcnJheShwZXJtaXNzaW9ucykpIHJldHVybiBudWxsO1xuICAgIHJldHVybiBwZXJtaXNzaW9ucztcbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tQZXJtaXNzaW9uTWF0Y2gocGVybWlzc2lvbnM6IHN0cmluZ1tdLCByZXF1aXJlZFBlcm1pc3Npb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmIChwZXJtaXNzaW9ucy5pbmNsdWRlcyhyZXF1aXJlZFBlcm1pc3Npb24pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBbcmVxdWlyZWRBY3Rpb24sIHJlcXVpcmVkUmVzb3VyY2VdID0gcmVxdWlyZWRQZXJtaXNzaW9uLnNwbGl0KCc6Jyk7XG4gICAgaWYgKHJlcXVpcmVkQWN0aW9uICYmIHJlcXVpcmVkUmVzb3VyY2UpIHtcbiAgICAgIGlmIChwZXJtaXNzaW9ucy5pbmNsdWRlcyhgJHtyZXF1aXJlZEFjdGlvbn06KmApKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHBlcm1pc3Npb25zLmluY2x1ZGVzKGAqOiR7cmVxdWlyZWRSZXNvdXJjZX1gKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHBlcm1pc3Npb25zLmluY2x1ZGVzKCcqOionKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG5cbiAgYXN5bmMgaGFzUGVybWlzc2lvbihASGVhZGVycygnYXV0aG9yaXphdGlvbicpIGF1dGgsIEBDdHgoKSBjdHgsIEBHdWFyZFBhcmFtcygpIHJlcXVpcmVkUGVybWlzc2lvbikge1xuICAgIFxuICAgIGF3YWl0IHRoaXMudG9rZW5TZXJ2aWNlLnN0b3JlVXNlckluQ2FjaGUoYXV0aCwgY3R4KTtcbiAgICBjb25zdCBwZXJtaXNzaW9ucyA9IGF3YWl0IHRoaXMuZ2V0VXNlclBlcm1pc3Npb25zKGF1dGgpO1xuICAgIGlmICghcGVybWlzc2lvbnMpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCBjaGVjayA9IHRoaXMuY2hlY2tQZXJtaXNzaW9uTWF0Y2gocGVybWlzc2lvbnMsIHJlcXVpcmVkUGVybWlzc2lvbik7XG4gICAgcmV0dXJuIGNoZWNrXG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IFBlcm1pc3Npb24gPSAoLi4ucGVybWlzc2lvbnMpID0+IGNyZWF0ZUd1YXJkKFBlcm1pc3Npb25HdWFyZHMsICdoYXNQZXJtaXNzaW9uJykoLi4ucGVybWlzc2lvbnMpO1xuXG4iLAogICAgImltcG9ydCB7IENvbnRyb2xsZXIsIEdldCwgUG9zdCwgUHV0LCBEZWxldGUsIFBhcmFtcywgQm9keSwgdCB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IFBlcm1pc3Npb25TZXJ2aWNlIH0gZnJvbSAnLi9QZXJtaXNzaW9uU2VydmljZSc7XG5pbXBvcnQgeyBpc0FkbWluIH0gZnJvbSAnQC9yb2xlcy9Sb2xlR3VhcmRzJztcblxuQENvbnRyb2xsZXIoJy9wZXJtaXNzaW9ucycpXG5AaXNBZG1pbigpXG5leHBvcnQgY2xhc3MgUGVybWlzc2lvbkNvbnRyb2xsZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHBlcm1pc3Npb25TZXJ2aWNlOiBQZXJtaXNzaW9uU2VydmljZSkgeyB9XG5cbiAgQEdldCgpXG4gIGFzeW5jIGdldFBlcm1pc3Npb25zKCkge1xuICAgIGNvbnN0IHBlcm1pc3Npb25zID0gYXdhaXQgdGhpcy5wZXJtaXNzaW9uU2VydmljZS5nZXRBbGwoKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogcGVybWlzc2lvbnMsXG4gICAgICBtZXNzYWdlOiB0KCdwZXJtaXNzaW9ucy5zdWNjZXNzLnJldHJpZXZlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQEdldCgnLzppZCcpXG4gIGFzeW5jIGdldFBlcm1pc3Npb24oQFBhcmFtcygnaWQnKSBpZDogc3RyaW5nKSB7XG4gICAgY29uc3QgcGVybWlzc2lvbiA9IGF3YWl0IHRoaXMucGVybWlzc2lvblNlcnZpY2UuZ2V0QnlJZChpZCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHBlcm1pc3Npb24sXG4gICAgICBtZXNzYWdlOiB0KCdwZXJtaXNzaW9ucy5zdWNjZXNzLnJldHJpZXZlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQFBvc3QoKVxuICBhc3luYyBjcmVhdGUoQEJvZHkoKSBib2R5KSB7XG4gICAgY29uc3QgbmV3UGVybWlzc2lvbiA9IGF3YWl0IHRoaXMucGVybWlzc2lvblNlcnZpY2UuY3JlYXRlKGJvZHkpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBuZXdQZXJtaXNzaW9uLFxuICAgICAgbWVzc2FnZTogdCgncGVybWlzc2lvbnMuc3VjY2Vzcy5jcmVhdGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBAUHV0KCcvOmlkJylcbiAgYXN5bmMgdXBkYXRlKEBQYXJhbXMoJ2lkJykgaWQ6IHN0cmluZywgQEJvZHkoKSBib2R5KSB7XG4gICAgY29uc3QgdXBkYXRlZFBlcm1pc3Npb24gPSBhd2FpdCB0aGlzLnBlcm1pc3Npb25TZXJ2aWNlLnVwZGF0ZShpZCwgYm9keSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHVwZGF0ZWRQZXJtaXNzaW9uLFxuICAgICAgbWVzc2FnZTogdCgncGVybWlzc2lvbnMuc3VjY2Vzcy51cGRhdGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBARGVsZXRlKCcvOmlkJylcbiAgYXN5bmMgZGVsZXRlKEBQYXJhbXMoJ2lkJykgaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucGVybWlzc2lvblNlcnZpY2UuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogcmVzdWx0LFxuICAgICAgbWVzc2FnZTogdCgncGVybWlzc2lvbnMuc3VjY2Vzcy5kZWxldGVkJyksXG4gICAgICBzdGF0dXM6ICdzdWNjZXNzJ1xuICAgIH07XG4gIH1cblxuICBAR2V0KCcvcm9sZS86cm9sZUlkJylcbiAgYXN5bmMgZ2V0QnlSb2xlKEBQYXJhbXMoJ3JvbGVJZCcpIHJvbGVJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCB0aGlzLnBlcm1pc3Npb25TZXJ2aWNlLmdldFBlcm1pc3Npb25zQnlSb2xlKHJvbGVJZCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHBlcm1pc3Npb25zLFxuICAgICAgbWVzc2FnZTogdCgncGVybWlzc2lvbnMuc3VjY2Vzcy5yZXRyaWV2ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBHZXQoJy9yb2xlcy86cGVybWlzc2lvbklkJylcbiAgYXN5bmMgZ2V0Um9sZXNCeVBlcm1pc3Npb24oQFBhcmFtcygncGVybWlzc2lvbklkJykgcGVybWlzc2lvbklkOiBzdHJpbmcpIHtcbiAgICBjb25zdCByb2xlcyA9IGF3YWl0IHRoaXMucGVybWlzc2lvblNlcnZpY2UuZ2V0Um9sZXNCeVBlcm1pc3Npb24ocGVybWlzc2lvbklkKTtcbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogcm9sZXMsXG4gICAgICBtZXNzYWdlOiB0KCdwZXJtaXNzaW9ucy5zdWNjZXNzLnJldHJpZXZlZCcpLFxuICAgICAgc3RhdHVzOiAnc3VjY2VzcydcbiAgICB9O1xuICB9XG5cbiAgQFBvc3QoJy9hc3NpZ24vOnJvbGVJZC86cGVybWlzc2lvbklkJylcbiAgYXN5bmMgYXNzaWduVG9Sb2xlKFxuICAgIEBQYXJhbXMoJ3JvbGVJZCcpIHJvbGVJZDogc3RyaW5nLFxuICAgIEBQYXJhbXMoJ3Blcm1pc3Npb25JZCcpIHBlcm1pc3Npb25JZDogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucGVybWlzc2lvblNlcnZpY2UuYXNzaWduUGVybWlzc2lvblRvUm9sZShyb2xlSWQsIHBlcm1pc3Npb25JZCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHJlc3VsdCxcbiAgICAgIG1lc3NhZ2U6IHQoJ3Blcm1pc3Npb25zLnN1Y2Nlc3MuYXNzaWduZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBEZWxldGUoJy9yZW1vdmUvOnJvbGVJZC86cGVybWlzc2lvbklkJylcbiAgYXN5bmMgcmVtb3ZlRnJvbVJvbGUoXG4gICAgQFBhcmFtcygncm9sZUlkJykgcm9sZUlkOiBzdHJpbmcsXG4gICAgQFBhcmFtcygncGVybWlzc2lvbklkJykgcGVybWlzc2lvbklkOiBzdHJpbmdcbiAgKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5wZXJtaXNzaW9uU2VydmljZS5yZW1vdmVQZXJtaXNzaW9uRnJvbVJvbGUocm9sZUlkLCBwZXJtaXNzaW9uSWQpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiByZXN1bHQsXG4gICAgICBtZXNzYWdlOiB0KCdwZXJtaXNzaW9ucy5zdWNjZXNzLnJlbW92ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxuXG4gIEBEZWxldGUoKVxuICBAaXNBZG1pbigpXG4gIGFzeW5jIGRlbGV0ZUFsbCgpIHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnBlcm1pc3Npb25TZXJ2aWNlLmRlbGV0ZUFsbCgpO1xuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiByZXN1bHQsXG4gICAgICBtZXNzYWdlOiB0KCdwZXJtaXNzaW9ucy5zdWNjZXNzLmFsbERlbGV0ZWQnKSxcbiAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnXG4gICAgfTtcbiAgfVxufSIsCiAgICAiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ25ham0tYXBpJztcbmltcG9ydCB7IFBlcm1pc3Npb25SZXBvc2l0b3J5IH0gZnJvbSAnLi9QZXJtaXNzaW9uUmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBQZXJtaXNzaW9uVmFsaWRhdG9yIH0gZnJvbSAnLi9QZXJtaXNzaW9uVmFsaWRhdG9yJztcbmltcG9ydCB7IFJvbGVTZXJ2aWNlIH0gZnJvbSAnLi4vcm9sZXMvUm9sZVNlcnZpY2UnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgUGVybWlzc2lvblNlcnZpY2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBlcm1pc3Npb25SZXBvc2l0b3J5OiBQZXJtaXNzaW9uUmVwb3NpdG9yeSxcbiAgICBwcml2YXRlIHBlcm1pc3Npb25WYWxpZGF0b3I6IFBlcm1pc3Npb25WYWxpZGF0b3IsXG4gICAgcHJpdmF0ZSByb2xlU2VydmljZTogUm9sZVNlcnZpY2VcbiAgKSB7IH1cblxuICBhc3luYyBnZXRBbGwoKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucGVybWlzc2lvblJlcG9zaXRvcnkuZ2V0QWxsKCk7XG4gIH1cblxuICBhc3luYyBnZXRCeUlkKGlkOiBzdHJpbmcpIHtcbiAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IuY2hlY2tQZXJtaXNzaW9uRXhpc3RzKGlkKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5nZXRCeUlkKGlkKTtcbiAgfVxuXG4gIGFzeW5jIGdldEJ5TmFtZShuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5nZXRCeU5hbWUobmFtZSk7XG4gIH1cblxuICBhc3luYyBnZXRCeVJlc291cmNlKHJlc291cmNlOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5nZXRBbGwoKS50aGVuKHBlcm1pc3Npb25zID0+XG4gICAgICBwZXJtaXNzaW9ucy5maWx0ZXIocCA9PiBwLnJlc291cmNlID09PSByZXNvdXJjZSlcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlKGRhdGEpIHtcbiAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IudmFsaWRhdGVDcmVhdGVQZXJtaXNzaW9uKGRhdGEpO1xuICAgIGF3YWl0IHRoaXMucGVybWlzc2lvblZhbGlkYXRvci5jaGVja1Blcm1pc3Npb25OYW1lVW5pcXVlKGRhdGEubmFtZSk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucGVybWlzc2lvblJlcG9zaXRvcnkuY3JlYXRlKGRhdGEpO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlKGlkOiBzdHJpbmcsIGRhdGEpIHtcbiAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IuY2hlY2tQZXJtaXNzaW9uRXhpc3RzKGlkKTtcbiAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IuY2hlY2tQZXJtaXNzaW9uTmFtZVVuaXF1ZShkYXRhLm5hbWUsIGlkKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS51cGRhdGUoaWQsIGRhdGEpO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlKGlkOiBzdHJpbmcpIHtcbiAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IuY2hlY2tQZXJtaXNzaW9uRXhpc3RzKGlkKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5kZWxldGUoaWQpO1xuICB9XG5cbiAgYXN5bmMgZ2V0UGVybWlzc2lvbnNCeVJvbGUocm9sZUlkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5nZXRQZXJtaXNzaW9uc0J5Um9sZShyb2xlSWQpO1xuICB9XG5cbiAgYXN5bmMgZ2V0Um9sZXNCeVBlcm1pc3Npb24ocGVybWlzc2lvbklkOiBzdHJpbmcpIHtcbiAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IuY2hlY2tQZXJtaXNzaW9uRXhpc3RzKHBlcm1pc3Npb25JZCk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucGVybWlzc2lvblJlcG9zaXRvcnkuZ2V0Um9sZXNCeVBlcm1pc3Npb24ocGVybWlzc2lvbklkKTtcbiAgfVxuXG4gIGFzeW5jIGFzc2lnblBlcm1pc3Npb25Ub1JvbGUocm9sZUlkOiBzdHJpbmcsIHBlcm1pc3Npb25JZDogc3RyaW5nKSB7XG4gICAgYXdhaXQgdGhpcy5wZXJtaXNzaW9uVmFsaWRhdG9yLmNoZWNrUm9sZUhhc1Blcm1pc3Npb24ocm9sZUlkLCBwZXJtaXNzaW9uSWQpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnBlcm1pc3Npb25SZXBvc2l0b3J5LmFzc2lnblBlcm1pc3Npb25Ub1JvbGUocm9sZUlkLCBwZXJtaXNzaW9uSWQpO1xuICB9XG5cbiAgYXN5bmMgcmVtb3ZlUGVybWlzc2lvbkZyb21Sb2xlKHJvbGVJZDogc3RyaW5nLCBwZXJtaXNzaW9uSWQ6IHN0cmluZykge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnBlcm1pc3Npb25SZXBvc2l0b3J5LnJlbW92ZVBlcm1pc3Npb25Gcm9tUm9sZShyb2xlSWQsIHBlcm1pc3Npb25JZCk7XG4gIH1cblxuICBhc3luYyBzZWVkRGVmYXVsdFBlcm1pc3Npb25zKGRlZmF1bHRQZXJtaXNzaW9ucykge1xuICAgIGNvbnN0IGNyZWF0ZWRQZXJtaXNzaW9ucyA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBwZXJtaXNzaW9uIG9mIGRlZmF1bHRQZXJtaXNzaW9ucykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGVybWlzc2lvbkVudGl0eSA9IGF3YWl0IHRoaXMuY3JlYXRlKHBlcm1pc3Npb24pO1xuICAgICAgICBjcmVhdGVkUGVybWlzc2lvbnMucHVzaChwZXJtaXNzaW9uRW50aXR5KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlZFBlcm1pc3Npb25zO1xuICB9XG5cbiAgYXN5bmMgc2VlZERlZmF1bHRSb2xlUGVybWlzc2lvbnMoZGVmYXVsdFJvbGVQZXJtaXNzaW9ucykge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBbXTtcblxuICAgIGZvciAoY29uc3QgeyByb2xlTmFtZSwgcGVybWlzc2lvbnMgfSBvZiBkZWZhdWx0Um9sZVBlcm1pc3Npb25zKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnBlcm1pc3Npb25WYWxpZGF0b3IuY2hlY2tSb2xlRXhpc3RzQnlOYW1lKHJvbGVOYW1lKTtcbiAgICAgICAgY29uc3Qgcm9sZSA9IGF3YWl0IHRoaXMucm9sZVNlcnZpY2UuZ2V0QnlOYW1lKHJvbGVOYW1lKTtcblxuICAgICAgICBmb3IgKGNvbnN0IHBlcm1pc3Npb25OYW1lIG9mIHBlcm1pc3Npb25zKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGVybWlzc2lvblZhbGlkYXRvci5jaGVja1Blcm1pc3Npb25FeGlzdHNCeU5hbWUocGVybWlzc2lvbk5hbWUpO1xuICAgICAgICAgICAgY29uc3QgcGVybWlzc2lvbiA9IGF3YWl0IHRoaXMuZ2V0QnlOYW1lKHBlcm1pc3Npb25OYW1lKTtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wZXJtaXNzaW9uVmFsaWRhdG9yLmNoZWNrUm9sZUhhc1Blcm1pc3Npb24ocm9sZS5pZCwgcGVybWlzc2lvbi5pZCk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuYXNzaWduUGVybWlzc2lvblRvUm9sZShyb2xlLmlkLCBwZXJtaXNzaW9uLmlkKTtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7IHJvbGU6IHJvbGVOYW1lLCBwZXJtaXNzaW9uOiBwZXJtaXNzaW9uTmFtZSB9KTtcbiAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZUFsbCgpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5kZWxldGVBbGwoKTtcbiAgfVxuXG59IiwKICAgICJpbXBvcnQgeyBJbmplY3RhYmxlLCB0IH0gZnJvbSAnbmFqbS1hcGknO1xuaW1wb3J0IHsgUGVybWlzc2lvblJlcG9zaXRvcnkgfSBmcm9tICcuL1Blcm1pc3Npb25SZXBvc2l0b3J5JztcbmltcG9ydCB7IFJvbGVWYWxpZGF0b3IgfSBmcm9tICcuLi9yb2xlcyc7XG5pbXBvcnQgeyBwYXJzZVNjaGVtYSB9IGZyb20gJ0Avc2hhcmVkJztcbmltcG9ydCB7IHogfSBmcm9tICd6b2QnO1xuXG5jb25zdCBwZXJtaXNzaW9uU2NoZW1hID0gei5vYmplY3Qoe1xuICBuYW1lOiB6LnN0cmluZygpLm1pbigxLCAnUGVybWlzc2lvbiBuYW1lIGlzIHJlcXVpcmVkJyksXG4gIGRlc2NyaXB0aW9uOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIHJlc291cmNlOiB6LnN0cmluZygpLm1pbigxLCAnUmVzb3VyY2UgaXMgcmVxdWlyZWQnKSxcbiAgYWN0aW9uOiB6LnN0cmluZygpLm1pbigxLCAnQWN0aW9uIGlzIHJlcXVpcmVkJyksXG59KTtcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFBlcm1pc3Npb25WYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBlcm1pc3Npb25SZXBvc2l0b3J5OiBQZXJtaXNzaW9uUmVwb3NpdG9yeSxcbiAgICBwcml2YXRlIHJvbGVWYWxpZGF0b3I6IFJvbGVWYWxpZGF0b3JcbiAgKSB7fVxuXG4gIGFzeW5jIHZhbGlkYXRlQ3JlYXRlUGVybWlzc2lvbihkYXRhKSB7XG4gICAgcmV0dXJuIHBhcnNlU2NoZW1hKHBlcm1pc3Npb25TY2hlbWEsIGRhdGEpO1xuICB9XG5cbiAgYXN5bmMgaXNQZXJtaXNzaW9uRXhpc3RzKGlkOiBzdHJpbmcpIHtcbiAgICBjb25zdCBleGlzdGluZ1Blcm1pc3Npb24gPSBhd2FpdCB0aGlzLnBlcm1pc3Npb25SZXBvc2l0b3J5LmdldEJ5SWQoaWQpO1xuICAgIHJldHVybiAhIWV4aXN0aW5nUGVybWlzc2lvbjtcbiAgfVxuXG4gIGFzeW5jIGlzUGVybWlzc2lvbk5hbWVFeGlzdHMobmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgZXhpc3RpbmdQZXJtaXNzaW9uID0gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5nZXRCeU5hbWUobmFtZSk7XG4gICAgcmV0dXJuICEhZXhpc3RpbmdQZXJtaXNzaW9uO1xuICB9XG5cbiAgLy89PT09PT09PT09PT09PT09PT09PT09PSB0aHJvdyBlcnJvcnNcblxuICBhc3luYyBjaGVja1Blcm1pc3Npb25FeGlzdHMoaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IHBlcm1pc3Npb25FeGlzdHMgPSBhd2FpdCB0aGlzLmlzUGVybWlzc2lvbkV4aXN0cyhpZCk7XG4gICAgaWYgKCFwZXJtaXNzaW9uRXhpc3RzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IodCgncGVybWlzc2lvbnMuZXJyb3JzLm5vdEZvdW5kJykpO1xuICAgIH1cbiAgICByZXR1cm4gcGVybWlzc2lvbkV4aXN0cztcbiAgfVxuXG4gIGFzeW5jIGNoZWNrUGVybWlzc2lvbkV4aXN0c0J5TmFtZShuYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBwZXJtaXNzaW9uRXhpc3RzID0gYXdhaXQgdGhpcy5pc1Blcm1pc3Npb25OYW1lRXhpc3RzKG5hbWUpO1xuICAgIGlmICghcGVybWlzc2lvbkV4aXN0cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHQoJ3Blcm1pc3Npb25zLmVycm9ycy5ub3RGb3VuZCcpKTtcbiAgICB9XG4gICAgcmV0dXJuIHBlcm1pc3Npb25FeGlzdHM7XG4gIH1cblxuICBhc3luYyBjaGVja1Blcm1pc3Npb25OYW1lVW5pcXVlKG5hbWU6IHN0cmluZywgZXhjbHVkZUlkID0gbnVsbCkge1xuICAgIGlmICghbmFtZSkgcmV0dXJuO1xuICAgIGNvbnN0IGV4aXN0aW5nUGVybWlzc2lvbiA9IGF3YWl0IHRoaXMucGVybWlzc2lvblJlcG9zaXRvcnkuZ2V0QnlOYW1lKG5hbWUpO1xuICAgIGlmIChleGlzdGluZ1Blcm1pc3Npb24gJiYgZXhpc3RpbmdQZXJtaXNzaW9uLmlkICE9PSBleGNsdWRlSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcih0KCdwZXJtaXNzaW9ucy5lcnJvcnMubmFtZUV4aXN0cycpKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjaGVja1JvbGVFeGlzdHMoaWQ6IHN0cmluZykge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnJvbGVWYWxpZGF0b3IuY2hlY2tSb2xlRXhpc3RzKGlkKTtcbiAgfVxuXG4gIGFzeW5jIGNoZWNrUm9sZUV4aXN0c0J5TmFtZShuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5yb2xlVmFsaWRhdG9yLmNoZWNrUm9sZUV4aXN0c0J5TmFtZShuYW1lKTtcbiAgfVxuXG4gIGFzeW5jIGNoZWNrUm9sZUhhc1Blcm1pc3Npb24ocm9sZUlkOiBzdHJpbmcsIHBlcm1pc3Npb25JZDogc3RyaW5nKSB7XG4gICAgYXdhaXQgdGhpcy5yb2xlVmFsaWRhdG9yLmNoZWNrUm9sZUV4aXN0cyhyb2xlSWQpO1xuICAgIGF3YWl0IHRoaXMuY2hlY2tQZXJtaXNzaW9uRXhpc3RzKHBlcm1pc3Npb25JZCk7XG5cbiAgICBjb25zdCBoYXNQZXJtaXNzaW9uID0gYXdhaXQgdGhpcy5wZXJtaXNzaW9uUmVwb3NpdG9yeS5jaGVja1JvbGVIYXNQZXJtaXNzaW9uKHJvbGVJZCwgcGVybWlzc2lvbklkKTtcbiAgICBpZiAoaGFzUGVybWlzc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKHQoJ3Blcm1pc3Npb25zLmVycm9ycy5yb2xlQWxyZWFkeUhhc1Blcm1pc3Npb24nKSk7XG4gICAgfVxuICB9XG5cbn0iLAogICAgIlxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBfaXNFbXB0eSBmcm9tICdsb2Rhc2guaXNlbXB0eSc7XG5pbXBvcnQgeyBTUUwsIHNxbCB9IGZyb20gJ2RyaXp6bGUtb3JtJztcbmltcG9ydCB7IEFueVBnQ29sdW1uIH0gZnJvbSAnZHJpenpsZS1vcm0vcGctY29yZSc7XG5cbmV4cG9ydCBjb25zdCBhdmF0YXJzUGF0aCA9IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAnYXZhdGFycycpO1xuXG5leHBvcnQgY29uc3QgcGFyc2VTY2hlbWEgPSBhc3luYyAoc2NoZW1hLCBkYXRhKSA9PiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHNjaGVtYS5wYXJzZUFzeW5jKGRhdGEpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnN0IGVycm9ycyA9IGVycm9yLmlzc3VlcyB8fCBlcnJvci5lcnJvcnMgfHwgW107XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3JzXG4gICAgICAubWFwKGVyciA9PiBgJHtlcnIucGF0aC5qb2luKCcuJyl9OiAke2Vyci5tZXNzYWdlfWApXG4gICAgICAuam9pbignOyAnKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNsZWFuID0gKG9iajogYW55KTogYW55ID0+IHtcbiAgY29uc3QgY2xlYW5lZCA9IHt9O1xuXG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gJycpIHtcbiAgICAgIGNsZWFuZWRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjbGVhbmVkO1xufVxuXG5leHBvcnQgY29uc3QgZ2V0QXZhdGFyRmlsZSA9IGFzeW5jIChmaWxlTmFtZSkgPT4ge1xuICB0cnkge1xuICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKGF2YXRhcnNQYXRoLCBmaWxlTmFtZSk7XG4gICAgY29uc3QgYnVmZmVyOiBhbnkgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCk7XG4gICAgY29uc3QgZmlsZSA9IG5ldyBGaWxlKFtidWZmZXJdLCBmaWxlTmFtZSwge1xuICAgICAgdHlwZTogJ2ltYWdlL3BuZydcbiAgICB9KTtcbiAgICByZXR1cm4gZmlsZTtcbiAgfVxuICBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZm9ybWF0RGF0ZSA9IChkYXRlVmFsdWUpID0+IHtcbiAgaWYgKCFkYXRlVmFsdWUpIHJldHVybiBudWxsO1xuXG4gIGxldCBkYXRlOiBEYXRlO1xuXG4gIGlmIChkYXRlVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgZGF0ZSA9IGRhdGVWYWx1ZTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZGF0ZVZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlVmFsdWUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgaWYgKGlzTmFOKGRhdGUuZ2V0VGltZSgpKSkgcmV0dXJuIG51bGw7XG5cbiAgcmV0dXJuIGRhdGUudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlQWdlKGRhdGVPZkJpcnRoKSB7XG4gIGlmICghZGF0ZU9mQmlydGgpIHJldHVybiBudWxsO1xuXG4gIGNvbnN0IGZvcm1hdHRlZERhdGUgPSBmb3JtYXREYXRlKGRhdGVPZkJpcnRoKTtcbiAgaWYgKCFmb3JtYXR0ZWREYXRlKSByZXR1cm4gbnVsbDtcblxuICBjb25zdCBiaXJ0aCA9IG5ldyBEYXRlKGZvcm1hdHRlZERhdGUpO1xuICBjb25zdCB0b2RheSA9IG5ldyBEYXRlKCk7XG4gIGxldCBhZ2UgPSB0b2RheS5nZXRGdWxsWWVhcigpIC0gYmlydGguZ2V0RnVsbFllYXIoKTtcbiAgY29uc3QgbW9udGhEaWZmID0gdG9kYXkuZ2V0TW9udGgoKSAtIGJpcnRoLmdldE1vbnRoKCk7XG5cbiAgaWYgKG1vbnRoRGlmZiA8IDAgfHwgKG1vbnRoRGlmZiA9PT0gMCAmJiB0b2RheS5nZXREYXRlKCkgPCBiaXJ0aC5nZXREYXRlKCkpKSB7XG4gICAgYWdlLS07XG4gIH1cblxuICByZXR1cm4gYWdlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlWWVhcnNPZkV4cGVyaWVuY2UoaGlyZURhdGUpIHtcbiAgaWYgKCFoaXJlRGF0ZSkgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgZm9ybWF0dGVkRGF0ZSA9IGZvcm1hdERhdGUoaGlyZURhdGUpO1xuICBpZiAoIWZvcm1hdHRlZERhdGUpIHJldHVybiBudWxsO1xuXG4gIGNvbnN0IGhpcmUgPSBuZXcgRGF0ZShmb3JtYXR0ZWREYXRlKTtcbiAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuICBsZXQgeWVhcnMgPSB0b2RheS5nZXRGdWxsWWVhcigpIC0gaGlyZS5nZXRGdWxsWWVhcigpO1xuICBjb25zdCBtb250aERpZmYgPSB0b2RheS5nZXRNb250aCgpIC0gaGlyZS5nZXRNb250aCgpO1xuXG4gIGlmIChtb250aERpZmYgPCAwIHx8IChtb250aERpZmYgPT09IDAgJiYgdG9kYXkuZ2V0RGF0ZSgpIDwgaGlyZS5nZXREYXRlKCkpKSB7XG4gICAgeWVhcnMtLTtcbiAgfVxuXG4gIHJldHVybiB5ZWFycztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBpY2tQcm9wczxUPihzb3VyY2U6IFQsIGtleXMpOiBQYXJ0aWFsPFQ+IHtcbiAgY29uc3QgcmVzdWx0ID0ge307XG5cbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgIGlmIChzb3VyY2Vba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXN1bHRba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBjb25zdCBpc0VtcHR5ID0gX2lzRW1wdHk7XG5cbmV4cG9ydCBmdW5jdGlvbiBqc29uQWdnKFxuICBmaWVsZHM6IFJlY29yZDxzdHJpbmcsIEFueVBnQ29sdW1uPixcbiAgb3JkZXJCeT86IEFueVBnQ29sdW1uIHwgU1FMXG4pIHtcbiAgY29uc3QgZmllbGRFbnRyaWVzID0gT2JqZWN0LmVudHJpZXMoZmllbGRzKTtcbiAgY29uc3QganNvbkJ1aWxkQXJncyA9IGZpZWxkRW50cmllcy5mbGF0TWFwKChba2V5LCBjb2x1bW5dKSA9PiBbXG4gICAgc3FsLnJhdyhgJyR7a2V5fSdgKSxcbiAgICBjb2x1bW5cbiAgXSk7XG5cbiAgbGV0IGFnZ3JlZ2F0aW9uID0gc3FsYGpzb25fYWdnKGpzb25fYnVpbGRfb2JqZWN0KCR7c3FsLmpvaW4oanNvbkJ1aWxkQXJncywgc3FsYCwgYCl9KWA7XG5cbiAgaWYgKG9yZGVyQnkpIHtcbiAgICBhZ2dyZWdhdGlvbiA9IHNxbGAke2FnZ3JlZ2F0aW9ufSBPUkRFUiBCWSAke29yZGVyQnl9YDtcbiAgfVxuXG4gIGFnZ3JlZ2F0aW9uID0gc3FsYCR7YWdncmVnYXRpb259KWA7XG5cbiAgLy8gV3JhcCB3aXRoIENPQUxFU0NFIHRvIHJldHVybiBlbXB0eSBhcnJheSBpbnN0ZWFkIG9mIG51bGxcbiAgcmV0dXJuIHNxbGBDT0FMRVNDRSgke2FnZ3JlZ2F0aW9ufSwgJ1tdJzo6anNvbilgO1xufVxuXG5leHBvcnQgZnVuY3Rpb24ganNvbkFnZ1N1YnF1ZXJ5KFxuICBmaWVsZHM6IFJlY29yZDxzdHJpbmcsIEFueVBnQ29sdW1uPixcbiAgZnJvbTogYW55LFxuICB3aGVyZTogU1FMLFxuICBvcmRlckJ5PzogQW55UGdDb2x1bW4gfCBTUUxcbikge1xuICBjb25zdCBmaWVsZEVudHJpZXMgPSBPYmplY3QuZW50cmllcyhmaWVsZHMpO1xuICBjb25zdCBqc29uQnVpbGRBcmdzID0gZmllbGRFbnRyaWVzLmZsYXRNYXAoKFtrZXksIGNvbHVtbl0pID0+IFtcbiAgICBzcWwucmF3KGAnJHtrZXl9J2ApLFxuICAgIGNvbHVtblxuICBdKTtcblxuICBsZXQgYWdncmVnYXRpb24gPSBzcWxgXG4gICAgU0VMRUNUIGpzb25fYWdnKERJU1RJTkNUIGpzb25fYnVpbGRfb2JqZWN0KCR7c3FsLmpvaW4oanNvbkJ1aWxkQXJncywgc3FsYCwgYCl9KSlcbiAgICBGUk9NICR7ZnJvbX1cbiAgICBXSEVSRSAke3doZXJlfVxuICBgO1xuXG4gIGlmIChvcmRlckJ5KSB7XG4gICAgYWdncmVnYXRpb24gPSBzcWxgXG4gICAgICBTRUxFQ1QganNvbl9hZ2coanNvbl9idWlsZF9vYmplY3QoJHtzcWwuam9pbihqc29uQnVpbGRBcmdzLCBzcWxgLCBgKX0pIE9SREVSIEJZICR7b3JkZXJCeX0pXG4gICAgICBGUk9NICR7ZnJvbX1cbiAgICAgIFdIRVJFICR7d2hlcmV9XG4gICAgYDtcbiAgfVxuXG4gIHJldHVybiBzcWxgQ09BTEVTQ0UoKCR7YWdncmVnYXRpb259KSwgJ1tdJzo6anNvbilgO1xufVxuXG5leHBvcnQgY29uc3QgaXNQYXRoID0gKGltZykgPT5cbiAgdHlwZW9mIGltZyA9PT0gJ3N0cmluZycgJiYgaW1nLnRyaW0oKS5sZW5ndGggPiAwICYmIChpbWcuc3RhcnRzV2l0aCgnLycpIHx8IGltZy5zdGFydHNXaXRoKCdodHRwJykgfHwgaW1nLnN0YXJ0c1dpdGgoJ3N0b3JhZ2UvJykpO1xuXG5cbmV4cG9ydCBjb25zdCBpc0ZpbGUgPSAoaW1nKSA9PlxuICAhIWltZyAmJiB0eXBlb2YgaW1nICE9PSAnc3RyaW5nJyAmJiBpbWcgaW5zdGFuY2VvZiBGaWxlO1xuXG4iLAogICAgImltcG9ydCB7IGRyaXp6bGUsIFBvc3RncmVzSnNEYXRhYmFzZSB9IGZyb20gJ2RyaXp6bGUtb3JtL3Bvc3RncmVzLWpzJztcbmltcG9ydCAqIGFzIHNjaGVtYSBmcm9tICcuL3NjaGVtYSc7XG5pbXBvcnQgeyBEQiBhcyBHZW5lcmljREIgfSBmcm9tICduYWptLWFwaSc7XG5cbmV4cG9ydCB0eXBlIERCID0gUG9zdGdyZXNKc0RhdGFiYXNlPHR5cGVvZiBzY2hlbWE+O1xuXG4vKipcbiAqIOKaoO+4jyAgSU1QT1JUQU5UOiBEZXZlbG9wbWVudC1Pbmx5IERhdGFiYXNlIEluc3RhbmNlXG4gKlxuICogVGhpcyBEQiBpbnN0YW5jZSBpcyBPTkxZIGZvciBzdGFuZGFsb25lIGRldmVsb3BtZW50IGFuZCB0ZXN0aW5nLlxuICogV2hlbiB1c2VkIGFzIGEgcGx1Z2luIGluIHByb2R1Y3Rpb24sIHRoZSBkYXRhYmFzZSB3aWxsIGJlIGluamVjdGVkXG4gKiBhdXRvbWF0aWNhbGx5IGJ5IHRoZSBuYWptLWFwaSBwbHVnaW4gc3lzdGVtLlxuICpcbiAqIERPIE5PVCB1c2UgdGhpcyBpbiBwcm9kdWN0aW9uIC0gaXQgY3JlYXRlcyBhIGR1cGxpY2F0ZSBjb25uZWN0aW9uIVxuICpcbiAqIEluIHByb2R1Y3Rpb246XG4gKiAtIFVzZSBuYWptLWF1dGggYXMgYSBwbHVnaW46IGBpbXBvcnQgeyBBdXRoUGx1Z2luIH0gZnJvbSAnbmFqbS1hdXRoL3BsdWdpbidgXG4gKiAtIFRoZSBtYWluIGFwcCByZWdpc3RlcnMgdGhlIGRhdGFiYXNlIGluIERhdGFiYXNlUmVnaXN0cnlcbiAqIC0gUmVwb3NpdG9yaWVzIGdldCB0aGUgREIgYXV0b21hdGljYWxseSBpbmplY3RlZCB2aWEgZGVwZW5kZW5jeSBpbmplY3Rpb25cbiAqXG4gKiBAZXhhbXBsZSBQcm9kdWN0aW9uIFVzYWdlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBTZXJ2ZXIsIERhdGFiYXNlUmVnaXN0cnkgfSBmcm9tICduYWptLWFwaSc7XG4gKiBpbXBvcnQgeyBBdXRoUGx1Z2luIH0gZnJvbSAnbmFqbS1hdXRoL3BsdWdpbic7XG4gKlxuICogY29uc3QgYXBwID0gYXdhaXQgU2VydmVyKHtcbiAqICAgZGF0YWJhc2VzOiB7XG4gKiAgICAgYXV0aDogbXlEYkluc3RhbmNlICAvLyBTaW5nbGUgc291cmNlIG9mIHRydXRoXG4gKiAgIH0sXG4gKiAgIHBsdWdpbnM6IFtBdXRoUGx1Z2luXVxuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IGRiOiBEQiB8IEdlbmVyaWNEQiA9IHByb2Nlc3MuZW52LkRCX1VSTFxuICA/IGRyaXp6bGUocHJvY2Vzcy5lbnYuREJfVVJMLCB7IHNjaGVtYSB9KVxuICA6IG51bGwgYXMgYW55OyAgLy8gV2lsbCBiZSBpbmplY3RlZCBieSBwbHVnaW4gc3lzdGVtIGluIHByb2R1Y3Rpb25cblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnICYmIGRiKSB7XG4gIGNvbnNvbGUud2Fybign4pqg77iPICBuYWptLWF1dGg6IFVzaW5nIHN0YW5kYWxvbmUgREIgaW5zdGFuY2UuIFRoaXMgc2hvdWxkIG9ubHkgYmUgdXNlZCBmb3IgZGV2ZWxvcG1lbnQuJyk7XG59IiwKICAgICJpbXBvcnQgeyBwZ1RhYmxlLCB0ZXh0LCBib29sZWFuLCB0aW1lc3RhbXAgfSBmcm9tICdkcml6emxlLW9ybS9wZy1jb3JlJztcclxuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkJztcclxuXHJcbmltcG9ydCB7IHNxbCB9IGZyb20gJ2RyaXp6bGUtb3JtJztcclxuaW1wb3J0IHsgdG9rZW5TdGF0dXNFbnVtLCB0b2tlblR5cGVFbnVtLCB1c2VyU3RhdHVzRW51bSB9IGZyb20gJy4vUGdFbnVtJztcclxuXHJcbmV4cG9ydCBjb25zdCB0aW1lc3RhbXBzID0ge1xyXG4gIGNyZWF0ZWRBdDogdGltZXN0YW1wKCdjcmVhdGVkX2F0JywgeyBtb2RlOiAnc3RyaW5nJyB9KS5kZWZhdWx0Tm93KCksXHJcbiAgdXBkYXRlZEF0OiB0aW1lc3RhbXAoJ3VwZGF0ZWRfYXQnLCB7IG1vZGU6ICdzdHJpbmcnIH0pLmRlZmF1bHROb3coKS4kb25VcGRhdGUoKCkgPT4gc3FsYENVUlJFTlRfVElNRVNUQU1QYCksXHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgaWRGaWVsZCA9IChsZW5ndGggPSA1KSA9PlxyXG4gIHRleHQoJ2lkJykucHJpbWFyeUtleSgpLm5vdE51bGwoKS4kZGVmYXVsdEZuKCgpID0+IG5hbm9pZChsZW5ndGgpKTtcclxuXHJcbmV4cG9ydCBjb25zdCByb2xlc1RhYmxlID0gcGdUYWJsZSgncm9sZXMnLCB7XHJcbiAgaWQ6IGlkRmllbGQoKSxcclxuICBuYW1lOiB0ZXh0KCduYW1lJykubm90TnVsbCgpLFxyXG4gIGRlc2NyaXB0aW9uOiB0ZXh0KCdkZXNjcmlwdGlvbicpLFxyXG59KTtcclxuXHJcbmV4cG9ydCBjb25zdCB1c2Vyc1RhYmxlID0gcGdUYWJsZSgndXNlcnMnLCB7XHJcbiAgaWQ6IGlkRmllbGQoOCksXHJcbiAgZW1haWw6IHRleHQoJ2VtYWlsJykubm90TnVsbCgpLnVuaXF1ZSgpLFxyXG4gIGVtYWlsVmVyaWZpZWQ6IGJvb2xlYW4oJ2VtYWlsX3ZlcmlmaWVkJykuZGVmYXVsdChmYWxzZSksXHJcbiAgcGFzc3dvcmQ6IHRleHQoJ3Bhc3N3b3JkJykubm90TnVsbCgpLFxyXG4gIGltYWdlOiB0ZXh0KCdpbWFnZScpLmRlZmF1bHQoJ25vYXZhdGFyLnBuZycpLFxyXG4gIHN0YXR1czogdXNlclN0YXR1c0VudW0oJ3N0YXR1cycpLmRlZmF1bHQoJ3BlbmRpbmcnKSxcclxuICByb2xlSWQ6IHRleHQoJ3JvbGVfaWQnKS5yZWZlcmVuY2VzKCgpID0+IHJvbGVzVGFibGUuaWQpLFxyXG4gIGxhc3RMb2dpbjogdGltZXN0YW1wKCdsYXN0X2xvZ2luJywgeyBtb2RlOiAnc3RyaW5nJyB9KSxcclxuICAuLi50aW1lc3RhbXBzLFxyXG59KTtcclxuXHJcbmV4cG9ydCBjb25zdCB0b2tlbnNUYWJsZSA9IHBnVGFibGUoJ3Rva2VucycsIHtcclxuICBpZDogaWRGaWVsZCgxMCksXHJcbiAgdXNlcklkOiB0ZXh0KCd1c2VyX2lkJykucmVmZXJlbmNlcygoKSA9PiB1c2Vyc1RhYmxlLmlkLCB7IG9uRGVsZXRlOiAnY2FzY2FkZScgfSkudW5pcXVlKCkubm90TnVsbCgpLFxyXG4gIHRva2VuOiB0ZXh0KCd0b2tlbicpLm5vdE51bGwoKSxcclxuICB0eXBlOiB0b2tlblR5cGVFbnVtKCd0eXBlJykuZGVmYXVsdCgncmVmcmVzaCcpLFxyXG4gIHN0YXR1czogdG9rZW5TdGF0dXNFbnVtKCdzdGF0dXMnKS5kZWZhdWx0KCdhY3RpdmUnKSxcclxuICBleHBpcmVzQXQ6IHRpbWVzdGFtcCgnZXhwaXJlc19hdCcsIHsgbW9kZTogJ3N0cmluZycgfSkubm90TnVsbCgpLFxyXG4gIC4uLnRpbWVzdGFtcHMsXHJcbn0pO1xyXG5cclxuXHJcbmV4cG9ydCBjb25zdCBwZXJtaXNzaW9uc1RhYmxlID0gcGdUYWJsZSgncGVybWlzc2lvbnMnLCB7XHJcbiAgaWQ6IGlkRmllbGQoKSxcclxuICBuYW1lOiB0ZXh0KCduYW1lJykubm90TnVsbCgpLnVuaXF1ZSgpLFxyXG4gIGRlc2NyaXB0aW9uOiB0ZXh0KCdkZXNjcmlwdGlvbicpLFxyXG4gIHJlc291cmNlOiB0ZXh0KCdyZXNvdXJjZScpLm5vdE51bGwoKSxcclxuICBhY3Rpb246IHRleHQoJ2FjdGlvbicpLm5vdE51bGwoKSxcclxuICAuLi50aW1lc3RhbXBzLFxyXG59KTtcclxuXHJcblxyXG5leHBvcnQgY29uc3Qgcm9sZVBlcm1pc3Npb25zVGFibGUgPSBwZ1RhYmxlKCdyb2xlX3Blcm1pc3Npb25zJywge1xyXG4gIGlkOiBpZEZpZWxkKCksXHJcbiAgcm9sZUlkOiB0ZXh0KCdyb2xlX2lkJykucmVmZXJlbmNlcygoKSA9PiByb2xlc1RhYmxlLmlkKS5ub3ROdWxsKCksXHJcbiAgcGVybWlzc2lvbklkOiB0ZXh0KCdwZXJtaXNzaW9uX2lkJykucmVmZXJlbmNlcygoKSA9PiBwZXJtaXNzaW9uc1RhYmxlLmlkKS5ub3ROdWxsKCksXHJcbiAgLi4udGltZXN0YW1wcyxcclxufSk7XHJcblxyXG5leHBvcnQgdHlwZSBVc2VyID0gdHlwZW9mIHVzZXJzVGFibGUuJGluZmVyU2VsZWN0O1xyXG5leHBvcnQgdHlwZSBOZXdVc2VyID0gdHlwZW9mIHVzZXJzVGFibGUuJGluZmVySW5zZXJ0O1xyXG5leHBvcnQgdHlwZSBUb2tlbiA9IHR5cGVvZiB0b2tlbnNUYWJsZS4kaW5mZXJTZWxlY3Q7XHJcbmV4cG9ydCB0eXBlIE5ld1Rva2VuID0gdHlwZW9mIHRva2Vuc1RhYmxlLiRpbmZlckluc2VydDtcclxuZXhwb3J0IHR5cGUgUm9sZSA9IHR5cGVvZiByb2xlc1RhYmxlLiRpbmZlclNlbGVjdDtcclxuZXhwb3J0IHR5cGUgTmV3Um9sZSA9IHR5cGVvZiByb2xlc1RhYmxlLiRpbmZlckluc2VydDtcclxuZXhwb3J0IHR5cGUgUGVybWlzc2lvbiA9IHR5cGVvZiBwZXJtaXNzaW9uc1RhYmxlLiRpbmZlclNlbGVjdDtcclxuZXhwb3J0IHR5cGUgTmV3UGVybWlzc2lvbiA9IHR5cGVvZiBwZXJtaXNzaW9uc1RhYmxlLiRpbmZlckluc2VydDtcclxuZXhwb3J0IHR5cGUgUm9sZVBlcm1pc3Npb24gPSB0eXBlb2Ygcm9sZVBlcm1pc3Npb25zVGFibGUuJGluZmVyU2VsZWN0O1xyXG5leHBvcnQgdHlwZSBOZXdSb2xlUGVybWlzc2lvbiA9IHR5cGVvZiByb2xlUGVybWlzc2lvbnNUYWJsZS4kaW5mZXJJbnNlcnQ7XHJcbiIsCiAgICAiLy8gLS0tIERyaXp6bGUgcGdFbnVtIEdlbmVyYXRpb24gLS0tXG5pbXBvcnQgeyBnZXRFbnVtQ29uZmlnIH0gZnJvbSBcIkAvbGliL0VOVU1TXCI7XG5pbXBvcnQgeyBwZ0VudW0gfSBmcm9tIFwiZHJpenpsZS1vcm0vcGctY29yZVwiO1xuXG5jb25zdCBjcmVhdGVQZ0VudW0gPSAoZW51bUtleSkgPT4ge1xuICBjb25zdCBjb25maWcgPSBnZXRFbnVtQ29uZmlnKGVudW1LZXkpXG4gIGlmICghY29uZmlnKSB0aHJvdyBuZXcgRXJyb3IoYEVudW0gJHtlbnVtS2V5fSBub3QgZm91bmRgKVxuICBjb25zdCBlbnVtTmFtZSA9IGNvbmZpZy5uYW1lIHx8IGVudW1LZXlcbiAgcmV0dXJuIHBnRW51bShlbnVtTmFtZSwgY29uZmlnLnZhbHVlcylcbn1cblxuZXhwb3J0IGNvbnN0IHVzZXJTdGF0dXNFbnVtID0gY3JlYXRlUGdFbnVtKCd1c2VyU3RhdHVzJyk7XG5leHBvcnQgY29uc3QgdG9rZW5TdGF0dXNFbnVtID0gY3JlYXRlUGdFbnVtKCd0b2tlblN0YXR1cycpO1xuZXhwb3J0IGNvbnN0IHRva2VuVHlwZUVudW0gPSBjcmVhdGVQZ0VudW0oJ3Rva2VuVHlwZScpO1xuZXhwb3J0IGNvbnN0IHN0dWRlbnRTdGF0dXNFbnVtID0gY3JlYXRlUGdFbnVtKCdzdHVkZW50U3RhdHVzJyk7XG4iLAogICAgImltcG9ydCB7IFBsdWdpbkNvbmZpZyB9IGZyb20gJ25ham0tYXBpJztcclxuXHJcbi8vIEltcG9ydCBhbGwgY29udHJvbGxlcnNcclxuaW1wb3J0IHsgVXNlckNvbnRyb2xsZXIgfSBmcm9tICcuL3VzZXJzL1VzZXJDb250cm9sbGVyJztcclxuaW1wb3J0IHsgQXV0aENvbnRyb2xsZXIgfSBmcm9tICcuL2F1dGgvQXV0aENvbnRyb2xsZXInO1xyXG5pbXBvcnQgeyBSb2xlQ29udHJvbGxlciB9IGZyb20gJy4vcm9sZXMvUm9sZUNvbnRyb2xsZXInO1xyXG5pbXBvcnQgeyBQZXJtaXNzaW9uQ29udHJvbGxlciB9IGZyb20gJy4vcGVybWlzc2lvbnMvUGVybWlzc2lvbkNvbnRyb2xsZXInO1xyXG5cclxuLy8gSW1wb3J0IGFsbCBzZXJ2aWNlc1xyXG5pbXBvcnQgeyBVc2VyU2VydmljZSB9IGZyb20gJy4vdXNlcnMvVXNlclNlcnZpY2UnO1xyXG5pbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJy4vYXV0aC9BdXRoU2VydmljZSc7XHJcbmltcG9ydCB7IENvb2tpZVNlcnZpY2UgfSBmcm9tICcuL2F1dGgvQ29va2llU2VydmljZSc7XHJcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSAnLi9hdXRoL0VuY3J5cHRpb25TZXJ2aWNlJztcclxuaW1wb3J0IHsgUm9sZVNlcnZpY2UgfSBmcm9tICcuL3JvbGVzL1JvbGVTZXJ2aWNlJztcclxuaW1wb3J0IHsgUGVybWlzc2lvblNlcnZpY2UgfSBmcm9tICcuL3Blcm1pc3Npb25zL1Blcm1pc3Npb25TZXJ2aWNlJztcclxuaW1wb3J0IHsgVG9rZW5TZXJ2aWNlIH0gZnJvbSAnLi90b2tlbnMvVG9rZW5TZXJ2aWNlJztcclxuXHJcbi8vIEltcG9ydCBhbGwgcmVwb3NpdG9yaWVzXHJcbmltcG9ydCB7IFVzZXJSZXBvc2l0b3J5IH0gZnJvbSAnLi91c2Vycy9Vc2VyUmVwb3NpdG9yeSc7XHJcbmltcG9ydCB7IFJvbGVSZXBvc2l0b3J5IH0gZnJvbSAnLi9yb2xlcy9Sb2xlUmVwb3NpdG9yeSc7XHJcbmltcG9ydCB7IFBlcm1pc3Npb25SZXBvc2l0b3J5IH0gZnJvbSAnLi9wZXJtaXNzaW9ucy9QZXJtaXNzaW9uUmVwb3NpdG9yeSc7XHJcbmltcG9ydCB7IFRva2VuUmVwb3NpdG9yeSB9IGZyb20gJy4vdG9rZW5zL1Rva2VuUmVwb3NpdG9yeSc7XHJcblxyXG4vLyBJbXBvcnQgYWxsIHZhbGlkYXRvcnNcclxuaW1wb3J0IHsgVXNlclZhbGlkYXRvciB9IGZyb20gJy4vdXNlcnMvVXNlclZhbGlkYXRvcic7XHJcbmltcG9ydCB7IFJvbGVWYWxpZGF0b3IgfSBmcm9tICcuL3JvbGVzL1JvbGVWYWxpZGF0b3InO1xyXG5pbXBvcnQgeyBQZXJtaXNzaW9uVmFsaWRhdG9yIH0gZnJvbSAnLi9wZXJtaXNzaW9ucy9QZXJtaXNzaW9uVmFsaWRhdG9yJztcclxuXHJcbi8vIEltcG9ydCBhbGwgZ3VhcmRzXHJcbmltcG9ydCB7IFJvbGVHdWFyZHMgfSBmcm9tICcuL3JvbGVzL1JvbGVHdWFyZHMnO1xyXG5pbXBvcnQgeyBQZXJtaXNzaW9uR3VhcmRzIH0gZnJvbSAnLi9wZXJtaXNzaW9ucy9QZXJtaXNzaW9uR3VhcmRzJztcclxuXHJcbi8qKlxyXG4gKiBuYWptLWF1dGggUGx1Z2luIENvbmZpZ3VyYXRpb25cclxuICpcclxuICogVGhpcyBwbHVnaW4gcHJvdmlkZXMgY29tcHJlaGVuc2l2ZSBhdXRoZW50aWNhdGlvbiBhbmQgYXV0aG9yaXphdGlvbiBmZWF0dXJlczpcclxuICogLSBVc2VyIG1hbmFnZW1lbnQgd2l0aCBzZWN1cmUgcGFzc3dvcmQgaGFzaGluZ1xyXG4gKiAtIFJvbGUtYmFzZWQgYWNjZXNzIGNvbnRyb2wgKFJCQUMpXHJcbiAqIC0gUGVybWlzc2lvbiBtYW5hZ2VtZW50IHdpdGggZ3VhcmRzXHJcbiAqIC0gSldUIHRva2VuIGF1dGhlbnRpY2F0aW9uXHJcbiAqIC0gU2Vzc2lvbiBtYW5hZ2VtZW50IHdpdGggY29va2llc1xyXG4gKiAtIEVuY3J5cHRpb24gdXRpbGl0aWVzXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogaW1wb3J0IHsgU2VydmVyIH0gZnJvbSAnbmFqbS1hcGknO1xyXG4gKiBpbXBvcnQgeyBBdXRoUGx1Z2luIH0gZnJvbSAnbmFqbS1hdXRoL3BsdWdpbic7XHJcbiAqIGltcG9ydCB7IGRiIH0gZnJvbSAnLi9kYXRhYmFzZSc7XHJcbiAqXHJcbiAqIGNvbnN0IGFwcCA9IGF3YWl0IFNlcnZlcih7XHJcbiAqICAgZGF0YWJhc2VzOiB7XHJcbiAqICAgICBkZWZhdWx0OiBkYixcclxuICogICAgIGF1dGg6IGRiICAvLyBDYW4gdXNlIHNhbWUgREIgb3Igc2VwYXJhdGVcclxuICogICB9LFxyXG4gKiAgIHBsdWdpbnM6IFtBdXRoUGx1Z2luXVxyXG4gKiB9KTtcclxuICogYGBgXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgQXV0aFBsdWdpbjogUGx1Z2luQ29uZmlnID0ge1xyXG4gIG5hbWU6ICduYWptLWF1dGgnLFxyXG4gIHZlcnNpb246ICcwLjEuMycsXHJcblxyXG4gIC8qKlxyXG4gICAqIERhdGFiYXNlIGNvbmZpZ3VyYXRpb25cclxuICAgKiBCeSBkZWZhdWx0IHVzZXMgJ2F1dGgnIGRhdGFiYXNlLCBidXQgY2FuIGJlIGNoYW5nZWQgdG8gJ2RlZmF1bHQnXHJcbiAgICogVGhlIG1haW4gYXBwbGljYXRpb24gc2hvdWxkIHJlZ2lzdGVyIHRoaXMgZGF0YWJhc2UgaW4gRGF0YWJhc2VSZWdpc3RyeVxyXG4gICAqL1xyXG4gIGRhdGFiYXNlOiAnYXV0aCcsXHJcblxyXG4gIC8qKlxyXG4gICAqIEhUVFAgQ29udHJvbGxlcnNcclxuICAgKiBQcm92aWRlcyBSRVNUIEFQSSBlbmRwb2ludHMgZm9yIGF1dGhlbnRpY2F0aW9uIGFuZCBhdXRob3JpemF0aW9uXHJcbiAgICovXHJcbiAgY29udHJvbGxlcnM6IFtcclxuICAgIFVzZXJDb250cm9sbGVyLCAgICAgICAvLyAvdXNlcnMgLSBVc2VyIENSVUQgb3BlcmF0aW9uc1xyXG4gICAgQXV0aENvbnRyb2xsZXIsICAgICAgIC8vIC9hdXRoIC0gTG9naW4sIGxvZ291dCwgcmVnaXN0ZXIsIHZlcmlmeVxyXG4gICAgUm9sZUNvbnRyb2xsZXIsICAgICAgIC8vIC9yb2xlcyAtIFJvbGUgbWFuYWdlbWVudFxyXG4gICAgUGVybWlzc2lvbkNvbnRyb2xsZXIsIC8vIC9wZXJtaXNzaW9ucyAtIFBlcm1pc3Npb24gbWFuYWdlbWVudFxyXG4gIF0sXHJcblxyXG4gIC8qKlxyXG4gICAqIEJ1c2luZXNzIExvZ2ljIFNlcnZpY2VzXHJcbiAgICogQ29yZSBzZXJ2aWNlcyBmb3IgYXV0aGVudGljYXRpb24gYW5kIGF1dGhvcml6YXRpb25cclxuICAgKi9cclxuICBzZXJ2aWNlczogW1xyXG4gICAgVXNlclNlcnZpY2UsICAgICAgICAvLyBVc2VyIGJ1c2luZXNzIGxvZ2ljXHJcbiAgICBBdXRoU2VydmljZSwgICAgICAgIC8vIEF1dGhlbnRpY2F0aW9uIGxvZ2ljIChsb2dpbiwgcmVnaXN0ZXIsIHZlcmlmeSlcclxuICAgIENvb2tpZVNlcnZpY2UsICAgICAgLy8gQ29va2llIG1hbmFnZW1lbnQgZm9yIHNlc3Npb25zXHJcbiAgICBFbmNyeXB0aW9uU2VydmljZSwgIC8vIFBhc3N3b3JkIGhhc2hpbmcgYW5kIGVuY3J5cHRpb25cclxuICAgIFJvbGVTZXJ2aWNlLCAgICAgICAgLy8gUm9sZSBtYW5hZ2VtZW50IGxvZ2ljXHJcbiAgICBQZXJtaXNzaW9uU2VydmljZSwgIC8vIFBlcm1pc3Npb24gbWFuYWdlbWVudCBsb2dpY1xyXG4gICAgVG9rZW5TZXJ2aWNlLCAgICAgICAvLyBKV1QgdG9rZW4gZ2VuZXJhdGlvbiBhbmQgdmFsaWRhdGlvblxyXG4gIF0sXHJcblxyXG4gIC8qKlxyXG4gICAqIERhdGEgQWNjZXNzIFJlcG9zaXRvcmllc1xyXG4gICAqIERhdGFiYXNlIGFjY2VzcyBsYXllciBmb3IgZW50aXRpZXNcclxuICAgKi9cclxuICByZXBvc2l0b3JpZXM6IFtcclxuICAgIFVzZXJSZXBvc2l0b3J5LCAgICAgICAvLyBVc2VycyB0YWJsZSBhY2Nlc3NcclxuICAgIFJvbGVSZXBvc2l0b3J5LCAgICAgICAvLyBSb2xlcyB0YWJsZSBhY2Nlc3NcclxuICAgIFBlcm1pc3Npb25SZXBvc2l0b3J5LCAvLyBQZXJtaXNzaW9ucyB0YWJsZSBhY2Nlc3NcclxuICAgIFRva2VuUmVwb3NpdG9yeSwgICAgICAvLyBUb2tlbnMgdGFibGUgYWNjZXNzXHJcbiAgXSxcclxuXHJcbiAgLyoqXHJcbiAgICogQWRkaXRpb25hbCBQcm92aWRlcnNcclxuICAgKiBWYWxpZGF0b3JzIGFuZCBHdWFyZHMgZm9yIHJlcXVlc3QgdmFsaWRhdGlvbiBhbmQgcm91dGUgcHJvdGVjdGlvblxyXG4gICAqL1xyXG4gIHByb3ZpZGVyczogW1xyXG4gICAgVXNlclZhbGlkYXRvciwgICAgICAgLy8gVXNlciBkYXRhIHZhbGlkYXRpb25cclxuICAgIFJvbGVWYWxpZGF0b3IsICAgICAgIC8vIFJvbGUgZGF0YSB2YWxpZGF0aW9uXHJcbiAgICBQZXJtaXNzaW9uVmFsaWRhdG9yLCAvLyBQZXJtaXNzaW9uIGRhdGEgdmFsaWRhdGlvblxyXG4gICAgUm9sZUd1YXJkcywgICAgICAgICAgLy8gUm9sZS1iYXNlZCByb3V0ZSBndWFyZHNcclxuICAgIFBlcm1pc3Npb25HdWFyZHMsICAgIC8vIFBlcm1pc3Npb24tYmFzZWQgcm91dGUgZ3VhcmRzXHJcbiAgXSxcclxuXHJcbiAgLyoqXHJcbiAgICogU2V0dXAgaG9vayAtIGNhbGxlZCBhZnRlciBwbHVnaW4gcmVnaXN0cmF0aW9uXHJcbiAgICovXHJcbiAgb25TZXR1cDogYXN5bmMgKCkgPT4ge1xyXG4gICAgY29uc29sZS5sb2coJyAg4pyTIG5ham0tYXV0aCBwbHVnaW4gaW5pdGlhbGl6ZWQnKTtcclxuICAgIGNvbnNvbGUubG9nKCcgICAgLSBBdXRoZW50aWNhdGlvbiBlbmRwb2ludHMgcmVhZHknKTtcclxuICAgIGNvbnNvbGUubG9nKCcgICAgLSBBdXRob3JpemF0aW9uIHN5c3RlbSBhY3RpdmUnKTtcclxuICAgIGNvbnNvbGUubG9nKCcgICAgLSBEYXRhYmFzZSBjb25uZWN0aW9uIGVzdGFibGlzaGVkJyk7XHJcbiAgfSxcclxuXHJcbiAgLyoqXHJcbiAgICogVGVhcmRvd24gaG9vayAtIGNhbGxlZCBiZWZvcmUgcGx1Z2luIHJlbW92YWxcclxuICAgKi9cclxuICBvblRlYXJkb3duOiBhc3luYyAoKSA9PiB7XHJcbiAgICBjb25zb2xlLmxvZygnICDinJMgbmFqbS1hdXRoIHBsdWdpbiBjbGVhbnVwIGNvbXBsZXRlJyk7XHJcbiAgfSxcclxufTsiCiAgXSwKICAibWFwcGluZ3MiOiAiK2tCQUNBLHFCQUFTLGtCQUNULHVCQUdPLE1BQU0sQ0FBa0IsQ0FDN0IsV0FBVyxFQUFHLE9BRVIsYUFBWSxDQUFDLEVBQVUsQ0FDM0IsSUFBSyxFQUFVLE9BQU8sS0FDdEIsR0FBSSxPQUFPLElBQWEsVUFBWSxFQUFTLEtBQUssRUFBRSxTQUFXLEVBQzdELE9BQU8sS0FFVCxPQUFPLEdBQU8sS0FBSyxFQUFVLEVBQUUsT0FHM0IsZ0JB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LEdBQVcsRUFBRSxFQUN0RCxVQUFXLEdBQVUsYUFBYyxDQUFFLEtBQU0sUUFBUyxDQUFDLEtBQ2xELEVBQ0wsQ0FBQyxFQUVZLEdBQWMsR0FBUSxTQUFVLENBQzNDLEdBQUksR0FBUSxFQUFFLEVBQ2QsT0FBUSxFQUFLLFNBQVMsRUFBRSxXQUFXLElBQU0sR0FBVyxHQUFJLENBQUUsU0FBVSxTQUFVLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUNsRyxNQUFPLEVBQUssT0FBTyxFQUFFLFFBQVEsRUFDN0IsS0FBTSxHQUFjLE1BQU0sRUFBRSxRQUFRLFNBQVMsRUFDN0MsT0FBUSxHQUFnQixRQUFRLEVBQUUsUUFBUSxRQUFRLEVBQ2xELFVBQVcsR0FBVSxhQUFjLENBQUUsS0FBTSxRQUFTLENBQUMsRUFBRSxRQUFRLEtBQzVELEVBQ0wsQ0FBQyxFQUdZLEdBQW1CLEdBQVEsY0FBZSxDQUNyRCxHQUFJLEdBQVEsRUFDWixLQUFNLEVBQUssTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQ3BDLFlBQWEsRUFBSyxhQUFhLEVBQy9CLFNBQVUsRUFBSyxVQUFVLEVBQUUsUUFBUSxFQUNuQyxPQUFRLEVBQUssUUFBUSxFQUFFLFFBQVEsS0FDNUIsRUFDTCxDQUFDLEVBR1ksR0FBdUIsR0FBUSxtQkFBb0IsQ0FDOUQsR0FBSSxHQUFRLEVBQ1osT0FBUSxFQUFLLFNBQVMsRUFBRSxXQUFXLElBQU0sR0FBVyxFQUFFLEVBQUUsUUFBUSxFQUNoRSxhQUFjLEVBQUssZUFBZSxFQUFFLFdBQVcsSUFBTSxHQUFpQixFQUFFLEVBQUUsUUFBUSxLQUMvRSxFQUNMLENBQUMsRUR6Qk0sSUFBTSxHQUFxQixRQUFRLElBQUksT0FDMUMsR0FBUSxRQUFRLElBQUksT0FBUSxDQUFFLFNBQU8sQ0FBQyxFQUN0QyxLQUVKLEdBQThDLEdBQzVDLFFBQVEsS0FBSyx3RkFBdUYsRUdvQi9GLElBQU0sR0FBMkIsQ0FDdEMsS0FBTSxZQUNOLFFBQVMsUUFPVCxTQUFVLE9BTVYsWUFBYSxDQUNYLEdBQ0EsR0FDQSxHQUNBLEVBQ0YsRUFNQSxTQUFVLENBQ1IsRUFDQSxFQUNBLEVBQ0EsRUFDQSxFQUNBLEVBQ0EsQ0FDRixFQU1BLGFBQWMsQ0FDWixFQUNBLEVBQ0EsRUFDQSxDQUNGLEVBTUEsVUFBVyxDQUNULEVBQ0EsRUFDQSxFQUNBLEVBQ0EsRUFDRixFQUtBLFFBQVMsU0FBWSxDQUNuQixRQUFRLElBQUksa0NBQWlDLEVBQzdDLFFBQVEsSUFBSSxzQ0FBc0MsRUFDbEQsUUFBUSxJQUFJLG1DQUFtQyxFQUMvQyxRQUFRLElBQUksdUNBQXVDLEdBTXJELFdBQVksU0FBWSxDQUN0QixRQUFRLElBQUksdUNBQXNDLEVBRXREIiwKICAiZGVidWdJZCI6ICI0NjQ0MEQ3RjVFOUYzMDcyNjQ3NTZFMjE2NDc1NkUyMSIsCiAgIm5hbWVzIjogW10KfQ==
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
12
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
13
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
15
|
+
else
|
|
16
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
17
|
+
if (d = decorators[i])
|
|
18
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
20
|
+
};
|
|
21
|
+
var __legacyDecorateParamTS = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
22
|
+
var __legacyMetadataTS = (k, v) => {
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
|
24
|
+
return Reflect.metadata(k, v);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// src/auth/EncryptionService.ts
|
|
28
|
+
import { Injectable } from "najm-api";
|
|
29
|
+
import bcrypt from "bcrypt";
|
|
30
|
+
class EncryptionService {
|
|
31
|
+
constructor() {}
|
|
32
|
+
async hashPassword(password) {
|
|
33
|
+
if (!password)
|
|
34
|
+
return null;
|
|
35
|
+
if (typeof password !== "string" || password.trim().length === 0) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return bcrypt.hash(password, 10);
|
|
39
|
+
}
|
|
40
|
+
async comparePassword(password, hashedPassword) {
|
|
41
|
+
return bcrypt.compare(password, hashedPassword);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
EncryptionService = __legacyDecorateClassTS([
|
|
45
|
+
Injectable(),
|
|
46
|
+
__legacyMetadataTS("design:paramtypes", [])
|
|
47
|
+
], EncryptionService);
|
|
48
|
+
// src/auth/CookieService.ts
|
|
49
|
+
import { setCookie, Injectable as Injectable2, deleteCookie } from "najm-api";
|
|
50
|
+
import timestring from "timestring";
|
|
51
|
+
class CookieService {
|
|
52
|
+
setRefreshCookie(refreshToken) {
|
|
53
|
+
const maxAge = timestring(process.env.REFRESH_EXPIRES_IN, "s");
|
|
54
|
+
setCookie("refreshToken", refreshToken, {
|
|
55
|
+
httpOnly: false,
|
|
56
|
+
sameSite: "Lax",
|
|
57
|
+
maxAge,
|
|
58
|
+
path: "/api/auth/refresh"
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
clearRefreshCookie() {
|
|
62
|
+
deleteCookie("refreshToken", {
|
|
63
|
+
httpOnly: false,
|
|
64
|
+
sameSite: "Lax",
|
|
65
|
+
path: "/api/auth/refresh",
|
|
66
|
+
maxAge: 0
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
CookieService = __legacyDecorateClassTS([
|
|
71
|
+
Injectable2()
|
|
72
|
+
], CookieService);
|
|
73
|
+
// src/auth/AuthController.ts
|
|
74
|
+
import { Controller as Controller3, Get as Get3, Post as Post3, Params as Params3, Body as Body3, User as User2, t as t7 } from "najm-api";
|
|
75
|
+
|
|
76
|
+
// src/auth/AuthService.ts
|
|
77
|
+
import { t as t6 } from "najm-api";
|
|
78
|
+
import { Injectable as Injectable9, getCurrentLanguage as getCurrentLanguage2 } from "najm-api";
|
|
79
|
+
|
|
80
|
+
// src/users/UserRepository.ts
|
|
81
|
+
import { rolesTable, usersTable, permissionsTable, rolePermissionsTable } from "@/database/schema";
|
|
82
|
+
import { eq, ne } from "drizzle-orm";
|
|
83
|
+
import { Repository } from "najm-api";
|
|
84
|
+
class UserRepository {
|
|
85
|
+
getUser() {
|
|
86
|
+
return {
|
|
87
|
+
id: usersTable.id,
|
|
88
|
+
email: usersTable.email,
|
|
89
|
+
emailVerified: usersTable.emailVerified,
|
|
90
|
+
image: usersTable.image,
|
|
91
|
+
status: usersTable.status,
|
|
92
|
+
roleId: usersTable.roleId,
|
|
93
|
+
role: rolesTable.name,
|
|
94
|
+
createdAt: usersTable.createdAt,
|
|
95
|
+
updatedAt: usersTable.updatedAt
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async getAll() {
|
|
99
|
+
const allUsers = await this.db.select(this.getUser()).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id));
|
|
100
|
+
return Promise.all(allUsers.map(async (user) => ({
|
|
101
|
+
...user,
|
|
102
|
+
permissions: await this.getUserPermissions(user.id)
|
|
103
|
+
})));
|
|
104
|
+
}
|
|
105
|
+
async getById(id) {
|
|
106
|
+
const [user] = await this.db.select(this.getUser()).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id)).where(eq(usersTable.id, id)).limit(1);
|
|
107
|
+
if (!user)
|
|
108
|
+
return user;
|
|
109
|
+
return {
|
|
110
|
+
...user,
|
|
111
|
+
permissions: await this.getUserPermissions(user.id)
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async getByEmail(email) {
|
|
115
|
+
const [existingUser] = await this.db.select(this.getUser()).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id)).where(eq(usersTable.email, email));
|
|
116
|
+
return existingUser;
|
|
117
|
+
}
|
|
118
|
+
async create(data) {
|
|
119
|
+
const [newUser] = await this.db.insert(usersTable).values(data).returning();
|
|
120
|
+
return newUser;
|
|
121
|
+
}
|
|
122
|
+
async update(id, data) {
|
|
123
|
+
const [updatedUser] = await this.db.update(usersTable).set(data).where(eq(usersTable.id, id)).returning();
|
|
124
|
+
return updatedUser;
|
|
125
|
+
}
|
|
126
|
+
async delete(id) {
|
|
127
|
+
const [deletedUser] = await this.db.delete(usersTable).where(eq(usersTable.id, id)).returning();
|
|
128
|
+
return deletedUser;
|
|
129
|
+
}
|
|
130
|
+
async deleteAll() {
|
|
131
|
+
const adminRole = await this.db.select({ id: rolesTable.id }).from(rolesTable).where(eq(rolesTable.name, "admin")).limit(1);
|
|
132
|
+
if (adminRole.length === 0) {
|
|
133
|
+
const deletedUsers2 = await this.db.delete(usersTable).returning();
|
|
134
|
+
return deletedUsers2;
|
|
135
|
+
}
|
|
136
|
+
const deletedUsers = await this.db.delete(usersTable).where(ne(usersTable.roleId, adminRole[0].id)).returning();
|
|
137
|
+
return deletedUsers;
|
|
138
|
+
}
|
|
139
|
+
async getRoleNameById(userId) {
|
|
140
|
+
const [role] = await this.db.select({
|
|
141
|
+
roleName: rolesTable.name
|
|
142
|
+
}).from(usersTable).leftJoin(rolesTable, eq(usersTable.roleId, rolesTable.id)).where(eq(usersTable.id, userId));
|
|
143
|
+
return role.roleName;
|
|
144
|
+
}
|
|
145
|
+
async getUserPassword(email) {
|
|
146
|
+
const [user] = await this.db.select({
|
|
147
|
+
id: usersTable.id,
|
|
148
|
+
email: usersTable.email,
|
|
149
|
+
password: usersTable.password
|
|
150
|
+
}).from(usersTable).where(eq(usersTable.email, email)).limit(1);
|
|
151
|
+
return user.password;
|
|
152
|
+
}
|
|
153
|
+
async getUserPermissions(userId) {
|
|
154
|
+
const [user] = await this.db.select({ roleId: usersTable.roleId }).from(usersTable).where(eq(usersTable.id, userId)).limit(1);
|
|
155
|
+
if (!user || !user.roleId)
|
|
156
|
+
return [];
|
|
157
|
+
const userPermissions = await this.db.select({
|
|
158
|
+
name: permissionsTable.name
|
|
159
|
+
}).from(rolePermissionsTable).leftJoin(permissionsTable, eq(rolePermissionsTable.permissionId, permissionsTable.id)).where(eq(rolePermissionsTable.roleId, user.roleId));
|
|
160
|
+
return userPermissions.map((p) => p.name).filter((name) => name);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
UserRepository = __legacyDecorateClassTS([
|
|
164
|
+
Repository()
|
|
165
|
+
], UserRepository);
|
|
166
|
+
// src/users/UserValidator.ts
|
|
167
|
+
import { Injectable as Injectable3, t } from "najm-api";
|
|
168
|
+
import { parseSchema } from "@/shared";
|
|
169
|
+
import { userSchema } from "@/lib/validations";
|
|
170
|
+
class UserValidator {
|
|
171
|
+
userRepository;
|
|
172
|
+
encryptionService;
|
|
173
|
+
constructor(userRepository, encryptionService) {
|
|
174
|
+
this.userRepository = userRepository;
|
|
175
|
+
this.encryptionService = encryptionService;
|
|
176
|
+
}
|
|
177
|
+
async validateCreateUser(data) {
|
|
178
|
+
return parseSchema(userSchema, data);
|
|
179
|
+
}
|
|
180
|
+
async isEmailExists(email) {
|
|
181
|
+
const existingUser = await this.userRepository.getByEmail(email);
|
|
182
|
+
return !!existingUser;
|
|
183
|
+
}
|
|
184
|
+
async isPasswordValid(password, hashedPassword) {
|
|
185
|
+
const isPasswordValid = await this.encryptionService.comparePassword(password, hashedPassword);
|
|
186
|
+
return !!isPasswordValid;
|
|
187
|
+
}
|
|
188
|
+
async isUserExist(id) {
|
|
189
|
+
const existingUser = await this.userRepository.getById(id);
|
|
190
|
+
return !!existingUser;
|
|
191
|
+
}
|
|
192
|
+
async checkUserIdIsUnique(id) {
|
|
193
|
+
if (!id)
|
|
194
|
+
return;
|
|
195
|
+
const existingUser = await this.userRepository.getById(id);
|
|
196
|
+
if (existingUser) {
|
|
197
|
+
throw new Error(t("users.errors.idExists"));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async isCorrectPass(password) {
|
|
201
|
+
return password && typeof password === "string" && password.trim().length > 0;
|
|
202
|
+
}
|
|
203
|
+
async hasRole(userId, roles) {
|
|
204
|
+
const roleName = await this.userRepository.getRoleNameById(userId);
|
|
205
|
+
if (!roleName) {
|
|
206
|
+
throw Error(t("auth.errors.accessDenied"));
|
|
207
|
+
}
|
|
208
|
+
const hasRole = roles.some((item) => roleName.toLowerCase() === item.toLowerCase());
|
|
209
|
+
if (!hasRole) {
|
|
210
|
+
throw Error(t("auth.errors.accessDenied"));
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
async checkUserExistsByEmail(email) {
|
|
215
|
+
const user = await this.userRepository.getByEmail(email);
|
|
216
|
+
if (!user) {
|
|
217
|
+
throw new Error(t("auth.errors.invalidCredentials"));
|
|
218
|
+
}
|
|
219
|
+
return user;
|
|
220
|
+
}
|
|
221
|
+
async checkUserExists(id) {
|
|
222
|
+
const userExists = await this.isUserExist(id);
|
|
223
|
+
if (!userExists) {
|
|
224
|
+
throw new Error(t("users.errors.notFound"));
|
|
225
|
+
}
|
|
226
|
+
return userExists;
|
|
227
|
+
}
|
|
228
|
+
async checkEmailUnique(email, excludeId = null) {
|
|
229
|
+
if (!email)
|
|
230
|
+
return;
|
|
231
|
+
const existingUser = await this.userRepository.getByEmail(email);
|
|
232
|
+
if (existingUser && existingUser.id !== excludeId) {
|
|
233
|
+
throw new Error(t("auth.errors.emailExists"));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async checkEmailExists(email) {
|
|
237
|
+
const user = await this.userRepository.getByEmail(email);
|
|
238
|
+
if (!user) {
|
|
239
|
+
throw new Error(t("users.errors.notFound"));
|
|
240
|
+
}
|
|
241
|
+
return user;
|
|
242
|
+
}
|
|
243
|
+
async checkPasswordValid(password, hashedPassword) {
|
|
244
|
+
const isPasswordValid = await this.isPasswordValid(password, hashedPassword);
|
|
245
|
+
if (!isPasswordValid) {
|
|
246
|
+
throw new Error(t("auth.errors.invalidCredentials"));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
UserValidator = __legacyDecorateClassTS([
|
|
251
|
+
Injectable3(),
|
|
252
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
253
|
+
typeof UserRepository === "undefined" ? Object : UserRepository,
|
|
254
|
+
typeof EncryptionService === "undefined" ? Object : EncryptionService
|
|
255
|
+
])
|
|
256
|
+
], UserValidator);
|
|
257
|
+
// src/users/UserService.ts
|
|
258
|
+
import { Injectable as Injectable8, setLanguage, getCurrentLanguage, Transactional } from "najm-api";
|
|
259
|
+
|
|
260
|
+
// src/roles/RoleRepository.ts
|
|
261
|
+
import { rolesTable as rolesTable2 } from "@/database/schema";
|
|
262
|
+
import { eq as eq2 } from "drizzle-orm";
|
|
263
|
+
import { Repository as Repository2 } from "najm-api";
|
|
264
|
+
class RoleRepository {
|
|
265
|
+
async getAll() {
|
|
266
|
+
return await this.db.select().from(rolesTable2);
|
|
267
|
+
}
|
|
268
|
+
async getById(id) {
|
|
269
|
+
const [existingRole] = await this.db.select().from(rolesTable2).where(eq2(rolesTable2.id, id));
|
|
270
|
+
return existingRole;
|
|
271
|
+
}
|
|
272
|
+
async getByName(name) {
|
|
273
|
+
const [existingRole] = await this.db.select().from(rolesTable2).where(eq2(rolesTable2.name, name));
|
|
274
|
+
return existingRole;
|
|
275
|
+
}
|
|
276
|
+
async create(data) {
|
|
277
|
+
const [newRole] = await this.db.insert(rolesTable2).values(data).returning();
|
|
278
|
+
return newRole;
|
|
279
|
+
}
|
|
280
|
+
async update(id, data) {
|
|
281
|
+
const [updatedRole] = await this.db.update(rolesTable2).set(data).where(eq2(rolesTable2.id, id)).returning();
|
|
282
|
+
return updatedRole;
|
|
283
|
+
}
|
|
284
|
+
async delete(id) {
|
|
285
|
+
const [deletedRole] = await this.db.delete(rolesTable2).where(eq2(rolesTable2.id, id)).returning();
|
|
286
|
+
return deletedRole;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
RoleRepository = __legacyDecorateClassTS([
|
|
290
|
+
Repository2()
|
|
291
|
+
], RoleRepository);
|
|
292
|
+
// src/roles/RoleValidator.ts
|
|
293
|
+
import { Injectable as Injectable4, t as t2 } from "najm-api";
|
|
294
|
+
import { parseSchema as parseSchema2 } from "@/shared";
|
|
295
|
+
import { roleSchema } from "@/lib/validations";
|
|
296
|
+
class RoleValidator {
|
|
297
|
+
roleRepository;
|
|
298
|
+
constructor(roleRepository) {
|
|
299
|
+
this.roleRepository = roleRepository;
|
|
300
|
+
}
|
|
301
|
+
async validateCreateRole(data) {
|
|
302
|
+
return parseSchema2(roleSchema, data);
|
|
303
|
+
}
|
|
304
|
+
async isRoleNameExists(roleName) {
|
|
305
|
+
const existingRole = await this.roleRepository.getByName(roleName);
|
|
306
|
+
return !!existingRole;
|
|
307
|
+
}
|
|
308
|
+
async isRoleIdExists(id) {
|
|
309
|
+
const existingRole = await this.roleRepository.getById(id);
|
|
310
|
+
return !!existingRole;
|
|
311
|
+
}
|
|
312
|
+
async checkNameUnique(roleName, excludeId = null) {
|
|
313
|
+
if (!roleName)
|
|
314
|
+
return;
|
|
315
|
+
const existingRole = await this.roleRepository.getByName(roleName);
|
|
316
|
+
if (existingRole && existingRole.id !== excludeId) {
|
|
317
|
+
throw new Error(t2("roles.errors.exists"));
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async checkRoleExists(id) {
|
|
321
|
+
const roleIdExists = await this.isRoleIdExists(id);
|
|
322
|
+
if (!roleIdExists) {
|
|
323
|
+
throw new Error(t2("roles.errors.notFound"));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async checkRoleExistsByName(roleName) {
|
|
327
|
+
const roleNameExists = await this.isRoleNameExists(roleName);
|
|
328
|
+
if (!roleNameExists) {
|
|
329
|
+
throw new Error(t2("roles.errors.notFound"));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async checkAdminRoleExists() {
|
|
333
|
+
const adminRole = await this.roleRepository.getByName("admin");
|
|
334
|
+
if (!adminRole) {
|
|
335
|
+
throw new Error(t2("users.errors.adminRoleNotFound"));
|
|
336
|
+
}
|
|
337
|
+
return adminRole;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
RoleValidator = __legacyDecorateClassTS([
|
|
341
|
+
Injectable4(),
|
|
342
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
343
|
+
typeof RoleRepository === "undefined" ? Object : RoleRepository
|
|
344
|
+
])
|
|
345
|
+
], RoleValidator);
|
|
346
|
+
// src/roles/RoleGuards.ts
|
|
347
|
+
import { Injectable as Injectable6, Headers as Headers2, createGuard, GuardParams, Ctx as Ctx2 } from "najm-api";
|
|
348
|
+
|
|
349
|
+
// src/tokens/TokenRepository.ts
|
|
350
|
+
import { tokensTable, usersTable as usersTable2, rolesTable as rolesTable3, permissionsTable as permissionsTable2, rolePermissionsTable as rolePermissionsTable2 } from "@/database/schema";
|
|
351
|
+
import { eq as eq3 } from "drizzle-orm";
|
|
352
|
+
import { Repository as Repository3 } from "najm-api";
|
|
353
|
+
class TokenRepository {
|
|
354
|
+
async storeRefreshToken(tokenData) {
|
|
355
|
+
return await this.db.insert(tokensTable).values(tokenData).onConflictDoUpdate({
|
|
356
|
+
target: tokensTable.userId,
|
|
357
|
+
set: {
|
|
358
|
+
token: tokenData.token,
|
|
359
|
+
expiresAt: tokenData.expiresAt
|
|
360
|
+
}
|
|
361
|
+
}).returning();
|
|
362
|
+
}
|
|
363
|
+
async getRefreshToken(userId) {
|
|
364
|
+
const [token] = await this.db.select().from(tokensTable).where(eq3(tokensTable.userId, userId));
|
|
365
|
+
return token?.token;
|
|
366
|
+
}
|
|
367
|
+
async revokeToken(userId) {
|
|
368
|
+
const [deletedToken] = await this.db.delete(tokensTable).where(eq3(tokensTable.userId, userId)).returning();
|
|
369
|
+
return deletedToken;
|
|
370
|
+
}
|
|
371
|
+
async isUserExists(userId) {
|
|
372
|
+
const [user] = await this.db.select({ id: usersTable2.id }).from(usersTable2).where(eq3(usersTable2.id, userId)).limit(1);
|
|
373
|
+
return !!user;
|
|
374
|
+
}
|
|
375
|
+
async getRoleNameById(userId) {
|
|
376
|
+
const [role] = await this.db.select({
|
|
377
|
+
roleName: rolesTable3.name
|
|
378
|
+
}).from(usersTable2).leftJoin(rolesTable3, eq3(usersTable2.roleId, rolesTable3.id)).where(eq3(usersTable2.id, userId)).limit(1);
|
|
379
|
+
return role?.roleName;
|
|
380
|
+
}
|
|
381
|
+
async getUserPermissions(userId) {
|
|
382
|
+
const [user] = await this.db.select({ roleId: usersTable2.roleId }).from(usersTable2).where(eq3(usersTable2.id, userId)).limit(1);
|
|
383
|
+
if (!user || !user.roleId)
|
|
384
|
+
return [];
|
|
385
|
+
const userPermissions = await this.db.select({
|
|
386
|
+
name: permissionsTable2.name
|
|
387
|
+
}).from(rolePermissionsTable2).leftJoin(permissionsTable2, eq3(rolePermissionsTable2.permissionId, permissionsTable2.id)).where(eq3(rolePermissionsTable2.roleId, user.roleId));
|
|
388
|
+
return userPermissions.map((p) => p.name).filter((name) => name);
|
|
389
|
+
}
|
|
390
|
+
async getUser(userId) {
|
|
391
|
+
const [user] = await this.db.select({
|
|
392
|
+
id: usersTable2.id,
|
|
393
|
+
email: usersTable2.email,
|
|
394
|
+
status: usersTable2.status,
|
|
395
|
+
roleId: usersTable2.roleId,
|
|
396
|
+
roleName: rolesTable3.name,
|
|
397
|
+
createdAt: usersTable2.createdAt,
|
|
398
|
+
updatedAt: usersTable2.updatedAt
|
|
399
|
+
}).from(usersTable2).leftJoin(rolesTable3, eq3(usersTable2.roleId, rolesTable3.id)).where(eq3(usersTable2.id, userId)).limit(1);
|
|
400
|
+
return user ? { ...user, role: user.roleName } : null;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
TokenRepository = __legacyDecorateClassTS([
|
|
404
|
+
Repository3()
|
|
405
|
+
], TokenRepository);
|
|
406
|
+
// src/tokens/TokenService.ts
|
|
407
|
+
import { t as t3 } from "najm-api";
|
|
408
|
+
import { getCookie, Injectable as Injectable5 } from "najm-api";
|
|
409
|
+
import jwt from "jsonwebtoken";
|
|
410
|
+
import { jwtDecode } from "jwt-decode";
|
|
411
|
+
import timestring2 from "timestring";
|
|
412
|
+
class TokenService {
|
|
413
|
+
tokenRepository;
|
|
414
|
+
accessSecretKey = process.env.JWT_ACCESS_SECRET;
|
|
415
|
+
accessExpiresIn = process.env.ACCESS_EXPIRES_IN;
|
|
416
|
+
refreshSecretKey = process.env.JWT_REFRESH_SECRET;
|
|
417
|
+
refreshExpiresIn = process.env.REFRESH_EXPIRES_IN;
|
|
418
|
+
constructor(tokenRepository) {
|
|
419
|
+
this.tokenRepository = tokenRepository;
|
|
420
|
+
}
|
|
421
|
+
extractAccessToken(authorization) {
|
|
422
|
+
if (authorization && authorization.startsWith("Bearer")) {
|
|
423
|
+
return authorization.split(" ")[1];
|
|
424
|
+
}
|
|
425
|
+
throw new Error(t3("auth.errors.tokenMissing"));
|
|
426
|
+
}
|
|
427
|
+
verifyAccessToken(token) {
|
|
428
|
+
try {
|
|
429
|
+
return jwt.verify(token, this.accessSecretKey);
|
|
430
|
+
} catch (error) {
|
|
431
|
+
throw new Error(t3("auth.errors.tokenVerificationFailed"));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
verifyRefreshToken(token) {
|
|
435
|
+
try {
|
|
436
|
+
const decoded = jwt.verify(token, this.refreshSecretKey);
|
|
437
|
+
return decoded.userId;
|
|
438
|
+
} catch (error) {
|
|
439
|
+
throw new Error(t3("auth.errors.tokenVerificationFailed"));
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
async getUserIdByAccessToken(header) {
|
|
443
|
+
const token = this.extractAccessToken(header);
|
|
444
|
+
const decodedToken = this.verifyAccessToken(token);
|
|
445
|
+
const userId = decodedToken.userId;
|
|
446
|
+
const userExists = await this.tokenRepository.isUserExists(userId);
|
|
447
|
+
if (!userExists) {
|
|
448
|
+
throw new Error(t3("users.errors.notFound"));
|
|
449
|
+
}
|
|
450
|
+
return userId;
|
|
451
|
+
}
|
|
452
|
+
async storeRefreshToken(userId, refreshToken) {
|
|
453
|
+
const expireInSecond = timestring2(this.refreshExpiresIn, "s");
|
|
454
|
+
const tokenData = {
|
|
455
|
+
userId,
|
|
456
|
+
token: refreshToken,
|
|
457
|
+
expiresAt: new Date(Date.now() + expireInSecond * 1000).toISOString()
|
|
458
|
+
};
|
|
459
|
+
await this.tokenRepository.storeRefreshToken(tokenData);
|
|
460
|
+
}
|
|
461
|
+
getTokenExpire(token) {
|
|
462
|
+
return jwtDecode(token).exp;
|
|
463
|
+
}
|
|
464
|
+
generateAccessToken(data) {
|
|
465
|
+
const options = { expiresIn: this.accessExpiresIn };
|
|
466
|
+
return jwt.sign(data, this.accessSecretKey, options);
|
|
467
|
+
}
|
|
468
|
+
generateRefreshToken(data) {
|
|
469
|
+
const options = { expiresIn: this.refreshExpiresIn };
|
|
470
|
+
return jwt.sign(data, this.refreshSecretKey, options);
|
|
471
|
+
}
|
|
472
|
+
async generateTokens(userId) {
|
|
473
|
+
const tokenData = { userId };
|
|
474
|
+
const accessToken = await this.generateAccessToken(tokenData);
|
|
475
|
+
const refreshToken = await this.generateRefreshToken(tokenData);
|
|
476
|
+
const accessTokenExpiresAt = this.getTokenExpire(accessToken);
|
|
477
|
+
const refreshTokenExpiresAt = this.getTokenExpire(refreshToken);
|
|
478
|
+
await this.storeRefreshToken(userId, refreshToken);
|
|
479
|
+
return {
|
|
480
|
+
accessToken,
|
|
481
|
+
refreshToken,
|
|
482
|
+
accessTokenExpiresAt,
|
|
483
|
+
refreshTokenExpiresAt
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
async refreshTokens() {
|
|
487
|
+
const newRefreshToken = getCookie("refreshToken");
|
|
488
|
+
const userId = this.verifyRefreshToken(newRefreshToken);
|
|
489
|
+
const userExists = await this.tokenRepository.isUserExists(userId);
|
|
490
|
+
if (!userExists) {
|
|
491
|
+
throw new Error(t3("users.errors.notFound"));
|
|
492
|
+
}
|
|
493
|
+
const storedRefreshToken = await this.tokenRepository.getRefreshToken(userId);
|
|
494
|
+
if (newRefreshToken != storedRefreshToken) {
|
|
495
|
+
throw new Error(t3("auth.errors.refreshTokenInvalid"));
|
|
496
|
+
}
|
|
497
|
+
return await this.generateTokens(userId);
|
|
498
|
+
}
|
|
499
|
+
async revokeToken(userId) {
|
|
500
|
+
return await this.tokenRepository.revokeToken(userId);
|
|
501
|
+
}
|
|
502
|
+
async getUserPermissions(auth) {
|
|
503
|
+
if (!auth)
|
|
504
|
+
return;
|
|
505
|
+
const userId = await this.getUserIdByAccessToken(auth);
|
|
506
|
+
const permissions = await this.tokenRepository.getUserPermissions(userId);
|
|
507
|
+
return permissions;
|
|
508
|
+
}
|
|
509
|
+
async getUserRole(auth) {
|
|
510
|
+
if (!auth)
|
|
511
|
+
return;
|
|
512
|
+
const userId = await this.getUserIdByAccessToken(auth);
|
|
513
|
+
const roleName = await this.tokenRepository.getRoleNameById(userId);
|
|
514
|
+
return roleName;
|
|
515
|
+
}
|
|
516
|
+
async getUser(auth) {
|
|
517
|
+
if (!auth)
|
|
518
|
+
return;
|
|
519
|
+
const userId = await this.getUserIdByAccessToken(auth);
|
|
520
|
+
const user = await this.tokenRepository.getUser(userId);
|
|
521
|
+
if (!user)
|
|
522
|
+
return null;
|
|
523
|
+
return user;
|
|
524
|
+
}
|
|
525
|
+
async storeUserInCache(auth, ctx) {
|
|
526
|
+
const cachedUser = ctx.get("user");
|
|
527
|
+
if (cachedUser)
|
|
528
|
+
return cachedUser;
|
|
529
|
+
const user = await this.getUser(auth);
|
|
530
|
+
if (user) {
|
|
531
|
+
ctx.set("user", user);
|
|
532
|
+
}
|
|
533
|
+
return user;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
TokenService = __legacyDecorateClassTS([
|
|
537
|
+
Injectable5(),
|
|
538
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
539
|
+
typeof TokenRepository === "undefined" ? Object : TokenRepository
|
|
540
|
+
])
|
|
541
|
+
], TokenService);
|
|
542
|
+
// src/roles/RoleGuards.ts
|
|
543
|
+
var ROLES = {
|
|
544
|
+
ADMIN: "admin",
|
|
545
|
+
PRINCIPAL: "principal",
|
|
546
|
+
ACCOUNTING: "accounting",
|
|
547
|
+
SECRETARY: "secretary",
|
|
548
|
+
TEACHER: "teacher",
|
|
549
|
+
STUDENT: "student",
|
|
550
|
+
PARENT: "parent"
|
|
551
|
+
};
|
|
552
|
+
var ROLE_GROUPS = {
|
|
553
|
+
ADMINISTRATORS: [ROLES.ADMIN, ROLES.PRINCIPAL],
|
|
554
|
+
FINANCIAL: [ROLES.ADMIN, ROLES.ACCOUNTING],
|
|
555
|
+
STAFF: [ROLES.ADMIN, ROLES.PRINCIPAL, ROLES.ACCOUNTING, ROLES.SECRETARY, ROLES.TEACHER],
|
|
556
|
+
END_USERS: [ROLES.STUDENT, ROLES.PARENT],
|
|
557
|
+
ALL: [ROLES.ADMIN, ROLES.PRINCIPAL, ROLES.ACCOUNTING, ROLES.SECRETARY, ROLES.TEACHER, ROLES.STUDENT, ROLES.PARENT]
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
class RoleChecker {
|
|
561
|
+
isInGroup(userRole, group) {
|
|
562
|
+
return group.includes(userRole?.toLowerCase());
|
|
563
|
+
}
|
|
564
|
+
isAdministrator(userRole) {
|
|
565
|
+
return this.isInGroup(userRole, ROLE_GROUPS.ADMINISTRATORS);
|
|
566
|
+
}
|
|
567
|
+
isStaff(userRole) {
|
|
568
|
+
return this.isInGroup(userRole, ROLE_GROUPS.STAFF);
|
|
569
|
+
}
|
|
570
|
+
hasAnyRole(userRole, roles) {
|
|
571
|
+
return roles.includes(userRole?.toLowerCase());
|
|
572
|
+
}
|
|
573
|
+
hasExactRole(userRole, requiredRole) {
|
|
574
|
+
return userRole?.toLowerCase() === requiredRole?.toLowerCase();
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
RoleChecker = __legacyDecorateClassTS([
|
|
578
|
+
Injectable6()
|
|
579
|
+
], RoleChecker);
|
|
580
|
+
|
|
581
|
+
class RoleGuards {
|
|
582
|
+
roleChecker;
|
|
583
|
+
tokenService;
|
|
584
|
+
constructor(roleChecker, tokenService) {
|
|
585
|
+
this.roleChecker = roleChecker;
|
|
586
|
+
this.tokenService = tokenService;
|
|
587
|
+
}
|
|
588
|
+
async isAuth(auth, ctx) {
|
|
589
|
+
const user = await this.tokenService.storeUserInCache(auth, ctx);
|
|
590
|
+
return !!user;
|
|
591
|
+
}
|
|
592
|
+
async hasRoles(auth, ctx, roles) {
|
|
593
|
+
try {
|
|
594
|
+
const user = await this.tokenService.storeUserInCache(auth, ctx);
|
|
595
|
+
if (!user?.role)
|
|
596
|
+
return false;
|
|
597
|
+
const roleArray = Array.isArray(roles) ? roles : [roles];
|
|
598
|
+
return this.roleChecker.hasAnyRole(user.role, roleArray);
|
|
599
|
+
} catch {
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
__legacyDecorateClassTS([
|
|
605
|
+
__legacyDecorateParamTS(0, Headers2("authorization")),
|
|
606
|
+
__legacyDecorateParamTS(1, Ctx2()),
|
|
607
|
+
__legacyMetadataTS("design:type", Function),
|
|
608
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
609
|
+
Object,
|
|
610
|
+
Object
|
|
611
|
+
]),
|
|
612
|
+
__legacyMetadataTS("design:returntype", Object)
|
|
613
|
+
], RoleGuards.prototype, "isAuth", null);
|
|
614
|
+
__legacyDecorateClassTS([
|
|
615
|
+
__legacyDecorateParamTS(0, Headers2("authorization")),
|
|
616
|
+
__legacyDecorateParamTS(1, Ctx2()),
|
|
617
|
+
__legacyDecorateParamTS(2, GuardParams()),
|
|
618
|
+
__legacyMetadataTS("design:type", Function),
|
|
619
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
620
|
+
Object,
|
|
621
|
+
Object,
|
|
622
|
+
Object
|
|
623
|
+
]),
|
|
624
|
+
__legacyMetadataTS("design:returntype", Object)
|
|
625
|
+
], RoleGuards.prototype, "hasRoles", null);
|
|
626
|
+
RoleGuards = __legacyDecorateClassTS([
|
|
627
|
+
Injectable6(),
|
|
628
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
629
|
+
typeof RoleChecker === "undefined" ? Object : RoleChecker,
|
|
630
|
+
typeof TokenService === "undefined" ? Object : TokenService
|
|
631
|
+
])
|
|
632
|
+
], RoleGuards);
|
|
633
|
+
var isAdmin = () => Role("admin");
|
|
634
|
+
var isPrincipal = () => Role("principal");
|
|
635
|
+
var isAccounting = () => Role("accounting");
|
|
636
|
+
var isSecretary = () => Role("secretary");
|
|
637
|
+
var isTeacher = () => Role("teacher");
|
|
638
|
+
var isParent = () => Role("parent");
|
|
639
|
+
var isStudent = () => Role("student");
|
|
640
|
+
var isAdministrator = () => Role("admin", "principal");
|
|
641
|
+
var isFinancial = () => Role("admin", "accounting");
|
|
642
|
+
var isStaff = () => Role("admin", "principal", "accounting", "secretary", "teacher");
|
|
643
|
+
var isAuth = createGuard(RoleGuards, "isAuth");
|
|
644
|
+
var Role = (...roles) => createGuard(RoleGuards, "hasRoles")(...roles);
|
|
645
|
+
// src/roles/RoleController.ts
|
|
646
|
+
import { Controller, Get, Post, Put, Delete, Params, Body, t as t4 } from "najm-api";
|
|
647
|
+
|
|
648
|
+
// src/roles/RoleService.ts
|
|
649
|
+
import { Injectable as Injectable7 } from "najm-api";
|
|
650
|
+
class RoleService {
|
|
651
|
+
roleRepository;
|
|
652
|
+
roleValidator;
|
|
653
|
+
constructor(roleRepository, roleValidator) {
|
|
654
|
+
this.roleRepository = roleRepository;
|
|
655
|
+
this.roleValidator = roleValidator;
|
|
656
|
+
}
|
|
657
|
+
async getAll() {
|
|
658
|
+
return await this.roleRepository.getAll();
|
|
659
|
+
}
|
|
660
|
+
async getById(id) {
|
|
661
|
+
await this.roleValidator.checkRoleExists(id);
|
|
662
|
+
return await this.roleRepository.getById(id);
|
|
663
|
+
}
|
|
664
|
+
async getByName(name) {
|
|
665
|
+
return await this.roleRepository.getByName(name);
|
|
666
|
+
}
|
|
667
|
+
async create(data) {
|
|
668
|
+
await this.roleValidator.validateCreateRole(data);
|
|
669
|
+
await this.roleValidator.checkNameUnique(data.name);
|
|
670
|
+
return await this.roleRepository.create(data);
|
|
671
|
+
}
|
|
672
|
+
async update(id, data) {
|
|
673
|
+
await this.roleValidator.checkRoleExists(id);
|
|
674
|
+
await this.roleValidator.checkNameUnique(data.name, id);
|
|
675
|
+
return await this.roleRepository.update(id, data);
|
|
676
|
+
}
|
|
677
|
+
async delete(id) {
|
|
678
|
+
await this.roleValidator.checkRoleExists(id);
|
|
679
|
+
return await this.roleRepository.delete(id);
|
|
680
|
+
}
|
|
681
|
+
async seedDefaultRoles(defaultRoles) {
|
|
682
|
+
const rolesToCreate = [];
|
|
683
|
+
for (const role of defaultRoles) {
|
|
684
|
+
const exists = await this.roleValidator.isRoleNameExists(role.name);
|
|
685
|
+
if (!exists) {
|
|
686
|
+
rolesToCreate.push(role);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
const createdRoles = await Promise.all(rolesToCreate.map((role) => this.roleRepository.create(role)));
|
|
690
|
+
return createdRoles;
|
|
691
|
+
}
|
|
692
|
+
async getRoleIdByName(name) {
|
|
693
|
+
const teacherRole = await this.getByName(name);
|
|
694
|
+
return teacherRole?.id;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
RoleService = __legacyDecorateClassTS([
|
|
698
|
+
Injectable7(),
|
|
699
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
700
|
+
typeof RoleRepository === "undefined" ? Object : RoleRepository,
|
|
701
|
+
typeof RoleValidator === "undefined" ? Object : RoleValidator
|
|
702
|
+
])
|
|
703
|
+
], RoleService);
|
|
704
|
+
|
|
705
|
+
// src/roles/RoleController.ts
|
|
706
|
+
class RoleController {
|
|
707
|
+
roleService;
|
|
708
|
+
constructor(roleService) {
|
|
709
|
+
this.roleService = roleService;
|
|
710
|
+
}
|
|
711
|
+
async getRoles() {
|
|
712
|
+
const roles = await this.roleService.getAll();
|
|
713
|
+
return {
|
|
714
|
+
data: roles,
|
|
715
|
+
message: t4("roles.success.retrieved"),
|
|
716
|
+
status: "success"
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
async getRole(id) {
|
|
720
|
+
const role = await this.roleService.getById(id);
|
|
721
|
+
return {
|
|
722
|
+
data: role,
|
|
723
|
+
message: t4("roles.success.retrieved"),
|
|
724
|
+
status: "success"
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
async createRole(body) {
|
|
728
|
+
const newRole = await this.roleService.create(body);
|
|
729
|
+
return {
|
|
730
|
+
data: newRole,
|
|
731
|
+
message: t4("roles.success.created"),
|
|
732
|
+
status: "success"
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
async updateRole(id, body) {
|
|
736
|
+
const updatedRole = await this.roleService.update(id, body);
|
|
737
|
+
return {
|
|
738
|
+
data: updatedRole,
|
|
739
|
+
message: t4("roles.success.updated"),
|
|
740
|
+
status: "success"
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
async deleteRole(id) {
|
|
744
|
+
const result = await this.roleService.delete(id);
|
|
745
|
+
return {
|
|
746
|
+
data: result,
|
|
747
|
+
message: t4("roles.success.deleted"),
|
|
748
|
+
status: "success"
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
__legacyDecorateClassTS([
|
|
753
|
+
Get(),
|
|
754
|
+
isAdmin(),
|
|
755
|
+
__legacyMetadataTS("design:type", Function),
|
|
756
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
757
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
758
|
+
], RoleController.prototype, "getRoles", null);
|
|
759
|
+
__legacyDecorateClassTS([
|
|
760
|
+
Get("/:id"),
|
|
761
|
+
isAdmin(),
|
|
762
|
+
__legacyDecorateParamTS(0, Params("id")),
|
|
763
|
+
__legacyMetadataTS("design:type", Function),
|
|
764
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
765
|
+
Object
|
|
766
|
+
]),
|
|
767
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
768
|
+
], RoleController.prototype, "getRole", null);
|
|
769
|
+
__legacyDecorateClassTS([
|
|
770
|
+
Post(),
|
|
771
|
+
isAdmin(),
|
|
772
|
+
__legacyDecorateParamTS(0, Body()),
|
|
773
|
+
__legacyMetadataTS("design:type", Function),
|
|
774
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
775
|
+
Object
|
|
776
|
+
]),
|
|
777
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
778
|
+
], RoleController.prototype, "createRole", null);
|
|
779
|
+
__legacyDecorateClassTS([
|
|
780
|
+
Put("/:id"),
|
|
781
|
+
isAdmin(),
|
|
782
|
+
__legacyDecorateParamTS(0, Params("id")),
|
|
783
|
+
__legacyDecorateParamTS(1, Body()),
|
|
784
|
+
__legacyMetadataTS("design:type", Function),
|
|
785
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
786
|
+
Object,
|
|
787
|
+
Object
|
|
788
|
+
]),
|
|
789
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
790
|
+
], RoleController.prototype, "updateRole", null);
|
|
791
|
+
__legacyDecorateClassTS([
|
|
792
|
+
Delete("/:id"),
|
|
793
|
+
isAdmin(),
|
|
794
|
+
__legacyDecorateParamTS(0, Params("id")),
|
|
795
|
+
__legacyMetadataTS("design:type", Function),
|
|
796
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
797
|
+
Object
|
|
798
|
+
]),
|
|
799
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
800
|
+
], RoleController.prototype, "deleteRole", null);
|
|
801
|
+
RoleController = __legacyDecorateClassTS([
|
|
802
|
+
Controller("/roles"),
|
|
803
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
804
|
+
typeof RoleService === "undefined" ? Object : RoleService
|
|
805
|
+
])
|
|
806
|
+
], RoleController);
|
|
807
|
+
// src/users/UserService.ts
|
|
808
|
+
import { nanoid } from "nanoid";
|
|
809
|
+
import { clean } from "@/shared";
|
|
810
|
+
class UserService {
|
|
811
|
+
roleValidator;
|
|
812
|
+
roleService;
|
|
813
|
+
userRepository;
|
|
814
|
+
userValidator;
|
|
815
|
+
encryptionService;
|
|
816
|
+
constructor(roleValidator, roleService, userRepository, userValidator, encryptionService) {
|
|
817
|
+
this.roleValidator = roleValidator;
|
|
818
|
+
this.roleService = roleService;
|
|
819
|
+
this.userRepository = userRepository;
|
|
820
|
+
this.userValidator = userValidator;
|
|
821
|
+
this.encryptionService = encryptionService;
|
|
822
|
+
}
|
|
823
|
+
sanitizeUser(user) {
|
|
824
|
+
if (!user)
|
|
825
|
+
return user;
|
|
826
|
+
const { password, ...sanitizedUser } = user;
|
|
827
|
+
return sanitizedUser;
|
|
828
|
+
}
|
|
829
|
+
sanitizeUsers(users) {
|
|
830
|
+
return users.map((user) => this.sanitizeUser(user));
|
|
831
|
+
}
|
|
832
|
+
async resolveUserRole(roleId, roleName) {
|
|
833
|
+
if (roleId) {
|
|
834
|
+
await this.roleValidator.checkRoleExists(roleId);
|
|
835
|
+
return roleId;
|
|
836
|
+
}
|
|
837
|
+
if (roleName) {
|
|
838
|
+
const roleByName = await this.roleService.getByName(roleName);
|
|
839
|
+
if (roleByName) {
|
|
840
|
+
return roleByName.id;
|
|
841
|
+
}
|
|
842
|
+
throw new Error(`Role '${roleName}' not found`);
|
|
843
|
+
}
|
|
844
|
+
const defaultRole = await this.roleService.getByName("Student");
|
|
845
|
+
return defaultRole.id;
|
|
846
|
+
}
|
|
847
|
+
async getAll() {
|
|
848
|
+
const users = await this.userRepository.getAll();
|
|
849
|
+
return this.sanitizeUsers(users);
|
|
850
|
+
}
|
|
851
|
+
async getById(id) {
|
|
852
|
+
await this.userValidator.checkUserExists(id);
|
|
853
|
+
const user = await this.userRepository.getById(id);
|
|
854
|
+
return this.sanitizeUser(user);
|
|
855
|
+
}
|
|
856
|
+
async getByEmail(email) {
|
|
857
|
+
const user = await this.userValidator.checkUserExistsByEmail(email);
|
|
858
|
+
return this.sanitizeUser(user);
|
|
859
|
+
}
|
|
860
|
+
async create(data) {
|
|
861
|
+
const { id, email, image, emailVerified, password, roleId, role } = data;
|
|
862
|
+
let userId = id || nanoid(5);
|
|
863
|
+
let pass = password || "12345678";
|
|
864
|
+
await this.userValidator.checkEmailUnique(data.email);
|
|
865
|
+
await this.userValidator.checkUserIdIsUnique(id);
|
|
866
|
+
const hashedPassword = await this.encryptionService.hashPassword(pass);
|
|
867
|
+
const resolvedRoleId = await this.resolveUserRole(roleId, role);
|
|
868
|
+
const userDetails = {
|
|
869
|
+
id: userId,
|
|
870
|
+
email,
|
|
871
|
+
image,
|
|
872
|
+
password: hashedPassword,
|
|
873
|
+
roleId: resolvedRoleId,
|
|
874
|
+
emailVerified,
|
|
875
|
+
status: "pending"
|
|
876
|
+
};
|
|
877
|
+
await this.userValidator.validateCreateUser(userDetails);
|
|
878
|
+
const newUser = await this.userRepository.create(userDetails);
|
|
879
|
+
return this.sanitizeUser(newUser);
|
|
880
|
+
}
|
|
881
|
+
async update(id, data) {
|
|
882
|
+
const { password, image } = data;
|
|
883
|
+
await this.userValidator.checkUserExists(id);
|
|
884
|
+
await this.userValidator.checkEmailUnique(data.email, id);
|
|
885
|
+
const currentUser = await this.userRepository.getById(id);
|
|
886
|
+
const hashedPassword = await this.encryptionService.hashPassword(password);
|
|
887
|
+
const updateData = {
|
|
888
|
+
...data,
|
|
889
|
+
image,
|
|
890
|
+
...hashedPassword && { password: hashedPassword }
|
|
891
|
+
};
|
|
892
|
+
const cleanedUpdateData = clean(updateData);
|
|
893
|
+
const updatedUser = await this.userRepository.update(id, cleanedUpdateData);
|
|
894
|
+
return this.sanitizeUser(updatedUser);
|
|
895
|
+
}
|
|
896
|
+
async delete(id) {
|
|
897
|
+
await this.userValidator.checkUserExists(id);
|
|
898
|
+
const user = await this.userRepository.delete(id);
|
|
899
|
+
return this.sanitizeUser(user);
|
|
900
|
+
}
|
|
901
|
+
async deleteAll() {
|
|
902
|
+
const deletedUsers = await this.userRepository.deleteAll();
|
|
903
|
+
return this.sanitizeUsers(deletedUsers);
|
|
904
|
+
}
|
|
905
|
+
async getRoleName(id) {
|
|
906
|
+
await this.userValidator.checkUserExists(id);
|
|
907
|
+
return await this.userRepository.getRoleNameById(id);
|
|
908
|
+
}
|
|
909
|
+
async getPassword(email) {
|
|
910
|
+
await this.userValidator.checkUserExistsByEmail(email);
|
|
911
|
+
return await this.userRepository.getUserPassword(email);
|
|
912
|
+
}
|
|
913
|
+
async assignRole(id, roleId, roleName) {
|
|
914
|
+
await this.userValidator.checkUserExists(id);
|
|
915
|
+
const resolvedRoleId = await this.resolveUserRole(roleId, roleName);
|
|
916
|
+
const updatedUser = await this.userRepository.update(id, { roleId: resolvedRoleId });
|
|
917
|
+
return this.sanitizeUser(updatedUser);
|
|
918
|
+
}
|
|
919
|
+
async removeRole(id) {
|
|
920
|
+
await this.userValidator.checkUserExists(id);
|
|
921
|
+
const updatedUser = await this.userRepository.update(id, { roleId: null });
|
|
922
|
+
return this.sanitizeUser(updatedUser);
|
|
923
|
+
}
|
|
924
|
+
async seedAdminUser() {
|
|
925
|
+
const email = "admin@admin.com";
|
|
926
|
+
const adminRole = await this.roleValidator.checkAdminRoleExists();
|
|
927
|
+
const existingUser = await this.userRepository.getByEmail(email);
|
|
928
|
+
if (existingUser) {
|
|
929
|
+
await this.delete(existingUser.id);
|
|
930
|
+
}
|
|
931
|
+
const newAdminUser = await this.create({
|
|
932
|
+
id: "USR00",
|
|
933
|
+
name: "System Administrator",
|
|
934
|
+
email,
|
|
935
|
+
password: "12345678",
|
|
936
|
+
image: null,
|
|
937
|
+
roleId: adminRole.id,
|
|
938
|
+
status: "active",
|
|
939
|
+
emailVerified: true
|
|
940
|
+
});
|
|
941
|
+
return this.sanitizeUser(newAdminUser);
|
|
942
|
+
}
|
|
943
|
+
async updateLang(language) {
|
|
944
|
+
setLanguage(language);
|
|
945
|
+
return language;
|
|
946
|
+
}
|
|
947
|
+
async getLang() {
|
|
948
|
+
return getCurrentLanguage();
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
__legacyDecorateClassTS([
|
|
952
|
+
Transactional(),
|
|
953
|
+
__legacyMetadataTS("design:type", Function),
|
|
954
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
955
|
+
Object
|
|
956
|
+
]),
|
|
957
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
958
|
+
], UserService.prototype, "create", null);
|
|
959
|
+
UserService = __legacyDecorateClassTS([
|
|
960
|
+
Injectable8(),
|
|
961
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
962
|
+
typeof RoleValidator === "undefined" ? Object : RoleValidator,
|
|
963
|
+
typeof RoleService === "undefined" ? Object : RoleService,
|
|
964
|
+
typeof UserRepository === "undefined" ? Object : UserRepository,
|
|
965
|
+
typeof UserValidator === "undefined" ? Object : UserValidator,
|
|
966
|
+
typeof EncryptionService === "undefined" ? Object : EncryptionService
|
|
967
|
+
])
|
|
968
|
+
], UserService);
|
|
969
|
+
// src/users/UserController.ts
|
|
970
|
+
import { Controller as Controller2, Get as Get2, Post as Post2, Put as Put2, Delete as Delete2, Params as Params2, Body as Body2, t as t5 } from "najm-api";
|
|
971
|
+
import { isAdmin as isAdmin2, isAuth as isAuth2 } from "@/roles/RoleGuards";
|
|
972
|
+
class UserController {
|
|
973
|
+
userService;
|
|
974
|
+
constructor(userService) {
|
|
975
|
+
this.userService = userService;
|
|
976
|
+
}
|
|
977
|
+
async getUsers() {
|
|
978
|
+
const users = await this.userService.getAll();
|
|
979
|
+
return {
|
|
980
|
+
data: users,
|
|
981
|
+
message: t5("users.success.retrieved"),
|
|
982
|
+
status: "success"
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
async getLang() {
|
|
986
|
+
const language = await this.userService.getLang();
|
|
987
|
+
return {
|
|
988
|
+
data: { language },
|
|
989
|
+
message: t5("users.success.retrieved"),
|
|
990
|
+
status: "success"
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
async updateLang(language) {
|
|
994
|
+
const data = await this.userService.updateLang(language);
|
|
995
|
+
return {
|
|
996
|
+
data,
|
|
997
|
+
message: t5("users.success.updated"),
|
|
998
|
+
status: "success"
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
async getUser(id) {
|
|
1002
|
+
const user = await this.userService.getById(id);
|
|
1003
|
+
return {
|
|
1004
|
+
data: user,
|
|
1005
|
+
message: t5("users.success.retrieved"),
|
|
1006
|
+
status: "success"
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
async getByEmail(email) {
|
|
1010
|
+
const user = await this.userService.getByEmail(email);
|
|
1011
|
+
return {
|
|
1012
|
+
data: user,
|
|
1013
|
+
message: t5("users.success.retrieved"),
|
|
1014
|
+
status: "success"
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
async getRole(userId) {
|
|
1018
|
+
const role = await this.userService.getRoleName(userId);
|
|
1019
|
+
return {
|
|
1020
|
+
data: role,
|
|
1021
|
+
message: t5("users.success.retrieved"),
|
|
1022
|
+
status: "success"
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
async create(body) {
|
|
1026
|
+
const newUser = await this.userService.create(body);
|
|
1027
|
+
return {
|
|
1028
|
+
data: newUser,
|
|
1029
|
+
message: t5("users.success.created"),
|
|
1030
|
+
status: "success"
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
async update(id, body) {
|
|
1034
|
+
const updatedUser = await this.userService.update(id, body);
|
|
1035
|
+
return {
|
|
1036
|
+
data: updatedUser,
|
|
1037
|
+
message: t5("users.success.updated"),
|
|
1038
|
+
status: "success"
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
async delete(id) {
|
|
1042
|
+
const result = await this.userService.delete(id);
|
|
1043
|
+
return {
|
|
1044
|
+
data: result,
|
|
1045
|
+
message: t5("users.success.deleted"),
|
|
1046
|
+
status: "success"
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
async deleteAll() {
|
|
1050
|
+
const result = await this.userService.deleteAll();
|
|
1051
|
+
return {
|
|
1052
|
+
data: result,
|
|
1053
|
+
message: t5("users.success.allDeleted"),
|
|
1054
|
+
status: "success"
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
async assignRole(userId, roleId) {
|
|
1058
|
+
await this.userService.assignRole(userId, roleId);
|
|
1059
|
+
return {
|
|
1060
|
+
message: t5("users.success.updated"),
|
|
1061
|
+
status: "success"
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
async removeRole(userId) {
|
|
1065
|
+
await this.userService.removeRole(userId);
|
|
1066
|
+
return {
|
|
1067
|
+
message: t5("users.success.updated"),
|
|
1068
|
+
status: "success"
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
__legacyDecorateClassTS([
|
|
1073
|
+
Get2(),
|
|
1074
|
+
isAdmin2(),
|
|
1075
|
+
__legacyMetadataTS("design:type", Function),
|
|
1076
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
1077
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1078
|
+
], UserController.prototype, "getUsers", null);
|
|
1079
|
+
__legacyDecorateClassTS([
|
|
1080
|
+
Get2("/lang"),
|
|
1081
|
+
isAuth2(),
|
|
1082
|
+
__legacyMetadataTS("design:type", Function),
|
|
1083
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
1084
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1085
|
+
], UserController.prototype, "getLang", null);
|
|
1086
|
+
__legacyDecorateClassTS([
|
|
1087
|
+
Post2("/lang/:language"),
|
|
1088
|
+
isAuth2(),
|
|
1089
|
+
__legacyDecorateParamTS(0, Params2("language")),
|
|
1090
|
+
__legacyMetadataTS("design:type", Function),
|
|
1091
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1092
|
+
Object
|
|
1093
|
+
]),
|
|
1094
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1095
|
+
], UserController.prototype, "updateLang", null);
|
|
1096
|
+
__legacyDecorateClassTS([
|
|
1097
|
+
Get2("/:id"),
|
|
1098
|
+
isAdmin2(),
|
|
1099
|
+
__legacyDecorateParamTS(0, Params2("id")),
|
|
1100
|
+
__legacyMetadataTS("design:type", Function),
|
|
1101
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1102
|
+
Object
|
|
1103
|
+
]),
|
|
1104
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1105
|
+
], UserController.prototype, "getUser", null);
|
|
1106
|
+
__legacyDecorateClassTS([
|
|
1107
|
+
Get2("/email/:email"),
|
|
1108
|
+
isAdmin2(),
|
|
1109
|
+
__legacyDecorateParamTS(0, Params2("email")),
|
|
1110
|
+
__legacyMetadataTS("design:type", Function),
|
|
1111
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1112
|
+
Object
|
|
1113
|
+
]),
|
|
1114
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1115
|
+
], UserController.prototype, "getByEmail", null);
|
|
1116
|
+
__legacyDecorateClassTS([
|
|
1117
|
+
Get2("/role/:userId"),
|
|
1118
|
+
isAdmin2(),
|
|
1119
|
+
__legacyDecorateParamTS(0, Params2("userId")),
|
|
1120
|
+
__legacyMetadataTS("design:type", Function),
|
|
1121
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1122
|
+
Object
|
|
1123
|
+
]),
|
|
1124
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1125
|
+
], UserController.prototype, "getRole", null);
|
|
1126
|
+
__legacyDecorateClassTS([
|
|
1127
|
+
Post2(),
|
|
1128
|
+
isAdmin2(),
|
|
1129
|
+
__legacyDecorateParamTS(0, Body2()),
|
|
1130
|
+
__legacyMetadataTS("design:type", Function),
|
|
1131
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1132
|
+
Object
|
|
1133
|
+
]),
|
|
1134
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1135
|
+
], UserController.prototype, "create", null);
|
|
1136
|
+
__legacyDecorateClassTS([
|
|
1137
|
+
Put2("/:id"),
|
|
1138
|
+
isAdmin2(),
|
|
1139
|
+
__legacyDecorateParamTS(0, Params2("id")),
|
|
1140
|
+
__legacyDecorateParamTS(1, Body2()),
|
|
1141
|
+
__legacyMetadataTS("design:type", Function),
|
|
1142
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1143
|
+
Object,
|
|
1144
|
+
Object
|
|
1145
|
+
]),
|
|
1146
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1147
|
+
], UserController.prototype, "update", null);
|
|
1148
|
+
__legacyDecorateClassTS([
|
|
1149
|
+
Delete2("/:id"),
|
|
1150
|
+
isAdmin2(),
|
|
1151
|
+
__legacyDecorateParamTS(0, Params2("id")),
|
|
1152
|
+
__legacyMetadataTS("design:type", Function),
|
|
1153
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1154
|
+
Object
|
|
1155
|
+
]),
|
|
1156
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1157
|
+
], UserController.prototype, "delete", null);
|
|
1158
|
+
__legacyDecorateClassTS([
|
|
1159
|
+
Delete2(),
|
|
1160
|
+
isAdmin2(),
|
|
1161
|
+
__legacyMetadataTS("design:type", Function),
|
|
1162
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
1163
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1164
|
+
], UserController.prototype, "deleteAll", null);
|
|
1165
|
+
__legacyDecorateClassTS([
|
|
1166
|
+
Post2("/assign/:userId/:roleId"),
|
|
1167
|
+
isAdmin2(),
|
|
1168
|
+
__legacyDecorateParamTS(0, Params2("userId")),
|
|
1169
|
+
__legacyDecorateParamTS(1, Params2("roleId")),
|
|
1170
|
+
__legacyMetadataTS("design:type", Function),
|
|
1171
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1172
|
+
Object,
|
|
1173
|
+
Object
|
|
1174
|
+
]),
|
|
1175
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1176
|
+
], UserController.prototype, "assignRole", null);
|
|
1177
|
+
__legacyDecorateClassTS([
|
|
1178
|
+
Delete2("/remove/:userId"),
|
|
1179
|
+
isAdmin2(),
|
|
1180
|
+
__legacyDecorateParamTS(0, Params2("userId")),
|
|
1181
|
+
__legacyMetadataTS("design:type", Function),
|
|
1182
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1183
|
+
Object
|
|
1184
|
+
]),
|
|
1185
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1186
|
+
], UserController.prototype, "removeRole", null);
|
|
1187
|
+
UserController = __legacyDecorateClassTS([
|
|
1188
|
+
Controller2("/users"),
|
|
1189
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1190
|
+
typeof UserService === "undefined" ? Object : UserService
|
|
1191
|
+
])
|
|
1192
|
+
], UserController);
|
|
1193
|
+
// src/auth/AuthService.ts
|
|
1194
|
+
class AuthService {
|
|
1195
|
+
tokenService;
|
|
1196
|
+
userService;
|
|
1197
|
+
userValidator;
|
|
1198
|
+
cookieService;
|
|
1199
|
+
constructor(tokenService, userService, userValidator, cookieService) {
|
|
1200
|
+
this.tokenService = tokenService;
|
|
1201
|
+
this.userService = userService;
|
|
1202
|
+
this.userValidator = userValidator;
|
|
1203
|
+
this.cookieService = cookieService;
|
|
1204
|
+
}
|
|
1205
|
+
async registerUser(body) {
|
|
1206
|
+
return await this.userService.create(body);
|
|
1207
|
+
}
|
|
1208
|
+
async loginUser(body) {
|
|
1209
|
+
const { email, password } = body;
|
|
1210
|
+
if (!email || !password) {
|
|
1211
|
+
throw new Error(t6("auth.errors.invalidCredentials"));
|
|
1212
|
+
}
|
|
1213
|
+
const existingPassword = await this.userService.getPassword(email);
|
|
1214
|
+
const { id } = await this.userService.getByEmail(email);
|
|
1215
|
+
await this.userValidator.checkPasswordValid(password, existingPassword);
|
|
1216
|
+
const data = await this.tokenService.generateTokens(id);
|
|
1217
|
+
this.cookieService.setRefreshCookie(data.refreshToken);
|
|
1218
|
+
return data;
|
|
1219
|
+
}
|
|
1220
|
+
async refreshTokens() {
|
|
1221
|
+
const data = await this.tokenService.refreshTokens();
|
|
1222
|
+
this.cookieService.setRefreshCookie(data.refreshToken);
|
|
1223
|
+
return data;
|
|
1224
|
+
}
|
|
1225
|
+
async logoutUser(userId) {
|
|
1226
|
+
await this.userValidator.checkUserExists(userId);
|
|
1227
|
+
await this.tokenService.revokeToken(userId);
|
|
1228
|
+
this.cookieService.clearRefreshCookie();
|
|
1229
|
+
return { data: null, message: t6("auth.success.logout") };
|
|
1230
|
+
}
|
|
1231
|
+
async getUserProfile(userData) {
|
|
1232
|
+
const lang = getCurrentLanguage2();
|
|
1233
|
+
return {
|
|
1234
|
+
...userData,
|
|
1235
|
+
language: lang
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
async forgotPassword(email) {}
|
|
1239
|
+
}
|
|
1240
|
+
AuthService = __legacyDecorateClassTS([
|
|
1241
|
+
Injectable9(),
|
|
1242
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1243
|
+
typeof TokenService === "undefined" ? Object : TokenService,
|
|
1244
|
+
typeof UserService === "undefined" ? Object : UserService,
|
|
1245
|
+
typeof UserValidator === "undefined" ? Object : UserValidator,
|
|
1246
|
+
typeof CookieService === "undefined" ? Object : CookieService
|
|
1247
|
+
])
|
|
1248
|
+
], AuthService);
|
|
1249
|
+
|
|
1250
|
+
// src/auth/AuthController.ts
|
|
1251
|
+
import { isAuth as isAuth3 } from "@/roles/RoleGuards";
|
|
1252
|
+
class AuthController {
|
|
1253
|
+
authService;
|
|
1254
|
+
constructor(authService) {
|
|
1255
|
+
this.authService = authService;
|
|
1256
|
+
}
|
|
1257
|
+
async registerUser(body) {
|
|
1258
|
+
const data = await this.authService.registerUser(body);
|
|
1259
|
+
return {
|
|
1260
|
+
data,
|
|
1261
|
+
message: t7("auth.success.register"),
|
|
1262
|
+
status: "success"
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
async loginUser(body) {
|
|
1266
|
+
const data = await this.authService.loginUser(body);
|
|
1267
|
+
return {
|
|
1268
|
+
data,
|
|
1269
|
+
message: t7("auth.success.login"),
|
|
1270
|
+
status: "success"
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
async refreshTokens() {
|
|
1274
|
+
const data = await this.authService.refreshTokens();
|
|
1275
|
+
return {
|
|
1276
|
+
data,
|
|
1277
|
+
message: t7("auth.success.tokenRefreshed"),
|
|
1278
|
+
status: "success"
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
async logoutUser(id) {
|
|
1282
|
+
const data = await this.authService.logoutUser(id);
|
|
1283
|
+
return {
|
|
1284
|
+
data,
|
|
1285
|
+
message: t7("auth.success.logout"),
|
|
1286
|
+
status: "success"
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
async userProfile(user) {
|
|
1290
|
+
const data = await this.authService.getUserProfile(user);
|
|
1291
|
+
return {
|
|
1292
|
+
data,
|
|
1293
|
+
message: t7("users.success.retrieved"),
|
|
1294
|
+
status: "success"
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
async forgotPassword(body) {
|
|
1298
|
+
const data = await this.authService.forgotPassword(body.email);
|
|
1299
|
+
return {
|
|
1300
|
+
data,
|
|
1301
|
+
message: t7("auth.success.passwordReset"),
|
|
1302
|
+
status: "success"
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
__legacyDecorateClassTS([
|
|
1307
|
+
Post3("/register"),
|
|
1308
|
+
__legacyDecorateParamTS(0, Body3()),
|
|
1309
|
+
__legacyMetadataTS("design:type", Function),
|
|
1310
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1311
|
+
Object
|
|
1312
|
+
]),
|
|
1313
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1314
|
+
], AuthController.prototype, "registerUser", null);
|
|
1315
|
+
__legacyDecorateClassTS([
|
|
1316
|
+
Post3("/login"),
|
|
1317
|
+
__legacyDecorateParamTS(0, Body3()),
|
|
1318
|
+
__legacyMetadataTS("design:type", Function),
|
|
1319
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1320
|
+
Object
|
|
1321
|
+
]),
|
|
1322
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1323
|
+
], AuthController.prototype, "loginUser", null);
|
|
1324
|
+
__legacyDecorateClassTS([
|
|
1325
|
+
Get3("/refresh"),
|
|
1326
|
+
__legacyMetadataTS("design:type", Function),
|
|
1327
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
1328
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1329
|
+
], AuthController.prototype, "refreshTokens", null);
|
|
1330
|
+
__legacyDecorateClassTS([
|
|
1331
|
+
Get3("/logout/:id"),
|
|
1332
|
+
__legacyDecorateParamTS(0, Params3("id")),
|
|
1333
|
+
__legacyMetadataTS("design:type", Function),
|
|
1334
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1335
|
+
Object
|
|
1336
|
+
]),
|
|
1337
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1338
|
+
], AuthController.prototype, "logoutUser", null);
|
|
1339
|
+
__legacyDecorateClassTS([
|
|
1340
|
+
Get3("/me"),
|
|
1341
|
+
isAuth3(),
|
|
1342
|
+
__legacyDecorateParamTS(0, User2()),
|
|
1343
|
+
__legacyMetadataTS("design:type", Function),
|
|
1344
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1345
|
+
Object
|
|
1346
|
+
]),
|
|
1347
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1348
|
+
], AuthController.prototype, "userProfile", null);
|
|
1349
|
+
__legacyDecorateClassTS([
|
|
1350
|
+
Post3("/forgot-password"),
|
|
1351
|
+
isAuth3(),
|
|
1352
|
+
__legacyDecorateParamTS(0, Body3()),
|
|
1353
|
+
__legacyMetadataTS("design:type", Function),
|
|
1354
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1355
|
+
Object
|
|
1356
|
+
]),
|
|
1357
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
1358
|
+
], AuthController.prototype, "forgotPassword", null);
|
|
1359
|
+
AuthController = __legacyDecorateClassTS([
|
|
1360
|
+
Controller3("/auth"),
|
|
1361
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1362
|
+
typeof AuthService === "undefined" ? Object : AuthService
|
|
1363
|
+
])
|
|
1364
|
+
], AuthController);
|
|
1365
|
+
// src/lib/ENUMS.ts
|
|
1366
|
+
var ENUMS = {
|
|
1367
|
+
userType: {
|
|
1368
|
+
values: ["admin", "teacher", "student", "parent"],
|
|
1369
|
+
translationKey: "enums.userType"
|
|
1370
|
+
},
|
|
1371
|
+
userStatus: {
|
|
1372
|
+
values: ["active", "inactive", "pending"],
|
|
1373
|
+
translationKey: "enums.userStatus"
|
|
1374
|
+
},
|
|
1375
|
+
tokenStatus: {
|
|
1376
|
+
values: ["active", "revoked", "expired"],
|
|
1377
|
+
translationKey: "enums.tokenStatus"
|
|
1378
|
+
},
|
|
1379
|
+
tokenType: {
|
|
1380
|
+
values: ["access", "refresh"],
|
|
1381
|
+
translationKey: "enums.tokenType"
|
|
1382
|
+
},
|
|
1383
|
+
fileStatus: {
|
|
1384
|
+
values: ["active", "deleted", "archived"],
|
|
1385
|
+
translationKey: "enums.fileStatus"
|
|
1386
|
+
},
|
|
1387
|
+
gender: {
|
|
1388
|
+
values: ["M", "F"],
|
|
1389
|
+
translationKey: "common.gender"
|
|
1390
|
+
},
|
|
1391
|
+
studentStatus: {
|
|
1392
|
+
values: ["active", "inactive", "graduated", "transferred"],
|
|
1393
|
+
translationKey: "students.status"
|
|
1394
|
+
},
|
|
1395
|
+
teacherStatus: {
|
|
1396
|
+
values: ["active", "inactive", "onLeave"],
|
|
1397
|
+
translationKey: "teachers.status"
|
|
1398
|
+
},
|
|
1399
|
+
employmentType: {
|
|
1400
|
+
values: ["fullTime", "partTime", "contract", "temporary"],
|
|
1401
|
+
translationKey: "teachers.employmentType"
|
|
1402
|
+
},
|
|
1403
|
+
relationshipType: {
|
|
1404
|
+
values: ["father", "mother", "guardian", "stepparent", "grandparent", "other"],
|
|
1405
|
+
translationKey: "parents.relationships"
|
|
1406
|
+
},
|
|
1407
|
+
semester: {
|
|
1408
|
+
values: ["spring", "summer", "fall", "winter"],
|
|
1409
|
+
translationKey: "academic.semester"
|
|
1410
|
+
},
|
|
1411
|
+
classStatus: {
|
|
1412
|
+
values: ["active", "completed", "cancelled"],
|
|
1413
|
+
translationKey: "classes.status"
|
|
1414
|
+
},
|
|
1415
|
+
sectionStatus: {
|
|
1416
|
+
values: ["active", "inactive", "archived"],
|
|
1417
|
+
translationKey: "sections.status"
|
|
1418
|
+
},
|
|
1419
|
+
language: {
|
|
1420
|
+
values: ["en", "fr", "ar", "es"],
|
|
1421
|
+
translationKey: "common.languages"
|
|
1422
|
+
},
|
|
1423
|
+
enrollmentStatus: {
|
|
1424
|
+
values: ["enrolled", "completed", "dropped", "failed"],
|
|
1425
|
+
translationKey: "enrollments.status"
|
|
1426
|
+
},
|
|
1427
|
+
assignmentStatus: {
|
|
1428
|
+
values: ["active", "completed", "cancelled"],
|
|
1429
|
+
translationKey: "assignments.status"
|
|
1430
|
+
},
|
|
1431
|
+
calendarSystem: {
|
|
1432
|
+
values: ["SEMESTER", "TRIMESTER", "QUARTER"],
|
|
1433
|
+
translationKey: "settings.calendarSystem"
|
|
1434
|
+
},
|
|
1435
|
+
assessmentType: {
|
|
1436
|
+
values: ["quiz", "assignment", "project", "participation", "test", "presentation"],
|
|
1437
|
+
translationKey: "assessments.type"
|
|
1438
|
+
},
|
|
1439
|
+
assessmentStatus: {
|
|
1440
|
+
values: ["scheduled", "active", "completed", "cancelled"],
|
|
1441
|
+
translationKey: "assessments.status"
|
|
1442
|
+
},
|
|
1443
|
+
submissionType: {
|
|
1444
|
+
values: ["online", "paper", "presentation", "practical", "discussion"],
|
|
1445
|
+
translationKey: "assessments.submissionType"
|
|
1446
|
+
},
|
|
1447
|
+
examType: {
|
|
1448
|
+
values: ["midterm", "final", "standardized"],
|
|
1449
|
+
translationKey: "exams.type"
|
|
1450
|
+
},
|
|
1451
|
+
examSecurity: {
|
|
1452
|
+
values: ["low", "medium", "high"],
|
|
1453
|
+
translationKey: "exams.security"
|
|
1454
|
+
},
|
|
1455
|
+
examStatus: {
|
|
1456
|
+
values: ["scheduled", "active", "completed", "cancelled", "rescheduled"],
|
|
1457
|
+
translationKey: "exams.status"
|
|
1458
|
+
},
|
|
1459
|
+
gradeStatus: {
|
|
1460
|
+
values: ["graded", "pending", "draft", "reviewed"],
|
|
1461
|
+
translationKey: "grades.status"
|
|
1462
|
+
},
|
|
1463
|
+
attendanceStatus: {
|
|
1464
|
+
values: ["present", "absent", "late", "excused"],
|
|
1465
|
+
translationKey: "attendance.status"
|
|
1466
|
+
},
|
|
1467
|
+
proficiencyLevel: {
|
|
1468
|
+
values: ["beginner", "intermediate", "advanced", "expert"],
|
|
1469
|
+
translationKey: "common.proficiencyLevel"
|
|
1470
|
+
},
|
|
1471
|
+
dayOfWeek: {
|
|
1472
|
+
values: ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"],
|
|
1473
|
+
translationKey: "common.days"
|
|
1474
|
+
},
|
|
1475
|
+
alertType: {
|
|
1476
|
+
values: ["academic", "attendance", "behavioral", "health", "system", "announcement", "reminder", "emergency"],
|
|
1477
|
+
translationKey: "alerts.type"
|
|
1478
|
+
},
|
|
1479
|
+
alertPriority: {
|
|
1480
|
+
values: ["low", "medium", "high", "critical"],
|
|
1481
|
+
translationKey: "alerts.priority"
|
|
1482
|
+
},
|
|
1483
|
+
alertStatus: {
|
|
1484
|
+
values: ["active", "acknowledged", "resolved", "dismissed"],
|
|
1485
|
+
translationKey: "alerts.status"
|
|
1486
|
+
},
|
|
1487
|
+
feeTypeStatus: {
|
|
1488
|
+
values: ["active", "inactive", "archived"],
|
|
1489
|
+
translationKey: "fees.typeStatus"
|
|
1490
|
+
},
|
|
1491
|
+
feeCategory: {
|
|
1492
|
+
values: ["tuition", "registration", "transport", "cafeteria", "books", "sports", "uniform", "technology", "fieldtrip", "other"],
|
|
1493
|
+
translationKey: "feeTypes.category"
|
|
1494
|
+
},
|
|
1495
|
+
paymentType: {
|
|
1496
|
+
values: ["recurring", "oneTime"],
|
|
1497
|
+
translationKey: "payments.type"
|
|
1498
|
+
},
|
|
1499
|
+
schedule: {
|
|
1500
|
+
values: ["monthly", "quarterly", "semester", "annually", "oneTime"],
|
|
1501
|
+
translationKey: "fees.schedule"
|
|
1502
|
+
},
|
|
1503
|
+
feeStatus: {
|
|
1504
|
+
values: ["pending", "partiallyPaid", "paid", "overdue"],
|
|
1505
|
+
translationKey: "fees.status"
|
|
1506
|
+
},
|
|
1507
|
+
feeInstallmentStatus: {
|
|
1508
|
+
values: ["pending", "partiallyPaid", "paid", "overdue"],
|
|
1509
|
+
translationKey: "fees.installmentStatus"
|
|
1510
|
+
},
|
|
1511
|
+
paymentMethod: {
|
|
1512
|
+
values: ["cash", "bankTransfer", "check", "creditCard", "debitCard", "online", "mobilePayment"],
|
|
1513
|
+
translationKey: "payments.methods"
|
|
1514
|
+
},
|
|
1515
|
+
paymentStatus: {
|
|
1516
|
+
values: ["completed", "pending", "failed", "refunded"],
|
|
1517
|
+
translationKey: "payments.status"
|
|
1518
|
+
},
|
|
1519
|
+
eventType: {
|
|
1520
|
+
values: ["academic", "sports", "cultural", "holiday", "exam", "meeting", "workshop", "fieldtrip", "ceremony", "conference", "other"],
|
|
1521
|
+
translationKey: "events.type"
|
|
1522
|
+
},
|
|
1523
|
+
eventStatus: {
|
|
1524
|
+
values: ["scheduled", "ongoing", "completed", "cancelled", "postponed"],
|
|
1525
|
+
translationKey: "events.status"
|
|
1526
|
+
},
|
|
1527
|
+
eventVisibility: {
|
|
1528
|
+
values: ["public", "private", "teachers", "students", "parents", "staff"],
|
|
1529
|
+
translationKey: "events.visibility"
|
|
1530
|
+
},
|
|
1531
|
+
participantType: {
|
|
1532
|
+
values: ["student", "teacher", "parent", "staff"],
|
|
1533
|
+
translationKey: "events.participantType"
|
|
1534
|
+
},
|
|
1535
|
+
expenseCategory: {
|
|
1536
|
+
values: ["salary", "utilities", "maintenance", "supplies", "equipment", "transport", "food", "security", "cleaning", "insurance", "rent", "tax", "marketing", "training", "technology", "miscellaneous"],
|
|
1537
|
+
translationKey: "expenses.categories"
|
|
1538
|
+
},
|
|
1539
|
+
expenseStatus: {
|
|
1540
|
+
values: ["pending", "approved", "paid", "rejected", "cancelled"],
|
|
1541
|
+
translationKey: "expenses.status"
|
|
1542
|
+
},
|
|
1543
|
+
trackerMode: {
|
|
1544
|
+
values: ["tracking", "gprs", "sms", "sleepTime", "sleepShock", "sleepDeep"],
|
|
1545
|
+
translationKey: "tracker.mode"
|
|
1546
|
+
},
|
|
1547
|
+
driverStatus: {
|
|
1548
|
+
values: ["active", "inactive", "onLeave", "suspended"],
|
|
1549
|
+
translationKey: "transport.driverStatus"
|
|
1550
|
+
},
|
|
1551
|
+
vehicleStatus: {
|
|
1552
|
+
values: ["active", "inactive", "maintenance", "retired"],
|
|
1553
|
+
translationKey: "transport.vehicleStatus"
|
|
1554
|
+
},
|
|
1555
|
+
vehicleType: {
|
|
1556
|
+
values: ["sedan", "minibus", "fullbus", "shuttle"],
|
|
1557
|
+
translationKey: "transport.vehicleType"
|
|
1558
|
+
},
|
|
1559
|
+
vehicleDocumentType: {
|
|
1560
|
+
values: ["insurance", "registration", "inspection", "emission", "license"],
|
|
1561
|
+
translationKey: "transport.documentType"
|
|
1562
|
+
},
|
|
1563
|
+
busStatus: {
|
|
1564
|
+
values: ["active", "inactive", "maintenance", "retired"],
|
|
1565
|
+
translationKey: "transport.busStatus"
|
|
1566
|
+
},
|
|
1567
|
+
refuelStatus: {
|
|
1568
|
+
values: ["pending", "completed", "cancelled"],
|
|
1569
|
+
translationKey: "transport.refuelStatus"
|
|
1570
|
+
},
|
|
1571
|
+
fuelType: {
|
|
1572
|
+
values: ["gasoline", "diesel", "electric", "hybrid", "lpg", "cng"],
|
|
1573
|
+
translationKey: "transport.fuelType"
|
|
1574
|
+
},
|
|
1575
|
+
maintenanceType: {
|
|
1576
|
+
values: ["scheduled", "repair", "inspection", "oilChange", "filterChange", "other"],
|
|
1577
|
+
translationKey: "transport.maintenanceType"
|
|
1578
|
+
},
|
|
1579
|
+
maintenanceStatus: {
|
|
1580
|
+
values: ["scheduled", "inProgress", "completed", "cancelled", "overdue"],
|
|
1581
|
+
translationKey: "transport.maintenanceStatus"
|
|
1582
|
+
},
|
|
1583
|
+
maritalStatus: {
|
|
1584
|
+
values: ["single", "married", "divorced", "widowed", "separated"],
|
|
1585
|
+
translationKey: "parents.maritalStatus"
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
var getEnumConfig = (enumKey) => ENUMS[enumKey];
|
|
1589
|
+
var getEnumValues = (enumKey) => ENUMS[enumKey]?.values || [];
|
|
1590
|
+
// src/lib/validations.ts
|
|
1591
|
+
import { z as z2 } from "zod";
|
|
1592
|
+
|
|
1593
|
+
// src/lib/ZodEnum.ts
|
|
1594
|
+
import { z } from "zod";
|
|
1595
|
+
var createZodEnum = (enumKey) => {
|
|
1596
|
+
const values = ENUMS[enumKey]?.values;
|
|
1597
|
+
if (!values)
|
|
1598
|
+
throw new Error(`Enum ${enumKey} not found`);
|
|
1599
|
+
return z.enum(values);
|
|
1600
|
+
};
|
|
1601
|
+
var userTypeEnum = createZodEnum("userType");
|
|
1602
|
+
var userStatusEnum = createZodEnum("userStatus");
|
|
1603
|
+
var tokenStatusEnum = createZodEnum("tokenStatus");
|
|
1604
|
+
var tokenTypeEnum = createZodEnum("tokenType");
|
|
1605
|
+
var fileStatusEnum = createZodEnum("fileStatus");
|
|
1606
|
+
var genderEnum = createZodEnum("gender");
|
|
1607
|
+
var studentStatusEnum = createZodEnum("studentStatus");
|
|
1608
|
+
var teacherStatusEnum = createZodEnum("teacherStatus");
|
|
1609
|
+
var employmentTypeEnum = createZodEnum("employmentType");
|
|
1610
|
+
var relationshipTypeEnum = createZodEnum("relationshipType");
|
|
1611
|
+
var semesterEnum = createZodEnum("semester");
|
|
1612
|
+
var classStatusEnum = createZodEnum("classStatus");
|
|
1613
|
+
var sectionStatusEnum = createZodEnum("sectionStatus");
|
|
1614
|
+
var languageEnum = createZodEnum("language");
|
|
1615
|
+
var enrollmentStatusEnum = createZodEnum("enrollmentStatus");
|
|
1616
|
+
var assignmentStatusEnum = createZodEnum("assignmentStatus");
|
|
1617
|
+
var calendarSystemEnum = createZodEnum("calendarSystem");
|
|
1618
|
+
var assessmentTypeEnum = createZodEnum("assessmentType");
|
|
1619
|
+
var assessmentStatusEnum = createZodEnum("assessmentStatus");
|
|
1620
|
+
var submissionTypeEnum = createZodEnum("submissionType");
|
|
1621
|
+
var examTypeEnum = createZodEnum("examType");
|
|
1622
|
+
var examSecurityEnum = createZodEnum("examSecurity");
|
|
1623
|
+
var examStatusEnum = createZodEnum("examStatus");
|
|
1624
|
+
var gradeStatusEnum = createZodEnum("gradeStatus");
|
|
1625
|
+
var attendanceStatusEnum = createZodEnum("attendanceStatus");
|
|
1626
|
+
var proficiencyLevelEnum = createZodEnum("proficiencyLevel");
|
|
1627
|
+
var dayOfWeekEnum = createZodEnum("dayOfWeek");
|
|
1628
|
+
var alertTypeEnum = createZodEnum("alertType");
|
|
1629
|
+
var alertPriorityEnum = createZodEnum("alertPriority");
|
|
1630
|
+
var alertStatusEnum = createZodEnum("alertStatus");
|
|
1631
|
+
var feeTypeStatusEnum = createZodEnum("feeTypeStatus");
|
|
1632
|
+
var paymentTypeEnum = createZodEnum("paymentType");
|
|
1633
|
+
var scheduleEnum = createZodEnum("schedule");
|
|
1634
|
+
var feeStatusEnum = createZodEnum("feeStatus");
|
|
1635
|
+
var feeInstallmentStatusEnum = createZodEnum("feeInstallmentStatus");
|
|
1636
|
+
var paymentMethodEnum = createZodEnum("paymentMethod");
|
|
1637
|
+
var paymentStatusEnum = createZodEnum("paymentStatus");
|
|
1638
|
+
var eventTypeEnum = createZodEnum("eventType");
|
|
1639
|
+
var eventStatusEnum = createZodEnum("eventStatus");
|
|
1640
|
+
var eventVisibilityEnum = createZodEnum("eventVisibility");
|
|
1641
|
+
var participantTypeEnum = createZodEnum("participantType");
|
|
1642
|
+
var expenseCategoryEnum = createZodEnum("expenseCategory");
|
|
1643
|
+
var expenseStatusEnum = createZodEnum("expenseStatus");
|
|
1644
|
+
var trackerModeEnum = createZodEnum("trackerMode");
|
|
1645
|
+
var driverStatusEnum = createZodEnum("driverStatus");
|
|
1646
|
+
var vehicleStatusEnum = createZodEnum("vehicleStatus");
|
|
1647
|
+
var vehicleTypeEnum = createZodEnum("vehicleType");
|
|
1648
|
+
var vehicleDocumentTypeEnum = createZodEnum("vehicleDocumentType");
|
|
1649
|
+
var busStatusEnum = createZodEnum("busStatus");
|
|
1650
|
+
var refuelStatusEnum = createZodEnum("refuelStatus");
|
|
1651
|
+
var fuelTypeEnum = createZodEnum("fuelType");
|
|
1652
|
+
var maintenanceTypeEnum = createZodEnum("maintenanceType");
|
|
1653
|
+
var maintenanceStatusEnum = createZodEnum("maintenanceStatus");
|
|
1654
|
+
var maritalStatusEnum = createZodEnum("maritalStatus");
|
|
1655
|
+
|
|
1656
|
+
// src/lib/validations.ts
|
|
1657
|
+
var requiredId = z2.preprocess((val) => val ?? "", z2.string().min(1, "ID is required"));
|
|
1658
|
+
var optionalId = z2.string().min(1, "ID cannot be empty").nullish().optional();
|
|
1659
|
+
var emailField = z2.string().email("Invalid email format").or(z2.literal(""));
|
|
1660
|
+
var phoneField = z2.string().regex(/^[\+]?[1-9][\d]{0,15}$/, "Invalid phone number");
|
|
1661
|
+
var nameField = z2.string().min(2, "Name must be at least 2 characters").max(100, "Name too long");
|
|
1662
|
+
var dateField = z2.string().regex(/^(\d{4}-\d{2}-\d{2}|\d{2}\/\d{2}\/\d{4}|\d{2}-\d{2}-\d{2}|\d{2}-\d{2}-\d{4})$/, "Date must be in YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, DD-MM-YY, or DD-MM-YYYY format");
|
|
1663
|
+
var optionalDateField = z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").nullable().optional();
|
|
1664
|
+
var timeField = z2.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, "Time must be in HH:MM format").optional().nullable();
|
|
1665
|
+
var cinField = z2.string().min(8, "CIN must be at least 8 characters").max(20, "CIN too long");
|
|
1666
|
+
var addressField = z2.string().max(500, "Address too long").optional();
|
|
1667
|
+
var academicYearField = z2.string().min(9, "Academic year is required").regex(/^\d{4}-\d{4}$/, "Academic year must be in YYYY-YYYY format");
|
|
1668
|
+
var num = () => {
|
|
1669
|
+
const createChainable = (currentSchema) => {
|
|
1670
|
+
const methods = {
|
|
1671
|
+
positive: (msg = "Must be positive") => createChainable(currentSchema.refine((val) => val > 0, { message: msg })),
|
|
1672
|
+
min: (value, msg) => createChainable(currentSchema.refine((val) => val >= value, { message: msg || `Must be at least ${value}` })),
|
|
1673
|
+
max: (value, msg) => createChainable(currentSchema.refine((val) => val <= value, { message: msg || `Cannot exceed ${value}` })),
|
|
1674
|
+
int: (msg = "Must be an integer") => createChainable(currentSchema.refine((val) => Number.isInteger(val), { message: msg }))
|
|
1675
|
+
};
|
|
1676
|
+
return Object.assign(currentSchema, methods);
|
|
1677
|
+
};
|
|
1678
|
+
const isValidNumber = (val) => {
|
|
1679
|
+
if (val === null || val === undefined || Number.isNaN(val))
|
|
1680
|
+
return false;
|
|
1681
|
+
if (typeof val === "number")
|
|
1682
|
+
return true;
|
|
1683
|
+
if (typeof val === "string") {
|
|
1684
|
+
const trimmed = val.trim();
|
|
1685
|
+
return trimmed !== "" && !isNaN(Number(trimmed));
|
|
1686
|
+
}
|
|
1687
|
+
return false;
|
|
1688
|
+
};
|
|
1689
|
+
const baseSchema = z2.any().refine(isValidNumber, { message: "Must be a valid number" }).transform((val) => typeof val === "string" ? Number(val) : val);
|
|
1690
|
+
return createChainable(baseSchema);
|
|
1691
|
+
};
|
|
1692
|
+
var userSchema2 = z2.object({
|
|
1693
|
+
id: optionalId,
|
|
1694
|
+
username: nameField.max(50).optional(),
|
|
1695
|
+
email: emailField,
|
|
1696
|
+
password: z2.string().min(8, "Password must be at least 8 characters"),
|
|
1697
|
+
roleId: optionalId,
|
|
1698
|
+
roleName: nameField.max(50).optional(),
|
|
1699
|
+
lastLogin: optionalDateField,
|
|
1700
|
+
image: z2.union([z2.string(), z2.instanceof(File), z2.undefined()]).optional(),
|
|
1701
|
+
emailVerified: z2.boolean().default(false),
|
|
1702
|
+
status: userStatusEnum,
|
|
1703
|
+
createdAt: optionalDateField
|
|
1704
|
+
});
|
|
1705
|
+
var roleSchema2 = z2.object({
|
|
1706
|
+
id: optionalId,
|
|
1707
|
+
name: nameField.max(50),
|
|
1708
|
+
description: z2.string().max(255, "Description too long").optional(),
|
|
1709
|
+
createdAt: optionalDateField
|
|
1710
|
+
});
|
|
1711
|
+
var studentSchema = z2.object({
|
|
1712
|
+
id: optionalId,
|
|
1713
|
+
classId: requiredId,
|
|
1714
|
+
sectionId: requiredId,
|
|
1715
|
+
studentCode: z2.string(),
|
|
1716
|
+
name: nameField,
|
|
1717
|
+
email: emailField,
|
|
1718
|
+
phone: phoneField.nullish(),
|
|
1719
|
+
address: addressField,
|
|
1720
|
+
dateOfBirth: optionalDateField,
|
|
1721
|
+
gender: genderEnum,
|
|
1722
|
+
enrollmentDate: dateField,
|
|
1723
|
+
medicalConditions: z2.string().max(1000, "Medical conditions description too long").nullish().optional(),
|
|
1724
|
+
previousSchool: z2.string().max(500, "Previous school name too long").optional().nullable(),
|
|
1725
|
+
image: z2.union([z2.string(), z2.instanceof(File), z2.null()]).optional(),
|
|
1726
|
+
status: studentStatusEnum.default("active")
|
|
1727
|
+
});
|
|
1728
|
+
var parentSchema = z2.object({
|
|
1729
|
+
id: optionalId,
|
|
1730
|
+
name: nameField,
|
|
1731
|
+
email: emailField.optional(),
|
|
1732
|
+
phone: phoneField,
|
|
1733
|
+
gender: genderEnum.optional(),
|
|
1734
|
+
address: addressField,
|
|
1735
|
+
dateOfBirth: optionalDateField,
|
|
1736
|
+
cin: cinField,
|
|
1737
|
+
occupation: z2.string().max(100, "Occupation too long").optional(),
|
|
1738
|
+
nationality: z2.string().max(100, "Nationality too long").optional(),
|
|
1739
|
+
maritalStatus: z2.string().max(50, "Marital status too long").optional(),
|
|
1740
|
+
relationshipType: relationshipTypeEnum,
|
|
1741
|
+
image: z2.union([z2.string(), z2.instanceof(File), z2.null()]).optional(),
|
|
1742
|
+
isEmergencyContact: z2.boolean().optional().default(false),
|
|
1743
|
+
financialResponsibility: z2.boolean().optional().default(false)
|
|
1744
|
+
});
|
|
1745
|
+
var driverSchema = z2.object({
|
|
1746
|
+
id: optionalId,
|
|
1747
|
+
name: nameField,
|
|
1748
|
+
email: emailField,
|
|
1749
|
+
cin: cinField,
|
|
1750
|
+
phone: phoneField,
|
|
1751
|
+
address: addressField,
|
|
1752
|
+
gender: genderEnum.optional(),
|
|
1753
|
+
licenseNumber: z2.string().min(5, "License number must be at least 5 characters").max(20, "License number too long"),
|
|
1754
|
+
licenseType: z2.string().max(10, "License type too long"),
|
|
1755
|
+
licenseExpiry: dateField,
|
|
1756
|
+
hireDate: dateField,
|
|
1757
|
+
salary: num().positive("Salary must be positive").optional(),
|
|
1758
|
+
yearsOfExperience: num().int().min(0, "Years of experience must be non-negative").optional(),
|
|
1759
|
+
emergencyContact: nameField.optional(),
|
|
1760
|
+
emergencyPhone: phoneField.optional(),
|
|
1761
|
+
image: z2.union([z2.string(), z2.instanceof(File), z2.null()]).optional(),
|
|
1762
|
+
status: driverStatusEnum.default("active"),
|
|
1763
|
+
notes: z2.string().max(1000, "Notes too long").optional().nullable()
|
|
1764
|
+
});
|
|
1765
|
+
var teacherPersonalSchema = z2.object({
|
|
1766
|
+
id: optionalId,
|
|
1767
|
+
name: nameField,
|
|
1768
|
+
cin: cinField,
|
|
1769
|
+
email: emailField,
|
|
1770
|
+
phone: phoneField,
|
|
1771
|
+
address: addressField,
|
|
1772
|
+
gender: genderEnum.optional(),
|
|
1773
|
+
emergencyContact: nameField.optional(),
|
|
1774
|
+
emergencyPhone: phoneField,
|
|
1775
|
+
status: teacherStatusEnum.default("active"),
|
|
1776
|
+
image: z2.union([z2.string(), z2.instanceof(File), z2.null()]).optional()
|
|
1777
|
+
});
|
|
1778
|
+
var teacherProfessionalSchema = z2.object({
|
|
1779
|
+
specialization: z2.string().max(100, "Specialization too long").optional(),
|
|
1780
|
+
yearsOfExperience: num().int().min(0, "Years of experience must be non-negative").optional(),
|
|
1781
|
+
salary: num().positive("Salary must be positive").optional(),
|
|
1782
|
+
hireDate: dateField,
|
|
1783
|
+
bankAccount: z2.coerce.string().max(100, { message: "Bank account too long" }).optional(),
|
|
1784
|
+
employmentType: employmentTypeEnum.optional(),
|
|
1785
|
+
workloadHours: num().int().min(0, "Workload hours must be non-negative").max(60, "Workload hours cannot exceed 60").optional(),
|
|
1786
|
+
academicDegrees: z2.string().max(500, "Academic degrees description too long").optional()
|
|
1787
|
+
});
|
|
1788
|
+
var assignmentSchema = z2.object({
|
|
1789
|
+
classId: z2.string().min(1, "Class is required"),
|
|
1790
|
+
sectionIds: z2.array(z2.string()).min(1, "At least one section is required"),
|
|
1791
|
+
subjectIds: z2.array(z2.string()).min(1, "At least one subject is required"),
|
|
1792
|
+
academicYear: z2.string().optional()
|
|
1793
|
+
});
|
|
1794
|
+
var assignmentsSchema = z2.object({
|
|
1795
|
+
assignments: z2.array(assignmentSchema).min(1, "At least one parent is required")
|
|
1796
|
+
});
|
|
1797
|
+
var teacherFullSchema = z2.object({
|
|
1798
|
+
...teacherPersonalSchema.shape,
|
|
1799
|
+
...teacherProfessionalSchema.shape,
|
|
1800
|
+
...assignmentsSchema.shape
|
|
1801
|
+
});
|
|
1802
|
+
var feeTypeSchema = z2.object({
|
|
1803
|
+
id: optionalId,
|
|
1804
|
+
name: z2.string().min(2, "Fee type name must be at least 2 characters").max(100, "Fee type name too long"),
|
|
1805
|
+
description: z2.string().max(500, "Description too long").optional().nullable(),
|
|
1806
|
+
category: z2.string(),
|
|
1807
|
+
amount: num().positive("Amount must be greater than 0").max(1e5, "Amount too large"),
|
|
1808
|
+
paymentType: paymentTypeEnum.default("recurring"),
|
|
1809
|
+
status: feeTypeStatusEnum.default("active").optional()
|
|
1810
|
+
});
|
|
1811
|
+
var feeSchema = z2.object({
|
|
1812
|
+
id: optionalId,
|
|
1813
|
+
studentId: requiredId,
|
|
1814
|
+
feeTypeId: requiredId,
|
|
1815
|
+
academicYear: academicYearField.optional(),
|
|
1816
|
+
status: feeStatusEnum.optional(),
|
|
1817
|
+
schedule: scheduleEnum,
|
|
1818
|
+
baseAmount: num().positive("Base amount must be positive").optional(),
|
|
1819
|
+
grossAmount: num().positive("Gross amount must be positive").optional(),
|
|
1820
|
+
netAmount: num().optional(),
|
|
1821
|
+
paidAmount: num().min(0, "Paid amount cannot be negative").optional(),
|
|
1822
|
+
discountAmount: num().min(0, "Discount cannot be negative").optional(),
|
|
1823
|
+
discountReason: z2.string().max(500, "Discount reason too long").optional().nullable(),
|
|
1824
|
+
assignedBy: optionalId.nullable(),
|
|
1825
|
+
notes: z2.string().max(1000, "Notes too long").optional().nullable()
|
|
1826
|
+
});
|
|
1827
|
+
var bulkFeeItemSchema = feeSchema.omit({ studentId: true });
|
|
1828
|
+
var bulkFeeFormSchema = z2.object({
|
|
1829
|
+
studentId: requiredId,
|
|
1830
|
+
fees: z2.array(bulkFeeItemSchema).min(1, "At least one fee is required")
|
|
1831
|
+
});
|
|
1832
|
+
var feeInstallmentSchema = z2.object({
|
|
1833
|
+
feeId: optionalId,
|
|
1834
|
+
number: num().int().min(1, "Installment must be at least 1"),
|
|
1835
|
+
dueDate: dateField,
|
|
1836
|
+
amount: num().positive("Amount must be greater than 0").max(1e5, "Amount too large"),
|
|
1837
|
+
paidAmount: num().min(0, "Paid amount cannot be negative").max(1e5, "Amount too large").optional(),
|
|
1838
|
+
status: feeInstallmentStatusEnum.optional()
|
|
1839
|
+
});
|
|
1840
|
+
var feePaymentSchema = z2.object({
|
|
1841
|
+
studentId: optionalId,
|
|
1842
|
+
amount: num().positive("Amount must be greater than 0").max(1e5, "Amount too large").optional(),
|
|
1843
|
+
paymentMethod: paymentMethodEnum,
|
|
1844
|
+
paymentDate: dateField,
|
|
1845
|
+
checkNumber: z2.preprocess((val) => val === "" ? null : val, z2.string().max(50, "Check number too long").optional().nullable()),
|
|
1846
|
+
checkDueDate: z2.preprocess((val) => val === "" ? null : val, optionalDateField.nullable()),
|
|
1847
|
+
transactionRef: z2.preprocess((val) => val === "" ? null : val, z2.string().max(100, "Transaction reference too long").optional().nullable()),
|
|
1848
|
+
receiptNumber: z2.preprocess((val) => val === "" ? null : val, z2.string().max(50, "Receipt number too long").optional().nullable()),
|
|
1849
|
+
status: paymentStatusEnum.default("completed"),
|
|
1850
|
+
processedBy: optionalId,
|
|
1851
|
+
notes: z2.preprocess((val) => val === "" ? null : val, z2.string().max(1000, "Notes too long").optional().nullable()),
|
|
1852
|
+
allocations: z2.array(z2.object({
|
|
1853
|
+
feeId: optionalId,
|
|
1854
|
+
number: z2.number().int().positive("Installment must be a positive number"),
|
|
1855
|
+
amount: num().positive("Amount must be greater than 0")
|
|
1856
|
+
})).optional().nullable()
|
|
1857
|
+
});
|
|
1858
|
+
var paymentAllocationSchema = z2.object({
|
|
1859
|
+
paymentId: z2.string().min(1, "Payment ID is required"),
|
|
1860
|
+
feeId: z2.string().min(1, "Fee ID is required"),
|
|
1861
|
+
installmentId: z2.string().optional(),
|
|
1862
|
+
amount: z2.number().positive("Amount must be positive"),
|
|
1863
|
+
type: z2.enum(["fee", "installment"]).default("installment"),
|
|
1864
|
+
notes: z2.string().optional()
|
|
1865
|
+
});
|
|
1866
|
+
var parentsSchema = z2.object({
|
|
1867
|
+
parents: z2.array(parentSchema).optional().default([])
|
|
1868
|
+
});
|
|
1869
|
+
var feesSchema = z2.object({
|
|
1870
|
+
fees: z2.array(bulkFeeItemSchema).min(1, "At least one fee is required")
|
|
1871
|
+
});
|
|
1872
|
+
var fullStudentSchema = z2.object({
|
|
1873
|
+
...studentSchema.shape,
|
|
1874
|
+
...parentsSchema.shape,
|
|
1875
|
+
...feesSchema.shape
|
|
1876
|
+
});
|
|
1877
|
+
var subjectSchema = z2.object({
|
|
1878
|
+
id: optionalId,
|
|
1879
|
+
code: z2.string().min(2, "Subject code must be at least 2 characters").max(10, "Subject code too long"),
|
|
1880
|
+
name: z2.string().min(2, "Subject name must be at least 2 characters").max(100, "Subject name too long"),
|
|
1881
|
+
description: z2.string().max(500, "Description too long").optional(),
|
|
1882
|
+
gradeLevel: num().int().min(1).max(12).optional()
|
|
1883
|
+
});
|
|
1884
|
+
var sectionSchema = z2.object({
|
|
1885
|
+
id: optionalId,
|
|
1886
|
+
classId: requiredId,
|
|
1887
|
+
name: z2.string().min(1, "Section name is required").max(10, "Section name too long"),
|
|
1888
|
+
maxStudents: num().int().min(1, "Max students must be at least 1").max(100, "Max students cannot exceed 100").default(30),
|
|
1889
|
+
roomNumber: num().max(1e4, "Room number too long").optional(),
|
|
1890
|
+
status: sectionStatusEnum.default("active")
|
|
1891
|
+
});
|
|
1892
|
+
var classSchema = z2.object({
|
|
1893
|
+
id: optionalId,
|
|
1894
|
+
name: z2.string().min(1, "Class name is required").max(50, "Class name too long"),
|
|
1895
|
+
description: z2.string().max(500, "Description too long").optional(),
|
|
1896
|
+
academicYear: academicYearField,
|
|
1897
|
+
level: z2.string().min(1, "Class level is required")
|
|
1898
|
+
});
|
|
1899
|
+
var attendanceSchema = z2.object({
|
|
1900
|
+
studentId: requiredId,
|
|
1901
|
+
teacherId: requiredId,
|
|
1902
|
+
subjectId: requiredId,
|
|
1903
|
+
sectionId: requiredId,
|
|
1904
|
+
date: dateField,
|
|
1905
|
+
status: attendanceStatusEnum.default("present"),
|
|
1906
|
+
notes: z2.string().max(500, "Notes too long").optional()
|
|
1907
|
+
});
|
|
1908
|
+
var assessmentSchema = z2.object({
|
|
1909
|
+
classId: requiredId,
|
|
1910
|
+
sectionId: requiredId,
|
|
1911
|
+
subjectId: requiredId,
|
|
1912
|
+
teacherId: requiredId,
|
|
1913
|
+
teacherAssignmentId: optionalId,
|
|
1914
|
+
title: z2.string().min(3, "Title must be at least 3 characters").max(200, "Title too long"),
|
|
1915
|
+
description: z2.string().max(1000, "Description too long").optional().nullable(),
|
|
1916
|
+
type: assessmentTypeEnum.default("quiz"),
|
|
1917
|
+
date: dateField,
|
|
1918
|
+
duration: num().int().min(1, "Duration must be at least 1 minute").max(480, "Duration cannot exceed 8 hours"),
|
|
1919
|
+
totalMarks: num().positive("Total marks must be greater than 0").max(1000, "Total marks cannot exceed 1000"),
|
|
1920
|
+
passingMarks: num().min(0, "Passing marks must be non-negative").max(1000, "Passing marks cannot exceed 1000"),
|
|
1921
|
+
instructions: z2.string().max(2000, "Instructions too long").optional().nullable(),
|
|
1922
|
+
status: assessmentStatusEnum.default("scheduled"),
|
|
1923
|
+
assessmentId: optionalId
|
|
1924
|
+
});
|
|
1925
|
+
var bulkAssessmentSchema = z2.object({
|
|
1926
|
+
assessments: z2.array(assessmentSchema).min(1, "At least one assessment is required").max(50, "Cannot create more than 50 assessments at once")
|
|
1927
|
+
});
|
|
1928
|
+
var gradeSchema = z2.object({
|
|
1929
|
+
assessmentId: requiredId,
|
|
1930
|
+
teacherId: requiredId,
|
|
1931
|
+
subjectId: requiredId,
|
|
1932
|
+
sectionId: requiredId,
|
|
1933
|
+
studentId: requiredId,
|
|
1934
|
+
gradeId: requiredId,
|
|
1935
|
+
assessmentTitle: z2.string().min(3, "Assessment title must be at least 3 characters").max(200, "Assessment title too long").optional(),
|
|
1936
|
+
marksObtained: num().min(0, "Marks obtained must be non-negative").max(1000, "Marks obtained cannot exceed 1000"),
|
|
1937
|
+
feedback: z2.string().max(1000, "Feedback too long").optional().nullable(),
|
|
1938
|
+
status: gradeStatusEnum.default("graded")
|
|
1939
|
+
});
|
|
1940
|
+
var examSchema = z2.object({
|
|
1941
|
+
classId: optionalId,
|
|
1942
|
+
sectionId: requiredId,
|
|
1943
|
+
subjectId: requiredId,
|
|
1944
|
+
teacherId: requiredId,
|
|
1945
|
+
examId: requiredId,
|
|
1946
|
+
teacherAssignmentId: requiredId,
|
|
1947
|
+
title: z2.string().min(3, "Title must be at least 3 characters").max(200, "Title too long"),
|
|
1948
|
+
description: z2.string().max(1000, "Description too long").optional().nullable(),
|
|
1949
|
+
type: examTypeEnum.default("midterm"),
|
|
1950
|
+
date: dateField,
|
|
1951
|
+
startTime: timeField,
|
|
1952
|
+
endTime: timeField,
|
|
1953
|
+
duration: num().int().min(30, "Exam duration must be at least 30 minutes").max(480, "Duration cannot exceed 8 hours"),
|
|
1954
|
+
totalMarks: num().positive("Total marks must be greater than 0").max(1000, "Total marks cannot exceed 1000"),
|
|
1955
|
+
passingMarks: num().min(0, "Passing marks must be non-negative").max(1000, "Passing marks cannot exceed 1000"),
|
|
1956
|
+
roomNumber: num().max(50, "Room number too long").optional().nullable(),
|
|
1957
|
+
allowedMaterials: z2.string().max(500, "Allowed materials description too long").optional().nullable(),
|
|
1958
|
+
instructions: z2.string().max(2000, "Instructions too long").optional().nullable(),
|
|
1959
|
+
status: examStatusEnum.default("scheduled")
|
|
1960
|
+
});
|
|
1961
|
+
var announcementSchema = z2.object({
|
|
1962
|
+
title: z2.string().min(3, "Title must be at least 3 characters").max(200, "Title too long"),
|
|
1963
|
+
content: z2.string().min(10, "Content must be at least 10 characters").max(5000, "Content too long"),
|
|
1964
|
+
authorId: optionalId,
|
|
1965
|
+
targetAudience: z2.enum(["all", "students", "teachers", "parents", "class"]),
|
|
1966
|
+
classId: optionalId,
|
|
1967
|
+
isPublished: z2.boolean().default(false),
|
|
1968
|
+
publishDate: z2.string().datetime("Invalid publish date").optional(),
|
|
1969
|
+
expiryDate: z2.string().datetime("Invalid expiry date").optional()
|
|
1970
|
+
});
|
|
1971
|
+
var alertSchema = z2.object({
|
|
1972
|
+
type: alertTypeEnum,
|
|
1973
|
+
title: z2.string().min(3, "Title must be at least 3 characters").max(200, "Title too long"),
|
|
1974
|
+
message: z2.string().min(10, "Message must be at least 10 characters").max(2000, "Message too long"),
|
|
1975
|
+
priority: alertPriorityEnum.default("medium"),
|
|
1976
|
+
status: alertStatusEnum.default("active"),
|
|
1977
|
+
studentId: optionalId,
|
|
1978
|
+
teacherId: optionalId,
|
|
1979
|
+
classId: optionalId,
|
|
1980
|
+
subjectId: optionalId,
|
|
1981
|
+
targetAudience: z2.enum(["all", "students", "teachers", "parents"]).optional(),
|
|
1982
|
+
authorId: optionalId,
|
|
1983
|
+
isRead: z2.boolean().default(false)
|
|
1984
|
+
});
|
|
1985
|
+
var eventSchema = z2.object({
|
|
1986
|
+
title: z2.string().min(3, "Title must be at least 3 characters").max(200, "Title too long"),
|
|
1987
|
+
description: z2.string().max(5000, "Description too long").optional().nullable(),
|
|
1988
|
+
type: eventTypeEnum,
|
|
1989
|
+
startDate: dateField,
|
|
1990
|
+
endDate: dateField,
|
|
1991
|
+
startTime: timeField,
|
|
1992
|
+
endTime: timeField,
|
|
1993
|
+
location: z2.string().max(200, "Location too long").optional().nullable(),
|
|
1994
|
+
venue: z2.string().max(200, "Venue too long").optional().nullable(),
|
|
1995
|
+
organizerId: optionalId,
|
|
1996
|
+
classId: optionalId.nullable(),
|
|
1997
|
+
sectionId: optionalId.nullable(),
|
|
1998
|
+
visibility: eventVisibilityEnum.default("public"),
|
|
1999
|
+
status: eventStatusEnum.default("scheduled"),
|
|
2000
|
+
capacity: num().int().positive("Capacity must be positive").optional().nullable(),
|
|
2001
|
+
registrationRequired: z2.boolean().default(false),
|
|
2002
|
+
registrationDeadline: optionalDateField.nullable(),
|
|
2003
|
+
attachments: z2.any().optional().nullable(),
|
|
2004
|
+
notes: z2.string().max(2000, "Notes too long").optional().nullable()
|
|
2005
|
+
});
|
|
2006
|
+
var eventParticipantSchema = z2.object({
|
|
2007
|
+
eventId: optionalId,
|
|
2008
|
+
participantId: optionalId,
|
|
2009
|
+
participantType: participantTypeEnum,
|
|
2010
|
+
attendanceStatus: attendanceStatusEnum.optional().nullable(),
|
|
2011
|
+
notes: z2.string().max(500, "Notes too long").optional().nullable()
|
|
2012
|
+
});
|
|
2013
|
+
var expenseSchema = z2.object({
|
|
2014
|
+
id: optionalId,
|
|
2015
|
+
category: expenseCategoryEnum,
|
|
2016
|
+
title: z2.string().min(3, "Title must be at least 3 characters").max(200, "Title too long"),
|
|
2017
|
+
amount: num().positive("Amount must be greater than 0").max(1e7, "Amount too large"),
|
|
2018
|
+
expenseDate: dateField,
|
|
2019
|
+
paymentMethod: paymentMethodEnum.optional().nullable(),
|
|
2020
|
+
paymentDate: optionalDateField.nullable(),
|
|
2021
|
+
vendor: z2.string().max(200, "Vendor name too long").optional().nullable(),
|
|
2022
|
+
invoiceNumber: z2.string().max(100, "Invoice number too long").optional().nullable(),
|
|
2023
|
+
receiptNumber: z2.string().max(100, "Receipt number too long").optional().nullable(),
|
|
2024
|
+
checkNumber: z2.string().max(50, "Check number too long").optional().nullable(),
|
|
2025
|
+
transactionRef: z2.string().max(100, "Transaction reference too long").optional().nullable(),
|
|
2026
|
+
status: expenseStatusEnum.default("pending"),
|
|
2027
|
+
notes: z2.string().max(1000, "Notes too long").optional().nullable()
|
|
2028
|
+
});
|
|
2029
|
+
var expenseApprovalSchema = z2.object({
|
|
2030
|
+
action: z2.enum(["approve", "reject"]),
|
|
2031
|
+
rejectionReason: z2.string().min(10, "Rejection reason must be at least 10 characters").max(1000, "Rejection reason too long").optional().nullable()
|
|
2032
|
+
});
|
|
2033
|
+
var expensePaymentSchema = z2.object({
|
|
2034
|
+
paymentMethod: paymentMethodEnum,
|
|
2035
|
+
paymentDate: dateField,
|
|
2036
|
+
checkNumber: z2.string().max(50, "Check number too long").optional().nullable(),
|
|
2037
|
+
transactionRef: z2.string().max(100, "Transaction reference too long").optional().nullable(),
|
|
2038
|
+
notes: z2.string().max(1000, "Notes too long").optional().nullable()
|
|
2039
|
+
});
|
|
2040
|
+
var vehicleSchema = z2.object({
|
|
2041
|
+
id: optionalId,
|
|
2042
|
+
name: z2.string().min(2, "Vehicle name must be at least 2 characters").max(100, "Vehicle name too long"),
|
|
2043
|
+
brand: z2.string().min(2, "Brand must be at least 2 characters").max(100, "Brand too long"),
|
|
2044
|
+
model: z2.string().min(2, "Model must be at least 2 characters").max(100, "Model too long"),
|
|
2045
|
+
year: num().int().min(1900, "Year must be after 1900").max(new Date().getFullYear() + 1, "Year cannot be in future"),
|
|
2046
|
+
type: vehicleTypeEnum.default("fullbus"),
|
|
2047
|
+
capacity: num().int().min(1, "Capacity must be at least 1").max(200, "Capacity cannot exceed 200"),
|
|
2048
|
+
licensePlate: z2.string().min(2, "License plate must be at least 2 characters").max(50, "License plate too long"),
|
|
2049
|
+
driverId: optionalId.nullable(),
|
|
2050
|
+
image: z2.string().max(500, "Image path too long").optional().nullable().default("novehicle.png"),
|
|
2051
|
+
purchaseDate: optionalDateField.nullable(),
|
|
2052
|
+
purchasePrice: num().min(0, "Purchase price must be non-negative").max(1e7, "Purchase price too large").optional().nullable(),
|
|
2053
|
+
initialMileage: num().min(0, "Initial mileage must be non-negative").max(1e7, "Initial mileage too large").optional().nullable(),
|
|
2054
|
+
currentMileage: num().min(0, "Current mileage must be non-negative").max(1e7, "Current mileage too large").optional().nullable(),
|
|
2055
|
+
status: vehicleStatusEnum.default("active"),
|
|
2056
|
+
notes: z2.string().max(1000, "Notes too long").optional().nullable()
|
|
2057
|
+
});
|
|
2058
|
+
var refuelSchema = z2.object({
|
|
2059
|
+
id: optionalId,
|
|
2060
|
+
busId: optionalId,
|
|
2061
|
+
refuelDate: dateField,
|
|
2062
|
+
quantity: num().positive("Quantity must be greater than 0").max(1e4, "Quantity too large"),
|
|
2063
|
+
unitPrice: num().positive("Unit price must be greater than 0").max(1e5, "Unit price too large"),
|
|
2064
|
+
totalCost: num().positive("Total cost must be greater than 0").max(1e7, "Total cost too large").optional(),
|
|
2065
|
+
fuelType: fuelTypeEnum.default("diesel"),
|
|
2066
|
+
odometer: num().min(0, "Odometer must be non-negative").max(1e7, "Odometer value too large").optional().nullable(),
|
|
2067
|
+
fuelStation: z2.string().max(200, "Fuel station name too long").optional().nullable(),
|
|
2068
|
+
invoiceNumber: z2.string().max(100, "Invoice number too long").optional().nullable(),
|
|
2069
|
+
paymentMethod: paymentMethodEnum.optional().nullable(),
|
|
2070
|
+
paidBy: optionalId.nullable(),
|
|
2071
|
+
status: refuelStatusEnum.default("completed"),
|
|
2072
|
+
notes: z2.string().max(1000, "Notes too long").optional().nullable()
|
|
2073
|
+
});
|
|
2074
|
+
var settingsSchema = z2.object({
|
|
2075
|
+
schoolName: z2.string().min(2, "School name must be at least 2 characters").max(200, "School name too long"),
|
|
2076
|
+
schoolAddress: z2.string().max(500, "School address too long").optional(),
|
|
2077
|
+
schoolPhone: phoneField,
|
|
2078
|
+
schoolEmail: emailField,
|
|
2079
|
+
schoolWebsite: z2.string().url("Must be a valid URL").max(255, "School website URL too long").optional(),
|
|
2080
|
+
schoolLogo: z2.string().url("Must be a valid image URL").max(255, "School logo URL too long").optional(),
|
|
2081
|
+
currentAcademicYear: academicYearField,
|
|
2082
|
+
gradingScale: z2.any().optional(),
|
|
2083
|
+
attendanceRequirement: num().min(0, "Attendance requirement must be non-negative").max(100, "Attendance requirement cannot exceed 100").default(75),
|
|
2084
|
+
maxClassSize: num().int("Max class size must be an integer").min(1, "Max class size must be at least 1").max(200, "Max class size cannot exceed 200").default(34),
|
|
2085
|
+
minimumPassingGrade: num().min(0, "Minimum passing grade must be non-negative").max(100, "Minimum passing grade cannot exceed 100").default(60),
|
|
2086
|
+
defaultExamDuration: num().int("Default exam duration must be in minutes").min(15, "Exam duration must be at least 15 minutes").max(480, "Exam duration cannot exceed 480 minutes").default(120),
|
|
2087
|
+
calendarSystem: calendarSystemEnum.default("SEMESTER"),
|
|
2088
|
+
startMonth: z2.string().default("september"),
|
|
2089
|
+
endMonth: z2.string().default("june"),
|
|
2090
|
+
academicAlerts: z2.boolean().default(true),
|
|
2091
|
+
attendanceAlerts: z2.boolean().default(true),
|
|
2092
|
+
eventAlerts: z2.boolean().default(true),
|
|
2093
|
+
homeworkAlerts: z2.boolean().default(true),
|
|
2094
|
+
feesReminder: z2.boolean().default(true),
|
|
2095
|
+
feesOverdueAlerts: z2.boolean().default(true),
|
|
2096
|
+
emailNotifications: z2.boolean().default(true),
|
|
2097
|
+
smsNotifications: z2.boolean().default(false),
|
|
2098
|
+
parentNotifications: z2.boolean().default(true),
|
|
2099
|
+
lowGradeAlerts: z2.boolean().default(true),
|
|
2100
|
+
allowLateSubmission: z2.boolean().default(true),
|
|
2101
|
+
examResultsAlerts: z2.boolean().default(true),
|
|
2102
|
+
disciplinaryAlerts: z2.boolean().default(true),
|
|
2103
|
+
achievementAlerts: z2.boolean().default(true),
|
|
2104
|
+
maintenanceNotifications: z2.boolean().default(true),
|
|
2105
|
+
twoFactorEnabled: z2.boolean().default(false),
|
|
2106
|
+
sessionTimeout: z2.string().regex(/^\d{1,4}$/, "Session timeout must be a number between 1-9999 minutes").default("60"),
|
|
2107
|
+
passwordRequireSymbols: z2.boolean().default(true),
|
|
2108
|
+
loginNotifications: z2.boolean().default(true),
|
|
2109
|
+
parentAccessEnabled: z2.boolean().default(true),
|
|
2110
|
+
teacherAccessEnabled: z2.boolean().default(true),
|
|
2111
|
+
studentAccessEnabled: z2.boolean().default(true),
|
|
2112
|
+
timeZone: z2.string().min(1, "Time zone is required").default("UTC"),
|
|
2113
|
+
language: languageEnum.default("en"),
|
|
2114
|
+
theme: z2.enum(["light", "dark", "system"]).default("system"),
|
|
2115
|
+
dateFormat: z2.enum(["YYYY-MM-DD", "MM/DD/YYYY", "DD/MM/YYYY", "DD-MM-YY", "DD-MM-YYYY"]).default("MM/DD/YYYY"),
|
|
2116
|
+
timeFormat: z2.enum(["12", "24"]).default("12"),
|
|
2117
|
+
currency: z2.string().length(3, "Currency must be a 3-letter ISO code").regex(/^[A-Z]{3}$/, "Currency must be uppercase ISO code").default("USD"),
|
|
2118
|
+
gradingPeriods: num().int("Grading periods must be an integer").min(1, "Grading periods must be at least 1").max(12, "Grading periods cannot exceed 12").default(4),
|
|
2119
|
+
schoolStartTime: z2.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, "Invalid start time format (HH:MM)").default("08:00"),
|
|
2120
|
+
schoolEndTime: z2.string().regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, "Invalid end time format (HH:MM)").default("15:00"),
|
|
2121
|
+
lunchBreakDuration: num().int("Lunch break duration must be in minutes").min(15, "Lunch break must be at least 15 minutes").max(120, "Lunch break cannot exceed 120 minutes").default(30),
|
|
2122
|
+
maintenanceMode: z2.boolean().default(false),
|
|
2123
|
+
autoBackup: z2.boolean().default(true)
|
|
2124
|
+
});
|
|
2125
|
+
var idParamSchema = z2.object({
|
|
2126
|
+
id: optionalId
|
|
2127
|
+
});
|
|
2128
|
+
var paginationSchema = z2.object({
|
|
2129
|
+
page: num().int().min(1).default(1),
|
|
2130
|
+
limit: num().int().min(1).max(100).default(10)
|
|
2131
|
+
});
|
|
2132
|
+
var dateRangeSchema = z2.object({
|
|
2133
|
+
dateFrom: dateField,
|
|
2134
|
+
dateTo: dateField
|
|
2135
|
+
});
|
|
2136
|
+
// src/permissions/PermissionRepository.ts
|
|
2137
|
+
import { permissionsTable as permissionsTable3, rolePermissionsTable as rolePermissionsTable3, rolesTable as rolesTable4 } from "@/database/schema";
|
|
2138
|
+
import { eq as eq4, and } from "drizzle-orm";
|
|
2139
|
+
import { Repository as Repository4 } from "najm-api";
|
|
2140
|
+
class PermissionRepository {
|
|
2141
|
+
async getAll() {
|
|
2142
|
+
return await this.db.select().from(permissionsTable3);
|
|
2143
|
+
}
|
|
2144
|
+
async getById(id) {
|
|
2145
|
+
const [existingPermission] = await this.db.select().from(permissionsTable3).where(eq4(permissionsTable3.id, id));
|
|
2146
|
+
return existingPermission;
|
|
2147
|
+
}
|
|
2148
|
+
async getByName(name) {
|
|
2149
|
+
const [existingPermission] = await this.db.select().from(permissionsTable3).where(eq4(permissionsTable3.name, name));
|
|
2150
|
+
return existingPermission;
|
|
2151
|
+
}
|
|
2152
|
+
async create(data) {
|
|
2153
|
+
const [newPermission] = await this.db.insert(permissionsTable3).values(data).returning();
|
|
2154
|
+
return newPermission;
|
|
2155
|
+
}
|
|
2156
|
+
async update(id, data) {
|
|
2157
|
+
const [updatedPermission] = await this.db.update(permissionsTable3).set(data).where(eq4(permissionsTable3.id, id)).returning();
|
|
2158
|
+
return updatedPermission;
|
|
2159
|
+
}
|
|
2160
|
+
async delete(id) {
|
|
2161
|
+
const [deletedPermission] = await this.db.delete(permissionsTable3).where(eq4(permissionsTable3.id, id)).returning();
|
|
2162
|
+
return deletedPermission;
|
|
2163
|
+
}
|
|
2164
|
+
async getPermissionsByRole(roleId) {
|
|
2165
|
+
return await this.db.select({
|
|
2166
|
+
id: permissionsTable3.id,
|
|
2167
|
+
name: permissionsTable3.name,
|
|
2168
|
+
description: permissionsTable3.description,
|
|
2169
|
+
resource: permissionsTable3.resource,
|
|
2170
|
+
action: permissionsTable3.action
|
|
2171
|
+
}).from(rolePermissionsTable3).leftJoin(permissionsTable3, eq4(rolePermissionsTable3.permissionId, permissionsTable3.id)).where(eq4(rolePermissionsTable3.roleId, roleId));
|
|
2172
|
+
}
|
|
2173
|
+
async getRolesByPermission(permissionId) {
|
|
2174
|
+
return await this.db.select({
|
|
2175
|
+
id: rolesTable4.id,
|
|
2176
|
+
name: rolesTable4.name,
|
|
2177
|
+
description: rolesTable4.description
|
|
2178
|
+
}).from(rolePermissionsTable3).leftJoin(rolesTable4, eq4(rolePermissionsTable3.roleId, rolesTable4.id)).where(eq4(rolePermissionsTable3.permissionId, permissionId));
|
|
2179
|
+
}
|
|
2180
|
+
async assignPermissionToRole(roleId, permissionId) {
|
|
2181
|
+
const [newRolePermission] = await this.db.insert(rolePermissionsTable3).values({ roleId, permissionId }).returning();
|
|
2182
|
+
return newRolePermission;
|
|
2183
|
+
}
|
|
2184
|
+
async removePermissionFromRole(roleId, permissionId) {
|
|
2185
|
+
const [deletedRolePermission] = await this.db.delete(rolePermissionsTable3).where(and(eq4(rolePermissionsTable3.roleId, roleId), eq4(rolePermissionsTable3.permissionId, permissionId))).returning();
|
|
2186
|
+
return deletedRolePermission;
|
|
2187
|
+
}
|
|
2188
|
+
async checkRoleHasPermission(roleId, permissionId) {
|
|
2189
|
+
const [rolePermission] = await this.db.select().from(rolePermissionsTable3).where(and(eq4(rolePermissionsTable3.roleId, roleId), eq4(rolePermissionsTable3.permissionId, permissionId)));
|
|
2190
|
+
return !!rolePermission;
|
|
2191
|
+
}
|
|
2192
|
+
async deleteAll() {
|
|
2193
|
+
await this.db.delete(rolePermissionsTable3);
|
|
2194
|
+
const deletedPermissions = await this.db.delete(permissionsTable3).returning();
|
|
2195
|
+
return deletedPermissions;
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
PermissionRepository = __legacyDecorateClassTS([
|
|
2199
|
+
Repository4()
|
|
2200
|
+
], PermissionRepository);
|
|
2201
|
+
// src/permissions/PermissionGuards.ts
|
|
2202
|
+
import { createGuard as createGuard2, Injectable as Injectable10, GuardParams as GuardParams2, Headers as Headers3, Ctx as Ctx3 } from "najm-api";
|
|
2203
|
+
class PermissionGuards {
|
|
2204
|
+
tokenService;
|
|
2205
|
+
constructor(tokenService) {
|
|
2206
|
+
this.tokenService = tokenService;
|
|
2207
|
+
}
|
|
2208
|
+
async getUserPermissions(auth) {
|
|
2209
|
+
const permissions = await this.tokenService.getUserPermissions(auth);
|
|
2210
|
+
if (!permissions || !Array.isArray(permissions))
|
|
2211
|
+
return null;
|
|
2212
|
+
return permissions;
|
|
2213
|
+
}
|
|
2214
|
+
checkPermissionMatch(permissions, requiredPermission) {
|
|
2215
|
+
if (permissions.includes(requiredPermission)) {
|
|
2216
|
+
return true;
|
|
2217
|
+
}
|
|
2218
|
+
const [requiredAction, requiredResource] = requiredPermission.split(":");
|
|
2219
|
+
if (requiredAction && requiredResource) {
|
|
2220
|
+
if (permissions.includes(`${requiredAction}:*`)) {
|
|
2221
|
+
return true;
|
|
2222
|
+
}
|
|
2223
|
+
if (permissions.includes(`*:${requiredResource}`)) {
|
|
2224
|
+
return true;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
if (permissions.includes("*:*")) {
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
return false;
|
|
2231
|
+
}
|
|
2232
|
+
async hasPermission(auth, ctx, requiredPermission) {
|
|
2233
|
+
await this.tokenService.storeUserInCache(auth, ctx);
|
|
2234
|
+
const permissions = await this.getUserPermissions(auth);
|
|
2235
|
+
if (!permissions)
|
|
2236
|
+
return false;
|
|
2237
|
+
const check = this.checkPermissionMatch(permissions, requiredPermission);
|
|
2238
|
+
return check;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
__legacyDecorateClassTS([
|
|
2242
|
+
__legacyDecorateParamTS(0, Headers3("authorization")),
|
|
2243
|
+
__legacyDecorateParamTS(1, Ctx3()),
|
|
2244
|
+
__legacyDecorateParamTS(2, GuardParams2()),
|
|
2245
|
+
__legacyMetadataTS("design:type", Function),
|
|
2246
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2247
|
+
Object,
|
|
2248
|
+
Object,
|
|
2249
|
+
Object
|
|
2250
|
+
]),
|
|
2251
|
+
__legacyMetadataTS("design:returntype", Object)
|
|
2252
|
+
], PermissionGuards.prototype, "hasPermission", null);
|
|
2253
|
+
PermissionGuards = __legacyDecorateClassTS([
|
|
2254
|
+
Injectable10(),
|
|
2255
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2256
|
+
typeof TokenService === "undefined" ? Object : TokenService
|
|
2257
|
+
])
|
|
2258
|
+
], PermissionGuards);
|
|
2259
|
+
var Permission = (...permissions) => createGuard2(PermissionGuards, "hasPermission")(...permissions);
|
|
2260
|
+
// src/permissions/PermissionController.ts
|
|
2261
|
+
import { Controller as Controller4, Get as Get4, Post as Post4, Put as Put3, Delete as Delete3, Params as Params4, Body as Body4, t as t9 } from "najm-api";
|
|
2262
|
+
|
|
2263
|
+
// src/permissions/PermissionService.ts
|
|
2264
|
+
import { Injectable as Injectable12 } from "najm-api";
|
|
2265
|
+
|
|
2266
|
+
// src/permissions/PermissionValidator.ts
|
|
2267
|
+
import { Injectable as Injectable11, t as t8 } from "najm-api";
|
|
2268
|
+
import { parseSchema as parseSchema3 } from "@/shared";
|
|
2269
|
+
import { z as z3 } from "zod";
|
|
2270
|
+
var permissionSchema = z3.object({
|
|
2271
|
+
name: z3.string().min(1, "Permission name is required"),
|
|
2272
|
+
description: z3.string().optional(),
|
|
2273
|
+
resource: z3.string().min(1, "Resource is required"),
|
|
2274
|
+
action: z3.string().min(1, "Action is required")
|
|
2275
|
+
});
|
|
2276
|
+
|
|
2277
|
+
class PermissionValidator {
|
|
2278
|
+
permissionRepository;
|
|
2279
|
+
roleValidator;
|
|
2280
|
+
constructor(permissionRepository, roleValidator) {
|
|
2281
|
+
this.permissionRepository = permissionRepository;
|
|
2282
|
+
this.roleValidator = roleValidator;
|
|
2283
|
+
}
|
|
2284
|
+
async validateCreatePermission(data) {
|
|
2285
|
+
return parseSchema3(permissionSchema, data);
|
|
2286
|
+
}
|
|
2287
|
+
async isPermissionExists(id) {
|
|
2288
|
+
const existingPermission = await this.permissionRepository.getById(id);
|
|
2289
|
+
return !!existingPermission;
|
|
2290
|
+
}
|
|
2291
|
+
async isPermissionNameExists(name) {
|
|
2292
|
+
const existingPermission = await this.permissionRepository.getByName(name);
|
|
2293
|
+
return !!existingPermission;
|
|
2294
|
+
}
|
|
2295
|
+
async checkPermissionExists(id) {
|
|
2296
|
+
const permissionExists = await this.isPermissionExists(id);
|
|
2297
|
+
if (!permissionExists) {
|
|
2298
|
+
throw new Error(t8("permissions.errors.notFound"));
|
|
2299
|
+
}
|
|
2300
|
+
return permissionExists;
|
|
2301
|
+
}
|
|
2302
|
+
async checkPermissionExistsByName(name) {
|
|
2303
|
+
const permissionExists = await this.isPermissionNameExists(name);
|
|
2304
|
+
if (!permissionExists) {
|
|
2305
|
+
throw new Error(t8("permissions.errors.notFound"));
|
|
2306
|
+
}
|
|
2307
|
+
return permissionExists;
|
|
2308
|
+
}
|
|
2309
|
+
async checkPermissionNameUnique(name, excludeId = null) {
|
|
2310
|
+
if (!name)
|
|
2311
|
+
return;
|
|
2312
|
+
const existingPermission = await this.permissionRepository.getByName(name);
|
|
2313
|
+
if (existingPermission && existingPermission.id !== excludeId) {
|
|
2314
|
+
throw new Error(t8("permissions.errors.nameExists"));
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
async checkRoleExists(id) {
|
|
2318
|
+
return await this.roleValidator.checkRoleExists(id);
|
|
2319
|
+
}
|
|
2320
|
+
async checkRoleExistsByName(name) {
|
|
2321
|
+
return await this.roleValidator.checkRoleExistsByName(name);
|
|
2322
|
+
}
|
|
2323
|
+
async checkRoleHasPermission(roleId, permissionId) {
|
|
2324
|
+
await this.roleValidator.checkRoleExists(roleId);
|
|
2325
|
+
await this.checkPermissionExists(permissionId);
|
|
2326
|
+
const hasPermission = await this.permissionRepository.checkRoleHasPermission(roleId, permissionId);
|
|
2327
|
+
if (hasPermission) {
|
|
2328
|
+
throw new Error(t8("permissions.errors.roleAlreadyHasPermission"));
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
PermissionValidator = __legacyDecorateClassTS([
|
|
2333
|
+
Injectable11(),
|
|
2334
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2335
|
+
typeof PermissionRepository === "undefined" ? Object : PermissionRepository,
|
|
2336
|
+
typeof RoleValidator === "undefined" ? Object : RoleValidator
|
|
2337
|
+
])
|
|
2338
|
+
], PermissionValidator);
|
|
2339
|
+
|
|
2340
|
+
// src/permissions/PermissionService.ts
|
|
2341
|
+
class PermissionService {
|
|
2342
|
+
permissionRepository;
|
|
2343
|
+
permissionValidator;
|
|
2344
|
+
roleService;
|
|
2345
|
+
constructor(permissionRepository, permissionValidator, roleService) {
|
|
2346
|
+
this.permissionRepository = permissionRepository;
|
|
2347
|
+
this.permissionValidator = permissionValidator;
|
|
2348
|
+
this.roleService = roleService;
|
|
2349
|
+
}
|
|
2350
|
+
async getAll() {
|
|
2351
|
+
return await this.permissionRepository.getAll();
|
|
2352
|
+
}
|
|
2353
|
+
async getById(id) {
|
|
2354
|
+
await this.permissionValidator.checkPermissionExists(id);
|
|
2355
|
+
return await this.permissionRepository.getById(id);
|
|
2356
|
+
}
|
|
2357
|
+
async getByName(name) {
|
|
2358
|
+
return await this.permissionRepository.getByName(name);
|
|
2359
|
+
}
|
|
2360
|
+
async getByResource(resource) {
|
|
2361
|
+
return await this.permissionRepository.getAll().then((permissions) => permissions.filter((p) => p.resource === resource));
|
|
2362
|
+
}
|
|
2363
|
+
async create(data) {
|
|
2364
|
+
await this.permissionValidator.validateCreatePermission(data);
|
|
2365
|
+
await this.permissionValidator.checkPermissionNameUnique(data.name);
|
|
2366
|
+
return await this.permissionRepository.create(data);
|
|
2367
|
+
}
|
|
2368
|
+
async update(id, data) {
|
|
2369
|
+
await this.permissionValidator.checkPermissionExists(id);
|
|
2370
|
+
await this.permissionValidator.checkPermissionNameUnique(data.name, id);
|
|
2371
|
+
return await this.permissionRepository.update(id, data);
|
|
2372
|
+
}
|
|
2373
|
+
async delete(id) {
|
|
2374
|
+
await this.permissionValidator.checkPermissionExists(id);
|
|
2375
|
+
return await this.permissionRepository.delete(id);
|
|
2376
|
+
}
|
|
2377
|
+
async getPermissionsByRole(roleId) {
|
|
2378
|
+
return await this.permissionRepository.getPermissionsByRole(roleId);
|
|
2379
|
+
}
|
|
2380
|
+
async getRolesByPermission(permissionId) {
|
|
2381
|
+
await this.permissionValidator.checkPermissionExists(permissionId);
|
|
2382
|
+
return await this.permissionRepository.getRolesByPermission(permissionId);
|
|
2383
|
+
}
|
|
2384
|
+
async assignPermissionToRole(roleId, permissionId) {
|
|
2385
|
+
await this.permissionValidator.checkRoleHasPermission(roleId, permissionId);
|
|
2386
|
+
return await this.permissionRepository.assignPermissionToRole(roleId, permissionId);
|
|
2387
|
+
}
|
|
2388
|
+
async removePermissionFromRole(roleId, permissionId) {
|
|
2389
|
+
return await this.permissionRepository.removePermissionFromRole(roleId, permissionId);
|
|
2390
|
+
}
|
|
2391
|
+
async seedDefaultPermissions(defaultPermissions) {
|
|
2392
|
+
const createdPermissions = [];
|
|
2393
|
+
for (const permission of defaultPermissions) {
|
|
2394
|
+
try {
|
|
2395
|
+
const permissionEntity = await this.create(permission);
|
|
2396
|
+
createdPermissions.push(permissionEntity);
|
|
2397
|
+
} catch (error) {
|
|
2398
|
+
continue;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
return createdPermissions;
|
|
2402
|
+
}
|
|
2403
|
+
async seedDefaultRolePermissions(defaultRolePermissions) {
|
|
2404
|
+
const results = [];
|
|
2405
|
+
for (const { roleName, permissions } of defaultRolePermissions) {
|
|
2406
|
+
try {
|
|
2407
|
+
await this.permissionValidator.checkRoleExistsByName(roleName);
|
|
2408
|
+
const role = await this.roleService.getByName(roleName);
|
|
2409
|
+
for (const permissionName of permissions) {
|
|
2410
|
+
try {
|
|
2411
|
+
await this.permissionValidator.checkPermissionExistsByName(permissionName);
|
|
2412
|
+
const permission = await this.getByName(permissionName);
|
|
2413
|
+
await this.permissionValidator.checkRoleHasPermission(role.id, permission.id);
|
|
2414
|
+
await this.assignPermissionToRole(role.id, permission.id);
|
|
2415
|
+
results.push({ role: roleName, permission: permissionName });
|
|
2416
|
+
} catch (error) {
|
|
2417
|
+
continue;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
} catch (error) {
|
|
2421
|
+
continue;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
return results;
|
|
2425
|
+
}
|
|
2426
|
+
async deleteAll() {
|
|
2427
|
+
return await this.permissionRepository.deleteAll();
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
PermissionService = __legacyDecorateClassTS([
|
|
2431
|
+
Injectable12(),
|
|
2432
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2433
|
+
typeof PermissionRepository === "undefined" ? Object : PermissionRepository,
|
|
2434
|
+
typeof PermissionValidator === "undefined" ? Object : PermissionValidator,
|
|
2435
|
+
typeof RoleService === "undefined" ? Object : RoleService
|
|
2436
|
+
])
|
|
2437
|
+
], PermissionService);
|
|
2438
|
+
|
|
2439
|
+
// src/permissions/PermissionController.ts
|
|
2440
|
+
import { isAdmin as isAdmin3 } from "@/roles/RoleGuards";
|
|
2441
|
+
class PermissionController {
|
|
2442
|
+
permissionService;
|
|
2443
|
+
constructor(permissionService) {
|
|
2444
|
+
this.permissionService = permissionService;
|
|
2445
|
+
}
|
|
2446
|
+
async getPermissions() {
|
|
2447
|
+
const permissions = await this.permissionService.getAll();
|
|
2448
|
+
return {
|
|
2449
|
+
data: permissions,
|
|
2450
|
+
message: t9("permissions.success.retrieved"),
|
|
2451
|
+
status: "success"
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2454
|
+
async getPermission(id) {
|
|
2455
|
+
const permission = await this.permissionService.getById(id);
|
|
2456
|
+
return {
|
|
2457
|
+
data: permission,
|
|
2458
|
+
message: t9("permissions.success.retrieved"),
|
|
2459
|
+
status: "success"
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
async create(body) {
|
|
2463
|
+
const newPermission = await this.permissionService.create(body);
|
|
2464
|
+
return {
|
|
2465
|
+
data: newPermission,
|
|
2466
|
+
message: t9("permissions.success.created"),
|
|
2467
|
+
status: "success"
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2470
|
+
async update(id, body) {
|
|
2471
|
+
const updatedPermission = await this.permissionService.update(id, body);
|
|
2472
|
+
return {
|
|
2473
|
+
data: updatedPermission,
|
|
2474
|
+
message: t9("permissions.success.updated"),
|
|
2475
|
+
status: "success"
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
async delete(id) {
|
|
2479
|
+
const result = await this.permissionService.delete(id);
|
|
2480
|
+
return {
|
|
2481
|
+
data: result,
|
|
2482
|
+
message: t9("permissions.success.deleted"),
|
|
2483
|
+
status: "success"
|
|
2484
|
+
};
|
|
2485
|
+
}
|
|
2486
|
+
async getByRole(roleId) {
|
|
2487
|
+
const permissions = await this.permissionService.getPermissionsByRole(roleId);
|
|
2488
|
+
return {
|
|
2489
|
+
data: permissions,
|
|
2490
|
+
message: t9("permissions.success.retrieved"),
|
|
2491
|
+
status: "success"
|
|
2492
|
+
};
|
|
2493
|
+
}
|
|
2494
|
+
async getRolesByPermission(permissionId) {
|
|
2495
|
+
const roles = await this.permissionService.getRolesByPermission(permissionId);
|
|
2496
|
+
return {
|
|
2497
|
+
data: roles,
|
|
2498
|
+
message: t9("permissions.success.retrieved"),
|
|
2499
|
+
status: "success"
|
|
2500
|
+
};
|
|
2501
|
+
}
|
|
2502
|
+
async assignToRole(roleId, permissionId) {
|
|
2503
|
+
const result = await this.permissionService.assignPermissionToRole(roleId, permissionId);
|
|
2504
|
+
return {
|
|
2505
|
+
data: result,
|
|
2506
|
+
message: t9("permissions.success.assigned"),
|
|
2507
|
+
status: "success"
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
async removeFromRole(roleId, permissionId) {
|
|
2511
|
+
const result = await this.permissionService.removePermissionFromRole(roleId, permissionId);
|
|
2512
|
+
return {
|
|
2513
|
+
data: result,
|
|
2514
|
+
message: t9("permissions.success.removed"),
|
|
2515
|
+
status: "success"
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
async deleteAll() {
|
|
2519
|
+
const result = await this.permissionService.deleteAll();
|
|
2520
|
+
return {
|
|
2521
|
+
data: result,
|
|
2522
|
+
message: t9("permissions.success.allDeleted"),
|
|
2523
|
+
status: "success"
|
|
2524
|
+
};
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
__legacyDecorateClassTS([
|
|
2528
|
+
Get4(),
|
|
2529
|
+
__legacyMetadataTS("design:type", Function),
|
|
2530
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2531
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2532
|
+
], PermissionController.prototype, "getPermissions", null);
|
|
2533
|
+
__legacyDecorateClassTS([
|
|
2534
|
+
Get4("/:id"),
|
|
2535
|
+
__legacyDecorateParamTS(0, Params4("id")),
|
|
2536
|
+
__legacyMetadataTS("design:type", Function),
|
|
2537
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2538
|
+
String
|
|
2539
|
+
]),
|
|
2540
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2541
|
+
], PermissionController.prototype, "getPermission", null);
|
|
2542
|
+
__legacyDecorateClassTS([
|
|
2543
|
+
Post4(),
|
|
2544
|
+
__legacyDecorateParamTS(0, Body4()),
|
|
2545
|
+
__legacyMetadataTS("design:type", Function),
|
|
2546
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2547
|
+
Object
|
|
2548
|
+
]),
|
|
2549
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2550
|
+
], PermissionController.prototype, "create", null);
|
|
2551
|
+
__legacyDecorateClassTS([
|
|
2552
|
+
Put3("/:id"),
|
|
2553
|
+
__legacyDecorateParamTS(0, Params4("id")),
|
|
2554
|
+
__legacyDecorateParamTS(1, Body4()),
|
|
2555
|
+
__legacyMetadataTS("design:type", Function),
|
|
2556
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2557
|
+
String,
|
|
2558
|
+
Object
|
|
2559
|
+
]),
|
|
2560
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2561
|
+
], PermissionController.prototype, "update", null);
|
|
2562
|
+
__legacyDecorateClassTS([
|
|
2563
|
+
Delete3("/:id"),
|
|
2564
|
+
__legacyDecorateParamTS(0, Params4("id")),
|
|
2565
|
+
__legacyMetadataTS("design:type", Function),
|
|
2566
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2567
|
+
String
|
|
2568
|
+
]),
|
|
2569
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2570
|
+
], PermissionController.prototype, "delete", null);
|
|
2571
|
+
__legacyDecorateClassTS([
|
|
2572
|
+
Get4("/role/:roleId"),
|
|
2573
|
+
__legacyDecorateParamTS(0, Params4("roleId")),
|
|
2574
|
+
__legacyMetadataTS("design:type", Function),
|
|
2575
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2576
|
+
String
|
|
2577
|
+
]),
|
|
2578
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2579
|
+
], PermissionController.prototype, "getByRole", null);
|
|
2580
|
+
__legacyDecorateClassTS([
|
|
2581
|
+
Get4("/roles/:permissionId"),
|
|
2582
|
+
__legacyDecorateParamTS(0, Params4("permissionId")),
|
|
2583
|
+
__legacyMetadataTS("design:type", Function),
|
|
2584
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2585
|
+
String
|
|
2586
|
+
]),
|
|
2587
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2588
|
+
], PermissionController.prototype, "getRolesByPermission", null);
|
|
2589
|
+
__legacyDecorateClassTS([
|
|
2590
|
+
Post4("/assign/:roleId/:permissionId"),
|
|
2591
|
+
__legacyDecorateParamTS(0, Params4("roleId")),
|
|
2592
|
+
__legacyDecorateParamTS(1, Params4("permissionId")),
|
|
2593
|
+
__legacyMetadataTS("design:type", Function),
|
|
2594
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2595
|
+
String,
|
|
2596
|
+
String
|
|
2597
|
+
]),
|
|
2598
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2599
|
+
], PermissionController.prototype, "assignToRole", null);
|
|
2600
|
+
__legacyDecorateClassTS([
|
|
2601
|
+
Delete3("/remove/:roleId/:permissionId"),
|
|
2602
|
+
__legacyDecorateParamTS(0, Params4("roleId")),
|
|
2603
|
+
__legacyDecorateParamTS(1, Params4("permissionId")),
|
|
2604
|
+
__legacyMetadataTS("design:type", Function),
|
|
2605
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2606
|
+
String,
|
|
2607
|
+
String
|
|
2608
|
+
]),
|
|
2609
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2610
|
+
], PermissionController.prototype, "removeFromRole", null);
|
|
2611
|
+
__legacyDecorateClassTS([
|
|
2612
|
+
Delete3(),
|
|
2613
|
+
isAdmin3(),
|
|
2614
|
+
__legacyMetadataTS("design:type", Function),
|
|
2615
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2616
|
+
__legacyMetadataTS("design:returntype", Promise)
|
|
2617
|
+
], PermissionController.prototype, "deleteAll", null);
|
|
2618
|
+
PermissionController = __legacyDecorateClassTS([
|
|
2619
|
+
Controller4("/permissions"),
|
|
2620
|
+
isAdmin3(),
|
|
2621
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2622
|
+
typeof PermissionService === "undefined" ? Object : PermissionService
|
|
2623
|
+
])
|
|
2624
|
+
], PermissionController);
|
|
2625
|
+
// src/shared/index.ts
|
|
2626
|
+
import * as fs from "fs/promises";
|
|
2627
|
+
import * as path from "path";
|
|
2628
|
+
import _isEmpty from "lodash.isempty";
|
|
2629
|
+
var avatarsPath = path.join(process.cwd(), "avatars");
|
|
2630
|
+
var parseSchema4 = async (schema, data) => {
|
|
2631
|
+
try {
|
|
2632
|
+
return await schema.parseAsync(data);
|
|
2633
|
+
} catch (error) {
|
|
2634
|
+
const errors = error.issues || error.errors || [];
|
|
2635
|
+
const errorMessage = errors.map((err) => `${err.path.join(".")}: ${err.message}`).join("; ");
|
|
2636
|
+
throw new Error(errorMessage);
|
|
2637
|
+
}
|
|
2638
|
+
};
|
|
2639
|
+
var clean2 = (obj) => {
|
|
2640
|
+
const cleaned = {};
|
|
2641
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2642
|
+
if (value !== null && value !== undefined && value !== "") {
|
|
2643
|
+
cleaned[key] = value;
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
return cleaned;
|
|
2647
|
+
};
|
|
2648
|
+
var getAvatarFile = async (fileName) => {
|
|
2649
|
+
try {
|
|
2650
|
+
const filePath = path.join(avatarsPath, fileName);
|
|
2651
|
+
const buffer = await fs.readFile(filePath);
|
|
2652
|
+
const file = new File([buffer], fileName, {
|
|
2653
|
+
type: "image/png"
|
|
2654
|
+
});
|
|
2655
|
+
return file;
|
|
2656
|
+
} catch (error) {
|
|
2657
|
+
return null;
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
var formatDate = (dateValue) => {
|
|
2661
|
+
if (!dateValue)
|
|
2662
|
+
return null;
|
|
2663
|
+
let date;
|
|
2664
|
+
if (dateValue instanceof Date) {
|
|
2665
|
+
date = dateValue;
|
|
2666
|
+
} else if (typeof dateValue === "string") {
|
|
2667
|
+
date = new Date(dateValue);
|
|
2668
|
+
} else {
|
|
2669
|
+
return null;
|
|
2670
|
+
}
|
|
2671
|
+
if (isNaN(date.getTime()))
|
|
2672
|
+
return null;
|
|
2673
|
+
return date.toISOString().split("T")[0];
|
|
2674
|
+
};
|
|
2675
|
+
function calculateAge(dateOfBirth) {
|
|
2676
|
+
if (!dateOfBirth)
|
|
2677
|
+
return null;
|
|
2678
|
+
const formattedDate = formatDate(dateOfBirth);
|
|
2679
|
+
if (!formattedDate)
|
|
2680
|
+
return null;
|
|
2681
|
+
const birth = new Date(formattedDate);
|
|
2682
|
+
const today = new Date;
|
|
2683
|
+
let age = today.getFullYear() - birth.getFullYear();
|
|
2684
|
+
const monthDiff = today.getMonth() - birth.getMonth();
|
|
2685
|
+
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birth.getDate()) {
|
|
2686
|
+
age--;
|
|
2687
|
+
}
|
|
2688
|
+
return age;
|
|
2689
|
+
}
|
|
2690
|
+
function calculateYearsOfExperience(hireDate) {
|
|
2691
|
+
if (!hireDate)
|
|
2692
|
+
return null;
|
|
2693
|
+
const formattedDate = formatDate(hireDate);
|
|
2694
|
+
if (!formattedDate)
|
|
2695
|
+
return null;
|
|
2696
|
+
const hire = new Date(formattedDate);
|
|
2697
|
+
const today = new Date;
|
|
2698
|
+
let years = today.getFullYear() - hire.getFullYear();
|
|
2699
|
+
const monthDiff = today.getMonth() - hire.getMonth();
|
|
2700
|
+
if (monthDiff < 0 || monthDiff === 0 && today.getDate() < hire.getDate()) {
|
|
2701
|
+
years--;
|
|
2702
|
+
}
|
|
2703
|
+
return years;
|
|
2704
|
+
}
|
|
2705
|
+
function pickProps(source, keys) {
|
|
2706
|
+
const result = {};
|
|
2707
|
+
for (const key of keys) {
|
|
2708
|
+
if (source[key] !== undefined) {
|
|
2709
|
+
result[key] = source[key];
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
return result;
|
|
2713
|
+
}
|
|
2714
|
+
var isEmpty = _isEmpty;
|
|
2715
|
+
var isPath = (img) => typeof img === "string" && img.trim().length > 0 && (img.startsWith("/") || img.startsWith("http") || img.startsWith("storage/"));
|
|
2716
|
+
var isFile = (img) => !!img && typeof img !== "string" && img instanceof File;
|
|
2717
|
+
// src/database/db.ts
|
|
2718
|
+
import { drizzle } from "drizzle-orm/postgres-js";
|
|
2719
|
+
|
|
2720
|
+
// src/database/schema/index.ts
|
|
2721
|
+
var exports_schema = {};
|
|
2722
|
+
__export(exports_schema, {
|
|
2723
|
+
usersTable: () => usersTable3,
|
|
2724
|
+
tokensTable: () => tokensTable2,
|
|
2725
|
+
timestamps: () => timestamps,
|
|
2726
|
+
rolesTable: () => rolesTable5,
|
|
2727
|
+
rolePermissionsTable: () => rolePermissionsTable4,
|
|
2728
|
+
permissionsTable: () => permissionsTable4,
|
|
2729
|
+
idField: () => idField
|
|
2730
|
+
});
|
|
2731
|
+
import { pgTable, text, boolean, timestamp } from "drizzle-orm/pg-core";
|
|
2732
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
2733
|
+
import { sql } from "drizzle-orm";
|
|
2734
|
+
|
|
2735
|
+
// src/database/schema/PgEnum.ts
|
|
2736
|
+
import { getEnumConfig as getEnumConfig2 } from "@/lib/ENUMS";
|
|
2737
|
+
import { pgEnum } from "drizzle-orm/pg-core";
|
|
2738
|
+
var createPgEnum = (enumKey) => {
|
|
2739
|
+
const config = getEnumConfig2(enumKey);
|
|
2740
|
+
if (!config)
|
|
2741
|
+
throw new Error(`Enum ${enumKey} not found`);
|
|
2742
|
+
const enumName = config.name || enumKey;
|
|
2743
|
+
return pgEnum(enumName, config.values);
|
|
2744
|
+
};
|
|
2745
|
+
var userStatusEnum2 = createPgEnum("userStatus");
|
|
2746
|
+
var tokenStatusEnum2 = createPgEnum("tokenStatus");
|
|
2747
|
+
var tokenTypeEnum2 = createPgEnum("tokenType");
|
|
2748
|
+
var studentStatusEnum2 = createPgEnum("studentStatus");
|
|
2749
|
+
|
|
2750
|
+
// src/database/schema/index.ts
|
|
2751
|
+
var timestamps = {
|
|
2752
|
+
createdAt: timestamp("created_at", { mode: "string" }).defaultNow(),
|
|
2753
|
+
updatedAt: timestamp("updated_at", { mode: "string" }).defaultNow().$onUpdate(() => sql`CURRENT_TIMESTAMP`)
|
|
2754
|
+
};
|
|
2755
|
+
var idField = (length = 5) => text("id").primaryKey().notNull().$defaultFn(() => nanoid2(length));
|
|
2756
|
+
var rolesTable5 = pgTable("roles", {
|
|
2757
|
+
id: idField(),
|
|
2758
|
+
name: text("name").notNull(),
|
|
2759
|
+
description: text("description")
|
|
2760
|
+
});
|
|
2761
|
+
var usersTable3 = pgTable("users", {
|
|
2762
|
+
id: idField(8),
|
|
2763
|
+
email: text("email").notNull().unique(),
|
|
2764
|
+
emailVerified: boolean("email_verified").default(false),
|
|
2765
|
+
password: text("password").notNull(),
|
|
2766
|
+
image: text("image").default("noavatar.png"),
|
|
2767
|
+
status: userStatusEnum2("status").default("pending"),
|
|
2768
|
+
roleId: text("role_id").references(() => rolesTable5.id),
|
|
2769
|
+
lastLogin: timestamp("last_login", { mode: "string" }),
|
|
2770
|
+
...timestamps
|
|
2771
|
+
});
|
|
2772
|
+
var tokensTable2 = pgTable("tokens", {
|
|
2773
|
+
id: idField(10),
|
|
2774
|
+
userId: text("user_id").references(() => usersTable3.id, { onDelete: "cascade" }).unique().notNull(),
|
|
2775
|
+
token: text("token").notNull(),
|
|
2776
|
+
type: tokenTypeEnum2("type").default("refresh"),
|
|
2777
|
+
status: tokenStatusEnum2("status").default("active"),
|
|
2778
|
+
expiresAt: timestamp("expires_at", { mode: "string" }).notNull(),
|
|
2779
|
+
...timestamps
|
|
2780
|
+
});
|
|
2781
|
+
var permissionsTable4 = pgTable("permissions", {
|
|
2782
|
+
id: idField(),
|
|
2783
|
+
name: text("name").notNull().unique(),
|
|
2784
|
+
description: text("description"),
|
|
2785
|
+
resource: text("resource").notNull(),
|
|
2786
|
+
action: text("action").notNull(),
|
|
2787
|
+
...timestamps
|
|
2788
|
+
});
|
|
2789
|
+
var rolePermissionsTable4 = pgTable("role_permissions", {
|
|
2790
|
+
id: idField(),
|
|
2791
|
+
roleId: text("role_id").references(() => rolesTable5.id).notNull(),
|
|
2792
|
+
permissionId: text("permission_id").references(() => permissionsTable4.id).notNull(),
|
|
2793
|
+
...timestamps
|
|
2794
|
+
});
|
|
2795
|
+
|
|
2796
|
+
// src/database/db.ts
|
|
2797
|
+
var db = process.env.DB_URL ? drizzle(process.env.DB_URL, { schema: exports_schema }) : null;
|
|
2798
|
+
if (db) {
|
|
2799
|
+
console.warn("⚠️ najm-auth: Using standalone DB instance. This should only be used for development.");
|
|
2800
|
+
}
|
|
2801
|
+
// src/plugin.ts
|
|
2802
|
+
var AuthPlugin = {
|
|
2803
|
+
name: "najm-auth",
|
|
2804
|
+
version: "0.1.3",
|
|
2805
|
+
database: "auth",
|
|
2806
|
+
controllers: [
|
|
2807
|
+
UserController,
|
|
2808
|
+
AuthController,
|
|
2809
|
+
RoleController,
|
|
2810
|
+
PermissionController
|
|
2811
|
+
],
|
|
2812
|
+
services: [
|
|
2813
|
+
UserService,
|
|
2814
|
+
AuthService,
|
|
2815
|
+
CookieService,
|
|
2816
|
+
EncryptionService,
|
|
2817
|
+
RoleService,
|
|
2818
|
+
PermissionService,
|
|
2819
|
+
TokenService
|
|
2820
|
+
],
|
|
2821
|
+
repositories: [
|
|
2822
|
+
UserRepository,
|
|
2823
|
+
RoleRepository,
|
|
2824
|
+
PermissionRepository,
|
|
2825
|
+
TokenRepository
|
|
2826
|
+
],
|
|
2827
|
+
providers: [
|
|
2828
|
+
UserValidator,
|
|
2829
|
+
RoleValidator,
|
|
2830
|
+
PermissionValidator,
|
|
2831
|
+
RoleGuards,
|
|
2832
|
+
PermissionGuards
|
|
2833
|
+
],
|
|
2834
|
+
onSetup: async () => {
|
|
2835
|
+
console.log(" ✓ najm-auth plugin initialized");
|
|
2836
|
+
console.log(" - Authentication endpoints ready");
|
|
2837
|
+
console.log(" - Authorization system active");
|
|
2838
|
+
console.log(" - Database connection established");
|
|
2839
|
+
},
|
|
2840
|
+
onTeardown: async () => {
|
|
2841
|
+
console.log(" ✓ najm-auth plugin cleanup complete");
|
|
2842
|
+
}
|
|
2843
|
+
};
|
|
2844
|
+
export {
|
|
2845
|
+
vehicleTypeEnum,
|
|
2846
|
+
vehicleStatusEnum,
|
|
2847
|
+
vehicleSchema,
|
|
2848
|
+
vehicleDocumentTypeEnum,
|
|
2849
|
+
usersTable3 as usersTable,
|
|
2850
|
+
userTypeEnum,
|
|
2851
|
+
userStatusEnum,
|
|
2852
|
+
userSchema2 as userSchema,
|
|
2853
|
+
trackerModeEnum,
|
|
2854
|
+
tokensTable2 as tokensTable,
|
|
2855
|
+
tokenTypeEnum,
|
|
2856
|
+
tokenStatusEnum,
|
|
2857
|
+
teacherStatusEnum,
|
|
2858
|
+
teacherProfessionalSchema,
|
|
2859
|
+
teacherPersonalSchema,
|
|
2860
|
+
teacherFullSchema,
|
|
2861
|
+
submissionTypeEnum,
|
|
2862
|
+
subjectSchema,
|
|
2863
|
+
studentStatusEnum,
|
|
2864
|
+
studentSchema,
|
|
2865
|
+
settingsSchema,
|
|
2866
|
+
semesterEnum,
|
|
2867
|
+
sectionStatusEnum,
|
|
2868
|
+
sectionSchema,
|
|
2869
|
+
scheduleEnum,
|
|
2870
|
+
rolesTable5 as rolesTable,
|
|
2871
|
+
roleSchema2 as roleSchema,
|
|
2872
|
+
rolePermissionsTable4 as rolePermissionsTable,
|
|
2873
|
+
relationshipTypeEnum,
|
|
2874
|
+
refuelStatusEnum,
|
|
2875
|
+
refuelSchema,
|
|
2876
|
+
proficiencyLevelEnum,
|
|
2877
|
+
pickProps,
|
|
2878
|
+
permissionsTable4 as permissionsTable,
|
|
2879
|
+
paymentTypeEnum,
|
|
2880
|
+
paymentStatusEnum,
|
|
2881
|
+
paymentMethodEnum,
|
|
2882
|
+
paymentAllocationSchema,
|
|
2883
|
+
participantTypeEnum,
|
|
2884
|
+
parseSchema4 as parseSchema,
|
|
2885
|
+
parentsSchema,
|
|
2886
|
+
parentSchema,
|
|
2887
|
+
paginationSchema,
|
|
2888
|
+
maritalStatusEnum,
|
|
2889
|
+
maintenanceTypeEnum,
|
|
2890
|
+
maintenanceStatusEnum,
|
|
2891
|
+
languageEnum,
|
|
2892
|
+
isTeacher,
|
|
2893
|
+
isStudent,
|
|
2894
|
+
isStaff,
|
|
2895
|
+
isSecretary,
|
|
2896
|
+
isPrincipal,
|
|
2897
|
+
isPath,
|
|
2898
|
+
isParent,
|
|
2899
|
+
isFinancial,
|
|
2900
|
+
isFile,
|
|
2901
|
+
isEmpty,
|
|
2902
|
+
isAuth,
|
|
2903
|
+
isAdministrator,
|
|
2904
|
+
isAdmin,
|
|
2905
|
+
isAccounting,
|
|
2906
|
+
idParamSchema,
|
|
2907
|
+
idField,
|
|
2908
|
+
gradeStatusEnum,
|
|
2909
|
+
gradeSchema,
|
|
2910
|
+
getEnumValues,
|
|
2911
|
+
getEnumConfig,
|
|
2912
|
+
getAvatarFile,
|
|
2913
|
+
genderEnum,
|
|
2914
|
+
fullStudentSchema,
|
|
2915
|
+
fuelTypeEnum,
|
|
2916
|
+
formatDate,
|
|
2917
|
+
fileStatusEnum,
|
|
2918
|
+
feesSchema,
|
|
2919
|
+
feeTypeStatusEnum,
|
|
2920
|
+
feeTypeSchema,
|
|
2921
|
+
feeStatusEnum,
|
|
2922
|
+
feeSchema,
|
|
2923
|
+
feePaymentSchema,
|
|
2924
|
+
feeInstallmentStatusEnum,
|
|
2925
|
+
feeInstallmentSchema,
|
|
2926
|
+
expenseStatusEnum,
|
|
2927
|
+
expenseSchema,
|
|
2928
|
+
expensePaymentSchema,
|
|
2929
|
+
expenseCategoryEnum,
|
|
2930
|
+
expenseApprovalSchema,
|
|
2931
|
+
examTypeEnum,
|
|
2932
|
+
examStatusEnum,
|
|
2933
|
+
examSecurityEnum,
|
|
2934
|
+
examSchema,
|
|
2935
|
+
eventVisibilityEnum,
|
|
2936
|
+
eventTypeEnum,
|
|
2937
|
+
eventStatusEnum,
|
|
2938
|
+
eventSchema,
|
|
2939
|
+
eventParticipantSchema,
|
|
2940
|
+
enrollmentStatusEnum,
|
|
2941
|
+
employmentTypeEnum,
|
|
2942
|
+
driverStatusEnum,
|
|
2943
|
+
driverSchema,
|
|
2944
|
+
db,
|
|
2945
|
+
dayOfWeekEnum,
|
|
2946
|
+
dateRangeSchema,
|
|
2947
|
+
clean2 as clean,
|
|
2948
|
+
classStatusEnum,
|
|
2949
|
+
classSchema,
|
|
2950
|
+
calendarSystemEnum,
|
|
2951
|
+
calculateYearsOfExperience,
|
|
2952
|
+
calculateAge,
|
|
2953
|
+
busStatusEnum,
|
|
2954
|
+
bulkFeeItemSchema,
|
|
2955
|
+
bulkFeeFormSchema,
|
|
2956
|
+
bulkAssessmentSchema,
|
|
2957
|
+
avatarsPath,
|
|
2958
|
+
attendanceStatusEnum,
|
|
2959
|
+
attendanceSchema,
|
|
2960
|
+
assignmentsSchema,
|
|
2961
|
+
assignmentStatusEnum,
|
|
2962
|
+
assignmentSchema,
|
|
2963
|
+
assessmentTypeEnum,
|
|
2964
|
+
assessmentStatusEnum,
|
|
2965
|
+
assessmentSchema,
|
|
2966
|
+
announcementSchema,
|
|
2967
|
+
alertTypeEnum,
|
|
2968
|
+
alertStatusEnum,
|
|
2969
|
+
alertSchema,
|
|
2970
|
+
alertPriorityEnum,
|
|
2971
|
+
UserValidator,
|
|
2972
|
+
UserService,
|
|
2973
|
+
UserRepository,
|
|
2974
|
+
UserController,
|
|
2975
|
+
TokenService,
|
|
2976
|
+
TokenRepository,
|
|
2977
|
+
RoleValidator,
|
|
2978
|
+
RoleService,
|
|
2979
|
+
RoleRepository,
|
|
2980
|
+
RoleGuards,
|
|
2981
|
+
RoleController,
|
|
2982
|
+
RoleChecker,
|
|
2983
|
+
Role,
|
|
2984
|
+
ROLE_GROUPS,
|
|
2985
|
+
ROLES,
|
|
2986
|
+
PermissionValidator,
|
|
2987
|
+
PermissionService,
|
|
2988
|
+
PermissionRepository,
|
|
2989
|
+
PermissionGuards,
|
|
2990
|
+
PermissionController,
|
|
2991
|
+
Permission,
|
|
2992
|
+
EncryptionService,
|
|
2993
|
+
ENUMS,
|
|
2994
|
+
CookieService,
|
|
2995
|
+
AuthService,
|
|
2996
|
+
AuthPlugin,
|
|
2997
|
+
AuthController
|
|
2998
|
+
};
|