ノードを学びましょう.JSとのバックエンドを構築する.レッスン2:ユーザー登録パート1


この記事はもともと1967年に出版されましたhttps://www.blog.duomly.com/node-js-course-with-building-a-fintech-banking-app-lesson-2-user-registration
前の週に、私は発表しましたthe first lesson of the Node.js Course, そこで巣を使ってプロジェクトを始めました.JS、ネストCLI、PostgreSQLデータベース、およびシーケンス化.それに加えて、我々は移動を作成し、データベースを設定することができました.
それで、あなたが更新されることを望むならば、レッスン1に戻って、そして、我々の我々から第1のレッスンコードを得るために自由に感じてくださいGithub.
また、ノードで作成されたバックエンドを比較したい場合.バックエンドはGoangと一緒に作成されたJSGolang Course . 両方ともAngular 9 Course and Python and AI Course . すべての1つのFintechアプリケーションを構築するために使用されます.
今日、私はノードでユーザー登録を作成する方法をあなたに示すつもりです.js
我々は、2つのモジュール、ユーザーとアカウントを作成するつもりです、そして、我々は新しいユーザーをつくるための機能を構築します、そして、各々の新しいユーザーは割り当てられる新しいアカウントを持ちます.
そしてもちろん、いつものように、我々はあなたのためのビデオバージョンを持っている!
始めましょう!

1 .リファクター移行


最初のステップは、最後のレッスンで行われた移行をリファクタリングすることです.テーブルにいくつかの列を追加しなければなりません.では、走りましょうnpm run migrate down 両方のテーブルを2回ドロップします.オープン1.1users.ts ファイルに次の変更を行います.
import * as Sequelize from 'sequelize';

const tableName = 'Users';

export async function up(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.createTable(tableName, {
    id: {
      type: Sequelize.INTEGER,
      allowNull: false,
      autoIncrement: true,
      unique: true,
      primaryKey: true,
    },
    Username: {
      type: Sequelize.CHAR(200),
      allowNull: false,
    },
    Email: {
      type: Sequelize.CHAR(50),
      allowNull: false,
    },
    Password: {
      type: Sequelize.CHAR(250),
      allowNull: false,
    },
    Salt: {
      type: Sequelize.CHAR(250),
      allowNull: true,
    },
    createdAt: {
      type: Sequelize.DATE,
    },
    updatedAt: {
      type: Sequelize.DATE,
    }
  });
};

export async function down(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.dropTable(tableName);
}
さて、他の移行ファイルを開きます1.2accounts.ts そして、以下のコードのように確認してください.
import * as Sequelize from 'sequelize';

const tableName = 'Accounts';

export async function up(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.createTable(tableName, {
    id: {
      type: Sequelize.INTEGER,
      allowNull: false,
      autoIncrement: true,
      unique: true,
      primaryKey: true,
    },
    Type: {
      type: Sequelize.CHAR(200),
      allowNull: false,
    },
    Name: {
      type: Sequelize.CHAR(200),
      allowNull: false,
    },
    Balance: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    UserId: {
      type: Sequelize.INTEGER,
      references: {
        model: 'Users',
        key: 'id',
      },
    },
    createdAt: {
      type: Sequelize.DATE,
    },
    updatedAt: {
      type: Sequelize.DATE,
    }
  });
};

export async function down(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.dropTable(tableName);
}
最後のステップは移動を再実行することですnpm run migrate up そして、あなたのデータベースが変わったかどうかチェックしてください.

パッケージのインストール


ユーザー登録を作成するには、追加のパッケージが必要です.コンソールを開きましょうjsonwebtoken .
$ npm install jsonwebtoken
そして、我々が必要とする他のパッケージはdotenv , 構成を作成するには
$ npm install dotenv
終わったら次のステップに進みましょう.

3 . createenvファイル


ルートファイルに移動し、新しいファイルを作成し.env . このファイルには、データベースの設定を移動します.
DB_HOST=<YOUR_HOST>
DB_USER=<YOUR_USERNAME>
DB_PASS=<YOUR_PASSWORD>
DB_NAME=<YOUR_DB_NAME>
JWT_KEY=<YOUR_JWT_KEY>
さて、この設定をmain.ts ファイルを設定します.migrate.ts and database.provider.ts ファイル.
から始めましょうmain.ts とインポート.env .
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
require('dotenv').config()

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();
さて、オープンmigrate.ts そして、このように確認してください.
...
require('dotenv').config()

