Skip to content

API Reference

Marcello Rosati edited this page Feb 19, 2020 · 5 revisions

We made a REST server that exposes a set of APIs for managing users and files. The following list contains all the APIs that our server exposes to the client.

api/user/login

  • description:

used to login the user. This will check if the given email and associated password exist.

  • method: GET
  • params to send:
    • email (string)
    • password (string)
  • response:
    • Success: JSON with user information
    • Errors: User not found / Invalid password

Usage example:

 

api/user/signin

  • description:

used to register a new user. An error will be returned if the given email already exists, otherwise it will be created a new user inside our remote database.

  • method: POST
  • params to send (as application/JSON):
    • name (string)
    • surname (string)
    • email (string)
    • password (string)
  • response:
    • Success: JSON with user registration information
    • Errors: no JSON is returned (email already in use)

Usage example:

 

api/user/pswRecovery

  • description:

used to start the recovery password process. A password recovery email with a specific link is sent to the email provided by the user if this email is already present in the database, then a registration exists. This link will contain the "uuid" and "pgid" params information that will be used then by the API /changePassword called in the next dedicated page. When a password recovery procedure starts, for that request a ChangePassword schema is created inside the remote database, and these information are stored here.

  • method: POST
  • params to send (as application/JSON):
    • email (string)
  • response:
    • Success: "true" (if the email has been successfully sent)
    • Errors: "Email not found" (if the email does not exist in the database)

Usage example:

api/user/changePassword

  • description:

used to update the password of an user with a new password. This is the second step of the password recovery API. "uuid" and "pgid" must be passed, and their values come from the result of pswRecovery API; the value of "password" is inserted by the user in the dedicated client page.

  • method: GET
  • params to send:
    • uuid (string)
    • pgid (string)
    • password (string)
  • response:
    • Success: JSON with updated user information
    • Errors: "PasswordChange not found" (if uuid and pgid values are not correct)

Usage example:

 

 

api/user/getUser

  • description:

 used to retrieve an user simply passing an user id.

  • method: GET
  • params to send:
    • id (string)
  • response:
    • Success: JSON with user information
    • Errors: JSON with "Internal server error" (if the given id does not exist)

Usage example:

 

 

api/file/createRepository

  • description:

used to create a public or private repository for the given user. The params needed are "userId", "publicR" (true for creating a public repository; false instead for a private repository), "repositoryName" that is the name of the repository that will be shown to the users and "autore" that contains the real name of the repository creator. Notice that the file system that we implemented, stores all folders and file locally on our server, inside the dedicated folder "BPMFiles": using this API if the user does not have already a folder for him inside the "BPMFiles" folder, this folder, named with the user id, will be created, then the folder for the new repository will be created too, named with an unique id.

 Please see File System page on this Wiki for more information about our file system.

  • method: GET
  • params to send:
    • idUser (string)
    • publicR (boolean)
    • repositoryName (string)
    • autore (string)
  • response:
    • Success: JSON with repository path information
    • Errors: JSON with "Internal server error" (if the given user id does not exist)

 

Usage example:

 

api/file/createFolder

  • description:

this API is used to create a folder inside a repository. The params needed are "idUser" that is the id of the current user, "idRepository" that is the id of the repository where the folder will be created, "folderName" that is the real name of the folder that will be shown to the user and "autore" that is the name of the user that is creating the folder.

  • method: GET
  • params to send:
    • idUser (string)
    • idRepository (string)
    • folderName (string)
    • autore (string)
  • response:
    • Success: JSON with folder information
    • Errors: JSON with "Internal server error" (if the given user id, or repository, id do not exist)

Usage example:

 

 

api/file/createFile

  • Description:

 this API is used to create a new file inside a repository or a folder. The params needed are "idUser" that is the id of the current user, "idRepository", "idFolder" (optional) that specifies the id of a folder where the user is creating the file (if that folder exist inside the repository), "originalName" that is the name of the file that will be shown to the users, "autore" that is the name of the user that is creating the file and "fileType" that assumes two value, "coreography" or "collaboration". This API will create a folder that is "hidden" to the user, but is used by the file system to wrap all the different versions of a single bpmn file. This API creates the file version n°1. The actual name of the file, ie the one not shown to the user but used in the file system, consists of the concatenation created by a dot between the id of this hidden wrapping folder and the file version.

  • method: GET
  • params to send:
    • idUser (string)
    • idRepository (string)
    • idFolder (string)
    • originalName (string)
    • autore (string)
    • fileType (string)

 

  • response:
    • Success: JSON with the information of the new file
    • Errors: JSON with "Internal server error" (if the given user id, repository id or file type do not exist, or the given folder id is wrong)

