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
- Host: GitHub
- URL: https://github.com/solvro/backend-topwr
- Owner: Solvro
- License: agpl-3.0
- Created: 2024-11-13T18:36:47.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2024-12-16T08:29:04.000Z (10 months ago)
- Last Synced: 2024-12-16T09:20:51.367Z (10 months ago)
- Topics: adonis, api, backend, pwr, rest, student, students, wust
- Language: TypeScript
- Homepage:
- Size: 1.28 MB
- Stars: 17
- Watchers: 1
- Forks: 0
- Open Issues: 16
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ToPWR Backend

## 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 pagesFor 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
[](https://docs.solvro.pl)