Skip to content

3.1 MOD.001 : REST API (Backend)

NamidM edited this page May 20, 2021 · 14 revisions

Contents

Changelog

Version Date Author Comment
0.1 16.01.2021 Namid Marxen und Nils-Christopher Wiesenauer created
1.0 14.05.2021 Namid Marxen und Nils-Christopher Wiesenauer finished

1. Scope

The Module Documentations (MODs) describes the architecture, the interfaces and the main features of the module. It also describes the module/component test including the results. It can also serve as a programming or integration manual for the module. If there are some risks related to the module itself, they shall be noted and commented within this document.

2. Definitions

AML: Automation Markup Language

CRUD: Create Read Update Delete

GUI: Graphical User Interface

JSend: A specification that lays down some rules for how JSON responses from web servers should be formatted

SAS: System Architecture Specification

SRS: System Requirements Specification

3. Module Requirements

3.1 Database Connection (MongoDB)

This REST API is the most important module because it contains the logic for converting the AML file to JSON. It also includes the authorization to the database. When a file is uploaded to the server it is converted from an AML format to a JSON format so that it can be saved in the MongoDB database. The content of the files are saved as a string and then converted into one JSON object, so that each file has their own database entry, with the JSON object as the content.

3.2 Conversion XML to JSON

When the file upload was successful and is now temporarily saved on the server, the system should convert the file to a JSON format, so it can be saved in a MongoDB database. The file should be converted by writing one JSON object with the file content as a string. If this was successful the user sees a success message that the file was saved. When an error occurs during the conversion process, the user is shown an error.

3.3 Module Context

The REST API is the core of the project. It communicates with the GUI and Database.

The GUI communicates with the REST API via GET/POST/PUT/DELETE request and gets responses via JSend from the REST API.

To provide the neccessary functionalities, the module has 5 submodules for different database operations. The database operations require a connection to the database.

Component REST API

4. Analysis

The REST API module needs to convert an uploaded AML file to JSON and then upload it to the database. These files also need to be accessed by the GUI afterwards. You also have to be able to edit and delete these files.

Therefore the module contains the 5 submodules, "Get AML Files", "Upload AML File", "Get AML File by id", "Edit AML File" and "Delete AML File" to provide these functionalities.

When an error occurs, the user need to be informed about the error, for example if he tried to upload an invalid AML file.

5. Design

The backend contains different files and program code. It is important to understand the file structure and architecture of the aml-database-management-api.

Architecture

All important files and folders are listed below:

  • /models: This folder contains all mongoose models. Such as file.js
  • .env: This is the environment file of our project, based on the npm package dotenv. Important values like DB_PORT, DB_Domain, DB_TABLE, DB_USER and DB_PASSWORD are included here.
  • .gitignore: This file is a text file that tells Git which files or folders to ignore in a project. In our case, we igored "/node_modules".
  • .prettierrc.json: This file defines how the code should be formatted with Prettier, a Opinionated Code Formatter. Our code will be formatted by running "npm run format".
  • README.md: This file contains information about other files in a directory or archive of computer software.
  • package-lock.json: This file is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
  • package.json: This file contains all npm packages and holds various metadata relevant to the project. This file is used to give information to npm that allows it to identify the project as well as handle the project's dependencies.
  • server.js: This file is the main part of our REST API. It contains all endpoints, the database connection and the conversion from a .aml file to .json.
  • aml-api-documentation.json/aml-api-documentation.yaml: This file describes the structure of our API. They are created with Swagger

5.1 Risks

This module is the main part for the communication with the frontend. It contains every endpoint for upload, edit, download and delete. It includes the database connection to MongoDB and the initial setup for the backend server too. These modules are described seperately in sub modules. The risks and how to handle them, are documented in the mentioned module documentations.

6. Implementation

Link to sourcecode: server.js

6.1 Initialize server

The REST API will be started with the defined values from our .env file.

