@andrewcaires/api 1.0.3 → 1.0.6

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.d.ts CHANGED
@@ -1,22 +1,21 @@
1
1
  /*!
2
- * @andrewcaires/api v1.0.3
2
+ * @andrewcaires/api v1.0.5
3
+ * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
3
4
  * (c) 2022 Andrew Caires
4
5
  * @license: MIT
5
6
  */
6
- /// <reference types="node" />
7
- import * as https from 'https';
8
- import * as http from 'http';
9
7
  import * as _sequelize from 'sequelize';
10
8
  import { Model, Sequelize, ModelStatic, FindOptions, Attributes } from 'sequelize';
11
9
  import * as express_serve_static_core from 'express-serve-static-core';
12
- import { Request, Response, NextFunction } from 'express';
10
+ import { Express, Request, Response, NextFunction } from 'express';
13
11
  import { ObjectSchema } from 'joi';
12
+ import { TypeObjectString, TypeObject } from '@andrewcaires/utils.js';
14
13
  import { WhereOptions } from 'sequelize/types';
15
- import { TypeObject } from '@andrewcaires/utils.js';
14
+ import * as http from 'http';
15
+ import * as https from 'https';
16
16
  import WebSocket from 'ws';
17
17
 
18
- declare const initialize: () => void;
19
- declare const server: http.Server | https.Server;
18
+ declare const initialize: () => Promise<void>;
20
19
 
21
20
  declare const API_AUTH_SLEEP: number;
22
21
  declare const API_DB_DATABASE: string;
@@ -94,14 +93,19 @@ declare class Auth extends Model {
94
93
  user: User;
95
94
  }
96
95
 
96
+ declare class Configs extends Model {
97
+ key: string;
98
+ value: string;
99
+ }
100
+
97
101
  declare class Logs extends Model {
98
102
  type: string;
99
103
  source: string;
100
104
  message: string;
101
105
  }
102
106
 
103
- declare const app: express_serve_static_core.Express;
104
107
  declare const router: express_serve_static_core.Router;
108
+ declare const useExpress: () => Express;
105
109
 
