どのように羽の電子メールの検証を設定します.js


確かにあなたのアプリケーションに登録しているときにユーザーに検証メールを送信します.このポストではFeathers.js
このポストでは、我々は、あなたがフレームワークについての知識を持っていることを当然のことと思います.ない場合は、次のリンクを参照してくださいhttps://docs.feathersjs.com/guides を参照してください.
レッツゴー!

1 .第一歩.
フォルダを作成します.mkdir feathers-email-verificationフォルダを入力cd feathers-email-verification我々は羽のCLIとアプリケーションを作成しますfeathers generate app次のオプションを選択します

Note: For use feathers-cli is necessary have it installed. visit this link https://docs.feathersjs.com/guides/basics/generator.html#generating-the-application


インストールが成功したことを確認します.MongoDBデータベースサーバーを実行し、開発サーバをコマンドで実行しますnpm run start我々が訪問するならばhttp://localhost:3030 次のようになります

完璧な、今我々はユーザーを登録し、ログインします.
新規ユーザーの作成

ユーザーが正常に作成されている場合は、次のレスポンスを取得します.

認証ユーザー

資格情報が正しくて、すべてがうまくいったならば、我々は以下の答えを得ます.

すばらしい、すべてが正しい.これは、電子メール配信システムを実装する時間です.