const sequelize = new Sequelize({
  dialect: 'postgres',
  host: process.env.DB_HOST,
  port: 5432,
  username: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
});
...
そして最後にdatabase.provider.ts ファイル.
export const databaseProvider = [
  {
    provide: 'SEQUELIZE',
    useFactory: async () => {
      const sequelize = new Sequelize({
        dialect: 'postgres',
        host: process.env.DB_HOST,
        port: 5432,
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
        database: process.env.DB_NAME,
      });
      sequelize.addModels([Users, Accounts]);
      return sequelize;
    }
  }
]
次の手順でJWT設定を作成します.

JWTの設定


レッツゴートゥザsrc フォルダとフォルダを作成するconfig . その設定フォルダでは、jwtConfig.ts ファイル、およびJWTのオプションを設定しましょう.
export const jwtConfig = {
  algorithm: 'HS256',
  expiresIn: '1 day',
}
もう一つ必要なことは、JWTRAKEキーを生成し、それを追加することです.env .
インターネットで利用できるツールのいずれかを使用してキーを生成したり、コンソールコマンドを使用したりできます.
ssh-keygen -t rsa -b 2048 -f jwtRS256.key
準備ができて、それに加えられるとき.env ファイルは、次のステップにしましょう!

ユーザモジュールとエンティティ


このステップでは、我々はuser.module.ts そして、我々は手動でそれを行うことができますまたはネストCLIを使用します.
$ nest generate module modules/user
たった今、私たちはこのファイルの他の何かをする必要はありません.users.entity.ts . このファイルの中でデータベースに渡すデータを設定します.
import { Table, Column, Model, DataType, CreatedAt, UpdatedAt, HasMany } from 'sequelize-typescript';
import { TableOptions } from 'sequelize-typescript';

const tableOptions: TableOptions = { timestamp: true, tableName: 'Users' } as TableOptions;

@Table(tableOptions)
export class Users extends Model<Users> {
  @Column({
    type: DataType.INTEGER,
    allowNull: false,
    autoIncrement: true,
    unique: true,
    primaryKey: true,
  })
  public id: number;

  @Column({
      type: DataType.CHAR(200),
      allowNull: false,
  })
  public Username: string;

  @Column({
    type: DataType.CHAR(50),
    allowNull: false,
    validate: {
      isEmail: true,
      isUnique: async (value: string, next: Function): Promise<any> => {
        const exists = await Users.findOne({ where: { Email: value } });
        if (exists) {
          const error = new Error('This email is already used.');
          next(error);
        }
        next();
      }
    }
  })
  public Email: string;

  @Column({
    type: DataType.CHAR(250),
    allowNull: false,
  })
  public Password: string;

  @Column({
    type: DataType.CHAR(250),
    allowNull: true,
  })
  public Salt: string;

  @CreatedAt
  public createdAt: Date;

  @UpdatedAt
  public updatedAt: Date;
}
偉大な、今我々は次のポイントに行くことができます!

6ユーザインタフェースとユーザインタフェース


次に、ユーザプロバイダの作成について説明します.ユーザーフォルダ内でusers.provider.ts ファイルとそのファイルの内部で次のコードを作成します.
import { Users } from './users.entity';

export const UsersProviders = {
  provide: 'USERS_REPOSITORY',
  useValue: Users
}
終わったら、モジュールを開きましょう.
@Module({
  providers: [UsersProviders],
  exports: [
    UsersProviders,
  ]
})
では、ユーザーオブジェクトの型を定義するインターフェイスを作りましょう.
user フォルダを作成しますinterface そしてそのフォルダでuser.interface.ts ファイル.このファイルで次のインターフェイスを作成します.
export interface IUser {
  id: number;
  Username: string;
  Email: string;
  Password: string;
  Salt: string;
  Accounts: [];
}
クール、今このレッスンの最もエキサイティングな部分に行くことができますか?

ユーザサービスとコントローラ


この時点で、我々はuser.service.ts ファイルと、このファイルの内部で、データベースにデータを保存する機能を構築します.
新しく作成したファイルを開き、次のコードを入力します.
import { Injectable, Inject } from '@nestjs/common';
import { Users } from './users.entity';
import * as jwt from 'jsonwebtoken';
import { jwtConfig } from './../../config/jwtConfig';
import crypto = require('crypto');

@Injectable()
export class UsersService { 
  constructor(
    @Inject('USERS_REPOSITORY') private usersRepository: typeof Users,
  ) { }

