Skip to content

CodeCoupler API

The CodeCoupler API is a modified Loopback boilerplate with integrated packages like cc-api-auth or dot-env for quick starting a backend.

Get Started

Install

  1. Create a new directory and start from there:
1
2
npm init @codecoupler/cc-api
npm i
  1. Create authentication database from the SQL File node_modules/@codecoupler/cc-api-auth/cc-api-auth.sql.

  2. Create a user allowing access to this database.

  3. Modify the database settings (host, user, password, database) in src/datasources/auth.datasourse.ts to match with the created database and user.
  4. Copy .env.default to .env and modify settings. You should at least change the JWT_SECRET from changeme to something cryptic.

Two Databases

This Package use a separate database to store the authentication data. It is recommended to name the authentication database like the main database finished with _auth. The extension with an underscore means that both databases are displayed grouped in phpMyAdmin. A good practice would also be to name the main database with the suffix _data if possible.

We are already ready to start, but the package.json could be fine-tuned at this point (or you do it later):

  1. Change name, version, description, author, keywords, homepage, license
  2. Remove private: "true" if you want to publish your code.
  3. Change the tag cc-api to the project name in the scripts docker:build and docker:run

Add your Main Database (The Quick Way)

Now we can add the main database to the project where the data are stored that we want to access via the API.

Step 1

1
lb4 datasource

You will be requested to enter a datasource name (type for example data) and then the credentials pointing to the target database.

Step 2

1
2
npm run build
lb4 discover --all
  1. Select the target database connection as specified above as Datasource-Name (not auth).
  2. In the second question you should select the recommended option CamelCase.

In some cases the terminal will hang after the message Models [...] created in src/models. You can stop here the execution with Ctrl-C.

Step 3

1
lb4 rest-crud
  1. Select the target database connection derived from the specified Datasource-Name (not AuthDatasource).
  2. In the next question all models should be selected and you have only to type Enter. Otherwise type a to select all models.

Step 4

Now open the file src/application.ts and search the following lines:

1
2
3
4
5
//Use this if you want to lock all rest endpoints with authentication by
//default. Do not forget to exclude the login controller in "sequence.ts".
//this.configure(AuthenticationBindings.COMPONENT).to({
//  defaultMetadata: {strategy: 'jwt'},
//});

Uncomment the last three lines:

1
2
3
4
5
//Use this if you want to lock all rest endpoints with authentication by
//default. Do not forget to exclude the login controller in "sequence.ts".
this.configure(AuthenticationBindings.COMPONENT).to({
  defaultMetadata: { strategy: "jwt" },
});

And put this line at the very beginning of the file:

1
import { AuthenticationBindings } from "@loopback/authentication";

Do not forget to save the file.

Step 5

Now open the file src/sequence.ts and search the following lines:

1
2
3
4
// If you have enabled the default authentication for
// all controllers by default, you should exclude here
// the login controller. Otherwise you cannot login:
// if (!request.path.endsWith('/auth/login') && !request.path.endsWith('/explorer/') && !request.path.endsWith('/openapi.json'))

Uncomment the last line:

1
2
3
4
// If you have enabled the default authentication for
// all controllers by default, you should exclude here
// the login controller. Otherwise you cannot login:
if (!request.path.endsWith('/auth/login') && !request.path.endsWith('/explorer/') && !request.path.endsWith('/openapi.json'))

Do not forget to save the file.

Quick Test

Now we start the project with npm start. The terminal will start a server listening on port 3000.

Start a browser and navigate to http://localhost:3000/. You should see a default page with two links. Please click on /explorer to start the API explorer.

Check the API here with the following steps:

  1. Go to the section AuthMeController and click on GET /auth/me > Try it out > Execute. The server response should be 401 Error: Unauthorized. You can do this test with almost any controller here. Search for the controller pointing to one of your models (not starting with Auth) and try it out.
  2. Go to the section AuthLoginController and click on POST /auth/login > Try it out and replace the request body with:
1
2
3
4
{
  "username": "admin",
  "password": "admin"
}
  1. Click on Execute. The server response should be 200 and the response body should contain a token.
  2. Go back to the section AuthMeController and click on GET /auth/me > Cancel > Try it out > Execute. The server response should be 200 and the response body should contain a structure of user informations. You can do this test with any controller here. Search for the controller pointing to one of your models (not starting with Auth) and try it out.

Ready

The API is now ready and you can execute all CRUD operations on any table in your database protected by an authetication and authorization mechanism.

To learn more about the authentication and authorization please read the documentation of the CodeCoupler API Auth package.

Disable default credentials

The library contains a line which ensures an initial login with the username "admin" and the password "admin". Do not forget to remove this line if you go into production.

You will find the line in the index.js:

1
await AddUserRolePermission(app, "admin", "admin", "admin", "admin.user");

Advanced Topics

Controllers and Repositories

In our example in Get Started we used the fastest method to create a REST API with authentication. In this case you do not have any repository or controller classes where you could inject your own logic. If you like to do so you have to create controllers and repositories.

First of all you should remove the folder model-endpoints if you have tried the "quick way". The created datasource definition and all the models can stay as they are.

To create repository classes you have to type:

1
lb4 repository
  1. Select the target database connection derived from the specified Datasource-Name (not AuthDataSource).
  2. In the next question type a to select all models.
  3. In the last question select the only option DefaultCrudRepository.

Now you can create for each repository a controller. You can create for each model and repository a controller or you only select certain ones that are necessary for external access:

1
lb4 controller
  1. Select a controller classname. We recommend to use the singular of the table name with capital first letter and if needed in CamelCase. Example: The table name is customers the name should be Customer.
  2. Select the REST-Controller type.
  3. Select in the next two questions the model and repository you like to use in this controller and match together (Example: Customers and CustomersRepository).
  4. Answers the next two questions regarding the primary key of the model (name and type).
  5. The next question you should answer with yes is the database will automatically create a primary key value.
  6. The last question you can modify the path to the endpoint or chose just the default value by pressing Enter.

Now you have as a last step to make a decission. In the "quick way" above we have modified the two files src/sequence.ts and src/application.ts. These changes mean that all controllers can only be reached in an authenticated manner. This is basically not a bad idea, but sometimes you need a more granular configuration for each controller.

If you need this, you have to undo the changes in these files and add in each controller in each method in there an @authenticate('jwt') decorator and optionally an @authorize(allowedRoles:[...],scopes:[...],disallowedRoles:[...]) decorator to restrict the access.

To learn more about the authentication and authorization plese read the documentation of the CodeCoupler API Auth package.

Read more about controllers and repositories on http://loopback.io/.

Relations

If you use the API to read data from the database you can use the argument includes to join data from related tables. To do this you have to modify the models and specify the relations between them.

You can do this only if you have created repositories and not used the "quick way"!

To do this start with the table including the foreign key column:

1
lb4 relation

Select belongsTo, the source model and answer all the other questions regarding the foreign key column.

Then repeat the command:

1
lb4 relation

Select haveMany, the target model and answer all the other questions regarding the foreign key.

Modifications of the origin Loopback boilerplate

  • Added "files.eol": "\n" to Visual Code Settings
  • Integrated package @codecoupler/cc-api-auth (Prepared Datasource "Auth"; Modified index.ts, application.ts, sequence.ts)
  • Control basepath with .env file
  • Tests modified to respect basepath from .env file
  • Mocha settings modified to read .env file
  • Added --exit flag to mocha in npm scripts
  • New script quicktest added for testing without linting
  • Excluded src from package and included .env.default
  • Package specified as private

LoopBack.