Strapi

Table of Contents

  1. Purpose

  2. About Strapi System

  3. Stakeholders

  4. Business Goals

  5. Architecturally Significant Requirements (ASR)

  6. Utility Tree

  7. Quality Attribute Scenarios (QAS)

  8. Module View

    • Primary Presentation

    • Element Catalog

      • Elements and Properties

      • Relations and Properties

      • Element Behaviour

    • Context Diagram

    • Rationale

  9. Component and Connector View

    • Primary Presentation

    • Element Catalog

      • Elements and Properties

      • Relations and Properties

      • Element Behaviour

    • Context Diagram

    • Variability Guide

    • Rationale

  10. Code Quality and Technical Debt

  11. Conclusion

Team

Supervisor

  • Neil Ernst

  • David Johnson

1. Purpose

The purpose of this document is to provide an overview of Strapi, an open source content manager application, and its architecture details. Various components which outlines the architecture of the system are included such as stakeholders involved, business goals, architecturally significant requirements, utility tree and related quality attribute scenarios, breakdown of one module view, breakdown of one component and connector view, project's code quality and technical debt founded.

2. About Strapi System

Strapi is an advance open-source Content Management Framework (CMF) to build powerful application programming interface (API) with little effort. It is designed for building production-ready APIs with Node.js, and to build scalable modern applications using a service-oriented architecture to fit with any web project that requires an API.

Specifically, Strapi is composed of a dashboard interface where users are able to create, put online, and manage an API without writing a line of code. For developers with more coding experience, Strapi is based on top of a model-view-controller (MVC) Node.js framework to customise the APIs.

3. Stakeholders

Role

Concern

Instances

Ownership

MIT License Copyright (c) 2015-2018 Strapi Solutions

Core Management

CEO and co-founder: Pierre Burgy

Core Developers & Testers

Construct and deploy the system from specifications, and test the system to ensure that it is suitable for use.

Software Engineer: Cyril Lopez

Maintainers

Manage the evolution of the system once it is operational

Strapi's Core Management Team

Communicators & Marketers

Explain the system to other stakeholders via its documentation and training materials

Strapi's Core Management Team

Support Staff

Provide support to users for the product or system when it is running

Strapi's Core Developers

Vendor & suppliers

Build and/or supply the hardware, software, or infrastructure on which the system will run

Upper (incubator)

Assessors

Oversee the system’s conformance to standards and legal regulation

MIT License Copyright (c) 2015-2018 Strapi Solutions

Investors

Investors are the Strapi's core management team/Strapi's maintainers

Sponsors

Strapi Solutions is the author and primary sponsor of the Strapi open-source project. Together with the community of maintainers and contributors, Strapi Solutions insure Strapi project sustainability, features evolution and bugfix patches / community growth

Community maintainers

Contributors

Strapi is open-source under the MIT license. All the work done is available on GitHub. The core team and the contributors send pull requests which go through the same validation process.

Strapi's core developers

End-users

Define the system’s functionality and ultimately make use of it

4. Business Goals

  • Enhance the user experience, learnability, satisfaction, and the flexibility of the system.

  • To be able to meet various business needs so that the database offered would correspond with the end-client’s database to increase the number of clients.

  • To be more reliable, and to have safeguards against cyber attacks. Meet security policies of large enterprises and to protect client’s information.

  • Enhance the website’s performance and load time to be more responsive.

  • To be able to integrate with front-end clients and platforms.

The Business model of such systems relies on offering fully hosted, scalable instances of the API for paid subscription. They will also provide consultation services for large organizations. Achieving these goals will allow Strapi to compete with other content management systems.

5. Architecturally Significant Requirements (ASR)

  1. Strapi must be able to process atleast 1000 API requests processed per second at peak load

  2. There must be maximum of 1 second response time for API requests

  3. There must be maximum of 1.5 second response time for admin dashboard operations

  4. A new person must be able to gain proficiency with using Strapi in no more than 7 business days

  5. The users should have the ability to define, create, update and delete content for the API without changing the source code

  6. A maintainer encountering issues within Strapi must fix the bug and distribute the bug fix in no more than 7 business days

  7. A maintainer modifying Strapi and its components to meet new business requirements should be completed in no more than 3 business weeks

  8. Adding or removing plugins to modify the functionality of the dashboard or Plunew feature that the user implemented should be in no more than 30 minutes

  9. The system must resist unauthorized access immediately

  10. Unauthorized users who can only access API content must not be able to modify or add new content

  11. Developers must be able to install important updates and plugins without affecting the availability of the API

  12. Support information and guidance must be provided via the official Strapi documentation or the available community channels such as StackOverflow, GitHub, Slack, Twitter and Facebook and professional support via e-mail

