Go to bilibili.com for an accompanying video tutorial

LoopBack is a highly extensible open source Node.js framework that enables you to create dynamic, end-to-end REST apis with little or no coding.

The LoopBack framework is made up of a set of Node.js modules. You can use these modules individually or in combination. Applications can access data through the LoopBack Model API in three ways.

  • Use the model as a standard Node object
  • Through the HTTP REST API
  • Through packaged API SDKS, including iOS, Android, and Angular

The application uses LoopBack Model API to query data, store data, upload files, send email, push messages, register/log in users and other remote or local services. You can also use Strong Remoting to make the back-end API available to clients via REST, WebSocket(or other transport protocol).

I. Project Overview

This is an official example of a coffee shop review.

Cafe Review is a website that we can use to post reviews of coffee shops. There are three data models:

  • CoffeeShop coffee shop
  • Review comments
  • Reviewer reviewers

They have the following relationship:

  • CoffeeShop has several reviews
  • CoffeeShop has multiple Reviewer’s
  • Review belongs to a CoffeeShop
  • Review belongs to the reviewer
  • Reviewer has multiple reviews

In general, users can create, edit, delete, and read coffee shop reviews and specify basic rules and permissions via ACLs:

  • Comments can be read by anyone, but they must be logged in to create, edit or delete them.
  • Anyone can register as a user and be logged in or logged out.
  • Logged-in users can create new reviews and edit or delete their own, but they cannot modify content related to coffee shops.

2. Create a project

Install the Loopback CLI tool

Install the Loopback CLI tool in nodeJS.

npm install -g loopback-cli
Copy the code

After the Loopback CLI is successfully installed, run the lb-help command to view the Loopback CLI command.

lb -help
Available commands:
  lb acl
  lb app
  lb bluemix
  lb boot-script
  lb datasource
  lb export-api-def
  lb middleware
  lb model
  lb oracle
  lb property
  lb relation
  lb remote-method
  lb soap
  lb swagger
  lb zosconnectee
Copy the code

Create a LoopBack project

On the command line, type:

lb
Copy the code

Enter the project name as prompted, and press Enter for other items.

? What is the name of your application? CoffeeShop ? Enter the directory name to contain the project: CoffeeShop create CoffeeShop/ info Change the working directory to CoffeeShop? Which version of LoopBack do you want to use? 3.x (Active Long Term Support) ? What kind of application do you want? Api-server (LoopBack API server using local user authentication) is generating.yo-rc.jsonCopy the code

After the installation is successful, perform the following steps as prompted:

Next step: Change the directory to your application $cdCoffeeShop creates the $LB model in the application to run the application $Node.Copy the code

Go to the project root directory and run the application.

node .
hsts deprecated The "includeSubdomains" parameter is deprecated. Use "includeSubDomains" (with a capital D) instead. node_modules/loopback/lib/server-app.js:74:25
Web server listening at: http://localhost:3000
Browse your REST API at http://localhost:3000/explorer
Copy the code

Open a browser and enter the address as prompted to access the API test page of LoopBack. Since we haven’t created any models yet, we can only see the framework’s built-in USER API call interface on the page.

Exit the service from the project root command line through Control +C.

Connect to the data source

LoopBack automatically connects to most data sources on the market. Let’s take MongoDb as an example to add a data persistence library for the project.

