@andrewcaires/api 1.0.1 → 1.0.2
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 +2 -2
- package/dist/index.umd.js +2 -2
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @andrewcaires/api v1.0.
|
|
2
|
+
* @andrewcaires/api v1.0.2
|
|
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,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};
|
|
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 w,readFileSync as y}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(w(e))return y(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")})),we=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()}},ye={username:S.string().min(5).required(),password:S.string().min(5).required()},Ie=we(S.object(ye)),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 w=yield this.model.findAll(c).catch((e=>{ce.error(e.message,this.log+".all")})),y=yield this.model.count(c).catch(i);return w?le.data(s,{count:y,records:t?t(w):w}):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=we(S.object(je)),ke={routes:S.array().items(S.number())},De=we(S.object(ke)),xe={name:S.string().min(3).empty(""),description:S.string().allow(null,""),state:S.boolean().empty("")},Be=we(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(),description:S.string().allow(null,""),state:S.boolean().required()},Fe=we(S.object(Me)),We={name:S.string().min(5).empty(""),description:S.string().allow(null,""),state:S.boolean().empty("")},Xe=we(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=we(S.object(Qe)),tt={groups:S.array().items(S.number())},rt=we(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=we(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&&(w(L)&&at.use(f.static(L)),at.get("*",((e,t)=>{if(!w(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 w(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,we as validation};
|
package/dist/index.umd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @andrewcaires/api v1.0.
|
|
2
|
+
* @andrewcaires/api v1.0.2
|
|
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 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;
|
|
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(),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(""),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