const mongoose = require('mongoose');
const cors = require('cors');
const express = require('express');
const bodyParser = require('body-parser');
const handlebars = require('handlebars');
const request = require('request');
const fs = require('fs');

const app = express();

const dotenv = require('dotenv');
dotenv.config();

const production = process.env.PRODUCTION === 'true';
const port = process.env.PORT;

const FILE = require('./models/file');

/**********************
 * Config / Preperation
 **********************/

app.use(bodyParser.json({limit: '12mb', extended: true}));
app.use(bodyParser.urlencoded({limit: '12mb', extended: true}));
app.use(bodyParser.json());


/** Origins */
app.use((req, res, next) => {
  const origin = req.headers.origin;
  res.header('Access-Control-Allow-Origin', origin);
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.header('Content-Type', 'application/json');
  res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE');
  res.header('Access-Control-Allow-Credentials', true);
  next();
});

...

/**********************
 * Init server & connect to db
 **********************/

...

app.listen(port, () => {
  console.log(`Server (Production Mode: ${production}) is running on port ${port}...`);
});

6.2 Endpoints

All needed endpoints are listed in this file too. The main endpoint / redirects to our team info page.

/**********************
 * Routes
 **********************/

/** Routes */ 
app.get('/file', (req, res) => {
  ...
});
 
app.post('/file', (req, res) => {
  ...
});

app.get('/file/:id', (req, res) => {
  ...
});

app.get(`/file/:id/download`, (req, res) => {
  ...
});
 
app.put('/file/:id', (req, res) => {
  ...
});

app.delete('/file/:id', (req, res) => {
  ...
});

/** Default */
app.get('/', (req, res) => {
  res.redirect('https://lmf.software/info');
  res.end();
});

6.3 Database Connection

Configuration and connection of our MongoDB. It connects in different ways, depends on the production value. If production is true, it connects to a production database with defined values in .env. If not, it connects without authorization to the defined local database.

...

mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('useUnifiedTopology', true);

if(production) {
  mongoose.connect(`mongodb://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_DOMAIN}:${process.env.DB_PORT}/${process.env.DB_TABLE}?authSource=admin`);
} else {
  mongoose.connect(`mongodb://${process.env.DB_DOMAIN}:${process.env.DB_PORT}/${process.env.DB_TABLE}`);
}

...

7. Module Test

7.1 Component Testplan

Testcase ID Feature ID Test Description
TC.REST.001.F LF110, LF100, LF30 Black Box test. The test case verifies that the REST API GET calls work as documented in the SRS
TC.REST.002.F LF110, LF100, LF30 Black Box test. The test case verifies that the REST API POST call works as documented in the SRS.
TC.REST.003.F LF110, LF100, LF30 Black Box test. The test case verifies that the REST API DELETE call works as documented in the SRS.
TC.REST.004.F LF110, LF100, LF30 Black Box test. The test case verifies that the REST API PUT call works as documented in the SRS.

7.2 Component Testreport

Test-ID Pass/Fail Testfailure Oberservation Date Tester
TC.REST.001.F PASS - 19.5.2021 Johannes Timter
TC.REST.002.F PASS - 19.5.2021 Johannes Timter
TC.REST.003.F PASS - 19.5.2021 Johannes Timter
TC.REST.004.F PASS - 19.5.2021 Johannes Timter

8. Summary

The REST API (Backend) module is the most important and powerful module of all. It handles a lot of tasks and contains the conversion for the .aml files.

All endpoints are documented in the swagger files. Other developers are able to understand them. Therefore, because of our well documented source code, other developers can edit or add new features to our backend.

The backend is expendable. Any new feature can be added very simply. The file module can be edited as well in future.

9. Appendix

9.1 References

  1. SRS (System Requirements Specification)
  2. SAS (System Architecuture Specification)
  3. Systemtestplan

9.2 Sourcecode

The source code of this module can be found here: aml-database-management-api

9.3 Module Test Cases

Testcase <TC.REST.001.F> (GET calls)