6. Utility Tree

7. Quality Attribute Scenarios

A scenario for security authentication

Aspect

Details

Scenario Name

Security authentication scenario

Business Goals

Strapi should be more reliable, have safeguards against unauthorized users, and meet security policies to protect client's information

Quality Attributes

Security

Stimulus

Account locked: Unauthorized access

Stimulus Source

Unknown user

Response

System logs information in audit trail; Denial of access (error message)

Response Measure

Access is denied temporarily for the account; Maintainer analyses audit trail for possible attack

A scenario for maintainability (issues)

Aspect

Details

Scenario Name

Maintainability scenario (issue fixes)

Business Goals

Strapi should keep improving user's satisfaction and experience

Quality Attributes

Maintainability

Stimulus

Non-working functionality: incorrect response to user's request

Stimulus Source

Correctly identified individuals (Strapi users)

Response

System maintains audit trail; Individual issues a bug ticket on GitHub; GitHub system will notify Strapi’s maintenance team

Response Measure

Correct response is restored within 2 days and source of issue is identified

A scenario for availability

Aspect

Details

Scenario

Availability scenario

Business Goals

Strapi system should be up and running with a maximum of 1% downtime per year

Quality Attributes

Availability

Stimulus

New alpha releases: updates

Stimulus Source

Internal to system

Response

Inform users to continue using the system

Response Measure

No downtime

8. Module View

The Primary Presentation

Element Catalog

Elements and Properties

StrapiApp

StrapiApp stands for Strapi Application. It is an advanced open-source Content Management Framework (CMF) to build powerful API with no effort

Strapi Package

The primary functionality of this package is to provide the system to load various dependencies and configurations while installing and initializing system.

Strapi-generate-api service

This package contains all the default functionalities to generate new API. It uses bookshelf and mongoose as ORM.

Strapi-generate-model service

This package contains functionalities to generate a model for a Strapi API. Its contains a before and index module. This before function is run before generating targets to validate, configure defaults, get extra dependencies, etc. Default template for ORM used here is Mongoose.

Strapi generate controller service

This package contains all the default functionalities to generate a controller for a Strapi API.

Strapi-generate-plugin service

This package contains functionalities to generate a plugin for a Strapi application. The list of all generated plugins can be found at admin/list-plugins. It contains a json package module which exposes main package JSON of the application with basic info, dependencies, etc. and a route package which exposes main routes of the generated plugin

Strapi generate plugin helper service

This package contains functionalities to Strapi application helper for Strapi plugins development. Such as adding check mark symbol and progress symbol while adding plugins.

Strapi-mongoose service

The functionality of this package is a hook that allows you to use the Mongoose ORM. Provides a straight-forward, schema-based solution to model application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box.

Strapi-content-manager service

This provides one of the primary functionalities of the system. A set of functions called "actions" are defined for ContentManager. It contains functionalities to finds, creates, update and delete entries. Also manages relationships between entries.

Strapi-content-type-manager service

This provides one of the primary functionalities of the system. This package provides plugin to create content type (API).

Strapi-users-and-permission service

The primary function of this package is to provide various user permission management services such as: 1. Connect the user to the third-party provider and manage. 2. Manage user and roles 2. Manage user permissions 3. Various validation functions such as user check, password check, email check etc. This package contains functionalities to protect users API with a full-authentication process based on JWT. The permissions are handled using model, controller and service which provides set of functions called "actions" of the users-permissions plugin.

Strapi-utils

This module contains functionalities for shared utilities between Strapi packages such as: 1. Find controller's location 2. Export shared utilities 3. Creates Joi based object schemas from JSON 4. Logger 5. Set of utils for models 6. Regex utilities

MongoDB

MongoDB is a cross-platform document-oriented database program that uses JSON-like documents with schemas.

MySQL

MySQL is an open-source relational database management system.

PostgreSQL

PostgreSQL is an object-relational database management system with an emphasis on extensibility and standards compliance

Nodemailer service