Usage example:

 

api/file/uploadFile

  • Description:

This API is used to upload a file from the user's local machine. The file thus loaded can be placed directly at the repository level or inside a folder; a new schema containing all the information it is saved in the database and the current version is 1. The request type is MULTIPART_FORM_DATA so the params are "idUser", "idRepository", "autore", "fileType" and the uploaded file "files" itself.

  • method: POST
  • params to send:
    • idUser (string)
    • idRepository (string)
    • autore (string)
    • fileType (string)
    • files (file)
  • response:
    • Success: the file is updated
    • Errors: JSON with "Internal Server Error" message

 

api/file/modifyBodyFile

  • Description:

 This API is used to upload a specific version of a file from the user's local machine. The file version thus loaded need to be placed directly inside the hidden wrapping folder for that file, and is going to replace that file with the specified version; this folder can be at repository level or inside a folder. The request type is MULTIPART_FORM_DATA so the params are "idUser", "idRepository", "idFolder" (optional), "version" and the uploaded file "files" itself.

  • method: POST
  • params to send:
    • idUser (string)
    • idRepository (string)
    • idFolder (string)
    • version (string)
    • files (file)
  • response:
    • Success: "OK"
    • Errors: JSON with "Internal Server Error" message

api/file/downloadFile

  • Description:

 this API allows the user to download a specific file on his local machine. The params needed are "idFile" that is the id of the file that the user wants to download and the "version".

  • method: GET
  • params to send:
    • idFile (string)
    • version (string)
  • response:
    • Success: the download for the indicated file starts
    • Errors: the download for the indicated file doesn't start (if the given file id does not exist in the database)

Usage example:

 

 

 

 

api/file/getAllRepo

  • Description:

this API returns a list of repository for a specific user. The param needed is "idUser".

  • method: GET
  • params to send:
    • idUser (string)
  • response:
    • Success: JSON with all the repositories information
    • Errors: empty JSON (if the given id does not exist in the database)

Usage example:

 

 

api/file/getRepoSpec

  • Description:

 this API returns information about a specific repository. The param needed is "id" of the desired repository.

  • method: GET
  • params to send:
    • id (string)
  • response:
    • Success: JSON with the repository information
    • Errors: empty JSON (if the given id does not exist in the database)

Usage example:

api/file/getAllFile

  • Description: this API returns a JSON with a list of file inside a repository or a folder. The params needed are "idRepository" and "idFolder" (optional).
  • method: GET
  • params to send:
    • idRepository (string)
    • idFolder (string)
  • response:
    • Success: JSON with information for all file inside a repository or a folder
    • Errors: empty JSON (if the given ids don't exist in the database)

Usage example:

 

api/file/getAllFolders

  • Description:

 this API returns a JSON with a list of folders inside a repository. The param needed is "idRepository".

  • method: GET
  • params to send:
    • idRepository (string)
  • response:
    • Success: JSON with information for all the folders inside the repository
    • Errors: empty JSON (if the given id does not exist in the database)

Usage example:

 

api/file/getFolderSpec

  • Description:

 this API returns a JSON with information about a specific folder, indicated by the param "id" for the folder.

  • method: GET
  • params to send:
    • id (string)
  • response:
    • Success: JSON with information for the specific folder
    • Errors: empty JSON (if the given id does not exist in the database)

Usage example:

 

api/file/createNewVersion

  • Description:

this API is used for the creation of a new version for an existing file. The params needed are "idFile" and the "version". The needed "version" is the current version of the file that the user wants to upgrade: server will create a new version for the indicated file, copying the file with the version indicated and renaming it at the end with the new highest version available for that file. For example, if the user, taken a file that has 5 versions wants to create a new version starting from its version 1, will indicate "version" = 1 and the server will create a copy in the file system for that version 1 file renamed at the end with the value 6 (which indicates that version number 6 was created). That new file will be placed inside the hidden wrapping folder containing all the file versions.

  • method: GET
  • params to send:
    • idFile (string)
    • version (string)
  • response:
    • Success: JSON with information for the new version of the file
    • Errors: empty JSON (if the given file id does not exist in the database) / "Version does not exist" (if the given version that the user wants to copy does not exist)

Usage example:

 

api/file/modifyRepoName

  • Description:

 this API is used to change the name of a specific repository, ie the one that is shown to the user and not the one in the file system. The required params are "idRepository" and "newRepoName".

  • method: GET
  • params to send:
    • idRepository (string)
    • newRepoName (string)
  • response:
    • Success: JSON with updated information for the repository
    • Errors: "Repository not found" (if the given idRepository does not exist in the database)

Usage example:

api/file/modifyFileName

  • Description:

 this API is used to change the name of a specific file, ie the one that is shown to the user and not the one in the file system. The required params are "idFile" and "newFileName".

  • method: GET
  • params to send:
    • idFile (string)
    • newFileName (string)
  • response:
    • Success: JSON with updated information for the file
    • Errors: "File not found" (if the given idFile does not exist in the database)

Usage example:

 

api/file/modifyRepoVisibility

  • Description:

this API is used to change the visibility for a repository. The params needed are "idRepository" and "newRepoVisibility" that can assume value true (to set the repository to public) or false (to set the repository to private).

  • method: GET
  • params to send:
    • idRepository (string)
    • newRepoVisibility (boolean)
  • response:
    • Success: JSON with updated information for the repository
    • Errors: "Repository not found" (if the given idRepository does not exist in the database)

Usage example:

api/file/modifyFolderName

  • Description:

this API is used to change the name for a folder, ie the one that is shown to the user and not the one in the file system. The required params are "idFolder" and "newFolderName".

  • method: GET
  • params to send:
    • idFolder (string)
    • newFolderName (string)
  • response:
    • Success: JSON with updated information for the folder
    • Errors: "Folder not found" (if the given idFolder does not exist in the database)

Usage example:

 

api/file/getFileSpec

  • Description:

 this API is used to retrive information for a specific file. The required param is the file "id".

  • method: GET
  • params to send:
    • id (string)
  • response:
    • Success: JSON with file information
    • Errors: "File not found" (if the given idFile does not exist in the database)

Usage example:

api/file/getAllRepoPublic

  • Description: this API is used to retrive information for all the public repository in the database. No params are needed.
  • method: GET
  • params to send: none
  • response:
    • Success: JSON with all public repositories information
    • Errors: none

Usage example:

api/file/deleteVersion

  • Description:

 this API is used to delete a specific version for a file. Params needed are "idFile" and "version": the file with the indicated version and id is deleted from the file system, moreover on the file entity inside the db a deletedVersion array keeps track of every version number of the deleted file versions.

  • method: GET
  • params to send:
    • idFile (string)
    • version (string)
  • response:
    • Success: "true"
    • Errors: none

Usage example:

 

api/file/exportCollection

  • Description:

this API is used to export the collection of all versions for a specific file in zip format. When the "idFile" is received, all the files on the corresponding hidden wrapping folder are zipped into an archive, named with the original file name (different from the one used by the file system).

  • method: GET
  • params to send:
    • idFile (string)
  • response:
    • Success: download of the zipped collection of file versions will start
    • Errors: JSON with "internal error" message if the idFile does not exist inside the db

Usage example:

api/file/moveFile

  • Description:

 this API is used to move a specific file from a specific location to another location of the same repository. The params needed "idUser", "idRepository", "idFolder" (optional) are related to the destination where the user want to move the file; instead "idFile" and "paths" are params that are related to the id of the file that the user is moving and the path where the moving file is located, respectively.

  • method: GET
  • params to send:
    • idUser (string)
    • idRepository (string)
    • idFolder (string)
    • idFile (string)
    • paths (string)
  • response:
    • Success: the file is correcly moved
    • Errors: the wrong path, if almost one of the id passed is not correct

Usage example:

 

api/file/deleteFile

  • Description:

this API is used to delete a file. Removing a file means remove entirely the hidden wrap folder and all the file inside this folder (the different versions of the file). Params needed are "idFile" that is the actual name of the hidden folder, "idRepository", "idUser" and "idFolder" that is optional (use only if the file is inside a folder).

  • method: GET
  • params to send:
    • idRepository (string)
    • idUser (string)
    • idFolder (string)
    • idFile (string)
  • response:
    • Success: the file (so the hidden wrapping file versions folder) is correcly deleted
    • Errors: JSON with "Internal Server Error" if one of the given ids does not exist

Usage example:

 

api/file/addValidity

  • Description:

given an "idFile", this API is going to update information about "soundness", "safeness" and "validity" for that file.

  • method: GET
  • params to send:
    • idFile (string)
    • soundness (string)
    • safeness (string)
    • validity (boolean)
  • response:
    • Success: JSON with updated file information
    • Errors: JSON with "Internal Server Error" if the given id does not exist

Usage example:

api/share/repository

  • Description:

this API is used to share a repository. The visibility of the specified repository will be set to public, while an email is sent to the email of the user which we want to share the repository to, and contains the link that points to this shared repository. Params needed are the "idRepository" and the "emailTo".

  • method: GET
  • params to send:
    • idRepository (string)
    • emailTo (string)
  • response:
    • Success: "true" (the email is sent to the user)
    • Errors: "Repository not found" (if the idRepository does not exist in the database) / JSON "Internal Server Error" (if the email could not be sent)

Usage example:

api/share/file

  • Description:

 this API is used to share a file. For doing that, a new public repository is created, the file (so the hidden folder with all the versions of that file) is copied into that new repository, while an email is sent to the email of the user which we want to share the file to, and contains the link that points to this shared repository with the copy of the specified file. The params needed are "idFile" (file to share), "emailTo", "repositoryName" (the name of the new repository that will be created), "idUser" (id of the user folder where we want to create the new repository) and "autore" (of the new repository).

  • method: GET
  • params to send:
    • idFile (string)
    • emailTo (string)
    • idUser(string)
    • repositoryName (string)
    • autore (string)
  • response:
    • Success: "true" (the email is sent to the user)
    • Errors: "File not found" (if the idFile does not exist in the database) / JSON "Internal Server Error" (if the email could not be sent)

Usage example:

/api/modelcheck/upload

  • Description:

Run a DFS algorithm on the models to generate the related LTS contained in the .aut files.

  • method: POST
  • params to send:
    • collaboration (File)
    • choreography (File)
  • response:

The result is a JSON File if the response is success. In the Json file there are two fields:

  • choreography (that contain the choreography’s name of the .aut file)
  • collaboration (that contain the collaboration’s name of the .aut file)

Return 500 Internal Error, if an error occurs.

 

 

 

 

 

/api/modelcheck/download

 

  • Description:

Download the .aut file whose name is specified as a parameter in the "filename" and a boolean to specify if is a collaboration or a choreography model..

  • method: GET
  • params to send:
    • filename ( contain the String of name of the .aut file)
    • collaboration ( is a boolean, true if is a collaboration file, false if is a choreography file)
  • response:

Download the file in your system

 

/api/modelcheck/check_equivalence

  • Description:

Use the "ltscompare" executable of the MCRL2 tool to perform the equivalences Trace, Branching and Bisimulation between models, with or without Weak.

  • method: POST
  • params to send:
    • weak (boolean, true o false)
    • equivalence ( contain “Trace”, “Branching” or “Bisimulation” value)
    • collaborationPath (name of .aut collaboration file)
    • choreographyPath (name of .aut choreography file)
  • response:

Return a Json object that contain the following fields: “state”,”resultState”,”command”,”log”,”result”,”counterExample”

 

/api/modelcheck/mergemodel

  • Description:

It takes 2 collaboration files as input generates a file that corresponds to the merge of the two files, if they meet certain requirements.

Connect a task sender of one file with the task receiver of the other file via message flow only if the message flows have the same label on both files.

  • method: POST
  • params to send:
    • sender (sender collaboration file)
    • receiver (receiver collaboration file)
  • response:

- File containing both models linked via messageFlow

- If the models have a different number of message flows -> returns BadRequest 400 with a message

- A name of a message flow of the first model is not present in the second model -> returns BadRequest 400 with a message

- A name of a message flow of the second model is not present in the first model -> returns BadRequest 400 with a message

- The name is present but the message flow sender of one model does not have the respective receiver in the other model (and vice versa) -> returns BadRequest 400 with a message

 

 

File system with MongoDB

Overview

We can distinguish two families of data in our application:

  • Data saved on database, such as file information, user information, repository information, folder information, temporary information for password changes
  • Physical .bpmn files and folders managed by our local file system

The first information are stored and managed by MongoDB, a document-oriented NoSQL DBMS; while the latter are the physical .bpmn files and the folders that organize them and are managed by our file system and saved locally on our server. For example, if the user creates a new .bpmn template, this physical file is saved to the local file system on our server, while information such as file id, file name, author, creation date and version are stored inside a JSON document present remotely on MongoDB. The following image will show this concept:

In the left image “a”, we physically see the file saved on the server disk locally, while in the right image "b" all the information for this file: the structure of this JSON document is well dictated by the entity classes, called domain classes or POCO classes, which contain simply all the properties for what is called "Entity" and for every property a get method and a set method.

We have identified five entities: File, Folder, Repository, User and PasswordChange.

MongoDB

We have created a document-oriented NoSQL database in mongoDB called "C4":

To connect to this database we have to set a connection string from our server.

For each entity created by us, we find a collection of JSON documents:

Each collection list all the JSON documents, and each document contains information about a particular user, file, repository, folder or active password changing process.

 For example we see Users documents:

For each User document, or let's say user stored in our database, we find properties like "id", "name", "surname", "email" and "password" that are, the properties defined in the POCO class User.java.

 Click here to see the User.java file.

 The other entities properties are defined by the following classes:

File System

Files and folders are saved locally on the server and they are all contained within a folder called BPMFiles which is at the root level of the server. In the structure we thought, a file corresponds to a specific version of a .bpmn model, while the repositories and the folders correspond to the system folders. We can see the following abstraction:

For each registered user is created a dedicated system folder renamed with the id of that specific user. Within this "user" system folder we immediately find the repositories of that user, and each repository is a system folder renamed with the id of that repository. Within a "repository" system folder we can find a system folder "folder" renamed with the id of that folder, or a system "file" folder renamed the file id containing a .bpmn file for each version of that file. Each .bpmn file is renamed with the file id + version number. The "file" folder is an hidden system folder unknown to the user and is used by our file system as a container for all versions of a specific file. In turn, a "folder" system folder can contain several "file" system folders. This is an example of a possible scenario within our file system:

 

The path to access the first version of the only file for the first user is the following:

Root/idUser/idRepository/idFile/idFile.version

Example:

BPMFiles/5c6aee05250d3e3990f54044/5c6c4ddd270d3e4cac53cf05/5c6c4ddd270d3e4cac53cf06/5c6c4ddd270d3e4cac53cf06.1

The path to access the third version of a file for the second user conteined inside a folder is the following:

Root/idUser/idRepository/idFolder/idFile/idFile.version

Example:

BPMFiles/5c6aee05270d3e3990f54044/5c6c21f2270d3e2960cf8cae/5c6b10b8270d3e3990f54048/5c6b10b8270d3e3990f54048.3

These ids are only used by our file system and are stored inside MongoDB, in fact, the ids will never be shown to the user, while rather, the user will display the real names of other users, repositories, folders and files while using our application, also stored in the remote database.

 

 

Server Architecture

Other than dependency management, Maven helps in cleaning and building the project. It is incorporated in Eclipse and can be used as well via command prompt.

 

To obtain a non-blocking web stack to handle concurrency with a small number of threads and scale with fewer hardware resources, we used Java Spring WebFlux, in particular we used a Functional Endpoints programming model: Lambda-based and functional programming model, with set of utilities that the application can use to route and handle requests.

 

Server architecture

Meaning of the main folders:

  • spm.api: contains the main file for running the server.
  • spm.api.config: contains server configuration files like cors, email and security configurations.
  • spm.api.entity: contains simple Java classes representing the abstraction of each entity of MongoDb database that we used.
  • spm.api.routes: contains the files that specify router functions used to route the requests to the corresponding handler function.
  • spm.api.handlers: an handler is a function that accesses the HTTP method, URI, headers, query parameters or body of a single request. Then it uses a declarative composition of asynchronous logic to compose server response. In this asynchronous logic, a handler could use an abstraction level called service, to make database-side calls and perform business logic with retrieved data.
  • spm.api.services: services are functions that use methods for database calls and perform business logic.
  • spm.api.repository: a repository is an interface for principal database calls methods.

 

 

User guide

In this guide we will see how to use our platform.

The first page shown to the user is the following:

Here the unregistered user can log in, register, retrieve his password or view the public repositories of all other registered users. By clicking on "Public Repositories" you can view the list of all public repositories even if this user is not logged in:

Once the user selects the repository he wants to use, the following page shows the list of folders and .bpmn files present at the repository level. The user will open these resources in read-only mode, in fact it will not be able to modify, upload files or folders; there is also a search bar to perform a search based on parameters such as "Name", "Creation date" and "Author": by setting the search values, the underlying list of contents is filtered.

Clicking on the affected file will open a preview page of the file. If the user is not logged in he can only select the version of the model he is interested in, without being able to upload other versions.

 

Once the desired version is selected, the model opens in the editor. The user can only export the model or make temporary changes: even here the changes that the user not logged in will bring to this file, can not be saved.

 

 

 

 

 

Let's create a user now. To do so, click on the SignUp item in the upper left menu. Now the user must enter the registration information.

 

Once registered, the user can log in to the login page using email and password. Once logged in, the user will see his dashboard:

In the lower part of the dashboard there is a list of all the repositories, both public and private, of the logged in user. At this point, the user can create a new repository: clicking on the "+ Create New Repository" button will open a popup that will allow you to enter a name for the repository you are creating and visibility, which can be public or private.

 

The newly created private repository will only appear in the creator's dashboard and will not be shown in the public repositories list. Returning to the list of public repositories, this time the registered user can open files and folders of all public repositories also in writing mode, then can make changes to files, upload, move files etc. We see these same operations by observing them within the newly created private repository. Clicking on the repository name will open a drop-down menu where the user can make changes to the repository, create a folder, create a new file, import a new file or share the same repository with another.

 

If the user clicks the "Modify Repository" option, he will be able to change the name of the repository by a popup. Let's insert the new name:

With the "Create folder" option, the user is given the possibility to create a folder to organize his models better. Once the folder is created, this is displayed in the list of resources contained in the repository.

 

Another option to take into consideration is that of "Sharing repository": the user can select an email to send a link to another user, if he wants to share the repository. Note that a private repository, once shared with another user, will become public, so it will also appear in the list of public repositories.

With the "Import file" option, the user can upload a file on his local machine. At this point, this .bpmn file will be shown in the resource list. Note that for this file, its version 1 will be generated immediately.

 

 

Now let's create a new file. A window will open that will allow the user to create a file of type collaboration or choreography:

 

Once the file is created, the user will be redirected to the editor and can create the relative model. Once you have created the model you can save it as it is a registered user.

When the user saves the newly created file (hence version number 1) now, he will be asked to enter a name:

Now that the file has been created it is possible to reopen it from the list of resources contained in the repository. At this point, however, is shown a page that will allow the user to create a new version for that same file, choose the version of that file to open, to delete or download locally.

 

 

By clicking on the "Create new version" button, a new version of the file is created. The new version is created starting from the current selected version, then a copy of the desired version is made and the first available next version number is assigned. The list of versions of the same file is shown in the drop-down menu on the left:

ù

 

 

Within the page where you can select the version for a specific file, you can also perform a series of operations:

 

  • Modify File Name: allows the user to change the file name.
  • Move File: allows the user to move a file within a folder of the same repository.
  • Share file: allows you to share the file with another user. If the repository where the file is located is private, a new public repository is created containing the copy of this file and shared with another user by means of a link sent by email.
  • Download ZIP models: allows the user to download locally a zip file containing all the versions of this file.
  • Delete File: allows the user to delete the file, so all versions for that file.

 

In this page you can also decide to merge the model with another collaboration model already present in your system.

If there is the right matching of the message flows in the two models, the merge will be correct and you will show the result in a new page.

 

 

This is the c4 initial page for matching two models. In this page you can choose two models from your system, one collaboration and one choreography and then apply the matching.

This is the result of the two file matched. The results are the two .aut files. You can download the files or see the diagram.

Then you can check the  equivalence of the two models that show the result and a counterExample.

 

Clone this wiki locally