Skip to content

Server Side

Mihály Dobos-Kovács edited this page Nov 25, 2020 · 1 revision

This page contains the documentation of the Server side component.

General overview

The server side component is a Spring server implemented in Java. It requires a database connection, and a GRPC connection to the native component, and provides a REST api through HTTP for consumption.

Architecture

The server side consists of three layers:

  • Data access layer
  • Business logic
  • Controller layer

Data access layer

The data layer is implemented using Hibernate, JPA and Spring Data. It provides access to the database using an entity-relation model defined in the code via JPA entities. The entities are accessed through Spring Repositories.

Business logic

The task of this layer is to provide business logic for the application. The layer is implemented via Spring services and provides additional security related functionalities such as authentication, authorization and logging.

The business layer consists of several subcomponents, closely connected to the dataflow map of the application:

  • Authentication component
  • Authorization component
  • User management component
  • CAFF management component
  • Email service component
  • Logging component

Controller layer

The layer is responsible for mapping the REST API calls to Java methods, and mapping the responses to REST. This layer is implemented using Spring's RestControllers.

REST API

This chapter documents the REST API endpoints of the application. Generally speaking, the API receives its parameters with multipart/form-data encoding, and returns its result as application/json.

The endpoints marked with [AUTH] require authentication before they can be called. The authentication token must be always passed in the Authorization header as a bearer token.

The API calls return the following:

  • The API returns status code 200 if the API call was successful.
  • If the caller was not authorized to make that operation, the API call return with status 401.
  • Should there be a client error (such as validation, etc...), the call returns with status code 400, and the following body:
    {
      "errorCode": "string",
      "errorMessage": "string"
    }
    The errorCode is a code unique to the error, while errorMessage is a textual message of the error.
  • Upon internal, unrecognised error, the server yield status code 500.

Authentication

  • POST /auth/login: Logs the user in with username or email and a password. Returns information about the user, and the corresponding token. Parameters:

    • email
    • username
    • password

    Returns:

    {
      "roles": [
        "string"
      ],
      "token": "string",
      "username": "string"
    }
  • POST /auth/register: Registers a user, and logs it in. Returns information about the user, and the corresponding token. Parameters:

    • email
    • username
    • password

    Returns:

    {
      "roles": [
        "string"
      ],
      "token": "string",
      "username": "string"
    }
  • POST /auth/passwordReset: Resets the password of a user. Upon reset, the user will receive a new, temporary password in email. Parameters:

    • email
    • username
  • POST /auth/logout [AUTH]: Logs the user out.

User management

  • GET /user [AUTH]: Returns the list of users paginated. Parameters:

    • offset: The 0 indexed page number.
    • pageSize: The size of the page.

    Returns:

    {
      "offset": 0,
      "pageSize": 0,
      "totalCount": 0,
      "users": [
        {
          "email": "string",
          "id": "string",
          "username": "string"
        }
      ]
    }
  • POST /user [AUTH]: Creates a new user. Parameters:

    • email
    • username
    • password

    Returns:

    {
      "email": "string",
      "id": "string",
      "username": "string"
    }
  • GET /user/{id} [AUTH]: Returns the data of the user with the given id.

    Returns:

    {
      "email": "string",
      "id": "string",
      "username": "string"
    }
  • PUT /user/{id} [AUTH]: Modifies the user with the current id. Parameters:

    • email
    • username
    • password

    Returns:

    {
      "email": "string",
      "id": "string",
      "username": "string"
    }
  • DELETE /user/{id} [AUTH]: Deletes the user with the given id.

