Jelajahi Sumber

Added error handling when accessing user-activation-page

Shun Miyazawa 3 tahun lalu
induk
melakukan
ad391900c6

+ 17 - 12
packages/app/src/components/CompleteUserRegistrationForm.tsx

@@ -3,14 +3,14 @@ import React, { useState, useEffect, useCallback } from 'react';
 import { useTranslation } from 'next-i18next';
 
 import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client';
+import { userActivationErrorCode } from '~/interfaces/errors/user-activation';
 
 import { toastSuccess, toastError } from '../client/util/apiNotification';
 
 interface Props {
-  messageErrors?: any,
-  inputs?: any,
   email: string,
   token: string,
+  errorCode?: userActivationErrorCode,
   isEmailAuthenticationEnabled: boolean,
 }
 
@@ -18,9 +18,10 @@ const CompleteUserRegistrationForm: React.FC<Props> = (props: Props) => {
 
   const { t } = useTranslation();
   const {
-    messageErrors,
     email,
     token,
+    errorCode,
+    isEmailAuthenticationEnabled,
   } = props;
 
   const [usernameAvailable, setUsernameAvailable] = useState(true);
@@ -63,19 +64,23 @@ const CompleteUserRegistrationForm: React.FC<Props> = (props: Props) => {
 
   return (
     <>
-      <div id="register-form-errors">
-        {messageErrors && (
-          <div className="alert alert-danger">
-            { messageErrors }
-          </div>
-        )}
-      </div>
-
       <div className="noLogin-dialog mx-auto" id="noLogin-dialog">
         <div className="row mx-0">
           <div className="col-12">
 
-            { !props.isEmailAuthenticationEnabled && (
+            { (errorCode != null && errorCode === userActivationErrorCode.TOKEN_NOT_FOUND) && (
+              <p className="alert alert-danger">
+                <span>Token not found</span>
+              </p>
+            )}
+
+            { (errorCode != null && errorCode === userActivationErrorCode.USER_REGISTRATION_ORDER_IS_NOT_APPROPRIATE) && (
+              <p className="alert alert-danger">
+                <span>{t('message.incorrect_token_or_expired_url')}</span>
+              </p>
+            )}
+
+            { !isEmailAuthenticationEnabled && (
               <p className="alert alert-danger">
                 <span>{t('message.email_authentication_is_not_enabled')}</span>
               </p>

+ 7 - 0
packages/app/src/pages/user-activation.page.tsx

@@ -4,6 +4,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
 import CompleteUserRegistrationForm from '~/components/CompleteUserRegistrationForm';
 import { NoLoginLayout } from '~/components/Layout/NoLoginLayout';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
+import { userActivationErrorCode } from '~/interfaces/errors/user-activation';
 import { IUserRegistrationOrder } from '~/server/models/user-registration-order';
 
 import {
@@ -13,6 +14,7 @@ import {
 type Props = CommonProps & {
   token: string
   email: string
+  errorCode: userActivationErrorCode
   isEmailAuthenticationEnabled: boolean
 }
 
@@ -22,6 +24,7 @@ const UserActivationPage: NextPage<Props> = (props: Props) => {
       <CompleteUserRegistrationForm
         token={props.token}
         email={props.email}
+        errorCode={props.errorCode}
         isEmailAuthenticationEnabled={props.isEmailAuthenticationEnabled}
       />
     </NoLoginLayout>
@@ -57,6 +60,10 @@ export const getServerSideProps: GetServerSideProps = async(context: GetServerSi
     props.token = userRegistrationOrder.token;
   }
 
+  if (typeof context.query.errorCode === 'string') {
+    props.errorCode = context.query.errorCode as userActivationErrorCode;
+  }
+
   props.isEmailAuthenticationEnabled = req.crowi.configManager.getConfig('crowi', 'security:passport-local:isEmailAuthenticationEnabled');
 
   await injectNextI18NextConfigurations(context, props, ['translation']);

+ 1 - 1
packages/app/src/server/middlewares/inject-user-registration-order-by-token-middleware.ts

@@ -19,7 +19,7 @@ export default async(req: ReqWithUserRegistrationOrder, res: Response, next: Nex
 
   // check if the token is valid
   if (userRegistrationOrder == null || userRegistrationOrder.isExpired() || userRegistrationOrder.isRevoked) {
-    return next(createError(400, 'userRegistrationOrder is null or expired or revoked', { code: 'password-reset-order-is-not-appropriate' }));
+    return next(createError(400, 'userRegistrationOrder is null or expired or revoked', { code: 'user-registration-order-is-not-appropriate' }));
   }
 
   req.userRegistrationOrder = userRegistrationOrder;

+ 1 - 1
packages/app/src/server/routes/index.js

@@ -201,7 +201,7 @@ module.exports = function(crowi, app) {
 
   app.use('/user-activation', express.Router()
     .get('/:token', applicationInstalled, injectUserRegistrationOrderByTokenMiddleware, userActivation.renderUserActivationPage(crowi))
-    .use(userActivation.tokenErrorHandlerMiddeware));
+    .use(userActivation.tokenErrorHandlerMiddeware(crowi)));
 
   app.get('/share/:linkId', next.delegateToNext);
 

+ 13 - 7
packages/app/src/server/routes/user-activation.ts

@@ -1,5 +1,6 @@
-import { Request, Response, NextFunction } from 'express';
+import { Response, NextFunction } from 'express';
 
+import { userActivationErrorCode } from '~/interfaces/errors/user-activation';
 import { ReqWithUserRegistrationOrder } from '~/server/middlewares/inject-user-registration-order-by-token-middleware';
 
 type Crowi = {
@@ -22,10 +23,15 @@ export const renderUserActivationPage = (crowi: Crowi) => {
 };
 
 // middleware to handle error
-export const tokenErrorHandlerMiddeware = (err, req: Request, res: Response, next: NextFunction) => {
-  if (err != null) {
-    // req.flash('errorMessage', req.t('message.incorrect_token_or_expired_url'));
-    return res.redirect('/login#register');
-  }
-  next();
+export const tokenErrorHandlerMiddeware = (crowi: Crowi) => {
+  return (error: Error & { code: userActivationErrorCode, statusCode: number }, req: CrowiReq, res: Response, next: NextFunction): void => {
+    if (error != null) {
+      const { nextApp } = crowi;
+      req.crowi = crowi;
+      nextApp.render(req, res, '/user-activation', { errorCode: error.code });
+      return;
+    }
+
+    next();
+  };
 };