github.com/minio/console@v1.4.1/web-app/src/screens/Console/Support/registerThunks.ts (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2023 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  import {
    18    resetRegisterForm,
    19    setClusterRegistered,
    20    setLicenseInfo,
    21    setLoading,
    22    setLoadingLicenseInfo,
    23    setSelectedSubnetOrganization,
    24    setSubnetAccessToken,
    25    setSubnetMFAToken,
    26    setSubnetOrganizations,
    27    setSubnetOTP,
    28  } from "./registerSlice";
    29  import api from "../../../common/api";
    30  import {
    31    SubnetInfo,
    32    SubnetLoginRequest,
    33    SubnetLoginResponse,
    34    SubnetLoginWithMFARequest,
    35    SubnetRegisterRequest,
    36  } from "../License/types";
    37  import { ErrorResponseHandler } from "../../../common/types";
    38  import {
    39    setErrorSnackMessage,
    40    setServerNeedsRestart,
    41  } from "../../../systemSlice";
    42  import { createAsyncThunk } from "@reduxjs/toolkit";
    43  import { AppState } from "../../../store";
    44  import { hasPermission } from "../../../common/SecureComponent";
    45  import {
    46    CONSOLE_UI_RESOURCE,
    47    IAM_PAGES,
    48    IAM_PAGES_PERMISSIONS,
    49  } from "../../../common/SecureComponent/permissions";
    50  
    51  export const fetchLicenseInfo = createAsyncThunk(
    52    "register/fetchLicenseInfo",
    53    async (_, { getState, dispatch }) => {
    54      const state = getState() as AppState;
    55  
    56      const getSubnetInfo = hasPermission(
    57        CONSOLE_UI_RESOURCE,
    58        IAM_PAGES_PERMISSIONS[IAM_PAGES.LICENSE],
    59        true,
    60      );
    61  
    62      const loadingLicenseInfo = state.register.loadingLicenseInfo;
    63  
    64      if (loadingLicenseInfo) {
    65        return;
    66      }
    67      if (getSubnetInfo) {
    68        dispatch(setLoadingLicenseInfo(true));
    69        api
    70          .invoke("GET", `/api/v1/subnet/info`)
    71          .then((res: SubnetInfo) => {
    72            dispatch(setLicenseInfo(res));
    73            dispatch(setClusterRegistered(true));
    74            dispatch(setLoadingLicenseInfo(false));
    75          })
    76          .catch((err: ErrorResponseHandler) => {
    77            if (
    78              err.detailedError.toLowerCase() !==
    79                "License is not present".toLowerCase() &&
    80              err.detailedError.toLowerCase() !==
    81                "license not found".toLowerCase()
    82            ) {
    83              dispatch(setErrorSnackMessage(err));
    84            }
    85            dispatch(setClusterRegistered(false));
    86            dispatch(setLoadingLicenseInfo(false));
    87          });
    88      } else {
    89        dispatch(setLoadingLicenseInfo(false));
    90      }
    91    },
    92  );
    93  
    94  export interface ClassRegisterArgs {
    95    token: string;
    96    account_id: string;
    97  }
    98  
    99  export const callRegister = createAsyncThunk(
   100    "register/callRegister",
   101    async (args: ClassRegisterArgs, { dispatch }) => {
   102      const request: SubnetRegisterRequest = {
   103        token: args.token,
   104        account_id: args.account_id,
   105      };
   106      api
   107        .invoke("POST", "/api/v1/subnet/register", request)
   108        .then(() => {
   109          dispatch(setLoading(false));
   110          dispatch(setServerNeedsRestart(true));
   111          dispatch(resetRegisterForm());
   112          dispatch(fetchLicenseInfo());
   113        })
   114        .catch((err: ErrorResponseHandler) => {
   115          dispatch(setErrorSnackMessage(err));
   116          dispatch(setLoading(false));
   117        });
   118    },
   119  );
   120  
   121  export const subnetLoginWithMFA = createAsyncThunk(
   122    "register/subnetLoginWithMFA",
   123    async (_, { getState, rejectWithValue, dispatch }) => {
   124      const state = getState() as AppState;
   125  
   126      const subnetEmail = state.register.subnetEmail;
   127      const subnetMFAToken = state.register.subnetMFAToken;
   128      const subnetOTP = state.register.subnetOTP;
   129      const loading = state.register.loading;
   130  
   131      if (loading) {
   132        return;
   133      }
   134      dispatch(setLoading(true));
   135      const request: SubnetLoginWithMFARequest = {
   136        username: subnetEmail,
   137        otp: subnetOTP,
   138        mfa_token: subnetMFAToken,
   139      };
   140      api
   141        .invoke("POST", "/api/v1/subnet/login/mfa", request)
   142        .then((resp: SubnetLoginResponse) => {
   143          dispatch(setLoading(false));
   144          if (resp && resp.access_token && resp.organizations.length > 0) {
   145            if (resp.organizations.length === 1) {
   146              dispatch(
   147                callRegister({
   148                  token: resp.access_token,
   149                  account_id: resp.organizations[0].accountId.toString(),
   150                }),
   151              );
   152            } else {
   153              dispatch(setSubnetAccessToken(resp.access_token));
   154              dispatch(setSubnetOrganizations(resp.organizations));
   155              dispatch(
   156                setSelectedSubnetOrganization(
   157                  resp.organizations[0].accountId.toString(),
   158                ),
   159              );
   160            }
   161          }
   162        })
   163        .catch((err: ErrorResponseHandler) => {
   164          dispatch(setErrorSnackMessage(err));
   165          dispatch(setLoading(false));
   166          dispatch(setSubnetOTP(""));
   167        });
   168    },
   169  );
   170  
   171  export const subnetLogin = createAsyncThunk(
   172    "register/subnetLogin",
   173    async (_, { getState, rejectWithValue, dispatch }) => {
   174      const state = getState() as AppState;
   175  
   176      const license = state.register.license;
   177      const subnetPassword = state.register.subnetPassword;
   178      const subnetEmail = state.register.subnetEmail;
   179      const loading = state.register.loading;
   180  
   181      if (loading) {
   182        return;
   183      }
   184      dispatch(setLoading(true));
   185      let request: SubnetLoginRequest = {
   186        username: subnetEmail,
   187        password: subnetPassword,
   188        apiKey: license,
   189      };
   190      api
   191        .invoke("POST", "/api/v1/subnet/login", request)
   192        .then((resp: SubnetLoginResponse) => {
   193          dispatch(setLoading(false));
   194          if (resp && resp.registered) {
   195            dispatch(resetRegisterForm());
   196            dispatch(fetchLicenseInfo());
   197          } else if (resp && resp.mfa_token) {
   198            dispatch(setSubnetMFAToken(resp.mfa_token));
   199          } else if (resp && resp.access_token && resp.organizations.length > 0) {
   200            dispatch(setSubnetAccessToken(resp.access_token));
   201            dispatch(setSubnetOrganizations(resp.organizations));
   202            dispatch(
   203              setSelectedSubnetOrganization(
   204                resp.organizations[0].accountId.toString(),
   205              ),
   206            );
   207          }
   208        })
   209        .catch((err: ErrorResponseHandler) => {
   210          dispatch(setErrorSnackMessage(err));
   211          dispatch(setLoading(false));
   212          dispatch(resetRegisterForm());
   213        });
   214    },
   215  );