@andrewcaires/api 2.0.3 → 3.0.0

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.
package/dist/index.cjs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @andrewcaires/api v2.0.3
2
+ * @andrewcaires/api v3.0.0
3
3
  * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
4
4
  * (c) 2023 Andrew Caires
5
5
  * @license: MIT
6
6
  */
7
- "use strict";var e=require("@andrewcaires/utils.js"),t=require("cors"),r=require("express"),s=require("fs"),i=require("http"),o=require("https"),n=require("net"),a=require("ws"),d=require("dotenv"),u=require("sequelize"),l=require("jsonwebtoken"),c=require("mime-types"),h=require("multer"),p=require("path"),m=require("crypto-js");function v(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var g=v(i),f=v(o);function y(e,t,r,s){return new(r||(r=Promise))((function(i,o){function n(e){try{d(s.next(e))}catch(e){o(e)}}function a(e){try{d(s.throw(e))}catch(e){o(e)}}function d(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(n,a)}d((s=s.apply(e,t||[])).next())}))}d.config();const I=e.toBool(process.env.API_CONSOLE_ERROR||"false"),_=process.env.API_DB_DATABASE||"",A=process.env.API_DB_HOST||"127.0.0.1",T=process.env.API_DB_PASSWORD||"",b=parseInt(process.env.API_DB_PORT||"3306"),S=process.env.API_DB_TYPE||"",w=process.env.API_DB_USERNAME||"root",O=e.toBool(process.env.API_DB_LOG||"false"),E=process.env.API_TABLE_PREFIX||"",P=process.env.API_HTTP_CRT||"",x=process.env.API_HTTP_KEY||"",q=parseInt(process.env.API_HTTP_PORT||"3000"),R=process.env.API_HTTP_PUBLIC||"",D=e.toBool(process.env.API_HTTP_CROSS||"false"),N=e.toBool(process.env.API_HTTP_HYBRID||"false"),k=parseInt(process.env.API_SLEEP_AUTH||"1000"),B=parseInt(process.env.API_SLEEP_FORGOT||"5000"),C=parseInt(process.env.API_SLEEP_REGISTRY||"5000"),G=process.env.API_TOKEN_CRT||"",V=process.env.API_TOKEN_KEY||"",j=process.env.API_TOKEN_HEADER||"authorization",z=parseInt(process.env.API_TOKEN_LIFETIME||"15"),L=parseInt(process.env.API_UPLOAD_COUNT||"1"),M=process.env.API_UPLOAD_FIELD||"upload",U=parseInt(process.env.API_UPLOAD_SIZE||"2"),H=process.env.API_UPLOAD_TEMP||"./temp",K=e.toBool(process.env.API_WEBSOCKET_START||"false");class F{static connect(e){const t=S.toLowerCase();if("connect_"+t in F)return F["connect_"+t](e);throw new Error("No database is connected to this API")}static connect_mariadb(e){return new u.Sequelize(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mariadb",logging:O,define:{timestamps:!1}})}static connect_memory(){return new u.Sequelize("sqlite::memory:",{logging:O,define:{timestamps:!1}})}static connect_mysql(e){return new u.Sequelize(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mysql",logging:O,define:{timestamps:!1}})}static connect_postgres(e){return new u.Sequelize(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"postgres",logging:O,define:{timestamps:!1}})}static connect_sqlite(e){return new u.Sequelize({dialect:"sqlite",storage:e.database,logging:O,define:{timestamps:!1}})}}const Y=F.connect({database:_,username:w,password:T,hostname:A,hostport:b});class W extends u.Model{}W.init({login:u.DataTypes.BIGINT,logout:u.DataTypes.BIGINT,secret:u.DataTypes.STRING,timestamp:u.DataTypes.BIGINT,useragent:u.DataTypes.STRING},{sequelize:Y,modelName:E+"auth",timestamps:!0,createdAt:"created",updatedAt:"updated"});class X extends u.Model{}X.init({token:u.DataTypes.STRING,timestamp:u.DataTypes.BIGINT,state:u.DataTypes.BOOLEAN},{sequelize:Y,modelName:E+"forgot",timestamps:!0,createdAt:"created",updatedAt:"updated"});class J extends u.Model{}J.init({name:u.DataTypes.STRING,description:u.DataTypes.TEXT,state:u.DataTypes.BOOLEAN},{sequelize:Y,modelName:E+"group",timestamps:!0,createdAt:"created",updatedAt:"updated"});class Z extends u.Model{}Z.init({name:u.DataTypes.STRING,description:u.DataTypes.TEXT,state:u.DataTypes.BOOLEAN},{sequelize:Y,modelName:E+"route",timestamps:!0,createdAt:"created",updatedAt:"updated"});class $ extends u.Model{}$.init({},{sequelize:Y,modelName:E+"groups_routes",timestamps:!0,createdAt:"created",updatedAt:!1}),$.removeAttribute("id");class Q extends u.Model{}Q.init({name:u.DataTypes.STRING,email:u.DataTypes.STRING,username:u.DataTypes.STRING,password:u.DataTypes.STRING,avatar:u.DataTypes.STRING,description:u.DataTypes.TEXT,state:u.DataTypes.BOOLEAN},{sequelize:Y,modelName:E+"user",timestamps:!0,createdAt:"created",updatedAt:"updated"});class ee extends u.Model{}ee.init({},{sequelize:Y,modelName:E+"users_groups",timestamps:!0,createdAt:"created",updatedAt:!1}),ee.removeAttribute("id");class te extends u.Model{}te.init({key:u.DataTypes.STRING,value:u.DataTypes.STRING},{sequelize:Y,modelName:E+"configs",timestamps:!0,createdAt:"created",updatedAt:"updated"}),te.removeAttribute("id");class re extends u.Model{}var se;re.init({type:u.DataTypes.STRING,source:u.DataTypes.STRING,message:u.DataTypes.TEXT},{sequelize:Y,modelName:E+"logs",timestamps:!0,createdAt:"created",updatedAt:!1}),Q.hasMany(W),W.belongsTo(Q),Q.hasMany(X),X.belongsTo(Q),J.hasMany($),$.belongsTo(J),Z.hasMany($),$.belongsTo(Z),Q.hasMany(ee),ee.belongsTo(Q),J.hasMany(ee),ee.belongsTo(J),function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(se||(se={}));class ie{static write(e,t,r){return y(this,void 0,void 0,(function*(){yield ie.writeRaw(se.NONE,"",e,t,r)}))}static error(e,t,r){return y(this,void 0,void 0,(function*(){yield ie.writeRaw(se.ERROR,"error",e,t,r)}))}static info(e,t,r){return y(this,void 0,void 0,(function*(){yield ie.writeRaw(se.INFO,"info",e,t,r)}))}static success(e,t,r){return y(this,void 0,void 0,(function*(){yield ie.writeRaw(se.ERROR,"success",e,t,r)}))}static warning(e,t,r){return y(this,void 0,void 0,(function*(){yield ie.writeRaw(se.WARNING,"warning",e,t,r)}))}static writeConsole(t,r,s){const i=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"","|",i,"|",s)}static writeRaw(e,t,r,s,i){return y(this,void 0,void 0,(function*(){i&&ie.writeConsole(e,t,r),Y&&(yield re.create({type:t,source:s,message:r}).catch((()=>null)))}))}}class oe{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t){return e.status(400).json({message:t})}static unauthorized(e,t){return e.status(401).json({message:t})}}const ne=e=>s.existsSync(e)?s.readFileSync(e):void 0,ae={http:ne(P),token:ne(G)},de={http:ne(x),token:ne(V)};class ue{static error(e){ie.error(e.message,"api.token",I)}static sign(e){return de.token?{token:l.sign(e,de.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static user(e){return y(this,void 0,void 0,(function*(){const{error:t,decode:r}=ue.verify(e);if(t)return{error:t};if(r){const{id:e,secret:t}=r;if(e&&r){const r=yield Q.findOne({where:{id:e,state:!0}}).catch(ue.error);if(r){const e=yield W.findOne({where:{secret:t,userId:r.id}}).catch(ue.error);if(e){const t=Date.now();if(t>e.timestamp)return e.logout=t,yield e.save(),{error:"Expired token"};if(e.timestamp=t+6e4*z,!e.logout)return yield e.save(),{auth:e,user:r}}}return{error:"Access denied"}}}return{error:"Invalid token"}}))}static verify(e){if(!ae.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:l.verify(e,ae.token)}}catch(e){return{error:"Invalid Token"}}}}class le extends e.EventEmitter{constructor(e){super(),this.app=r(),this.router=r.Router(),this.middlewares(),this.controllers(e)}controllers(e){e.forEach((e=>{e.intialize(this),this.router.use(e.path(),e.router)}))}listen(){return y(this,void 0,void 0,(function*(){if(yield Y.sync(),ae.http&&de.http||(this._server=g.createServer(this.app),this._server.listen(q,(()=>ie.info("Server started on port "+q,"api.server",!0)))),!this._server){const e=g.createServer(((e,t)=>{const r=80==q?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),t=f.createServer({key:de.http,cert:ae.http},this.app);if(N){new n.Server((r=>{r.once("data",(s=>{r.pause(),r.unshift(s),(22===s[0]?t:e).emit("connection",r),process.nextTick((()=>r.resume()))}))})).listen(q,(()=>ie.info("Server started on port "+q,"api.server",!0))),this._server=t}this._server||(443==q&&e.listen(80,(()=>ie.info("Server started on port 80","api.server",!0))),t.listen(q,(()=>ie.info("Server started on port "+q,"api.server",!0))),this._server=t)}K&&this._server&&(this._webSocket=new a.Server({server:this._server,verifyClient:(e,t)=>t(K)}),this._webSocket.on("connection",((t,r)=>y(this,void 0,void 0,(function*(){r.url||(r.url="");const s=r.url.length<=1?"":r.url.replace(/\//g,".");let i;t.on("message",(e=>y(this,void 0,void 0,(function*(){if(i)try{const o=JSON.parse(e);this.emit("ws.message"+s,{data:o,message:e,req:r,user:i,ws:t})}catch(o){this.emit("ws.message"+s,{message:e,req:r,user:i,ws:t})}else{const{user:o}=yield ue.user(e.toString());o&&(i=o,this.emit("ws.connection"+s,{req:r,user:i,ws:t}))}i||t.close()})))),t.on("close",(()=>{i&&this.emit("ws.close"+s,{user:i,ws:t})})),yield e.sleep(2e3),i||t.close()})))))}))}middlewares(){this.app.use(r.json()),this.app.use(((e,t,r,s)=>e?(ie.error(e.message,"api.express",I),oe.error(r,"Internal Server Error")):s())),this.app.use(r.urlencoded({extended:!0})),this.app.disable("x-powered-by"),D&&this.app.use(t()),this.app.use("/api",this.router),this.app.all("/api/*",((e,t)=>oe.notfound(t,"Invalid API"))),R&&(s.existsSync(R)&&this.app.use(r.static(R)),this.app.get("*",((e,t)=>{if(!s.existsSync(R))return oe.notfound(t,'File "index.html" not found');t.sendFile(R+"/index.html")})))}server(){return this._server}websocket(){return this._webSocket}}class ce{static all(){return y(this,void 0,void 0,(function*(){const e=yield te.findAll().catch(ce.error),t={};return e&&e.forEach((e=>{t[e.key]=e.value})),t}))}static del(e){return y(this,void 0,void 0,(function*(){return((yield te.destroy({where:{key:e}}).catch(ce.error))||0)>0}))}static error(e){ie.error(e.message,"api.config",I)}static get(e){return y(this,void 0,void 0,(function*(){const t=yield te.findOne({where:{key:e}}).catch(ce.error);return t&&t.value||""}))}static set(e,t){return y(this,void 0,void 0,(function*(){const[r]=(yield te.findOrCreate({where:{key:e}}).catch(ce.error))||[];r&&(r.value=t,yield r.save().catch(ce.error))}))}}class he{static all(e,t){return y(this,void 0,void 0,(function*(){return yield Z.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:$,required:!0,include:[{model:J,required:!0,where:{state:!0},include:[{model:ee,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ie.error(e.message,"api.permission",I)}))}))}static get(e){return y(this,void 0,void 0,(function*(){const t=yield he.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return y(this,void 0,void 0,(function*(){const r=yield he.all(e,{name:t});return!!r&&r.length>0}))}}const pe=(t,r)=>{const i=e.uuidv4()+"."+r;return s.existsSync(p.join(t,i))?pe(t,r):i};class me extends e.EventEmitter{constructor(e){super(),this.router=r.Router(),this._path=e}auth(){return(e,t,r)=>y(this,void 0,void 0,(function*(){const s=e.get(j)||"",{auth:i,error:o,user:n}=yield ue.user(s);if(o)return oe.error(t,o);if(i&&n){const t=e.get("User-Agent");return t&&(i.useragent=t),yield i.save(),e.auth=i,e.user=n,r()}return oe.error(t,"Internal Server Error")}))}error(e){ie.error(e.message,"api.controller."+this.name(),I)}name(){return"api"}path(){return this._path}permission(e){return(t,r,s)=>y(this,void 0,void 0,(function*(){const i=t.user;return i?(yield he.is(i,e))?s():oe.error(r,"Unauthorized access"):oe.unauthorized(r,"Access denied")}))}read(e=""){return this.permission((e||this.name())+".read")}upload(e){const t=(null==e?void 0:e.path)||H,r=h.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>y(this,void 0,void 0,(function*(){return s(null,pe(t,c.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||U),i=h({storage:r,fileFilter(t,r,s){var i;return y(this,void 0,void 0,(function*(){const t=null===(i=null==e?void 0:e.types)||void 0===i?void 0:i.indexOf(r.mimetype);return void 0!==t&&t<0?s(new Error("File type not allowed")):s(null,!0)}))},limits:{fileSize:s}}),o=(null==e?void 0:e.count)||L,n=(null==e?void 0:e.field)||M,a=i.array(n,o);return(e,t,r)=>{a(e,t,(function(e){return e?oe.error(t,e.message):r()}))}}validation(t){return(r,s,i)=>y(this,void 0,void 0,(function*(){const{error:o,value:n}=yield e.Validation.object(t).validateAsync(r.body);return o?oe.validation(s,o):(r.body=n,i())}))}write(e=""){return this.permission((e||this.name())+".write")}}class ve extends me{add(){return(e,t)=>y(this,void 0,void 0,(function*(){if(!this._model)return oe.error(t,"Internal Server Error");const r=yield this._model.create(e.body).catch(this.error);return r?(this.emit("add",{req:e,record:r}),oe.data(t,{id:r.id})):oe.error(t,"Internal Server Error")}))}all(t,r){return(s,i)=>y(this,void 0,void 0,(function*(){var o,n,a,d,l;if(!this._model)return oe.error(i,"Internal Server Error");const c=Object.assign({},t||{});c.where=Object.assign({},c.where||{});const h=null===(o=s.query.limit)||void 0===o?void 0:o.toString();h&&(c.limit=parseInt(h));const p=null===(n=s.query.offset)||void 0===n?void 0:n.toString();p&&(c.offset=parseInt(p));const m=Object.keys(this._model.getAttributes()),v=[],g=null===(a=s.query.asc)||void 0===a?void 0:a.toString();g&&g.length&&g.split(",").forEach((e=>{m.indexOf(e)>=0&&v.push([e,"ASC"])}));const f=null===(d=s.query.desc)||void 0===d?void 0:d.toString();f&&f.length&&f.split(",").forEach((e=>{m.indexOf(e)>=0&&v.push([e,"DESC"])})),v.length&&(c.order=v);const y=[],I=e.isArray(c.attributes)?c.attributes:m,_=null===(l=s.query.search)||void 0===l?void 0:l.toString();I.forEach((t=>{var r;if(e.isString(t)&&(_&&_.length&&y.push({[t]:{[u.Op.like]:`%${_}%`}}),"search_"+t in s.query)){const e=null===(r=s.query["search_"+t])||void 0===r?void 0:r.toString();e&&e.length&&y.push({[t]:{[u.Op.like]:`%${e}%`}})}})),y.length&&(c.where=Object.assign(Object.assign({},c.where),{[u.Op.or]:[...y]}));const A=yield this._model.findAll(c).catch(this.error),T=yield this._model.count(c).catch(e.noop);return A?(this.emit("all",{req:s,records:A}),oe.data(i,{count:T,records:r?r(A):A})):oe.error(i,"Internal Server Error")}))}del(){return(e,t)=>y(this,void 0,void 0,(function*(){if(!this._model)return oe.error(t,"Internal Server Error");const{id:r}=e.params;return(yield this._model.destroy({where:{id:r}}).catch(this.error))?(this.emit("del",{req:e,id:r}),oe.success(t,"OK")):oe.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>y(this,void 0,void 0,(function*(){if(!this._model)return oe.error(s,"Internal Server Error");e||(e={});const i=Object.assign({},e);i.where=i.where?Object.assign({},i.where):{};const{id:o}=r.params,n=yield this._model.findByPk(o,i).catch(this.error);return n?(this.emit("get",{req:r,record:n}),oe.data(s,t?t(n):n.toJSON())):null===n?oe.notfound(s,"Record not found"):oe.error(s,"Internal Server Error")}))}name(){var e;return this._model?null===(e=this._model)||void 0===e?void 0:e.tableName:super.name()}set(){return(e,t)=>y(this,void 0,void 0,(function*(){if(!this._model)return oe.error(t,"Internal Server Error");const{id:r}=e.params,[s]=(yield this._model.update(e.body,{where:{id:r}}).catch(this.error))||[];return s?(this.emit("set",{req:e,id:r}),oe.success(t,"OK")):oe.success(t,"Record not changed")}))}getModel(){return this._model}setModel(e){this._model=e}}class ge extends ve{intialize(){const e=this.model();e&&this.setModel(e),this.router.use(this.auth()),this.router.get("/",this.read(),this.all().bind(this)),this.router.post("/",this.write(),this.validation(this.create()),this.add().bind(this)),this.router.route("/:id").get(this.read(),this.get().bind(this)).put(this.write(),this.validation(this.update()),this.set().bind(this)).delete(this.write(),this.del().bind(this))}}class fe extends u.Model{}fe.init({token:u.DataTypes.STRING,timestamp:u.DataTypes.BIGINT,state:u.DataTypes.BOOLEAN},{sequelize:Y,modelName:E+"registry",timestamps:!0,createdAt:"created",updatedAt:"updated"});exports.API_CONSOLE_ERROR=I,exports.API_DB_DATABASE=_,exports.API_DB_HOST=A,exports.API_DB_LOG=O,exports.API_DB_PASSWORD=T,exports.API_DB_PORT=b,exports.API_DB_TYPE=S,exports.API_DB_USERNAME=w,exports.API_HTTP_CROSS=D,exports.API_HTTP_CRT=P,exports.API_HTTP_HYBRID=N,exports.API_HTTP_KEY=x,exports.API_HTTP_PORT=q,exports.API_HTTP_PUBLIC=R,exports.API_SLEEP_AUTH=k,exports.API_SLEEP_FORGOT=B,exports.API_SLEEP_REGISTRY=C,exports.API_TABLE_PREFIX=E,exports.API_TOKEN_CRT=G,exports.API_TOKEN_HEADER=j,exports.API_TOKEN_KEY=V,exports.API_TOKEN_LIFETIME=z,exports.API_UPLOAD_COUNT=L,exports.API_UPLOAD_FIELD=M,exports.API_UPLOAD_SIZE=U,exports.API_UPLOAD_TEMP=H,exports.API_WEBSOCKET_START=K,exports.Application=le,exports.Auth=W,exports.AuthController=class extends me{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar"],this.query={username:e.Validation.string().min(4).required(),password:e.Validation.string().min(5).required()}}intialize(){this.router.get("/",this.auth(),this.user.bind(this)),this.router.post("/login",this.validation(this.query),this.login.bind(this)),this.router.get("/logout",this.auth(),this.logout.bind(this))}login(t,r){return y(this,void 0,void 0,(function*(){yield e.sleep(k);const{username:s,password:i}=t.body,o=yield Q.findOne({where:{username:s}}).catch(this.error);if(!o)return oe.notfound(r,"Username not found");if(!o.state)return oe.error(r,"Username is disabled");const n=m.SHA256(i).toString();if(o.password!=n)return oe.error(r,"Invalid password");const a=o.id,d=e.uniqueID(),{error:u,token:l}=ue.sign({id:a,secret:d});if(u)return oe.error(r,u);if(l){const e=Date.now(),s=e+6e4*z,i=t.get("User-Agent"),n=yield W.create({login:e,secret:d,timestamp:s,useragent:i,userId:a}).catch(this.error);if(n)return this.emit("login",{auth:n,req:t,user:o}),oe.data(r,{token:l})}return oe.error(r,"Internal Server Error")}))}logout(e,t){return y(this,void 0,void 0,(function*(){const r=e.auth,s=e.user;return r&&s&&!r.logout?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),this.emit("logout",{auth:r,req:e,user:s}),oe.success(t,"Disconcerted")):oe.unauthorized(t,"Access denied")}))}user(t,r){return y(this,void 0,void 0,(function*(){const s=t.user;if(!s)return oe.unauthorized(r,"Access denied");const i=yield he.all(s);if(i){const o=e.allowedObject(this.attributes,s.toJSON()),n=i.map((e=>e.name));return this.emit("user",{req:t,user:s}),oe.data(r,Object.assign(Object.assign({},o),{permissions:n}))}return oe.error(r,"Internal Server Error")}))}},exports.Config=ce,exports.Configs=te,exports.Controller=me,exports.CrudController=ge,exports.Database=F,exports.Forgot=X,exports.ForgotController=class extends me{constructor(){super(...arguments),this.username={username:e.Validation.string().min(4).required()},this.password={token:e.Validation.string().required(),password:e.Validation.string().min(5).required()},this.query={token:e.Validation.string().required()}}intialize(){this.router.post("/",this.validation(this.username),this.forgot.bind(this)),this.router.post("/check",this.validation(this.query),this.check.bind(this)),this.router.post("/reset",this.validation(this.password),this.reset.bind(this))}check(t,r){return y(this,void 0,void 0,(function*(){const{token:s}=t.body,i=yield this.findOne(s);return i&&i.user?(i.token=e.uniqueID(),yield i.save(),oe.data(r,{token:i.token})):oe.notfound(r,"User not found")}))}forgot(t,r){return y(this,void 0,void 0,(function*(){const{username:s}=t.body;yield e.sleep(B);const i=yield Q.findOne({where:{username:s}}).catch(this.error);if(!i)return oe.notfound(r,"User not found");const o=e.uniqueID(),n=Date.now()+6e4*z,a=yield X.create({token:o,timestamp:n,state:!0,userId:i.id});return this.emit("forgot",{forgot:a,req:t,user:i}),oe.success(r,"OK")}))}findOne(e){return y(this,void 0,void 0,(function*(){return yield X.findOne({where:{token:e,state:!0},include:[{model:Q,required:!0}]}).catch(this.error)}))}reset(e,t){return y(this,void 0,void 0,(function*(){const{token:r,password:s}=e.body,i=yield this.findOne(r);return i?(i.state=!1,yield i.save().catch(this.error),i.user.password=m.SHA256(s).toString(),yield i.user.save().catch(this.error),this.emit("reset",{req:e,user:i.user}),oe.success(t,"OK")):oe.notfound(t,"User not found")}))}},exports.Group=J,exports.GroupController=class extends ge{create(){return{name:e.Validation.string().required(),description:e.Validation.string().empty(""),state:e.Validation.boolean().parse().required()}}model(){return J}update(){return{name:e.Validation.string().empty(),description:e.Validation.string().empty(),state:e.Validation.boolean().parse().empty()}}},exports.GroupRoute=$,exports.GroupRouteController=class extends ve{constructor(){super(...arguments),this.groups={groups:e.Validation.array().items(e.Validation.number())}}intialize(){this.setModel($),this.router.use(this.auth()),this.router.route("/:id/groups").get(this.read("users"),this.groupRouteAll.bind(this)).put(this.write("users"),this.validation(this.groups),this.groupRouteSet.bind(this))}groupRouteAll(e,t){return y(this,void 0,void 0,(function*(){const{id:r}=e.params;return this.all({where:{groupId:r},include:[{model:Z,required:!0}]},(e=>e.map((e=>e.route))))(e,t)}))}groupRouteSet(t,r){return y(this,void 0,void 0,(function*(){const{id:s}=t.params,{routes:i}=t.body,o=yield J.findByPk(s,{attributes:["id"]}).catch(this.error);if(o){const e=o.id;if(yield $.destroy({where:{groupId:e}}),i){let t=0;for(let r=0;r<i.length;r++)t=yield Z.count({where:{id:i[r]}}),t&&(yield $.create({groupId:e,routeId:i[r]}))}return oe.success(r,"OK")}return e.isNull(o)?oe.notfound(r,"Record not found"):oe.error(r,"Internal Server Error")}))}},exports.Log=ie,exports.Logs=re,exports.LogsController=class extends ve{intialize(){this.setModel(re),this.router.use(this.auth()),this.router.get("/",this.read("logs"),this.logsAll.bind(this))}logsAll(e,t){return y(this,void 0,void 0,(function*(){const{source:r,type:s}=e.query,i=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return this.all({where:i,order:[["created","DESC"]]})(e,t)}))}},exports.ModelController=ve,exports.Permission=he,exports.RegisterController=class extends me{constructor(){super(...arguments),this.create={name:e.Validation.string().required(),email:e.Validation.string().email().required(),username:e.Validation.string().min(4).required(),password:e.Validation.string().min(5).required()},this.query={token:e.Validation.string().required()}}intialize(){this.router.post("/",this.validation(this.create),this.register.bind(this)),this.router.post("/confirm",this.validation(this.query),this.confirm.bind(this))}confirm(e,t){return y(this,void 0,void 0,(function*(){const{token:r}=e.body,s=yield fe.findOne({where:{token:r,state:!0},include:[{model:Q,required:!0}]}).catch(this.error);return s?(s.user.state=!0,yield s.user.save().catch(this.error),this.emit("confirm",{req:e,user:s.user}),oe.success(t,"OK")):oe.notfound(t,"User not found")}))}register(t,r){return y(this,void 0,void 0,(function*(){const{username:s}=t.body;yield e.sleep(B);const i=yield Q.findOne({where:{username:s}}).catch(this.error);if(i)return oe.error(r,"Invalid Username");if(!e.isNull(i))return oe.error(r,"Internal Server Error");const o=yield Q.create(Object.assign(Object.assign({},t.body),{state:!1}));return this.emit("register",{req:t,user:o}),oe.success(r,"OK")}))}},exports.Responses=oe,exports.Route=Z,exports.RouteController=class extends ge{create(){return{name:e.Validation.string().required(),description:e.Validation.string().empty(""),state:e.Validation.boolean().parse().required()}}model(){return Z}update(){return{name:e.Validation.string().empty(),description:e.Validation.string().empty(),state:e.Validation.boolean().empty()}}},exports.SetupController=class extends me{intialize(){this.router.get("/",this.setup.bind(this))}setup(t,r){return y(this,void 0,void 0,(function*(){if(0==(yield Q.count())){const t={description:"",state:!0},r=yield Q.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",avatar:""},t)),s=yield J.create(Object.assign({name:"admin"},t));yield ee.create({userId:r.id,groupId:s.id});const i=["read","write"],o=["users","groups","routes"];yield e.forEachSeries(o,(r=>y(this,void 0,void 0,(function*(){yield e.forEachSeries(i,(e=>y(this,void 0,void 0,(function*(){const i=r+"."+e,o=yield Z.create(Object.assign({name:i},t));yield $.create({groupId:s.id,routeId:o.id})}))))}))));const n=yield Z.create(Object.assign({name:"logs.read"},t));yield $.create({groupId:s.id,routeId:n.id})}return oe.success(r,"OK")}))}},exports.Token=ue,exports.User=Q,exports.UserController=class extends ve{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar","description","state","created","updated"],this.create={name:e.Validation.string().required(),email:e.Validation.string().email().required(),username:e.Validation.string().min(4).required(),password:e.Validation.string().min(5).required(),description:e.Validation.string().required(),state:e.Validation.boolean().parse().required()},this.update={name:e.Validation.string().empty(),email:e.Validation.string().email().empty(),username:e.Validation.string().min(4).empty(),password:e.Validation.string().min(5).empty(),description:e.Validation.string().empty(),state:e.Validation.boolean().parse().empty()}}intialize(){this.setModel(Q),this.router.use(this.auth()),this.router.get("/",this.read(),this.userAll.bind(this)),this.router.post("/",this.write(),this.validation(this.create),this.userAdd.bind(this)),this.router.route("/:id").get(this.read(),this.userGet.bind(this)).put(this.write(),this.validation(this.update),this.userSet.bind(this)).delete(this.write(),this.userDel.bind(this))}userAdd(e,t){return y(this,void 0,void 0,(function*(){return e.body.password=m.SHA256(e.body.password).toString(),yield this.add()(e,t)}))}userAll(e,t){return y(this,void 0,void 0,(function*(){return this.all({attributes:this.attributes})(e,t)}))}userDel(e,t){return y(this,void 0,void 0,(function*(){const r=e.user;if(r){const{id:s}=e.params;if(r.id.toString()!=s)return this.del()(e,t)}return oe.error(t,"Internal Server Error")}))}userGet(e,t){return y(this,void 0,void 0,(function*(){return this.get({attributes:this.attributes})(e,t)}))}userSet(e,t){return y(this,void 0,void 0,(function*(){return e.body.password&&(e.body.password=m.SHA256(e.body.password).toString()),this.set()(e,t)}))}},exports.UserGroup=ee,exports.UserGroupController=class extends ve{constructor(){super(...arguments),this.groups={groups:e.Validation.array(e.Validation.number())}}intialize(){this.setModel(ee),this.router.use(this.auth()),this.router.route("/:id/groups").get(this.read("groups"),this.userGroupsAll.bind(this)).put(this.write("groups"),this.validation(this.groups),this.userGroupsSet.bind(this))}userGroupsAll(e,t){return y(this,void 0,void 0,(function*(){const{id:r}=e.params;return this.all({where:{userId:r},include:[{model:J,required:!0}]},(e=>e.map((e=>e.group))))(e,t)}))}userGroupsSet(t,r){return y(this,void 0,void 0,(function*(){const{id:s}=t.params,{groups:i}=t.body,o=yield Q.findByPk(s,{attributes:["id"]}).catch(this.error);if(o){if(yield ee.destroy({where:{userId:o.id}}),i){let e=0;for(let t=0;t<i.length;t++)e=yield J.count({where:{id:i[t]}}),e&&(yield ee.create({userId:o.id,groupId:i[t]}))}return oe.success(r,"OK")}return e.isNull(o),oe.notfound(r,"Record not found")}))}},exports.crt=ae,exports.key=de,exports.sequelize=Y;
7
+ "use strict";var e=require("@andrewcaires/express"),t=require("@andrewcaires/utils.js"),r=require("ws"),s=require("sequelize"),o=require("dotenv"),n=require("fs"),i=require("jsonwebtoken"),a=require("crypto-js"),d=require("mime-types"),u=require("multer"),l=require("path");function p(e,t,r,s){var o,n=arguments.length,i=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,r):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,r,s);else for(var a=e.length-1;a>=0;a--)(o=e[a])&&(i=(n<3?o(i):n>3?o(t,r,i):o(t,r))||i);return n>3&&i&&Object.defineProperty(t,r,i),i}function c(e,t){return function(r,s){t(r,s,e)}}function g(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function y(e,t,r,s){return new(r||(r=Promise))((function(o,n){function i(e){try{d(s.next(e))}catch(e){n(e)}}function a(e){try{d(s.throw(e))}catch(e){n(e)}}function d(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,a)}d((s=s.apply(e,t||[])).next())}))}o.config();class m{}m.API_CONSOLE_ERROR=t.toBool(process.env.API_CONSOLE_ERROR||"false"),m.API_DB_DATABASE=process.env.API_DB_DATABASE||"",m.API_DB_HOST=process.env.API_DB_HOST||"127.0.0.1",m.API_DB_PASSWORD=process.env.API_DB_PASSWORD||"",m.API_DB_PORT=parseInt(process.env.API_DB_PORT||"3306"),m.API_DB_TYPE=process.env.API_DB_TYPE||"",m.API_DB_USERNAME=process.env.API_DB_USERNAME||"root",m.API_DB_LOG=t.toBool(process.env.API_DB_LOG||"false"),m.API_TABLE_PREFIX=process.env.API_TABLE_PREFIX||"",m.API_HTTP_CRT=process.env.API_HTTP_CRT||"",m.API_HTTP_KEY=process.env.API_HTTP_KEY||"",m.API_HTTP_PORT=parseInt(process.env.API_HTTP_PORT||"3000"),m.API_HTTP_PUBLIC=process.env.API_HTTP_PUBLIC||"",m.API_HTTP_CROSS=t.toBool(process.env.API_HTTP_CROSS||"false"),m.API_HTTP_HYBRID=t.toBool(process.env.API_HTTP_HYBRID||"false"),m.API_SLEEP_AUTH=parseInt(process.env.API_SLEEP_AUTH||"1000"),m.API_SLEEP_FORGOT=parseInt(process.env.API_SLEEP_FORGOT||"5000"),m.API_SLEEP_REGISTRY=parseInt(process.env.API_SLEEP_REGISTRY||"5000"),m.API_TOKEN_CRT=process.env.API_TOKEN_CRT||"",m.API_TOKEN_KEY=process.env.API_TOKEN_KEY||"",m.API_TOKEN_HEADER=process.env.API_TOKEN_HEADER||"authorization",m.API_TOKEN_LIFETIME=parseInt(process.env.API_TOKEN_LIFETIME||"15"),m.API_UPLOAD_COUNT=parseInt(process.env.API_UPLOAD_COUNT||"1"),m.API_UPLOAD_FIELD=process.env.API_UPLOAD_FIELD||"upload",m.API_UPLOAD_SIZE=parseInt(process.env.API_UPLOAD_SIZE||"2"),m.API_UPLOAD_TEMP=process.env.API_UPLOAD_TEMP||"./temp",m.API_WEBSOCKET_START=t.toBool(process.env.API_WEBSOCKET_START||"false");class h{static connect(e){const t=m.API_DB_TYPE.toLowerCase();if("connect_"+t in h)return h["connect_"+t](e);throw new Error("No database is connected to this API")}static connect_mariadb(e){return new s.Sequelize(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mariadb",logging:m.API_DB_LOG,define:{timestamps:!1}})}static connect_memory(){return new s.Sequelize("sqlite::memory:",{logging:m.API_DB_LOG,define:{timestamps:!1}})}static connect_mysql(e){return new s.Sequelize(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mysql",logging:m.API_DB_LOG,define:{timestamps:!1}})}static connect_postgres(e){return new s.Sequelize(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"postgres",logging:m.API_DB_LOG,define:{timestamps:!1}})}static connect_sqlite(e){return new s.Sequelize({dialect:"sqlite",storage:e.database,logging:m.API_DB_LOG,define:{timestamps:!1}})}}const R=h.connect({database:m.API_DB_DATABASE,username:m.API_DB_USERNAME,password:m.API_DB_PASSWORD,hostname:m.API_DB_HOST,hostport:m.API_DB_PORT});class v extends s.Model{}v.init({login:s.DataTypes.BIGINT,logout:s.DataTypes.BIGINT,secret:s.DataTypes.STRING,timestamp:s.DataTypes.BIGINT,useragent:s.DataTypes.STRING},{sequelize:R,modelName:m.API_TABLE_PREFIX+"auth",timestamps:!0,createdAt:"created",updatedAt:"updated"});class A extends s.Model{}A.init({token:s.DataTypes.STRING,timestamp:s.DataTypes.BIGINT,state:s.DataTypes.BOOLEAN},{sequelize:R,modelName:m.API_TABLE_PREFIX+"forgot",timestamps:!0,createdAt:"created",updatedAt:"updated"});class O extends s.Model{}O.init({name:s.DataTypes.STRING,description:s.DataTypes.TEXT,state:s.DataTypes.BOOLEAN},{sequelize:R,modelName:m.API_TABLE_PREFIX+"group",timestamps:!0,createdAt:"created",updatedAt:"updated"});class I extends s.Model{}I.init({name:s.DataTypes.STRING,description:s.DataTypes.TEXT,state:s.DataTypes.BOOLEAN},{sequelize:R,modelName:m.API_TABLE_PREFIX+"route",timestamps:!0,createdAt:"created",updatedAt:"updated"});class _ extends s.Model{}_.init({},{sequelize:R,modelName:m.API_TABLE_PREFIX+"groups_routes",timestamps:!0,createdAt:"created",updatedAt:!1}),_.removeAttribute("id");class P extends s.Model{}P.init({name:s.DataTypes.STRING,email:s.DataTypes.STRING,username:s.DataTypes.STRING,password:s.DataTypes.STRING,avatar:s.DataTypes.STRING,description:s.DataTypes.TEXT,state:s.DataTypes.BOOLEAN},{sequelize:R,modelName:m.API_TABLE_PREFIX+"user",timestamps:!0,createdAt:"created",updatedAt:"updated"});class f extends s.Model{}f.init({},{sequelize:R,modelName:m.API_TABLE_PREFIX+"users_groups",timestamps:!0,createdAt:"created",updatedAt:!1}),f.removeAttribute("id");class T extends s.Model{}T.init({key:s.DataTypes.STRING,value:s.DataTypes.STRING},{sequelize:R,modelName:m.API_TABLE_PREFIX+"configs",timestamps:!0,createdAt:"created",updatedAt:"updated"}),T.removeAttribute("id");class E extends s.Model{}var w;E.init({type:s.DataTypes.STRING,source:s.DataTypes.STRING,message:s.DataTypes.TEXT},{sequelize:R,modelName:m.API_TABLE_PREFIX+"logs",timestamps:!0,createdAt:"created",updatedAt:!1}),P.hasMany(v),v.belongsTo(P),P.hasMany(A),A.belongsTo(P),O.hasMany(_),_.belongsTo(O),I.hasMany(_),_.belongsTo(I),P.hasMany(f),f.belongsTo(P),O.hasMany(f),f.belongsTo(O),function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(w||(w={}));class b{static write(e,t,r){return y(this,void 0,void 0,(function*(){yield b.writeRaw(w.NONE,"",e,t,r)}))}static error(e,t,r){return y(this,void 0,void 0,(function*(){yield b.writeRaw(w.ERROR,"error",e,t,r)}))}static info(e,t,r){return y(this,void 0,void 0,(function*(){yield b.writeRaw(w.INFO,"info",e,t,r)}))}static success(e,t,r){return y(this,void 0,void 0,(function*(){yield b.writeRaw(w.ERROR,"success",e,t,r)}))}static warning(e,t,r){return y(this,void 0,void 0,(function*(){yield b.writeRaw(w.WARNING,"warning",e,t,r)}))}static writeConsole(e,r,s){const o=t.dateFormat(new Date,"%H:%M:%S");console.log(">",e,r+" ".repeat(10-r.length),"","|",o,"|",s)}static writeRaw(e,t,r,s,o){return y(this,void 0,void 0,(function*(){o&&b.writeConsole(e,t,r),R&&(yield E.create({type:t,source:s,message:r}).catch((()=>null)))}))}}const S=e=>n.existsSync(e)?n.readFileSync(e):void 0,q={http:S(m.API_HTTP_CRT),token:S(m.API_TOKEN_CRT)},x={http:S(m.API_HTTP_KEY),token:S(m.API_TOKEN_KEY)};class C{static error(e){b.error(e.message,"api.token",m.API_CONSOLE_ERROR)}static sign(e){return x.token?{token:i.sign(e,x.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static user(e){return y(this,void 0,void 0,(function*(){const{error:t,decode:r}=C.verify(e);if(t)return{error:t};if(r){const{id:e,secret:t}=r;if(e&&r){const r=yield P.findOne({where:{id:e,state:!0}}).catch(C.error);if(r){const e=yield v.findOne({where:{secret:t,userId:r.id}}).catch(C.error);if(e){const t=Date.now();if(t>e.timestamp)return e.logout=t,yield e.save(),{error:"Expired token"};if(e.timestamp=t+6e4*m.API_TOKEN_LIFETIME,!e.logout)return yield e.save(),{auth:e,user:r}}}return{error:"Access denied"}}}return{error:"Invalid token"}}))}static verify(e){if(!q.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:i.verify(e,q.token)}}catch(e){return{error:"Invalid Token"}}}}class D extends e.Application{constructor(e){super(e,{cert:q.http,cross:m.API_HTTP_CROSS,hybrid:m.API_HTTP_HYBRID,key:x.http,path:"/api",port:m.API_HTTP_PORT,public:m.API_HTTP_PUBLIC})}error(e,t){b.info(e.message,t,m.API_CONSOLE_ERROR)}log(e,t){b.info(e,t,!0)}listen(){const e=Object.create(null,{listen:{get:()=>super.listen}});return y(this,void 0,void 0,(function*(){yield R.sync(),yield e.listen.call(this),m.API_WEBSOCKET_START&&this.server&&(this._webSocket=new r.Server({server:this.server,verifyClient:(e,t)=>t(m.API_WEBSOCKET_START)}),this._webSocket.on("connection",((e,r)=>y(this,void 0,void 0,(function*(){r.url||(r.url="");const s=r.url.length<=1?"":r.url.replace(/\//g,".");let o;e.on("message",(t=>y(this,void 0,void 0,(function*(){if(o)try{const n=JSON.parse(t);this.emit("ws.message"+s,{data:n,message:t,req:r,user:o,ws:e})}catch(n){this.emit("ws.message"+s,{message:t,req:r,user:o,ws:e})}else{const{user:n}=yield C.user(t.toString());n&&(o=n,this.emit("ws.connection"+s,{req:r,user:o,ws:e}))}o||e.close()})))),e.on("close",(()=>{o&&this.emit("ws.close"+s,{user:o,ws:e})})),yield t.sleep(2e3),o||e.close()})))))}))}websocket(){return this._webSocket}}class j{static all(){return y(this,void 0,void 0,(function*(){const e=yield T.findAll().catch(j.error),t={};return e&&e.forEach((e=>{t[e.key]=e.value})),t}))}static del(e){return y(this,void 0,void 0,(function*(){return((yield T.destroy({where:{key:e}}).catch(j.error))||0)>0}))}static error(e){b.error(e.message,"api.config",m.API_CONSOLE_ERROR)}static get(e){return y(this,void 0,void 0,(function*(){const t=yield T.findOne({where:{key:e}}).catch(j.error);return t&&t.value||""}))}static set(e,t){return y(this,void 0,void 0,(function*(){const[r]=(yield T.findOrCreate({where:{key:e}}).catch(j.error))||[];r&&(r.value=t,yield r.save().catch(j.error))}))}}class N{static all(e,t){return y(this,void 0,void 0,(function*(){return yield I.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:_,required:!0,include:[{model:O,required:!0,where:{state:!0},include:[{model:f,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{b.error(e.message,"api.permission",m.API_CONSOLE_ERROR)}))}))}static get(e){return y(this,void 0,void 0,(function*(){const t=yield N.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return y(this,void 0,void 0,(function*(){const r=yield N.all(e,{name:t});return!!r&&r.length>0}))}}const F=e.parameterFactory((({req:e})=>e.auth)),G=e.parameterFactory((({req:e})=>e.user)),B=(e,r)=>{const s=t.uuidv4()+"."+r;return n.existsSync(l.join(e,s))?B(e,r):s};class M extends t.EventEmitter{auth(t,r,s,o,n){return y(this,void 0,void 0,(function*(){const{auth:i,error:a,user:d}=yield C.user(s);return a?e.Responses.error(t,a):i&&d?(o&&(i.useragent=o),yield i.save(),r.auth=i,r.user=d,n()):e.Responses.error(t,"Internal Server Error")}))}error(e){b.error(e.message,"api.controller",m.API_CONSOLE_ERROR)}name(){return"api"}permission(t,r,s,o){return y(this,void 0,void 0,(function*(){return r?(yield N.is(r,o))?s():e.Responses.error(t,"Unauthorized access"):e.Responses.unauthorized(t,"Access denied")}))}read(e,t,r,s){return this.permission(e,t,r,(s||this.name())+".read")}upload(t,r,s,o){const n=(null==o?void 0:o.path)||m.API_UPLOAD_TEMP,i=u.diskStorage({destination:(e,t,r)=>r(null,n),filename:(e,t,r)=>y(this,void 0,void 0,(function*(){return r(null,B(n,d.extension(t.mimetype)||"bin"))}))}),a=1e6*((null==o?void 0:o.size)||m.API_UPLOAD_SIZE),l=u({storage:i,fileFilter(e,t,r){var s;return y(this,void 0,void 0,(function*(){const e=null===(s=null==o?void 0:o.types)||void 0===s?void 0:s.indexOf(t.mimetype);return void 0!==e&&e<0?r(new Error("File type not allowed")):r(null,!0)}))},limits:{fileSize:a}}),p=(null==o?void 0:o.count)||m.API_UPLOAD_COUNT,c=(null==o?void 0:o.field)||m.API_UPLOAD_FIELD;l.array(c,p)(r,t,(r=>r?e.Responses.error(t,r.message):s()))}validation(r,s,o,n){return y(this,void 0,void 0,(function*(){const{error:i,value:a}=yield t.Validation.object(n).validateAsync(s.body);return i?e.Responses.validation(r,i):(s.body=a,o())}))}write(e,t,r,s){return this.permission(e,t,r,(s||this.name())+".write")}}p([c(0,e.Res()),c(1,e.Req()),c(2,e.Headers(m.API_TOKEN_HEADER)),c(3,e.Headers("user-agent")),c(4,e.Next()),g("design:type",Function),g("design:paramtypes",[Object,Object,String,String,Function]),g("design:returntype",Promise)],M.prototype,"auth",null),p([c(0,e.Res()),c(1,G()),c(2,e.Next()),c(3,e.Argument()),g("design:type",Function),g("design:paramtypes",[Object,P,Function,String]),g("design:returntype",Promise)],M.prototype,"permission",null),p([c(0,e.Res()),c(1,G()),c(2,e.Next()),c(3,e.Argument()),g("design:type",Function),g("design:paramtypes",[Object,P,Function,String]),g("design:returntype",void 0)],M.prototype,"read",null),p([c(0,e.Res()),c(1,e.Req()),c(2,e.Next()),c(3,e.Argument()),g("design:type",Function),g("design:paramtypes",[Object,Object,Function,Object]),g("design:returntype",void 0)],M.prototype,"upload",null),p([c(0,e.Res()),c(1,e.Req()),c(2,e.Next()),c(3,e.Argument()),g("design:type",Function),g("design:paramtypes",[Object,Object,Function,Object]),g("design:returntype",Promise)],M.prototype,"validation",null),p([c(0,e.Res()),c(1,G()),c(2,e.Next()),c(3,e.Argument()),g("design:type",Function),g("design:paramtypes",[Object,P,Function,String]),g("design:returntype",void 0)],M.prototype,"write",null),exports.AuthController=class extends M{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar"]}login(r,s,o,n){return y(this,void 0,void 0,(function*(){yield t.sleep(m.API_SLEEP_AUTH);const{username:i,password:d}=s.body,u=yield P.findOne({where:{username:i}}).catch(this.error);if(!u)return n.emit("auth.failure",{req:s}),e.Responses.notfound(r,"Username not found");if(!u.state)return n.emit("auth.failure",{req:s}),e.Responses.error(r,"Username is disabled");const l=a.SHA256(d).toString();if(u.password!=l)return n.emit("auth.failure",{req:s}),e.Responses.error(r,"Invalid password");const p=u.id,c=t.uniqueID(),{error:g,token:y}=C.sign({id:p,secret:c});if(g)return n.emit("auth.failure",{req:s}),e.Responses.error(r,g);if(y){const t=Date.now(),n=t+6e4*m.API_TOKEN_LIFETIME,i=yield v.create({login:t,secret:c,timestamp:n,useragent:o,userId:p}).catch(this.error);if(i)return this.emit("auth.login",{auth:i,req:s,user:u}),e.Responses.data(r,{token:y})}return n.emit("auth.failure",{req:s}),e.Responses.error(r,"Internal Server Error")}))}logout(t,r,s,o,n){return y(this,void 0,void 0,(function*(){return s&&o&&!s.logout?(s.logout=Date.now(),s.timestamp=s.logout,yield s.save(),n.emit("auth.logout",{auth:s,req:r,user:o}),e.Responses.success(t,"Disconcerted")):e.Responses.unauthorized(t,"Access denied")}))}user(r,s){return y(this,void 0,void 0,(function*(){const o=s.user;if(!o)return e.Responses.unauthorized(r,"Access denied");const n=yield N.all(o);if(n){const s=n.map((e=>e.name));return e.Responses.data(r,Object.assign(Object.assign({},t.allowedObject(this.attributes,o.toJSON())),{permissions:s}))}return e.Responses.error(r,"Internal Server Error")}))}},p([e.Post("/login"),e.Middleware("validation",{username:t.Validation.string().min(4).required(),password:t.Validation.string().min(5).required()}),c(0,e.Res()),c(1,e.Req()),c(2,e.Headers("user-agent")),c(3,e.App()),g("design:type",Function),g("design:paramtypes",[Object,Object,String,D]),g("design:returntype",Promise)],exports.AuthController.prototype,"login",null),p([e.Get("/logout"),e.Middleware("auth"),c(0,e.Res()),c(1,e.Req()),c(2,F()),c(3,G()),c(4,e.App()),g("design:type",Function),g("design:paramtypes",[Object,Object,v,P,D]),g("design:returntype",Promise)],exports.AuthController.prototype,"logout",null),p([e.Get(),e.Middleware("auth"),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.AuthController.prototype,"user",null),exports.AuthController=p([e.Controller("/auth")],exports.AuthController),exports.ForgotController=class extends M{check(r,s){return y(this,void 0,void 0,(function*(){const{token:o}=s.body,n=yield this.findOne(o);return n&&n.user?(n.token=t.uniqueID(),yield n.save(),e.Responses.data(r,{token:n.token})):e.Responses.notfound(r,"User not found")}))}forgot(r,s){return y(this,void 0,void 0,(function*(){const{username:o}=s.body;yield t.sleep(m.API_SLEEP_FORGOT);const n=yield P.findOne({where:{username:o}}).catch(this.error);if(!n)return e.Responses.notfound(r,"User not found");const i=t.uniqueID(),a=Date.now()+6e4*m.API_TOKEN_LIFETIME,d=yield A.create({token:i,timestamp:a,state:!0,userId:n.id});return this.emit("forgot",{forgot:d,req:s,user:n}),e.Responses.success(r,"OK")}))}reset(t,r){return y(this,void 0,void 0,(function*(){const{token:s,password:o}=r.body,n=yield this.findOne(s);return n?(n.state=!1,yield n.save().catch(this.error),n.user.password=a.SHA256(o).toString(),yield n.user.save().catch(this.error),this.emit("forgot.reset",{req:r,user:n.user}),e.Responses.success(t,"OK")):e.Responses.notfound(t,"User not found")}))}findOne(e){return y(this,void 0,void 0,(function*(){return yield A.findOne({where:{token:e,state:!0},include:[{model:P,required:!0}]}).catch(this.error)}))}},p([e.Get("/check"),e.Middleware("validation",{token:t.Validation.string().required()}),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.ForgotController.prototype,"check",null),p([e.Get(),e.Middleware("validation",{username:t.Validation.string().min(4).required()}),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.ForgotController.prototype,"forgot",null),p([e.Get("/reset"),e.Middleware("validation",{token:t.Validation.string().required(),password:t.Validation.string().min(5).required()}),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.ForgotController.prototype,"reset",null),exports.ForgotController=p([e.Controller("/forgot")],exports.ForgotController);class L extends M{add(t,r,s){return y(this,void 0,void 0,(function*(){const o=yield this.model().create(t.body,s||{}).catch(this.error);return o?e.Responses.data(r,{id:o.id}):e.Responses.error(r,"Internal Server Error")}))}all(r,o,n,i){var a,d,u,l,p;return y(this,void 0,void 0,(function*(){const c=this.model(),g=Object.assign({},n||{});g.where=Object.assign({},g.where||{});const y=null===(a=r.query.limit)||void 0===a?void 0:a.toString();y&&(g.limit=parseInt(y));const m=null===(d=r.query.offset)||void 0===d?void 0:d.toString();m&&(g.offset=parseInt(m));const h=Object.keys(c.getAttributes()),R=[],v=null===(u=r.query.asc)||void 0===u?void 0:u.toString();v&&v.length&&v.split(",").forEach((e=>{h.indexOf(e)>=0&&R.push([e,"ASC"])}));const A=null===(l=r.query.desc)||void 0===l?void 0:l.toString();A&&A.length&&A.split(",").forEach((e=>{h.indexOf(e)>=0&&R.push([e,"DESC"])})),R.length&&(g.order=R);const O=[],I=t.isArray(g.attributes)?g.attributes:h,_=null===(p=r.query.search)||void 0===p?void 0:p.toString();I.forEach((e=>{var o;if(t.isString(e)&&(_&&_.length&&O.push({[e]:{[s.Op.like]:`%${_}%`}}),"search_"+e in r.query)){const t=null===(o=r.query["search_"+e])||void 0===o?void 0:o.toString();t&&t.length&&O.push({[e]:{[s.Op.like]:`%${t}%`}})}})),O.length&&(g.where=Object.assign(Object.assign({},g.where),{[s.Op.or]:[...O]}));const P=yield c.count(Object.assign(Object.assign({},g),{col:h[0]})).catch(this.error),f=yield c.findAll(g).catch(this.error);return f?e.Responses.data(o,{count:P,records:i?i(f):f}):e.Responses.error(o,"Internal Server Error")}))}del(t,r,s){return y(this,void 0,void 0,(function*(){const{id:o}=t.params;if(!o)return e.Responses.error(r,"Internal Server Error");return(yield this.model().destroy(Object.assign(Object.assign({},s||{}),{where:{id:o}})).catch(this.error))?e.Responses.success(r,"OK"):e.Responses.notfound(r,"Record not found")}))}error(e){super.error(e),e.sql&&b.error(e.sql,"api.controller.sql",m.API_CONSOLE_ERROR)}get(t,r,s,o){return y(this,void 0,void 0,(function*(){const n=Object.assign({},s||{});n.where=n.where?Object.assign({},n.where):{};const{id:i}=t.params,a=yield this.model().findByPk(i,n).catch(this.error);return a?e.Responses.data(r,o?o(a):a.toJSON()):null===a?e.Responses.notfound(r,"Record not found"):e.Responses.error(r,"Internal Server Error")}))}name(){return this.model().tableName}set(t,r,s){return y(this,void 0,void 0,(function*(){const{id:o}=t.params,[n]=(yield this.model().update(t.body,Object.assign(Object.assign({},s||{}),{where:Object.assign(Object.assign({},(s||{}).where),{id:o})})).catch(this.error))||[];return n?e.Responses.success(r,"OK"):e.Responses.success(r,"Record not changed")}))}}class k extends L{create(){return{}}crudAdd(e,t){return this.add(e,t,this.optionsAdd())}crudAll(e,t){return this.all(e,t,this.optionsAll())}crudDel(e,t){return this.del(e,t,this.optionsDel())}crudGet(e,t){return this.get(e,t,this.optionsGet())}crudSet(e,t){return this.set(e,t,this.optionsSet())}optionsAdd(){return{}}optionsAll(){return{}}optionsDel(){return{}}optionsGet(){return{}}optionsSet(){return{where:{}}}update(){return{}}validationAdd(e,t,r){return this.validation(t,e,r,this.create())}validationSet(e,t,r){return this.validation(t,e,r,this.update())}}p([e.Post(),e.Middleware("auth"),e.Middleware("write"),e.Middleware("validationAdd"),c(0,e.Req()),c(1,e.Res()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",void 0)],k.prototype,"crudAdd",null),p([e.Get(),e.Middleware("auth"),e.Middleware("read"),c(0,e.Req()),c(1,e.Res()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",void 0)],k.prototype,"crudAll",null),p([e.Delete("/:id"),e.Middleware("auth"),e.Middleware("write"),c(0,e.Req()),c(1,e.Res()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",void 0)],k.prototype,"crudDel",null),p([e.Get("/:id"),e.Middleware("auth"),e.Middleware("read"),c(0,e.Req()),c(1,e.Res()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",void 0)],k.prototype,"crudGet",null),p([e.Put("/:id"),e.Middleware("auth"),e.Middleware("write"),e.Middleware("validationSet"),c(0,e.Req()),c(1,e.Res()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",void 0)],k.prototype,"crudSet",null),p([c(0,e.Req()),c(1,e.Res()),c(2,e.Next()),g("design:type",Function),g("design:paramtypes",[Object,Object,Function]),g("design:returntype",void 0)],k.prototype,"validationAdd",null),p([c(0,e.Req()),c(1,e.Res()),c(2,e.Next()),g("design:type",Function),g("design:paramtypes",[Object,Object,Function]),g("design:returntype",void 0)],k.prototype,"validationSet",null),exports.GroupController=class extends k{model(){return O}create(){return{name:t.Validation.string().required(),description:t.Validation.string().empty(""),state:t.Validation.boolean().parse().required()}}update(){return{name:t.Validation.string().empty(),description:t.Validation.string().empty(),state:t.Validation.boolean().parse().empty()}}},exports.GroupController=p([e.Controller("/groups")],exports.GroupController),exports.GroupRouteController=class extends L{model(){return _}groupRouteAll(e,t,r){return y(this,void 0,void 0,(function*(){return this.all(t,e,{where:{groupId:r},include:[{model:I,required:!0}]},(e=>e.map((e=>e.route))))}))}groupRouteSet(r,s,o){return y(this,void 0,void 0,(function*(){const n=yield O.findByPk(s,{attributes:["id"]}).catch(this.error);if(n){const t=n.id;if(yield _.destroy({where:{groupId:t}}),o){let e=0;for(let r=0;r<o.length;r++)e=yield I.count({where:{id:o[r]}}),e&&(yield _.create({groupId:t,routeId:o[r]}))}return e.Responses.success(r,"OK")}return t.isNull(n)?e.Responses.notfound(r,"Record not found"):e.Responses.error(r,"Internal Server Error")}))}},p([e.Get("/:id/routes"),e.Middleware("auth"),e.Middleware("read","routes"),c(0,e.Res()),c(1,e.Req()),c(2,e.Params("id")),g("design:type",Function),g("design:paramtypes",[Object,Object,String]),g("design:returntype",Promise)],exports.GroupRouteController.prototype,"groupRouteAll",null),p([e.Put("/:id/groups"),e.Middleware("auth"),e.Middleware("write","groups"),e.Middleware("validation",{routes:t.Validation.array(t.Validation.number().parse())}),c(0,e.Res()),c(1,e.Params("id")),c(2,e.Body("routes")),g("design:type",Function),g("design:paramtypes",[Object,String,Array]),g("design:returntype",Promise)],exports.GroupRouteController.prototype,"groupRouteSet",null),exports.GroupRouteController=p([e.Controller("/groups")],exports.GroupRouteController),exports.LogsController=class extends L{model(){return E}logsAll(e,t){return y(this,void 0,void 0,(function*(){const{source:r,type:s}=t.query,o=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return this.all(t,e,{where:o,order:[["created","DESC"]]})}))}},p([e.Get(),e.Middleware("auth"),e.Middleware("read"),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.LogsController.prototype,"logsAll",null),exports.LogsController=p([e.Controller("/logs")],exports.LogsController);class U extends s.Model{}U.init({token:s.DataTypes.STRING,timestamp:s.DataTypes.BIGINT,state:s.DataTypes.BOOLEAN},{sequelize:R,modelName:m.API_TABLE_PREFIX+"registry",timestamps:!0,createdAt:"created",updatedAt:"updated"}),exports.RegisterController=class extends M{confirm(t,r){return y(this,void 0,void 0,(function*(){const s=yield U.findOne({where:{token:r,state:!0},include:[{model:P,required:!0}]}).catch(this.error);return s?(s.user.state=!0,yield s.user.save().catch(this.error),this.emit("user.confirm",{user:s.user}),e.Responses.success(t,"OK")):e.Responses.notfound(t,"User not found")}))}register(r,s,o,n){return y(this,void 0,void 0,(function*(){yield t.sleep(m.API_SLEEP_REGISTRY);const s=yield P.findOne({where:{username:n}}).catch(this.error);if(s)return e.Responses.error(r,"Invalid Username");if(!t.isNull(s))return e.Responses.error(r,"Internal Server Error");const i=yield P.create(Object.assign(Object.assign({},o),{state:!1}));return this.emit("user.register",{user:i}),e.Responses.success(r,"OK")}))}},p([e.Get("/confirm"),e.Middleware("validation",{token:t.Validation.string().required()}),c(0,e.Res()),c(1,e.Body("token")),g("design:type",Function),g("design:paramtypes",[Object,String]),g("design:returntype",Promise)],exports.RegisterController.prototype,"confirm",null),p([e.Get(),e.Middleware("validation",{name:t.Validation.string().required(),email:t.Validation.string().email().required(),username:t.Validation.string().min(4).required(),password:t.Validation.string().min(5).required()}),c(0,e.Res()),c(1,e.Req()),c(2,e.Body()),c(3,e.Body("username")),g("design:type",Function),g("design:paramtypes",[Object,Object,Object,String]),g("design:returntype",Promise)],exports.RegisterController.prototype,"register",null),exports.RegisterController=p([e.Controller("/register")],exports.RegisterController),exports.RouteController=class extends k{model(){return I}create(){return{name:t.Validation.string().required(),description:t.Validation.string().empty(""),state:t.Validation.boolean().parse().required()}}update(){return{name:t.Validation.string().empty(),description:t.Validation.string().empty(),state:t.Validation.boolean().empty()}}},exports.RouteController=p([e.Controller("/routes")],exports.RouteController),exports.SetupController=class extends M{setup(r){return y(this,void 0,void 0,(function*(){if(0==(yield P.count())){const e={description:"",state:!0},r=yield P.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",avatar:""},e)),s=yield O.create(Object.assign({name:"admin"},e));yield f.create({userId:r.id,groupId:s.id});const o=["read","write"],n=["users","groups","routes"];yield t.forEachSeries(n,(r=>y(this,void 0,void 0,(function*(){yield t.forEachSeries(o,(t=>y(this,void 0,void 0,(function*(){const o=r+"."+t,n=yield I.create(Object.assign({name:o},e));yield _.create({groupId:s.id,routeId:n.id})}))))}))));const i=yield I.create(Object.assign({name:"logs.read"},e));yield _.create({groupId:s.id,routeId:i.id})}return e.Responses.success(r,"OK")}))}},p([e.Get(),c(0,e.Res()),g("design:type",Function),g("design:paramtypes",[Object]),g("design:returntype",Promise)],exports.SetupController.prototype,"setup",null),exports.SetupController=p([e.Controller("/setup")],exports.SetupController),exports.UserController=class extends L{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar","description","state","created","updated"]}model(){return P}userAdd(e,t){return y(this,void 0,void 0,(function*(){return t.body.password=a.SHA256(t.body.password).toString(),yield this.add(t,e)}))}userAll(e,t){return y(this,void 0,void 0,(function*(){return this.all(t,e,{attributes:this.attributes})}))}userDel(t,r,s,o){return y(this,void 0,void 0,(function*(){return s&&s.id.toString()!=o?this.del(r,t):e.Responses.error(t,"Internal Server Error")}))}userGet(e,t){return y(this,void 0,void 0,(function*(){return this.get(t,e,{attributes:this.attributes})}))}userSet(e,t){return y(this,void 0,void 0,(function*(){return t.body.password&&(t.body.password=a.SHA256(t.body.password).toString()),this.set(t,e)}))}},p([e.Post(),e.Middleware("auth"),e.Middleware("write"),e.Middleware("validation",{name:t.Validation.string().required(),email:t.Validation.string().email().required(),username:t.Validation.string().min(4).required(),password:t.Validation.string().min(5).required(),description:t.Validation.string().required(),state:t.Validation.boolean().parse().required()}),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.UserController.prototype,"userAdd",null),p([e.Get(),e.Middleware("auth"),e.Middleware("read"),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.UserController.prototype,"userAll",null),p([e.Delete("/:id"),e.Middleware("auth"),e.Middleware("write"),c(0,e.Res()),c(1,e.Req()),c(2,G()),c(3,e.Params("id")),g("design:type",Function),g("design:paramtypes",[Object,Object,P,String]),g("design:returntype",Promise)],exports.UserController.prototype,"userDel",null),p([e.Get("/:id"),e.Middleware("auth"),e.Middleware("read"),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.UserController.prototype,"userGet",null),p([e.Put("/:id"),e.Middleware("auth"),e.Middleware("write"),e.Middleware("validation",{name:t.Validation.string().empty(),email:t.Validation.string().email().empty(),username:t.Validation.string().min(4).empty(),password:t.Validation.string().min(5).empty(),description:t.Validation.string().empty(),state:t.Validation.boolean().parse().empty()}),c(0,e.Res()),c(1,e.Req()),g("design:type",Function),g("design:paramtypes",[Object,Object]),g("design:returntype",Promise)],exports.UserController.prototype,"userSet",null),exports.UserController=p([e.Controller("/users")],exports.UserController),exports.UserGroupController=class extends L{model(){return f}userGroupsAll(e,t,r){return y(this,void 0,void 0,(function*(){return this.all(t,e,{where:{userId:r},include:[{model:O,required:!0}]},(e=>e.map((e=>e.group))))}))}userGroupsSet(r,s,o){return y(this,void 0,void 0,(function*(){const n=yield P.findByPk(s,{attributes:["id"]}).catch(this.error);if(n){if(yield f.destroy({where:{userId:n.id}}),o){let e=0;for(let t=0;t<o.length;t++)e=yield O.count({where:{id:o[t]}}),e&&(yield f.create({userId:n.id,groupId:o[t]}))}return e.Responses.success(r,"OK")}return t.isNull(n)?e.Responses.notfound(r,"Record not found"):e.Responses.error(r,"Internal Server Error")}))}},p([e.Get("/:id/groups"),e.Middleware("auth"),e.Middleware("read","groups"),c(0,e.Res()),c(1,e.Req()),c(2,e.Params("id")),g("design:type",Function),g("design:paramtypes",[Object,Object,String]),g("design:returntype",Promise)],exports.UserGroupController.prototype,"userGroupsAll",null),p([e.Put("/:id/groups"),e.Middleware("auth"),e.Middleware("write","groups"),e.Middleware("validation",{groups:t.Validation.array(t.Validation.number().parse())}),c(0,e.Res()),c(1,e.Params("id")),c(2,e.Body("groups")),g("design:type",Function),g("design:paramtypes",[Object,String,Array]),g("design:returntype",Promise)],exports.UserGroupController.prototype,"userGroupsSet",null),exports.UserGroupController=p([e.Controller("/users")],exports.UserGroupController),exports.Application=D,exports.Auth=v,exports.Config=j,exports.Configs=T,exports.ControllerBase=M,exports.CrudController=k,exports.Database=h,exports.Env=m,exports.Forgot=A,exports.Group=O,exports.GroupRoute=_,exports.Log=b,exports.Logs=E,exports.ModelController=L,exports.Permission=N,exports.ReqAuth=F,exports.ReqUser=G,exports.Route=I,exports.Token=C,exports.User=P,exports.UserGroup=f,exports.crt=q,exports.key=x,exports.sequelize=R;
package/dist/index.d.ts CHANGED
@@ -1,17 +1,15 @@
1
1
  /*!
2
- * @andrewcaires/api v2.0.3
2
+ * @andrewcaires/api v3.0.0
3
3
  * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
4
4
  * (c) 2023 Andrew Caires
5
5
  * @license: MIT
6
6
  */
7
- import * as express_serve_static_core from 'express-serve-static-core';
8
- import { EventEmitter, TypeObject, ValidationBase, TypeObjectString } from '@andrewcaires/utils.js';
9
- import * as http from 'http';
10
- import * as https from 'https';
7
+ import * as _andrewcaires_express from '@andrewcaires/express';
8
+ import { Application as Application$1 } from '@andrewcaires/express';
11
9
  import WebSocket from 'ws';
12
- import { RequestHandler, Request, Response } from 'express';
13
- import { Model, FindOptions, Attributes, ModelStatic, Sequelize } from 'sequelize';
14
- import { WhereOptions } from 'sequelize/types';
10
+ import { EventEmitter, TypeObject, ValidationBase, TypeObjectString } from '@andrewcaires/utils.js';
11
+ import { Response, Request, NextFunction } from 'express';
12
+ import { Model, CreateOptions, Attributes, FindOptions, ModelStatic, UpdateOptions, Sequelize, WhereOptions } from 'sequelize';
15
13
 
16
14
  declare class Route extends Model {
17
15
  id: number;
@@ -23,8 +21,8 @@ declare class Route extends Model {
23
21
 
24
22
  declare class GroupRoute extends Model {
25
23
  groupId: number;
26
- routeId: number;
27
24
  group: Group;
25
+ routeId: number;
28
26
  route: Route;
29
27
  }
30
28
 
@@ -39,8 +37,8 @@ declare class Group extends Model {
39
37
 
40
38
  declare class UserGroup extends Model {
41
39
  userId: number;
42
- groupId: number;
43
40
  user: User;
41
+ groupId: number;
44
42
  group: Group;
45
43
  }
46
44
 
@@ -63,6 +61,7 @@ declare class Auth extends Model {
63
61
  secret: string;
64
62
  timestamp: number;
65
63
  useragent: string;
64
+ userId: number;
66
65
  user: User;
67
66
  }
68
67
 
@@ -86,14 +85,6 @@ declare class Logs extends Model {
86
85
  message: string;
87
86
  }
88
87
 
89
- declare global {
90
- namespace Express {
91
- interface Request {
92
- auth?: Auth;
93
- user?: User;
94
- }
95
- }
96
- }
97
88
  interface UploadOptions {
98
89
  count?: number;
99
90
  field?: string;
@@ -101,32 +92,23 @@ interface UploadOptions {
101
92
  size?: number;
102
93
  types?: string[];
103
94
  }
104
- declare abstract class Controller extends EventEmitter {
105
- private _path;
106
- readonly router: express_serve_static_core.Router;
107
- constructor(path: string);
108
- protected auth(): RequestHandler;
109
- protected error(error: any): void;
110
- abstract intialize(app: Application): void;
95
+ declare abstract class ControllerBase extends EventEmitter {
96
+ auth(res: Response, req: Request, token: string, useragent: string, next: NextFunction): Promise<void | _andrewcaires_express.ResponseJson>;
97
+ error(error: any): void;
111
98
  protected name(): string;
112
- path(): string;
113
- protected permission(name: string): RequestHandler;
114
- protected read(name?: string): RequestHandler;
115
- protected upload(options: UploadOptions): RequestHandler;
116
- protected validation(options: TypeObject<ValidationBase>): RequestHandler;
117
- protected write(name?: string): RequestHandler;
99
+ permission(res: Response, user: User, next: NextFunction, name: string): Promise<void | _andrewcaires_express.ResponseJson>;
100
+ read(res: Response, user: User, next: NextFunction, name: string): Promise<void | _andrewcaires_express.ResponseJson>;
101
+ upload(res: Response, req: Request, next: NextFunction, options: UploadOptions): void;
102
+ validation(res: Response, req: Request, next: NextFunction, options: TypeObject<ValidationBase>): Promise<void | _andrewcaires_express.ResponseJson>;
103
+ write(res: Response, user: User, next: NextFunction, name: string): Promise<void | _andrewcaires_express.ResponseJson>;
118
104
  }
119
105
 
120
- declare class Application extends EventEmitter {
121
- private _server?;
106
+ declare class Application extends Application$1 {
122
107
  private _webSocket?;
123
- readonly app: express_serve_static_core.Express;
124
- readonly router: express_serve_static_core.Router;
125
- constructor(controllers: Array<Controller>);
126
- private controllers;
108
+ constructor(controllers: Array<ControllerBase>);
109
+ error(error: any, source?: string): void;
110
+ log(message: string, source?: string): void;
127
111
  listen(): Promise<void>;
128
- private middlewares;
129
- server(): http.Server | https.Server | undefined;
130
112
  websocket(): WebSocket.Server | undefined;
131
113
  }
132
114
 
@@ -138,129 +120,96 @@ declare class Config {
138
120
  static set(key: string, value: string): Promise<void>;
139
121
  }
140
122
 
141
- declare const API_CONSOLE_ERROR: boolean;
142
- declare const API_DB_DATABASE: string;
143
- declare const API_DB_HOST: string;
144
- declare const API_DB_PASSWORD: string;
145
- declare const API_DB_PORT: number;
146
- declare const API_DB_TYPE: string;
147
- declare const API_DB_USERNAME: string;
148
- declare const API_DB_LOG: boolean;
149
- declare const API_TABLE_PREFIX: string;
150
- declare const API_HTTP_CRT: string;
151
- declare const API_HTTP_KEY: string;
152
- declare const API_HTTP_PORT: number;
153
- declare const API_HTTP_PUBLIC: string;
154
- declare const API_HTTP_CROSS: boolean;
155
- declare const API_HTTP_HYBRID: boolean;
156
- declare const API_SLEEP_AUTH: number;
157
- declare const API_SLEEP_FORGOT: number;
158
- declare const API_SLEEP_REGISTRY: number;
159
- declare const API_TOKEN_CRT: string;
160
- declare const API_TOKEN_KEY: string;
161
- declare const API_TOKEN_HEADER: string;
162
- declare const API_TOKEN_LIFETIME: number;
163
- declare const API_UPLOAD_COUNT: number;
164
- declare const API_UPLOAD_FIELD: string;
165
- declare const API_UPLOAD_SIZE: number;
166
- declare const API_UPLOAD_TEMP: string;
167
- declare const API_WEBSOCKET_START: boolean;
168
-
169
- declare class AuthController extends Controller {
123
+ declare class AuthController extends ControllerBase {
170
124
  readonly attributes: string[];
171
- private readonly query;
172
- intialize(): void;
173
- protected login(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
174
- protected logout(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
175
- protected user(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
176
- }
177
-
178
- declare class ForgotController extends Controller {
179
- private readonly username;
180
- private readonly password;
181
- private readonly query;
182
- intialize(): void;
183
- protected check(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
184
- protected forgot(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
125
+ protected login(res: Response, req: Request, useragent: string, app: Application): Promise<_andrewcaires_express.ResponseJson>;
126
+ protected logout(res: Response, req: Request, auth: Auth, user: User, app: Application): Promise<_andrewcaires_express.ResponseJson>;
127
+ protected user(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
128
+ }
129
+
130
+ declare class ForgotController extends ControllerBase {
131
+ check(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
132
+ forgot(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
133
+ reset(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
185
134
  private findOne;
186
- protected reset(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
187
135
  }
188
136
 
189
137
  type FnRecord<M> = (records: M) => any;
190
138
  type FnRecords<M> = (records: Array<M>) => Array<any>;
191
- declare abstract class ModelController<M extends Model<M>> extends Controller {
192
- private _model?;
193
- protected add(): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
194
- protected all(options?: FindOptions<Attributes<M>>, fn?: FnRecords<M>): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
195
- protected del(): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
196
- protected get(options?: FindOptions<Attributes<M>>, fn?: FnRecord<M>): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
139
+ declare abstract class ModelController<M extends Model<M>> extends ControllerBase {
140
+ protected add(req: Request, res: Response, options?: CreateOptions<Attributes<M>>): Promise<_andrewcaires_express.ResponseJson>;
141
+ protected all(req: Request, res: Response, options?: FindOptions<Attributes<M>>, fn?: FnRecords<M>): Promise<_andrewcaires_express.ResponseJson>;
142
+ protected del(req: Request, res: Response, options?: FindOptions<Attributes<M>>): Promise<_andrewcaires_express.ResponseJson>;
143
+ error(error: any): void;
144
+ protected get(req: Request, res: Response, options?: FindOptions<Attributes<M>>, fn?: FnRecord<M>): Promise<_andrewcaires_express.ResponseJson>;
145
+ abstract model(): ModelStatic<M>;
197
146
  protected name(): string;
198
- protected set(): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
199
- protected getModel(): ModelStatic<M> | undefined;
200
- protected setModel(model: ModelStatic<M>): void;
147
+ protected set(req: Request, res: Response, options?: UpdateOptions<Attributes<M>>): Promise<_andrewcaires_express.ResponseJson>;
201
148
  }
202
149
 
203
150
  declare abstract class CrudController<M extends Model<M>> extends ModelController<M> {
204
- protected abstract create(): TypeObject<ValidationBase>;
205
- intialize(): void;
206
- protected abstract model(): ModelStatic<M>;
207
- protected abstract update(): TypeObject<ValidationBase>;
151
+ create(): TypeObject<ValidationBase>;
152
+ crudAdd(req: Request, res: Response): Promise<_andrewcaires_express.ResponseJson>;
153
+ crudAll(req: Request, res: Response): Promise<_andrewcaires_express.ResponseJson>;
154
+ crudDel(req: Request, res: Response): Promise<_andrewcaires_express.ResponseJson>;
155
+ crudGet(req: Request, res: Response): Promise<_andrewcaires_express.ResponseJson>;
156
+ crudSet(req: Request, res: Response): Promise<_andrewcaires_express.ResponseJson>;
157
+ optionsAdd(): CreateOptions<Attributes<M>>;
158
+ optionsAll(): FindOptions<Attributes<M>>;
159
+ optionsDel(): FindOptions<Attributes<M>>;
160
+ optionsGet(): FindOptions<Attributes<M>>;
161
+ optionsSet(): UpdateOptions<Attributes<M>>;
162
+ update(): TypeObject<ValidationBase>;
163
+ validationAdd(req: Request, res: Response, next: NextFunction): Promise<void | _andrewcaires_express.ResponseJson>;
164
+ validationSet(req: Request, res: Response, next: NextFunction): Promise<void | _andrewcaires_express.ResponseJson>;
208
165
  }
209
166
 
210
167
  declare class GroupController extends CrudController<Group> {
211
- protected create(): TypeObject<ValidationBase>;
212
- protected model(): ModelStatic<Group>;
213
- protected update(): TypeObject<ValidationBase>;
168
+ model(): typeof Group;
169
+ create(): TypeObject<ValidationBase>;
170
+ update(): TypeObject<ValidationBase>;
214
171
  }
215
172
 
216
173
  declare class GroupRouteController extends ModelController<GroupRoute> {
217
- private readonly groups;
218
- intialize(): void;
219
- protected groupRouteAll(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
220
- protected groupRouteSet(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
174
+ model(): typeof GroupRoute;
175
+ groupRouteAll(res: Response, req: Request, groupId: string): Promise<_andrewcaires_express.ResponseJson>;
176
+ groupRouteSet(res: Response, id: string, routes: Array<number>): Promise<_andrewcaires_express.ResponseJson>;
221
177
  }
222
178
 
223
179
  declare class LogsController extends ModelController<Logs> {
224
- intialize(): void;
225
- protected logsAll(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
180
+ model(): typeof Logs;
181
+ protected logsAll(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
226
182
  }
227
183
 
228
- declare class RegisterController extends Controller {
229
- private readonly create;
230
- private readonly query;
231
- intialize(): void;
232
- confirm(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
233
- register(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
184
+ declare class RegisterController extends ControllerBase {
185
+ confirm(res: Response, token: string): Promise<_andrewcaires_express.ResponseJson>;
186
+ register(res: Response, req: Request, body: any, username: string): Promise<_andrewcaires_express.ResponseJson>;
234
187
  }
235
188
 
236
189
  declare class RouteController extends CrudController<Route> {
237
- protected create(): TypeObject<ValidationBase>;
238
- protected model(): ModelStatic<Route>;
239
- protected update(): TypeObject<ValidationBase>;
190
+ model(): typeof Route;
191
+ create(): TypeObject<ValidationBase>;
192
+ update(): TypeObject<ValidationBase>;
240
193
  }
241
194
 
242
- declare class SetupController extends Controller {
243
- intialize(): void;
244
- protected setup(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
195
+ declare class SetupController extends ControllerBase {
196
+ protected setup(res: Response): Promise<_andrewcaires_express.ResponseJson>;
245
197
  }
246
198
 
247
199
  declare class UserController extends ModelController<User> {
248
200
  private readonly attributes;
249
- private readonly create;
250
- private readonly update;
251
- intialize(): void;
252
- protected userAdd(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
253
- protected userAll(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
254
- protected userDel(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
255
- protected userGet(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
256
- protected userSet(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
201
+ model(): typeof User;
202
+ userAdd(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
203
+ protected userAll(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
204
+ protected userDel(res: Response, req: Request, user: User, id: string): Promise<_andrewcaires_express.ResponseJson>;
205
+ protected userGet(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
206
+ protected userSet(res: Response, req: Request): Promise<_andrewcaires_express.ResponseJson>;
257
207
  }
258
208
 
259
209
  declare class UserGroupController extends ModelController<UserGroup> {
260
- private readonly groups;
261
- intialize(): void;
262
- protected userGroupsAll(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
263
- protected userGroupsSet(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
210
+ model(): typeof UserGroup;
211
+ userGroupsAll(res: Response, req: Request, userId: string): Promise<_andrewcaires_express.ResponseJson>;
212
+ userGroupsSet(res: Response, id: string, groups: Array<number>): Promise<_andrewcaires_express.ResponseJson>;
264
213
  }
265
214
 
266
215
  interface DatabaseOptions {
@@ -280,6 +229,47 @@ declare class Database {
280
229
  }
281
230
  declare const sequelize: Sequelize;
282
231
 
232
+ declare class Env {
233
+ static readonly API_CONSOLE_ERROR: boolean;
234
+ static readonly API_DB_DATABASE: string;
235
+ static readonly API_DB_HOST: string;
236
+ static readonly API_DB_PASSWORD: string;
237
+ static readonly API_DB_PORT: number;
238
+ static readonly API_DB_TYPE: string;
239
+ static readonly API_DB_USERNAME: string;
240
+ static readonly API_DB_LOG: boolean;
241
+ static readonly API_TABLE_PREFIX: string;
242
+ static readonly API_HTTP_CRT: string;
243
+ static readonly API_HTTP_KEY: string;
244
+ static readonly API_HTTP_PORT: number;
245
+ static readonly API_HTTP_PUBLIC: string;
246
+ static readonly API_HTTP_CROSS: boolean;
247
+ static readonly API_HTTP_HYBRID: boolean;
248
+ static readonly API_SLEEP_AUTH: number;
249
+ static readonly API_SLEEP_FORGOT: number;
250
+ static readonly API_SLEEP_REGISTRY: number;
251
+ static readonly API_TOKEN_CRT: string;
252
+ static readonly API_TOKEN_KEY: string;
253
+ static readonly API_TOKEN_HEADER: string;
254
+ static readonly API_TOKEN_LIFETIME: number;
255
+ static readonly API_UPLOAD_COUNT: number;
256
+ static readonly API_UPLOAD_FIELD: string;
257
+ static readonly API_UPLOAD_SIZE: number;
258
+ static readonly API_UPLOAD_TEMP: string;
259
+ static readonly API_WEBSOCKET_START: boolean;
260
+ }
261
+
262
+ declare global {
263
+ namespace Express {
264
+ interface Request {
265
+ auth?: Auth;
266
+ user?: User;
267
+ }
268
+ }
269
+ }
270
+ declare const ReqAuth: (key?: string | undefined) => ParameterDecorator;
271
+ declare const ReqUser: (key?: string | undefined) => ParameterDecorator;
272
+
283
273
  declare class Log {
284
274
  static write(message: string, source?: string, console?: boolean): Promise<void>;
285
275
  static error(message: string, source?: string, console?: boolean): Promise<void>;
@@ -296,17 +286,6 @@ declare class Permission {
296
286
  static is(user: User, name: string): Promise<boolean>;
297
287
  }
298
288
 
299
- type ResponseJson = Response<any, Record<string, any>>;
300
- declare class Responses {
301
- static success(res: Response, message: string): ResponseJson;
302
- static data(res: Response, obj: object): ResponseJson;
303
- static error(res: Response, message: string): ResponseJson;
304
- static list(res: Response, arr: Array<any>): ResponseJson;
305
- static notfound(res: Response, message: string): ResponseJson;
306
- static validation(res: Response, message: string): ResponseJson;
307
- static unauthorized(res: Response, message: string): ResponseJson;
308
- }
309
-
310
289
  declare const crt: {
311
290
  http: Buffer | undefined;
312
291
  token: Buffer | undefined;
@@ -336,4 +315,4 @@ declare class Token {
336
315
  static verify(token: string): TokenVerify;
337
316
  }
338
317
 
339
- export { API_CONSOLE_ERROR, API_DB_DATABASE, API_DB_HOST, API_DB_LOG, API_DB_PASSWORD, API_DB_PORT, API_DB_TYPE, API_DB_USERNAME, API_HTTP_CROSS, API_HTTP_CRT, API_HTTP_HYBRID, API_HTTP_KEY, API_HTTP_PORT, API_HTTP_PUBLIC, API_SLEEP_AUTH, API_SLEEP_FORGOT, API_SLEEP_REGISTRY, API_TABLE_PREFIX, API_TOKEN_CRT, API_TOKEN_HEADER, API_TOKEN_KEY, API_TOKEN_LIFETIME, API_UPLOAD_COUNT, API_UPLOAD_FIELD, API_UPLOAD_SIZE, API_UPLOAD_TEMP, API_WEBSOCKET_START, Application, Auth, AuthController, Config, Configs, Controller, CrudController, Database, Forgot, ForgotController, Group, GroupController, GroupRoute, GroupRouteController, Log, Logs, LogsController, ModelController, Permission, RegisterController, Responses, Route, RouteController, SetupController, Token, User, UserController, UserGroup, UserGroupController, crt, key, sequelize };
318
+ export { Application, Auth, AuthController, Config, Configs, ControllerBase, CrudController, Database, Env, Forgot, ForgotController, Group, GroupController, GroupRoute, GroupRouteController, Log, Logs, LogsController, ModelController, Permission, RegisterController, ReqAuth, ReqUser, Route, RouteController, SetupController, Token, User, UserController, UserGroup, UserGroupController, crt, key, sequelize };
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @andrewcaires/api v2.0.3
2
+ * @andrewcaires/api v3.0.0
3
3
  * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
4
4
  * (c) 2023 Andrew Caires
5
5
  * @license: MIT
6
6
  */
7
- import{toBool as e,dateFormat as t,EventEmitter as r,sleep as s,Validation as i,uuidv4 as n,uniqueID as o,allowedObject as a,isArray as d,isString as u,noop as c,isNull as l,forEachSeries as h}from"@andrewcaires/utils.js";import p from"cors";import m,{Router as v,json as g,urlencoded as f}from"express";import{existsSync as y,readFileSync as w}from"fs";import*as I from"http";import*as b from"https";import{Server as A}from"net";import _ from"ws";import{config as S}from"dotenv";import{Sequelize as O,DataTypes as q,Model as E,Op as T}from"sequelize";import{sign as R,verify as N}from"jsonwebtoken";import P from"mime-types";import k from"multer";import{join as x}from"path";import{SHA256 as G}from"crypto-js";function j(e,t,r,s){return new(r||(r=Promise))((function(i,n){function o(e){try{d(s.next(e))}catch(e){n(e)}}function a(e){try{d(s.throw(e))}catch(e){n(e)}}function d(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(o,a)}d((s=s.apply(e,t||[])).next())}))}S();const z=e(process.env.API_CONSOLE_ERROR||"false"),D=process.env.API_DB_DATABASE||"",B=process.env.API_DB_HOST||"127.0.0.1",L=process.env.API_DB_PASSWORD||"",U=parseInt(process.env.API_DB_PORT||"3306"),C=process.env.API_DB_TYPE||"",M=process.env.API_DB_USERNAME||"root",K=e(process.env.API_DB_LOG||"false"),H=process.env.API_TABLE_PREFIX||"",F=process.env.API_HTTP_CRT||"",X=process.env.API_HTTP_KEY||"",Y=parseInt(process.env.API_HTTP_PORT||"3000"),W=process.env.API_HTTP_PUBLIC||"",J=e(process.env.API_HTTP_CROSS||"false"),$=e(process.env.API_HTTP_HYBRID||"false"),Z=parseInt(process.env.API_SLEEP_AUTH||"1000"),Q=parseInt(process.env.API_SLEEP_FORGOT||"5000"),V=parseInt(process.env.API_SLEEP_REGISTRY||"5000"),ee=process.env.API_TOKEN_CRT||"",te=process.env.API_TOKEN_KEY||"",re=process.env.API_TOKEN_HEADER||"authorization",se=parseInt(process.env.API_TOKEN_LIFETIME||"15"),ie=parseInt(process.env.API_UPLOAD_COUNT||"1"),ne=process.env.API_UPLOAD_FIELD||"upload",oe=parseInt(process.env.API_UPLOAD_SIZE||"2"),ae=process.env.API_UPLOAD_TEMP||"./temp",de=e(process.env.API_WEBSOCKET_START||"false");class ue{static connect(e){const t=C.toLowerCase();if("connect_"+t in ue)return ue["connect_"+t](e);throw new Error("No database is connected to this API")}static connect_mariadb(e){return new O(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mariadb",logging:K,define:{timestamps:!1}})}static connect_memory(){return new O("sqlite::memory:",{logging:K,define:{timestamps:!1}})}static connect_mysql(e){return new O(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mysql",logging:K,define:{timestamps:!1}})}static connect_postgres(e){return new O(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"postgres",logging:K,define:{timestamps:!1}})}static connect_sqlite(e){return new O({dialect:"sqlite",storage:e.database,logging:K,define:{timestamps:!1}})}}const ce=ue.connect({database:D,username:M,password:L,hostname:B,hostport:U});class le extends E{}le.init({login:q.BIGINT,logout:q.BIGINT,secret:q.STRING,timestamp:q.BIGINT,useragent:q.STRING},{sequelize:ce,modelName:H+"auth",timestamps:!0,createdAt:"created",updatedAt:"updated"});class he extends E{}he.init({token:q.STRING,timestamp:q.BIGINT,state:q.BOOLEAN},{sequelize:ce,modelName:H+"forgot",timestamps:!0,createdAt:"created",updatedAt:"updated"});class pe extends E{}pe.init({name:q.STRING,description:q.TEXT,state:q.BOOLEAN},{sequelize:ce,modelName:H+"group",timestamps:!0,createdAt:"created",updatedAt:"updated"});class me extends E{}me.init({name:q.STRING,description:q.TEXT,state:q.BOOLEAN},{sequelize:ce,modelName:H+"route",timestamps:!0,createdAt:"created",updatedAt:"updated"});class ve extends E{}ve.init({},{sequelize:ce,modelName:H+"groups_routes",timestamps:!0,createdAt:"created",updatedAt:!1}),ve.removeAttribute("id");class ge extends E{}ge.init({name:q.STRING,email:q.STRING,username:q.STRING,password:q.STRING,avatar:q.STRING,description:q.TEXT,state:q.BOOLEAN},{sequelize:ce,modelName:H+"user",timestamps:!0,createdAt:"created",updatedAt:"updated"});class fe extends E{}fe.init({},{sequelize:ce,modelName:H+"users_groups",timestamps:!0,createdAt:"created",updatedAt:!1}),fe.removeAttribute("id");class ye extends E{}ye.init({key:q.STRING,value:q.STRING},{sequelize:ce,modelName:H+"configs",timestamps:!0,createdAt:"created",updatedAt:"updated"}),ye.removeAttribute("id");class we extends E{}var Ie;we.init({type:q.STRING,source:q.STRING,message:q.TEXT},{sequelize:ce,modelName:H+"logs",timestamps:!0,createdAt:"created",updatedAt:!1}),ge.hasMany(le),le.belongsTo(ge),ge.hasMany(he),he.belongsTo(ge),pe.hasMany(ve),ve.belongsTo(pe),me.hasMany(ve),ve.belongsTo(me),ge.hasMany(fe),fe.belongsTo(ge),pe.hasMany(fe),fe.belongsTo(pe),function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(Ie||(Ie={}));class be{static write(e,t,r){return j(this,void 0,void 0,(function*(){yield be.writeRaw(Ie.NONE,"",e,t,r)}))}static error(e,t,r){return j(this,void 0,void 0,(function*(){yield be.writeRaw(Ie.ERROR,"error",e,t,r)}))}static info(e,t,r){return j(this,void 0,void 0,(function*(){yield be.writeRaw(Ie.INFO,"info",e,t,r)}))}static success(e,t,r){return j(this,void 0,void 0,(function*(){yield be.writeRaw(Ie.ERROR,"success",e,t,r)}))}static warning(e,t,r){return j(this,void 0,void 0,(function*(){yield be.writeRaw(Ie.WARNING,"warning",e,t,r)}))}static writeConsole(e,r,s){const i=t(new Date,"%H:%M:%S");console.log(">",e,r+" ".repeat(10-r.length),"","|",i,"|",s)}static writeRaw(e,t,r,s,i){return j(this,void 0,void 0,(function*(){i&&be.writeConsole(e,t,r),ce&&(yield we.create({type:t,source:s,message:r}).catch((()=>null)))}))}}class Ae{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t){return e.status(400).json({message:t})}static unauthorized(e,t){return e.status(401).json({message:t})}}const _e=e=>y(e)?w(e):void 0,Se={http:_e(F),token:_e(ee)},Oe={http:_e(X),token:_e(te)};class qe{static error(e){be.error(e.message,"api.token",z)}static sign(e){return Oe.token?{token:R(e,Oe.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static user(e){return j(this,void 0,void 0,(function*(){const{error:t,decode:r}=qe.verify(e);if(t)return{error:t};if(r){const{id:e,secret:t}=r;if(e&&r){const r=yield ge.findOne({where:{id:e,state:!0}}).catch(qe.error);if(r){const e=yield le.findOne({where:{secret:t,userId:r.id}}).catch(qe.error);if(e){const t=Date.now();if(t>e.timestamp)return e.logout=t,yield e.save(),{error:"Expired token"};if(e.timestamp=t+6e4*se,!e.logout)return yield e.save(),{auth:e,user:r}}}return{error:"Access denied"}}}return{error:"Invalid token"}}))}static verify(e){if(!Se.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:N(e,Se.token)}}catch(e){return{error:"Invalid Token"}}}}class Ee extends r{constructor(e){super(),this.app=m(),this.router=v(),this.middlewares(),this.controllers(e)}controllers(e){e.forEach((e=>{e.intialize(this),this.router.use(e.path(),e.router)}))}listen(){return j(this,void 0,void 0,(function*(){if(yield ce.sync(),Se.http&&Oe.http||(this._server=I.createServer(this.app),this._server.listen(Y,(()=>be.info("Server started on port "+Y,"api.server",!0)))),!this._server){const e=I.createServer(((e,t)=>{const r=80==Y?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),t=b.createServer({key:Oe.http,cert:Se.http},this.app);if($){new A((r=>{r.once("data",(s=>{r.pause(),r.unshift(s),(22===s[0]?t:e).emit("connection",r),process.nextTick((()=>r.resume()))}))})).listen(Y,(()=>be.info("Server started on port "+Y,"api.server",!0))),this._server=t}this._server||(443==Y&&e.listen(80,(()=>be.info("Server started on port 80","api.server",!0))),t.listen(Y,(()=>be.info("Server started on port "+Y,"api.server",!0))),this._server=t)}de&&this._server&&(this._webSocket=new _.Server({server:this._server,verifyClient:(e,t)=>t(de)}),this._webSocket.on("connection",((e,t)=>j(this,void 0,void 0,(function*(){t.url||(t.url="");const r=t.url.length<=1?"":t.url.replace(/\//g,".");let i;e.on("message",(s=>j(this,void 0,void 0,(function*(){if(i)try{const n=JSON.parse(s);this.emit("ws.message"+r,{data:n,message:s,req:t,user:i,ws:e})}catch(n){this.emit("ws.message"+r,{message:s,req:t,user:i,ws:e})}else{const{user:n}=yield qe.user(s.toString());n&&(i=n,this.emit("ws.connection"+r,{req:t,user:i,ws:e}))}i||e.close()})))),e.on("close",(()=>{i&&this.emit("ws.close"+r,{user:i,ws:e})})),yield s(2e3),i||e.close()})))))}))}middlewares(){this.app.use(g()),this.app.use(((e,t,r,s)=>e?(be.error(e.message,"api.express",z),Ae.error(r,"Internal Server Error")):s())),this.app.use(f({extended:!0})),this.app.disable("x-powered-by"),J&&this.app.use(p()),this.app.use("/api",this.router),this.app.all("/api/*",((e,t)=>Ae.notfound(t,"Invalid API"))),W&&(y(W)&&this.app.use(m.static(W)),this.app.get("*",((e,t)=>{if(!y(W))return Ae.notfound(t,'File "index.html" not found');t.sendFile(W+"/index.html")})))}server(){return this._server}websocket(){return this._webSocket}}class Te{static all(){return j(this,void 0,void 0,(function*(){const e=yield ye.findAll().catch(Te.error),t={};return e&&e.forEach((e=>{t[e.key]=e.value})),t}))}static del(e){return j(this,void 0,void 0,(function*(){return((yield ye.destroy({where:{key:e}}).catch(Te.error))||0)>0}))}static error(e){be.error(e.message,"api.config",z)}static get(e){return j(this,void 0,void 0,(function*(){const t=yield ye.findOne({where:{key:e}}).catch(Te.error);return t&&t.value||""}))}static set(e,t){return j(this,void 0,void 0,(function*(){const[r]=(yield ye.findOrCreate({where:{key:e}}).catch(Te.error))||[];r&&(r.value=t,yield r.save().catch(Te.error))}))}}class Re{static all(e,t){return j(this,void 0,void 0,(function*(){return yield me.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:ve,required:!0,include:[{model:pe,required:!0,where:{state:!0},include:[{model:fe,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{be.error(e.message,"api.permission",z)}))}))}static get(e){return j(this,void 0,void 0,(function*(){const t=yield Re.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return j(this,void 0,void 0,(function*(){const r=yield Re.all(e,{name:t});return!!r&&r.length>0}))}}const Ne=(e,t)=>{const r=n()+"."+t;return y(x(e,r))?Ne(e,t):r};class Pe extends r{constructor(e){super(),this.router=v(),this._path=e}auth(){return(e,t,r)=>j(this,void 0,void 0,(function*(){const s=e.get(re)||"",{auth:i,error:n,user:o}=yield qe.user(s);if(n)return Ae.error(t,n);if(i&&o){const t=e.get("User-Agent");return t&&(i.useragent=t),yield i.save(),e.auth=i,e.user=o,r()}return Ae.error(t,"Internal Server Error")}))}error(e){be.error(e.message,"api.controller."+this.name(),z)}name(){return"api"}path(){return this._path}permission(e){return(t,r,s)=>j(this,void 0,void 0,(function*(){const i=t.user;return i?(yield Re.is(i,e))?s():Ae.error(r,"Unauthorized access"):Ae.unauthorized(r,"Access denied")}))}read(e=""){return this.permission((e||this.name())+".read")}upload(e){const t=(null==e?void 0:e.path)||ae,r=k.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>j(this,void 0,void 0,(function*(){return s(null,Ne(t,P.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||oe),i=k({storage:r,fileFilter(t,r,s){var i;return j(this,void 0,void 0,(function*(){const t=null===(i=null==e?void 0:e.types)||void 0===i?void 0:i.indexOf(r.mimetype);return void 0!==t&&t<0?s(new Error("File type not allowed")):s(null,!0)}))},limits:{fileSize:s}}),n=(null==e?void 0:e.count)||ie,o=(null==e?void 0:e.field)||ne,a=i.array(o,n);return(e,t,r)=>{a(e,t,(function(e){return e?Ae.error(t,e.message):r()}))}}validation(e){return(t,r,s)=>j(this,void 0,void 0,(function*(){const{error:n,value:o}=yield i.object(e).validateAsync(t.body);return n?Ae.validation(r,n):(t.body=o,s())}))}write(e=""){return this.permission((e||this.name())+".write")}}class ke extends Pe{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar"],this.query={username:i.string().min(4).required(),password:i.string().min(5).required()}}intialize(){this.router.get("/",this.auth(),this.user.bind(this)),this.router.post("/login",this.validation(this.query),this.login.bind(this)),this.router.get("/logout",this.auth(),this.logout.bind(this))}login(e,t){return j(this,void 0,void 0,(function*(){yield s(Z);const{username:r,password:i}=e.body,n=yield ge.findOne({where:{username:r}}).catch(this.error);if(!n)return Ae.notfound(t,"Username not found");if(!n.state)return Ae.error(t,"Username is disabled");const a=G(i).toString();if(n.password!=a)return Ae.error(t,"Invalid password");const d=n.id,u=o(),{error:c,token:l}=qe.sign({id:d,secret:u});if(c)return Ae.error(t,c);if(l){const r=Date.now(),s=r+6e4*se,i=e.get("User-Agent"),o=yield le.create({login:r,secret:u,timestamp:s,useragent:i,userId:d}).catch(this.error);if(o)return this.emit("login",{auth:o,req:e,user:n}),Ae.data(t,{token:l})}return Ae.error(t,"Internal Server Error")}))}logout(e,t){return j(this,void 0,void 0,(function*(){const r=e.auth,s=e.user;return r&&s&&!r.logout?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),this.emit("logout",{auth:r,req:e,user:s}),Ae.success(t,"Disconcerted")):Ae.unauthorized(t,"Access denied")}))}user(e,t){return j(this,void 0,void 0,(function*(){const r=e.user;if(!r)return Ae.unauthorized(t,"Access denied");const s=yield Re.all(r);if(s){const i=a(this.attributes,r.toJSON()),n=s.map((e=>e.name));return this.emit("user",{req:e,user:r}),Ae.data(t,Object.assign(Object.assign({},i),{permissions:n}))}return Ae.error(t,"Internal Server Error")}))}}class xe extends Pe{constructor(){super(...arguments),this.username={username:i.string().min(4).required()},this.password={token:i.string().required(),password:i.string().min(5).required()},this.query={token:i.string().required()}}intialize(){this.router.post("/",this.validation(this.username),this.forgot.bind(this)),this.router.post("/check",this.validation(this.query),this.check.bind(this)),this.router.post("/reset",this.validation(this.password),this.reset.bind(this))}check(e,t){return j(this,void 0,void 0,(function*(){const{token:r}=e.body,s=yield this.findOne(r);return s&&s.user?(s.token=o(),yield s.save(),Ae.data(t,{token:s.token})):Ae.notfound(t,"User not found")}))}forgot(e,t){return j(this,void 0,void 0,(function*(){const{username:r}=e.body;yield s(Q);const i=yield ge.findOne({where:{username:r}}).catch(this.error);if(!i)return Ae.notfound(t,"User not found");const n=o(),a=Date.now()+6e4*se,d=yield he.create({token:n,timestamp:a,state:!0,userId:i.id});return this.emit("forgot",{forgot:d,req:e,user:i}),Ae.success(t,"OK")}))}findOne(e){return j(this,void 0,void 0,(function*(){return yield he.findOne({where:{token:e,state:!0},include:[{model:ge,required:!0}]}).catch(this.error)}))}reset(e,t){return j(this,void 0,void 0,(function*(){const{token:r,password:s}=e.body,i=yield this.findOne(r);return i?(i.state=!1,yield i.save().catch(this.error),i.user.password=G(s).toString(),yield i.user.save().catch(this.error),this.emit("reset",{req:e,user:i.user}),Ae.success(t,"OK")):Ae.notfound(t,"User not found")}))}}class Ge extends Pe{add(){return(e,t)=>j(this,void 0,void 0,(function*(){if(!this._model)return Ae.error(t,"Internal Server Error");const r=yield this._model.create(e.body).catch(this.error);return r?(this.emit("add",{req:e,record:r}),Ae.data(t,{id:r.id})):Ae.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>j(this,void 0,void 0,(function*(){var i,n,o,a,l;if(!this._model)return Ae.error(s,"Internal Server Error");const h=Object.assign({},e||{});h.where=Object.assign({},h.where||{});const p=null===(i=r.query.limit)||void 0===i?void 0:i.toString();p&&(h.limit=parseInt(p));const m=null===(n=r.query.offset)||void 0===n?void 0:n.toString();m&&(h.offset=parseInt(m));const v=Object.keys(this._model.getAttributes()),g=[],f=null===(o=r.query.asc)||void 0===o?void 0:o.toString();f&&f.length&&f.split(",").forEach((e=>{v.indexOf(e)>=0&&g.push([e,"ASC"])}));const y=null===(a=r.query.desc)||void 0===a?void 0:a.toString();y&&y.length&&y.split(",").forEach((e=>{v.indexOf(e)>=0&&g.push([e,"DESC"])})),g.length&&(h.order=g);const w=[],I=d(h.attributes)?h.attributes:v,b=null===(l=r.query.search)||void 0===l?void 0:l.toString();I.forEach((e=>{var t;if(u(e)&&(b&&b.length&&w.push({[e]:{[T.like]:`%${b}%`}}),"search_"+e in r.query)){const s=null===(t=r.query["search_"+e])||void 0===t?void 0:t.toString();s&&s.length&&w.push({[e]:{[T.like]:`%${s}%`}})}})),w.length&&(h.where=Object.assign(Object.assign({},h.where),{[T.or]:[...w]}));const A=yield this._model.findAll(h).catch(this.error),_=yield this._model.count(h).catch(c);return A?(this.emit("all",{req:r,records:A}),Ae.data(s,{count:_,records:t?t(A):A})):Ae.error(s,"Internal Server Error")}))}del(){return(e,t)=>j(this,void 0,void 0,(function*(){if(!this._model)return Ae.error(t,"Internal Server Error");const{id:r}=e.params;return(yield this._model.destroy({where:{id:r}}).catch(this.error))?(this.emit("del",{req:e,id:r}),Ae.success(t,"OK")):Ae.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>j(this,void 0,void 0,(function*(){if(!this._model)return Ae.error(s,"Internal Server Error");e||(e={});const i=Object.assign({},e);i.where=i.where?Object.assign({},i.where):{};const{id:n}=r.params,o=yield this._model.findByPk(n,i).catch(this.error);return o?(this.emit("get",{req:r,record:o}),Ae.data(s,t?t(o):o.toJSON())):null===o?Ae.notfound(s,"Record not found"):Ae.error(s,"Internal Server Error")}))}name(){var e;return this._model?null===(e=this._model)||void 0===e?void 0:e.tableName:super.name()}set(){return(e,t)=>j(this,void 0,void 0,(function*(){if(!this._model)return Ae.error(t,"Internal Server Error");const{id:r}=e.params,[s]=(yield this._model.update(e.body,{where:{id:r}}).catch(this.error))||[];return s?(this.emit("set",{req:e,id:r}),Ae.success(t,"OK")):Ae.success(t,"Record not changed")}))}getModel(){return this._model}setModel(e){this._model=e}}class je extends Ge{intialize(){const e=this.model();e&&this.setModel(e),this.router.use(this.auth()),this.router.get("/",this.read(),this.all().bind(this)),this.router.post("/",this.write(),this.validation(this.create()),this.add().bind(this)),this.router.route("/:id").get(this.read(),this.get().bind(this)).put(this.write(),this.validation(this.update()),this.set().bind(this)).delete(this.write(),this.del().bind(this))}}class ze extends je{create(){return{name:i.string().required(),description:i.string().empty(""),state:i.boolean().parse().required()}}model(){return pe}update(){return{name:i.string().empty(),description:i.string().empty(),state:i.boolean().parse().empty()}}}class De extends Ge{constructor(){super(...arguments),this.groups={groups:i.array().items(i.number())}}intialize(){this.setModel(ve),this.router.use(this.auth()),this.router.route("/:id/groups").get(this.read("users"),this.groupRouteAll.bind(this)).put(this.write("users"),this.validation(this.groups),this.groupRouteSet.bind(this))}groupRouteAll(e,t){return j(this,void 0,void 0,(function*(){const{id:r}=e.params;return this.all({where:{groupId:r},include:[{model:me,required:!0}]},(e=>e.map((e=>e.route))))(e,t)}))}groupRouteSet(e,t){return j(this,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,i=yield pe.findByPk(r,{attributes:["id"]}).catch(this.error);if(i){const e=i.id;if(yield ve.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield me.count({where:{id:s[r]}}),t&&(yield ve.create({groupId:e,routeId:s[r]}))}return Ae.success(t,"OK")}return l(i)?Ae.notfound(t,"Record not found"):Ae.error(t,"Internal Server Error")}))}}class Be extends Ge{intialize(){this.setModel(we),this.router.use(this.auth()),this.router.get("/",this.read("logs"),this.logsAll.bind(this))}logsAll(e,t){return j(this,void 0,void 0,(function*(){const{source:r,type:s}=e.query,i=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return this.all({where:i,order:[["created","DESC"]]})(e,t)}))}}class Le extends E{}Le.init({token:q.STRING,timestamp:q.BIGINT,state:q.BOOLEAN},{sequelize:ce,modelName:H+"registry",timestamps:!0,createdAt:"created",updatedAt:"updated"});class Ue extends Pe{constructor(){super(...arguments),this.create={name:i.string().required(),email:i.string().email().required(),username:i.string().min(4).required(),password:i.string().min(5).required()},this.query={token:i.string().required()}}intialize(){this.router.post("/",this.validation(this.create),this.register.bind(this)),this.router.post("/confirm",this.validation(this.query),this.confirm.bind(this))}confirm(e,t){return j(this,void 0,void 0,(function*(){const{token:r}=e.body,s=yield Le.findOne({where:{token:r,state:!0},include:[{model:ge,required:!0}]}).catch(this.error);return s?(s.user.state=!0,yield s.user.save().catch(this.error),this.emit("confirm",{req:e,user:s.user}),Ae.success(t,"OK")):Ae.notfound(t,"User not found")}))}register(e,t){return j(this,void 0,void 0,(function*(){const{username:r}=e.body;yield s(Q);const i=yield ge.findOne({where:{username:r}}).catch(this.error);if(i)return Ae.error(t,"Invalid Username");if(!l(i))return Ae.error(t,"Internal Server Error");const n=yield ge.create(Object.assign(Object.assign({},e.body),{state:!1}));return this.emit("register",{req:e,user:n}),Ae.success(t,"OK")}))}}class Ce extends je{create(){return{name:i.string().required(),description:i.string().empty(""),state:i.boolean().parse().required()}}model(){return me}update(){return{name:i.string().empty(),description:i.string().empty(),state:i.boolean().empty()}}}class Me extends Pe{intialize(){this.router.get("/",this.setup.bind(this))}setup(e,t){return j(this,void 0,void 0,(function*(){if(0==(yield ge.count())){const e={description:"",state:!0},t=yield ge.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",avatar:""},e)),r=yield pe.create(Object.assign({name:"admin"},e));yield fe.create({userId:t.id,groupId:r.id});const s=["read","write"],i=["users","groups","routes"];yield h(i,(t=>j(this,void 0,void 0,(function*(){yield h(s,(s=>j(this,void 0,void 0,(function*(){const i=t+"."+s,n=yield me.create(Object.assign({name:i},e));yield ve.create({groupId:r.id,routeId:n.id})}))))}))));const n=yield me.create(Object.assign({name:"logs.read"},e));yield ve.create({groupId:r.id,routeId:n.id})}return Ae.success(t,"OK")}))}}class Ke extends Ge{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar","description","state","created","updated"],this.create={name:i.string().required(),email:i.string().email().required(),username:i.string().min(4).required(),password:i.string().min(5).required(),description:i.string().required(),state:i.boolean().parse().required()},this.update={name:i.string().empty(),email:i.string().email().empty(),username:i.string().min(4).empty(),password:i.string().min(5).empty(),description:i.string().empty(),state:i.boolean().parse().empty()}}intialize(){this.setModel(ge),this.router.use(this.auth()),this.router.get("/",this.read(),this.userAll.bind(this)),this.router.post("/",this.write(),this.validation(this.create),this.userAdd.bind(this)),this.router.route("/:id").get(this.read(),this.userGet.bind(this)).put(this.write(),this.validation(this.update),this.userSet.bind(this)).delete(this.write(),this.userDel.bind(this))}userAdd(e,t){return j(this,void 0,void 0,(function*(){return e.body.password=G(e.body.password).toString(),yield this.add()(e,t)}))}userAll(e,t){return j(this,void 0,void 0,(function*(){return this.all({attributes:this.attributes})(e,t)}))}userDel(e,t){return j(this,void 0,void 0,(function*(){const r=e.user;if(r){const{id:s}=e.params;if(r.id.toString()!=s)return this.del()(e,t)}return Ae.error(t,"Internal Server Error")}))}userGet(e,t){return j(this,void 0,void 0,(function*(){return this.get({attributes:this.attributes})(e,t)}))}userSet(e,t){return j(this,void 0,void 0,(function*(){return e.body.password&&(e.body.password=G(e.body.password).toString()),this.set()(e,t)}))}}class He extends Ge{constructor(){super(...arguments),this.groups={groups:i.array(i.number())}}intialize(){this.setModel(fe),this.router.use(this.auth()),this.router.route("/:id/groups").get(this.read("groups"),this.userGroupsAll.bind(this)).put(this.write("groups"),this.validation(this.groups),this.userGroupsSet.bind(this))}userGroupsAll(e,t){return j(this,void 0,void 0,(function*(){const{id:r}=e.params;return this.all({where:{userId:r},include:[{model:pe,required:!0}]},(e=>e.map((e=>e.group))))(e,t)}))}userGroupsSet(e,t){return j(this,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,i=yield ge.findByPk(r,{attributes:["id"]}).catch(this.error);if(i){if(yield fe.destroy({where:{userId:i.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield pe.count({where:{id:s[t]}}),e&&(yield fe.create({userId:i.id,groupId:s[t]}))}return Ae.success(t,"OK")}return l(i),Ae.notfound(t,"Record not found")}))}}export{z as API_CONSOLE_ERROR,D as API_DB_DATABASE,B as API_DB_HOST,K as API_DB_LOG,L as API_DB_PASSWORD,U as API_DB_PORT,C as API_DB_TYPE,M as API_DB_USERNAME,J as API_HTTP_CROSS,F as API_HTTP_CRT,$ as API_HTTP_HYBRID,X as API_HTTP_KEY,Y as API_HTTP_PORT,W as API_HTTP_PUBLIC,Z as API_SLEEP_AUTH,Q as API_SLEEP_FORGOT,V as API_SLEEP_REGISTRY,H as API_TABLE_PREFIX,ee as API_TOKEN_CRT,re as API_TOKEN_HEADER,te as API_TOKEN_KEY,se as API_TOKEN_LIFETIME,ie as API_UPLOAD_COUNT,ne as API_UPLOAD_FIELD,oe as API_UPLOAD_SIZE,ae as API_UPLOAD_TEMP,de as API_WEBSOCKET_START,Ee as Application,le as Auth,ke as AuthController,Te as Config,ye as Configs,Pe as Controller,je as CrudController,ue as Database,he as Forgot,xe as ForgotController,pe as Group,ze as GroupController,ve as GroupRoute,De as GroupRouteController,be as Log,we as Logs,Be as LogsController,Ge as ModelController,Re as Permission,Ue as RegisterController,Ae as Responses,me as Route,Ce as RouteController,Me as SetupController,qe as Token,ge as User,Ke as UserController,fe as UserGroup,He as UserGroupController,Se as crt,Oe as key,ce as sequelize};
7
+ import{Application as e,parameterFactory as t,Res as r,Req as n,Headers as i,Next as s,Argument as o,Responses as d,Post as a,Middleware as u,App as c,Get as l,Controller as p,Delete as m,Put as g,Params as y,Body as h}from"@andrewcaires/express";import{toBool as v,dateFormat as O,sleep as _,EventEmitter as A,Validation as I,uuidv4 as f,uniqueID as P,allowedObject as E,isArray as b,isString as T,isNull as S,forEachSeries as R}from"@andrewcaires/utils.js";import w from"ws";import{Sequelize as j,DataTypes as N,Model as q,Op as D}from"sequelize";import{config as F}from"dotenv";import{existsSync as L,readFileSync as B}from"fs";import{sign as k,verify as G}from"jsonwebtoken";import{SHA256 as C}from"crypto-js";import x from"mime-types";import K from"multer";import{join as U}from"path";function H(e,t,r,n){var i,s=arguments.length,o=s<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,r,n);else for(var d=e.length-1;d>=0;d--)(i=e[d])&&(o=(s<3?i(o):s>3?i(t,r,o):i(t,r))||o);return s>3&&o&&Object.defineProperty(t,r,o),o}function z(e,t){return function(r,n){t(r,n,e)}}function M(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function X(e,t,r,n){return new(r||(r=Promise))((function(i,s){function o(e){try{a(n.next(e))}catch(e){s(e)}}function d(e){try{a(n.throw(e))}catch(e){s(e)}}function a(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(o,d)}a((n=n.apply(e,t||[])).next())}))}F();class Y{}Y.API_CONSOLE_ERROR=v(process.env.API_CONSOLE_ERROR||"false"),Y.API_DB_DATABASE=process.env.API_DB_DATABASE||"",Y.API_DB_HOST=process.env.API_DB_HOST||"127.0.0.1",Y.API_DB_PASSWORD=process.env.API_DB_PASSWORD||"",Y.API_DB_PORT=parseInt(process.env.API_DB_PORT||"3306"),Y.API_DB_TYPE=process.env.API_DB_TYPE||"",Y.API_DB_USERNAME=process.env.API_DB_USERNAME||"root",Y.API_DB_LOG=v(process.env.API_DB_LOG||"false"),Y.API_TABLE_PREFIX=process.env.API_TABLE_PREFIX||"",Y.API_HTTP_CRT=process.env.API_HTTP_CRT||"",Y.API_HTTP_KEY=process.env.API_HTTP_KEY||"",Y.API_HTTP_PORT=parseInt(process.env.API_HTTP_PORT||"3000"),Y.API_HTTP_PUBLIC=process.env.API_HTTP_PUBLIC||"",Y.API_HTTP_CROSS=v(process.env.API_HTTP_CROSS||"false"),Y.API_HTTP_HYBRID=v(process.env.API_HTTP_HYBRID||"false"),Y.API_SLEEP_AUTH=parseInt(process.env.API_SLEEP_AUTH||"1000"),Y.API_SLEEP_FORGOT=parseInt(process.env.API_SLEEP_FORGOT||"5000"),Y.API_SLEEP_REGISTRY=parseInt(process.env.API_SLEEP_REGISTRY||"5000"),Y.API_TOKEN_CRT=process.env.API_TOKEN_CRT||"",Y.API_TOKEN_KEY=process.env.API_TOKEN_KEY||"",Y.API_TOKEN_HEADER=process.env.API_TOKEN_HEADER||"authorization",Y.API_TOKEN_LIFETIME=parseInt(process.env.API_TOKEN_LIFETIME||"15"),Y.API_UPLOAD_COUNT=parseInt(process.env.API_UPLOAD_COUNT||"1"),Y.API_UPLOAD_FIELD=process.env.API_UPLOAD_FIELD||"upload",Y.API_UPLOAD_SIZE=parseInt(process.env.API_UPLOAD_SIZE||"2"),Y.API_UPLOAD_TEMP=process.env.API_UPLOAD_TEMP||"./temp",Y.API_WEBSOCKET_START=v(process.env.API_WEBSOCKET_START||"false");class W{static connect(e){const t=Y.API_DB_TYPE.toLowerCase();if("connect_"+t in W)return W["connect_"+t](e);throw new Error("No database is connected to this API")}static connect_mariadb(e){return new j(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mariadb",logging:Y.API_DB_LOG,define:{timestamps:!1}})}static connect_memory(){return new j("sqlite::memory:",{logging:Y.API_DB_LOG,define:{timestamps:!1}})}static connect_mysql(e){return new j(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"mysql",logging:Y.API_DB_LOG,define:{timestamps:!1}})}static connect_postgres(e){return new j(e.database,e.username,e.password,{host:e.hostname,port:e.hostport,dialect:"postgres",logging:Y.API_DB_LOG,define:{timestamps:!1}})}static connect_sqlite(e){return new j({dialect:"sqlite",storage:e.database,logging:Y.API_DB_LOG,define:{timestamps:!1}})}}const J=W.connect({database:Y.API_DB_DATABASE,username:Y.API_DB_USERNAME,password:Y.API_DB_PASSWORD,hostname:Y.API_DB_HOST,hostport:Y.API_DB_PORT});class Z extends q{}Z.init({login:N.BIGINT,logout:N.BIGINT,secret:N.STRING,timestamp:N.BIGINT,useragent:N.STRING},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"auth",timestamps:!0,createdAt:"created",updatedAt:"updated"});class $ extends q{}$.init({token:N.STRING,timestamp:N.BIGINT,state:N.BOOLEAN},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"forgot",timestamps:!0,createdAt:"created",updatedAt:"updated"});class Q extends q{}Q.init({name:N.STRING,description:N.TEXT,state:N.BOOLEAN},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"group",timestamps:!0,createdAt:"created",updatedAt:"updated"});class V extends q{}V.init({name:N.STRING,description:N.TEXT,state:N.BOOLEAN},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"route",timestamps:!0,createdAt:"created",updatedAt:"updated"});class ee extends q{}ee.init({},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"groups_routes",timestamps:!0,createdAt:"created",updatedAt:!1}),ee.removeAttribute("id");class te extends q{}te.init({name:N.STRING,email:N.STRING,username:N.STRING,password:N.STRING,avatar:N.STRING,description:N.TEXT,state:N.BOOLEAN},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"user",timestamps:!0,createdAt:"created",updatedAt:"updated"});class re extends q{}re.init({},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"users_groups",timestamps:!0,createdAt:"created",updatedAt:!1}),re.removeAttribute("id");class ne extends q{}ne.init({key:N.STRING,value:N.STRING},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"configs",timestamps:!0,createdAt:"created",updatedAt:"updated"}),ne.removeAttribute("id");class ie extends q{}var se;ie.init({type:N.STRING,source:N.STRING,message:N.TEXT},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"logs",timestamps:!0,createdAt:"created",updatedAt:!1}),te.hasMany(Z),Z.belongsTo(te),te.hasMany($),$.belongsTo(te),Q.hasMany(ee),ee.belongsTo(Q),V.hasMany(ee),ee.belongsTo(V),te.hasMany(re),re.belongsTo(te),Q.hasMany(re),re.belongsTo(Q),function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(se||(se={}));class oe{static write(e,t,r){return X(this,void 0,void 0,(function*(){yield oe.writeRaw(se.NONE,"",e,t,r)}))}static error(e,t,r){return X(this,void 0,void 0,(function*(){yield oe.writeRaw(se.ERROR,"error",e,t,r)}))}static info(e,t,r){return X(this,void 0,void 0,(function*(){yield oe.writeRaw(se.INFO,"info",e,t,r)}))}static success(e,t,r){return X(this,void 0,void 0,(function*(){yield oe.writeRaw(se.ERROR,"success",e,t,r)}))}static warning(e,t,r){return X(this,void 0,void 0,(function*(){yield oe.writeRaw(se.WARNING,"warning",e,t,r)}))}static writeConsole(e,t,r){const n=O(new Date,"%H:%M:%S");console.log(">",e,t+" ".repeat(10-t.length),"","|",n,"|",r)}static writeRaw(e,t,r,n,i){return X(this,void 0,void 0,(function*(){i&&oe.writeConsole(e,t,r),J&&(yield ie.create({type:t,source:n,message:r}).catch((()=>null)))}))}}const de=e=>L(e)?B(e):void 0,ae={http:de(Y.API_HTTP_CRT),token:de(Y.API_TOKEN_CRT)},ue={http:de(Y.API_HTTP_KEY),token:de(Y.API_TOKEN_KEY)};class ce{static error(e){oe.error(e.message,"api.token",Y.API_CONSOLE_ERROR)}static sign(e){return ue.token?{token:k(e,ue.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static user(e){return X(this,void 0,void 0,(function*(){const{error:t,decode:r}=ce.verify(e);if(t)return{error:t};if(r){const{id:e,secret:t}=r;if(e&&r){const r=yield te.findOne({where:{id:e,state:!0}}).catch(ce.error);if(r){const e=yield Z.findOne({where:{secret:t,userId:r.id}}).catch(ce.error);if(e){const t=Date.now();if(t>e.timestamp)return e.logout=t,yield e.save(),{error:"Expired token"};if(e.timestamp=t+6e4*Y.API_TOKEN_LIFETIME,!e.logout)return yield e.save(),{auth:e,user:r}}}return{error:"Access denied"}}}return{error:"Invalid token"}}))}static verify(e){if(!ae.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:G(e,ae.token)}}catch(e){return{error:"Invalid Token"}}}}class le extends e{constructor(e){super(e,{cert:ae.http,cross:Y.API_HTTP_CROSS,hybrid:Y.API_HTTP_HYBRID,key:ue.http,path:"/api",port:Y.API_HTTP_PORT,public:Y.API_HTTP_PUBLIC})}error(e,t){oe.info(e.message,t,Y.API_CONSOLE_ERROR)}log(e,t){oe.info(e,t,!0)}listen(){const e=Object.create(null,{listen:{get:()=>super.listen}});return X(this,void 0,void 0,(function*(){yield J.sync(),yield e.listen.call(this),Y.API_WEBSOCKET_START&&this.server&&(this._webSocket=new w.Server({server:this.server,verifyClient:(e,t)=>t(Y.API_WEBSOCKET_START)}),this._webSocket.on("connection",((e,t)=>X(this,void 0,void 0,(function*(){t.url||(t.url="");const r=t.url.length<=1?"":t.url.replace(/\//g,".");let n;e.on("message",(i=>X(this,void 0,void 0,(function*(){if(n)try{const s=JSON.parse(i);this.emit("ws.message"+r,{data:s,message:i,req:t,user:n,ws:e})}catch(s){this.emit("ws.message"+r,{message:i,req:t,user:n,ws:e})}else{const{user:s}=yield ce.user(i.toString());s&&(n=s,this.emit("ws.connection"+r,{req:t,user:n,ws:e}))}n||e.close()})))),e.on("close",(()=>{n&&this.emit("ws.close"+r,{user:n,ws:e})})),yield _(2e3),n||e.close()})))))}))}websocket(){return this._webSocket}}class pe{static all(){return X(this,void 0,void 0,(function*(){const e=yield ne.findAll().catch(pe.error),t={};return e&&e.forEach((e=>{t[e.key]=e.value})),t}))}static del(e){return X(this,void 0,void 0,(function*(){return((yield ne.destroy({where:{key:e}}).catch(pe.error))||0)>0}))}static error(e){oe.error(e.message,"api.config",Y.API_CONSOLE_ERROR)}static get(e){return X(this,void 0,void 0,(function*(){const t=yield ne.findOne({where:{key:e}}).catch(pe.error);return t&&t.value||""}))}static set(e,t){return X(this,void 0,void 0,(function*(){const[r]=(yield ne.findOrCreate({where:{key:e}}).catch(pe.error))||[];r&&(r.value=t,yield r.save().catch(pe.error))}))}}class me{static all(e,t){return X(this,void 0,void 0,(function*(){return yield V.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:ee,required:!0,include:[{model:Q,required:!0,where:{state:!0},include:[{model:re,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{oe.error(e.message,"api.permission",Y.API_CONSOLE_ERROR)}))}))}static get(e){return X(this,void 0,void 0,(function*(){const t=yield me.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return X(this,void 0,void 0,(function*(){const r=yield me.all(e,{name:t});return!!r&&r.length>0}))}}const ge=t((({req:e})=>e.auth)),ye=t((({req:e})=>e.user)),he=(e,t)=>{const r=f()+"."+t;return L(U(e,r))?he(e,t):r};class ve extends A{auth(e,t,r,n,i){return X(this,void 0,void 0,(function*(){const{auth:s,error:o,user:a}=yield ce.user(r);return o?d.error(e,o):s&&a?(n&&(s.useragent=n),yield s.save(),t.auth=s,t.user=a,i()):d.error(e,"Internal Server Error")}))}error(e){oe.error(e.message,"api.controller",Y.API_CONSOLE_ERROR)}name(){return"api"}permission(e,t,r,n){return X(this,void 0,void 0,(function*(){return t?(yield me.is(t,n))?r():d.error(e,"Unauthorized access"):d.unauthorized(e,"Access denied")}))}read(e,t,r,n){return this.permission(e,t,r,(n||this.name())+".read")}upload(e,t,r,n){const i=(null==n?void 0:n.path)||Y.API_UPLOAD_TEMP,s=K.diskStorage({destination:(e,t,r)=>r(null,i),filename:(e,t,r)=>X(this,void 0,void 0,(function*(){return r(null,he(i,x.extension(t.mimetype)||"bin"))}))}),o=1e6*((null==n?void 0:n.size)||Y.API_UPLOAD_SIZE),a=K({storage:s,fileFilter(e,t,r){var i;return X(this,void 0,void 0,(function*(){const e=null===(i=null==n?void 0:n.types)||void 0===i?void 0:i.indexOf(t.mimetype);return void 0!==e&&e<0?r(new Error("File type not allowed")):r(null,!0)}))},limits:{fileSize:o}}),u=(null==n?void 0:n.count)||Y.API_UPLOAD_COUNT,c=(null==n?void 0:n.field)||Y.API_UPLOAD_FIELD;a.array(c,u)(t,e,(t=>t?d.error(e,t.message):r()))}validation(e,t,r,n){return X(this,void 0,void 0,(function*(){const{error:i,value:s}=yield I.object(n).validateAsync(t.body);return i?d.validation(e,i):(t.body=s,r())}))}write(e,t,r,n){return this.permission(e,t,r,(n||this.name())+".write")}}H([z(0,r()),z(1,n()),z(2,i(Y.API_TOKEN_HEADER)),z(3,i("user-agent")),z(4,s()),M("design:type",Function),M("design:paramtypes",[Object,Object,String,String,Function]),M("design:returntype",Promise)],ve.prototype,"auth",null),H([z(0,r()),z(1,ye()),z(2,s()),z(3,o()),M("design:type",Function),M("design:paramtypes",[Object,te,Function,String]),M("design:returntype",Promise)],ve.prototype,"permission",null),H([z(0,r()),z(1,ye()),z(2,s()),z(3,o()),M("design:type",Function),M("design:paramtypes",[Object,te,Function,String]),M("design:returntype",void 0)],ve.prototype,"read",null),H([z(0,r()),z(1,n()),z(2,s()),z(3,o()),M("design:type",Function),M("design:paramtypes",[Object,Object,Function,Object]),M("design:returntype",void 0)],ve.prototype,"upload",null),H([z(0,r()),z(1,n()),z(2,s()),z(3,o()),M("design:type",Function),M("design:paramtypes",[Object,Object,Function,Object]),M("design:returntype",Promise)],ve.prototype,"validation",null),H([z(0,r()),z(1,ye()),z(2,s()),z(3,o()),M("design:type",Function),M("design:paramtypes",[Object,te,Function,String]),M("design:returntype",void 0)],ve.prototype,"write",null);let Oe=class extends ve{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar"]}login(e,t,r,n){return X(this,void 0,void 0,(function*(){yield _(Y.API_SLEEP_AUTH);const{username:i,password:s}=t.body,o=yield te.findOne({where:{username:i}}).catch(this.error);if(!o)return n.emit("auth.failure",{req:t}),d.notfound(e,"Username not found");if(!o.state)return n.emit("auth.failure",{req:t}),d.error(e,"Username is disabled");const a=C(s).toString();if(o.password!=a)return n.emit("auth.failure",{req:t}),d.error(e,"Invalid password");const u=o.id,c=P(),{error:l,token:p}=ce.sign({id:u,secret:c});if(l)return n.emit("auth.failure",{req:t}),d.error(e,l);if(p){const n=Date.now(),i=n+6e4*Y.API_TOKEN_LIFETIME,s=yield Z.create({login:n,secret:c,timestamp:i,useragent:r,userId:u}).catch(this.error);if(s)return this.emit("auth.login",{auth:s,req:t,user:o}),d.data(e,{token:p})}return n.emit("auth.failure",{req:t}),d.error(e,"Internal Server Error")}))}logout(e,t,r,n,i){return X(this,void 0,void 0,(function*(){return r&&n&&!r.logout?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),i.emit("auth.logout",{auth:r,req:t,user:n}),d.success(e,"Disconcerted")):d.unauthorized(e,"Access denied")}))}user(e,t){return X(this,void 0,void 0,(function*(){const r=t.user;if(!r)return d.unauthorized(e,"Access denied");const n=yield me.all(r);if(n){const t=n.map((e=>e.name));return d.data(e,Object.assign(Object.assign({},E(this.attributes,r.toJSON())),{permissions:t}))}return d.error(e,"Internal Server Error")}))}};H([a("/login"),u("validation",{username:I.string().min(4).required(),password:I.string().min(5).required()}),z(0,r()),z(1,n()),z(2,i("user-agent")),z(3,c()),M("design:type",Function),M("design:paramtypes",[Object,Object,String,le]),M("design:returntype",Promise)],Oe.prototype,"login",null),H([l("/logout"),u("auth"),z(0,r()),z(1,n()),z(2,ge()),z(3,ye()),z(4,c()),M("design:type",Function),M("design:paramtypes",[Object,Object,Z,te,le]),M("design:returntype",Promise)],Oe.prototype,"logout",null),H([l(),u("auth"),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],Oe.prototype,"user",null),Oe=H([p("/auth")],Oe);let _e=class extends ve{check(e,t){return X(this,void 0,void 0,(function*(){const{token:r}=t.body,n=yield this.findOne(r);return n&&n.user?(n.token=P(),yield n.save(),d.data(e,{token:n.token})):d.notfound(e,"User not found")}))}forgot(e,t){return X(this,void 0,void 0,(function*(){const{username:r}=t.body;yield _(Y.API_SLEEP_FORGOT);const n=yield te.findOne({where:{username:r}}).catch(this.error);if(!n)return d.notfound(e,"User not found");const i=P(),s=Date.now()+6e4*Y.API_TOKEN_LIFETIME,o=yield $.create({token:i,timestamp:s,state:!0,userId:n.id});return this.emit("forgot",{forgot:o,req:t,user:n}),d.success(e,"OK")}))}reset(e,t){return X(this,void 0,void 0,(function*(){const{token:r,password:n}=t.body,i=yield this.findOne(r);return i?(i.state=!1,yield i.save().catch(this.error),i.user.password=C(n).toString(),yield i.user.save().catch(this.error),this.emit("forgot.reset",{req:t,user:i.user}),d.success(e,"OK")):d.notfound(e,"User not found")}))}findOne(e){return X(this,void 0,void 0,(function*(){return yield $.findOne({where:{token:e,state:!0},include:[{model:te,required:!0}]}).catch(this.error)}))}};H([l("/check"),u("validation",{token:I.string().required()}),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],_e.prototype,"check",null),H([l(),u("validation",{username:I.string().min(4).required()}),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],_e.prototype,"forgot",null),H([l("/reset"),u("validation",{token:I.string().required(),password:I.string().min(5).required()}),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],_e.prototype,"reset",null),_e=H([p("/forgot")],_e);class Ae extends ve{add(e,t,r){return X(this,void 0,void 0,(function*(){const n=yield this.model().create(e.body,r||{}).catch(this.error);return n?d.data(t,{id:n.id}):d.error(t,"Internal Server Error")}))}all(e,t,r,n){var i,s,o,a,u;return X(this,void 0,void 0,(function*(){const c=this.model(),l=Object.assign({},r||{});l.where=Object.assign({},l.where||{});const p=null===(i=e.query.limit)||void 0===i?void 0:i.toString();p&&(l.limit=parseInt(p));const m=null===(s=e.query.offset)||void 0===s?void 0:s.toString();m&&(l.offset=parseInt(m));const g=Object.keys(c.getAttributes()),y=[],h=null===(o=e.query.asc)||void 0===o?void 0:o.toString();h&&h.length&&h.split(",").forEach((e=>{g.indexOf(e)>=0&&y.push([e,"ASC"])}));const v=null===(a=e.query.desc)||void 0===a?void 0:a.toString();v&&v.length&&v.split(",").forEach((e=>{g.indexOf(e)>=0&&y.push([e,"DESC"])})),y.length&&(l.order=y);const O=[],_=b(l.attributes)?l.attributes:g,A=null===(u=e.query.search)||void 0===u?void 0:u.toString();_.forEach((t=>{var r;if(T(t)&&(A&&A.length&&O.push({[t]:{[D.like]:`%${A}%`}}),"search_"+t in e.query)){const n=null===(r=e.query["search_"+t])||void 0===r?void 0:r.toString();n&&n.length&&O.push({[t]:{[D.like]:`%${n}%`}})}})),O.length&&(l.where=Object.assign(Object.assign({},l.where),{[D.or]:[...O]}));const I=yield c.count(Object.assign(Object.assign({},l),{col:g[0]})).catch(this.error),f=yield c.findAll(l).catch(this.error);return f?d.data(t,{count:I,records:n?n(f):f}):d.error(t,"Internal Server Error")}))}del(e,t,r){return X(this,void 0,void 0,(function*(){const{id:n}=e.params;if(!n)return d.error(t,"Internal Server Error");return(yield this.model().destroy(Object.assign(Object.assign({},r||{}),{where:{id:n}})).catch(this.error))?d.success(t,"OK"):d.notfound(t,"Record not found")}))}error(e){super.error(e),e.sql&&oe.error(e.sql,"api.controller.sql",Y.API_CONSOLE_ERROR)}get(e,t,r,n){return X(this,void 0,void 0,(function*(){const i=Object.assign({},r||{});i.where=i.where?Object.assign({},i.where):{};const{id:s}=e.params,o=yield this.model().findByPk(s,i).catch(this.error);return o?d.data(t,n?n(o):o.toJSON()):null===o?d.notfound(t,"Record not found"):d.error(t,"Internal Server Error")}))}name(){return this.model().tableName}set(e,t,r){return X(this,void 0,void 0,(function*(){const{id:n}=e.params,[i]=(yield this.model().update(e.body,Object.assign(Object.assign({},r||{}),{where:Object.assign(Object.assign({},(r||{}).where),{id:n})})).catch(this.error))||[];return i?d.success(t,"OK"):d.success(t,"Record not changed")}))}}class Ie extends Ae{create(){return{}}crudAdd(e,t){return this.add(e,t,this.optionsAdd())}crudAll(e,t){return this.all(e,t,this.optionsAll())}crudDel(e,t){return this.del(e,t,this.optionsDel())}crudGet(e,t){return this.get(e,t,this.optionsGet())}crudSet(e,t){return this.set(e,t,this.optionsSet())}optionsAdd(){return{}}optionsAll(){return{}}optionsDel(){return{}}optionsGet(){return{}}optionsSet(){return{where:{}}}update(){return{}}validationAdd(e,t,r){return this.validation(t,e,r,this.create())}validationSet(e,t,r){return this.validation(t,e,r,this.update())}}H([a(),u("auth"),u("write"),u("validationAdd"),z(0,n()),z(1,r()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",void 0)],Ie.prototype,"crudAdd",null),H([l(),u("auth"),u("read"),z(0,n()),z(1,r()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",void 0)],Ie.prototype,"crudAll",null),H([m("/:id"),u("auth"),u("write"),z(0,n()),z(1,r()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",void 0)],Ie.prototype,"crudDel",null),H([l("/:id"),u("auth"),u("read"),z(0,n()),z(1,r()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",void 0)],Ie.prototype,"crudGet",null),H([g("/:id"),u("auth"),u("write"),u("validationSet"),z(0,n()),z(1,r()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",void 0)],Ie.prototype,"crudSet",null),H([z(0,n()),z(1,r()),z(2,s()),M("design:type",Function),M("design:paramtypes",[Object,Object,Function]),M("design:returntype",void 0)],Ie.prototype,"validationAdd",null),H([z(0,n()),z(1,r()),z(2,s()),M("design:type",Function),M("design:paramtypes",[Object,Object,Function]),M("design:returntype",void 0)],Ie.prototype,"validationSet",null);let fe=class extends Ie{model(){return Q}create(){return{name:I.string().required(),description:I.string().empty(""),state:I.boolean().parse().required()}}update(){return{name:I.string().empty(),description:I.string().empty(),state:I.boolean().parse().empty()}}};fe=H([p("/groups")],fe);let Pe=class extends Ae{model(){return ee}groupRouteAll(e,t,r){return X(this,void 0,void 0,(function*(){return this.all(t,e,{where:{groupId:r},include:[{model:V,required:!0}]},(e=>e.map((e=>e.route))))}))}groupRouteSet(e,t,r){return X(this,void 0,void 0,(function*(){const n=yield Q.findByPk(t,{attributes:["id"]}).catch(this.error);if(n){const t=n.id;if(yield ee.destroy({where:{groupId:t}}),r){let e=0;for(let n=0;n<r.length;n++)e=yield V.count({where:{id:r[n]}}),e&&(yield ee.create({groupId:t,routeId:r[n]}))}return d.success(e,"OK")}return S(n)?d.notfound(e,"Record not found"):d.error(e,"Internal Server Error")}))}};H([l("/:id/routes"),u("auth"),u("read","routes"),z(0,r()),z(1,n()),z(2,y("id")),M("design:type",Function),M("design:paramtypes",[Object,Object,String]),M("design:returntype",Promise)],Pe.prototype,"groupRouteAll",null),H([g("/:id/groups"),u("auth"),u("write","groups"),u("validation",{routes:I.array(I.number().parse())}),z(0,r()),z(1,y("id")),z(2,h("routes")),M("design:type",Function),M("design:paramtypes",[Object,String,Array]),M("design:returntype",Promise)],Pe.prototype,"groupRouteSet",null),Pe=H([p("/groups")],Pe);let Ee=class extends Ae{model(){return ie}logsAll(e,t){return X(this,void 0,void 0,(function*(){const{source:r,type:n}=t.query,i=r&&n?{source:r,type:n}:r?{source:r}:n?{type:n}:{};return this.all(t,e,{where:i,order:[["created","DESC"]]})}))}};H([l(),u("auth"),u("read"),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],Ee.prototype,"logsAll",null),Ee=H([p("/logs")],Ee);class be extends q{}be.init({token:N.STRING,timestamp:N.BIGINT,state:N.BOOLEAN},{sequelize:J,modelName:Y.API_TABLE_PREFIX+"registry",timestamps:!0,createdAt:"created",updatedAt:"updated"});let Te=class extends ve{confirm(e,t){return X(this,void 0,void 0,(function*(){const r=yield be.findOne({where:{token:t,state:!0},include:[{model:te,required:!0}]}).catch(this.error);return r?(r.user.state=!0,yield r.user.save().catch(this.error),this.emit("user.confirm",{user:r.user}),d.success(e,"OK")):d.notfound(e,"User not found")}))}register(e,t,r,n){return X(this,void 0,void 0,(function*(){yield _(Y.API_SLEEP_REGISTRY);const t=yield te.findOne({where:{username:n}}).catch(this.error);if(t)return d.error(e,"Invalid Username");if(!S(t))return d.error(e,"Internal Server Error");const i=yield te.create(Object.assign(Object.assign({},r),{state:!1}));return this.emit("user.register",{user:i}),d.success(e,"OK")}))}};H([l("/confirm"),u("validation",{token:I.string().required()}),z(0,r()),z(1,h("token")),M("design:type",Function),M("design:paramtypes",[Object,String]),M("design:returntype",Promise)],Te.prototype,"confirm",null),H([l(),u("validation",{name:I.string().required(),email:I.string().email().required(),username:I.string().min(4).required(),password:I.string().min(5).required()}),z(0,r()),z(1,n()),z(2,h()),z(3,h("username")),M("design:type",Function),M("design:paramtypes",[Object,Object,Object,String]),M("design:returntype",Promise)],Te.prototype,"register",null),Te=H([p("/register")],Te);let Se=class extends Ie{model(){return V}create(){return{name:I.string().required(),description:I.string().empty(""),state:I.boolean().parse().required()}}update(){return{name:I.string().empty(),description:I.string().empty(),state:I.boolean().empty()}}};Se=H([p("/routes")],Se);let Re=class extends ve{setup(e){return X(this,void 0,void 0,(function*(){if(0==(yield te.count())){const e={description:"",state:!0},t=yield te.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",avatar:""},e)),r=yield Q.create(Object.assign({name:"admin"},e));yield re.create({userId:t.id,groupId:r.id});const n=["read","write"],i=["users","groups","routes"];yield R(i,(t=>X(this,void 0,void 0,(function*(){yield R(n,(n=>X(this,void 0,void 0,(function*(){const i=t+"."+n,s=yield V.create(Object.assign({name:i},e));yield ee.create({groupId:r.id,routeId:s.id})}))))}))));const s=yield V.create(Object.assign({name:"logs.read"},e));yield ee.create({groupId:r.id,routeId:s.id})}return d.success(e,"OK")}))}};H([l(),z(0,r()),M("design:type",Function),M("design:paramtypes",[Object]),M("design:returntype",Promise)],Re.prototype,"setup",null),Re=H([p("/setup")],Re);let we=class extends Ae{constructor(){super(...arguments),this.attributes=["id","name","email","username","avatar","description","state","created","updated"]}model(){return te}userAdd(e,t){return X(this,void 0,void 0,(function*(){return t.body.password=C(t.body.password).toString(),yield this.add(t,e)}))}userAll(e,t){return X(this,void 0,void 0,(function*(){return this.all(t,e,{attributes:this.attributes})}))}userDel(e,t,r,n){return X(this,void 0,void 0,(function*(){return r&&r.id.toString()!=n?this.del(t,e):d.error(e,"Internal Server Error")}))}userGet(e,t){return X(this,void 0,void 0,(function*(){return this.get(t,e,{attributes:this.attributes})}))}userSet(e,t){return X(this,void 0,void 0,(function*(){return t.body.password&&(t.body.password=C(t.body.password).toString()),this.set(t,e)}))}};H([a(),u("auth"),u("write"),u("validation",{name:I.string().required(),email:I.string().email().required(),username:I.string().min(4).required(),password:I.string().min(5).required(),description:I.string().required(),state:I.boolean().parse().required()}),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],we.prototype,"userAdd",null),H([l(),u("auth"),u("read"),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],we.prototype,"userAll",null),H([m("/:id"),u("auth"),u("write"),z(0,r()),z(1,n()),z(2,ye()),z(3,y("id")),M("design:type",Function),M("design:paramtypes",[Object,Object,te,String]),M("design:returntype",Promise)],we.prototype,"userDel",null),H([l("/:id"),u("auth"),u("read"),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],we.prototype,"userGet",null),H([g("/:id"),u("auth"),u("write"),u("validation",{name:I.string().empty(),email:I.string().email().empty(),username:I.string().min(4).empty(),password:I.string().min(5).empty(),description:I.string().empty(),state:I.boolean().parse().empty()}),z(0,r()),z(1,n()),M("design:type",Function),M("design:paramtypes",[Object,Object]),M("design:returntype",Promise)],we.prototype,"userSet",null),we=H([p("/users")],we);let je=class extends Ae{model(){return re}userGroupsAll(e,t,r){return X(this,void 0,void 0,(function*(){return this.all(t,e,{where:{userId:r},include:[{model:Q,required:!0}]},(e=>e.map((e=>e.group))))}))}userGroupsSet(e,t,r){return X(this,void 0,void 0,(function*(){const n=yield te.findByPk(t,{attributes:["id"]}).catch(this.error);if(n){if(yield re.destroy({where:{userId:n.id}}),r){let e=0;for(let t=0;t<r.length;t++)e=yield Q.count({where:{id:r[t]}}),e&&(yield re.create({userId:n.id,groupId:r[t]}))}return d.success(e,"OK")}return S(n)?d.notfound(e,"Record not found"):d.error(e,"Internal Server Error")}))}};H([l("/:id/groups"),u("auth"),u("read","groups"),z(0,r()),z(1,n()),z(2,y("id")),M("design:type",Function),M("design:paramtypes",[Object,Object,String]),M("design:returntype",Promise)],je.prototype,"userGroupsAll",null),H([g("/:id/groups"),u("auth"),u("write","groups"),u("validation",{groups:I.array(I.number().parse())}),z(0,r()),z(1,y("id")),z(2,h("groups")),M("design:type",Function),M("design:paramtypes",[Object,String,Array]),M("design:returntype",Promise)],je.prototype,"userGroupsSet",null),je=H([p("/users")],je);export{le as Application,Z as Auth,Oe as AuthController,pe as Config,ne as Configs,ve as ControllerBase,Ie as CrudController,W as Database,Y as Env,$ as Forgot,_e as ForgotController,Q as Group,fe as GroupController,ee as GroupRoute,Pe as GroupRouteController,oe as Log,ie as Logs,Ee as LogsController,Ae as ModelController,me as Permission,Te as RegisterController,ge as ReqAuth,ye as ReqUser,V as Route,Se as RouteController,Re as SetupController,ce as Token,te as User,we as UserController,re as UserGroup,je as UserGroupController,ae as crt,ue as key,J as sequelize};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrewcaires/api",
3
- "version": "2.0.3",
3
+ "version": "3.0.0",
4
4
  "description": "Simple api for small applications using express, jsonwebtoken, sequelize and websocket",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "types": "./dist/index.d.ts",
@@ -45,7 +45,8 @@
45
45
  },
46
46
  "homepage": "https://github.com/andrewcaires/npm/tree/main/api#readme",
47
47
  "dependencies": {
48
- "@andrewcaires/utils.js": "^0.2.9",
48
+ "@andrewcaires/express": "^1.0.3",
49
+ "@andrewcaires/utils.js": "^0.2.10",
49
50
  "cors": "^2.8.5",
50
51
  "crypto-js": "^4.1.1",
51
52
  "dotenv": "^16.0.3",
@@ -54,8 +55,8 @@
54
55
  "mariadb": "^3.1.0",
55
56
  "mime-types": "^2.1.35",
56
57
  "multer": "^1.4.5-lts.1",
57
- "mysql2": "^3.1.2",
58
- "sequelize": "^6.29.0",
58
+ "mysql2": "^3.2.0",
59
+ "sequelize": "^6.29.1",
59
60
  "ws": "^8.12.1"
60
61
  },
61
62
  "devDependencies": {
@@ -68,10 +69,10 @@
68
69
  "@types/jsonwebtoken": "^9.0.1",
69
70
  "@types/mime-types": "^2.1.1",
70
71
  "@types/multer": "^1.4.7",
71
- "@types/node": "^18.14.4",
72
+ "@types/node": "^18.14.6",
72
73
  "@types/ws": "^8.5.4",
73
- "@typescript-eslint/eslint-plugin": "^5.54.0",
74
- "@typescript-eslint/parser": "^5.54.0",
74
+ "@typescript-eslint/eslint-plugin": "^5.54.1",
75
+ "@typescript-eslint/parser": "^5.54.1",
75
76
  "eslint": "^8.35.0",
76
77
  "rollup": "^3.18.0",
77
78
  "rollup-plugin-dts": "^5.2.0",