Jupiter - Cloud storage API - Specification

Jupiter should be implemented as REST API Server, with functional requirements being:

  1. POST/PUT Uploading file to cloud storage
  2. POST/PUT Updating file to cloud storage, perserving the link from old file
  3. GET Downloading file
  4. GET Receiving all data for logged user or avaliable folder
  5. GET Getting info about file
  6. POST Creating database specified by Minerva API
  7. POST Deleting selected file
  8. POST Creating user space, afterwards avaliable for user to upload files to
  9. POST Making file or directory public
  10. POST Sharing file or directory with another user with given privileges
  11. POST Increasing/Decreasing avaliable storage space for upgraded users

Except for given request, this service should realize the following features:

  1. Controlling the internal structure of file-system, something like unix-like(Linux e.g.) systems directories. Basically meaning each user can have his own directory, and can access only that directory, while he can also see shared directories of other users. This means that engineers working on this service needs to implement some type of user privileges, possibly just by using authentication header.
  2. Internally, this service should be able to host any type of file, but should check the size of those files and should terminate upload or expansion of those files that exceed the total maximum size that is avaliable for user.

Before we start...

First thing we need to do here is to create simple functions for controlling the storage. Each user will have UUID(will be generated by gateway, you should store it in your own database) that will be the name of his folder, too, the url-s of files uploaded by that user would be as follows: jupiter.lws/get?file=UUID/name_of_file or if it's inside some folder jupiter.lws/get?file=UUID/folder_name/name_of_file All requests will contain username inside header, it will be sent by gateway and that is the only service which will this service communicate directly. If the header does not contain username inside of a header, it means the user is not loged in, and he can access file only if its public. If the header does contain a username, but it is not owner of a file or folder, then he can access it if he has the rights to access or is public.

Public files are public for view only, no one else can modify them. On the other hand, a user can give privileges to another user for modify or view. If the user can modify them, he can upload files to that folder, and it will go to that folder, not occuping space for user that uploaded it, but instead for the user who is owner of the file. The privileges for given directory is inherited by all files inside directory, meaning if the directory is public, then all files inside are public too.

Note that not everyone can execute this requests, if someone does not have privileges for given file or something similar, he should receive error instead.

1. Uploading file to cloud storage

URL: jupiter.lws/upload or jupiter.lws/upload?dir=UUID/directory_name

In this request, a user should be able to upload a file, a message should contain a file in the body. The 2 links given as example are as follows:

  • jupiter.lws/upload - Uploads to root directory of user, meaning the url generated for download would be jupiter.lws/get?file=UUID/file_name\
  • jupiter.lws/upload?dir=UUID/directory_name - Uploads to sub-directory of users cloud storage, meaning the url generated for download would be jupiter.lws/upload?dir=UUID/directory_name/file_name Response should be simple:
{    "status": "STATUS FIELD CAN BE SUCCESS OR FALSE",    "message" : "DESCRIBE THE SCENARIO THAT HAPPENED OR URL TO THE FILE",}

2. Updating file to cloud storage

URL: jupiter.lws/update?file=url_to_file

In this request, a user should be able to upload a file, a message should contain a file in the body. Response should be simple:

{    "status": "STATUS FIELD CAN BE SUCCESS OR FALSE",    "message" : "DESCRIBE THE SCENARIO THAT HAPPENED",}

No need to respond with url, it is same

3. Downloading file

URL: jupiter.lws/get?file=url_to_file

In this request, a user should simply call GET request to receive the file downloaded, the response should be the file itself. Here you will have to make sure that user that has no privilege to see this file gets rejected with error response. Basically, the reponse is either a file or Not authorized.

4. Receiving all data for logged user or avaliable folder

URL: jupiter.lws/get or jupiter.lws/get?full=false or jupiter.lws/get?dir=name_of_directory&full=false