  public async create(user: any): Promise<object> {
    const exists = await Users.findOne({ where: { Email: user.Email } });
    if (exists) {
      throw new Error('This email is already used.');
    } else {
      user.Salt = crypto.randomBytes(128).toString('base64');
      user.Password = crypto.createHmac('sha256', user.Password + user.Salt).digest('hex');
      const newUser: any = await this.usersRepository.create<Users>(user);
      const jwtToken = jwt.sign(user, process.env.JWT_KEY, jwtConfig);
      newUser.Token = jwtToken;
      return newUser;
    }
  }
}
すごい、それはそれのように見える!現在、エンドポイントとAPIメソッドを設定するコントローラが必要です.
を作成しましょうuser.controller.ts ファイルを作成し、次のコードを作成します.
import { Controller, Post, Body, HttpException, HttpStatus } from '@nestjs/common';
import { UsersService } from './users.service';
import { IUser } from './interfaces/user.interface';

@Controller('users')
export class UsersController {
  constructor(private usersService: UsersService) { }

  @Post('register')  
    public async register(@Body() user: IUser): Promise<any> {    
    const result: any = await this.usersService.create(user,);
    if (!result.success) {
        throw new HttpException(result.message, HttpStatus.BAD_REQUEST);    
    }
    return result;  
  }
}
さて、これらのファイルをモジュールファイルに注入する必要があります.
@Module({
  controllers: [UsersController],
  providers: [UsersProviders, UsersService],
  exports: [
    UsersService,
    UsersProviders,
  ]
})
私たちの登録の最初の部分が準備ができているようであるので、我々は第2の部分をつくりましょう.

アカウントモジュールとエンティティ


巣CLIを使って新しいモジュールを作りましょう.
$ nest generate module modules/accounts
新しいモジュールを新しいフォルダに作成し、以前にはモジュールモジュールファイルには何もすることができません.では、作成しましょうaccounts.entity.ts ファイルを確認し、ファイルが以下のコードに見えるようにします.
import { Table, Column, Model, DataType, CreatedAt, UpdatedAt, ForeignKey, BelongsTo } from 'sequelize-typescript';
import { TableOptions } from 'sequelize-typescript';
import { Users } from '../user/users.entity';

const tableOptions: TableOptions = { timestamp: true, tableName: 'Accounts' } as TableOptions;
@Table(tableOptions)
export class Accounts extends Model<Accounts> {
  @Column({
    type: DataType.INTEGER,
    allowNull: false,
    autoIncrement: true,
    unique: true,
    primaryKey: true,
  })
  public id: number;

  @Column({
    type: DataType.CHAR(200),
    allowNull: false,
  })
  public Type: string;

  @Column({
    type: DataType.CHAR(200),
    allowNull: false,
  })
  public Name: string;

  @Column({
    type: DataType.INTEGER,
    allowNull: true,
  })
  public Balance: number;

  @ForeignKey(() => Users)
  public UserId: number;

  @BelongsTo(() => Users, {
      as: 'Users',
      foreignKey: 'UserId',
      targetKey: 'id',
  })
  public Users: Users;

  @CreatedAt
  public createdAt: Date;

  @UpdatedAt
  public updatedAt: Date;
}
グレート、それは準備ができているので、次の手順に行くことができます.

会計提供者とインタフェース


今すぐアカウントモジュールのプロバイダを作成しましょう.にaccounts フォルダを作成してくださいaccounts.provider.ts ファイル.このファイルでは、プロバイダーに次のコードを設定する必要があります.
import { Accounts } from './accounts.entity';

export const AccountsProviders = {
  provide: 'ACCOUNTS_REPOSITORY',
  useValue: Accounts
};
以前はインターフェイスが必要なので、新しいフォルダを作成しましょうinterfaces そのファイルの中にaccounts.interface.ts ファイルを以下のオブジェクトとします.
export interface IAccount {
  id: number;
  Type: string;
  Name: string;
  Balance: number;
  UserId: number;
}
Accountサービスとコントローラを作成する準備が整いました.

アカウントサービスとコントローラ


accounts フォルダを作成しましょうaccounts.service.ts このファイルでは、次の関数を作成する必要があります.
import { Injectable, Inject } from '@nestjs/common';
import { Accounts } from './accounts.entity';

@Injectable()
export class AccountsService { 
  constructor(
    @Inject('ACCOUNTS_REPOSITORY')
    private accountsRepository: typeof Accounts
  ) { }

  public async create(UserId: number): Promise<object> {
    const account = {
      Name: 'Account',
      Type: 'Personal Account',
      Balance: 100, 
      UserId: UserId,
    }
    const newAccount: any = await this.accountsRepository.create<Accounts>(account);
    return newAccount;
  }
}
ご覧のように、私たちは初期のユーザーアカウントのハードコーディングされた値を設定します.
を作成しましょうaccounts.controller.ts 同じフォルダ内のファイル.そして、そのファイルに次のコードを入力するので、エンドポイントからも使用できます.
import { AccountsService } from './accounts.service';
import { Controller, Post, Body, HttpException, HttpStatus } from '@nestjs/common';
import { IAccount } from './interfaces/accounts.interface';