106
110
  declare global {
107
111
  namespace Express {
@@ -143,12 +147,18 @@ declare const key: {
143
147
  token: Buffer | undefined;
144
148
  };
145
149
 
150
+ declare class Config {
151
+ static all(): Promise<TypeObjectString>;
152
+ static del(key: string): Promise<boolean>;
153
+ static get(key: string): Promise<string>;
154
+ static set(key: string, value: string): Promise<void>;
155
+ }
156
+
146
157
  declare type FnRecord<M> = (records: M) => any;
147
158
  declare type FnRecords<M> = (records: Array<M>) => Array<any>;
148
159
  declare class Controller<M extends Model<M>> {
149
- private log;
150
160
  private model;
151
- constructor(log: string, model: ModelStatic<M>);
161
+ constructor(model: ModelStatic<M>);
152
162
  add(): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
153
163
  all(options?: FindOptions<Attributes<M>>, fn?: FnRecords<M>): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
154
164
  del(): (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
@@ -157,11 +167,11 @@ declare class Controller<M extends Model<M>> {
157
167
  }
158
168
 
159
169
  declare class Log {
160
- static write(message: string, source?: string, console?: boolean): void;
161
- static error(message: string, source?: string, console?: boolean): void;
162
- static info(message: string, source?: string, console?: boolean): void;
163
- static success(message: string, source?: string, console?: boolean): void;
164
- static warning(message: string, source?: string, console?: boolean): void;
170
+ static write(message: string, source?: string, console?: boolean): Promise<void>;
171
+ static error(message: string, source?: string, console?: boolean): Promise<void>;
172
+ static info(message: string, source?: string, console?: boolean): Promise<void>;
173
+ static success(message: string, source?: string, console?: boolean): Promise<void>;
174
+ static warning(message: string, source?: string, console?: boolean): Promise<void>;
165
175
  private static writeConsole;
166
176
  private static writeRaw;
167
177
  }
@@ -197,4 +207,4 @@ declare class Token {
197
207
 
198
208
  declare const startSocket: (server: http.Server | https.Server) => WebSocket.Server;
199
209
 
200
- export { API_AUTH_SLEEP, API_DB_DATABASE, API_DB_HOST, API_DB_LOG, API_DB_PASSWORD, API_DB_PORT, API_DB_TYPE, API_DB_USERNAME, API_HTTP_CROSS, API_HTTP_CRT, API_HTTP_HYBRID, API_HTTP_KEY, API_HTTP_PORT, API_HTTP_PUBLIC, API_TOKEN_CRT, API_TOKEN_HEADER, API_TOKEN_KEY, API_TOKEN_LIFETIME, API_UPLOAD_COUNT, API_UPLOAD_FIELD, API_UPLOAD_SIZE, API_UPLOAD_TEMP, API_WEBSOCKET_START, Auth, Controller, Group, GroupRoute, Log, Logs, Permission, Responses, Route, Token, User, UserGroup, app, auth, crt, initialize, key, permission, router, sequelize, server, startSocket, upload, uuid, validation };
210
+ export { API_AUTH_SLEEP, API_DB_DATABASE, API_DB_HOST, API_DB_LOG, API_DB_PASSWORD, API_DB_PORT, API_DB_TYPE, API_DB_USERNAME, API_HTTP_CROSS, API_HTTP_CRT, API_HTTP_HYBRID, API_HTTP_KEY, API_HTTP_PORT, API_HTTP_PUBLIC, API_TOKEN_CRT, API_TOKEN_HEADER, API_TOKEN_KEY, API_TOKEN_LIFETIME, API_UPLOAD_COUNT, API_UPLOAD_FIELD, API_UPLOAD_SIZE, API_UPLOAD_TEMP, API_WEBSOCKET_START, Auth, Config, Configs, Controller, Group, GroupRoute, Log, Logs, Permission, Responses, Route, Token, User, UserGroup, auth, crt, initialize, key, permission, router, sequelize, startSocket, upload, useExpress, uuid, validation };
package/dist/index.esm.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /*!
2
- * @andrewcaires/api v1.0.3
2
+ * @andrewcaires/api v1.0.5
3
+ * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
3
4
  * (c) 2022 Andrew Caires
4
5
  * @license: MIT
5
6
  */
6
- import{toBool as e,forEachSeries as t,dateFormat as r,isUndefined as s,noop as o,sleep as n,uniqueID as i,allowedObject as d,uuidv4 as a}from"@andrewcaires/utils.js";import{config as u}from"dotenv";import{Sequelize as c,UUID as l,UUIDV4 as m,DataTypes as p,Model as g,Op as v}from"sequelize";import f from"cors";import h,{Router as y}from"express";import{existsSync as w,readFileSync as I}from"fs";import{SHA256 as b}from"crypto-js";import{sign as S,verify as T}from"jsonwebtoken";import A from"mime-types";import O from"multer";import{join as E}from"path";import _ from"joi";import*as P from"http";import*as N from"https";import{Server as R}from"net";import j from"ws";u();const q=parseInt(process.env.API_AUTH_SLEEP||"1000"),k=process.env.API_DB_DATABASE||"",D=process.env.API_DB_HOST||"127.0.0.1",x=process.env.API_DB_PASSWORD||"",B=parseInt(process.env.API_DB_PORT||"3306"),z=process.env.API_DB_TYPE||"",G=process.env.API_DB_USERNAME||"root",U=e(process.env.API_DB_LOG||"false"),C=process.env.API_HTTP_CRT||"",L=process.env.API_HTTP_KEY||"",H=parseInt(process.env.API_HTTP_PORT||"3000"),K=process.env.API_HTTP_PUBLIC||"",M=e(process.env.API_HTTP_CROSS||"false"),F=e(process.env.API_HTTP_HYBRID||"false"),W=process.env.API_TOKEN_CRT||"",X=process.env.API_TOKEN_KEY||"",Y=process.env.API_TOKEN_HEADER||"authorization",$=parseInt(process.env.API_TOKEN_LIFETIME||"15"),J=parseInt(process.env.API_UPLOAD_COUNT||"1"),V=process.env.API_UPLOAD_FIELD||"upload",Z=parseInt(process.env.API_UPLOAD_SIZE||"2"),Q=process.env.API_UPLOAD_TEMP||"./temp",ee=e(process.env.API_WEBSOCKET_START||"false");function te(e,t,r,s){return new(r||(r=Promise))((function(o,n){function i(e){try{a(s.next(e))}catch(e){n(e)}}function d(e){try{a(s.throw(e))}catch(e){n(e)}}function a(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,d)}a((s=s.apply(e,t||[])).next())}))}const re={type:l,defaultValue:m,allowNull:!1,primaryKey:!0},se=(()=>{switch(z){case"mariadb":return new c(k,G,x,{host:D,port:B,dialect:"mariadb",logging:U,define:{timestamps:!1}});case"mysql":return new c(k,G,x,{host:D,port:B,dialect:"mysql",logging:U,define:{timestamps:!1}});case"postgres":return new c(k,G,x,{host:D,port:B,dialect:"postgres",logging:U,define:{timestamps:!1}})}throw new Error("No database selected")})();class oe extends g{}oe.init({login:p.BIGINT,logout:p.BIGINT,secret:p.STRING,timestamp:p.BIGINT,useragent:p.STRING},{sequelize:se,modelName:"auth"});class ne extends g{}ne.init({name:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:se,modelName:"group"});class ie extends g{}ie.init({type:p.STRING,source:p.STRING,message:p.TEXT},{sequelize:se,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class de extends g{}de.init({name:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:se,modelName:"route"});class ae extends g{}ae.init({},{sequelize:se,modelName:"groups_routes"}),ae.removeAttribute("id");class ue extends g{}ue.init({name:p.STRING,email:p.STRING,username:p.STRING,password:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:se,modelName:"user"});class ce extends g{}ce.init({},{sequelize:se,modelName:"users_groups"}),ce.removeAttribute("id"),ue.hasMany(oe),oe.belongsTo(ue),ne.hasMany(ae),ae.belongsTo(ne),de.hasMany(ae),ae.belongsTo(de),ue.hasMany(ce),ce.belongsTo(ue),ne.hasMany(ce),ce.belongsTo(ne);var le;!function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(le||(le={}));class me{static write(e,t,r){me.writeRaw(le.NONE,"",e,t,r)}static error(e,t,r){me.writeRaw(le.ERROR,"error",e,t,r)}static info(e,t,r){me.writeRaw(le.INFO,"info",e,t,r)}static success(e,t,r){me.writeRaw(le.ERROR,"success",e,t,r)}static warning(e,t,r){me.writeRaw(le.WARNING,"warning",e,t,r)}static writeConsole(e,t,s){const o=r(new Date,"%H:%M:%S");console.log(">",e,t+" ".repeat(10-t.length),"","|",o,"|",s)}static writeRaw(e,t,r,o,n){(n=!!s(n)||n)&&me.writeConsole(e,t,r),ie.create({type:t,source:o,message:r}).catch((()=>null))}}class pe{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})}}class ge{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>te(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{me.error(e.message,this.log+".add")}));return r?pe.data(t,{id:r.id}):pe.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>te(this,void 0,void 0,(function*(){var n,i,d,a,u;e||(e={});const c=Object.assign({},e);c.where=c.where?Object.assign({},c.where):{};const l=null===(n=r.query.limit)||void 0===n?void 0:n.toString();l&&(c.limit=parseInt(l));const m=null===(i=r.query.offset)||void 0===i?void 0:i.toString();m&&(c.offset=parseInt(m));const p=null===(d=r.query.asc)||void 0===d?void 0:d.toString();p&&(c.order=[[p,"ASC"]]);const g=null===(a=r.query.desc)||void 0===a?void 0:a.toString();g&&(c.order=[[g,"DESC"]]);const f=[],h=null===(u=r.query.search)||void 0===u?void 0:u.toString();h&&(Object.keys(this.model.getAttributes()).forEach((e=>{"password"!=e&&f.push({[e]:{[v.like]:`%${h}%`}})})),f.length&&(c.where=Object.assign(Object.assign({},c.where),{[v.or]:[...f]})));const y=yield this.model.findAll(c).catch((e=>{me.error(e.message,this.log+".all")})),w=yield this.model.count(c).catch(o);return y?pe.data(s,{count:w,records:t?t(y):y}):pe.error(s,"Internal Server Error")}))}del(){return(e,t)=>te(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{me.error(e.message,this.log+".del")})))?pe.success(t,"OK"):pe.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>te(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=>{me.error(e.message,this.log+".get")}));return i?pe.data(s,t?t(i):i.toJSON()):null===i?pe.notfound(s,"Record not found"):pe.error(s,"Internal Server Error")}))}set(){return(e,t)=>te(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{me.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return pe.success(t,"OK")}return pe.success(t,"Record not changed")}))}}class ve{static all(e,t){return te(this,void 0,void 0,(function*(){return yield de.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:ae,required:!0,include:[{model:ne,required:!0,where:{state:!0},include:[{model:ce,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{me.error(e.message,"permission")}))}))}static get(e){return te(this,void 0,void 0,(function*(){const t=yield ve.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return te(this,void 0,void 0,(function*(){const r=yield ve.all(e,{name:t});return r&&!!r.length}))}}const fe=e=>{if(w(e))return I(e)},he={http:fe(C),token:fe(W)},ye={http:fe(L),token:fe(X)};class we{static sign(e){return ye.token?{token:S(e,ye.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static verify(e){if(!he.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:T(e,he.token)}}catch(e){return{error:"Invalid Token"}}}}const Ie=["id","name","email","username"],be=(e,t,r)=>te(void 0,void 0,void 0,(function*(){const s=e.get(Y)||"",{error:o,decode:n}=we.verify(s);if(o)return pe.error(t,o);if(n){const{id:s,secret:o}=n;if(s&&n){const n=yield ue.findOne({where:{id:s,state:!0}}).catch((e=>{me.error(e.message,"token.check")}));if(n){const s=yield oe.findOne({where:{secret:o,userId:n.id}}).catch((e=>{me.error(e.message,"token.check")}));if(s){const o=Date.now();if(o>s.timestamp)return pe.error(t,"Expired token");s.timestamp=o+6e4*$;const i=e.get("User-Agent");return i&&(s.useragent=i),yield s.save(),e.auth=s,e.user=n,r()}}return pe.error(t,"Access denied")}}return pe.error(t,"Invalid token")})),Se=e=>(t,r,s)=>te(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield ve.is(o,e))?s():pe.error(r,"Unauthorized access"):pe.unauthorized(r,"Access denied")})),Te=(e,t)=>{const r=a()+"."+t;return w(E(e,r))?Te(e,t):r},Ae=e=>{const t=(null==e?void 0:e.path)||Q,r=O.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>te(void 0,void 0,void 0,(function*(){return s(null,Te(t,A.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||Z),o=O({storage:r,fileFilter(t,r,s){var o;return te(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)||J,i=(null==e?void 0:e.field)||V,d=o.array(i,n);return(e,t,r)=>{d(e,t,(function(e){return e?pe.error(t,e.message):r()}))}},Oe=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})})),pe.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},Ee={username:_.string().min(5).required(),password:_.string().min(5).required()},_e=Oe(_.object(Ee)),Pe=y();Pe.get("/",be,((e,t)=>te(void 0,void 0,void 0,(function*(){const r=e.user;if(!r)return pe.unauthorized(t,"Access denied");const s=yield ve.all(r);if(s){const e=d(Ie,r.toJSON()),o=s.map((e=>e.name));return pe.data(t,Object.assign(Object.assign({},e),{permissions:o}))}return pe.error(t,"Internal Server Error")})))),Pe.post("/login",_e,((e,t)=>te(void 0,void 0,void 0,(function*(){const{username:r,password:s}=e.body;if(!r||!s)return pe.error(t,"Invalid parameters");yield n(q);const o=yield ue.findOne({where:{username:r}}).catch((e=>{me.error(e.message,"auth.login")}));if(!o)return pe.notfound(t,"Username not found");if(!o.state)return pe.error(t,"Username is disabled");const d=b(s).toString();if(o.password!=d)return pe.error(t,"Invalid password");const a=o.id,u=i(),{error:c,token:l}=we.sign({id:a,secret:u});if(c)return pe.error(t,c);if(l){const r=Date.now(),s=r+6e4*$,o=e.get("User-Agent"),n=yield oe.create({login:r,secret:u,timestamp:s,useragent:o,userId:a}).catch((e=>{me.error(e.message,"auth.login")}));if(n)return pe.data(t,{token:l})}return pe.error(t,"Internal Server Error")})))),Pe.get("/logout",be,((e,t)=>te(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),pe.success(t,"Disconcerted")):pe.unauthorized(t,"Access denied")}))));const Ne=new ge("groups",ne),Re=new ge("groups.route",ae),je=Ne.add(),qe=Ne.all(),ke=Ne.del(),De=Ne.get(),xe=Ne.set(),Be={name:_.string().min(3).required(),description:_.string().allow(null,""),state:_.boolean().required()},ze=Oe(_.object(Be)),Ge={routes:_.array().items(_.number())},Ue=Oe(_.object(Ge)),Ce={name:_.string().min(3).empty(""),description:_.string().allow(null,""),state:_.boolean().empty("")},Le=Oe(_.object(Ce)),He=y();He.use(be),He.get("/",Se("groups.read"),qe),He.post("/",Se("groups.write"),ze,je),He.route("/:id").get(Se("groups.read"),De).put(Se("groups.write"),Le,xe).delete(Se("groups.write"),ke),He.route("/:id/routes").get(Se("groups.read"),Ue,((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Re.all({where:{groupId:r},include:[{model:de,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(Se("groups.write"),Ue,((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield ne.findByPk(r,{attributes:["id"]}).catch((e=>{me.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield ae.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield de.count({where:{id:s[r]}}),t&&(yield ae.create({groupId:e,routeId:s[r]}))}return pe.success(t,"OK")}return null===o?pe.notfound(t,"Record not found"):pe.error(t,"Internal Server Error")}))));const Ke=new ge("logs",ie),Me=y();Me.use(be),Me.get("/",Se("logs.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){const{source:r,type:s}=e.query,o=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return Ke.all({where:o,order:[["created","DESC"]]})(e,t)}))));const Fe=new ge("route",de),We=Fe.add(),Xe=Fe.all(),Ye=Fe.del(),$e=Fe.get(),Je=Fe.set(),Ve={name:_.string().min(5).required(),description:_.string().allow(null,""),state:_.boolean().required()},Ze=Oe(_.object(Ve)),Qe={name:_.string().min(5).empty(""),description:_.string().allow(null,""),state:_.boolean().empty("")},et=Oe(_.object(Qe)),tt=y();tt.use(be),tt.get("/",Se("routes.read"),Xe),tt.post("/",Se("routes.write"),Ze,We),tt.route("/:id").get(Se("routes.read"),$e).put(Se("routes.write"),et,Je).delete(Se("routes.write"),Ye);const rt=new ge("user",ue),st=new ge("user.groups",ce),ot=["id","name","email","username","description","state"],nt=rt.del(),it={name:_.string().min(5).required(),email:_.string().email().required(),username:_.string().min(5).required(),password:_.string().min(5).required(),description:_.string().allow(null,""),state:_.boolean().required()},dt=Oe(_.object(it)),at={groups:_.array().items(_.number())},ut=Oe(_.object(at)),ct={name:_.string().min(5).empty(""),email:_.string().email().empty(""),username:_.string().min(5).empty(""),password:_.string().min(5).empty(""),description:_.string().allow(null,""),state:_.boolean().empty("")},lt=Oe(_.object(ct)),mt=y();mt.use(be),mt.get("/",Se("users.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){return rt.all({attributes:ot})(e,t)})))),mt.post("/",Se("users.write"),dt,((e,t)=>te(void 0,void 0,void 0,(function*(){return e.body.password=b(e.body.password).toString(),yield rt.add()(e,t)})))),mt.route("/:id").get(Se("users.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){return rt.get({attributes:ot})(e,t)})))).put(Se("users.write"),lt,((e,t)=>te(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=b(e.body.password).toString()),rt.set()(e,t)})))).delete(Se("users.write"),nt),mt.route("/:id/groups").get(Se("users.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return st.all({where:{userId:r},include:[{model:ne,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Se("users.write"),ut,((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield ue.findByPk(r,{attributes:["id"]}).catch((e=>{me.error(e.message,"user.groups.set")}));if(o){if(yield ce.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield ne.count({where:{id:s[t]}}),e&&(yield ce.create({userId:o.id,groupId:s[t]}))}return pe.success(t,"OK")}return pe.notfound(t,"Record not found")}))));const pt=y();pt.use("/auth",Pe),pt.use("/groups",He),pt.use("/logs",Me),pt.use("/routes",tt),pt.use("/users",mt);const gt=h();gt.use(h.json()),gt.use(((e,t,r,s)=>e?(me.error(e.message,"express"),pe.error(r,"Internal Server Error")):s())),gt.use(h.urlencoded({extended:!0})),gt.disable("x-powered-by"),M&&gt.use(f());const vt=y();gt.use("/api",vt),gt.use("/api",pt),gt.all("/api/*",((e,t)=>pe.notfound(t,"Invalid API"))),K&&(w(K)&&gt.use(h.static(K)),gt.get("*",((e,t)=>{if(!w(K))return pe.notfound(t,'File "index.html" not found');t.sendFile(K+"/index.html")})));const ft=e=>{const t=new j.Server({server:e,verifyClient:ht});return t.on("connection",(e=>{e.on("message",(t=>te(void 0,void 0,void 0,(function*(){we.verify(t.toString()),e.close()})))),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},ht=(e,t)=>t(ee),yt=()=>{se.sync().then((()=>{te(void 0,void 0,void 0,(function*(){if(0==(yield ue.count())){const e={description:"",state:!0},r=yield ue.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"},e));if(0==(yield ne.count())){const s=yield ne.create(Object.assign({name:"admin"},e));if(yield ce.create({userId:r.id,groupId:s.id}),0==(yield de.count())){const r=["read","write"],o=["users","groups","permission"];yield t(o,(o=>te(void 0,void 0,void 0,(function*(){yield t(r,(t=>te(void 0,void 0,void 0,(function*(){const r=o+"."+t,n=yield de.create(Object.assign({name:r},e));yield ae.create({groupId:s.id,routeId:n.id})}))))}))));const n=yield de.create(Object.assign({name:"logs.read"},e));yield ae.create({groupId:s.id,routeId:n.id})}}}})),ee&&ft(wt)}))},wt=(e=>{if(!he.http||!ye.http){const t=P.createServer(e);return t.listen(H,(()=>me.info(`Server started on port ${H}`))),t}const t=P.createServer(((e,t)=>{const r=80==H?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=N.createServer({key:ye.http,cert:he.http},e);if(F){return new R((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(H,(()=>me.info(`Server started on port ${H}`))),r}return 443==H&&t.listen(80,(()=>me.info("Server started on port 80"))),r.listen(H,(()=>me.info(`Server started on port ${H}`))),r})(gt);export{q as API_AUTH_SLEEP,k as API_DB_DATABASE,D as API_DB_HOST,U as API_DB_LOG,x as API_DB_PASSWORD,B as API_DB_PORT,z as API_DB_TYPE,G as API_DB_USERNAME,M as API_HTTP_CROSS,C as API_HTTP_CRT,F as API_HTTP_HYBRID,L as API_HTTP_KEY,H as API_HTTP_PORT,K as API_HTTP_PUBLIC,W as API_TOKEN_CRT,Y as API_TOKEN_HEADER,X as API_TOKEN_KEY,$ as API_TOKEN_LIFETIME,J as API_UPLOAD_COUNT,V as API_UPLOAD_FIELD,Z as API_UPLOAD_SIZE,Q as API_UPLOAD_TEMP,ee as API_WEBSOCKET_START,oe as Auth,ge as Controller,ne as Group,ae as GroupRoute,me as Log,ie as Logs,ve as Permission,pe as Responses,de as Route,we as Token,ue as User,ce as UserGroup,gt as app,be as auth,he as crt,yt as initialize,ye as key,Se as permission,vt as router,se as sequelize,wt as server,ft as startSocket,Ae as upload,re as uuid,Oe as validation};
7
+ import{toBool as e,dateFormat as t,isArray as r,isString as o,noop as s,sleep as i,uniqueID as n,allowedObject as a,uuidv4 as d}from"@andrewcaires/utils.js";import{config as u}from"dotenv";import{UUID as c,UUIDV4 as l,Sequelize as m,DataTypes as p,Model as v,Op as g}from"sequelize";import*as f from"http";import*as h from"https";import{Server as y}from"net";import w from"cors";import I,{Router as b}from"express";import{existsSync as S,readFileSync as T}from"fs";import{SHA256 as A}from"crypto-js";import{sign as N,verify as O}from"jsonwebtoken";import E from"mime-types";import _ from"multer";import{join as P}from"path";import R from"joi";import q from"ws";function j(e,t,r,o){return new(r||(r=Promise))((function(s,i){function n(e){try{d(o.next(e))}catch(e){i(e)}}function a(e){try{d(o.throw(e))}catch(e){i(e)}}function d(e){var t;e.done?s(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(n,a)}d((o=o.apply(e,t||[])).next())}))}u();const k=parseInt(process.env.API_AUTH_SLEEP||"1000"),x=process.env.API_DB_DATABASE||"",D=process.env.API_DB_HOST||"127.0.0.1",B=process.env.API_DB_PASSWORD||"",G=parseInt(process.env.API_DB_PORT||"3306"),z=process.env.API_DB_TYPE||"",U=process.env.API_DB_USERNAME||"root",C=e(process.env.API_DB_LOG||"false"),L=process.env.API_HTTP_CRT||"",H=process.env.API_HTTP_KEY||"",K=parseInt(process.env.API_HTTP_PORT||"3000"),M=process.env.API_HTTP_PUBLIC||"",F=e(process.env.API_HTTP_CROSS||"false"),W=e(process.env.API_HTTP_HYBRID||"false"),X=process.env.API_TOKEN_CRT||"",Y=process.env.API_TOKEN_KEY||"",J=process.env.API_TOKEN_HEADER||"authorization",V=parseInt(process.env.API_TOKEN_LIFETIME||"15"),$=parseInt(process.env.API_UPLOAD_COUNT||"1"),Z=process.env.API_UPLOAD_FIELD||"upload",Q=parseInt(process.env.API_UPLOAD_SIZE||"2"),ee=process.env.API_UPLOAD_TEMP||"./temp",te=e(process.env.API_WEBSOCKET_START||"false"),re={type:c,defaultValue:l,allowNull:!1,primaryKey:!0},oe=(()=>{switch(z){case"mariadb":return new m(x,U,B,{host:D,port:G,dialect:"mariadb",logging:C,define:{timestamps:!1}});case"mysql":return new m(x,U,B,{host:D,port:G,dialect:"mysql",logging:C,define:{timestamps:!1}});case"postgres":return new m(x,U,B,{host:D,port:G,dialect:"postgres",logging:C,define:{timestamps:!1}})}throw new Error("No database selected")})();class se extends v{}se.init({login:p.BIGINT,logout:p.BIGINT,secret:p.STRING,timestamp:p.BIGINT,useragent:p.STRING},{sequelize:oe,modelName:"auth"});class ie extends v{}ie.init({name:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:oe,modelName:"group"});class ne extends v{}ne.init({name:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:oe,modelName:"route"});class ae extends v{}ae.init({},{sequelize:oe,modelName:"groups_routes"}),ae.removeAttribute("id");class de extends v{}de.init({name:p.STRING,email:p.STRING,username:p.STRING,password:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:oe,modelName:"user"});class ue extends v{}ue.init({},{sequelize:oe,modelName:"users_groups"}),ue.removeAttribute("id");class ce extends v{}ce.init({key:p.STRING,value:p.STRING},{sequelize:oe,modelName:"configs",timestamps:!0,createdAt:"created",updatedAt:"updated"}),ce.removeAttribute("id");class le extends v{}var me;le.init({type:p.STRING,source:p.STRING,message:p.TEXT},{sequelize:oe,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1}),de.hasMany(se),se.belongsTo(de),ie.hasMany(ae),ae.belongsTo(ie),ne.hasMany(ae),ae.belongsTo(ne),de.hasMany(ue),ue.belongsTo(de),ie.hasMany(ue),ue.belongsTo(ie),function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(me||(me={}));class pe{static write(e,t,r){return j(this,void 0,void 0,(function*(){yield pe.writeRaw(me.NONE,"",e,t,r)}))}static error(e,t,r){return j(this,void 0,void 0,(function*(){yield pe.writeRaw(me.ERROR,"error",e,t,r)}))}static info(e,t,r){return j(this,void 0,void 0,(function*(){yield pe.writeRaw(me.INFO,"info",e,t,r)}))}static success(e,t,r){return j(this,void 0,void 0,(function*(){yield pe.writeRaw(me.ERROR,"success",e,t,r)}))}static warning(e,t,r){return j(this,void 0,void 0,(function*(){yield pe.writeRaw(me.WARNING,"warning",e,t,r)}))}static writeConsole(e,r,o){const s=t(new Date,"%H:%M:%S");console.log(">",e,r+" ".repeat(10-r.length),"","|",s,"|",o)}static writeRaw(e,t,r,o,s){return j(this,void 0,void 0,(function*(){s&&pe.writeConsole(e,t,r),yield le.create({type:t,source:o,message:r}).catch((()=>null))}))}}class ve{static all(){return j(this,void 0,void 0,(function*(){const e=yield ce.findAll().catch((e=>{pe.error(e.message,"api.config",!0)})),t={};return e&&e.forEach((e=>{t[e.key]=e.value})),t}))}static del(e){return j(this,void 0,void 0,(function*(){return((yield ce.destroy({where:{key:e}}).catch((e=>{pe.error(e.message,"api.config",!0)})))||0)>0}))}static get(e){return j(this,void 0,void 0,(function*(){const t=yield ce.findOne({where:{key:e}}).catch((e=>{pe.error(e.message,"api.config",!0)}));return t&&t.value||""}))}static set(e,t){return j(this,void 0,void 0,(function*(){const[r]=(yield ce.findOrCreate({where:{key:e}}).catch((e=>{pe.error(e.message,"api.config",!0)})))||[];r&&(r.value=t,yield r.save().catch((e=>{pe.error(e.message,"api.config",!0)})))}))}}class ge{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})}}class fe{constructor(e){this.model=e}add(){return(e,t)=>j(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{pe.error(e.message,"api.controller."+this.model.tableName,!0)}));return r?ge.data(t,{id:r.id}):ge.error(t,"Internal Server Error")}))}all(e,t){return(i,n)=>j(this,void 0,void 0,(function*(){var a,d,u,c,l;const m=Object.assign({},e||{});m.where=Object.assign({},m.where||{});const p=null===(a=i.query.limit)||void 0===a?void 0:a.toString();p&&(m.limit=parseInt(p));const v=null===(d=i.query.offset)||void 0===d?void 0:d.toString();v&&(m.offset=parseInt(v));const f=Object.keys(this.model.getAttributes()),h=[],y=null===(u=i.query.asc)||void 0===u?void 0:u.toString();y&&y.length&&y.split(",").forEach((e=>{f.indexOf(e)>=0&&h.push([e,"ASC"])}));const w=null===(c=i.query.desc)||void 0===c?void 0:c.toString();w&&w.length&&w.split(",").forEach((e=>{f.indexOf(e)>=0&&h.push([e,"DESC"])})),h.length&&(m.order=h);const I=[],b=r(m.attributes)?m.attributes:f,S=null===(l=i.query.search)||void 0===l?void 0:l.toString();b.forEach((e=>{var t;if(o(e)&&(S&&S.length&&I.push({[e]:{[g.like]:`%${S}%`}}),"search_"+e in i.query)){const r=null===(t=i.query["search_"+e])||void 0===t?void 0:t.toString();r&&r.length&&I.push({[e]:{[g.like]:`%${r}%`}})}})),I.length&&(m.where=Object.assign(Object.assign({},m.where),{[g.or]:[...I]}));const T=yield this.model.findAll(m).catch((e=>{pe.error(e.message,"api.controller."+this.model.tableName,!0)})),A=yield this.model.count(m).catch(s);return T?ge.data(n,{count:A,records:t?t(T):T}):ge.error(n,"Internal Server Error")}))}del(){return(e,t)=>j(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{pe.error(e.message,"api.controller."+this.model.tableName,!0)})))?ge.success(t,"OK"):ge.notfound(t,"Record not found")}))}get(e,t){return(r,o)=>j(this,void 0,void 0,(function*(){e||(e={});const s=Object.assign({},e);s.where=s.where?Object.assign({},s.where):{};const{id:i}=r.params,n=yield this.model.findByPk(i,s).catch((e=>{pe.error(e.message,"api.controller."+this.model.tableName,!0)}));return n?ge.data(o,t?t(n):n.toJSON()):null===n?ge.notfound(o,"Record not found"):ge.error(o,"Internal Server Error")}))}set(){return(e,t)=>j(this,void 0,void 0,(function*(){const{id:r}=e.params,[o]=(yield this.model.update(e.body,{where:{id:r}}).catch((e=>{pe.error(e.message,"api.controller."+this.model.tableName,!0)})))||[];return o?ge.success(t,"OK"):ge.success(t,"Record not changed")}))}}class he{static all(e,t){return j(this,void 0,void 0,(function*(){return yield ne.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:ae,required:!0,include:[{model:ie,required:!0,where:{state:!0},include:[{model:ue,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{pe.error(e.message,"api.permission",!0)}))}))}static get(e){return j(this,void 0,void 0,(function*(){const t=yield he.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return j(this,void 0,void 0,(function*(){const r=yield he.all(e,{name:t});return r&&!!r.length}))}}const ye=e=>{if(S(e))return T(e)},we={http:ye(L),token:ye(X)},Ie={http:ye(H),token:ye(Y)};class be{static sign(e){return Ie.token?{token:N(e,Ie.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static verify(e){if(!we.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:O(e,we.token)}}catch(e){return{error:"Invalid Token"}}}}const Se=["id","name","email","username"],Te=(e,t,r)=>j(void 0,void 0,void 0,(function*(){const o=e.get(J)||"",{error:s,decode:i}=be.verify(o);if(s)return ge.error(t,s);if(i){const{id:o,secret:s}=i;if(o&&i){const i=yield de.findOne({where:{id:o,state:!0}}).catch((e=>{pe.error(e.message,"api.auth",!0)}));if(i){const o=yield se.findOne({where:{secret:s,userId:i.id}}).catch((e=>{pe.error(e.message,"api.auth",!0)}));if(o){const s=Date.now();if(s>o.timestamp)return ge.error(t,"Expired token");if(!o.logout){o.timestamp=s+6e4*V;const t=e.get("User-Agent");return t&&(o.useragent=t),yield o.save(),e.auth=o,e.user=i,r()}}}return ge.error(t,"Access denied")}}return ge.error(t,"Invalid token")})),Ae=e=>(t,r,o)=>j(void 0,void 0,void 0,(function*(){const s=t.user;return s?(yield he.is(s,e))?o():ge.error(r,"Unauthorized access"):ge.unauthorized(r,"Access denied")})),Ne=(e,t)=>{const r=d()+"."+t;return S(P(e,r))?Ne(e,t):r},Oe=e=>{const t=(null==e?void 0:e.path)||ee,r=_.diskStorage({destination:(e,r,o)=>o(null,t),filename:(e,r,o)=>j(void 0,void 0,void 0,(function*(){return o(null,Ne(t,E.extension(r.mimetype)||"bin"))}))}),o=1e6*((null==e?void 0:e.size)||Q),s=_({storage:r,fileFilter(t,r,o){var s;return j(this,void 0,void 0,(function*(){const t=null===(s=null==e?void 0:e.types)||void 0===s?void 0:s.indexOf(r.mimetype);return void 0!==t&&t<0?o(new Error("File type not allowed")):o(null,!0)}))},limits:{fileSize:o}}),i=(null==e?void 0:e.count)||$,n=(null==e?void 0:e.field)||Z,a=s.array(n,i);return(e,t,r)=>{a(e,t,(function(e){return e?ge.error(t,e.message):r()}))}},Ee=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,o,s)=>{const{error:i,value:n}=e.validate(r.body,t);if(i){const e=i.details.map((e=>e.message)).join(", "),t=[];return i.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),ge.validation(o,"Validation error: "+e,t)}return r.body=n,s()}},_e={username:R.string().min(5).required(),password:R.string().min(5).required()},Pe=Ee(R.object(_e)),Re=b();Re.get("/",Te,((e,t)=>j(void 0,void 0,void 0,(function*(){const r=e.user;if(!r)return ge.unauthorized(t,"Access denied");const o=yield he.all(r);if(o){const e=a(Se,r.toJSON()),s=o.map((e=>e.name));return ge.data(t,Object.assign(Object.assign({},e),{permissions:s}))}return ge.error(t,"Internal Server Error")})))),Re.post("/login",Pe,((e,t)=>j(void 0,void 0,void 0,(function*(){const{username:r,password:o}=e.body;if(!r||!o)return ge.error(t,"Invalid parameters");yield i(k);const s=yield de.findOne({where:{username:r}}).catch((e=>{pe.error(e.message,"api.controller."+de.tableName,!0)}));if(!s)return ge.notfound(t,"Username not found");if(!s.state)return ge.error(t,"Username is disabled");const a=A(o).toString();if(s.password!=a)return ge.error(t,"Invalid password");const d=s.id,u=n(),{error:c,token:l}=be.sign({id:d,secret:u});if(c)return ge.error(t,c);if(l){const r=Date.now(),o=r+6e4*V,s=e.get("User-Agent"),i=yield se.create({login:r,secret:u,timestamp:o,useragent:s,userId:d}).catch((e=>{pe.error(e.message,"api.controller."+se.tableName,!0)}));if(i)return ge.data(t,{token:l})}return ge.error(t,"Internal Server Error")})))),Re.get("/logout",Te,((e,t)=>j(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),ge.success(t,"Disconcerted")):ge.unauthorized(t,"Access denied")}))));const qe=new fe(ie),je=new fe(ae),ke=qe.add(),xe=qe.all(),De=qe.del(),Be=qe.get(),Ge=qe.set(),ze={name:R.string().min(3).required(),description:R.string().allow(null,""),state:R.boolean().required()},Ue=Ee(R.object(ze)),Ce={routes:R.array().items(R.number())},Le=Ee(R.object(Ce)),He={name:R.string().min(3).empty(""),description:R.string().allow(null,""),state:R.boolean().empty("")},Ke=Ee(R.object(He)),Me=b();Me.use(Te),Me.get("/",Ae("groups.read"),xe),Me.post("/",Ae("groups.write"),Ue,ke),Me.route("/:id").get(Ae("groups.read"),Be).put(Ae("groups.write"),Ke,Ge).delete(Ae("groups.write"),De),Me.route("/:id/routes").get(Ae("groups.read"),Le,((e,t)=>j(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return je.all({where:{groupId:r},include:[{model:ne,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(Ae("groups.write"),Le,((e,t)=>j(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:o}=e.body,s=yield ie.findByPk(r,{attributes:["id"]}).catch((e=>{pe.error(e.message,"api.controller."+ie.tableName,!0)}));if(s){const e=s.id;if(yield ae.destroy({where:{groupId:e}}),o){let t=0;for(let r=0;r<o.length;r++)t=yield ne.count({where:{id:o[r]}}),t&&(yield ae.create({groupId:e,routeId:o[r]}))}return ge.success(t,"OK")}return null===s?ge.notfound(t,"Record not found"):ge.error(t,"Internal Server Error")}))));const Fe=new fe(le),We=b();We.use(Te),We.get("/",Ae("logs.read"),((e,t)=>j(void 0,void 0,void 0,(function*(){const{source:r,type:o}=e.query,s=r&&o?{source:r,type:o}:r?{source:r}:o?{type:o}:{};return Fe.all({where:s,order:[["created","DESC"]]})(e,t)}))));const Xe=new fe(ne),Ye=Xe.add(),Je=Xe.all(),Ve=Xe.del(),$e=Xe.get(),Ze=Xe.set(),Qe={name:R.string().min(5).required(),description:R.string().allow(null,""),state:R.boolean().required()},et=Ee(R.object(Qe)),tt={name:R.string().min(5).empty(""),description:R.string().allow(null,""),state:R.boolean().empty("")},rt=Ee(R.object(tt)),ot=b();ot.use(Te),ot.get("/",Ae("routes.read"),Je),ot.post("/",Ae("routes.write"),et,Ye),ot.route("/:id").get(Ae("routes.read"),$e).put(Ae("routes.write"),rt,Ze).delete(Ae("routes.write"),Ve);const st=new fe(de),it=new fe(ue),nt=["id","name","email","username","description","state"],at=st.del(),dt={name:R.string().min(5).required(),email:R.string().email().required(),username:R.string().min(5).required(),password:R.string().min(5).required(),description:R.string().allow(null,""),state:R.boolean().required()},ut=Ee(R.object(dt)),ct={groups:R.array().items(R.number())},lt=Ee(R.object(ct)),mt={name:R.string().min(5).empty(""),email:R.string().email().empty(""),username:R.string().min(5).empty(""),password:R.string().min(5).empty(""),description:R.string().allow(null,""),state:R.boolean().empty("")},pt=Ee(R.object(mt)),vt=b();vt.use(Te),vt.get("/",Ae("users.read"),((e,t)=>j(void 0,void 0,void 0,(function*(){return st.all({attributes:nt})(e,t)})))),vt.post("/",Ae("users.write"),ut,((e,t)=>j(void 0,void 0,void 0,(function*(){return e.body.password=A(e.body.password).toString(),yield st.add()(e,t)})))),vt.route("/:id").get(Ae("users.read"),((e,t)=>j(void 0,void 0,void 0,(function*(){return st.get({attributes:nt})(e,t)})))).put(Ae("users.write"),pt,((e,t)=>j(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=A(e.body.password).toString()),st.set()(e,t)})))).delete(Ae("users.write"),at),vt.route("/:id/groups").get(Ae("users.read"),((e,t)=>j(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return it.all({where:{userId:r},include:[{model:ie,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Ae("users.write"),lt,((e,t)=>j(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:o}=e.body,s=yield de.findByPk(r,{attributes:["id"]}).catch((e=>{pe.error(e.message,"api.controller."+de.tableName,!0)}));if(s){if(yield ue.destroy({where:{userId:s.id}}),o){let e=0;for(let t=0;t<o.length;t++)e=yield ie.count({where:{id:o[t]}}),e&&(yield ue.create({userId:s.id,groupId:o[t]}))}return ge.success(t,"OK")}return ge.notfound(t,"Record not found")}))));const gt=b();let ft;gt.use("/auth",Re),gt.use("/groups",Me),gt.use("/logs",We),gt.use("/routes",ot),gt.use("/users",vt);const ht=b(),yt=()=>{var e;return ft||(ft=I(),(e=ft).use(I.json()),e.use(((e,t,r,o)=>e?(pe.error(e.message,"api.express",!0),ge.error(r,"Internal Server Error")):o())),e.use(I.urlencoded({extended:!0})),e.disable("x-powered-by"),F&&e.use(w()),e.use("/api",ht),e.use("/api",gt),e.all("/api/*",((e,t)=>ge.notfound(t,"Invalid API"))),M&&(S(M)&&e.use(I.static(M)),e.get("*",((e,t)=>{if(!S(M))return ge.notfound(t,'File "index.html" not found');t.sendFile(M+"/index.html")})))),ft};let wt;const It=()=>(wt||(wt=(e=>{if(!we.http||!Ie.http){const t=f.createServer(e);return t.listen(K,(()=>pe.info("Server started on port "+K,"api.server",!0))),t}const t=f.createServer(((e,t)=>{const r=80==K?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=h.createServer({key:Ie.http,cert:we.http},e);if(W)return new y((e=>{e.once("data",(o=>{e.pause(),e.unshift(o),(22===o[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(K,(()=>pe.info("Server started on port "+K,"api.server",!0))),r;return 443==K&&t.listen(80,(()=>pe.info("Server started on port 80","api.server",!0))),r.listen(K,(()=>pe.info("Server started on port "+K,"api.server",!0))),r})(yt())),wt),bt=e=>{const t=new q.Server({server:e,verifyClient:St});return t.on("connection",(e=>{e.on("message",(t=>j(void 0,void 0,void 0,(function*(){be.verify(t.toString()),e.close()})))),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},St=(e,t)=>t(te),Tt=()=>j(void 0,void 0,void 0,(function*(){yield oe.sync();const e=It();te&&bt(e)}));export{k as API_AUTH_SLEEP,x as API_DB_DATABASE,D as API_DB_HOST,C as API_DB_LOG,B as API_DB_PASSWORD,G as API_DB_PORT,z as API_DB_TYPE,U as API_DB_USERNAME,F as API_HTTP_CROSS,L as API_HTTP_CRT,W as API_HTTP_HYBRID,H as API_HTTP_KEY,K as API_HTTP_PORT,M as API_HTTP_PUBLIC,X as API_TOKEN_CRT,J as API_TOKEN_HEADER,Y as API_TOKEN_KEY,V as API_TOKEN_LIFETIME,$ as API_UPLOAD_COUNT,Z as API_UPLOAD_FIELD,Q as API_UPLOAD_SIZE,ee as API_UPLOAD_TEMP,te as API_WEBSOCKET_START,se as Auth,ve as Config,ce as Configs,fe as Controller,ie as Group,ae as GroupRoute,pe as Log,le as Logs,he as Permission,ge as Responses,ne as Route,be as Token,de as User,ue as UserGroup,Te as auth,we as crt,Tt as initialize,Ie as key,Ae as permission,ht as router,oe as sequelize,bt as startSocket,Oe as upload,yt as useExpress,re as uuid,Ee as validation};
package/dist/index.umd.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /*!
2
- * @andrewcaires/api v1.0.3
2
+ * @andrewcaires/api v1.0.5
3
+ * Simple api for small applications using express, jsonwebtoken, sequelize and websocket
3
4
  * (c) 2022 Andrew Caires
4
5
  * @license: MIT
5
6
  */
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("mime-types"),u=require("multer"),l=require("path"),c=require("joi"),p=require("http"),f=require("https"),m=require("net"),g=require("ws");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(d),w=v(u),_=v(c),A=y(p),P=y(f),S=v(g);t.config();const b=parseInt(process.env.API_AUTH_SLEEP||"1000"),O=process.env.API_DB_DATABASE||"",x=process.env.API_DB_HOST||"127.0.0.1",E=process.env.API_DB_PASSWORD||"",D=parseInt(process.env.API_DB_PORT||"3306"),R=process.env.API_DB_TYPE||"",q=process.env.API_DB_USERNAME||"root",N=e.toBool(process.env.API_DB_LOG||"false"),j=process.env.API_HTTP_CRT||"",B=process.env.API_HTTP_KEY||"",k=parseInt(process.env.API_HTTP_PORT||"3000"),U=process.env.API_HTTP_PUBLIC||"",H=e.toBool(process.env.API_HTTP_CROSS||"false"),L=e.toBool(process.env.API_HTTP_HYBRID||"false"),z=process.env.API_TOKEN_CRT||"",C=process.env.API_TOKEN_KEY||"",M=process.env.API_TOKEN_HEADER||"authorization",G=parseInt(process.env.API_TOKEN_LIFETIME||"15"),K=parseInt(process.env.API_UPLOAD_COUNT||"1"),F=process.env.API_UPLOAD_FIELD||"upload",Y=parseInt(process.env.API_UPLOAD_SIZE||"2"),W=process.env.API_UPLOAD_TEMP||"./temp",X=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 V={type:r.UUID,defaultValue:r.UUIDV4,allowNull:!1,primaryKey:!0},J=(()=>{switch(R){case"mariadb":return new r.Sequelize(O,q,E,{host:x,port:D,dialect:"mariadb",logging:N,define:{timestamps:!1}});case"mysql":return new r.Sequelize(O,q,E,{host:x,port:D,dialect:"mysql",logging:N,define:{timestamps:!1}});case"postgres":return new r.Sequelize(O,q,E,{host:x,port:D,dialect:"postgres",logging:N,define:{timestamps:!1}})}throw new Error("No database selected")})();class Z extends r.Model{}Z.init({login:r.DataTypes.BIGINT,logout:r.DataTypes.BIGINT,secret:r.DataTypes.STRING,timestamp:r.DataTypes.BIGINT,useragent:r.DataTypes.STRING},{sequelize:J,modelName:"auth"});class Q extends r.Model{}Q.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:J,modelName:"group"});class ee extends r.Model{}ee.init({type:r.DataTypes.STRING,source:r.DataTypes.STRING,message:r.DataTypes.TEXT},{sequelize:J,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class te extends r.Model{}te.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:J,modelName:"route"});class re extends r.Model{}re.init({},{sequelize:J,modelName:"groups_routes"}),re.removeAttribute("id");class se extends r.Model{}se.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:J,modelName:"user"});class oe extends r.Model{}oe.init({},{sequelize:J,modelName:"users_groups"}),oe.removeAttribute("id"),se.hasMany(Z),Z.belongsTo(se),Q.hasMany(re),re.belongsTo(Q),te.hasMany(re),re.belongsTo(te),se.hasMany(oe),oe.belongsTo(se),Q.hasMany(oe),oe.belongsTo(Q);var ne;!function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(ne||(ne={}));class ie{static write(e,t,r){ie.writeRaw(ne.NONE,"",e,t,r)}static error(e,t,r){ie.writeRaw(ne.ERROR,"error",e,t,r)}static info(e,t,r){ie.writeRaw(ne.INFO,"info",e,t,r)}static success(e,t,r){ie.writeRaw(ne.ERROR,"success",e,t,r)}static warning(e,t,r){ie.writeRaw(ne.WARNING,"warning",e,t,r)}static writeConsole(t,r,s){const o=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"","|",o,"|",s)}static writeRaw(t,r,s,o,n){(n=!!e.isUndefined(n)||n)&&ie.writeConsole(t,r,s),ee.create({type:r,source:o,message:s}).catch((()=>null))}}class ae{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}class de{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=>{ie.error(e.message,this.log+".add")}));return r?ae.data(t,{id:r.id}):ae.error(t,"Internal Server Error")}))}all(t,s){return(o,n)=>$(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=>{"password"!=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=>{ie.error(e.message,this.log+".all")})),I=yield this.model.count(c).catch(e.noop);return h?ae.data(n,{count:I,records:s?s(h):h}):ae.error(n,"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=>{ie.error(e.message,this.log+".del")})))?ae.success(t,"OK"):ae.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>$(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=>{ie.error(e.message,this.log+".get")}));return i?ae.data(s,t?t(i):i.toJSON()):null===i?ae.notfound(s,"Record not found"):ae.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=>{ie.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return ae.success(t,"OK")}return ae.success(t,"Record not changed")}))}}class ue{static all(e,t){return $(this,void 0,void 0,(function*(){return yield te.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:re,required:!0,include:[{model:Q,required:!0,where:{state:!0},include:[{model:oe,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ie.error(e.message,"permission")}))}))}static get(e){return $(this,void 0,void 0,(function*(){const t=yield ue.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return $(this,void 0,void 0,(function*(){const r=yield ue.all(e,{name:t});return r&&!!r.length}))}}const le=e=>{if(n.existsSync(e))return n.readFileSync(e)},ce={http:le(j),token:le(z)},pe={http:le(B),token:le(C)};class fe{static sign(e){return pe.token?{token:a.sign(e,pe.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static verify(e){if(!ce.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:a.verify(e,ce.token)}}catch(e){return{error:"Invalid Token"}}}}const me=["id","name","email","username"],ge=(e,t,r)=>$(void 0,void 0,void 0,(function*(){const s=e.get(M)||"",{error:o,decode:n}=fe.verify(s);if(o)return ae.error(t,o);if(n){const{id:s,secret:o}=n;if(s&&n){const n=yield se.findOne({where:{id:s,state:!0}}).catch((e=>{ie.error(e.message,"token.check")}));if(n){const s=yield Z.findOne({where:{secret:o,userId:n.id}}).catch((e=>{ie.error(e.message,"token.check")}));if(s){const o=Date.now();if(o>s.timestamp)return ae.error(t,"Expired token");s.timestamp=o+6e4*G;const i=e.get("User-Agent");return i&&(s.useragent=i),yield s.save(),e.auth=s,e.user=n,r()}}return ae.error(t,"Access denied")}}return ae.error(t,"Invalid token")})),ve=e=>(t,r,s)=>$(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield ue.is(o,e))?s():ae.error(r,"Unauthorized access"):ae.unauthorized(r,"Access denied")})),ye=(t,r)=>{const s=e.uuidv4()+"."+r;return n.existsSync(l.join(t,s))?ye(t,r):s},he=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})})),ae.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},Ie={username:_.default.string().min(5).required(),password:_.default.string().min(5).required()},Te=he(_.default.object(Ie)),we=o.Router();we.get("/",ge,((t,r)=>$(void 0,void 0,void 0,(function*(){const s=t.user;if(!s)return ae.unauthorized(r,"Access denied");const o=yield ue.all(s);if(o){const t=e.allowedObject(me,s.toJSON()),n=o.map((e=>e.name));return ae.data(r,Object.assign(Object.assign({},t),{permissions:n}))}return ae.error(r,"Internal Server Error")})))),we.post("/login",Te,((t,r)=>$(void 0,void 0,void 0,(function*(){const{username:s,password:o}=t.body;if(!s||!o)return ae.error(r,"Invalid parameters");yield e.sleep(b);const n=yield se.findOne({where:{username:s}}).catch((e=>{ie.error(e.message,"auth.login")}));if(!n)return ae.notfound(r,"Username not found");if(!n.state)return ae.error(r,"Username is disabled");const a=i.SHA256(o).toString();if(n.password!=a)return ae.error(r,"Invalid password");const d=n.id,u=e.uniqueID(),{error:l,token:c}=fe.sign({id:d,secret:u});if(l)return ae.error(r,l);if(c){const e=Date.now(),s=e+6e4*G,o=t.get("User-Agent"),n=yield Z.create({login:e,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{ie.error(e.message,"auth.login")}));if(n)return ae.data(r,{token:c})}return ae.error(r,"Internal Server Error")})))),we.get("/logout",ge,((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(),ae.success(t,"Disconcerted")):ae.unauthorized(t,"Access denied")}))));const _e=new de("groups",Q),Ae=new de("groups.route",re),Pe=_e.add(),Se=_e.all(),be=_e.del(),Oe=_e.get(),xe=_e.set(),Ee={name:_.default.string().min(3).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},De=he(_.default.object(Ee)),Re={routes:_.default.array().items(_.default.number())},qe=he(_.default.object(Re)),Ne={name:_.default.string().min(3).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},je=he(_.default.object(Ne)),Be=o.Router();Be.use(ge),Be.get("/",ve("groups.read"),Se),Be.post("/",ve("groups.write"),De,Pe),Be.route("/:id").get(ve("groups.read"),Oe).put(ve("groups.write"),je,xe).delete(ve("groups.write"),be),Be.route("/:id/routes").get(ve("groups.read"),qe,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ae.all({where:{groupId:r},include:[{model:te,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(ve("groups.write"),qe,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield Q.findByPk(r,{attributes:["id"]}).catch((e=>{ie.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield re.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield te.count({where:{id:s[r]}}),t&&(yield re.create({groupId:e,routeId:s[r]}))}return ae.success(t,"OK")}return null===o?ae.notfound(t,"Record not found"):ae.error(t,"Internal Server Error")}))));const ke=new de("logs",ee),Ue=o.Router();Ue.use(ge),Ue.get("/",ve("logs.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){const{source:r,type:s}=e.query,o=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return ke.all({where:o,order:[["created","DESC"]]})(e,t)}))));const He=new de("route",te),Le=He.add(),ze=He.all(),Ce=He.del(),Me=He.get(),Ge=He.set(),Ke={name:_.default.string().min(5).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},Fe=he(_.default.object(Ke)),Ye={name:_.default.string().min(5).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},We=he(_.default.object(Ye)),Xe=o.Router();Xe.use(ge),Xe.get("/",ve("routes.read"),ze),Xe.post("/",ve("routes.write"),Fe,Le),Xe.route("/:id").get(ve("routes.read"),Me).put(ve("routes.write"),We,Ge).delete(ve("routes.write"),Ce);const $e=new de("user",se),Ve=new de("user.groups",oe),Je=["id","name","email","username","description","state"],Ze=$e.del(),Qe={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()},et=he(_.default.object(Qe)),tt={groups:_.default.array().items(_.default.number())},rt=he(_.default.object(tt)),st={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("")},ot=he(_.default.object(st)),nt=o.Router();nt.use(ge),nt.get("/",ve("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return $e.all({attributes:Je})(e,t)})))),nt.post("/",ve("users.write"),et,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password=i.SHA256(e.body.password).toString(),yield $e.add()(e,t)})))),nt.route("/:id").get(ve("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return $e.get({attributes:Je})(e,t)})))).put(ve("users.write"),ot,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=i.SHA256(e.body.password).toString()),$e.set()(e,t)})))).delete(ve("users.write"),Ze),nt.route("/:id/groups").get(ve("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ve.all({where:{userId:r},include:[{model:Q,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(ve("users.write"),rt,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield se.findByPk(r,{attributes:["id"]}).catch((e=>{ie.error(e.message,"user.groups.set")}));if(o){if(yield oe.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield Q.count({where:{id:s[t]}}),e&&(yield oe.create({userId:o.id,groupId:s[t]}))}return ae.success(t,"OK")}return ae.notfound(t,"Record not found")}))));const it=o.Router();it.use("/auth",we),it.use("/groups",Be),it.use("/logs",Ue),it.use("/routes",Xe),it.use("/users",nt);const at=I.default();at.use(I.default.json()),at.use(((e,t,r,s)=>e?(ie.error(e.message,"express"),ae.error(r,"Internal Server Error")):s())),at.use(I.default.urlencoded({extended:!0})),at.disable("x-powered-by"),H&&at.use(h.default());const dt=o.Router();at.use("/api",dt),at.use("/api",it),at.all("/api/*",((e,t)=>ae.notfound(t,"Invalid API"))),U&&(n.existsSync(U)&&at.use(I.default.static(U)),at.get("*",((e,t)=>{if(!n.existsSync(U))return ae.notfound(t,'File "index.html" not found');t.sendFile(U+"/index.html")})));const ut=e=>{const t=new S.default.Server({server:e,verifyClient:lt});return t.on("connection",(e=>{e.on("message",(t=>$(void 0,void 0,void 0,(function*(){fe.verify(t.toString()),e.close()})))),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},lt=(e,t)=>t(X),ct=(e=>{if(!ce.http||!pe.http){const t=A.createServer(e);return t.listen(k,(()=>ie.info(`Server started on port ${k}`))),t}const t=A.createServer(((e,t)=>{const r=80==k?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=P.createServer({key:pe.http,cert:ce.http},e);if(L){return new m.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,(()=>ie.info(`Server started on port ${k}`))),r}return 443==k&&t.listen(80,(()=>ie.info("Server started on port 80"))),r.listen(k,(()=>ie.info(`Server started on port ${k}`))),r})(at);exports.API_AUTH_SLEEP=b,exports.API_DB_DATABASE=O,exports.API_DB_HOST=x,exports.API_DB_LOG=N,exports.API_DB_PASSWORD=E,exports.API_DB_PORT=D,exports.API_DB_TYPE=R,exports.API_DB_USERNAME=q,exports.API_HTTP_CROSS=H,exports.API_HTTP_CRT=j,exports.API_HTTP_HYBRID=L,exports.API_HTTP_KEY=B,exports.API_HTTP_PORT=k,exports.API_HTTP_PUBLIC=U,exports.API_TOKEN_CRT=z,exports.API_TOKEN_HEADER=M,exports.API_TOKEN_KEY=C,exports.API_TOKEN_LIFETIME=G,exports.API_UPLOAD_COUNT=K,exports.API_UPLOAD_FIELD=F,exports.API_UPLOAD_SIZE=Y,exports.API_UPLOAD_TEMP=W,exports.API_WEBSOCKET_START=X,exports.Auth=Z,exports.Controller=de,exports.Group=Q,exports.GroupRoute=re,exports.Log=ie,exports.Logs=ee,exports.Permission=ue,exports.Responses=ae,exports.Route=te,exports.Token=fe,exports.User=se,exports.UserGroup=oe,exports.app=at,exports.auth=ge,exports.crt=ce,exports.initialize=()=>{J.sync().then((()=>{$(void 0,void 0,void 0,(function*(){if(0==(yield se.count())){const t={description:"",state:!0},r=yield se.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"},t));if(0==(yield Q.count())){const s=yield Q.create(Object.assign({name:"admin"},t));if(yield oe.create({userId:r.id,groupId:s.id}),0==(yield te.count())){const r=["read","write"],o=["users","groups","permission"];yield e.forEachSeries(o,(o=>$(void 0,void 0,void 0,(function*(){yield e.forEachSeries(r,(e=>$(void 0,void 0,void 0,(function*(){const r=o+"."+e,n=yield te.create(Object.assign({name:r},t));yield re.create({groupId:s.id,routeId:n.id})}))))}))));const n=yield te.create(Object.assign({name:"logs.read"},t));yield re.create({groupId:s.id,routeId:n.id})}}}})),X&&ut(ct)}))},exports.key=pe,exports.permission=ve,exports.router=dt,exports.sequelize=J,exports.server=ct,exports.startSocket=ut,exports.upload=e=>{const t=(null==e?void 0:e.path)||W,r=w.default.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>$(void 0,void 0,void 0,(function*(){return s(null,ye(t,T.default.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||Y),o=w.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)||K,i=(null==e?void 0:e.field)||F,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?ae.error(t,e.message):r()}))}},exports.uuid=V,exports.validation=he;
7
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@andrewcaires/utils.js"),t=require("dotenv"),r=require("sequelize"),s=require("http"),o=require("https"),i=require("net"),n=require("cors"),a=require("express"),d=require("fs"),u=require("crypto-js"),l=require("jsonwebtoken"),c=require("mime-types"),p=require("multer"),f=require("path"),m=require("joi"),v=require("ws");function g(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=y(s),I=y(o),T=g(n),w=g(a),_=g(c),A=g(p),P=g(m),S=g(v);function b(e,t,r,s){return new(r||(r=Promise))((function(o,i){function n(e){try{d(s.next(e))}catch(e){i(e)}}function a(e){try{d(s.throw(e))}catch(e){i(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(n,a)}d((s=s.apply(e,t||[])).next())}))}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"),N=process.env.API_DB_TYPE||"",q=process.env.API_DB_USERNAME||"root",j=e.toBool(process.env.API_DB_LOG||"false"),k=process.env.API_HTTP_CRT||"",B=process.env.API_HTTP_KEY||"",U=parseInt(process.env.API_HTTP_PORT||"3000"),H=process.env.API_HTTP_PUBLIC||"",C=e.toBool(process.env.API_HTTP_CROSS||"false"),L=e.toBool(process.env.API_HTTP_HYBRID||"false"),z=process.env.API_TOKEN_CRT||"",G=process.env.API_TOKEN_KEY||"",M=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"),J={type:r.UUID,defaultValue:r.UUIDV4,allowNull:!1,primaryKey:!0},Z=(()=>{switch(N){case"mariadb":return new r.Sequelize(x,q,D,{host:E,port:R,dialect:"mariadb",logging:j,define:{timestamps:!1}});case"mysql":return new r.Sequelize(x,q,D,{host:E,port:R,dialect:"mysql",logging:j,define:{timestamps:!1}});case"postgres":return new r.Sequelize(x,q,D,{host:E,port:R,dialect:"postgres",logging:j,define:{timestamps:!1}})}throw new Error("No database selected")})();class $ extends r.Model{}$.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 Q extends r.Model{}Q.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"group"});class ee extends r.Model{}ee.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"route"});class te extends r.Model{}te.init({},{sequelize:Z,modelName:"groups_routes"}),te.removeAttribute("id");class re extends r.Model{}re.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 se extends r.Model{}se.init({},{sequelize:Z,modelName:"users_groups"}),se.removeAttribute("id");class oe extends r.Model{}oe.init({key:r.DataTypes.STRING,value:r.DataTypes.STRING},{sequelize:Z,modelName:"configs",timestamps:!0,createdAt:"created",updatedAt:"updated"}),oe.removeAttribute("id");class ie extends r.Model{}var ne;ie.init({type:r.DataTypes.STRING,source:r.DataTypes.STRING,message:r.DataTypes.TEXT},{sequelize:Z,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1}),re.hasMany($),$.belongsTo(re),Q.hasMany(te),te.belongsTo(Q),ee.hasMany(te),te.belongsTo(ee),re.hasMany(se),se.belongsTo(re),Q.hasMany(se),se.belongsTo(Q),function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(ne||(ne={}));class ae{static write(e,t,r){return b(this,void 0,void 0,(function*(){yield ae.writeRaw(ne.NONE,"",e,t,r)}))}static error(e,t,r){return b(this,void 0,void 0,(function*(){yield ae.writeRaw(ne.ERROR,"error",e,t,r)}))}static info(e,t,r){return b(this,void 0,void 0,(function*(){yield ae.writeRaw(ne.INFO,"info",e,t,r)}))}static success(e,t,r){return b(this,void 0,void 0,(function*(){yield ae.writeRaw(ne.ERROR,"success",e,t,r)}))}static warning(e,t,r){return b(this,void 0,void 0,(function*(){yield ae.writeRaw(ne.WARNING,"warning",e,t,r)}))}static writeConsole(t,r,s){const o=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"","|",o,"|",s)}static writeRaw(e,t,r,s,o){return b(this,void 0,void 0,(function*(){o&&ae.writeConsole(e,t,r),yield ie.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})}}class ue{constructor(e){this.model=e}add(){return(e,t)=>b(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{ae.error(e.message,"api.controller."+this.model.tableName,!0)}));return r?de.data(t,{id:r.id}):de.error(t,"Internal Server Error")}))}all(t,s){return(o,i)=>b(this,void 0,void 0,(function*(){var n,a,d,u,l;const c=Object.assign({},t||{});c.where=Object.assign({},c.where||{});const p=null===(n=o.query.limit)||void 0===n?void 0:n.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=Object.keys(this.model.getAttributes()),v=[],g=null===(d=o.query.asc)||void 0===d?void 0:d.toString();g&&g.length&&g.split(",").forEach((e=>{m.indexOf(e)>=0&&v.push([e,"ASC"])}));const y=null===(u=o.query.desc)||void 0===u?void 0:u.toString();y&&y.length&&y.split(",").forEach((e=>{m.indexOf(e)>=0&&v.push([e,"DESC"])})),v.length&&(c.order=v);const h=[],I=e.isArray(c.attributes)?c.attributes:m,T=null===(l=o.query.search)||void 0===l?void 0:l.toString();I.forEach((t=>{var s;if(e.isString(t)&&(T&&T.length&&h.push({[t]:{[r.Op.like]:`%${T}%`}}),"search_"+t in o.query)){const e=null===(s=o.query["search_"+t])||void 0===s?void 0:s.toString();e&&e.length&&h.push({[t]:{[r.Op.like]:`%${e}%`}})}})),h.length&&(c.where=Object.assign(Object.assign({},c.where),{[r.Op.or]:[...h]}));const w=yield this.model.findAll(c).catch((e=>{ae.error(e.message,"api.controller."+this.model.tableName,!0)})),_=yield this.model.count(c).catch(e.noop);return w?de.data(i,{count:_,records:s?s(w):w}):de.error(i,"Internal Server Error")}))}del(){return(e,t)=>b(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,"api.controller."+this.model.tableName,!0)})))?de.success(t,"OK"):de.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>b(this,void 0,void 0,(function*(){e||(e={});const o=Object.assign({},e);o.where=o.where?Object.assign({},o.where):{};const{id:i}=r.params,n=yield this.model.findByPk(i,o).catch((e=>{ae.error(e.message,"api.controller."+this.model.tableName,!0)}));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)=>b(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,"api.controller."+this.model.tableName,!0)})))||[];return s?de.success(t,"OK"):de.success(t,"Record not changed")}))}}class le{static all(e,t){return b(this,void 0,void 0,(function*(){return yield ee.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:te,required:!0,include:[{model:Q,required:!0,where:{state:!0},include:[{model:se,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ae.error(e.message,"api.permission",!0)}))}))}static get(e){return b(this,void 0,void 0,(function*(){const t=yield le.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return b(this,void 0,void 0,(function*(){const r=yield le.all(e,{name:t});return r&&!!r.length}))}}const ce=e=>{if(d.existsSync(e))return d.readFileSync(e)},pe={http:ce(k),token:ce(z)},fe={http:ce(B),token:ce(G)};class me{static sign(e){return fe.token?{token:l.sign(e,fe.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static verify(e){if(!pe.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:l.verify(e,pe.token)}}catch(e){return{error:"Invalid Token"}}}}const ve=["id","name","email","username"],ge=(e,t,r)=>b(void 0,void 0,void 0,(function*(){const s=e.get(M)||"",{error:o,decode:i}=me.verify(s);if(o)return de.error(t,o);if(i){const{id:s,secret:o}=i;if(s&&i){const i=yield re.findOne({where:{id:s,state:!0}}).catch((e=>{ae.error(e.message,"api.auth",!0)}));if(i){const s=yield $.findOne({where:{secret:o,userId:i.id}}).catch((e=>{ae.error(e.message,"api.auth",!0)}));if(s){const o=Date.now();if(o>s.timestamp)return de.error(t,"Expired token");if(!s.logout){s.timestamp=o+6e4*K;const t=e.get("User-Agent");return t&&(s.useragent=t),yield s.save(),e.auth=s,e.user=i,r()}}}return de.error(t,"Access denied")}}return de.error(t,"Invalid token")})),ye=e=>(t,r,s)=>b(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield le.is(o,e))?s():de.error(r,"Unauthorized access"):de.unauthorized(r,"Access denied")})),he=(t,r)=>{const s=e.uuidv4()+"."+r;return d.existsSync(f.join(t,s))?he(t,r):s},Ie=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:i,value:n}=e.validate(r.body,t);if(i){const e=i.details.map((e=>e.message)).join(", "),t=[];return i.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=n,o()}},Te={username:P.default.string().min(5).required(),password:P.default.string().min(5).required()},we=Ie(P.default.object(Te)),_e=a.Router();_e.get("/",ge,((t,r)=>b(void 0,void 0,void 0,(function*(){const s=t.user;if(!s)return de.unauthorized(r,"Access denied");const o=yield le.all(s);if(o){const t=e.allowedObject(ve,s.toJSON()),i=o.map((e=>e.name));return de.data(r,Object.assign(Object.assign({},t),{permissions:i}))}return de.error(r,"Internal Server Error")})))),_e.post("/login",we,((t,r)=>b(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 i=yield re.findOne({where:{username:s}}).catch((e=>{ae.error(e.message,"api.controller."+re.tableName,!0)}));if(!i)return de.notfound(r,"Username not found");if(!i.state)return de.error(r,"Username is disabled");const n=u.SHA256(o).toString();if(i.password!=n)return de.error(r,"Invalid password");const a=i.id,d=e.uniqueID(),{error:l,token:c}=me.sign({id:a,secret:d});if(l)return de.error(r,l);if(c){const e=Date.now(),s=e+6e4*K,o=t.get("User-Agent"),i=yield $.create({login:e,secret:d,timestamp:s,useragent:o,userId:a}).catch((e=>{ae.error(e.message,"api.controller."+$.tableName,!0)}));if(i)return de.data(r,{token:c})}return de.error(r,"Internal Server Error")})))),_e.get("/logout",ge,((e,t)=>b(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")}))));const Ae=new ue(Q),Pe=new ue(te),Se=Ae.add(),be=Ae.all(),Oe=Ae.del(),xe=Ae.get(),Ee=Ae.set(),De={name:P.default.string().min(3).required(),description:P.default.string().allow(null,""),state:P.default.boolean().required()},Re=Ie(P.default.object(De)),Ne={routes:P.default.array().items(P.default.number())},qe=Ie(P.default.object(Ne)),je={name:P.default.string().min(3).empty(""),description:P.default.string().allow(null,""),state:P.default.boolean().empty("")},ke=Ie(P.default.object(je)),Be=a.Router();Be.use(ge),Be.get("/",ye("groups.read"),be),Be.post("/",ye("groups.write"),Re,Se),Be.route("/:id").get(ye("groups.read"),xe).put(ye("groups.write"),ke,Ee).delete(ye("groups.write"),Oe),Be.route("/:id/routes").get(ye("groups.read"),qe,((e,t)=>b(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Pe.all({where:{groupId:r},include:[{model:ee,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(ye("groups.write"),qe,((e,t)=>b(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield Q.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"api.controller."+Q.tableName,!0)}));if(o){const e=o.id;if(yield te.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield ee.count({where:{id:s[r]}}),t&&(yield te.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 Ue=new ue(ie),He=a.Router();He.use(ge),He.get("/",ye("logs.read"),((e,t)=>b(void 0,void 0,void 0,(function*(){const{source:r,type:s}=e.query,o=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return Ue.all({where:o,order:[["created","DESC"]]})(e,t)}))));const Ce=new ue(ee),Le=Ce.add(),ze=Ce.all(),Ge=Ce.del(),Me=Ce.get(),Ke=Ce.set(),Fe={name:P.default.string().min(5).required(),description:P.default.string().allow(null,""),state:P.default.boolean().required()},Ye=Ie(P.default.object(Fe)),We={name:P.default.string().min(5).empty(""),description:P.default.string().allow(null,""),state:P.default.boolean().empty("")},Xe=Ie(P.default.object(We)),Ve=a.Router();Ve.use(ge),Ve.get("/",ye("routes.read"),ze),Ve.post("/",ye("routes.write"),Ye,Le),Ve.route("/:id").get(ye("routes.read"),Me).put(ye("routes.write"),Xe,Ke).delete(ye("routes.write"),Ge);const Je=new ue(re),Ze=new ue(se),$e=["id","name","email","username","description","state"],Qe=Je.del(),et={name:P.default.string().min(5).required(),email:P.default.string().email().required(),username:P.default.string().min(5).required(),password:P.default.string().min(5).required(),description:P.default.string().allow(null,""),state:P.default.boolean().required()},tt=Ie(P.default.object(et)),rt={groups:P.default.array().items(P.default.number())},st=Ie(P.default.object(rt)),ot={name:P.default.string().min(5).empty(""),email:P.default.string().email().empty(""),username:P.default.string().min(5).empty(""),password:P.default.string().min(5).empty(""),description:P.default.string().allow(null,""),state:P.default.boolean().empty("")},it=Ie(P.default.object(ot)),nt=a.Router();nt.use(ge),nt.get("/",ye("users.read"),((e,t)=>b(void 0,void 0,void 0,(function*(){return Je.all({attributes:$e})(e,t)})))),nt.post("/",ye("users.write"),tt,((e,t)=>b(void 0,void 0,void 0,(function*(){return e.body.password=u.SHA256(e.body.password).toString(),yield Je.add()(e,t)})))),nt.route("/:id").get(ye("users.read"),((e,t)=>b(void 0,void 0,void 0,(function*(){return Je.get({attributes:$e})(e,t)})))).put(ye("users.write"),it,((e,t)=>b(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=u.SHA256(e.body.password).toString()),Je.set()(e,t)})))).delete(ye("users.write"),Qe),nt.route("/:id/groups").get(ye("users.read"),((e,t)=>b(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ze.all({where:{userId:r},include:[{model:Q,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(ye("users.write"),st,((e,t)=>b(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield re.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"api.controller."+re.tableName,!0)}));if(o){if(yield se.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield Q.count({where:{id:s[t]}}),e&&(yield se.create({userId:o.id,groupId:s[t]}))}return de.success(t,"OK")}return de.notfound(t,"Record not found")}))));const at=a.Router();let dt;at.use("/auth",_e),at.use("/groups",Be),at.use("/logs",He),at.use("/routes",Ve),at.use("/users",nt);const ut=a.Router(),lt=()=>{var e;return dt||(dt=w.default(),(e=dt).use(w.default.json()),e.use(((e,t,r,s)=>e?(ae.error(e.message,"api.express",!0),de.error(r,"Internal Server Error")):s())),e.use(w.default.urlencoded({extended:!0})),e.disable("x-powered-by"),C&&e.use(T.default()),e.use("/api",ut),e.use("/api",at),e.all("/api/*",((e,t)=>de.notfound(t,"Invalid API"))),H&&(d.existsSync(H)&&e.use(w.default.static(H)),e.get("*",((e,t)=>{if(!d.existsSync(H))return de.notfound(t,'File "index.html" not found');t.sendFile(H+"/index.html")})))),dt};let ct;const pt=()=>(ct||(ct=(e=>{if(!pe.http||!fe.http){const t=h.createServer(e);return t.listen(U,(()=>ae.info("Server started on port "+U,"api.server",!0))),t}const t=h.createServer(((e,t)=>{const r=80==U?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=I.createServer({key:fe.http,cert:pe.http},e);if(L)return new i.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,"api.server",!0))),r;return 443==U&&t.listen(80,(()=>ae.info("Server started on port 80","api.server",!0))),r.listen(U,(()=>ae.info("Server started on port "+U,"api.server",!0))),r})(lt())),ct),ft=e=>{const t=new S.default.Server({server:e,verifyClient:mt});return t.on("connection",(e=>{e.on("message",(t=>b(void 0,void 0,void 0,(function*(){me.verify(t.toString()),e.close()})))),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},mt=(e,t)=>t(V);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=N,exports.API_DB_USERNAME=q,exports.API_HTTP_CROSS=C,exports.API_HTTP_CRT=k,exports.API_HTTP_HYBRID=L,exports.API_HTTP_KEY=B,exports.API_HTTP_PORT=U,exports.API_HTTP_PUBLIC=H,exports.API_TOKEN_CRT=z,exports.API_TOKEN_HEADER=M,exports.API_TOKEN_KEY=G,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=$,exports.Config=class{static all(){return b(this,void 0,void 0,(function*(){const e=yield oe.findAll().catch((e=>{ae.error(e.message,"api.config",!0)})),t={};return e&&e.forEach((e=>{t[e.key]=e.value})),t}))}static del(e){return b(this,void 0,void 0,(function*(){return((yield oe.destroy({where:{key:e}}).catch((e=>{ae.error(e.message,"api.config",!0)})))||0)>0}))}static get(e){return b(this,void 0,void 0,(function*(){const t=yield oe.findOne({where:{key:e}}).catch((e=>{ae.error(e.message,"api.config",!0)}));return t&&t.value||""}))}static set(e,t){return b(this,void 0,void 0,(function*(){const[r]=(yield oe.findOrCreate({where:{key:e}}).catch((e=>{ae.error(e.message,"api.config",!0)})))||[];r&&(r.value=t,yield r.save().catch((e=>{ae.error(e.message,"api.config",!0)})))}))}},exports.Configs=oe,exports.Controller=ue,exports.Group=Q,exports.GroupRoute=te,exports.Log=ae,exports.Logs=ie,exports.Permission=le,exports.Responses=de,exports.Route=ee,exports.Token=me,exports.User=re,exports.UserGroup=se,exports.auth=ge,exports.crt=pe,exports.initialize=()=>b(void 0,void 0,void 0,(function*(){yield Z.sync();const e=pt();V&&ft(e)})),exports.key=fe,exports.permission=ye,exports.router=ut,exports.sequelize=Z,exports.startSocket=ft,exports.upload=e=>{const t=(null==e?void 0:e.path)||X,r=A.default.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>b(void 0,void 0,void 0,(function*(){return s(null,he(t,_.default.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||W),o=A.default({storage:r,fileFilter(t,r,s){var o;return b(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}}),i=(null==e?void 0:e.count)||F,n=(null==e?void 0:e.field)||Y,a=o.array(n,i);return(e,t,r)=>{a(e,t,(function(e){return e?de.error(t,e.message):r()}))}},exports.useExpress=lt,exports.uuid=J,exports.validation=Ie;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrewcaires/api",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "Simple api for small applications using express, jsonwebtoken, sequelize and websocket",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.esm.js",
@@ -8,7 +8,7 @@
8
8
  "scripts": {
9
9
  "serve": "ts-node src/test.ts",
10
10
  "build": "rollup -c build/rollup.config.js",
11
- "dev": "ts-node-dev --respawn --transpile-only ./src/index.ts"
11
+ "dev": "ts-node-dev --respawn --transpile-only ./src/test.ts"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "homepage": "https://github.com/andrewcaires/npm/tree/main/api#readme",
37
37
  "dependencies": {
38
- "@andrewcaires/utils.js": "^0.1.5",
38
+ "@andrewcaires/utils.js": "^0.1.6",
39
39
  "cors": "^2.8.5",
40
40
  "crypto-js": "^4.1.1",
41
41
  "dotenv": "^16.0.1",
@@ -43,33 +43,33 @@
43
43
  "fs": "^0.0.1-security",
44
44
  "joi": "^17.6.0",
45
45
  "jsonwebtoken": "^8.5.1",
46
- "mariadb": "^3.0.0",
46
+ "mariadb": "^3.0.1",
47
47
  "mime-types": "^2.1.35",
48
48
  "multer": "^1.4.5-lts.1",
49
49
  "mysql2": "^2.3.3",
50
50
  "pg": "^8.7.3",
51
51
  "pg-hstore": "^2.3.4",
52
- "sequelize": "^6.21.2",
53
- "ws": "^8.8.0"
52
+ "sequelize": "^6.21.4",
53
+ "ws": "^8.8.1"
54
54
  },
55
55
  "devDependencies": {
56
- "@rollup/plugin-commonjs": "^22.0.1",
57
- "@rollup/plugin-typescript": "^8.3.3",
56
+ "@rollup/plugin-commonjs": "^22.0.2",
57
+ "@rollup/plugin-typescript": "^8.3.4",
58
58
  "@types/cors": "^2.8.12",
59
59
  "@types/crypto-js": "^4.1.1",
60
60
  "@types/express": "^4.17.13",
61
61
  "@types/jsonwebtoken": "^8.5.8",
62
62
  "@types/mime-types": "^2.1.1",
63
63
  "@types/multer": "^1.4.7",
64
- "@types/node": "^18.0.1",
64
+ "@types/node": "^18.7.6",
65
65
  "@types/ws": "^8.5.3",
66
- "@typescript-eslint/eslint-plugin": "^5.30.4",
67
- "@typescript-eslint/parser": "^5.30.0",
68
- "eslint": "^8.19.0",
69
- "rollup": "^2.75.7",
66
+ "@typescript-eslint/eslint-plugin": "^5.33.1",
67
+ "@typescript-eslint/parser": "^5.33.1",
68
+ "eslint": "^8.22.0",
69
+ "rollup": "^2.78.1",
70
70
  "rollup-plugin-dts": "^4.2.2",
71
71
  "rollup-plugin-terser": "^7.0.2",
72
- "ts-node": "^10.8.2",
72
+ "ts-node": "^10.9.1",
73
73
  "ts-node-dev": "^2.0.0",
74
74
  "typescript": "^4.7.4"
75
75
  }