Testcase ID: TC.REST.001.F
Testcase Name: GET calls
Requirement ID(s): LF110, LF100, LF30
Description: The test case verifies that the REST API GET calls work as documented in the SRS

Test Steps:

Step Action Expected Result
1 Use the GUI to upload two files Two files are uploaded and visible in the table in the home page
2 Open Postman and send the following GET request: localhost:3000/file The two files that are present in the database are returned in the format as seen below, along with HTTP-Code 200.
3 Send the following GET request: localhost:3000/file/{mongoDBID}, where {mongoDBID} is the _id attribute of the first file that has been received in step 2 Verify that only the first uploaded file is returned in the format below, along with HTTP-Code 200.
{
"status": "success",
    "data": {
        "name": "TINF19C_AML_Library.aml",
        "content":  string
    }
}

Testcase <TC.REST.002.F> (POST call)

Testcase ID: TC.REST.002.F
Testcase Name: POST call
Requirement ID(s): LF110, LF100, LF30
Description: The test case verifies that the REST API POST call works as documented in the SRS

Test Steps:

Step Action Expected Result
1 Open Postman and send the following POST request: localhost:3000/file and use the Testdata below as body Verify that you receive a JSON response containing "status": "success", as well as the just object that hast just been added
2 Send the following GET request: localhost:3000/file Verify that the file is now present in the database

Testdata:

{
    "file": {
    "base64": "data:application/xml;base64,ZnVlciBiYWxsdWY=",
    "name": "test-file.xml",
    "size": 560,
    "type": "text/xml"
    }
}

Testcase <TC.REST.003.F> (DELETE call)

Testcase ID: TC.REST.003.F
Testcase Name: DELETE call
Requirement ID(s): LF110, LF100, LF30
Description: The test case verifies that the REST API DELETE call works as documented in the SRS

Test Steps:

Step Action Expected Result
1 Use the GUI to upload two files Two files are uploaded and visible in the table in the home page
2 Open Postman and send the following GET request: localhost:3000/file. Remember the _id attribute of one of the files One of the _id attributes is remembered.
3 Send the following DELETE request: localhost:3000/file/{mongoDBID}, where {mongoDBID} is the _id attribute of the first file that has been received in step 2. You receive "status": "success" as well as the a response in the format below, along with HTTP-Code 200.
2 Send the following GET request: localhost:3000/file Verify only the not deleted file is not returned anymore, along with HTTP-Code 200.
{
    "status": "success",
    "data": {
        "n": 1,
        "ok": 1,
        "deletedCount": 1
    }
}

Testcase <TC.REST.004.F> (PUT call)

Testcase ID: TC.REST.004.F
Testcase Name: PUT call
Requirement ID(s): LF110, LF100, LF30
Description: The test case verifies that the REST API PUT call works as documented in the SRS

Test Steps:

Step Action Expected Result
1 Open Postman and send the following GET request: localhost:3000/file. Remember the _id attribute of one of the files -
2 Send the following PUT request: localhost:3000/file/id={mongoDBID}, where {mongoDBID} is the _id attribute of the first file that has been received in step 1. Use the JSON testdata below as body of the PUT request. You receive a JSON response containing "status": "success", as well as the object that hast just been manipulated (name and content)
3 Send the following GET request: localhost:3000/file The content and name of the file have been changed according to the name and content of the testdata.

Testdata:

{
  "file": {
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"aml\" ContentType=\"model/vnd.automationml+xml\" /><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" /><Default Extension=\"xsd\" ContentType=\"text/xml\" /><Default Extension=\"png\" ContentType=\"image/png\" /><Default Extension=\"bmp\" ContentType=\"image/bmp\" /><Default Extension=\"edz\"ContentType=\"application/octet-stream\" /><Default Extension=\"xml\" ContentType=\"text/xml\" /></Types>",
    "name": "New_Test_Name.xml"
  }
}
Clone this wiki locally