== Features

The features of the project are the ones present in the course project description, but with an extra feature, the possibility to reset the database of the server. This was shown to be useful for testing purposes, but it should be disabled/deleted in a production environment.


The API has a list of endpoints that require different permission levels to access. Mainly, it's divided into 3 categories:

* <<_anonymous_endpoints,Anonymous>>: No authentication required.
* <<_authenticated_endpoints,Authenticated>>: Authentication required.
* <<_authorized_endpoints,Authorized>>: Authentication and permissions required.

[[_anonymous_endpoints]]
=== Anonymous Endpoints

[cols="1,1,1,1", options="header"]
|===
| Endpoint | Required headers | Required payload fields | Optional payload parameters

a| `GET /` → Returns a ping message.
| N/A
| N/A
| N/A

a| `POST /reset` → Resets the database and deletes all data.
a| * `Content-Type: application/json`
a| * `password`: The reset password. *Note: The reset password is `123` (very secure!).*
| N/A

a| `GET /org/list` → Returns a list of all organizations.
| N/A
| N/A
| N/A

a| `POST /org/create` → Creates a new organization.
a| * `Content-Type: application/octet-stream`
a|
* `name`: Organization name.
* `username`: Manager username.
* `full_name`: Manager full name.
* `email`: Manager email.
* `public_key`: Manager public key.
| N/A

a| `GET /file/get/<file_handle>/content` → Downloads the file content.
| N/A
| N/A
| N/A

.2+a| `POST /user/login` → Logs in a user.
a| * `Content-Type: application/json`
a| * `org`: Organization name.
* `username`: User username.
| N/A

a| * `Content-Type: application/octet-stream`
* `Authorization: token`
a| * `signature`: Signature of the challenge using the private key.
| N/A

|===

[[_authenticated_endpoints]]
=== Authenticated Endpoints

[cols="1,1,1,1", options="header", source]
|===
| Endpoint | Required headers | Required payload fields | Optional payload parameters

a| `GET /user/list` → Returns a list of all users
a| * `Content-Type: application/octet-stream`
* `Authorization: token`
| N/A
a| * `username`: Filter by username.

a| `GET /user/<username>/roles` → Returns a list of all roles of a user.
a| * `Authorization: token`
| N/A
| N/A

a| `GET /file/list` → Returns a list of all files.
a| * `Content-Type: application/octet-stream`
* `Authorization: token`
| N/A
a| * `username`: Filter by username.
* `datetime`: Filter by datetime. The datetime filter has the following fields:
** `value`: Epoch time in seconds.
** `relation`: `ot` \| `eq` \| `nt`. (One of the following: older than, equal to, newer than)

a| `POST /user/logout` → Logs out a user.
a| * `Authorization: token`
| N/A
| N/A

a| `POST /role/session/assume/<role>` → Assumes a role in the session.
a| * `Authorization: token`
| N/A
| N/A

a| `POST /role/session/drop/<role>` → Drops a role from the session.
a| * `Authorization: token`
| N/A
| N/A

a| `GET /role/session/list` → Lists the roles for the session.
a| * `Authorization: token`
| N/A
| N/A

a| `GET /role/<role>/list/users` → Lists the users for a role.
a| * `Authorization: token`
| N/A
| N/A

a| `GET /role/<role>/list/perms` → Lists the permissions for a role.
a| * `Authorization: token`
| N/A
| N/A

a| `GET /role/perm/<perm>/roles`: → Lists the roles with a permission.
a| * `Authorization: token`
| N/A
| N/A

|===

[[_authorized_endpoints]]
=== Authorized Endpoints

[cols="1,1,1,1", options="header", source]
|===
| Endpoint | Required headers | Required payload fields | Required permission

| `POST /user/create` → Creates a new user.
a| * `Content-Type: application/octet-stream`
* `Authorization: token`
a| * `username`: User's username.
* `name`: User's name.
* `email`: User's email.
* `public_key`: User's public key.
| SUBJECT_NEW

a| `POST /user/<username>/suspend` → Suspends a user.
a| * `Authorization: token`
| N/A
| SUBJECT_DOWN

