An open API service indexing awesome lists of open source software.

https://github.com/solvro/backend-topwr


https://github.com/solvro/backend-topwr

adonis api backend pwr rest student students wust

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

          

# ToPWR Backend

![Solvro banner](https://github.com/Solvro/backend-topwr-sks/blob/main/assets/solvro_dark.png#gh-dark-mode-only)
![Solvro banner](https://github.com/Solvro/backend-topwr-sks/blob/main/assets/solvro_dark.png#gh-light-mode-only)

## API Documentation

### Disclaimer

Documentation and API are in WiP stage

Some endpoints require authentication.
To authenticate, first generate a token using the `POST /api/v1/auth/login` endpoint.
Then pass the received token via the `Authorization` header as a `Bearer` token. (`Authorization: Bearer `)

### Endpoints

#### Custom controllers

The following controllers were implemented manually and contain custom endpoints that might function differently to autogenerated controllers.

##### Files

- **GET /api/v1/files/:key**
- Returns metadata for a given file
- Response: serialized `FileEntry` instnace
- **POST /api/v1/files**
- **Requres authentication**
- Uploads a new file to the server
- Requires a multipart request body
- File must be uploaded in a field called `file`
- Response: `{ "key": "" }`

##### About Us

- **GET /api/v1/about_us**
- Returns "about us" data
- Response: `{ "data": { "aboutUs": AboutUsGeneral, "solvroSocialLinks": AboutUsGeneralLink[] } }`
- the AboutUsGeneral object has the `coverPhoto` relation automatically included

##### Authentication

- **POST /api/v1/auth/login**
- Requires a json request body: `{ "email": string, "password": string, "rememberMe"?: boolean }`
- technically you can also pass these with query parameters, but please don't
- Creates and returns a new token for the specified user, if the credentials are correct
- the token is valid for **30 days** if `rememberMe` = true, **1 day** otherwise.
- Response: `{ "user": User, "token": "" }`
- **GET /api/v1/auth/me**
- **Requires authentication**
- Returns your user object
- Response: serialized `User` instance
- **POST /api/v1/auth/logout**
- **Requires authentication**
- Invalidates the current token
- Response: `{ "success": true, "message": "Logged out" }`

##### Newsfeed

- **GET /api/v1/newsfeed/latest**
- Returns the first page of university news items
- Accepts optional query parameters:
- `completeOnly` - boolean, defaults to `true`, only includes fully scraped news items (with no missing fields)
- `lang` - enum: `pl`, `en`; defaults to `pl`, selects the newsfeed's language, languages contain different news items
- Response: `{ "articles": { "url": string, "imageLink": string, "title": string, "previewText": string, "date": string, "categories": string[] }[], "updateTime": string }`
- **GET /api/v1/newsfeed/stats**
- Returns stats about the scraped news items
- includes count of articles scraped and the last update timestamp
- Response: `Partial>`

#### Autogenerated controllers

Most other models get an autogenerated controller with multiple standard endpoints.
All names in paths are in `snake_case`.

- **GET /api/v1/:model**
- Lists all available objects of a requested type
- Supports pagination, on-demand recursive relations, filtering and sorting (see below)
- Response: `{ "meta": , "data": Model[] }`
- **GET /api/v1/:model/:id**
- Returns the requested object
- Supports on-demand recursive relations
- Response: `{ "data": Model }`
- **POST /api/v1/:model**
- **Requres authentication**
- Creates the requested object
- Requires a json request body with the object to create (full model)
- Response: `{ "success": true, "data": Model }`
- **PATCH /api/v1/:model/:id**
- **Requres authentication**
- Updates the requested object
- Requires a json request body with the changes to apply (partial model)
- Response: `{ "success": true, "data": Model }`
- **DELETE /api/v1/:model/:id**
- **Requres authentication**
- Deletes the requested object
- Response: `{ "success": true }`
- **GET /api/v1/:model/:id/:crudRelation**
- Lists all objects associated with the requested object (`id`) via the specified relation (`crudRelation`)
- Supports pagination, on-demand recursive relations (relative to the requested relation), filtering and sorting
- Response: `{ "meta": , "data": RelatedModel[] }`
- **POST /api/v1/:model/:id/:crudRelation**
- **Requires authentication**
- **Only applies to 1:n relations (hasMany)**
- Creates a new object (from json body) associated with the requested object (`id`) via the specified relation (`crudRelation`)
- Requires a json request body with the object to create (full model, -fk)
- Response: `{ "success": true, "data": RelatedModel }`
- **POST /api/v1/:model/:mainId/:crudRelation/:relatedId**
- **Requires authentication**
- **Only applies to n:m relations (manyToMany)**
- Attaches an existing object (`relatedId`) to the requested object (`mainId`) via the specified relation (`crudRelation`)
- Requires a json request body with any non-autoGenerated pivot fields.
- Response: `{ "success": true }`
- **DELETE /api/v1/:model/:mainId/:crudRelation/:relatedId**
- **Requires authentication**
- **Only applies to n:m relations (manyToMany)**
- Removes the relation (`crudRelation`) between the related object (`relatedId`) and the requested object (`mainId`)
- If the related object is attached multiple times, all attachments are removed by default
- Pivot properties marked as `detachFilter: true` can be specified via query params or json body as filters to limit which attachments are removed
- Response: `{ "success": true, "numDetached": }`

##### What model properties can I send?

To find out what properties are allowed for each model in json bodies, see the respective model definition files. (in `/app/models`)

All endpoints that require a model in the json body recognize all column fields that aren't considered `autoGenerated`.
A field is considered `autoGenerated` if:

- it is explicitly marked as `autoGenerated: true`, or
- it is makred as `isPrimary: true`, `autoCreate: true` or `autoUpdate: true`, and is NOT marked as `autoGenerated: false`.

Additionally, endpoints marked with _`-fk`_ ignore the corresponding foreign key of the requested relation.
This field will be automatically set to the primary key of the main object. (`mainId`)

Endpoints marked with _full model_ require that you send ALL recognized column fields that aren't marked with `optional: true`.

Endpoints marked with _partial model_ consider all fields to be optional.

##### What relations can I request?

To find out which relations are valid for each controller, see that controller's definition file. (in `/app/controllers`)

For on-demand recursive relations, look at the `queryRelations` array.

For relations specified as a path variable, look at the `crudRelations` array.

##### How does pagination work?

All autogenerated enpoints are **not** paginated by default - pagination must be explicitly requested.

To request pagination on a supported endpoint, set the `page` query parameter to a positive integer.
By default, a page size of `10` is used. Set the `limit` query parameter to set a custom page size.

When pagination is requested, pagination metadata will be returned in the `meta` field.
This field will include information such as:

- `total` - the total record count
- `lastPage` - the total number of pages

For example, to request the `5`th page of buildings, with `15` buildings per page:

`GET https://api.topwr.solvro.pl/api/v1/buildings?page=5&limit=15`

##### How do on-demand relations work?

Some autogenerated endpoints support on-demand recursive relations.
These allow you to fetch related objects along with the main object, in a single API request.

To request a relation, set its name to `true` in the query parameters.
Recursive relation chains contain `.` in their names.
If you request a relation chain, any relations along the way will be requested and returned as well.

Arrays of related objects will be attached to a property with the relation's name.

Example:

- Request: `GET https://api.topwr.solvro.pl/api/v1/campuses/1?buildings.aeds=true`
- Response:
```json
{
"id": 1,
...campus properties...,
"buildings": [
{
"id": ...,
"campusId": 1,
...building properties...,
"aeds": [
{
"id": ...,
"buildingId": 1,
...aed properties...
}
]
},
...more buildings...
]
}
```

##### How do I request custom sorting?

To request the response to be sorted by a specified key, add a `sort` query parameter.

To sort in ascending order, use `+`.
To sort in descending order, use `-`.

For example, to sort campuses by `name`, in ascending order, send the following request:

`GET https://api.topwr.solvro.pl/api/v1/campuses?sort=+name`

##### How does filtering work?

To request filtering, pass property names & predicates as query parameter keys and values.
Property names should use the same casing as in model definition files. (camelCase)

For strings properties, the values are matched against the predicates using `ILIKE` - this means the filtering is **case insensitive**, and **`%` can be used as a wildcard**.
Other types of properties are matched using direct equality.

Examples:

- get all fields of study that belong to department number six:

`GET https://api.topwr.solvro.pl/api/v1/fields_of_study?departmentId=6`
- get all contributors' youtube links:

`GET https://api.topwr.solvro.pl/api/v1/contributor_social_links?linkType=youtu`
- get all campuses whose names end with `a`:

`GET https://api.topwr.solro.pl/api/v1/campuses?name=%a`

Any numeric or date-time field can be filtered by range. Pass the following query params to filter by range:

- for lower bound of greater or equal to value: `.from=`
- for upper bound of lesser or equal to value: `.to=`
- for both lower and upper bound, pass both params separately (that is: `.from=&.to=`)

You can pass both `from` lower bound and `to` upper bound or only one of them.
If `from` is equal to `to`, the filter works exactly like the single value filter (in other words: `departmentId.from=1&departmentId.to=1` is equal to `departmentId=1`).

Example of a correctly formed request:
Goal: Fields of study belonging to departments with ids ranging from two to four, both ends inclusive
Request: `GET https://api.topwr.solvro.pl/api/v1/fields_of_study?departmentId.from=2&departmentId.to=4`

### Errors

Any errors will be indicated by a status code from the `4xx` or `5xx` range.
`4xx` errors are caused by invalid or incomplete requests, while `5xx` errors are server errors.

All error responses follow a standardised format, defined and documented in-depth in [/app/exceptions/base_error.ts](https://github.com/Solvro/backend-topwr/blob/2630637842b4ca61d6fc215b5eb90ebee2e8a37a/app/exceptions/base_error.ts#L369-L408)

## Links

[![docs.solvro.pl](https://i.imgur.com/fuV0gra.png)](https://docs.solvro.pl)