Overview
This is a collection of node tools to make express server development quicker and cleaner. Contains tools for jwt generation, SQL utilities, file management, error handling and others.
SimpleToken
import { SimpleToken } from 'backend-tools';
const simpleToken = new SimpleToken('SECRET KEY STRING');
const payload = {
user: 265,
permissions: 'af8',
};
/**
* Create a token that expires in 300 seconds (5 minutes)
*/
const token = simpleToken.sign(payload, 300);
simpleToken
.verify(token)
.then(payloadIntoToken => {
/**
* Must be:
* {
* user: 265,
* permissions: 'af8'
* }
*/
console.log(payloadIntoToken);
})
.catch(err => {
// Invalid token
});
Bcrypt algorithm is used to have better security, set the saltRound or cost factor (10 by default) into the instance of a SimpleToken object.
const simpleToken = new SimpleToken('SECRET KEY STRING', 15);
PermissionsManager
import { PermissionsManager } from 'backend-tools';
const permissionsManager = new PermissionsManager([
'products_create',
'products_update',
'products_delete',
'clients_create',
'clients_update',
'clients_delete',
'providers_create',
'providers_update',
'providers_delete',
'admin_users',
]);
Decode and encode permissions object into a short string of a base 32 number (each digit can be between 0 and v).
const permissions = {
clients_create: true,
clients_update: true,
providers_create: true,
providers_update: true,
};
/**
* Must be equal to '6o'
*/
const encoded = permissionsManager.encode(permissions);
/*
* Must match to permissions object previously declared
*/
const decodedPermissions = permissionsManager.decode(encoded);
Build and verify payloads according to a list of permissions declared.
const permissions = {
products_delete: true,
clients_delete: true,
providers_delete: true,
admin_users: true,
};
/**
* Payload must be
* {
* user: 'admin',
* _pp: 'p4',
* }
*/
const payload = permissionsManager.buildPayload(
{
user: 'admin',
},
permissions
);
/**
* Return the permissions object
*/
const canDeleteClients = permissionsManager.verifyPayload(
payload,
'clients_delete'
);
/**
* Must be false
*/
const canUpdateClients = permissionsManager.verifyPayload(
payload,
'clients_update'
);
Verify the permissions by other methods too.
const adminUsersVerifier = permissionsManager.getVerifier('admin_users');
const canAdminUsers = adminUsersVerifier(payload);
const {
products_create,
products_update,
products_delete,
} = permissionsManager.verifyPayload(payload);
Session manager
import express from 'express';
import { sessionManager, verifySession } from 'backend-tools';
let expressApp = express();
expressApp.use(express.json());
expressApp.use(sessionManager('SECRET KEY STRING'));
expressApp.post('/login', (req, res, next) => {
let { username, password } = req.body;
// ...
// Success login
/*
Expires on 1800 seconds (30 min).
*/
req.setSession({ user: username, canReadPrivate: true }, 1800, {
// Only accepted on https request.
secure: true,
});
res.sendStatus(200);
});
expressApp.get(
'/private-resource',
verifySession(session_data => session_data.canReadPrivate),
(req, res, next) => {
res.send('This is a private data');
}
);
Configuration
sessionManager(secret, defaultOptions);
- secret: Password to sign sessions.
-
defaultOptions: Options to configure sessions by default.
- lifetime: Seconds of lifetime before expires.
-
authorizationHeader: Set if the manager accept authorization header (Default:
true
). - cookie: Cookie configuration.
- errorHandler: Function that handle if a token verify is unsuccessful.
Usage
req.setSession
req.setSession(payload, expiresIn, options);
-
payload: Object with session information.
-
expiresIn: (Optional) Seconds of lifetime before expires (By default defaultOption.lifetime), if it's
0
orundefined
never expires. -
options: (Optional) Set session url (By default defaultOption.cookie).
- secure: If only used on HTTPS protocol.
- domain
- path
Returns a object that can be used on OAuth2.
- access_token.
- token_type:
Bearer
. - expires_in.
- expires_at.
verifySession
verifySession(verifyPayload?: (payload) => boolean)
Returns a middleware that checks if the request has a session and checks its payload (if verifyPayload has setted).
PermissionsManager Verifiers can be used
canCreateVerify = permissionsManager.getVerifier('products_create');
expressApp.post(
'/products',
verifySession(canCreateVerify),
createProductsHandler
);
req.removeSession
req.removeSession(path?: string)
Delete the session associated with the path.
EasySQL
import { EasySQL } from 'backend-tools';
const testDBConnection = new EasySQL.Connection({
username: 'tester',
database: 'test',
});
/**
Table object implements CRUD operation like Find, FindOne, Create, Update, Delete
*/
const usersTable = testDBConnection.table('users');
/**
Equals to "SELECT * FROM users WHERE team IN ('A','Y','E','X','B') AND (email LIKE '%@gmail.com' OR email LIKE '%@outlook.com') ORDER BY team ASC ;" query
*/
usersTable
.find({
_sort: 'team:ASC',
team_in: 'A,Y,E,X,B',
email_like: ['%@gmail.com', '%@outlook.com'],
})
.then(users => {
console.log(users);
});
More details on docs/EasySQL.md file in the repository.
AdminFile
import { AdminFile } from 'backend-tools';
const adminFile = new AdminFile(AdminFile.path.resolve(__dirname, 'adminfile'));
adminFile.makeDir('logs');
adminFile.appendFile(
'logs',
'access.log',
`
<-------------------------------------------->
Start at ${new Date().toLocaleString()}
`
);
ErrorHandler
import express from 'express';
import path from 'path';
import { ErrorHandler } from 'backend-tools';
import mainRouter from './routes';
let expressApp = express();
const errorHandler = new ErrorHandler(
path.resolve(__dirname, 'logs', 'error.log')
);
expressApp.use('/', mainRouter);
expressApp.use(errorHandler.handler);
ApiREST
import express from 'express';
import { ApiREST, EasySQL } from 'backend-tools';
const connectionStore = new EasySQL.Connection({
user: 'seller',
database: 'store',
});
const products = connectionStore.table('products', { id_name: 'id' });
const simpleToken = new SimpleToken('Secret store key');
/**
* Set Securit middlewares
*/
const getSecurityMiddleware = ApiREST.defaultSecurity(simpleToken.verify);
/**
* Require valid token
*/
const authNeeded = getSecurityMiddleware(payload => true);
/**
* Payload of the token must have { canModify: true }
*/
const canModifyPermission = getSecurityMiddleware(payload => payload.canModify);
/**
* Enable
* - Find: Get /
* - FindOne: Get /:id
* - Create: Post /
* - Modify: Patch /:id
*
* The token is passed into header Authorization.
*
*/
const productsAPI = ApiREST.createApiREST({
find: [authNeeded, ApiREST.defaultFind(products)],
findOne: [
authNeeded,
ApiREST.defaultFindOne(products)
]
create: [
canModifyPermission,
ApiREST.defaultCreate(products)
],
modify: [
canModifyPermission,
ApiREST.defaultModify(products)
]
}, 'id')
const app = express();
app.use(express.json());
app.use('/products', productsAPI);
More details on docs/ApiREST.md file in the repository.