@andrewcaires/api 1.0.0 → 1.0.1
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.esm.js +1 -1
- package/dist/index.umd.js +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* (c) 2022 Andrew Caires
|
|
4
4
|
* @license: MIT
|
|
5
5
|
*/
|
|
6
|
-
import{toBool as e,forEachSeries as t,dateFormat as r,sleep as s,uniqueID as o,allowedObject as n,uuidv4 as i}from"@andrewcaires/utils.js";import{config as a}from"dotenv";import{Sequelize as d,UUID as u,UUIDV4 as c,DataTypes as l,Model as m}from"sequelize";import p from"cors";import g,{Router as v}from"express";import{existsSync as f,readFileSync as h}from"fs";import{SHA256 as y}from"crypto-js";import w from"jsonwebtoken";import I from"joi";import*as b from"http";import*as T from"https";import{Server as A}from"net";import S from"ws";import _ from"mime-types";import E from"multer";import{join as P}from"path";a();const O=parseInt(process.env.API_AUTH_SLEEP||"1000"),N=process.env.API_DB_DATABASE||"",R=process.env.API_DB_HOST||"127.0.0.1",q=process.env.API_DB_PASSWORD||"",j=parseInt(process.env.API_DB_PORT||"3306"),k=process.env.API_DB_TYPE||"",x=process.env.API_DB_USERNAME||"root",D=e(process.env.API_DB_LOG||"false"),B=process.env.API_HTTP_CRT||"",z=process.env.API_HTTP_KEY||"",G=parseInt(process.env.API_HTTP_PORT||"3000"),U=process.env.API_HTTP_PUBLIC||"",L=e(process.env.API_HTTP_CROSS||"false"),C=e(process.env.API_HTTP_HYBRID||"false"),H=process.env.API_TOKEN_CRT||"",K=process.env.API_TOKEN_KEY||"",M=process.env.API_TOKEN_HEADER||"authorization",F=parseInt(process.env.API_TOKEN_LIFETIME||"15"),W=parseInt(process.env.API_UPLOAD_COUNT||"1"),X=process.env.API_UPLOAD_FIELD||"upload",Y=parseInt(process.env.API_UPLOAD_SIZE||"2"),$=process.env.API_UPLOAD_TEMP||"./temp",J=e(process.env.API_WEBSOCKET_START||"false");function V(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())}))}const Z={type:u,defaultValue:c,allowNull:!1,primaryKey:!0},Q=(()=>{switch(k){case"mariadb":return new d(N,x,q,{host:R,port:j,dialect:"mariadb",logging:D,define:{timestamps:!1}});case"mysql":return new d(N,x,q,{host:R,port:j,dialect:"mysql",logging:D,define:{timestamps:!1}});case"postgres":return new d(N,x,q,{host:R,port:j,dialect:"postgres",logging:D,define:{timestamps:!1}})}throw new Error("No database selected")})();class ee extends m{}ee.init({login:l.BIGINT,logout:l.BIGINT,secret:l.STRING,timestamp:l.BIGINT,useragent:l.STRING},{sequelize:Q,modelName:"auth"});class te extends m{}te.init({name:l.STRING,description:l.TEXT,state:l.BOOLEAN},{sequelize:Q,modelName:"group"});class re extends m{}re.init({type:l.STRING,source:l.STRING,message:l.TEXT},{sequelize:Q,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class se extends m{}se.init({name:l.STRING,description:l.TEXT,state:l.BOOLEAN},{sequelize:Q,modelName:"route"});class oe extends m{}oe.init({},{sequelize:Q,modelName:"groups_routes"}),oe.removeAttribute("id");class ne extends m{}ne.init({name:l.STRING,email:l.STRING,username:l.STRING,password:l.STRING,description:l.TEXT,state:l.BOOLEAN},{sequelize:Q,modelName:"user"});class ie extends m{}ie.init({},{sequelize:Q,modelName:"users_groups"}),ie.removeAttribute("id"),ne.hasMany(ee),ee.belongsTo(ne),te.hasMany(oe),oe.belongsTo(te),se.hasMany(oe),oe.belongsTo(se),ne.hasMany(ie),ie.belongsTo(ne),te.hasMany(ie),ie.belongsTo(te);var ae;!function(e){e.ERROR="[31m",e.INFO="[36m",e.NONE="[37m",e.SUCCESS="[32m",e.WARNING="[33m"}(ae||(ae={}));class de{static write(e,t){de.writeRaw(ae.NONE,"",e,t)}static error(e,t){de.writeRaw(ae.ERROR,"error",e,t)}static info(e,t){de.writeRaw(ae.INFO,"info",e,t)}static success(e,t){de.writeRaw(ae.ERROR,"success",e,t)}static warning(e,t){de.writeRaw(ae.WARNING,"warning",e,t)}static writeConsole(e,t,s){const o=r(new Date,"%H:%M:%S");console.log(">",e,t+" ".repeat(10-t.length),"[37m","|",o,"|",s)}static writeRaw(e,t,r,s){de.writeConsole(e,t,r),re.create({type:t,source:s,message:r}).catch((()=>null))}}class ue{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,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}const ce=e=>{if(f(e))return h(e)},le={http:ce(B),token:ce(H)},me={http:ce(z),token:ce(K)};class pe{static all(e,t){return V(this,void 0,void 0,(function*(){return yield se.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:oe,required:!0,include:[{model:te,required:!0,where:{state:!0},include:[{model:ie,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{de.error(e.message,"permission")}))}))}static get(e){return V(this,void 0,void 0,(function*(){const t=yield pe.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return V(this,void 0,void 0,(function*(){const r=yield pe.all(e,{name:t});return r&&!!r.length}))}}const ge=["id","name","email","username"],ve=(e,t,r)=>V(void 0,void 0,void 0,(function*(){const s=e.get(M)||"";if(!le.token)return ue.error(t,"Invalid Secret");if(!s||s.split(".").length<3)return ue.error(t,"Invalid token");const o=w.verify(s,le.token);if(o&&o.id&&o.secret){const s=yield ne.findOne({where:{id:o.id}}).catch((e=>{de.error(e.message,"token.check")}));if(s&&s.state){const n=yield ee.findOne({where:{logout:null,secret:o.secret,userId:s.id}}).catch((e=>{de.error(e.message,"token.check")}));if(n){const o=Date.now();if(o>n.timestamp)return ue.error(t,"Expired token");n.timestamp=o+6e4*F;const i=e.get("User-Agent");return i&&(n.useragent=i),yield n.save(),e.auth=n,e.user=s,r()}}return ue.error(t,"Access denied")}return ue.error(t,"Invalid token")})),fe=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),ue.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},he={username:I.string().min(5).required(),password:I.string().min(5).required()},ye=fe(I.object(he)),we=v();we.get("/",ve,((e,t)=>V(void 0,void 0,void 0,(function*(){const r=e.user;if(!r)return ue.unauthorized(t,"Access denied");const s=yield pe.all(r);if(s){const e=n(ge,r.toJSON()),o=s.map((e=>e.name));return ue.data(t,Object.assign(Object.assign({},e),{permissions:o}))}return ue.error(t,"Internal Server Error")})))),we.post("/login",ye,((e,t)=>V(void 0,void 0,void 0,(function*(){const{username:r,password:n}=e.body;if(!r||!n)return ue.error(t,"Invalid parameters");yield s(O);const i=yield ne.findOne({where:{username:r}}).catch((e=>{de.error(e.message,"auth.login")}));if(!i)return ue.notfound(t,"User not found");if(!i.state)return ue.error(t,"User is disabled");const a=y(n).toString();if(i.password!=a)return ue.error(t,"Invalid password");if(!me.token)return ue.error(t,"Invalid Secret");const d=i.id,u=o(),c=w.sign({id:d,secret:u},me.token,{algorithm:"RS256"});if(c){const r=Date.now(),s=r+6e4*F,o=e.get("User-Agent");if(yield ee.create({login:r,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{de.error(e.message,"auth.login")})))return ue.data(t,{token:c})}return ue.error(t,"Internal Server Error")})))),we.get("/logout",ve,((e,t)=>V(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),ue.success(t,"Disconcerted")):ue.unauthorized(t,"Access denied")}))));class Ie{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>V(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{de.error(e.message,this.log+".add")}));return r?ue.data(t,{id:r.id}):ue.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>V(this,void 0,void 0,(function*(){var o,n;e||(e={});const i=null===(o=r.query.limit)||void 0===o?void 0:o.toString();i&&(e.limit=parseInt(i));const a=null===(n=r.query.offset)||void 0===n?void 0:n.toString();a&&(e.offset=parseInt(a));const d=yield this.model.findAll(e).catch((e=>{de.error(e.message,this.log+".all")})),u=yield this.model.count().catch((e=>{de.error(e.message,this.log+".all")}));return d?ue.data(s,{count:u,records:t?t(d):d}):ue.error(s,"Internal Server Error")}))}del(){return(e,t)=>V(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{de.error(e.message,this.log+".del")})))?ue.success(t,"OK"):ue.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>V(this,void 0,void 0,(function*(){e||(e={});const{id:o}=r.params,n=yield this.model.findByPk(o,e).catch((e=>{de.error(e.message,this.log+".get")}));return n?ue.data(s,t?t(n):n.toJSON()):null===n?ue.notfound(s,"Record not found"):ue.error(s,"Internal Server Error")}))}set(){return(e,t)=>V(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{de.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return ue.success(t,"OK")}return ue.success(t,"Record not changed")}))}}const be=new Ie("groups",te),Te=be.add(),Ae=be.all(),Se=be.del(),_e=be.get(),Ee=be.set(),Pe=e=>(t,r,s)=>V(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield pe.is(o,e))?s():ue.error(r,"Unauthorized access"):ue.unauthorized(r,"Access denied")})),Oe={name:I.string().min(3).required(),description:I.string().allow(null,""),state:I.boolean().required()},Ne=fe(I.object(Oe)),Re={routes:I.array().items(I.number())},qe=fe(I.object(Re)),je={name:I.string().min(3).empty(""),description:I.string().allow(null,""),state:I.boolean().empty("")},ke=fe(I.object(je)),xe=v();xe.use(ve),xe.get("/",Pe("groups.read"),Ae),xe.post("/",Pe("groups.write"),Ne,Te),xe.route("/:id").get(Pe("groups.read"),_e).put(Pe("groups.write"),ke,Ee).delete(Pe("groups.write"),Se),xe.route("/:id/routes").get(Pe("groups.read"),qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,s=yield oe.findAll({where:{groupId:r},include:[{model:se,required:!0}]}).catch((e=>{de.error(e.message,"groups.routesAll")}));return s?ue.list(t,s.map((e=>e.route))):ue.error(t,"Internal Server Error")})))).put(Pe("groups.write"),qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield te.findByPk(r,{attributes:["id"]}).catch((e=>{de.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield oe.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield se.count({where:{id:s[r]}}),t&&(yield oe.create({groupId:e,routeId:s[r]}))}return ue.success(t,"OK")}return null===o?ue.notfound(t,"Record not found"):ue.error(t,"Internal Server Error")}))));const De=new Ie("route",se),Be=De.add(),ze=De.all(),Ge=De.del(),Ue=De.get(),Le=De.set(),Ce={name:I.string().min(5).required(),permission:I.string().required(),description:I.string().allow(null,""),state:I.boolean().required()},He=fe(I.object(Ce)),Ke={name:I.string().min(5).empty(""),permission:I.string().empty(""),description:I.string().allow(null,""),state:I.boolean().empty("")},Me=fe(I.object(Ke)),Fe=v();Fe.use(ve),Fe.get("/",Pe("routes.read"),ze),Fe.post("/",Pe("routes.write"),He,Be),Fe.route("/:id").get(Pe("routes.read"),Ue).put(Pe("routes.write"),Me,Le).delete(Pe("routes.write"),Ge);const We=new Ie("user",ne),Xe=new Ie("user.groups",ie),Ye=["id","name","email","username","description","state"],$e=We.del(),Je={name:I.string().min(5).required(),email:I.string().email().required(),username:I.string().min(5).required(),password:I.string().min(5).required(),description:I.string().allow(null,""),state:I.boolean().required()},Ve=fe(I.object(Je)),Ze={groups:I.array().items(I.number())},Qe=fe(I.object(Ze)),et={name:I.string().min(5).empty(""),email:I.string().email().empty(""),username:I.string().min(5).empty(""),password:I.string().min(5).empty(""),description:I.string().allow(null,""),state:I.boolean().empty("")},tt=fe(I.object(et)),rt=v();rt.use(ve),rt.get("/",Pe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){return We.all({attributes:Ye})(e,t)})))),rt.post("/",Pe("users.write"),Ve,((e,t)=>V(void 0,void 0,void 0,(function*(){return e.body.password=y(e.body.password).toString(),yield We.add()(e,t)})))),rt.route("/:id").get(Pe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){return We.get({attributes:Ye})(e,t)})))).put(Pe("users.write"),tt,((e,t)=>V(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=y(e.body.password).toString()),We.set()(e,t)})))).delete(Pe("users.write"),$e),rt.route("/:id/groups").get(Pe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Xe.all({where:{userId:r},include:[{model:te,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Pe("users.write"),Qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield ne.findByPk(r,{attributes:["id"]}).catch((e=>{de.error(e.message,"user.groups.set")}));if(o){if(yield ie.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield te.count({where:{id:s[t]}}),e&&(yield ie.create({userId:o.id,groupId:s[t]}))}return ue.success(t,"OK")}return ue.notfound(t,"Record not found")}))));const st=v();st.use("/v1/auth",we),st.use("/v1/groups",xe),st.use("/v1/routes",Fe),st.use("/v1/users",rt);const ot=g();ot.use(g.json()),ot.use(((e,t,r,s)=>e?(de.error(e.message,"express"),ue.error(r,"Internal Server Error")):s())),ot.use(g.urlencoded({extended:!0})),ot.disable("x-powered-by"),L&&ot.use(p()),ot.use("/api",st),ot.all("/api/*",((e,t)=>ue.notfound(t,"Invalid API"))),U&&(f(U)&&ot.use(g.static(U)),ot.get("*",((e,t)=>{if(!f(U))return ue.notfound(t,'File "index.html" not found');t.sendFile(U+"/index.html")})));const nt=e=>{const t=new S.Server({server:e,verifyClient:it});return t.on("connection",(e=>{e.on("message",(t=>{e.close()})),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},it=(e,t)=>t(J),at=()=>{Q.sync().then((()=>{V(void 0,void 0,void 0,(function*(){if(0==(yield ne.count())){const e=yield ne.create({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",description:"",state:!0});if(0==(yield te.count())){const r=yield te.create({name:"admin",description:"",state:!0});if(yield ie.create({userId:e.id,groupId:r.id}),0==(yield se.count())){const e=["read","write"];t(["users","groups","permission"],(s=>V(void 0,void 0,void 0,(function*(){t(e,(e=>V(void 0,void 0,void 0,(function*(){const t=s.toLowerCase()+"."+e.toLowerCase(),o=yield se.create({name:t,description:"",state:!0});yield oe.create({groupId:r.id,routeId:o.id})}))))}))))}}}})),J&&nt(dt)}))},dt=(e=>{if(!le.http||!me.http){const t=b.createServer(e);return t.listen(G,(()=>de.info(`Server started on port ${G}`))),t}const t=b.createServer(((e,t)=>{const r=80==G?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=T.createServer({key:me.http,cert:le.http},e);if(C){return new A((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(G,(()=>de.info(`Server started on port ${G}`))),r}return 443==G&&t.listen(80,(()=>de.info("Server started on port 80"))),r.listen(G,(()=>de.info(`Server started on port ${G}`))),r})(ot),ut=(e,t)=>{const r=i()+"."+t;return f(P(e,r))?ut(e,t):r},ct=e=>{const t=(null==e?void 0:e.path)||$,r=E.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>V(void 0,void 0,void 0,(function*(){return s(null,ut(t,_.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||Y),o=E({storage:r,fileFilter(t,r,s){var o;return V(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.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)||W,i=(null==e?void 0:e.field)||X,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?ue.error(t,e.message):r()}))}};export{O as API_AUTH_SLEEP,N as API_DB_DATABASE,R as API_DB_HOST,D as API_DB_LOG,q as API_DB_PASSWORD,j as API_DB_PORT,k as API_DB_TYPE,x as API_DB_USERNAME,L as API_HTTP_CROSS,B as API_HTTP_CRT,C as API_HTTP_HYBRID,z as API_HTTP_KEY,G as API_HTTP_PORT,U as API_HTTP_PUBLIC,H as API_TOKEN_CRT,M as API_TOKEN_HEADER,K as API_TOKEN_KEY,F as API_TOKEN_LIFETIME,W as API_UPLOAD_COUNT,X as API_UPLOAD_FIELD,Y as API_UPLOAD_SIZE,$ as API_UPLOAD_TEMP,J as API_WEBSOCKET_START,ee as Auth,Ie as Controller,te as Group,oe as GroupRoute,de as Log,re as Logs,pe as Permission,ue as Responses,se as Route,ne as User,ie as UserGroup,ot as app,ve as auth,le as crt,at as initialize,me as key,Pe as permission,st as router,Q as sequelize,dt as server,nt as startSocket,ct as upload,Z as uuid,fe as validation};
|
|
6
|
+
import{toBool as e,forEachSeries as t,dateFormat as r,sleep as s,uniqueID as o,allowedObject as n,noop as i,uuidv4 as a}from"@andrewcaires/utils.js";import{config as d}from"dotenv";import{Sequelize as u,UUID as c,UUIDV4 as l,DataTypes as m,Model as p,Op as g}from"sequelize";import v from"cors";import f,{Router as h}from"express";import{existsSync as y,readFileSync as w}from"fs";import{SHA256 as I}from"crypto-js";import b from"jsonwebtoken";import S from"joi";import*as T from"http";import*as A from"https";import{Server as O}from"net";import E from"ws";import _ from"mime-types";import P from"multer";import{join as N}from"path";d();const R=parseInt(process.env.API_AUTH_SLEEP||"1000"),j=process.env.API_DB_DATABASE||"",q=process.env.API_DB_HOST||"127.0.0.1",k=process.env.API_DB_PASSWORD||"",D=parseInt(process.env.API_DB_PORT||"3306"),x=process.env.API_DB_TYPE||"",B=process.env.API_DB_USERNAME||"root",z=e(process.env.API_DB_LOG||"false"),G=process.env.API_HTTP_CRT||"",U=process.env.API_HTTP_KEY||"",C=parseInt(process.env.API_HTTP_PORT||"3000"),L=process.env.API_HTTP_PUBLIC||"",H=e(process.env.API_HTTP_CROSS||"false"),K=e(process.env.API_HTTP_HYBRID||"false"),M=process.env.API_TOKEN_CRT||"",F=process.env.API_TOKEN_KEY||"",W=process.env.API_TOKEN_HEADER||"authorization",X=parseInt(process.env.API_TOKEN_LIFETIME||"15"),Y=parseInt(process.env.API_UPLOAD_COUNT||"1"),$=process.env.API_UPLOAD_FIELD||"upload",J=parseInt(process.env.API_UPLOAD_SIZE||"2"),V=process.env.API_UPLOAD_TEMP||"./temp",Z=e(process.env.API_WEBSOCKET_START||"false");function Q(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())}))}const ee={type:c,defaultValue:l,allowNull:!1,primaryKey:!0},te=(()=>{switch(x){case"mariadb":return new u(j,B,k,{host:q,port:D,dialect:"mariadb",logging:z,define:{timestamps:!1}});case"mysql":return new u(j,B,k,{host:q,port:D,dialect:"mysql",logging:z,define:{timestamps:!1}});case"postgres":return new u(j,B,k,{host:q,port:D,dialect:"postgres",logging:z,define:{timestamps:!1}})}throw new Error("No database selected")})();class re extends p{}re.init({login:m.BIGINT,logout:m.BIGINT,secret:m.STRING,timestamp:m.BIGINT,useragent:m.STRING},{sequelize:te,modelName:"auth"});class se extends p{}se.init({name:m.STRING,description:m.TEXT,state:m.BOOLEAN},{sequelize:te,modelName:"group"});class oe extends p{}oe.init({type:m.STRING,source:m.STRING,message:m.TEXT},{sequelize:te,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class ne extends p{}ne.init({name:m.STRING,description:m.TEXT,state:m.BOOLEAN},{sequelize:te,modelName:"route"});class ie extends p{}ie.init({},{sequelize:te,modelName:"groups_routes"}),ie.removeAttribute("id");class ae extends p{}ae.init({name:m.STRING,email:m.STRING,username:m.STRING,password:m.STRING,description:m.TEXT,state:m.BOOLEAN},{sequelize:te,modelName:"user"});class de extends p{}de.init({},{sequelize:te,modelName:"users_groups"}),de.removeAttribute("id"),ae.hasMany(re),re.belongsTo(ae),se.hasMany(ie),ie.belongsTo(se),ne.hasMany(ie),ie.belongsTo(ne),ae.hasMany(de),de.belongsTo(ae),se.hasMany(de),de.belongsTo(se);var ue;!function(e){e.ERROR="[31m",e.INFO="[36m",e.NONE="[37m",e.SUCCESS="[32m",e.WARNING="[33m"}(ue||(ue={}));class ce{static write(e,t){ce.writeRaw(ue.NONE,"",e,t)}static error(e,t){ce.writeRaw(ue.ERROR,"error",e,t)}static info(e,t){ce.writeRaw(ue.INFO,"info",e,t)}static success(e,t){ce.writeRaw(ue.ERROR,"success",e,t)}static warning(e,t){ce.writeRaw(ue.WARNING,"warning",e,t)}static writeConsole(e,t,s){const o=r(new Date,"%H:%M:%S");console.log(">",e,t+" ".repeat(10-t.length),"[37m","|",o,"|",s)}static writeRaw(e,t,r,s){ce.writeConsole(e,t,r),oe.create({type:t,source:s,message:r}).catch((()=>null))}}class le{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,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}const me=e=>{if(y(e))return w(e)},pe={http:me(G),token:me(M)},ge={http:me(U),token:me(F)};class ve{static all(e,t){return Q(this,void 0,void 0,(function*(){return yield ne.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:ie,required:!0,include:[{model:se,required:!0,where:{state:!0},include:[{model:de,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ce.error(e.message,"permission")}))}))}static get(e){return Q(this,void 0,void 0,(function*(){const t=yield ve.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return Q(this,void 0,void 0,(function*(){const r=yield ve.all(e,{name:t});return r&&!!r.length}))}}const fe=["id","name","email","username"],he=(e,t,r)=>Q(void 0,void 0,void 0,(function*(){const s=e.get(W)||"";if(!pe.token)return le.error(t,"Invalid Secret");if(!s||s.split(".").length<3)return le.error(t,"Invalid token");let o;try{o=b.verify(s,pe.token)}catch(e){return le.error(t,"Invalid token")}if(o&&o.id&&o.secret){const s=yield ae.findOne({where:{id:o.id}}).catch((e=>{ce.error(e.message,"token.check")}));if(s&&s.state){const n=yield re.findOne({where:{logout:null,secret:o.secret,userId:s.id}}).catch((e=>{ce.error(e.message,"token.check")}));if(n){const o=Date.now();if(o>n.timestamp)return le.error(t,"Expired token");n.timestamp=o+6e4*X;const i=e.get("User-Agent");return i&&(n.useragent=i),yield n.save(),e.auth=n,e.user=s,r()}}return le.error(t,"Access denied")}return le.error(t,"Invalid token")})),ye=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),le.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},we={username:S.string().min(5).required(),password:S.string().min(5).required()},Ie=ye(S.object(we)),be=h();be.get("/",he,((e,t)=>Q(void 0,void 0,void 0,(function*(){const r=e.user;if(!r)return le.unauthorized(t,"Access denied");const s=yield ve.all(r);if(s){const e=n(fe,r.toJSON()),o=s.map((e=>e.name));return le.data(t,Object.assign(Object.assign({},e),{permissions:o}))}return le.error(t,"Internal Server Error")})))),be.post("/login",Ie,((e,t)=>Q(void 0,void 0,void 0,(function*(){const{username:r,password:n}=e.body;if(!r||!n)return le.error(t,"Invalid parameters");yield s(R);const i=yield ae.findOne({where:{username:r}}).catch((e=>{ce.error(e.message,"auth.login")}));if(!i)return le.notfound(t,"User not found");if(!i.state)return le.error(t,"User is disabled");const a=I(n).toString();if(i.password!=a)return le.error(t,"Invalid password");if(!ge.token)return le.error(t,"Invalid Secret");const d=i.id,u=o(),c=b.sign({id:d,secret:u},ge.token,{algorithm:"RS256"});if(c){const r=Date.now(),s=r+6e4*X,o=e.get("User-Agent");if(yield re.create({login:r,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{ce.error(e.message,"auth.login")})))return le.data(t,{token:c})}return le.error(t,"Internal Server Error")})))),be.get("/logout",he,((e,t)=>Q(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),le.success(t,"Disconcerted")):le.unauthorized(t,"Access denied")}))));class Se{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>Q(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{ce.error(e.message,this.log+".add")}));return r?le.data(t,{id:r.id}):le.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>Q(this,void 0,void 0,(function*(){var o,n,a,d,u;e||(e={});const c=Object.assign({},e);c.where=c.where?Object.assign({},c.where):{};const l=null===(o=r.query.limit)||void 0===o?void 0:o.toString();l&&(c.limit=parseInt(l));const m=null===(n=r.query.offset)||void 0===n?void 0:n.toString();m&&(c.offset=parseInt(m));const p=null===(a=r.query.asc)||void 0===a?void 0:a.toString();p&&(c.order=[[p,"ASC"]]);const v=null===(d=r.query.desc)||void 0===d?void 0:d.toString();v&&(c.order=[[v,"DESC"]]);const f=[],h=null===(u=r.query.search)||void 0===u?void 0:u.toString();h&&(Object.keys(this.model.getAttributes()).forEach((e=>{f.push({[e]:{[g.like]:`%${h}%`}})})),f.length&&(c.where=Object.assign(Object.assign({},c.where),{[g.or]:[...f]})));const y=yield this.model.findAll(c).catch((e=>{ce.error(e.message,this.log+".all")})),w=yield this.model.count(c).catch(i);return y?le.data(s,{count:w,records:t?t(y):y}):le.error(s,"Internal Server Error")}))}del(){return(e,t)=>Q(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{ce.error(e.message,this.log+".del")})))?le.success(t,"OK"):le.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>Q(this,void 0,void 0,(function*(){e||(e={});const o=Object.assign({},e);o.where=o.where?Object.assign({},o.where):{};const{id:n}=r.params,i=yield this.model.findByPk(n,o).catch((e=>{ce.error(e.message,this.log+".get")}));return i?le.data(s,t?t(i):i.toJSON()):null===i?le.notfound(s,"Record not found"):le.error(s,"Internal Server Error")}))}set(){return(e,t)=>Q(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{ce.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return le.success(t,"OK")}return le.success(t,"Record not changed")}))}}const Te=new Se("groups",se),Ae=new Se("groups.route",ie),Oe=Te.add(),Ee=Te.all(),_e=Te.del(),Pe=Te.get(),Ne=Te.set(),Re=e=>(t,r,s)=>Q(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield ve.is(o,e))?s():le.error(r,"Unauthorized access"):le.unauthorized(r,"Access denied")})),je={name:S.string().min(3).required(),description:S.string().allow(null,""),state:S.boolean().required()},qe=ye(S.object(je)),ke={routes:S.array().items(S.number())},De=ye(S.object(ke)),xe={name:S.string().min(3).empty(""),description:S.string().allow(null,""),state:S.boolean().empty("")},Be=ye(S.object(xe)),ze=h();ze.use(he),ze.get("/",Re("groups.read"),Ee),ze.post("/",Re("groups.write"),qe,Oe),ze.route("/:id").get(Re("groups.read"),Pe).put(Re("groups.write"),Be,Ne).delete(Re("groups.write"),_e),ze.route("/:id/routes").get(Re("groups.read"),De,((e,t)=>Q(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ae.all({where:{groupId:r},include:[{model:ne,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(Re("groups.write"),De,((e,t)=>Q(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield se.findByPk(r,{attributes:["id"]}).catch((e=>{ce.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield ie.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield ne.count({where:{id:s[r]}}),t&&(yield ie.create({groupId:e,routeId:s[r]}))}return le.success(t,"OK")}return null===o?le.notfound(t,"Record not found"):le.error(t,"Internal Server Error")}))));const Ge=new Se("route",ne),Ue=Ge.add(),Ce=Ge.all(),Le=Ge.del(),He=Ge.get(),Ke=Ge.set(),Me={name:S.string().min(5).required(),permission:S.string().required(),description:S.string().allow(null,""),state:S.boolean().required()},Fe=ye(S.object(Me)),We={name:S.string().min(5).empty(""),permission:S.string().empty(""),description:S.string().allow(null,""),state:S.boolean().empty("")},Xe=ye(S.object(We)),Ye=h();Ye.use(he),Ye.get("/",Re("routes.read"),Ce),Ye.post("/",Re("routes.write"),Fe,Ue),Ye.route("/:id").get(Re("routes.read"),He).put(Re("routes.write"),Xe,Ke).delete(Re("routes.write"),Le);const $e=new Se("user",ae),Je=new Se("user.groups",de),Ve=["id","name","email","username","description","state"],Ze=$e.del(),Qe={name:S.string().min(5).required(),email:S.string().email().required(),username:S.string().min(5).required(),password:S.string().min(5).required(),description:S.string().allow(null,""),state:S.boolean().required()},et=ye(S.object(Qe)),tt={groups:S.array().items(S.number())},rt=ye(S.object(tt)),st={name:S.string().min(5).empty(""),email:S.string().email().empty(""),username:S.string().min(5).empty(""),password:S.string().min(5).empty(""),description:S.string().allow(null,""),state:S.boolean().empty("")},ot=ye(S.object(st)),nt=h();nt.use(he),nt.get("/",Re("users.read"),((e,t)=>Q(void 0,void 0,void 0,(function*(){return $e.all({attributes:Ve})(e,t)})))),nt.post("/",Re("users.write"),et,((e,t)=>Q(void 0,void 0,void 0,(function*(){return e.body.password=I(e.body.password).toString(),yield $e.add()(e,t)})))),nt.route("/:id").get(Re("users.read"),((e,t)=>Q(void 0,void 0,void 0,(function*(){return $e.get({attributes:Ve})(e,t)})))).put(Re("users.write"),ot,((e,t)=>Q(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=I(e.body.password).toString()),$e.set()(e,t)})))).delete(Re("users.write"),Ze),nt.route("/:id/groups").get(Re("users.read"),((e,t)=>Q(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Je.all({where:{userId:r},include:[{model:se,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Re("users.write"),rt,((e,t)=>Q(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield ae.findByPk(r,{attributes:["id"]}).catch((e=>{ce.error(e.message,"user.groups.set")}));if(o){if(yield de.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield se.count({where:{id:s[t]}}),e&&(yield de.create({userId:o.id,groupId:s[t]}))}return le.success(t,"OK")}return le.notfound(t,"Record not found")}))));const it=h();it.use("/v1/auth",be),it.use("/v1/groups",ze),it.use("/v1/routes",Ye),it.use("/v1/users",nt);const at=f();at.use(f.json()),at.use(((e,t,r,s)=>e?(ce.error(e.message,"express"),le.error(r,"Internal Server Error")):s())),at.use(f.urlencoded({extended:!0})),at.disable("x-powered-by"),H&&at.use(v()),at.use("/api",it),at.all("/api/*",((e,t)=>le.notfound(t,"Invalid API"))),L&&(y(L)&&at.use(f.static(L)),at.get("*",((e,t)=>{if(!y(L))return le.notfound(t,'File "index.html" not found');t.sendFile(L+"/index.html")})));const dt=e=>{const t=new E.Server({server:e,verifyClient:ut});return t.on("connection",(e=>{e.on("message",(t=>{e.close()})),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},ut=(e,t)=>t(Z),ct=()=>{te.sync().then((()=>{Q(void 0,void 0,void 0,(function*(){if(0==(yield ae.count())){const e=yield ae.create({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",description:"",state:!0});if(0==(yield se.count())){const r=yield se.create({name:"admin",description:"",state:!0});if(yield de.create({userId:e.id,groupId:r.id}),0==(yield ne.count())){const e=["read","write"];t(["users","groups","permission"],(s=>Q(void 0,void 0,void 0,(function*(){t(e,(e=>Q(void 0,void 0,void 0,(function*(){const t=s.toLowerCase()+"."+e.toLowerCase(),o=yield ne.create({name:t,description:"",state:!0});yield ie.create({groupId:r.id,routeId:o.id})}))))}))))}}}})),Z&&dt(lt)}))},lt=(e=>{if(!pe.http||!ge.http){const t=T.createServer(e);return t.listen(C,(()=>ce.info(`Server started on port ${C}`))),t}const t=T.createServer(((e,t)=>{const r=80==C?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=A.createServer({key:ge.http,cert:pe.http},e);if(K){return new O((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(C,(()=>ce.info(`Server started on port ${C}`))),r}return 443==C&&t.listen(80,(()=>ce.info("Server started on port 80"))),r.listen(C,(()=>ce.info(`Server started on port ${C}`))),r})(at),mt=(e,t)=>{const r=a()+"."+t;return y(N(e,r))?mt(e,t):r},pt=e=>{const t=(null==e?void 0:e.path)||V,r=P.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>Q(void 0,void 0,void 0,(function*(){return s(null,mt(t,_.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||J),o=P({storage:r,fileFilter(t,r,s){var o;return Q(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.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)||Y,i=(null==e?void 0:e.field)||$,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?le.error(t,e.message):r()}))}};export{R as API_AUTH_SLEEP,j as API_DB_DATABASE,q as API_DB_HOST,z as API_DB_LOG,k as API_DB_PASSWORD,D as API_DB_PORT,x as API_DB_TYPE,B as API_DB_USERNAME,H as API_HTTP_CROSS,G as API_HTTP_CRT,K as API_HTTP_HYBRID,U as API_HTTP_KEY,C as API_HTTP_PORT,L as API_HTTP_PUBLIC,M as API_TOKEN_CRT,W as API_TOKEN_HEADER,F as API_TOKEN_KEY,X as API_TOKEN_LIFETIME,Y as API_UPLOAD_COUNT,$ as API_UPLOAD_FIELD,J as API_UPLOAD_SIZE,V as API_UPLOAD_TEMP,Z as API_WEBSOCKET_START,re as Auth,Se as Controller,se as Group,ie as GroupRoute,ce as Log,oe as Logs,ve as Permission,le as Responses,ne as Route,ae as User,de as UserGroup,at as app,he as auth,pe as crt,ct as initialize,ge as key,Re as permission,it as router,te as sequelize,lt as server,dt as startSocket,pt as upload,ee as uuid,ye as validation};
|
package/dist/index.umd.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* (c) 2022 Andrew Caires
|
|
4
4
|
* @license: MIT
|
|
5
5
|
*/
|
|
6
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@andrewcaires/utils.js"),t=require("dotenv"),r=require("sequelize"),s=require("cors"),o=require("express"),n=require("fs"),i=require("crypto-js"),a=require("jsonwebtoken"),d=require("joi"),u=require("http"),l=require("https"),c=require("net"),p=require("ws"),f=require("mime-types"),m=require("multer"),g=require("path");function v(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function y(e){if(e&&e.__esModule)return 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 I=v(s),h=v(o),T=v(a),_=v(d),w=y(u),A=y(l),P=v(p),S=v(f),x=v(m);t.config();const E=parseInt(process.env.API_AUTH_SLEEP||"1000"),b=process.env.API_DB_DATABASE||"",O=process.env.API_DB_HOST||"127.0.0.1",D=process.env.API_DB_PASSWORD||"",R=parseInt(process.env.API_DB_PORT||"3306"),q=process.env.API_DB_TYPE||"",N=process.env.API_DB_USERNAME||"root",j=e.toBool(process.env.API_DB_LOG||"false"),B=process.env.API_HTTP_CRT||"",U=process.env.API_HTTP_KEY||"",k=parseInt(process.env.API_HTTP_PORT||"3000"),L=process.env.API_HTTP_PUBLIC||"",H=e.toBool(process.env.API_HTTP_CROSS||"false"),z=e.toBool(process.env.API_HTTP_HYBRID||"false"),M=process.env.API_TOKEN_CRT||"",C=process.env.API_TOKEN_KEY||"",G=process.env.API_TOKEN_HEADER||"authorization",K=parseInt(process.env.API_TOKEN_LIFETIME||"15"),F=parseInt(process.env.API_UPLOAD_COUNT||"1"),Y=process.env.API_UPLOAD_FIELD||"upload",W=parseInt(process.env.API_UPLOAD_SIZE||"2"),X=process.env.API_UPLOAD_TEMP||"./temp",V=e.toBool(process.env.API_WEBSOCKET_START||"false");function $(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())}))}const J={type:r.UUID,defaultValue:r.UUIDV4,allowNull:!1,primaryKey:!0},Z=(()=>{switch(q){case"mariadb":return new r.Sequelize(b,N,D,{host:O,port:R,dialect:"mariadb",logging:j,define:{timestamps:!1}});case"mysql":return new r.Sequelize(b,N,D,{host:O,port:R,dialect:"mysql",logging:j,define:{timestamps:!1}});case"postgres":return new r.Sequelize(b,N,D,{host:O,port:R,dialect:"postgres",logging:j,define:{timestamps:!1}})}throw new Error("No database selected")})();class Q extends r.Model{}Q.init({login:r.DataTypes.BIGINT,logout:r.DataTypes.BIGINT,secret:r.DataTypes.STRING,timestamp:r.DataTypes.BIGINT,useragent:r.DataTypes.STRING},{sequelize:Z,modelName:"auth"});class ee extends r.Model{}ee.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"group"});class te extends r.Model{}te.init({type:r.DataTypes.STRING,source:r.DataTypes.STRING,message:r.DataTypes.TEXT},{sequelize:Z,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class re extends r.Model{}re.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"route"});class se extends r.Model{}se.init({},{sequelize:Z,modelName:"groups_routes"}),se.removeAttribute("id");class oe extends r.Model{}oe.init({name:r.DataTypes.STRING,email:r.DataTypes.STRING,username:r.DataTypes.STRING,password:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"user"});class ne extends r.Model{}ne.init({},{sequelize:Z,modelName:"users_groups"}),ne.removeAttribute("id"),oe.hasMany(Q),Q.belongsTo(oe),ee.hasMany(se),se.belongsTo(ee),re.hasMany(se),se.belongsTo(re),oe.hasMany(ne),ne.belongsTo(oe),ee.hasMany(ne),ne.belongsTo(ee);var ie;!function(e){e.ERROR="[31m",e.INFO="[36m",e.NONE="[37m",e.SUCCESS="[32m",e.WARNING="[33m"}(ie||(ie={}));class ae{static write(e,t){ae.writeRaw(ie.NONE,"",e,t)}static error(e,t){ae.writeRaw(ie.ERROR,"error",e,t)}static info(e,t){ae.writeRaw(ie.INFO,"info",e,t)}static success(e,t){ae.writeRaw(ie.ERROR,"success",e,t)}static warning(e,t){ae.writeRaw(ie.WARNING,"warning",e,t)}static writeConsole(t,r,s){const o=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"[37m","|",o,"|",s)}static writeRaw(e,t,r,s){ae.writeConsole(e,t,r),te.create({type:t,source:s,message:r}).catch((()=>null))}}class de{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,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}const ue=e=>{if(n.existsSync(e))return n.readFileSync(e)},le={http:ue(B),token:ue(M)},ce={http:ue(U),token:ue(C)};class pe{static all(e,t){return $(this,void 0,void 0,(function*(){return yield re.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:se,required:!0,include:[{model:ee,required:!0,where:{state:!0},include:[{model:ne,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ae.error(e.message,"permission")}))}))}static get(e){return $(this,void 0,void 0,(function*(){const t=yield pe.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return $(this,void 0,void 0,(function*(){const r=yield pe.all(e,{name:t});return r&&!!r.length}))}}const fe=["id","name","email","username"],me=(e,t,r)=>$(void 0,void 0,void 0,(function*(){const s=e.get(G)||"";if(!le.token)return de.error(t,"Invalid Secret");if(!s||s.split(".").length<3)return de.error(t,"Invalid token");const o=T.default.verify(s,le.token);if(o&&o.id&&o.secret){const s=yield oe.findOne({where:{id:o.id}}).catch((e=>{ae.error(e.message,"token.check")}));if(s&&s.state){const n=yield Q.findOne({where:{logout:null,secret:o.secret,userId:s.id}}).catch((e=>{ae.error(e.message,"token.check")}));if(n){const o=Date.now();if(o>n.timestamp)return de.error(t,"Expired token");n.timestamp=o+6e4*K;const i=e.get("User-Agent");return i&&(n.useragent=i),yield n.save(),e.auth=n,e.user=s,r()}}return de.error(t,"Access denied")}return de.error(t,"Invalid token")})),ge=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),de.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},ve={username:_.default.string().min(5).required(),password:_.default.string().min(5).required()},ye=ge(_.default.object(ve)),Ie=o.Router();Ie.get("/",me,((t,r)=>$(void 0,void 0,void 0,(function*(){const s=t.user;if(!s)return de.unauthorized(r,"Access denied");const o=yield pe.all(s);if(o){const t=e.allowedObject(fe,s.toJSON()),n=o.map((e=>e.name));return de.data(r,Object.assign(Object.assign({},t),{permissions:n}))}return de.error(r,"Internal Server Error")})))),Ie.post("/login",ye,((t,r)=>$(void 0,void 0,void 0,(function*(){const{username:s,password:o}=t.body;if(!s||!o)return de.error(r,"Invalid parameters");yield e.sleep(E);const n=yield oe.findOne({where:{username:s}}).catch((e=>{ae.error(e.message,"auth.login")}));if(!n)return de.notfound(r,"User not found");if(!n.state)return de.error(r,"User is disabled");const a=i.SHA256(o).toString();if(n.password!=a)return de.error(r,"Invalid password");if(!ce.token)return de.error(r,"Invalid Secret");const d=n.id,u=e.uniqueID(),l=T.default.sign({id:d,secret:u},ce.token,{algorithm:"RS256"});if(l){const e=Date.now(),s=e+6e4*K,o=t.get("User-Agent");if(yield Q.create({login:e,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{ae.error(e.message,"auth.login")})))return de.data(r,{token:l})}return de.error(r,"Internal Server Error")})))),Ie.get("/logout",me,((e,t)=>$(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),de.success(t,"Disconcerted")):de.unauthorized(t,"Access denied")}))));class he{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>$(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{ae.error(e.message,this.log+".add")}));return r?de.data(t,{id:r.id}):de.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>$(this,void 0,void 0,(function*(){var o,n;e||(e={});const i=null===(o=r.query.limit)||void 0===o?void 0:o.toString();i&&(e.limit=parseInt(i));const a=null===(n=r.query.offset)||void 0===n?void 0:n.toString();a&&(e.offset=parseInt(a));const d=yield this.model.findAll(e).catch((e=>{ae.error(e.message,this.log+".all")})),u=yield this.model.count().catch((e=>{ae.error(e.message,this.log+".all")}));return d?de.data(s,{count:u,records:t?t(d):d}):de.error(s,"Internal Server Error")}))}del(){return(e,t)=>$(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{ae.error(e.message,this.log+".del")})))?de.success(t,"OK"):de.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>$(this,void 0,void 0,(function*(){e||(e={});const{id:o}=r.params,n=yield this.model.findByPk(o,e).catch((e=>{ae.error(e.message,this.log+".get")}));return n?de.data(s,t?t(n):n.toJSON()):null===n?de.notfound(s,"Record not found"):de.error(s,"Internal Server Error")}))}set(){return(e,t)=>$(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{ae.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return de.success(t,"OK")}return de.success(t,"Record not changed")}))}}const Te=new he("groups",ee),_e=Te.add(),we=Te.all(),Ae=Te.del(),Pe=Te.get(),Se=Te.set(),xe=e=>(t,r,s)=>$(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield pe.is(o,e))?s():de.error(r,"Unauthorized access"):de.unauthorized(r,"Access denied")})),Ee={name:_.default.string().min(3).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},be=ge(_.default.object(Ee)),Oe={routes:_.default.array().items(_.default.number())},De=ge(_.default.object(Oe)),Re={name:_.default.string().min(3).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},qe=ge(_.default.object(Re)),Ne=o.Router();Ne.use(me),Ne.get("/",xe("groups.read"),we),Ne.post("/",xe("groups.write"),be,_e),Ne.route("/:id").get(xe("groups.read"),Pe).put(xe("groups.write"),qe,Se).delete(xe("groups.write"),Ae),Ne.route("/:id/routes").get(xe("groups.read"),De,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,s=yield se.findAll({where:{groupId:r},include:[{model:re,required:!0}]}).catch((e=>{ae.error(e.message,"groups.routesAll")}));return s?de.list(t,s.map((e=>e.route))):de.error(t,"Internal Server Error")})))).put(xe("groups.write"),De,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield ee.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield se.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield re.count({where:{id:s[r]}}),t&&(yield se.create({groupId:e,routeId:s[r]}))}return de.success(t,"OK")}return null===o?de.notfound(t,"Record not found"):de.error(t,"Internal Server Error")}))));const je=new he("route",re),Be=je.add(),Ue=je.all(),ke=je.del(),Le=je.get(),He=je.set(),ze={name:_.default.string().min(5).required(),permission:_.default.string().required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},Me=ge(_.default.object(ze)),Ce={name:_.default.string().min(5).empty(""),permission:_.default.string().empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},Ge=ge(_.default.object(Ce)),Ke=o.Router();Ke.use(me),Ke.get("/",xe("routes.read"),Ue),Ke.post("/",xe("routes.write"),Me,Be),Ke.route("/:id").get(xe("routes.read"),Le).put(xe("routes.write"),Ge,He).delete(xe("routes.write"),ke);const Fe=new he("user",oe),Ye=new he("user.groups",ne),We=["id","name","email","username","description","state"],Xe=Fe.del(),Ve={name:_.default.string().min(5).required(),email:_.default.string().email().required(),username:_.default.string().min(5).required(),password:_.default.string().min(5).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},$e=ge(_.default.object(Ve)),Je={groups:_.default.array().items(_.default.number())},Ze=ge(_.default.object(Je)),Qe={name:_.default.string().min(5).empty(""),email:_.default.string().email().empty(""),username:_.default.string().min(5).empty(""),password:_.default.string().min(5).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},et=ge(_.default.object(Qe)),tt=o.Router();tt.use(me),tt.get("/",xe("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return Fe.all({attributes:We})(e,t)})))),tt.post("/",xe("users.write"),$e,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password=i.SHA256(e.body.password).toString(),yield Fe.add()(e,t)})))),tt.route("/:id").get(xe("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return Fe.get({attributes:We})(e,t)})))).put(xe("users.write"),et,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=i.SHA256(e.body.password).toString()),Fe.set()(e,t)})))).delete(xe("users.write"),Xe),tt.route("/:id/groups").get(xe("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ye.all({where:{userId:r},include:[{model:ee,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(xe("users.write"),Ze,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield oe.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"user.groups.set")}));if(o){if(yield ne.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield ee.count({where:{id:s[t]}}),e&&(yield ne.create({userId:o.id,groupId:s[t]}))}return de.success(t,"OK")}return de.notfound(t,"Record not found")}))));const rt=o.Router();rt.use("/v1/auth",Ie),rt.use("/v1/groups",Ne),rt.use("/v1/routes",Ke),rt.use("/v1/users",tt);const st=h.default();st.use(h.default.json()),st.use(((e,t,r,s)=>e?(ae.error(e.message,"express"),de.error(r,"Internal Server Error")):s())),st.use(h.default.urlencoded({extended:!0})),st.disable("x-powered-by"),H&&st.use(I.default()),st.use("/api",rt),st.all("/api/*",((e,t)=>de.notfound(t,"Invalid API"))),L&&(n.existsSync(L)&&st.use(h.default.static(L)),st.get("*",((e,t)=>{if(!n.existsSync(L))return de.notfound(t,'File "index.html" not found');t.sendFile(L+"/index.html")})));const ot=e=>{const t=new P.default.Server({server:e,verifyClient:nt});return t.on("connection",(e=>{e.on("message",(t=>{e.close()})),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},nt=(e,t)=>t(V),it=(e=>{if(!le.http||!ce.http){const t=w.createServer(e);return t.listen(k,(()=>ae.info(`Server started on port ${k}`))),t}const t=w.createServer(((e,t)=>{const r=80==k?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=A.createServer({key:ce.http,cert:le.http},e);if(z){return new c.Server((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(k,(()=>ae.info(`Server started on port ${k}`))),r}return 443==k&&t.listen(80,(()=>ae.info("Server started on port 80"))),r.listen(k,(()=>ae.info(`Server started on port ${k}`))),r})(st),at=(t,r)=>{const s=e.uuidv4()+"."+r;return n.existsSync(g.join(t,s))?at(t,r):s};exports.API_AUTH_SLEEP=E,exports.API_DB_DATABASE=b,exports.API_DB_HOST=O,exports.API_DB_LOG=j,exports.API_DB_PASSWORD=D,exports.API_DB_PORT=R,exports.API_DB_TYPE=q,exports.API_DB_USERNAME=N,exports.API_HTTP_CROSS=H,exports.API_HTTP_CRT=B,exports.API_HTTP_HYBRID=z,exports.API_HTTP_KEY=U,exports.API_HTTP_PORT=k,exports.API_HTTP_PUBLIC=L,exports.API_TOKEN_CRT=M,exports.API_TOKEN_HEADER=G,exports.API_TOKEN_KEY=C,exports.API_TOKEN_LIFETIME=K,exports.API_UPLOAD_COUNT=F,exports.API_UPLOAD_FIELD=Y,exports.API_UPLOAD_SIZE=W,exports.API_UPLOAD_TEMP=X,exports.API_WEBSOCKET_START=V,exports.Auth=Q,exports.Controller=he,exports.Group=ee,exports.GroupRoute=se,exports.Log=ae,exports.Logs=te,exports.Permission=pe,exports.Responses=de,exports.Route=re,exports.User=oe,exports.UserGroup=ne,exports.app=st,exports.auth=me,exports.crt=le,exports.initialize=()=>{Z.sync().then((()=>{$(void 0,void 0,void 0,(function*(){if(0==(yield oe.count())){const t=yield oe.create({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",description:"",state:!0});if(0==(yield ee.count())){const r=yield ee.create({name:"admin",description:"",state:!0});if(yield ne.create({userId:t.id,groupId:r.id}),0==(yield re.count())){const t=["read","write"],s=["users","groups","permission"];e.forEachSeries(s,(s=>$(void 0,void 0,void 0,(function*(){e.forEachSeries(t,(e=>$(void 0,void 0,void 0,(function*(){const t=s.toLowerCase()+"."+e.toLowerCase(),o=yield re.create({name:t,description:"",state:!0});yield se.create({groupId:r.id,routeId:o.id})}))))}))))}}}})),V&&ot(it)}))},exports.key=ce,exports.permission=xe,exports.router=rt,exports.sequelize=Z,exports.server=it,exports.startSocket=ot,exports.upload=e=>{const t=(null==e?void 0:e.path)||X,r=x.default.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>$(void 0,void 0,void 0,(function*(){return s(null,at(t,S.default.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||W),o=x.default({storage:r,fileFilter(t,r,s){var o;return $(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.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)||F,i=(null==e?void 0:e.field)||Y,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?de.error(t,e.message):r()}))}},exports.uuid=J,exports.validation=ge;
|
|
6
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@andrewcaires/utils.js"),t=require("dotenv"),r=require("sequelize"),s=require("cors"),o=require("express"),n=require("fs"),i=require("crypto-js"),a=require("jsonwebtoken"),d=require("joi"),u=require("http"),l=require("https"),c=require("net"),p=require("ws"),f=require("mime-types"),m=require("multer"),g=require("path");function v(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function y(e){if(e&&e.__esModule)return 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 h=v(s),I=v(o),T=v(a),w=v(d),_=y(u),A=y(l),P=v(p),S=v(f),b=v(m);t.config();const O=parseInt(process.env.API_AUTH_SLEEP||"1000"),x=process.env.API_DB_DATABASE||"",E=process.env.API_DB_HOST||"127.0.0.1",D=process.env.API_DB_PASSWORD||"",R=parseInt(process.env.API_DB_PORT||"3306"),q=process.env.API_DB_TYPE||"",N=process.env.API_DB_USERNAME||"root",j=e.toBool(process.env.API_DB_LOG||"false"),B=process.env.API_HTTP_CRT||"",k=process.env.API_HTTP_KEY||"",U=parseInt(process.env.API_HTTP_PORT||"3000"),L=process.env.API_HTTP_PUBLIC||"",H=e.toBool(process.env.API_HTTP_CROSS||"false"),z=e.toBool(process.env.API_HTTP_HYBRID||"false"),C=process.env.API_TOKEN_CRT||"",M=process.env.API_TOKEN_KEY||"",G=process.env.API_TOKEN_HEADER||"authorization",K=parseInt(process.env.API_TOKEN_LIFETIME||"15"),F=parseInt(process.env.API_UPLOAD_COUNT||"1"),Y=process.env.API_UPLOAD_FIELD||"upload",W=parseInt(process.env.API_UPLOAD_SIZE||"2"),X=process.env.API_UPLOAD_TEMP||"./temp",$=e.toBool(process.env.API_WEBSOCKET_START||"false");function V(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())}))}const J={type:r.UUID,defaultValue:r.UUIDV4,allowNull:!1,primaryKey:!0},Z=(()=>{switch(q){case"mariadb":return new r.Sequelize(x,N,D,{host:E,port:R,dialect:"mariadb",logging:j,define:{timestamps:!1}});case"mysql":return new r.Sequelize(x,N,D,{host:E,port:R,dialect:"mysql",logging:j,define:{timestamps:!1}});case"postgres":return new r.Sequelize(x,N,D,{host:E,port:R,dialect:"postgres",logging:j,define:{timestamps:!1}})}throw new Error("No database selected")})();class Q extends r.Model{}Q.init({login:r.DataTypes.BIGINT,logout:r.DataTypes.BIGINT,secret:r.DataTypes.STRING,timestamp:r.DataTypes.BIGINT,useragent:r.DataTypes.STRING},{sequelize:Z,modelName:"auth"});class ee extends r.Model{}ee.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"group"});class te extends r.Model{}te.init({type:r.DataTypes.STRING,source:r.DataTypes.STRING,message:r.DataTypes.TEXT},{sequelize:Z,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class re extends r.Model{}re.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"route"});class se extends r.Model{}se.init({},{sequelize:Z,modelName:"groups_routes"}),se.removeAttribute("id");class oe extends r.Model{}oe.init({name:r.DataTypes.STRING,email:r.DataTypes.STRING,username:r.DataTypes.STRING,password:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"user"});class ne extends r.Model{}ne.init({},{sequelize:Z,modelName:"users_groups"}),ne.removeAttribute("id"),oe.hasMany(Q),Q.belongsTo(oe),ee.hasMany(se),se.belongsTo(ee),re.hasMany(se),se.belongsTo(re),oe.hasMany(ne),ne.belongsTo(oe),ee.hasMany(ne),ne.belongsTo(ee);var ie;!function(e){e.ERROR="[31m",e.INFO="[36m",e.NONE="[37m",e.SUCCESS="[32m",e.WARNING="[33m"}(ie||(ie={}));class ae{static write(e,t){ae.writeRaw(ie.NONE,"",e,t)}static error(e,t){ae.writeRaw(ie.ERROR,"error",e,t)}static info(e,t){ae.writeRaw(ie.INFO,"info",e,t)}static success(e,t){ae.writeRaw(ie.ERROR,"success",e,t)}static warning(e,t){ae.writeRaw(ie.WARNING,"warning",e,t)}static writeConsole(t,r,s){const o=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"[37m","|",o,"|",s)}static writeRaw(e,t,r,s){ae.writeConsole(e,t,r),te.create({type:t,source:s,message:r}).catch((()=>null))}}class de{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,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}const ue=e=>{if(n.existsSync(e))return n.readFileSync(e)},le={http:ue(B),token:ue(C)},ce={http:ue(k),token:ue(M)};class pe{static all(e,t){return V(this,void 0,void 0,(function*(){return yield re.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:se,required:!0,include:[{model:ee,required:!0,where:{state:!0},include:[{model:ne,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ae.error(e.message,"permission")}))}))}static get(e){return V(this,void 0,void 0,(function*(){const t=yield pe.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return V(this,void 0,void 0,(function*(){const r=yield pe.all(e,{name:t});return r&&!!r.length}))}}const fe=["id","name","email","username"],me=(e,t,r)=>V(void 0,void 0,void 0,(function*(){const s=e.get(G)||"";if(!le.token)return de.error(t,"Invalid Secret");if(!s||s.split(".").length<3)return de.error(t,"Invalid token");let o;try{o=T.default.verify(s,le.token)}catch(e){return de.error(t,"Invalid token")}if(o&&o.id&&o.secret){const s=yield oe.findOne({where:{id:o.id}}).catch((e=>{ae.error(e.message,"token.check")}));if(s&&s.state){const n=yield Q.findOne({where:{logout:null,secret:o.secret,userId:s.id}}).catch((e=>{ae.error(e.message,"token.check")}));if(n){const o=Date.now();if(o>n.timestamp)return de.error(t,"Expired token");n.timestamp=o+6e4*K;const i=e.get("User-Agent");return i&&(n.useragent=i),yield n.save(),e.auth=n,e.user=s,r()}}return de.error(t,"Access denied")}return de.error(t,"Invalid token")})),ge=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),de.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},ve={username:w.default.string().min(5).required(),password:w.default.string().min(5).required()},ye=ge(w.default.object(ve)),he=o.Router();he.get("/",me,((t,r)=>V(void 0,void 0,void 0,(function*(){const s=t.user;if(!s)return de.unauthorized(r,"Access denied");const o=yield pe.all(s);if(o){const t=e.allowedObject(fe,s.toJSON()),n=o.map((e=>e.name));return de.data(r,Object.assign(Object.assign({},t),{permissions:n}))}return de.error(r,"Internal Server Error")})))),he.post("/login",ye,((t,r)=>V(void 0,void 0,void 0,(function*(){const{username:s,password:o}=t.body;if(!s||!o)return de.error(r,"Invalid parameters");yield e.sleep(O);const n=yield oe.findOne({where:{username:s}}).catch((e=>{ae.error(e.message,"auth.login")}));if(!n)return de.notfound(r,"User not found");if(!n.state)return de.error(r,"User is disabled");const a=i.SHA256(o).toString();if(n.password!=a)return de.error(r,"Invalid password");if(!ce.token)return de.error(r,"Invalid Secret");const d=n.id,u=e.uniqueID(),l=T.default.sign({id:d,secret:u},ce.token,{algorithm:"RS256"});if(l){const e=Date.now(),s=e+6e4*K,o=t.get("User-Agent");if(yield Q.create({login:e,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{ae.error(e.message,"auth.login")})))return de.data(r,{token:l})}return de.error(r,"Internal Server Error")})))),he.get("/logout",me,((e,t)=>V(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),de.success(t,"Disconcerted")):de.unauthorized(t,"Access denied")}))));class Ie{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>V(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{ae.error(e.message,this.log+".add")}));return r?de.data(t,{id:r.id}):de.error(t,"Internal Server Error")}))}all(t,s){return(o,n)=>V(this,void 0,void 0,(function*(){var i,a,d,u,l;t||(t={});const c=Object.assign({},t);c.where=c.where?Object.assign({},c.where):{};const p=null===(i=o.query.limit)||void 0===i?void 0:i.toString();p&&(c.limit=parseInt(p));const f=null===(a=o.query.offset)||void 0===a?void 0:a.toString();f&&(c.offset=parseInt(f));const m=null===(d=o.query.asc)||void 0===d?void 0:d.toString();m&&(c.order=[[m,"ASC"]]);const g=null===(u=o.query.desc)||void 0===u?void 0:u.toString();g&&(c.order=[[g,"DESC"]]);const v=[],y=null===(l=o.query.search)||void 0===l?void 0:l.toString();y&&(Object.keys(this.model.getAttributes()).forEach((e=>{v.push({[e]:{[r.Op.like]:`%${y}%`}})})),v.length&&(c.where=Object.assign(Object.assign({},c.where),{[r.Op.or]:[...v]})));const h=yield this.model.findAll(c).catch((e=>{ae.error(e.message,this.log+".all")})),I=yield this.model.count(c).catch(e.noop);return h?de.data(n,{count:I,records:s?s(h):h}):de.error(n,"Internal Server Error")}))}del(){return(e,t)=>V(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{ae.error(e.message,this.log+".del")})))?de.success(t,"OK"):de.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>V(this,void 0,void 0,(function*(){e||(e={});const o=Object.assign({},e);o.where=o.where?Object.assign({},o.where):{};const{id:n}=r.params,i=yield this.model.findByPk(n,o).catch((e=>{ae.error(e.message,this.log+".get")}));return i?de.data(s,t?t(i):i.toJSON()):null===i?de.notfound(s,"Record not found"):de.error(s,"Internal Server Error")}))}set(){return(e,t)=>V(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{ae.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return de.success(t,"OK")}return de.success(t,"Record not changed")}))}}const Te=new Ie("groups",ee),we=new Ie("groups.route",se),_e=Te.add(),Ae=Te.all(),Pe=Te.del(),Se=Te.get(),be=Te.set(),Oe=e=>(t,r,s)=>V(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield pe.is(o,e))?s():de.error(r,"Unauthorized access"):de.unauthorized(r,"Access denied")})),xe={name:w.default.string().min(3).required(),description:w.default.string().allow(null,""),state:w.default.boolean().required()},Ee=ge(w.default.object(xe)),De={routes:w.default.array().items(w.default.number())},Re=ge(w.default.object(De)),qe={name:w.default.string().min(3).empty(""),description:w.default.string().allow(null,""),state:w.default.boolean().empty("")},Ne=ge(w.default.object(qe)),je=o.Router();je.use(me),je.get("/",Oe("groups.read"),Ae),je.post("/",Oe("groups.write"),Ee,_e),je.route("/:id").get(Oe("groups.read"),Se).put(Oe("groups.write"),Ne,be).delete(Oe("groups.write"),Pe),je.route("/:id/routes").get(Oe("groups.read"),Re,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return we.all({where:{groupId:r},include:[{model:re,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(Oe("groups.write"),Re,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield ee.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield se.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield re.count({where:{id:s[r]}}),t&&(yield se.create({groupId:e,routeId:s[r]}))}return de.success(t,"OK")}return null===o?de.notfound(t,"Record not found"):de.error(t,"Internal Server Error")}))));const Be=new Ie("route",re),ke=Be.add(),Ue=Be.all(),Le=Be.del(),He=Be.get(),ze=Be.set(),Ce={name:w.default.string().min(5).required(),permission:w.default.string().required(),description:w.default.string().allow(null,""),state:w.default.boolean().required()},Me=ge(w.default.object(Ce)),Ge={name:w.default.string().min(5).empty(""),permission:w.default.string().empty(""),description:w.default.string().allow(null,""),state:w.default.boolean().empty("")},Ke=ge(w.default.object(Ge)),Fe=o.Router();Fe.use(me),Fe.get("/",Oe("routes.read"),Ue),Fe.post("/",Oe("routes.write"),Me,ke),Fe.route("/:id").get(Oe("routes.read"),He).put(Oe("routes.write"),Ke,ze).delete(Oe("routes.write"),Le);const Ye=new Ie("user",oe),We=new Ie("user.groups",ne),Xe=["id","name","email","username","description","state"],$e=Ye.del(),Ve={name:w.default.string().min(5).required(),email:w.default.string().email().required(),username:w.default.string().min(5).required(),password:w.default.string().min(5).required(),description:w.default.string().allow(null,""),state:w.default.boolean().required()},Je=ge(w.default.object(Ve)),Ze={groups:w.default.array().items(w.default.number())},Qe=ge(w.default.object(Ze)),et={name:w.default.string().min(5).empty(""),email:w.default.string().email().empty(""),username:w.default.string().min(5).empty(""),password:w.default.string().min(5).empty(""),description:w.default.string().allow(null,""),state:w.default.boolean().empty("")},tt=ge(w.default.object(et)),rt=o.Router();rt.use(me),rt.get("/",Oe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){return Ye.all({attributes:Xe})(e,t)})))),rt.post("/",Oe("users.write"),Je,((e,t)=>V(void 0,void 0,void 0,(function*(){return e.body.password=i.SHA256(e.body.password).toString(),yield Ye.add()(e,t)})))),rt.route("/:id").get(Oe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){return Ye.get({attributes:Xe})(e,t)})))).put(Oe("users.write"),tt,((e,t)=>V(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=i.SHA256(e.body.password).toString()),Ye.set()(e,t)})))).delete(Oe("users.write"),$e),rt.route("/:id/groups").get(Oe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return We.all({where:{userId:r},include:[{model:ee,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Oe("users.write"),Qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield oe.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"user.groups.set")}));if(o){if(yield ne.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield ee.count({where:{id:s[t]}}),e&&(yield ne.create({userId:o.id,groupId:s[t]}))}return de.success(t,"OK")}return de.notfound(t,"Record not found")}))));const st=o.Router();st.use("/v1/auth",he),st.use("/v1/groups",je),st.use("/v1/routes",Fe),st.use("/v1/users",rt);const ot=I.default();ot.use(I.default.json()),ot.use(((e,t,r,s)=>e?(ae.error(e.message,"express"),de.error(r,"Internal Server Error")):s())),ot.use(I.default.urlencoded({extended:!0})),ot.disable("x-powered-by"),H&&ot.use(h.default()),ot.use("/api",st),ot.all("/api/*",((e,t)=>de.notfound(t,"Invalid API"))),L&&(n.existsSync(L)&&ot.use(I.default.static(L)),ot.get("*",((e,t)=>{if(!n.existsSync(L))return de.notfound(t,'File "index.html" not found');t.sendFile(L+"/index.html")})));const nt=e=>{const t=new P.default.Server({server:e,verifyClient:it});return t.on("connection",(e=>{e.on("message",(t=>{e.close()})),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},it=(e,t)=>t($),at=(e=>{if(!le.http||!ce.http){const t=_.createServer(e);return t.listen(U,(()=>ae.info(`Server started on port ${U}`))),t}const t=_.createServer(((e,t)=>{const r=80==U?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=A.createServer({key:ce.http,cert:le.http},e);if(z){return new c.Server((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(U,(()=>ae.info(`Server started on port ${U}`))),r}return 443==U&&t.listen(80,(()=>ae.info("Server started on port 80"))),r.listen(U,(()=>ae.info(`Server started on port ${U}`))),r})(ot),dt=(t,r)=>{const s=e.uuidv4()+"."+r;return n.existsSync(g.join(t,s))?dt(t,r):s};exports.API_AUTH_SLEEP=O,exports.API_DB_DATABASE=x,exports.API_DB_HOST=E,exports.API_DB_LOG=j,exports.API_DB_PASSWORD=D,exports.API_DB_PORT=R,exports.API_DB_TYPE=q,exports.API_DB_USERNAME=N,exports.API_HTTP_CROSS=H,exports.API_HTTP_CRT=B,exports.API_HTTP_HYBRID=z,exports.API_HTTP_KEY=k,exports.API_HTTP_PORT=U,exports.API_HTTP_PUBLIC=L,exports.API_TOKEN_CRT=C,exports.API_TOKEN_HEADER=G,exports.API_TOKEN_KEY=M,exports.API_TOKEN_LIFETIME=K,exports.API_UPLOAD_COUNT=F,exports.API_UPLOAD_FIELD=Y,exports.API_UPLOAD_SIZE=W,exports.API_UPLOAD_TEMP=X,exports.API_WEBSOCKET_START=$,exports.Auth=Q,exports.Controller=Ie,exports.Group=ee,exports.GroupRoute=se,exports.Log=ae,exports.Logs=te,exports.Permission=pe,exports.Responses=de,exports.Route=re,exports.User=oe,exports.UserGroup=ne,exports.app=ot,exports.auth=me,exports.crt=le,exports.initialize=()=>{Z.sync().then((()=>{V(void 0,void 0,void 0,(function*(){if(0==(yield oe.count())){const t=yield oe.create({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",description:"",state:!0});if(0==(yield ee.count())){const r=yield ee.create({name:"admin",description:"",state:!0});if(yield ne.create({userId:t.id,groupId:r.id}),0==(yield re.count())){const t=["read","write"],s=["users","groups","permission"];e.forEachSeries(s,(s=>V(void 0,void 0,void 0,(function*(){e.forEachSeries(t,(e=>V(void 0,void 0,void 0,(function*(){const t=s.toLowerCase()+"."+e.toLowerCase(),o=yield re.create({name:t,description:"",state:!0});yield se.create({groupId:r.id,routeId:o.id})}))))}))))}}}})),$&&nt(at)}))},exports.key=ce,exports.permission=Oe,exports.router=st,exports.sequelize=Z,exports.server=at,exports.startSocket=nt,exports.upload=e=>{const t=(null==e?void 0:e.path)||X,r=b.default.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>V(void 0,void 0,void 0,(function*(){return s(null,dt(t,S.default.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||W),o=b.default({storage:r,fileFilter(t,r,s){var o;return V(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.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)||F,i=(null==e?void 0:e.field)||Y,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?de.error(t,e.message):r()}))}},exports.uuid=J,exports.validation=ge;
|
package/package.json
CHANGED