Nodemailer service is utilised by Strapi helper plugin package. The primary fucntion of this service to help system admin and other users with e-mail functionalilties.

Relations and Properties

The << uses >> indicates that a module or package uses the other module/ package

Element Behaviour

This section documents key behavioural questions for the view created above. This is represented by four diagrams: content manager, content type builder, manage plugins, and manage users & permissions for the Strapi system. Among these four diagrams, content manager and content type builder are shown as state machine behaviour diagrams (static behaviour modelling), and manage plugins and manage users & permissions are shown using activity diagrams (trace oriented representations). Using these two types of behaviour modelling will cover all the aspects (stimulus, activity, ordering, and elements) and behaviour (static and trace-based) with clarity.

Manage Behaviour

This behaviour of system is related to the content manager plugin. This plugin allows the administrator to manage user details and allows other users to manage products. The primary functionality of this plugin is to add, edit and delete. Once the entry is made on form, the database is updated with new values.

Build Content Type

This behaviour of system is related to the content type builder plugin. This plugin allows the administrator to manage user’s page and functionalities including roles and permissions. The primary functionality of this plugin is to create new APIs which can be utilized by other users. Once the entry is made on form, the database is updated with new values.

Manage Plugins

The administrator is the only user who is allowed to use this functionality. This functionality allows the administrator to install new plugins from the ‘marketplace’ and remove existing plugins.

Manage User and Permissions

The administrator is the only user who utilizes this functionality. This functionality allows the administrator to add, remove, or update user permissions (i.e. count, create, find, update) for a specific plugin.

Context Diagram

Rationale

Maintainability

The core plugins of the system namely Content Manager, Content type Builder, User Permission is separated from the core admin package to ease the maintainability of the system, and allows the community to easily modify and add functionality or even replace those core plugins with third party ones. The plugin architecture is divided mainly into the admin folder which contains the frontend components of the plugin, the config which contains the policies and different http routes of the plugin. In addition, controllers, middlewares, and services is also defined in different files in the plugin to make the readability and bug fixes easier. The system also provides an easy to use command line interface to ease performing upgrades and services for developers. Moreover, strapi makes good use of many open source libraries that accomplish tasks like connecting with different databases, authentication, DOM manipulation, and the team chose well documented libraries that allows developers to quickly learn them and accomplish complex tasks easier. Some of the external libraries are not used directly by code and they chose to develop layers such as the HTTP layer on top of the Koa JS library so that when external library choose to make changes, the team will only have to change the code in that specific layer to upgrade the code. The Strapi HTTP layer work to provide structural convention to the Node JS applications and provides routing used by many services in Strapi. Overall the system seems to be not tightly coupled as different services is separated into different files or classes, and each service is also well structured as it uses the Model View controller architectural pattern.

Availability

The system uses the monorepo architecture to organize the code, which makes deploying, and updating parts of the system easy without dependencies issues. So all the modules like react, koa JS, and database libraries like mongoose are all included in the same project. Although, this makes the project looks more complicated, it make updating the code and keeping everything in sync much easier. Updating the system configuration is as easy as clicking a button on the dashboard, or changing the config file in folders. The system also allows for multi environment setup which makes it easy to test new API in a testing environment before publishing it to the production one which increase the availability of the system, and reduces errors. Moreover, it uses Node Package manager for installing and upgrading which results in easy upgrade process. However, We recommend that the system should include an automatic upgrade of the CMS that handles database backups, code base bucks to allow for reverting back in case of any unexpected error.

Authentication & Authorization

The authentication plugin provides the main functionality of registering, logging, resetting user password. JSON Web Tokens and author OAuth are both supported by the system. Strapi uses Grant, an OAuth Middleware for Koa, which gives the access to Facebook, Google, Github, Linkedin authentication. The system also allows to authorize users according to certain roles and permission and allow them to access only certain actions and deny access to others. The authorization can be setup for have CRUD access to the content generated by the Content Manager. However, users can change the permission to access plugin routes based on the policy file in the plugin folder. The Authorization and Authentication code is well structured, and can be easily expanded to allow for more Oauth authentication providers, or custom plugin routes.

9. Component and Connector View

Element Catalog

Elements and Properties

User

Any agent that can generate and send and receive HTTP requests.

Routing

HTTP routing provided by the Koa.js library that maps HTTP paths to JavaScript callbacks (functions).

API Generator