@Controller('accounts')
export class AccountsController {
  constructor(private accountsService: AccountsService) { }

  @Post('create-account')  
    public async register(@Body() UserId: number): Promise<any> {    
    const result: any = await this.accountsService.create(UserId);
    if (!result.success) {
      throw new HttpException(result.message, HttpStatus.BAD_REQUEST);    
    }
    return result;  
  }
}
私たちはもう少しで授業の終わりです.我々はちょうどいくつかのファイルを更新し、それをテストする必要があります.

ユーザサービスにAccountサービスを追加する


我々は、我々の登録関数でアカウントを作成するために、関数を使用します.しかし最初に、モジュールを更新する必要がありますaccounts.module.ts ファイルを確認し、以下のコードのように確認してください.
@Module({
  imports: [DatabaseModule],
  controllers: [AccountsController],
  providers: [AccountsProviders, AccountsService],
  exports: [AccountsProviders, AccountsService]
})
保存すると、他のモジュールファイルを開きます.users.module.ts そして、それを更新します.
@Module({
  controllers: [UsersController],
  imports: [AccountsModule],
  providers: [UsersProviders, UsersService],
  exports: [
    UsersService,
    UsersProviders,
  ]
})
だから、我々はそれをインポートすることができますuser.service.ts . ファイルは以下のコードのようになります.
import { Injectable, Inject } from '@nestjs/common';
import { Users } from './users.entity';
import * as jwt from 'jsonwebtoken';
import { jwtConfig } from './../../config/jwtConfig';
import { AccountsService } from './../accounts/accounts.service';
import crypto = require('crypto');

@Injectable()
export class UsersService { 
  constructor(
    @Inject('USERS_REPOSITORY') private usersRepository: typeof Users,
    private accountsService: AccountsService,
  ) { }

  public async create(user: any): Promise<object> {
    const exists = await Users.findOne({ where: { Email: user.Email } });
    if (exists) {
      throw new Error('This email is already used.');
    } else {
      user.Salt = crypto.randomBytes(128).toString('base64');
      user.Password = crypto.createHmac('sha256', user.Password + user.S
alt).digest('hex');
      const newUser: any = await this.usersRepository.create<Users>(user);
      const jwtToken = jwt.sign(user, process.env.JWT_KEY, jwtConfig);
      newUser.Token = jwtToken;
      if (newUser) {
        this.accountsService.create(newUser.id)
      }
      return newUser;
    }
  }
}
OK、AccountsServiceからCreate関数を通過し、新しいユーザーが登録するたびに新しいアカウントを作成しました.
バックエンド全体を動作させるには、ユーザーエンティティとデータベースプロバイダーを更新する必要があります.ユーザーを開きましょう.エンティティ.TSファイル、およびユーザークラスの末尾にいくつかの行のコードを追加します.
  @HasMany(() => Accounts, 'UserId')
  public Accounts: Accounts[];
さあ、データベースを開きましょう.プロバイダ.TSファイルと両方のエンティティをインポートします.インポートが行われると、モデルとしてそれらを注入します.
import { Sequelize } from 'sequelize-typescript'; 
import { Users } from '../user/users.entity'; 
import { Accounts } from '../accounts/accounts.entity'; 
export const databaseProvider = [ 
  { 
      provide: 'SEQUELIZE', 
      useFactory: async () => { 
         const sequelize = new Sequelize({ 
            dialect: 'postgres', 
            host: process.env.DB_HOST, 
            port: 5432, 
            username: process.env.DB_USER, 
            password: process.env.DB_PASS, 
            database: process.env.DB_NAME, 
         }); 
     sequelize.addModels([Users, Accounts]); 
     return sequelize; 
    } 
  }
]
とVoila!テストしましょう!

12章テスト


私はすぐにAPIをテストするために郵便配達人を使用します.あなたはまだアプリを実行していない場合は、それを使用してくださいnest start or npm run start , そして、それが郵便配達人を開く準備ができているとき.下の画像では、私の設定を見ることができます.また、データがあるかどうかを確認するデータベースを開くことができます.

私はそれがあなたのために働くことを望む!

結論


このレッスンでは、新しいユーザーの登録を作成し、既定のアカウントを作成します.
次のレッスンでは、ログイン機能に取り組みます.
あなたが正しくすべてのコードを取得するために管理していない場合は、当社のgithubにジャンプして、バグを見つける.
Node.js Course - Lesson 2: User registration - Code
また、我々が構築している他のコースに飛び込むことを忘れないでくださいGoLang backend 同じアプリ、AI for investment , とフロントエンドAngular 9 .
読んでくれてありがとう.
からのアナ