In this request, a user requests to get view of his directory, It has few possible scenarios, given in header

  • jupiter.lws/get - This is the most basic scenario, in this scenario a user should receive json with all files, this returns full scope of everything inside the root directory, like this:
{   "path": "/",   "max_storage": "1GB",   "occupied": "324MB",   "files" : [       {           "name": "example_file_1",           "size": "20MB",           "dir" : false       },       {           "name": "example_dir_1",           "size": "300MB",           "dir" : true,           "files" : [               {                   "name": "example_file_2",                   "size": "50MB",                   "dir" : false               },               {                   "name": "example_file_3",                   "size": "50MB",                   "dir" : false               },               {                   "name": "example_dir_2",                   "size": "200MB",                   "dir" : true,                   "files" : [                       {                           "name": "example_file_4",                           "size": "100MB",                           "dir" : false                       },                       {                           "name": "example_file_5",                           "size": "100MB",                           "dir" : false                       },                   ]               }           ]       }   ]}
  • jupiter.lws/get?full=false - full flag can be left of or set to true to show everything inside the root directory, but can be set to true, then it will show just information about first files/directories shown, it will not go in depth. As for example above:
{   "path": "/",   "max_storage": "1GB",   "occupied": "324MB",   "files" : [       {           "name": "example_file_1",           "size": "20MB",           "dir" : false       },       {           "name": "example_dir_1",           "size": "300MB",           "dir" : true       }   ]}
  • jupiter.lws/get?dir=name_of_directory&full=false - User can also specify which directory he wants to look at, he can still specify if he wants it full or not, if not, and he wants to see everything inside example_dir_2 directory, he would send get request like this : jupiter.lws/get?dir=example_dir_1%2Fexample_dir_2&full=false, %2F is escape code for /, but in url you can't send /, it is ambiguous. The response for it would be:
{   "name": "/example_dir_1/example_dir_2",   "size": "200MB",   "files" : [       {           "name": "example_file_4",           "size": "100MB",           "dir" : false       },       {           "name": "example_file_5",           "size": "100MB",           "dir" : false       },   ]}

If full was set to true, it would show everything in subdirectories, too. But there are none inside this directory.

5. Getting info about file

URL: jupiter.lws/info?path=url_to_file or jupiter.lws/info?path=url_to_directory

This request should return everything about the certain file or directory, the response should look like this:

{    "real_path": "path on hard disk, for example /home/lws/jupiter/storage/UUID/nice_image.png",    "size": "2MB",    "public": true, //(or false)    "shared" : [        {            "username": "marko",            "privilege": "view" //or modify?        },        {            "username": "mateja",            "privilege": "modify" //or view?        },        {            "username": "marija",            "privilege": "view" //or modify?        }    ]}

6. Creating database specified by Minerva API

URL: jupiter.lws/db?name=database_name

This request will be sent by Minerva, trough Mercury. This is actually pretty simple, all you need to do is touch(create empty) file and return the path of file on machine. Response would be:

{    "path" : "/home/lws/jupiter/storage/UUID/database1.db"}

7. Deleting selected file

URL: jupiter.lws/delete?path=path_to_file_or_dir

This request will delete a file or directory from cloud storage. The response would look like:

{    "status": "success", // or not?    "message": "200MB", // or why it failed    "free": "834MB",    "used": "166MB"}

If this request returns success, in message, return the size of freed space, if it fails, in message, returns why it fails.

8. Creating user space, afterwards avaliable for user to upload files to

URL: jupiter.lws/create

This request will be sent by Mercury upon registering. The request would look like this:

{    "username": "some_username",    "uuid": "user_unique_id"}

It should create default free space, and return response with status with appropriate message.

9. Making file or directory public

URL: jupiter.lws/mkpublic?path=path_to_dir_or_file

This request should make directory or certain file public and return response with status and appropriate message.

10. Sharing file or directory with another user with given privileges

URL: jupiter.lws/share

The body of this request should look like this:

{    "path": "path_to_dir_or_file",    "username": "username_that_gets_shared",    "privilege": "view" // or modify?}

The request should make it shared with given user and return response:

{    "status": "status",    "message": "if successful, return path, if false, return message"}

11. Increasing/Decreasing avaliable storage space for upgraded users

URL: jupiter.lws/storage?size=some_size

This request should increase or decrease the maximum storage avaliable and make it specified by value of size. In case the storage decreases by some size that is smaller then current occupied space, you should just ignore the further uploads until user deletes the files to free up space. The response should be:

{    "status": "success", //or not    "message": "describe it",    "free": "20GB",    "max_storage": "24GB"}