Merge pull request #163 from thevahidal/feature_swagger_documentation

Feature swagger documentation
This commit is contained in:
Ian Mayo
2024-03-11 10:33:42 +00:00
committed by GitHub
3 changed files with 438 additions and 22 deletions

View File

@@ -162,6 +162,19 @@ const updateSuperuser = async (fields) => {
};
const registerUser = async (req, res) => {
/*
#swagger.tags = ['Auth']
#swagger.summary = 'Register User'
#swagger.description = 'Endpoint to signup'
#swagger.parameters['username'] = {
in: 'body',
required: true,
type: 'object',
schema: { $ref: '#/definitions/UserRegistrationRequestBody' }
}
*/
const { username, password } = req.body.fields;
try {
@@ -182,6 +195,15 @@ const registerUser = async (req, res) => {
if (user.length > 0) {
return res.status(409).send({ message: 'This username is taken' });
/*
#swagger.responses[409] = {
description: 'Username taken error',
schema: {
$ref: '#/definitions/UsernameTakenErrorResponse'
}
}
*/
}
// check if the password is weak
@@ -193,6 +215,15 @@ const registerUser = async (req, res) => {
return res.status(400).send({
message: 'This password is weak, please use another password',
});
/*
#swagger.responses[400] = {
description: 'Weak password error',
schema: {
$ref: '#/definitions/WeakPasswordErrorResponse'
}
}
*/
}
// hash the password
@@ -220,6 +251,14 @@ const registerUser = async (req, res) => {
return res.status(500).send({
message: 'Please restart soul so a default role can be created',
});
/*
#swagger.responses[500] = {
description: 'Server error',
schema: {
$ref: '#/definitions/DefaultRoleNotCreatedErrorResponse'
}
}
*/
}
// create a role for the user
@@ -229,6 +268,15 @@ const registerUser = async (req, res) => {
});
res.status(201).send({ message: 'Row Inserted' });
/*
#swagger.responses[201] = {
description: 'Row inserted',
schema: {
$ref: '#/definitions/InsertRowSuccessResponse'
}
}
*/
} catch (error) {
console.log(error);
res.status(500).send({ message: error.message });
@@ -236,6 +284,19 @@ const registerUser = async (req, res) => {
};
const obtainAccessToken = async (req, res) => {
/*
#swagger.tags = ['Auth']
#swagger.summary = 'Obtain Access Token'
#swagger.description = 'Endpoint to generate access and refresh tokens'
#swagger.parameters['body'] = {
in: 'body',
required: true,
type: 'object',
schema: { $ref: '#/definitions/ObtainAccessTokenRequestBody' }
}
*/
// extract payload
const { username, password } = req.body.fields;
@@ -257,6 +318,14 @@ const obtainAccessToken = async (req, res) => {
if (!isMatch) {
return res.status(401).send({ message: 'Invalid username or password' });
/*
#swagger.responses[401] = {
description: 'Invalid username or password error',
schema: {
$ref: '#/definitions/InvalidCredentialErrorResponse'
}
}
*/
}
let userRoles, permissions, roleIds;
@@ -313,6 +382,15 @@ const obtainAccessToken = async (req, res) => {
res.cookie('refreshToken', refreshToken, cookieOptions);
res.status(201).send({ message: 'Success', data: { userId: user.id } });
/*
#swagger.responses[201] = {
description: 'Access token and Refresh token generated',
schema: {
$ref: '#/definitions/ObtainAccessTokenSuccessResponse'
}
}
*/
} catch (error) {
console.log(error);
return res.status(500).json({
@@ -323,6 +401,12 @@ const obtainAccessToken = async (req, res) => {
};
const refreshAccessToken = async (req, res) => {
/*
#swagger.tags = ['Auth']
#swagger.summary = 'Refresh Access Token'
#swagger.description = 'Endpoint to refresh access and refresh tokens'
*/
try {
// extract the payload from the token and verify it
const payload = await decodeToken(
@@ -341,6 +425,15 @@ const refreshAccessToken = async (req, res) => {
return res
.status(401)
.send({ message: `User with userId = ${payload.userId} not found` });
/*
#swagger.responses[401] = {
description: 'User not found error',
schema: {
$ref: '#/definitions/UserNotFoundErrorResponse'
}
}
*/
}
let userRoles, permissions, roleIds;
@@ -392,12 +485,44 @@ const refreshAccessToken = async (req, res) => {
res.cookie('refreshToken', refreshToken, cookieOptions);
res.status(200).send({ message: 'Success', data: { userId: user.id } });
/*
#swagger.responses[200] = {
description: 'Access token refreshed',
schema: {
$ref: '#/definitions/RefreshAccessTokenSuccessResponse'
}
}
*/
} catch (error) {
res.status(403).send({ message: 'Invalid refresh token' });
/*
#swagger.responses[401] = {
description: 'Invalid refresh token error',
schema: {
$ref: '#/definitions/InvalidRefreshTokenErrorResponse'
}
}
*/
}
};
const changePassword = async (req, res) => {
/*
#swagger.tags = ['Auth']
#swagger.summary = 'Change Password'
#swagger.description = 'Endpoint to change a password'
#swagger.parameters['body'] = {
in: 'body',
required: true,
type: 'object',
schema: {
$ref: '#/definitions/ChangePasswordRequestBody'
}
}
*/
const userInfo = req.user;
const { currentPassword, newPassword } = req.body.fields;
@@ -423,6 +548,14 @@ const changePassword = async (req, res) => {
if (!isMatch) {
return res.status(401).send({ message: 'Invalid current password' });
/*
#swagger.responses[401] = {
description: 'User not found error',
schema: {
$ref: '#/definitions/InvalidPasswordErrorResponse'
}
}
*/
}
// check if the new password is strong
@@ -434,6 +567,15 @@ const changePassword = async (req, res) => {
return res.status(400).send({
message: 'This password is weak, please use another password',
});
/*
#swagger.responses[400] = {
description: 'Weak password error',
schema: {
$ref: '#/definitions/WeakPasswordErrorResponse'
}
}
*/
}
// hash the password
@@ -454,6 +596,15 @@ const changePassword = async (req, res) => {
message: 'Password updated successfully',
data: { id: user.id, username: user.username },
});
/*
#swagger.responses[200] = {
description: 'Weak password error',
schema: {
$ref: '#/definitions/ChangePasswordSuccessResponse'
}
}
*/
} catch (error) {
res.status(500).send({ message: error.message });
}

View File

@@ -31,6 +31,10 @@ const doc = {
name: 'Rows',
description: 'Rows endpoints',
},
{
name: 'Auth',
description: 'Auth endpoints',
},
],
securityDefinitions: {},
definitions: {
@@ -122,6 +126,69 @@ const doc = {
TransactionRequestBody: {
$ref: '#/definitions/Transaction',
},
ObtainAccessTokenRequestBody: {
fields: {
username: '@john',
password: 'Ak22#cPM33@v*#',
},
},
ObtainAccessTokenSuccessResponse: {
message: 'Success',
data: {
userId: 1,
},
},
InvalidCredentialErrorResponse: {
message: 'Invalid username or password',
},
UserRegisterationRequestBody: {
fields: {
username: '@john',
password: 'Ak22#cPM33@v*#',
},
},
WeakPasswordErrorResponse: {
message: 'This password is weak, please use another password',
},
UsernameTakenErrorResponse: {
message: 'This username is taken',
},
DefaultRoleNotCreatedErrorResponse: {
message: 'Please restart soul so a default role can be created',
},
UserNotFoundErrorResponse: {
message: 'User not found',
},
InvalidRefreshTokenErrorResponse: {
message: 'Invalid refresh token',
},
ChangePasswordRequestBody: {
fields: {
currentPassword: 'Ak22#cPM33@v*#',
newPassword: 'hKB33o@3245CD$',
},
},
ChangePasswordSuccessResponse: {
message: 'Password updated successfully',
data: { id: 1, username: '@john' },
},
RefreshAccessTokenSuccessResponse: {
message: 'Success',
data: { userId: 1 },
},
InvalidPasswordErrorResponse: { message: 'Invalid password' },
},
};

View File

@@ -19,6 +19,10 @@
{
"name": "Rows",
"description": "Rows endpoints"
},
{
"name": "Auth",
"description": "Auth endpoints"
}
],
"schemes": ["http", "https"],
@@ -504,30 +508,34 @@
},
"/api/auth/token/obtain": {
"post": {
"description": "",
"tags": ["Auth"],
"summary": "Obtain Access Token",
"description": "Endpoint to generate access and refresh tokens",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"type": "object",
"properties": {
"fields": {
"example": "any"
}
}
"$ref": "#/definitions/ObtainAccessTokenRequestBody"
}
}
],
"responses": {
"201": {
"description": "Created"
"description": "Access token and Refresh token generated",
"schema": {
"$ref": "#/definitions/ObtainAccessTokenSuccessResponse"
}
},
"400": {
"description": "Bad Request"
},
"401": {
"description": "Unauthorized"
"description": "Invalid username or password error",
"schema": {
"$ref": "#/definitions/InvalidCredentialErrorResponse"
}
},
"404": {
"description": "Not Found"
@@ -540,17 +548,25 @@
},
"/api/auth/token/refresh": {
"get": {
"description": "",
"tags": ["Auth"],
"summary": "Refresh Access Token",
"description": "Endpoint to refresh access and refresh tokens",
"parameters": [],
"responses": {
"200": {
"description": "OK"
"description": "Access token refreshed",
"schema": {
"$ref": "#/definitions/RefreshAccessTokenSuccessResponse"
}
},
"400": {
"description": "Bad Request"
},
"401": {
"description": "Unauthorized"
"description": "Invalid refresh token error",
"schema": {
"$ref": "#/definitions/InvalidRefreshTokenErrorResponse"
}
},
"403": {
"description": "Forbidden"
@@ -560,30 +576,37 @@
},
"/api/auth/change-password": {
"put": {
"description": "",
"tags": ["Auth"],
"summary": "Change Password",
"description": "Endpoint to change a password",
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"type": "object",
"properties": {
"fields": {
"example": "any"
}
}
"$ref": "#/definitions/ChangePasswordRequestBody"
}
}
],
"responses": {
"200": {
"description": "OK"
"description": "Weak password error",
"schema": {
"$ref": "#/definitions/ChangePasswordSuccessResponse"
}
},
"400": {
"description": "Bad Request"
"description": "Weak password error",
"schema": {
"$ref": "#/definitions/WeakPasswordErrorResponse"
}
},
"401": {
"description": "Unauthorized"
"description": "User not found error",
"schema": {
"$ref": "#/definitions/InvalidPasswordErrorResponse"
}
},
"403": {
"description": "Forbidden"
@@ -868,6 +891,181 @@
},
"TransactionRequestBody": {
"$ref": "#/definitions/Transaction"
},
"ObtainAccessTokenRequestBody": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"properties": {
"username": {
"type": "string",
"example": "@john"
},
"password": {
"type": "string",
"example": "Ak22#cPM33@v*#"
}
}
}
}
},
"ObtainAccessTokenSuccessResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Success"
},
"data": {
"type": "object",
"properties": {
"userId": {
"type": "number",
"example": 1
}
}
}
}
},
"InvalidCredentialErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Invalid username or password"
}
}
},
"UserRegisterationRequestBody": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"properties": {
"username": {
"type": "string",
"example": "@john"
},
"password": {
"type": "string",
"example": "Ak22#cPM33@v*#"
}
}
}
}
},
"WeakPasswordErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "This password is weak, please use another password"
}
}
},
"UsernameTakenErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "This username is taken"
}
}
},
"DefaultRoleNotCreatedErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Please restart soul so a default role can be created"
}
}
},
"UserNotFoundErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "User not found"
}
}
},
"InvalidRefreshTokenErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Invalid refresh token"
}
}
},
"ChangePasswordRequestBody": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"properties": {
"currentPassword": {
"type": "string",
"example": "Ak22#cPM33@v*#"
},
"newPassword": {
"type": "string",
"example": "hKB33o@3245CD$"
}
}
}
}
},
"ChangePasswordSuccessResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Password updated successfully"
},
"data": {
"type": "object",
"properties": {
"id": {
"type": "number",
"example": 1
},
"username": {
"type": "string",
"example": "@john"
}
}
}
}
},
"RefreshAccessTokenSuccessResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Success"
},
"data": {
"type": "object",
"properties": {
"userId": {
"type": "number",
"example": 1
}
}
}
}
},
"InvalidPasswordErrorResponse": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "Invalid password"
}
}
}
}
}