a| `POST /user/<username>/activate` → Activates a user.
a| `Authorization: token`
| N/A
| SUBJECT_UP

a| `POST /file/upload/metadata` → Uploads a file's metadata.
a| * `Content-Type: application/octet-stream`
* `Authorization: token`
a| * `document_name`: Document name.
* `key`: Document key.
* `alg`: Document algorithm.
| DOC_NEW

a| `POST /file/upload/content` → Uploads a file's content.
a| * `Authorization: token`
* `Content-Type: multipart/form-data`
a| * file's content as request data
| DOC_NEW

a| `GET /file/get/<document_handle>/metadata` → Downloads a file's metadata.
a| * `Authorization: token`
| N/A
| DOC_READ

a| `POST /file/delete/<document_handle>` → Deletes a file.
a| * `Authorization: token`
| N/A
| DOC_DELETE

a| `POST /file/acl` → Updates the ACL of a file.
a| * `Content-Type: application/octet-stream`
* `Authorization: token`
a| * `document_handle`: Document handle.
* `role`: Role name.
* `perm`: Permission name.
* `operation`: `add` \| `remove`. (One of the following: add, remove)
| DOC_ACL

a| `POST /role/create` → Creates a new role.
a| * `Content-Type: application/octet-stream`
* `Authorization: token`
a| * `role`: Role name.
| ROLE_NEW

a| `POST /role/<role>/suspend` → Suspends a role.
a| * `Authorization: token`
| N/A
| ROLE_DOWN

a| `POST /role/<role>/activate` → Activates a role
a| * `Authorization: token`
| N/A
| ROLE_UP

a| `POST /role/<role>/user/add/<username>` → Adds a user to a role.
a| * `Authorization: token`
| N/A
| ROLE_MOD

a| `POST /role/<role>/user/remove/<username>` → Removes a user from a role.
a| * `Authorization: token`
| N/A
| ROLE_MOD

a| `POST /role/<role>/perm/add/<perm>` → Adds a permission to a role.
a| * `Authorization: token`
| N/A
| ROLE_MOD

a| `POST /role/<role>/perm/remove/<perm>` → Removes a permission from a role.
a| * `Authorization: token`
| N/A
| ROLE_MOD

|===

=== Client Interaction

For the client, each command is executed via terminal and it is used multiple tools with specific functionalities:

* Argparse footnote:[https://docs.python.org/3/library/argparse.html] → Check for errors in arguments given by the user.
* Logging footnote:[https://docs.python.org/3/library/logging.html] → Logging system to send out messages such as errors.
* OS footnote:[https://docs.python.org/3/library/os.html] → Add path to local folder `~/.sio` to save or load any files used by the current command.
* Requests footnote:[https://requests.readthedocs.io/en/latest/] → Main library to allow communication from the client to the API.

For every command the argument `-r` is present to set the API's address. It is needed to define if it wasn't previously, otherwise an error is cast with the corresponding message.

To use the API, it is first needed to create a public key to create an organization with the key.
The command `rep_subject_credentials` it is generated a keypair using RSA with a given password and both public and private keys are saved in different files.

==== Creating an Organization

The command `rep_create_org` creates an organization and for it the client must give the file containing his public key in order to create a session afterwards.

==== Creating a session
For the client to use the Authenticated API, the command `rep_create_session` allows the user to create a session and assume an identity. This command also protects information that shouldn't be visible to outsiders when it's being transfered between the client and the server.

To protect the information, the client and the server initiate a Diffie-Hellman footnote:[https://cryptography.io/en/latest/hazmat/primitives/asymmetric/dh/] key exchange where both create a key pair with the same parameters and share each other their public key to derive with their own private key and obtain a common key which can be used to encrypt and decrypt information between both entities.

[source, python]
----
generator = 2; key_size = 1024
parameters = generate_parameters(generator, key_size)
private_key, public_key = generate_key_pair(parameters)

response = req.json()
server_public_key = serialization.load_pem_public_key(bytes.fromhex(response['public_key']))
derived_key = derive_keys(private_key, server_public_key)
----

If the exchange is succesful, the client will attempt to login using it's private key that should be given when executing this command. 
