Fix login error + Fix merge conflicts
This commit is contained in:
54
README.md
54
README.md
@@ -19,6 +19,8 @@ Install Soul CLI with npm
|
||||
|
||||
## Usage
|
||||
|
||||
### 1. Running Soul
|
||||
|
||||
Soul is command line tool, after installing it,
|
||||
Run `soul -d sqlite.db -p 8000` and it'll start a REST API on [http://localhost:8000](http://localhost:8000) and a Websocket server on [ws://localhost:8000](ws://localhost:8000).
|
||||
|
||||
@@ -33,21 +35,19 @@ Options:
|
||||
-r, --rate-limit-enabled Enable rate limiting [boolean]
|
||||
-c, --cors CORS whitelist origins [string]
|
||||
-a, --auth Enable authentication and authorization [boolean]
|
||||
-js, --jwtsecret JWT Secret [string]
|
||||
-jet, --jwtexpirationtime JWT Expiration Time [string]
|
||||
-suu, --superuserusername Initial user username [string]
|
||||
-sup, --superuserpassword Initial user password [string]
|
||||
|
||||
-iuu, --initialuserusername Initial user username [string]
|
||||
-iup, --initialuserpassword Initial user password [string]
|
||||
|
||||
-ats, --accesstokensecret Access Token Secret [string]
|
||||
-atet, --accesstokenexpirationtime Access Token Expiration Time [string]
|
||||
-rts, --refreshtokensecret Refresh Token Secret [string]
|
||||
-rtet, --refreshtokenexpirationtime Refresh Token Expiration Time [string]
|
||||
-S, --studio Start Soul Studio in parallel
|
||||
--help Show help
|
||||
|
||||
```
|
||||
|
||||
NOTE: When specifying the JWT expiration time in Soul, it must be in a specific format. Here are some examples:
|
||||
|
||||
60M: Represents a duration of 60 minutes.
|
||||
5H: Represents a duration of 5 hours.
|
||||
1D: Represents a duration of 1 day.
|
||||
|
||||
Then to test Soul is working run the following command
|
||||
|
||||
```bash
|
||||
@@ -56,36 +56,46 @@ curl http://localhost:8000/api/tables
|
||||
|
||||
It should return a list of the tables inside `sqlite.db` database.
|
||||
|
||||
**Running Soul in Auth mode**
|
||||
### 2. Running Soul in Auth mode
|
||||
|
||||
To run Soul in auth mode, allowing login and signup features with authorization capabilities in your database tables, follow these steps:
|
||||
|
||||
Run the Soul command with the necessary parameters:
|
||||
|
||||
```
|
||||
soul --d foobar.db -a -js=<your_jwt_secret_value> -jet=3D -iuu=john -iup=<your_password>
|
||||
soul --d foobar.db -a -ats <your_jwt_access_token_secret_value> -atet=4H -rts <your_jwt_refresh_token_secret_value> -rtet=3D -iuu=john -iup=<your_password>
|
||||
```
|
||||
|
||||
Note: When configuring your JWT Secret, it is recommended to use a long string value for enhanced security. It is advisable to use a secret that is at least 10 characters in length.
|
||||
|
||||
In this example:
|
||||
|
||||
The `-a` flag enables Soul to run in auth mode.
|
||||
The `-js` flag allows you to pass a JWT secret value for token generation and verification. Replace <your_jwt_secret_value> with your desired secret value.
|
||||
The `-jet` flag sets the JWT expiration time. In this case, it is set to one day (3D), meaning the tokens will expire after 72 hours. (`jet` is used for the JWT Refresh Token)
|
||||
The `-a` flag instructs Soul to run in auth mode.
|
||||
The `-ats` flag allows you to pass a JWT secret value for the `access token` generation and verification. Replace <your_jwt_access_token_secret_value> with your desired secret value.
|
||||
The `-atet` flag sets the JWT expiration time for the access token. In this case, it is set to four hours (4H), meaning the token will expire after 4 hours.
|
||||
The `-rts` flag allows you to pass a JWT secret value for the `refresh token` generation and verification. Replace <your_jwt_refresh_token_secret_value> with your desired secret value.
|
||||
The `-rtet` flag sets the JWT expiration time for the refresh token. In this case, it is set to three days (3D), meaning the token will expire after 3 days.
|
||||
The `-iuu` flag is used to pass a username for the initial user
|
||||
The `--iup` flag is used to pass a password for the initial user
|
||||
The `-iup` flag is used to pass a password for the initial user
|
||||
|
||||
**NOTE: It is crucial to securely store a copy of the JWT secret value used in Soul. Once you pass this value, make sure to keep a backup because you will need it every time you restart Soul. Losing this secret value can result in a situation where all of your users are blocked from accessing Soul.**
|
||||
Here are some example values for the `-atet` and `rtet` flags
|
||||
|
||||
**Updating Super Users**
|
||||
- 60M: Represents a duration of 60 minutes.
|
||||
- 5H: Represents a duration of 5 hours.
|
||||
- 1D: Represents a duration of 1 day.
|
||||
|
||||
To modify user information in a database, you can utilize the `updateuser` command. This command allows you to change a user's `password` and upgrade a normal user to a `superuser`. Below is an example of how to use it:
|
||||
NOTE: It is crucial to securely store a copy of the `Access token secret` and `Refresh token secret` values used in Soul. Once you pass this values, make sure to keep a backup because you will need it every time you restart Soul. Losing this secret values can result in a situation where all of your users are blocked from accessing Soul.
|
||||
|
||||
### 3. Updating Super Users
|
||||
|
||||
To modify a superuser information in a database, you can utilize the `updatesuperuser` command. This command allows you to change a superuser's `password` or upgrade/downgrade a normal user to a `superuser`. Below is an example of how to use it:
|
||||
|
||||
```
|
||||
soul --d foobar.db updateuser --id=1 password=<new_password_for_the_user> // Update the password for the user with ID 1
|
||||
soul --d foobar.db updatesuperuser --id=1 password=<new_password_for_the_user> // Update the password for the superuser with ID 1
|
||||
|
||||
soul --d foobar.db updateuser --id=1 --is_superuser=true // Upgrade the user with ID 1 to a superuser
|
||||
soul --d foobar.db updatesuperuser --id=1 --is_superuser=true // Upgrade the user with ID 1 to a superuser
|
||||
|
||||
soul --d foobar.db updateuser --id=1 --is_superuser=false // Revoke the superuser role from the user with ID 1
|
||||
soul --d foobar.db updatesuperuser --id=1 --is_superuser=false // Revoke the superuser role from the superuser with ID 1
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
34
src/cli.js
34
src/cli.js
@@ -53,16 +53,30 @@ if (process.env.NO_CLI !== 'true') {
|
||||
default: false,
|
||||
demandOption: false,
|
||||
})
|
||||
.options('js', {
|
||||
alias: 'jwtsecret',
|
||||
describe: 'JWT secret',
|
||||
.options('ats', {
|
||||
alias: 'accesstokensecret',
|
||||
describe: 'JWT secret for access token',
|
||||
type: 'string',
|
||||
default: null,
|
||||
demandOption: false,
|
||||
})
|
||||
.options('jet', {
|
||||
alias: 'jwtexpirationtime',
|
||||
describe: 'JWT expiration time',
|
||||
.options('atet', {
|
||||
alias: 'accesstokenexpirationtime',
|
||||
describe: 'JWT expiration time for access token',
|
||||
type: 'string',
|
||||
default: '5H',
|
||||
demandOption: false,
|
||||
})
|
||||
.options('rts', {
|
||||
alias: 'refreshtokensecret',
|
||||
describe: 'JWT secret for refresh token',
|
||||
type: 'string',
|
||||
default: null,
|
||||
demandOption: false,
|
||||
})
|
||||
.options('rtet', {
|
||||
alias: 'refreshtokenexpirationtime',
|
||||
describe: 'JWT expiration time for refresh token',
|
||||
type: 'string',
|
||||
default: '3D',
|
||||
demandOption: false,
|
||||
@@ -85,20 +99,20 @@ if (process.env.NO_CLI !== 'true') {
|
||||
type: 'boolean',
|
||||
demandOption: false,
|
||||
})
|
||||
.command('updateuser', 'Update a user', (yargs) => {
|
||||
.command('updatesuperuser', 'Update a superuser', (yargs) => {
|
||||
return yargs
|
||||
.option('id', {
|
||||
describe: 'The ID of the user you want to update',
|
||||
describe: 'The ID of the superuser you want to update',
|
||||
type: 'number',
|
||||
demandOption: true,
|
||||
})
|
||||
.option('password', {
|
||||
describe: 'The new password for the user you want to update',
|
||||
describe: 'The new password for the superuser you want to update',
|
||||
type: 'string',
|
||||
demandOption: false,
|
||||
})
|
||||
.option('is_superuser', {
|
||||
describe: 'The role of the user you want to update',
|
||||
describe: 'The role of the superuser you want to update',
|
||||
type: 'boolean',
|
||||
demandOption: false,
|
||||
});
|
||||
|
||||
22
src/commands.js
Normal file
22
src/commands.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const { yargs } = require('./cli');
|
||||
const { updateSuperuser } = require('./controllers/auth');
|
||||
|
||||
const { argv } = yargs;
|
||||
|
||||
const runCLICommands = () => {
|
||||
//If the updatesuperuser command is passed from the CLI execute the updatesuperuser function
|
||||
if (argv._.includes('updatesuperuser')) {
|
||||
const { id, password, is_superuser } = argv;
|
||||
|
||||
if (!password && !is_superuser) {
|
||||
console.log(
|
||||
'Please provide either the --password or --is_superuser flag when using the updateuser command.',
|
||||
);
|
||||
process.exit(1);
|
||||
} else {
|
||||
updateSuperuser({ id, password, is_superuser });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { runCLICommands };
|
||||
@@ -30,11 +30,13 @@ const envVarsSchema = Joi.object()
|
||||
|
||||
START_WITH_STUDIO: Joi.boolean().default(false),
|
||||
|
||||
JWT_SECRET: Joi.string().default(null),
|
||||
JWT_EXPIRATION_TIME: Joi.string().default('1D'),
|
||||
|
||||
INITIAL_USER_USERNAME: Joi.string(),
|
||||
INITIAL_USER_PASSWORD: Joi.string(),
|
||||
|
||||
ACCESS_TOKEN_SECRET: Joi.string().default(null),
|
||||
ACCESS_TOKEN_EXPIRATION_TIME: Joi.string().default('5H'),
|
||||
REFRESH_TOKEN_SECRET: Joi.string().default(null),
|
||||
REFRESH_TOKEN_EXPIRATION_TIME: Joi.string().default('3D'),
|
||||
})
|
||||
.unknown();
|
||||
|
||||
@@ -66,12 +68,20 @@ if (argv['rate-limit-enabled']) {
|
||||
env.RATE_LIMIT_ENABLED = argv['rate-limit-enabled'];
|
||||
}
|
||||
|
||||
if (argv.jwtsecret) {
|
||||
env.JWT_SECRET = argv.jwtsecret;
|
||||
if (argv.accesstokensecret) {
|
||||
env.ACCESS_TOKEN_SECRET = argv.accesstokensecret;
|
||||
}
|
||||
|
||||
if (argv.jwtexpirationtime) {
|
||||
env.JWT_EXPIRATION_TIME = argv.jwtexpirationtime;
|
||||
if (argv.accesstokenexpirationtime) {
|
||||
env.ACCESS_TOKEN_EXPIRATION_TIME = argv.accesstokenexpirationtime;
|
||||
}
|
||||
|
||||
if (argv.refreshtokensecret) {
|
||||
env.REFRESH_TOKEN_SECRET = argv.refreshtokensecret;
|
||||
}
|
||||
|
||||
if (argv.refreshtokenexpirationtime) {
|
||||
env.REFRESH_TOKEN_EXPIRATION_TIME = argv.refreshtokenexpirationtime;
|
||||
}
|
||||
|
||||
if (argv.initialuserusername) {
|
||||
@@ -109,8 +119,12 @@ module.exports = {
|
||||
},
|
||||
|
||||
auth: argv.auth || envVars.AUTH,
|
||||
jwtSecret: argv.jwtsecret || envVars.JWT_SECRET,
|
||||
jwtExpirationTime: argv.jwtexpirationtime || envVars.JWT_EXPIRATION_TIME,
|
||||
accessTokenSecret: argv.accesstokensecret || envVars.ACCESS_TOKEN_SECRET,
|
||||
accessTokenExpirationTime:
|
||||
argv.accesstokenexpirationtime || envVars.ACCESS_TOKEN_EXPIRATION_TIME,
|
||||
refreshTokenSecret: argv.refreshtokensecret || envVars.REFRESH_TOKEN_SECRET,
|
||||
refreshTokenExpirationTime:
|
||||
argv.refreshtokenexpirationtime || envVars.REFRESH_TOKEN_EXPIRATION_TIME,
|
||||
|
||||
initialUserUsername:
|
||||
argv.initialuserusername || envVars.INITIAL_USER_USERNAME,
|
||||
|
||||
3
src/constants/api.js
Normal file
3
src/constants/api.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
defaultRoutes: ['_users', '_roles', '_roles_permissions', '_users_roles'],
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
const dbTables = require('./dbTables');
|
||||
const apiConstants = require('./api');
|
||||
const constantRoles = require('./roles');
|
||||
|
||||
module.exports = { dbTables };
|
||||
module.exports = { dbTables, apiConstants, constantRoles };
|
||||
|
||||
3
src/constants/roles.js
Normal file
3
src/constants/roles.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
DEFAULT_ROLE: 'default',
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
const { tableService } = require('../services');
|
||||
const { rowService } = require('../services');
|
||||
const { dbTables } = require('../constants');
|
||||
const { dbTables, constantRoles } = require('../constants');
|
||||
const config = require('../config');
|
||||
const {
|
||||
hashPassword,
|
||||
@@ -12,6 +12,8 @@ const {
|
||||
} = require('../utils');
|
||||
|
||||
const createDefaultTables = async () => {
|
||||
let roleId;
|
||||
|
||||
// check if the default tables are already created
|
||||
const roleTable = tableService.checkTableExists('_roles');
|
||||
const usersTable = tableService.checkTableExists('_users');
|
||||
@@ -19,11 +21,13 @@ const createDefaultTables = async () => {
|
||||
tableService.checkTableExists('_roles_permissions');
|
||||
const usersRolesTable = tableService.checkTableExists('_users_roles');
|
||||
|
||||
// create _users table
|
||||
if (!usersTable) {
|
||||
// create the _users table
|
||||
tableService.createTable('_users', dbTables.userSchema);
|
||||
}
|
||||
|
||||
// create _users_roles table
|
||||
if (!usersRolesTable) {
|
||||
// create the _users_roles table
|
||||
tableService.createTable(
|
||||
@@ -39,17 +43,21 @@ const createDefaultTables = async () => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!roleTable && !rolesPermissionTable) {
|
||||
// create _roles table
|
||||
if (!roleTable) {
|
||||
// create the _role table
|
||||
tableService.createTable('_roles', dbTables.roleSchema);
|
||||
|
||||
// create a default role in the _roles table
|
||||
const role = rowService.save({
|
||||
tableName: '_roles',
|
||||
fields: { name: 'default' },
|
||||
fields: { name: constantRoles.DEFAULT_ROLE },
|
||||
});
|
||||
const roleId = role.lastInsertRowid;
|
||||
roleId = role.lastInsertRowid;
|
||||
}
|
||||
|
||||
// create _roles_permissions table
|
||||
if (!rolesPermissionTable && roleId) {
|
||||
// create the _roles_permissions table
|
||||
tableService.createTable(
|
||||
'_roles_permissions',
|
||||
@@ -86,7 +94,7 @@ const createDefaultTables = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const updateUser = async (fields) => {
|
||||
const updateSuperuser = async (fields) => {
|
||||
const { id, password, is_superuser } = fields;
|
||||
let newHashedPassword, newSalt;
|
||||
let fieldsString = '';
|
||||
@@ -268,15 +276,15 @@ const obtainAccessToken = async (req, res) => {
|
||||
// generate an access token
|
||||
const accessToken = await generateToken(
|
||||
{ subject: 'accessToken', ...payload },
|
||||
config.jwtSecret,
|
||||
'1H',
|
||||
config.accessTokenSecret,
|
||||
config.accessTokenExpirationTime,
|
||||
);
|
||||
|
||||
// generate a refresh token
|
||||
const refreshToken = await generateToken(
|
||||
{ subject: 'refreshToken', ...payload },
|
||||
config.jwtSecret,
|
||||
config.jwtExpirationTime,
|
||||
config.refreshTokenSecret,
|
||||
config.refreshTokenExpirationTime,
|
||||
);
|
||||
|
||||
// set the token in the cookie
|
||||
@@ -299,7 +307,7 @@ const refreshAccessToken = async (req, res) => {
|
||||
// extract the payload from the token and verify it
|
||||
const payload = await decodeToken(
|
||||
req.cookies.refreshToken,
|
||||
config.jwtSecret,
|
||||
config.refreshTokenSecret,
|
||||
);
|
||||
|
||||
// find the user
|
||||
@@ -310,28 +318,52 @@ const refreshAccessToken = async (req, res) => {
|
||||
});
|
||||
|
||||
if (users.length <= 0) {
|
||||
return res.status(401).send({ message: 'User not found' });
|
||||
return res
|
||||
.status(401)
|
||||
.send({ message: `User with userId = ${payload.userId} not found` });
|
||||
}
|
||||
|
||||
let userRoles, permissions, roleIds;
|
||||
const user = users[0];
|
||||
|
||||
const newPaylod = {
|
||||
username: payload.username,
|
||||
userId: payload.userId,
|
||||
roleId: payload.roleId,
|
||||
// if the user is not a superuser get the role and its permission from the DB
|
||||
if (!toBoolean(user.is_superuser)) {
|
||||
userRoles = rowService.get({
|
||||
tableName: '_users_roles',
|
||||
whereString: 'WHERE user_id=?',
|
||||
whereStringValues: [user.id],
|
||||
});
|
||||
|
||||
roleIds = userRoles.map((role) => role.role_id);
|
||||
|
||||
// get the permission of the role
|
||||
permissions = rowService.get({
|
||||
tableName: '_roles_permissions',
|
||||
whereString: `WHERE role_id IN (${roleIds.map(() => '?')})`,
|
||||
whereStringValues: [...roleIds],
|
||||
});
|
||||
}
|
||||
|
||||
const newPayload = {
|
||||
username: user.username,
|
||||
userId: user.id,
|
||||
isSuperuser: user.is_superuser,
|
||||
roleIds,
|
||||
permissions,
|
||||
};
|
||||
|
||||
// generate an access token
|
||||
const accessToken = await generateToken(
|
||||
{ subject: 'accessToken', ...newPaylod },
|
||||
config.jwtSecret,
|
||||
'1H',
|
||||
{ subject: 'accessToken', ...newPayload },
|
||||
config.accessTokenSecret,
|
||||
config.accessTokenExpirationTime,
|
||||
);
|
||||
|
||||
// generate a refresh token
|
||||
const refreshToken = await generateToken(
|
||||
{ subject: 'refreshToken', ...newPaylod },
|
||||
config.jwtSecret,
|
||||
config.jwtExpirationTime,
|
||||
{ subject: 'refreshToken', ...newPayload },
|
||||
config.refreshTokenSecret,
|
||||
config.refreshTokenExpirationTime,
|
||||
);
|
||||
|
||||
// set the token in the cookie
|
||||
@@ -475,13 +507,12 @@ const createInitialUser = async () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createDefaultTables,
|
||||
updateUser,
|
||||
updateSuperuser,
|
||||
registerUser,
|
||||
obtainAccessToken,
|
||||
refreshAccessToken,
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows should return a list of all rows', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -39,7 +39,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows?_limit=8&_schema=firstName,lastName&_ordering:-firstName&_page=2: should query the rows by the provided query params', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -80,7 +80,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows: should return a null field', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -96,7 +96,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows: should successfully retrieve users created after 2010-01-01 00:00:00.', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -121,7 +121,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows: should successfully retrieve users created before 2008-01-20 00:00:00.', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -146,7 +146,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows: should successfully retrieve users created at 2013-01-08 00:00:00', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -171,7 +171,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows: should successfully retrieve users created at 2007-01-08 00:00:00', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -188,7 +188,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows: should successfully retrieve users that are not created at 2021-01-08 00:00:00', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -213,7 +213,7 @@ describe('Rows Endpoints', () => {
|
||||
it('POST /tables/:name/rows should insert a new row and return the lastInsertRowid', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -230,7 +230,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows/:pks should return a row by its primary key', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -249,7 +249,7 @@ describe('Rows Endpoints', () => {
|
||||
it('PUT /tables/:name/rows/:pks should update a row by its primary key and return the number of changes', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
const res = await requestWithSupertest
|
||||
@@ -263,7 +263,7 @@ describe('Rows Endpoints', () => {
|
||||
it('DELETE /tables/:name/rows/:pks should delete a row by its primary key and return the number of changes', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -277,7 +277,7 @@ describe('Rows Endpoints', () => {
|
||||
it('POST /tables/:name/rows should insert a new row if any of the value of the object being inserted is null', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
const res = await requestWithSupertest
|
||||
@@ -299,7 +299,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows should return values if any of the IDs from the array match the user ID.', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -315,7 +315,7 @@ describe('Rows Endpoints', () => {
|
||||
it('GET /tables/:name/rows should return values if the provided ID matches the user ID.', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('Tables Endpoints', () => {
|
||||
it('GET /tables should return a list of all tables', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('Tables Endpoints', () => {
|
||||
it('POST /tables should create a new table and return generated schema', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('Tables Endpoints', () => {
|
||||
it('GET /tables/:name should return schema of the table', async () => {
|
||||
const accessToken = await generateToken(
|
||||
{ username: 'John', isSuperuser: true },
|
||||
config.jwtSecret,
|
||||
config.accessTokenSecret,
|
||||
'1H',
|
||||
);
|
||||
|
||||
|
||||
21
src/index.js
21
src/index.js
@@ -21,14 +21,12 @@ const swaggerFile = require('./swagger/swagger.json');
|
||||
const { setupExtensions } = require('./extensions');
|
||||
const {
|
||||
createDefaultTables,
|
||||
updateUser,
|
||||
createInitialUser,
|
||||
} = require('./controllers/auth');
|
||||
const { yargs } = require('./cli');
|
||||
|
||||
const { runCLICommands } = require('./commands');
|
||||
|
||||
const app = express();
|
||||
const { argv } = yargs;
|
||||
|
||||
app.get('/health', (req, res) => {
|
||||
res.send('OK');
|
||||
});
|
||||
@@ -91,19 +89,8 @@ if (config.auth) {
|
||||
);
|
||||
}
|
||||
|
||||
//If the updateuser command is passed from the CLI execute the updateuser function
|
||||
if (argv._.includes('updateuser')) {
|
||||
const { id, password, is_superuser } = argv;
|
||||
|
||||
if (!password && !is_superuser) {
|
||||
console.log(
|
||||
'Please provide either the --password or --is_superuser flag when using the updateuser command.',
|
||||
);
|
||||
process.exit(1);
|
||||
} else {
|
||||
updateUser({ id, password, is_superuser });
|
||||
}
|
||||
}
|
||||
// If the user has passed custom CLI commands run the command and exit to avoid running the server
|
||||
runCLICommands();
|
||||
|
||||
app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerFile));
|
||||
app.use('/api', rootRoutes);
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
const config = require('../config');
|
||||
const { registerUser } = require('../controllers/auth');
|
||||
const { apiConstants } = require('../constants/');
|
||||
|
||||
const processRequest = async (req, res, next) => {
|
||||
const resource = req.params.name;
|
||||
const method = req.method;
|
||||
|
||||
// If the user sends a request when auth is set to false, throw an error
|
||||
if (apiConstants.defaultRoutes.includes(resource) && !config.auth) {
|
||||
return res.status(401).send({
|
||||
message: 'You can not access this endpoint while AUTH is set to false',
|
||||
});
|
||||
}
|
||||
|
||||
// Execute user registration function
|
||||
if (resource === '_users' && method === 'POST') {
|
||||
if (resource === '_users' && method === 'POST' && config.auth) {
|
||||
return registerUser(req, res);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@ const isAuthorized = async (req, res, next) => {
|
||||
if (config.auth) {
|
||||
// extract the payload from the token and verify it
|
||||
try {
|
||||
payload = await decodeToken(req.cookies.accessToken, config.jwtSecret);
|
||||
payload = await decodeToken(
|
||||
req.cookies.accessToken,
|
||||
config.accessTokenSecret,
|
||||
);
|
||||
req.user = payload;
|
||||
} catch (error) {
|
||||
return res.status(403).send({ message: 'Invalid access token' });
|
||||
@@ -59,6 +62,7 @@ const isAuthorized = async (req, res, next) => {
|
||||
next();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(401).send({ message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ const dropTestDatabase = async (path = 'test.db') => {
|
||||
|
||||
if (fs.existsSync(path + '-wal')) {
|
||||
try {
|
||||
await Promise.allSettled(unlink(path + '-wal'), unlink(path + '-shm'));
|
||||
await Promise.allSettled([unlink(path + '-wal'), unlink(path + '-shm')]);
|
||||
} catch (error) {
|
||||
console.error('there was an error:', error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user