CAFF management

  • GET /caff [AUTH]: Returns the list of caffs paginated. Parameters:

    • offset: The 0 indexed page number.
    • pageSize: The size of the page.
    • title: Searches for the given title amongst the caffs
    • tag: Searches for the given tag amongst the caffs
    • userId: Searches for the caffs of the given user.

    Returns:

    {
      "caffs": [
        {
          "id": "string",
          "lastModifiedById": "string",
          "lastModifiedByName": "string",
          "lastModifiedDate": "2020-11-25T19:19:54.185Z",
          "ownerId": "string",
          "ownerName": "string",
          "tags": [
            "string"
          ],
          "title": "string"
        }
      ],
      "offset": 0,
      "pageSize": 0,
      "totalCount": 0
    }
  • POST /caff [AUTH]: Creates a new caff. Parameters:

    • title: The title of the caff
    • tags: The tags of the caff textually encoded, the different tags separated with the character |.
    • file: The caff file.

    Returns:

    {
      "id": "string",
      "lastModifiedById": "string",
      "lastModifiedByName": "string",
      "lastModifiedDate": "2020-11-25T19:20:17.428Z",
      "ownerId": "string",
      "ownerName": "string",
      "tags": [
        "string"
      ],
      "title": "string"
    }
  • GET /caff/{id} [AUTH]: Returns the data of the caff with the given id.

    Returns:

    {
      "id": "string",
      "lastModifiedById": "string",
      "lastModifiedByName": "string",
      "lastModifiedDate": "2020-11-25T19:21:33.362Z",
      "ownerId": "string",
      "ownerName": "string",
      "tags": [
        "string"
      ],
      "title": "string"
    }
  • GET /caff/{id}/download [AUTH]: Downloads the caff with the given id.

  • GET /caff/{id}/preview [AUTH]: Returns the preview image of the caff.

  • PUT /caff/{id} [AUTH]: Modifies the caff with the given id. Parameters:

    • title: The title of the caff
    • tags: The tags of the caff textually encoded, the different tags separated with the character |.
    • file: The caff file.

    Returns:

    {
      "id": "string",
      "lastModifiedById": "string",
      "lastModifiedByName": "string",
      "lastModifiedDate": "2020-11-25T19:21:51.645Z",
      "ownerId": "string",
      "ownerName": "string",
      "tags": [
        "string"
      ],
      "title": "string"
    }
  • DELETE /caff/{id} [AUTH]: Deletes the caff with the given id.

  • GET /caff/{id}/comment [AUTH]: Returns the list of comments paginated of the caff with the given id. Parameters:

    • offset: The 0 indexed page number.
    • pageSize: The size of the page.

    Returns:

    {
      "comments": [
        {
          "caffId": "string",
          "content": "string",
          "createdDate": "2020-11-25T19:24:43.522Z",
          "id": "string",
          "lastModifiedById": "string",
          "lastModifiedByName": "string",
          "lastModifiedDate": "2020-11-25T19:24:43.522Z",
          "userId": "string",
          "userName": "string"
        }
      ],
      "offset": 0,
      "pageSize": 0,
      "totalCount": 0
    }
  • POST /caff/{id}/comment [AUTH]: Creates a new comment for the caff with the given id. Parameters:

    • content: The content of the comment

    Returns:

    {
      "caffId": "string",
      "content": "string",
      "createdDate": "2020-11-25T19:25:44.134Z",
      "id": "string",
      "lastModifiedById": "string",
      "lastModifiedByName": "string",
      "lastModifiedDate": "2020-11-25T19:25:44.134Z",
      "userId": "string",
      "userName": "string"
    }
  • GET /caff/{id}/comment/{commentId} [AUTH]: Returns the data of the comment with the given id of caff with the given id.

    Returns:

    {
      "id": "string",
      "lastModifiedById": "string",
      "lastModifiedByName": "string",
      "lastModifiedDate": "2020-11-25T19:21:33.362Z",
      "ownerId": "string",
      "ownerName": "string",
      "tags": [
        "string"
      ],
      "title": "string"
    }
  • PUT /caff/{id}/comment/{commentId} [AUTH]: Modifies the data of the comment with the given id of caff with the given id. Parameters:

    • content: The content of the comment

    Returns:

    {
      "caffId": "string",
      "content": "string",
      "createdDate": "2020-11-25T19:27:10.772Z",
      "id": "string",
      "lastModifiedById": "string",
      "lastModifiedByName": "string",
      "lastModifiedDate": "2020-11-25T19:27:10.772Z",
      "userId": "string",
      "userName": "string"
    }
  • DELETE /caff/{id}/comment/{commentId} [AUTH]: Deletes the data of the comment with the given id of caff with the given id.

Data model

The data model of our application can be seen on the picture below.

The data model consists of the following entities:

  • User: A user in the application.
    • id: The id of the user
    • username: The username of the user
    • email: The email of the user
    • password: The salted and hashed password
    • isAdmin: Indicates whether the user is admin or not
    • credentialValidityDate: Indicates a timestamp. All tokens that have been created before this timestamp are considered invalid.
    • temporaryPasswords: The list of currently valid temporary passwords of the user.
    • caffs: The caffs of the user.
    • lastModifiedBy (CAFF): The caffs that the user modified by last
    • comments: The comments of the user.
    • lastModifiedBy (Comment): The comments that the user modified by last.
  • TemporaryPassword: A temporary password of a user.
    • id: The id of the temporary password.
    • password: The salted and hashed password.
    • validUntil: Indicates until when the temporary password is valid
    • user: The user, the temporary password belongs to.
  • CAFF: The data of a CAFF.
    • id: The id of a CAFF.
    • title: The title of a CAFF.
    • tags: The tags of a CAFF.
    • user: The owner of the CAFF.
    • lastModifiedDate: Indicates when this CAFF was last modified.
    • lastModifiedBy: Indicates the user that modified it for the last time.
    • fileData: The files associated with the CAFF.
    • comments: The comments of the CAFF.
  • CAFFFileData: The files associated to a CAFF.
    • id: The id of the entry.
    • file: Stores the content of the CAFF file.
    • preview: Stores the content of the preview of the CAFF file.
    • caff: The CAFF the files belong to.
  • Comment: A comment.
    • id: The id of the comment.
    • content: The content of the comment.
    • createdDate: The date the comment was created on.
    • user: The user that made the comment.
    • lastModifiedDate: The date the comment was last modified on.
    • lastModifiedBy: The user that modified the comment last.

Security aspects

Configuration

The Spring server is configured via th application.properties file. This file contains sensitive data, so in production environment the passwords and security configuration in this file should be changed.

Authentication

The authentication is handled in a distinct submodule. This module is responsible for processing login requests, and providing tokens on successful logins. Moreover, its job is to verify such tokens.

Also, this submodule is responsible for secure password storage. The passwords are salted and hashed via BCryptPasswordEncoder.

Authorization

The authorization logic is centralized in its own subcomponent. This subcomponent decides for each operation, whether the user in question has the rights to execute it.

Clone this wiki locally