GithubHelp home page GithubHelp logo

sucrose0413 / solen.api Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 0.0 785 KB

This project represents the API or the « back end » of Solen LMS solution. It's built using ASP.NET Core and following the principles of Clean Architecture by Robert C. Martin (aka Uncle Bob).

Home Page: https://demo.solenlms.com

C# 97.92% Gherkin 2.08%

solen.api's Introduction

Solen.Api

This project represents the API or the « back end » of Solen LMS solution. It's built using ASP.NET Core and following the principles of Clean Architecture by Robert C. Martin (aka Uncle Bob).

Table of Contents

Getting Started

Prerequisites

What you need to be installed in your machine to run this app :

Getting the source code

First, you should get the source code from the GitHub repository. You can either clone the repo or just download it as a Zip file.

# clone the repo
git clone https://github.com/imanys/Solen.Api.git

Application Settings

The configuration file appsettings.json is not checked into the repository. Instead, there is a template file called appsettings.template.json located in Src\Main\Solen directory which you can rename to appsettings.json.

Click here to see all the settings

{
  "AppSettings": {
    // The application uses SignalR to send Web Socket notifications. In order to enable Cross-Origin Requests (CORS), SignalR requires to specify the expected origins.
    // The default value corresponds to the address used by Solen-SPA App (https://github.com/imanys/Solen-SPA) when it's locally installed.
    "CorsOrigins": "http://localhost:4200"
  },
  "ConnectionStrings": {
    "Default": "Server=localhost; Database=Solen-db; Uid=app-user; Pwd=app-user-password"
  },
  "Serilog": {
    "Using": [],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Information",
        "System": "Warning"
      }
    },
    "Enrich": [
      "FromLogContext",
      "WithMachineName",
      "WithProcessId",
      "WithThreadId"
    ],
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "Seq",
        "Args": {
          "serverUrl": "http://localhost:8081"
        }
      }
    ]
  },
  "Security": {
    "Key": "JWT Tokens secret key", // The secret key used to generate JWT Tokens

    "JwtTokenExpiryTimeInMinutes": "1", // JWT Token expiry time in minutes. JWT Tokens should be short-lived
    "RefreshTokenExpiryTimeInDays": "1", // Refresh Token expiry time in days.
    "IsSigninUpEnabled": true // Indicates whether or not the signing up process should be enabled
  },
  "AllowedHosts": "*",
  "SwaggerOptions": {
    "Enable": true, // Indicates whether or not swagger should be available
    "Url": "/swagger/v1/swagger.json",
    "Name": "Solen LMS API"
  },
  "EmailSettings": {
    "ApiKey": "sendGrid API Key", // Solen API uses this field as the SendGrid key to send emails
    "From": "[email protected]",
    "IsPickupDirectory": true, // When it's set to true, emails are generated in a Pickup directory. Otherwise, the emails are sent by SendGrid.
    "PickupDirectory": "C:\\Temp\\SolenMails" // The path to the Pickup directory
  },
  // Local storage settings. By default, the app uses the local storage to store resources
  "LocalStorageSettings": {
    "BaseUrl": "http://localhost:5000",
    "ResourcesFolder": "Resources",
    "ImagesFolder": "Images",
    "VideosFolder": "Videos",
    "RawFolder": "Raw"
  },
  "CompleteOrganizationSigningUpPageInfo": {
    "Url": "http://localhost:4200/signing-up/organization/complete",
    "TokenParameterName": "token"
  },
  "CompleteUserSigningUpPageInfo": {
    "Url": "http://localhost:4200/signing-up/user",
    "TokenParameterName": "token"
  },
  "ResetPasswordPageInfo": {
    "Url": "http://localhost:4200/auth/reset",
    "TokenParameterName": "token"
  }
}

💣 Since the application checks whether the database is up to date with all EF Core migrations at the startup time, you should define a valid ConnectionStrings before running the app.

Building and running the application

# change directory to the « Main » folder
cd Solen.Api/Src/Main/Solen

# build the solution
dotnet build Solen.Api.sln

# run the solution
dotnet run

The application should now be listening on http://localhost:5000 :

Solen API Discovery

There are three ways to « discover » Solen API :

Swagger (OpenAPI)

A great way to discover and tests APIs, is using Swagger / OpenAPI. To access the Swagger UI via a browser, run Solen API application, access the application's URL and add /swagger at the end of it. The swagger UI should show up :

Click here to see the screenshot

⚠️ make sur that Swagger is enabled ("Enable": true) in the SwaggerOptions section of the appsettings.json file.

Living documentation

As the application uses Specflow (a framework to support BDD for .NET applications), we can use tools like Pickles to generate a living documentation using the specifications written in Gherkin. To access this documentation, navigate to https://doc.api.solenlms.com.

⚠️ The application is not fully covered by Automated Acceptance Tests, thus the living documentation is not yet complete!

Solen SPA

Finally, you can install Solen SPA, the Angular « front end » application of Solen LMS, and check out how Solen SPA makes calls to Solen API.

Clean Architecture (Quick Overview)

Introduction

As stated at the beginning of this document, the Solen API architecture is inspired by the Clean Architecture.

The idea of Clean Architecture, is to put the Business Logic and Rules (aka Policies) at the centre of the design, and put the Infrastructure (aka mechanisms) at the edges of this design.

The Business Rules are divided between two layers: the Domain layer (aka Entities) and the Application layer (aka Use Cases). The Domain layer contains the enterprise business rules, and the Application layer contains the application business rules. The difference being that enterprise rules could be shared with other systems whereas application rules would typically be specific to this system.