どのようにすべての作品.
構成に入る前に、その操作を理解する必要があります.我々が作成しようとしているのは、ユーザーが自分のメールアドレスを確認するための流れです.これは次のようになります.
  • ユーザーは羽のアプリケーションでアカウントを作成します.
  • サーバー追加フィールドはデータベース内のオブジェクトユーザーに設定され、false
  • サーバーは、ユーザーの検証トークンを作成します.
  • 使用は、パラメータとしてトークンでクライアントリンクを含む電子メールを得ます.
  • ユーザーがリンクをクリックし、クライアントを訪問すると、このトークンがサーバーに送信されます.
  • サーバはユーザオブジェクトにフィールドを設定しますtrue
  • すべてが終わった.
  • 優れた、それはすべて知っている必要があります.今は仕事を始める時間です.

    電子メールサービスを設定します.
    さて、メールを送信できるサービスを作りましょう.
    しかし、まずパッケージをダウンロードする必要があります.だからインストールnodemailer .npm i nodemailer型をインストールします.npm i @types/nodemailer私たちがすることはメールフォルダを作成することです.
    • mails.class.ts: You will have the logic to send emails, here we initialize nodemailer
    • mails.hooks.ts: This file will contain all of our hooks. If you don't know what hooks are in feathers, visit the following link: Feathers hooks
    • mails.service.ts: Here we register the service, what will its path be, add the hooks, etc.

    さて、我々はmails.class.ts
    src > services > mails > mails.class.ts
    
    import { Application } from "@feathersjs/express";
    import { ServiceMethods } from "@feathersjs/feathers";
    import { createTransport, Transporter, SendMailOptions } from "nodemailer";
    
    export class Mails implements Partial<ServiceMethods<SendMailOptions>> {
        private transporter: Transporter;
    
        constructor(app: Application) {
            // We initialize the transporter.
            this.transporter = createTransport(app.get("mailer"));
        }
    
        /**
         * We send the email.
         * @param data 
         * @returns 
         */
        async create(data: Partial<SendMailOptions>): Promise<any> {
            return await this.transporter.sendMail(data);
        }
    }
    
    
    今、我々はmails.hooks.ts ファイル
    src > services > mails > mails.hooks.ts
    
    import { HooksObject } from "@feathersjs/feathers";
    
    const hooks: HooksObject = {
        before: {},
        after: {},
        error: {}
    };
    
    export default hooks;
    
    今、我々はmails.service.ts ファイル
    src > services > mails > mails.service.ts
    
    import { Application } from "@feathersjs/express";
    import { Service } from "@feathersjs/feathers";
    import { SendMailOptions } from "nodemailer";
    
    import hooks from "./mails.hooks";
    
    import { Mails } from "./mails.class";
    
    export default function (app: Application): void {
        // Register service.
        app.use("mails", new Mails(app));
    
        // Get mail service.
        const service: Service<SendMailOptions> = app.service("mails");
    
        // Register hooks in the service.
        service.hooks(hooks);
    }
    
    すごい!今ではほとんどすべてが完了すると、それはアプリケーション全体で利用可能なように、アプリケーションのグローバルサービスにこのサービスをインポートする必要があります.
    src > services > index.ts
    
    import { Application } from '../declarations';
    
    import users from './users/users.service';
    
    // We import the mail service.
    import mails from "./mails/mails.service";
    
    export default function (app: Application): void {
      // We expose the service to the rest of the application.
      app.configure(mails);
      app.configure(users);
    }
    
    
    既に気づいているかもしれませんが、エラーが発生しましたdefaul.json それはmailer プロパティ、我々がしなければならないことは、それを追加し、すべて設定されます.

    Note: By the way, do not expose the user and pass since this is confidential content, I did it for didactic reasons. But in the same way I have already reset the credentials.


    我々は再び開発サーバーを起動しますnpm run dev エラーが発生します.
    すべてが正しいというチェックに、我々はこの要求を送ります.

    すべてがうまくいくなら、我々はMailtrapでこれを見るべきです.

    If you wonder what service he is using to test the sending of emails, that is nothing more and nothing less than mailtrap


    明らかに、私たちのメーラーがスパムか何かのために誤用されることを望まないので、テストの後、我々はすべてのメーラールートに前フックを加えることによってそれを閉じます.このためにfeathers-hooks-common
    src > services > mails > mails.hooks.ts
    
    import { HooksObject } from "@feathersjs/feathers";
    import { disallow } from "feathers-hooks-common";
    
    const hooks: HooksObject = {
        before: {
            // Reject all requests that come from outside.
            all: [disallow("external")]
        },
        after: {},
        error: {}
    };
    
    export default hooks;
    
    リクエストを拒否したかどうかを確認するには、前の手順で再度メールを送信します.
    ワンダフル、電子メールの送信の設定が完了しました.

    羽認証管理モジュールの設定
    今、我々は羽認証管理モジュールを設定するつもりです.まずインストールしましょう.npm i feathers-authentication-management-tsインストールされたら、サービスフォルダ内の名前の管理を持つフォルダを作成します.このフォルダには次の構造があります.

    インデックス.戦略TS
    このファイルにはすべての戦略が含まれます.存在する戦略はverificationEmail and verifiedEmail . 次のコンテンツをコピーします.
    src > services > authmanagement > strategies > index.strategies.ts
    
    import { User, Types } from "feathers-authentication-management-ts";
    import { SendMailOptions } from "nodemailer";
    
    export interface MailOptions extends Partial<SendMailOptions> {
        user: User;
        token?: string;
        domain: string;
    }
    
    export interface ParamsLink {
        type?: string;
        token?: string;
        domain: string;
    }
    
    export type StrategiesAuthManagement = Record<
        Types,
        (options: MailOptions) => MailOptions
    >;
    
    export function generateLink(data: ParamsLink): string {
        const { domain, type, token } = data;
        return `${ domain }/${ type }?token=${ token }`;
    }
    
    export function verificationEmail(options: MailOptions): MailOptions {
        const { token, domain } = options;
        const link: string = generateLink({ token, domain, type: "verifyEmail" });
    
        return {
            ...options,
            subject: "Email Verification",
            text: "Feathers welcomes you, check your email to access our services 📧",
            html: `
                <h1>Thanks for registering 🥰</h1>
                <p>Verify your email and everything will be ready.</p>
                <a href="${ link }">Verify your email</a>
            `
        };
    }
    
    export function confirmationEmail(options: MailOptions): MailOptions {
        const html: string = `
            <h1>Your email has been verified</h1>
            <p>Great, now that your account is verified. It is time to get down to work.</p>
        `;
    
        return {
            ...options,
            subject: "Verified Email",
            text: "Congratulations! Your email has been verified 🏆",
            html
        };
    }
    
    export const strategies: Partial<StrategiesAuthManagement> = {
        resendVerifySignup: verificationEmail,
        verifySignup: confirmationEmail
    }
    
    
    オーサ管理コントローラ.TS
    このファイルには、その種類に応じて戦略を取得する方法のすべてのロジックが含まれます.メールサービスとの対話に責任があります.以前に設定したものです.次のコンテンツをコピーします.
    src > services > authmanagement > authmanagement.controller.ts
    
    import { SendMailOptions } from "nodemailer";
    import { Application } from "@feathersjs/express";
    import { MethodNotAllowed } from "@feathersjs/errors";
    import { Service } from "@feathersjs/feathers";
    import { Options, Types, User } from "feathers-authentication-management-ts";
    
    import { strategies, MailOptions } from "./strategies/index.strategies";
    
    export default function (app: Application): Partial<Options> {
        return {
            notifier(types: Types, user: User): void {
                // Get strategy by types.
                const strategy = strategies[types];
    
                // Check if the strategy exists.
                if (typeof strategy !== "function") throw new MethodNotAllowed({
                    name: "StrategyNotAllowed",
                    message: `The <${types}> strategy has not been implemented`
                });
    
                // Get email service.
                const email: Service<SendMailOptions> = app.service("mails");
    
                // Set payload.
                const payload: MailOptions = strategy({
                    from: app.get("email_domain"),
                    to: user.email,
                    token: user.verifyToken,
                    domain: app.get("domain"),
                    user
                });
    
                // Dispatch email.
                email.create(payload)
                    .then(() => console.log("Sent email successfully"))
                    .catch(console.error)
            }
        };
    }
    
    

    Note: If the url of your users service is different from users for example /api/users, it is important that you add the url of the users service that you assigned, since by default it will look in users


    src > services > authmanagement > authmanagement.controller.ts
    
    export default function (): Partial<Options> {
        return {
            // Name of the user service.
            service: "<Your name user service>",
            // Notifier.
            notifier(type: Types, user: User) {}
        }
    }
    
    オーサ管理フック.TS
    これは、サービスのすべてのフックが含まれます.次のコンテンツをコピーします.
    src > services > authmanagement > authmanagement.hooks.ts
    
    import { HooksObject } from "@feathersjs/feathers";
    
    const hooks: HooksObject = {
        before: {},
        after: {},
        error: {}
    }
    
    export default hooks;
    
    
    オーサ管理サービスTS
    サービスを登録する責任があります.次のコンテンツをコピーします.
    src > services > authmanagement > authmanagement.service.ts
    
    import { Application } from "@feathersjs/express";
    import { Service } from "@feathersjs/feathers";
    import authmanagement from "feathers-authentication-management-ts";
    
    import hooks from "./authmanagement.hooks";
    
    import controller from "./authmanagement.controller";
    
    export default function (app: Application): void {
        // Initialize service.
        app.configure(authmanagement(controller(app)));
    
        // Get service.
        const service: Service<any> = app.service("authManagement");
    
        // Add hooks.
        service.hooks(hooks);
    }
    
    次に、グローバルサービスにAuthManagementサービスを追加します.
    src > services > index.ts
    
    import authmanagement from "./authmanagement/authmanagement.service";
    
    export default function (app: Application): void {
      // Configure my auth management.
      app.configure(authmanagement);
      // More services...
    }
    
    

    Note: If you use any ORMs like Mongoose or Sequelize you need to add the verification fields manually to the user model. These need to be the following fields.


    
    const schema = new Schema({
        // More properties...
        isVerified: { type: Boolean },
        verifyToken: { type: String },
        verifyExpires: { type: Date },
        verifyChanges: { type: Object },
        resetToken: { type: String },
        resetExpires: { type: Date }
    });
    
    最後に、ユーザーモデルに作成フックを2つ追加する必要があります.つは、我々のnotifier機能を呼び出して、もう一度検証を削除する1つを呼び出します.これはこういう感じです.
    src > services > users > users.hooks.ts
    
    import * as feathersAuthentication from '@feathersjs/authentication';
    import * as local from '@feathersjs/authentication-local';
    import { Application } from '@feathersjs/express';
    import { HooksObject } from '@feathersjs/feathers';
    import { BadRequest } from "@feathersjs/errors";
    import authmanagement from "feathers-authentication-management-ts";
    
    import notifier from "../authmanagement/authmanagement.controller";
    
    const { authenticate } = feathersAuthentication.hooks;
    const { hashPassword, protect } = local.hooks;
    
    const hooks: HooksObject = {
      before: {
        all: [],
        find: [ authenticate('jwt') ],
        get: [ authenticate('jwt') ],
        create: [
          hashPassword('password'),
          // Sets values to some properties of the users model.
          authmanagement.hooks.addVerification()
        ],
        update: [ hashPassword('password'),  authenticate('jwt') ],
        patch: [ hashPassword('password'),  authenticate('jwt') ],
        remove: [ authenticate('jwt') ]
      },
    
      after: {
        all: [ protect('password') ],
        create: [
          ({ app, result }) => {
            const sender = notifier(app as Application);
    
            if (typeof sender.notifier !== "function") throw new BadRequest({
              name: "EmailNotSupported",
              message: "Sending emails not supported"
            });
    
            sender.notifier("resendVerifySignup", result);
          },
          // Protects sensitive properties before they are shipped to the customer.
          authmanagement.hooks.removeVerification()
        ]
      },
      error: {}
    };
    
    export default hooks;
    

    アプリケーションのセキュリティー.
    今では、アプリが完了する1つのステップとは、ユーザーサービスにいくつかのセキュリティを追加して動作します.我々は良い認証フローを実行しているので、我々はすべてのユーザーは、もはやユーザーサービスをメグドルをしたくない.我々はフックの前に2つを作成します.アップデートメソッドとパッチメソッドの1つ.アップデートメソッドの1つでは、このメソッドを完全に無効にします.結局のところ、我々は誰かが私たちの慎重に検証されたユーザーを新しいものに置き換えることができません.パッチメソッドの1つは、認証フィールドメソッドのいずれかを直接ユーザーから制限する必要があります.これを行うには、フックの前にユーザを更新します.
    src > services > users > users.hooks.ts
    
    import { HooksObject } from '@feathersjs/feathers';
    import feathersCommon from "feathers-hooks-common";
    
    const hooks: HooksObject = {
      before: {
        update: [
          feathersCommon.disallow("external")
        ],
        patch: [
          feathersCommon.iff(
            feathersCommon.isProvider('external'),
            feathersCommon.preventChanges(true,
              'email',
              'isVerified',
              'verifyToken',
              'verifyShortToken',
              'verifyExpires',
              'verifyChanges',
              'resetToken',
              'resetShortToken',
              'resetExpires'
            )
          )
        ]
      }
    };
    
    export default hooks;
    
    
    これが最終結果です.
    src > services > users > users.hooks.ts
    
    import * as feathersAuthentication from '@feathersjs/authentication';
    import * as local from '@feathersjs/authentication-local';
    import { Application } from '@feathersjs/express';
    import { HooksObject } from '@feathersjs/feathers';
    import { BadRequest } from "@feathersjs/errors";
    import authmanagement from "feathers-authentication-management-ts";
    import feathersCommon from "feathers-hooks-common";
    
    import notifier from "../authmanagement/authmanagement.controller";
    
    const { authenticate } = feathersAuthentication.hooks;
    const { hashPassword, protect } = local.hooks;
    
    const hooks: HooksObject = {
      before: {
        all: [],
        find: [ authenticate('jwt') ],
        get: [ authenticate('jwt') ],
        create: [
          hashPassword('password'),
          // Sets values to some properties of the users model.
          authmanagement.hooks.addVerification()
        ],
        update: [
          hashPassword('password'),
          authenticate('jwt'),
          feathersCommon.disallow("external")
        ],
        patch: [
          feathersCommon.iff(
            feathersCommon.isProvider('external'),
            feathersCommon.preventChanges(true,
              'email',
              'isVerified',
              'verifyToken',
              'verifyShortToken',
              'verifyExpires',
              'verifyChanges',
              'resetToken',
              'resetShortToken',
              'resetExpires'
            )
          ),
          hashPassword('password'),
          authenticate('jwt')
        ],
        remove: [ authenticate('jwt') ]
      },
    
      after: {
        all: [ protect('password') ],
        create: [
          ({ app, result }) => {
            const sender = notifier(app as Application);
    
            if (typeof sender.notifier !== "function") throw new BadRequest({
              name: "EmailNotSupported",
              message: "Sending emails not supported"
            });
    
            sender.notifier("resendVerifySignup", result);
          },
          // Protects sensitive properties before they are shipped to the customer.
          authmanagement.hooks.removeVerification()
        ]
      },
      error: {}
    };
    
    export default hooks;
    
    
    すべてがすばらしいことを確認するには、ユーザ登録の時間です.

    Mailtrapに行くならば、我々はこのように何かを見ます.

    優れた、我々はサーバーの設定で行われます.別のポストでは、クライアントの一部をビルドするVuejs and Angular .
    プロジェクトリポジトリを残しますhttps://github.com/IvanZM123/feathers-email-verification

    社会的ネットワークで私に続いてください.
  • 🎉 Twitter
  • 💡 ギタブhttps://github.com/IvanZM123