This module contains logic for generating data APIs. The ODM / ORM is used to retrieve and store the model for the data.

Authentication

This module contains logic for authorization of users such as login, change password, forget password, and registration. In the case of forget password and registration, the external service provider Nodemailer is used for sending emails. A third party authentication provider may by used such Google, Facebook, GitHub and LinkedIn. The ODM / ORM is used to store and retrieve user information.

API Consumer

This module contains logic for generated APIs such as finding, creating, updating, and deleting data entries. The ODM / ORM is used to store and retrieve data entries.

Authorization

This module contains logic for verifying and updating access to resources. The ODM / ORM is used retrieve and store user permissions.

ODM / ORM

Object Document Mapper provided by Mongoose.js for non-relational database or Object Relational Mapper provided by Bookshelf.js for relational database.

Users & API DB

The database stores users, permissions, and the API content itself. This database can either be relational or non-relational. If relational, the Bookshelf.js ORM library is used and the database is configured with either PostgreSQL, MySQL or SQLite3. If non-relational, the Moongose.js ORM library is used and the database is configured with MongoDB.

Third Party Auth Service

An external authentication service provider such as Google, Facebook, GitHub and LinkedIn.

Relations and Properties

Services Endpoint

A port for communication between modules or services.

HTTP / HTTPS

A HTTP / HTTPS request.

Data Access

A database connection for data transaction.

Service Call

A call to another library or module.

JavaScript Call

A JavaScript function call.

Element Interface

Auth Service

Identity

Login Interface login (identifier, password)

Resource

A. Syntax The identifier parameter can be either an email or an username

B. Semantics Pre-conditions:

  • User is properly registered into the system

  • User inputted valid identifier and password

Post-conditions:

  • User is assigned a token on valid login

  • User data will be available in the response payload (email, role, provider, etc.)

Data type

HTTP request with JSON key/value pairs; string

Error Handling

Bad request on invalid identifier and/or password

Error: {
    "statusCode": 400,
    "error": "Bad Request",
    "message": "Please provide your username or your e-mail."
}

Variability