lb datasource ? Enter the data source name: MD? Select connector for MD: MongoDB (StrongLoop support)? Connection String url to override other settings (eg: mongodb://username:password@hostname:port/da tabase): ? host: localhost ? port: 27017 ? user: ? password: [hidden] ? database: cshop ? Install loopback-connector-mongodb@^4.0.0 Yes + [email protected] added 7 packages from 11 ficol3in2.342 sCopy the code

First, you must ensure that the development environment has the MongoDB database and has been started. The database does not need to be created. The framework will automatically create the database based on the entered database name. Since the MongoDB connection plug-in is not installed, select Yes to install it.

In the server subdirectory of the project directory there are the following files:

├── authentication.js │ ├─ authentication.js │ ├─ authentication.js │ ├─ authentication.js │ ├─ authentication.js │ ├─ config.json │ ├─ Datasources. Json ├ ─ ─ middleware. Development. Json ├ ─ ─ middleware. The json ├ ─ ─ model - config. Json └ ─ ─ for server jsCopy the code

Where datasources.json is the configuration file for the datasource, we open this file in the code editor and see the MD datasource we created.

{
  "db": {
    "name": "db"."connector": "memory"
  },
  "md": {
    "host": "localhost"."port": 27017,
    "url": ""."database": "cshop"."password": ""."name": "md"."user": ""."connector": "mongodb"}}Copy the code

Since the framework originally defined a data source db, we don’t need it anymore. Delete the DB data source and rename the MD data source db. The modified code is as follows:

 {
  "db": {
    "host": "localhost"."port": 27017,
    "url": ""."database": "cshop"."password": ""."name": "md"."user": ""."connector": "mongodb"}}Copy the code

After creating the data source, the framework automatically connects us to the database, and our persistent operations on the data are automatically saved to the database.

Create a model

CoffeeShop model

The property name Attribute types If required
name String y
city String y
lb model ? Please enter the model name: CoffeeShop? Select the data source to which you want to append CoffeeShop: DB (mongodb)? Choose PersistedModel, the base class for your model? Expose CoffeeShop via the REST API? Yes ? Custom plural (for building REST urls) :? Common model or server only? Public now add some CoffeeShop properties. Enter an empty property name when finished. ? Attribute name: name? Attribute type: String? Is it required? Yes ? Default [leave blank for none] : Add another CoffeeShop property next. Enter an empty property name when finished. ? Property name: City? Attribute type: String? Is it required? Yes ? Default [leave blank for none] : Add another CoffeeShop property next. Enter an empty property name when finished. ? The attribute nameCopy the code

Review the model

The property name Attribute types If required
date date y
rating number n
comments string y
lb model ? Please enter the model name: Review? Select the data source to which you want to append Review: DB (mongodb)? Choose PersistedModel, the base class for your model? Expose Review through the REST API? Yes ? Custom plural (for building REST urls) :? Common model or server only? Public now adds some Review properties. Enter an empty property name when finished. ? Attribute name: date? Attribute type: date? Is it required? Yes ? Default [leave blank for none] : Add another Review property next. Enter an empty property name when finished. ? Attribute name: rating? Attribute type: number? Is it required? No ? Default [leave blank for none] : Add another Review property next. Enter an empty property name when finished. ? Property name: Comments? Attribute type: String? Is it required? Yes ? Default [leave blank for none] : Add another Review property next. Enter an empty property name when finished. ? Attribute name:Copy the code

Reviewer model

The Reviewer model will inherit from the user model that came with the framework. Select PersistedModel instead of PersistedModel. Select User without adding any attributes.

lb model ? Please enter a model name: Reviewer? Select the data source to which you want to add a Reviewer: DB (mongodb)? Select the model's base class User? Expose Reviewer? Through the REST API. Yes ? Custom plural (for building REST urls) :? Common model or server only? Public now add some Reviewer properties. Enter an empty property name when finished. ? Attribute name:Copy the code

Start the service from the project root command line via Node. In the browser to open http://localhost:3000/explorer again.

You can see that the API debugging interface adds interfaces for the three models we just created in addition to the previous User interface.

Define the relationship between models

LoopBack supports many different types of model relationships: BelongsTo, HasMany, HasManyThrough, and HasAndBelongsToMany, to name a few. The following relationships can be defined according to project requirements:

  • CoffeeShop HasMany review
  • CoffeeShop HasMany reviewer
  • review BelongsTo CoffeeShop
  • review BelongsTo reviewer
  • reviewer HasMany review

CoffeeShop has multiple reviews, no intermediate models and no foreign keys.

lb relation ? Select the model from which to create the relationship: CoffeeShop? Relationship type: has many? Select a model to create a relationship with: Review? Enter the property name of the relationship: reviews? (Optional) Enter a custom foreign key:? Need a straight-through model? No ? Allows nesting of relationships in REST apis: No? Forbid inclusion relation: NoCopy the code

CoffeeShop has multiple Reviewer’s and no intermediate model or foreign key.

lb relation ? Select the model from which to create the relationship: CoffeeShop? Relationship type: has many? Select a model with which to create a relationship: Reviewer? Enter the name of the relationship property: reviewers? (Optional) Enter a custom foreign key:? Need a straight-through model? No ? Allows nesting of relationships in REST apis: No? Forbid inclusion relation: NoCopy the code

Review belongs to a CoffeeShop with no intermediate models and no foreign keys.

lb relation ? Select the model from which to create the relationship: Review? Relationship type: Belongs to? Select a model to create a relationship with: CoffeeShop? Enter the property name of the relationship: coffeeShop? (Optional) Enter a custom foreign key:? Allows nesting of relationships in REST apis: No? Forbid inclusion relation: NoCopy the code

Review belongs to a Reviewer, the foreign key is publisherId, and there is no intermediate model.

lb relation ? Select the model from which to create the relationship: Review? Relationship type: Belongs to? Select a model with which to create a relationship: Reviewer? Enter a property name for the relationship: Reviewer? (Optional) Enter custom foreign key: publisherId? Allows nesting of relationships in REST apis: No? Forbid inclusion relation: NoCopy the code

Reviewer has multiple reviews, foreign key is publisherId, and no intermediate model.

lb relation ? Select the model from which to create a relationship: Reviewer? Relationship type: has many? Select a model to create a relationship with: Review? Enter the property name of the relationship: reviews? (Optional) Enter custom foreign key: publisherId? Need a straight-through model? No ? Allows nesting of relationships in REST apis: No? Forbid inclusion relation: NoCopy the code

In the model directory in the common subdirectory of the project root directory, we can see the six files we created related to the model:

└── ├─ Self Exercises ── Self Exercises ── Self Exercises ── Self Exercises ── Self Exercises ── Self Exercises ── Self Exercises ── reviewer.jsonCopy the code

Relationships defined in coffee-shop.json file:

 "relations": {
    "reviews": {
      "type": "hasMany"."model": "Review"."foreignKey": ""
    },
    "reviewers": {
      "type": "hasMany"."model": "Reviewer"."foreignKey": ""}},Copy the code

Relationships defined in the review.json file:

"relations": {
    "coffeeShop": {
      "type": "belongsTo"."model": "CoffeeShop"."foreignKey": ""
    },
    "reviewer": {
      "type": "belongsTo"."model": "Reviewer"."foreignKey": "publisherId"}},Copy the code

Relationships defined in the Reviewer. Json file:

"relations": {
    "reviews": {
      "type": "hasMany"."model": "Review"."foreignKey": "publisherId"}},Copy the code

Define operation permissions

Loopback applications access data through the model, so controlling access to data means controlling permissions on the model: that is, specifying which roles can perform the methods of reading and writing data on the model. Loopback permission control is determined by a permission control list or ACL.

Based on the requirements of the project, permission control should enforce the following rules:

Anyone can read the comments. However, create, edit, and delete operations must be logged in before they have permission. Anyone can register as a user and log in and out. Logged-in users can create new comments and edit or delete their own. However, they cannot modify the reviews of coffee shops.

First, denying everyone access to all interfaces is often the starting point for defining acLs, because you can selectively allow access to specific operations.

lb acl ? Select the model to which ACL entries apply: (all existing models)? Select ACL scope: All methods and attributes? Select access type: All (matches all types)? Select role all users? Select the permissions to apply to explicitly deny accessCopy the code

Now everyone is allowed to read reviews.

lb acl ? Select the model to which ACL entries are to be applied: Review? Select ACL scope: All methods and attributes? Select access type: Read? Select role all users? Explicitly authorize access by selecting the permissions to applyCopy the code

Authenticated users are allowed to read coffeeshops, which means that logged-in users can browse all coffeeshops.

lb acl ? Select the model to which you want to apply the ACL entry: CoffeeShop? Select ACL scope: All methods and attributes? Select access type: Read? Select role any authenticated user? Explicitly authorize access by selecting the permissions to applyCopy the code

Allows authenticated users to create reviews, that is, logged-in users can add a review.

lb acl ? Select the model to which ACL entries are to be applied: Review? Select ACL scope: single method? Enter the method name create? Select role any authenticated user? Explicitly authorize access by selecting the permissions to applyCopy the code

Give the review author permission (its “owner”) to make any changes to it.

lb acl ? Select the model to which ACL entries are to be applied: Review? Select ACL scope: All methods and attributes? Select access type: Write? Select the user whose role owns the object? Explicitly authorize access by selecting the permissions to applyCopy the code

7. Automatically fill field contents

We need users to automatically populate the date field with the current date when they add comments. Also, since the comment is associated with the reviewer through the foreign key publisherId, the user needs to populate the reviewer’s user Id as its content when adding a comment.

We will define a remote hook that will be called whenever the create() method is called on the Review model (when a new comment is created).

In general, we can define two types of remote hooks:

  • beforeRemote()Run before remote methods.
  • afterRemote()Run after the remote method.

In both cases, there are two arguments we can use: a string that matches the remote method to which we want the hook function, and a callback function.

Create a remote hook

Here, we’ll define a remote hook in the Review model, specifically review.beforeremote.

  • Set publisherId to the userId in the request
  • Sets the date to the current date.

Modify the common/models/review. Js:

module.exports = function(Review) {
  Review.beforeRemote('create'.function(context, user, next) {
    context.args.data.date = Date.now();
    context.args.data.publisherId = context.req.accessToken.userId;
    next();
  });
};
Copy the code

Call this function before creating a new instance of the Review model.

Viii. Background management

How to manage the data of CoffeesHops? This is the background management we often say, need an administrator admin role to assume. This will be covered in another article. LoopBack3.0 custom roles and authorization