From 265d4653a7cececcc19b0ced4fbd5cc663552c92 Mon Sep 17 00:00:00 2001 From: zerosoul Date: Thu, 31 Mar 2022 17:43:58 +0800 Subject: [PATCH] feat: login config --- src/app/services/base.query.js | 180 ++++++----- src/app/services/server.js | 289 +++++++++--------- src/common/component/Setting/config/Logins.js | 115 +++++++ .../component/Setting/config/useConfig.js | 180 ++++++----- src/common/component/Setting/navs.js | 190 ++++++------ src/routes/login/SolidLoginButton.js | 56 ++-- src/routes/login/index.js | 246 +++++++-------- 7 files changed, 686 insertions(+), 570 deletions(-) create mode 100644 src/common/component/Setting/config/Logins.js diff --git a/src/app/services/base.query.js b/src/app/services/base.query.js index 3b09165e..f28b0a95 100644 --- a/src/app/services/base.query.js +++ b/src/app/services/base.query.js @@ -1,106 +1,100 @@ -import { fetchBaseQuery } from "@reduxjs/toolkit/query"; -import toast from "react-hot-toast"; -import dayjs from "dayjs"; -import { updateToken, resetAuthData } from "../slices/auth.data"; -import BASE_URL, { tokenHeader } from "../config"; +import { fetchBaseQuery } from '@reduxjs/toolkit/query'; +import toast from 'react-hot-toast'; +import dayjs from 'dayjs'; +import { updateToken, resetAuthData } from '../slices/auth.data'; +import BASE_URL, { tokenHeader } from '../config'; const whiteList = [ - "login", - "register", - "checkInviteTokenValid", - "getServer", - "getOpenid", - "getMetamaskNonce", - "renew", + 'login', + 'register', + 'checkInviteTokenValid', + 'getLoginConfig', + 'getServer', + 'getOpenid', + 'getMetamaskNonce', + 'renew' ]; const baseQuery = fetchBaseQuery({ - baseUrl: BASE_URL, - prepareHeaders: (headers, { getState, endpoint }) => { - console.log("req", endpoint); - const { token } = getState().authData; - if (token && !whiteList.includes(endpoint)) { - headers.set(tokenHeader, token); - } - return headers; - }, + baseUrl: BASE_URL, + prepareHeaders: (headers, { getState, endpoint }) => { + console.log('req', endpoint); + const { token } = getState().authData; + if (token && !whiteList.includes(endpoint)) { + headers.set(tokenHeader, token); + } + return headers; + } }); let waitingForRenew = null; const baseQueryWithTokenCheck = async (args, api, extraOptions) => { - if (waitingForRenew) { - await waitingForRenew; - } - // 先检查token是否过期,过期则renew - const { - token, - refreshToken, - expireTime = new Date().getTime(), - } = api.getState().authData; - let result = null; - if ( - !whiteList.includes(api.endpoint) && - dayjs().isAfter(new Date(expireTime - 20 * 1000)) - ) { - // 快过期了,renew - waitingForRenew = baseQuery( - { - url: "/token/renew", - method: "POST", - body: { - token, - refresh_token: refreshToken, - }, - }, - api, - extraOptions - ); - result = await waitingForRenew; - waitingForRenew = null; - if (result.data) { - // store the new token - api.dispatch(updateToken(result.data)); - // retry the initial query - result = await baseQuery(args, api, extraOptions); + if (waitingForRenew) { + await waitingForRenew; + } + // 先检查token是否过期,过期则renew + const { token, refreshToken, expireTime = new Date().getTime() } = api.getState().authData; + let result = null; + if (!whiteList.includes(api.endpoint) && dayjs().isAfter(new Date(expireTime - 20 * 1000))) { + // 快过期了,renew + waitingForRenew = baseQuery( + { + url: '/token/renew', + method: 'POST', + body: { + token, + refresh_token: refreshToken } - } else { - result = await baseQuery(args, api, extraOptions); + }, + api, + extraOptions + ); + result = await waitingForRenew; + waitingForRenew = null; + if (result.data) { + // store the new token + api.dispatch(updateToken(result.data)); + // retry the initial query + result = await baseQuery(args, api, extraOptions); } - if (result?.error) { - console.log("api error", result.error, api.endpoint); - switch (result.error.originalStatus || result.error.status) { - case "FETCH_ERROR": - { - toast.error(`${api.endpoint}: Failed to fetch`); - } - break; - case 404: - { - toast.error("Request Not Found"); - } - break; - case 500: - { - toast.error(result.error.data || "server error"); - } - break; - case 401: - { - // if (api.endpoint === "renew") { - // toast.error("token expired, please login again"); - api.dispatch(resetAuthData()); - location.href = "/#/login"; - // } else { - toast.error("API Not Authenticated"); - // return; - // } - } - break; - case 403: - toast.error("Request Not Allowed"); - break; - default: - break; + } else { + result = await baseQuery(args, api, extraOptions); + } + if (result?.error) { + console.log('api error', result.error, api.endpoint); + switch (result.error.originalStatus || result.error.status) { + case 'FETCH_ERROR': + { + toast.error(`${api.endpoint}: Failed to fetch`); } + break; + case 404: + { + toast.error('Request Not Found'); + } + break; + case 500: + { + toast.error(result.error.data || 'server error'); + } + break; + case 401: + { + // if (api.endpoint === "renew") { + // toast.error("token expired, please login again"); + api.dispatch(resetAuthData()); + location.href = '/#/login'; + // } else { + toast.error('API Not Authenticated'); + // return; + // } + } + break; + case 403: + toast.error('Request Not Allowed'); + break; + default: + break; } - return result; + } + return result; }; export default baseQueryWithTokenCheck; diff --git a/src/app/services/server.js b/src/app/services/server.js index 070476d8..ced50103 100644 --- a/src/app/services/server.js +++ b/src/app/services/server.js @@ -1,147 +1,156 @@ -import { createApi } from "@reduxjs/toolkit/query/react"; -import BASE_URL from "../config"; -import { updateInviteLink, updateInfo } from "../slices/server"; -import baseQuery from "./base.query"; +import { createApi } from '@reduxjs/toolkit/query/react'; +import BASE_URL from '../config'; +import { updateInviteLink, updateInfo } from '../slices/server'; +import baseQuery from './base.query'; const defaultExpireDuration = 7 * 24 * 60 * 60; export const serverApi = createApi({ - reducerPath: "serverApi", - baseQuery, - endpoints: (builder) => ({ - getServer: builder.query({ - query: () => ({ url: `admin/system/organization` }), - transformResponse: (data) => { - data.logo = `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`; - return data; - }, - async onQueryStarted(data, { dispatch, queryFulfilled }) { - try { - const { data: server } = await queryFulfilled; - dispatch(updateInfo(server)); - } catch { - console.log("get server info error"); - } - }, - }), - getMetrics: builder.query({ - query: () => ({ url: `/admin/system/metrics` }), - }), - getFirebaseConfig: builder.query({ - query: () => ({ url: `admin/fcm/config` }), - }), - sendTestEmail: builder.mutation({ - query: (data) => ({ - url: `/admin/system/send_mail`, - method: "POST", - body: data, - }), - }), - updateFirebaseConfig: builder.mutation({ - query: (data) => ({ - url: `admin/fcm/config`, - method: "POST", - body: data, - }), - }), - getAgoraConfig: builder.query({ - query: () => ({ url: `admin/agora/config` }), - }), - updateAgoraConfig: builder.mutation({ - query: (data) => ({ - url: `admin/agora/config`, - method: "POST", - body: data, - }), - }), - getSMTPConfig: builder.query({ - query: () => ({ url: `admin/smtp/config` }), - }), - updateSMTPConfig: builder.mutation({ - query: (data) => ({ - url: `admin/smtp/config`, - method: "POST", - body: data, - }), - }), - updateLogo: builder.mutation({ - query: (data) => ({ - headers: { - "content-type": "image/png", - }, - url: `admin/system/organization/logo`, - method: "POST", - body: data, - }), - async onQueryStarted(data, { dispatch, queryFulfilled }) { - try { - await queryFulfilled; - dispatch( - updateInfo({ - logo: `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`, - }) - ); - } catch { - console.log("update server logo error"); - } - }, - }), - createInviteLink: builder.query({ - query: (expired_in = defaultExpireDuration) => ({ - headers: { - "content-type": "text/plain", - accept: "text/plain", - }, - url: `/admin/user/create_invite_link?expired_in=${expired_in}`, - responseHandler: (response) => response.text(), - }), - transformResponse: (link) => { - // 替换掉域名 - const invite = new URL(link); - return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`; - }, - async onQueryStarted( - expire = defaultExpireDuration, - { dispatch, queryFulfilled } - ) { - try { - const { data: link } = await queryFulfilled; - console.log("link", link); - dispatch(updateInviteLink({ expire, link })); - } catch { - console.log("invite link error"); - } - }, - }), - updateServer: builder.mutation({ - query: (data) => ({ - url: `admin/system/organization`, - method: "POST", - body: data, - }), - async onQueryStarted(data, { dispatch, queryFulfilled, getState }) { - const { name: prevName, description: prevDesc } = getState().server; - dispatch(updateInfo(data)); - try { - await queryFulfilled; - } catch { - dispatch(updateInfo({ name: prevName, description: prevDesc })); - } - }, - }), + reducerPath: 'serverApi', + baseQuery, + endpoints: (builder) => ({ + getServer: builder.query({ + query: () => ({ url: `admin/system/organization` }), + transformResponse: (data) => { + data.logo = `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`; + return data; + }, + async onQueryStarted(data, { dispatch, queryFulfilled }) { + try { + const { data: server } = await queryFulfilled; + dispatch(updateInfo(server)); + } catch { + console.log('get server info error'); + } + } }), + getMetrics: builder.query({ + query: () => ({ url: `/admin/system/metrics` }) + }), + getFirebaseConfig: builder.query({ + query: () => ({ url: `admin/fcm/config` }) + }), + sendTestEmail: builder.mutation({ + query: (data) => ({ + url: `/admin/system/send_mail`, + method: 'POST', + body: data + }) + }), + updateFirebaseConfig: builder.mutation({ + query: (data) => ({ + url: `admin/fcm/config`, + method: 'POST', + body: data + }) + }), + getAgoraConfig: builder.query({ + query: () => ({ url: `admin/agora/config` }) + }), + updateAgoraConfig: builder.mutation({ + query: (data) => ({ + url: `admin/agora/config`, + method: 'POST', + body: data + }) + }), + getSMTPConfig: builder.query({ + query: () => ({ url: `admin/smtp/config` }) + }), + updateSMTPConfig: builder.mutation({ + query: (data) => ({ + url: `admin/smtp/config`, + method: 'POST', + body: data + }) + }), + getLoginConfig: builder.query({ + query: () => ({ url: `admin/login/config` }) + }), + updateLoginConfig: builder.mutation({ + query: (data) => ({ + url: `admin/login/config`, + method: 'POST', + body: data + }) + }), + updateLogo: builder.mutation({ + query: (data) => ({ + headers: { + 'content-type': 'image/png' + }, + url: `admin/system/organization/logo`, + method: 'POST', + body: data + }), + async onQueryStarted(data, { dispatch, queryFulfilled }) { + try { + await queryFulfilled; + dispatch( + updateInfo({ + logo: `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}` + }) + ); + } catch { + console.log('update server logo error'); + } + } + }), + createInviteLink: builder.query({ + query: (expired_in = defaultExpireDuration) => ({ + headers: { + 'content-type': 'text/plain', + accept: 'text/plain' + }, + url: `/admin/user/create_invite_link?expired_in=${expired_in}`, + responseHandler: (response) => response.text() + }), + transformResponse: (link) => { + // 替换掉域名 + const invite = new URL(link); + return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`; + }, + async onQueryStarted(expire = defaultExpireDuration, { dispatch, queryFulfilled }) { + try { + const { data: link } = await queryFulfilled; + console.log('link', link); + dispatch(updateInviteLink({ expire, link })); + } catch { + console.log('invite link error'); + } + } + }), + updateServer: builder.mutation({ + query: (data) => ({ + url: `admin/system/organization`, + method: 'POST', + body: data + }), + async onQueryStarted(data, { dispatch, queryFulfilled, getState }) { + const { name: prevName, description: prevDesc } = getState().server; + dispatch(updateInfo(data)); + try { + await queryFulfilled; + } catch { + dispatch(updateInfo({ name: prevName, description: prevDesc })); + } + } + }) + }) }); export const { - useSendTestEmailMutation, - useUpdateFirebaseConfigMutation, - useGetFirebaseConfigQuery, - useGetSMTPConfigQuery, - useUpdateSMTPConfigMutation, - useGetAgoraConfigQuery, - useUpdateAgoraConfigMutation, - useGetServerQuery, - useLazyGetMetricsQuery, - useLazyGetServerQuery, - useUpdateServerMutation, - useUpdateLogoMutation, - useLazyCreateInviteLinkQuery, + useSendTestEmailMutation, + useUpdateFirebaseConfigMutation, + useGetFirebaseConfigQuery, + useGetLoginConfigQuery, + useUpdateLoginConfigMutation, + useGetSMTPConfigQuery, + useUpdateSMTPConfigMutation, + useGetAgoraConfigQuery, + useUpdateAgoraConfigMutation, + useGetServerQuery, + useLazyGetMetricsQuery, + useLazyGetServerQuery, + useUpdateServerMutation, + useUpdateLogoMutation, + useLazyCreateInviteLinkQuery } = serverApi; diff --git a/src/common/component/Setting/config/Logins.js b/src/common/component/Setting/config/Logins.js new file mode 100644 index 00000000..2e96cfcb --- /dev/null +++ b/src/common/component/Setting/config/Logins.js @@ -0,0 +1,115 @@ +// import { useState, useEffect } from "react"; +import StyledContainer from './StyledContainer'; +// import Input from "../../styled/Input"; +import Textarea from '../../styled/Textarea'; +import Toggle from '../../styled/Toggle'; +import Label from '../../styled/Label'; +import SaveTip from '../../SaveTip'; +import useConfig from './useConfig'; + +export default function Logins() { + const { values, updateConfig, setValues, reset, changed } = useConfig('login'); + const handleUpdate = () => { + // const { token_url, description } = values; + updateConfig(values); + }; + const handleChange = (evt) => { + const newValue = evt.target.value; + const { type } = evt.target.dataset; + const items = newValue ? newValue.split('\n') : []; + setValues((prev) => { + return { ...prev, [type]: items }; + }); + }; + const handleToggle = (val) => { + setValues((prev) => { + return { ...prev, ...val }; + }); + }; + if (!values) return null; + const { google, metamask, password, oidc = [] } = values ?? {}; + return ( + +
+
+ + +
+
+ + +
+
+ + +
+
+ +