When using external Authentication providers such as Facebook, Google, GitHub or LinkedIn, the client first sends a request to any of these servers, and request the token from them. The user will then use this token and send a request to the Resource Server ( Strapi ) to retrieve data. Strapi will then send a request to the Authorization server to verify the token received. Strapi uses Grant (https://github.com/simov/grant) libraries to integrate with providers.

In the case of Google OAuth2, Strapi will send a request to https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=1/fFBGRNJru1FQd44AzqT3Zg

Google will then respond with user information.

{                     
 "audience":"8819981768.apps.googleusercontent.com",         
"user_id":"123456789", 
"scope":"https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",             
"expires_in":436                                             
}

Quality Attribute

Security Authentication.

Rationale

This authentication plugin interface allows the user to login to Strapi via local or external provider. The system authenticates users by their identifier and password.

Usage Guide

Request: POST request to /auth/local/

data: {
  "identifier": "admin",
  "password": "password"
}

Response

{
    "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YTlmNDdiZDM2NTFmZDJmYTJmMzQ4YTQiLCJpYXQiOjE1MjAzOTEwNjIsImV4cCI6MTUyMjk4MzA2Mn0.70UZNQ9trWYxOKq0iKqgPhZsccePfx3fJenprzgwgRw",
    "user": {
        "_id": "5a9f47bd3651fd2fa2f348a4",
        "username": "admin",
        "email": "khaled@uvic.ca",
        "provider": "local", 
        "role": {
            "_id": "5a9f47a53651fd2fa2f3482c",
            "name": "Administrator",
            "description": "These users have all access in the project.",
            "type": "root",
            "__v": 0
        },
        "__v": 0
    }
}

API Service

Identity: Send Authenticated API Request Interface

Resource: A. Syntax To send an authenticate request, we specify one of the CRUD operations needed, and the HTTP request with JSON-Web-Token (JWT).

 headers: {
    Authorization: `Bearer ${token}`
  },

B. Semantics

Pre-condition:

  • User has been assigned a ‘‘JWT”

  • Permissions are properly set for user

Post-condition:

  • User is able to find/ findOne/ create/ update/ delete/ etc.

Data type:

HTTP request with JSON key/value; string

Error Handling:

When trying to access an entry that is not found:

{
    "statusCode": 404,
    "error": "Not Found",
    "message": "Not Found"
}

When accessing information with an invalid JWT. ( authentication is needed now ):

{
    "statusCode": 401,
    "error": "Unauthorized",
    "message": "Invalid Token"
}

Variability: We can send the following different requests:

findOne      GET Request         /product/:id
find         GET Request         /product + Filters
create          POST Request            /product
delete         DELETE Request      /product/:id
update        PUT Request         /product/:id

Configurability of data access: To configure data storage so that it supports various database vendors, queries will go through ORMs like mongoose and bookshelf to retrieve the data without hindering the specific details of the different database vendors.

Quality Attribute:

Security Authentication

Rationale:

This interface authenticates different requests like find, update, delete etc. using a JSON-Web-Token provided at the time of login so that there are no unauthorized changes in the API. Filters are operators that can be included in the request to specify the information needed. GET /product?price_gte=3 // Return products with price greater than 3

Usage Guide:

Specify a CRUD operation, and send the request with the JSON-Web-Token received upon login. Request: GET request to /product/5a9f4b8857ca5234de919d10

Response: (successful retrieval for findOne)

    {
        "_id": "5a9f4b8857ca5234de919d10",
        "title": "article1",
        "description": "test",
        "__v": 0,
        "id": "5a9f4b8857ca5234de919d10"
    }

Element Behaviour

This section documents key behavioural questions for the interfaces described above. Authentication can be broken down and represented by two diagrams: login authentication and authenticated API request for Content Manager for the Strapi system. Among these two diagrams, login authentication is shown as multilayered sequence diagram (trace oriented representation), and authenticated API request is shown using state machine behaviour diagram (static behaviour modelling). Using these two types of behaviour modelling will cover all the aspects (stimulus, activity, ordering, and elements) and behaviour (static and trace-based) with clarity.

Login authentication

This behaviour of the system is related to the login authentication for Strapi. This interface shows the data flow within the system for the login aspect of the system. The primary functionality of this tool is to authenticate users through their

identifier

and

password

. Once the entry is made on the form, the user will be logged into the system.

Authenticated API Request for Content Manager

This behaviour of system is related to the content manager plugin. This interface allows the users to manage entries within the system. The primary functionality of this plugin is to add, edit, delete, findOne, and find. Once the entry is made on form, the database is updated with new values. There will be error codes and messages when there is unauthorized access, content conflicts, content not found, and etc.

Context Diagram

Variability Guide

Add or remove Authentication or Third party authentication The system allows user to login by adding various partner authentication providers such as Facebook, Google, Github and LinkedIn using OAuth and OAuth2 protocols and implementing the auth provider interface. At runtime Authentication service makes the call to provider on the basis of users request after which the type of the provider is identified by querying the database and connection is established which is variable on the basis of one of the provider partner.

Rationale

Strapi handles Authentication and Authorization to validate API Requests made by the user. Using postman to make requests and VS code debugger to run through the code, we have identified the main libraries and services needed for the server to respond back with the information requested. Strapi handles authentication using a local Provider (JWT), or external providers such as Google. The system can also store user information with various database provider; however, we have mainly focused on mongoDB. Once a request is made, the request goes through the Strapi HTTP layer that sits on top of Koa JS. The routing configuration file has a list of all the possible requests that a client can make, and sends this request to the controller that is responsible of handling it. If the user send a request without an Authentication Token, the user will be given a guest role, otherwise the role is identified in the the users table in the database. To verify whether a specific user role has access to the actions requested, Strapi has to communicate with the database using the mongoose or bookshelf ORM. Strapi choses to have three different collections in the database to carry user information namely: user, roles, and permission.

User collection: A list of all users, and their roles

{ "_id" : ObjectId(":ID"), "username" : "admin", "password" : ":hashed_password", "email" : "khaled@uvic.ca", "provider" : "local", "role" : ObjectId("Role_ID"), "__v" : 0 }

Roles collection: A list of all possible roles, and its description

{ "_id" : ObjectId("Role_ID"), "name" : "Administrator", "description" : "These users have all access in the project.", "type" : "root", "__v" : 0 }

Permission collection: The permission table has information of the different actions granted for each role. For instance, a guest user can have access to read content, but not deleting it.

{ "_id" : ObjectId("permision_ID"), "type" : "application", "controller" : "blog", "action" : "create", "enabled" : true, "policy" : "", "role" : ObjectId("Role_ID"), "__v" : 0 }

Once this information is retrieved from a database, Strapi Users Authorization controller will then validates the request by checking if the user is allowed to perform the requested action. Strapi will then respond with the content requested. The modules of the system are loosely decoupled, and can be easily expanded as the Grant library used by strapi already support 150 different auth provider.

10. Code Quality and Technical Debt

Using SonarCloud / SonarQube

SonarCloud is a cloud service based on SonarQube provided by SonarSource. It is an analytic tool to examine the code quality for open source projects. Using SonarCloud to inspect Strapi, it provided an analysis of code duplications, bad practices, complexity, and technical debt load. The primary metrics used to analyze this project are bugs, code smells, vulnerability, coverage, and duplications.

  • Bugs: the number of errors, flaws, failures or faults within the codes

  • Code smells: The number of bad practices in writing code. These are measured in hours and days (8-hour day is assumed).

    These two metrics can be classified as:

    • Blocker: Error with high probability of impact on the behavior of the applications

    • Critical: Error with low probability of impact on the behavior of the application or an issue that represents a security flaw

    • Major: Quality defect that may have a high impact on developer productivity

    • Minor: Quality defect that may have a low impact on developer productivity

    • Info: The code does not have any error or quality flaw, only a finding. It is not known if it is a risk to safety or impact on productivity

  • Vulnerabilities: The number of weakness that can be exploited

  • Coverage: The amount of source code has been covered by the unit tests

  • Duplications: The number of repeated blocks of code, files, number of lines, and percentage of duplicated lines

Most of these metrics is associated to a quality attribute. For example, bugs are related to maintainability and code smells are related to maintainability. These quality attributes are given a rating:

  • A : Zero (0) number of errors

  • B : At least one (1) minor error

  • C : At least one (1) major error

  • D : At least one (1) critical error

  • E : At least one (1) blocker error

The following link is the SonarQube Instance for the Strapi project and a screen shot is provided below on the main analytics dashboard.

SonarQube rated Strapi an A grade for code smells since it has a technical debt ratio of less than 5.0%. The rating for bugs is an E grade since there is at least one "blocker" type error.

Code Quality - Bugs

For the Strapi, the number of bugs can be represented in the table below:

Severity

Number of Bugs

Blocker

7

Critical

3

Major

93

Minor

10

Info

0

However, focusing on the JavaScript, Python, and C++ files, the number of bugs will be reduced to:

Severity

Number of Bugs

Blocker

7

Critical

3

Major

20

Minor

5

Info

0

Many of the “Minor” bugs within Strapi is the recommendation of not using a counter of type float due to the accumulation of rounding errors in “for” loops. This happens in several files in Strapi and can be fixed easily. This is due to the iterations of the floating-point loop counters; it may give a different number of iterations on different implementations.

There are a number of different “Major” bugs found using SonarQube. It can be grouped into two categories: unreachable statements and return errors. For the unreachable statements, there has been instances in the node-module files where there are statements after a jump statements like return and continue. Any statements in a block after these jump statements will never be reached.

For the return errors, the branches in the switch chains has the same implementation. For example, in the pugins/email/admin/src/containers/HomePage/reducer.js file, all cases for the switch chain returns the same result. This error occurs in multiple files. This adds towards the technical debt because it is assumed that there should be different cases that will return different states. However, none of the current files have different cases and thus creates an error.

The significant “Critical” bug that was found is an argument error. For example, a critical bug provided by SonarCloud is "callback" declared at line 829 expects 1 argument, but 3 were provided. These function calls should not pass extra arguments -- index and array in this example -- because the extra arguments passed in will be ignored by the function execution.

Code Quality - Code Duplication

Density = Number of duplicated lines / Total number of lines * 100

Duplication

Values

Density

6.7%

Duplicated Lines

8,822

Duplicated Blocks

313

Duplicated Files

75

Technical Debt - Poor Readability

One of the significant “Blocker” bugs is the “Add a ‘return’ statement to this callback.”. For example, consider the following code, specifically line 11 to 13. In the above code, we see a case switch block which uses mapping function to map the key values to new key values. It does not, however, return that new value inside the case block. A map function requires a return statement so that the new values are properly stored. Since this code does not have a return statement in its case blocks, the map function only iterates through the old values to map them to new values but does not return them properly. It does return the formErrors in the very end after case switch block but this is considered bad practice. Another example of this is shown below.

Technical Debt - Data duplication in Database

https://github.com/strapi/strapi/issues/797

To make Strapi compatible with different databases, the team choose to duplicate the id into two attributes id & _id. MongoDB required an _id field to each document and assign the primary index on it. While other SQL databases are using id attribute. Since they wanted to have the api requests exactly matches what is stored in the database, they duplicated the information twice.

Problems: increase in API response time. Increase in database storage

Solution The database ORM layer such as the strapi-mongoose should be able to handle this problem by selecting the appropriate attribute based on the database (Mongo or SQL). The issue was self admitted

Using CodeScene

The total number of lines of code found with Codes Scene is 74,755 with majority of code i.e. 37,555 lines of code is JavaScript. This is show in below screenshot,

Below is the analysis with Code Scene to identify Technical debt. We can start with “Hotspot analysis” of the code using Code scene. The 74,755 lines of code here is shown using bubble visualization. This is shown in below screenshot,

The blue circles shows the folders in the code base for Strapi. So this is the hierarchical visualization which shows the folder structure of Strapi. We can click on one of the folders to zoom in at any level of detail we want as shown below for the lib folder,

We can see that each file is represented as a circle as well. The size of each circle is different from each other. This size represents the amount of code present in that file. We can also see that circles represents different colors. The color represents the frequency and how much a contributor of Strapi work on each piece of code. This heuristic we can use here to read about interest rate of technical debt.

We can also see from the zoomed out diagram that there are lot of red circles which means there are lot of hotspots in the code. Codescene also provides something called refactoring targets. Code scene runs on machine learning algorithm which can prioritize technical debt, so this visualization is made on many different factors such as code complexity, how many contributors are involved and also how signification is this piece of code is from architecture point of view. On the package Strapi/lib we can see that there are red bubbles which shows hotspot and we can investigate that. We can see that on below screenshot,

We can also see there for that folder, Strapi.js is the file which is a red bubble and the total number of lines of code is 240. We can also see that this file has really high change frequency (77 commits). Once we have identified the hotspot our next question is how bad is it? We need to know if this code has started accumulating complexity. To answer this we can use code scene complexity trend analysis tool. We can see each historic revision of the code in the below analysis and calculates its complexity evolution,

We can see two lines here. The blue lines shows that collation of lines of code over time. We can see on the blue line that it started with 46 lines of code in July 2016 and now it is 240 lines of code. That says it accumulated almost 200 lines of code over past one year. A bit more serious is the red line which shows the code complexity at each point of time. We can clearly see that its been increasing ever since and after Feb 2017 it started increasing drastically till date. The complexity is still increasing and refactoring needs to be done here before it increases further. The core team can rectify this issue using x-ray analysis of code scene tool. With this analysis we can see the same results as before but at functional level,

Here code scene parses the Strapi code here to look at what function each commit hits. This analyses do pretty well prioritizing the list of refactoring function of Strapi. We can see here the most prioritized hotspot here is Strapi.constructor. We can see that it has accumulated 29 commits. So we can see this is the functions which has been changed a lot. We can see in the next column that shows this function has 61 line of code. Also, For Strapi-analysis/packages/strapi/lib/Strapi.js we can analyse something called internal temporal coupling. This is about functions those are evolve together. This is shown in below screenshot,

We can see here, we have two modules Strapi.reload and Strapi.stop. This says that each time there is a code change in one module there is change in the coupled module as well. The degree of coupling says the percentage of predictable change and that 76 percent here which is quite high. We can also see that this has happened 13 times. The last column says about the similarity of code which is 69 percent which is also quite high here. We can provide the same analysis for other red bubbles. But the critical ones should be analysed. One of those is shown below,

We can see that this file contains much higher amount of lines of code (768) which has higher complexity as well as shown below,

X-ray results show at the functional level that which function has been more complex inside that file,

We can see that module.exports has been changed a lot many times and contains 970 lines of code which quite large for a single module.

11. Conclusion

Strapi content Management framework was understood and reviewed carefully to find whether the business goals and quality attributes were satisfied, and what possible improvements can be made. The system was mainly created to enhance the experience of developers when developing websites or apps by handling content modeling, authentication & authorization, and other common functionality task. Throughout the course, we learned about how large scale projects are architected and how code should be organized to enhance various quality attributes of the system.

Last updated