These two layers form what is called the Core of the system.

The Dependency Rule

What makes this architecture work is that all dependencies must flow inwards. The Core of the system has no dependencies on any outside layers. Infrastructure, Persistence... depend on Core, but not on one another.

Source code dependencies must point only inward, toward high-level policies.

This is the architectural application of the Dependecy Inversion Principle.

Characteristics of a Clean Architecture

A Clean Architecture produces systems that have the following characteristics :

  • Independent of frameworks. Core should not be dependent on external frameworks such as Entity Framework.
  • Testable. The business rules can be tested without the UI, database, web server, or any other external element.
  • Independent of the UI. The UI can change easily. For example, we can swap out the Web UI for a Console UI, or Angular for React. Logic is contained within Core, so changing the UI will not impact the system.
  • Independent of the database. We can change SQL Server for Oracle, Mongo, or something else. Core is not bound to the database.
  • Independent of any external agency. Core simply doesn't know anything about the outside world.

For further reading about Clean Architecture, I highly recommend this book.

Architecture of Solen API

Overview

Domain Layer

This layer contains the Entities of Solen API. There are business objects that contain reusable Business Logic. There are absolutely NOT simple data structures. This layer is independent of data access concerns and has no dependencies.

Click here to see the `Domain Layer` structure

Application Layer

Click here to see the `Application Layer` structure

Use Cases

This layer encapsulates and implements all the Use Cases of Solen API. In general, each Use Case is independent of the others (Single Responsibility Principle).
For example, in the Users Management « module », modifying or deleting the Use Case InviteMembers will have absolutely no effects on the BlockUser Use Case.

CQRS Pattern

To tackle business complexity and keep use cases simple to read and maintain, the Application layer implements the architectural pattern CQRS. Using this pattern means clear separation between Commands (Write operations) and Queries (Read operations). This separation gives us, we developers, a clear picture of what pieces of code change the state of the application.

Click here to see an example of Use Cases (Commands and Queries)

Mediator Pattern

To keep the application business rules out the external layers and to prevent this layers from knowing much about the Business Logic, the Application layer implements the Mediator Pattern.

MediatR Library

To implement the CQRS Pattern and the Mediator Pattern easily, the Application layer makes use of an open source .NET library called MediatR. It allows in-process messaging and provides an elegant and powerful approach for writing CQRS. When starting using MediatR, whe should first define a Request. A Request can be either a Query or a Command.

Click here to see an example of a Request

Once a Request is created, we need a Handler to execute the Request.

Click here to see an example of a Request Handler

Requests Validation

When exposing public APIs, it is important to validate each incoming request to ensure that it meets all expected pre-conditions. The system should process valid requests but return an error for any invalid requests.
The validation process is part of the application business logic. Therefore, the responsibility for validating requests does not belong within the Web API or Console UI or whatsoever external interfaces, but rather in the Application layer.
To make the validation process easier, we make use of a popular .NET library for building validation rules called FLUENT VALIDATION. The other advantage of using this library, is we can make use of MediatR pipeline behaviours to validate automatically every request that requires validation before further processing occurs.

Click here to see an example of a Request Validator

Infrastructure layer

The Infrastructure layer contains by two sub-layers : The Persistence sub-layer and the Infrastructure sub-layer.

Persistence sub-layer

The Persistence layer is typically the implementations of all repository interfaces defined in the Application layer.

The layer is actually implemented based on Entity Framework Core. All the configurations related to EF Core are also implemented in this layer.

Infrastructure sub-layer

The Infrastructure sub-layer implements all interfaces (other than repositories ) from the Application layer to provide functionality to access external systems or to perform some technical tasks :

  • Sending notifications (Web Sockets with SignalR, Emails with SendGrid)
  • Accessing resource files (on File System or on the Cloud)
  • MediatR pipeline behaviours
  • Security (Passwords generator, JWT Tokens generator...)
  • ...

Presentation layer

The Presentation layer is the entry point to the system from the user’s point of view. Its primary concerns are routing requests to the Application layer. In the context of Solen API, the Presentation layer contains ASP.NET Core Web APIs. All the concerns related to the GUIs are handled by Solen SPA application.

Thin Controller vs Fat Controller

In the "traditional" way to write controllers, we usually implement some business logic flow in like as Validation, Mapping Objects, Return HTTP status code...

Example of a Fat Controller :

[HttpPost]
public async Task<IHttpActionResult> CreateCourse(CourseModel model) {
    if (!ModelState.IsValid) return BadRequest (ModelState);

    var course = new Course {
        Title = model.title
    };

    var result = await _coursesService.CreateCourse(course);

    if (!result.Succeeded) return GetErrorResult (result);

    return Ok ();
}

Using the Clean Architecture (where all the business logic and rules are implemented in the Core layer), and a library like Mediadtr, we can write controllers with few lines of code. With such dumb controllers, we have no need to test them.

Main

The Main is just the entry point to the application and where all configurations are registered (Dependency Injection, Security...).

Basic Use Case process flow

Automated Tests

Unit Tests

NUnit is the framework used for unit-testing all the Core layer components : Requests Handlers, Requests Validators, Services and Domain Objects.

Acceptance Tests

Specflow is the framework used to implement Acceptance Tests.

⚠️ The application Use Cases are not all covered by Acceptance Tests, yet! The work is in progress 🚧 😎

Contribution

For the moment, I will be the only contributor of the project. Nevertheless, you're welcome to report bugs or/and submit features by creating issues.

solen.api's People

Contributors

iliashamdaoui avatar dependabot-preview[bot] avatar sucrose0413 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.