go-exercises-backend, v1.6
Posted on

Back-end of the service for solving programming exercises.
Support for disabling access to specific users.
Change Log
- authentication:
- user model:
- storing:
- flag indicating whether the user is disabled or not.
- storing:
- user model:
Features
- RESTful API:
- models:
- task model:
- storing:
- author ID;
- title;
- description;
- boilerplate code;
- test cases:
- all test cases are represented by a single string;
- operations:
- getting all tasks:
- calculate a total correctness flag based on all solutions of a requesting author;
- sort the results by creation time in descending order;
- process pagination:
- implemented using an offset and a limit;
- getting a single task by an ID:
- calculate a total correctness flag based on all solutions of a requesting author;
- creating:
- automatically format a task boilerplate code;
- updating by an ID:
- allowed for its author only;
- automatically format a task boilerplate code;
- deleting by an ID:
- allowed for its author only;
- getting all tasks:
- storing:
- solution model:
- storing:
- author ID;
- task ID;
- code;
- correctness flag;
- testing result:
- represented by a string;
- operations:
- getting all solutions by a task ID:
- filtered by a requesting author:
- allow a solution task author to get solutions of other authors;
- sort the results by creation time in descending order;
- process pagination:
- implemented using an offset and a limit;
- filtered by a requesting author:
- getting a single solution by an ID:
- allowed for:
- solution author;
- solution task author;
- allowed for:
- creating:
- automatically format a solution code;
- updating by an ID:
- performed by a queue consumer only (see below);
- formatting a solution code;
- getting all solutions by a task ID:
- storing:
- task model:
- representing:
- in a JSON:
- payloads:
- of requests;
- of responses;
- payloads:
- as a plain text:
- errors;
- in a JSON:
- models:
- server:
- additional routing:
- serving static files;
- storing settings in environment variables;
- supporting graceful shutdown;
- logging:
- logging requests;
- logging errors;
- panics:
- recovering on panics;
- logging of panics;
- additional routing:
- authentication:
- use the Bearer authentication scheme based on JSON Web Tokens:
- store in a JWT claims:
- expiration time claim;
- user claim:
- contains a whole user model;
- store in a JWT claims:
- generate a token signing key automatically by default;
- user model:
- storing:
- username (unique);
- password hash:
- generated using the bcrypt function;
- flag indicating whether the user is disabled or not;
- storing:
- use the Bearer authentication scheme based on JSON Web Tokens:
- databases:
- storing data in the PostgreSQL database;
- interaction with queues:
- using the RabbitMQ message broker;
- common properties:
- automatic declaring of the used queues;
- passing of a message data in JSON;
- operations:
- producing solutions:
- concurrent producing;
- consuming solution results:
- concurrent consuming;
- once requeue the solution on failure;
- producing solutions:
- utilities:
- utility for managing users:
- commands:
- add a user:
- parameters:
- username;
- password:
- generate automatically by default;
- password hashing cost;
- generated password length;
- parameters:
- add a user:
- commands:
- utility for managing users:
- distributing:
- Docker image;
- Docker Compose configuration.
API Description
Web API description in the Swagger format:
swagger: "2.0"
info:
title: go-exercises-backend API
version: "1.6"
license:
name: MIT
host: localhost:8080
basePath: /api/v1
paths:
/solutions/{id}:
get:
parameters:
- description: solution ID
in: path
minimum: 1
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: "#/definitions/entities.Solution"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Solution
/solutions/format:
post:
consumes:
- application/json
parameters:
- description: solution data
in: body
name: data
required: true
schema:
$ref: "#/definitions/entities.Solution"
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: "#/definitions/entities.Solution"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Solution
/tasks/:
get:
parameters:
- description: page size
in: query
minimum: 1
name: pageSize
required: true
type: integer
- description: page
in: query
minimum: 1
name: page
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: "#/definitions/entities.TaskGroup"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Task
post:
consumes:
- application/json
parameters:
- description: task data
in: body
name: data
required: true
schema:
$ref: "#/definitions/entities.Task"
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: "#/definitions/entities.Task"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Task
/tasks/{id}:
delete:
parameters:
- description: task ID
in: path
minimum: 1
name: id
required: true
type: integer
produces:
- text/plain
responses:
"204":
description: No Content
schema:
type: string
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Task
get:
parameters:
- description: task ID
in: path
minimum: 1
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: "#/definitions/entities.Task"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Task
put:
consumes:
- application/json
parameters:
- description: task ID
in: path
minimum: 1
name: id
required: true
type: integer
- description: task data
in: body
name: data
required: true
schema:
$ref: "#/definitions/entities.Task"
produces:
- text/plain
responses:
"204":
description: No Content
schema:
type: string
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Task
/tasks/{taskID}/solutions/:
get:
parameters:
- description: task ID
in: path
minimum: 1
name: taskID
required: true
type: integer
- description: page size
in: query
minimum: 1
name: pageSize
required: true
type: integer
- description: page
in: query
minimum: 1
name: page
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: "#/definitions/entities.SolutionGroup"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Solution
post:
consumes:
- application/json
parameters:
- description: task ID
in: path
minimum: 1
name: taskID
required: true
type: integer
- description: solution data
in: body
name: data
required: true
schema:
$ref: "#/definitions/entities.Solution"
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: "#/definitions/entities.Solution"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- JWTAuthorization: []
tags:
- Solution
/tokens/:
post:
consumes:
- application/json
parameters:
- description: user data
in: body
name: data
required: true
schema:
$ref: "#/definitions/entities.User"
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: "#/definitions/entities.Credentials"
"400":
description: Bad Request
schema:
type: string
"401":
description: Unauthorized
schema:
type: string
"403":
description: Forbidden
schema:
type: string
"404":
description: Not Found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
tags:
- Token
definitions:
gorm.DeletedAt:
type: object
properties:
Time:
type: string
Valid:
type: boolean
description: Valid is true if Time is not NULL
entities.Task:
type: object
properties:
ID:
type: integer
CreatedAt:
type: string
UpdatedAt:
type: string
DeletedAt:
$ref: "#/definitions/gorm.DeletedAt"
UserID:
type: integer
minimum: 1
User:
$ref: "#/definitions/entities.User"
Title:
type: string
Description:
type: string
BoilerplateCode:
type: string
TestCases:
type: object
Status:
type: integer
enum:
- 0
- 1
- 2
entities.TaskGroup:
type: object
properties:
Tasks:
type: array
items:
$ref: "#/definitions/entities.Task"
TotalCount:
type: integer
minimum: 0
entities.Solution:
type: object
properties:
ID:
type: integer
CreatedAt:
type: string
UpdatedAt:
type: string
DeletedAt:
$ref: "#/definitions/gorm.DeletedAt"
UserID:
type: integer
minimum: 1
User:
$ref: "#/definitions/entities.User"
TaskID:
type: integer
minimum: 1
Task:
$ref: "#/definitions/entities.Task"
Code:
type: string
IsCorrect:
type: boolean
Result:
type: object
entities.SolutionGroup:
type: object
properties:
Solutions:
type: array
items:
$ref: "#/definitions/entities.Solution"
TotalCount:
type: integer
minimum: 0
entities.User:
type: object
properties:
ID:
type: integer
CreatedAt:
type: string
UpdatedAt:
type: string
DeletedAt:
$ref: "#/definitions/gorm.DeletedAt"
Username:
type: string
Password:
type: string
PasswordHash:
type: string
IsDisabled:
type: boolean
entities.Credentials:
type: object
properties:
AccessToken:
type: string
securityDefinitions:
JWTAuthorization:
type: apiKey
name: Authorization
in: header
Repository
Link: https://github.com/thewizardplusplus/go-exercises-backend/tree/v1.6.
Content: code.
License: MIT.