Merge remote-tracking branch 'upstream/main' into refactor/typescript

# Conflicts:
#	src/app/services/server.ts
#	src/common/component/GoogleLoginButton.tsx
#	src/common/utils.tsx
This commit is contained in:
HD
2022-06-28 10:10:56 +08:00
47 changed files with 513 additions and 355 deletions
+20 -19
View File
@@ -1,22 +1,22 @@
// const BASE_URL = `${location.origin}/api`;
const BASE_URL = `https://dev.rustchat.com/api`;
export const CACHE_VERSION = `0.2.17`;
export const CACHE_VERSION = `0.3.0`;
export const ContentTypes = {
text: "text/plain",
markdown: "text/markdown",
file: "rustchat/file",
file: "vocechat/file",
archive: "vocechat/archive",
formData: "multipart/form-data",
json: "application/json",
archive: "rustchat/archive"
json: "application/json"
};
export const firebaseConfig = {
apiKey: "AIzaSyDyJ6B1Ouenoha_gdGkBwIkBNStlwhlbO0",
authDomain: "rustchat-develop.firebaseapp.com",
projectId: "rustchat-develop",
storageBucket: "rustchat-develop.appspot.com",
messagingSenderId: "418687074928",
appId: "1:418687074928:web:753286adbf239f5af9eab5",
measurementId: "G-XV476KEC8P"
apiKey: "AIzaSyCc3VuCJZgzQLIH2wrYdQzsUOc1DuZiIOA",
authDomain: "vocechatdev.firebaseapp.com",
projectId: "vocechatdev",
storageBucket: "vocechatdev.appspot.com",
messagingSenderId: "526613312184",
appId: "1:526613312184:web:d13c92582baf470d487a4d",
measurementId: "G-82RQ3YSCP7"
};
export const ChatPrefixs = {
channel: "#",
@@ -27,14 +27,15 @@ export const vapidKey = `BGXCn-5YRXSFw38Q9lUKJ5bibL212-yIQn1pCvthGhp6_KwA29FO1Ax
export const tokenHeader = "X-API-Key";
export const FILE_SLICE_SIZE = 1000 * 200 * 8; //200kb
export const FILE_IMAGE_SIZE = 1000 * 10000 * 8; //10mb
export const KEY_TOKEN = "RUSTCHAT_TOKEN";
export const KEY_EXPIRE = "RUSTCHAT_TOKEN_EXPIRE";
export const KEY_REFRESH_TOKEN = "RUSTCHAT_REFRESH_TOKEN";
export const KEY_UID = "RUSTCHAT_CURR_UID";
export const KEY_DEVICE_KEY = "RUSTCHAT_DEVICE_KEY";
export const KEY_USERS_VERSION = "RUSTCHAT_USERS_VERSION";
export const KEY_AFTER_MID = "RUSTCHAT_AFTER_MID";
export const KEY_PWA_INSTALLED = "RUSTCHAT_PWA_INSTALLED";
export const KEY_TOKEN = "VOCECHAT_TOKEN";
export const KEY_EXPIRE = "VOCECHAT_TOKEN_EXPIRE";
export const KEY_REFRESH_TOKEN = "VOCECHAT_REFRESH_TOKEN";
export const KEY_UID = "VOCECHAT_CURR_UID";
export const KEY_DEVICE_KEY = "VOCECHAT_DEVICE_KEY";
export const KEY_USERS_VERSION = "VOCECHAT_USERS_VERSION";
export const KEY_AFTER_MID = "VOCECHAT_AFTER_MID";
export const KEY_PWA_INSTALLED = "VOCECHAT_PWA_INSTALLED";
export const KEY_LOCAL_MAGIC_TOKEN = "VOCECHAT_LOCAL_MAGIC_TOKEN";
export const Emojis = ["👍", "❤️", "😄", "👀", "👎", "🎉", "🙁", "🚀"];
export const Views = {
item: "item",
+18 -13
View File
@@ -2,8 +2,8 @@ import { createApi } from "@reduxjs/toolkit/query/react";
import { nanoid } from "@reduxjs/toolkit";
import baseQuery from "./base.query";
import { setAuthData, updateToken, resetAuthData, updateInitialized } from "../slices/auth.data";
import BASE_URL, { KEY_DEVICE_KEY } from "../config";
import { AuthData } from "../../types/auth";
import BASE_URL, { KEY_DEVICE_KEY, KEY_LOCAL_MAGIC_TOKEN } from "../config";
import { AuthData, LoginCredential } from "../../types/auth";
const getDeviceId = () => {
let d = localStorage.getItem(KEY_DEVICE_KEY);
@@ -18,12 +18,12 @@ export const authApi = createApi({
reducerPath: "authApi",
baseQuery,
endpoints: (builder) => ({
login: builder.mutation<AuthData, string>({
query: (credentials) => ({
login: builder.mutation<AuthData, LoginCredential>({
query: (credential) => ({
url: "token/login",
method: "POST",
body: {
credential: credentials,
credential,
device: getDeviceId(),
device_token: "test"
}
@@ -32,13 +32,10 @@ export const authApi = createApi({
const { avatar_updated_at } = data.user;
return {
...data,
user: {
...data.user,
avatar:
avatar_updated_at == 0
? ""
: `${BASE_URL}/resource/avatar?uid=${data.user.uid}&t=${avatar_updated_at}`
}
avatar:
avatar_updated_at == 0
? ""
: `${BASE_URL}/resource/avatar?uid=${data.user.uid}&t=${avatar_updated_at}`
};
},
async onQueryStarted(params, { dispatch, queryFulfilled }) {
@@ -47,6 +44,8 @@ export const authApi = createApi({
if (data) {
dispatch(setAuthData(data));
}
// 从localstorage 去掉 magic token
localStorage.removeItem(KEY_LOCAL_MAGIC_TOKEN);
} catch {
console.log("login error");
}
@@ -139,6 +138,11 @@ export const authApi = createApi({
url: `/token/metamask/nonce?public_address=${address}`
})
}),
checkEmail: builder.query({
query: (email) => ({
url: `/user/check_email?email=${encodeURIComponent(email)}`
})
}),
getCredentials: builder.query({
query: () => ({ url: "/token/credentials" })
}),
@@ -153,7 +157,7 @@ export const authApi = createApi({
}
}
}),
getInitialized: builder.query({
getInitialized: builder.query<boolean, void>({
query: () => ({ url: "/admin/system/initialized" }),
async onQueryStarted(params, { dispatch, queryFulfilled }) {
try {
@@ -168,6 +172,7 @@ export const authApi = createApi({
});
export const {
useLazyCheckEmailQuery,
useGetInitializedQuery,
useSendLoginMagicLinkMutation,
useSendRegMagicLinkMutation,
+12 -14
View File
@@ -9,6 +9,7 @@ const whiteList = [
"register",
"sendLoginMagicLink",
"sendRegMagicLink",
"checkEmail",
"checkMagicTokenValid",
"getGoogleAuthConfig",
"getGithubAuthConfig",
@@ -76,16 +77,6 @@ const baseQueryWithTokenCheck = async (args, api, extraOptions) => {
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 !== "login") {
@@ -93,15 +84,22 @@ const baseQueryWithTokenCheck = async (args, api, extraOptions) => {
location.href = "/#/login";
toast.error("API Not Authenticated");
}
// toast.error("token expired, please login again");
// } else {
// return;
// }
}
break;
case 403:
toast.error("Request Not Allowed");
break;
case 404:
{
toast.error("Request Not Found");
}
break;
case 500:
{
toast.error(result.error.data || "Server Error");
}
break;
default:
break;
}
+48 -49
View File
@@ -1,26 +1,31 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import BASE_URL from "../config";
import { updateInfo } from "../slices/server";
import { updateInfo, StoredServer } from "../slices/server";
import baseQuery from "./base.query";
import { RootState } from "../store";
import { User } from "../../types/auth";
import {
FirebaseConfig,
GoogleAuthConfig,
LoginConfig,
Server,
TestEmailDTO,
NewAdminDTO,
SMTPConfig,
AgoraConfig,
GithubAuthConfig
} from "../../types/server";
const defaultExpireDuration = 7 * 24 * 60 * 60;
// todo: doc
interface GetServerResponse {}
interface GetThirdPartySecretResponse {}
interface UpdateThirdPartySecretResponse {}
// interface GetServerVersionResponse {}
interface GetLoginConfigResponse {}
export const serverApi = createApi({
reducerPath: "serverApi",
baseQuery,
endpoints: (builder) => ({
getServer: builder.query<GetServerResponse, void>({
getServer: builder.query<StoredServer, void>({
query: () => ({ url: `admin/system/organization` }),
transformResponse: (data) => {
data.logo = `${BASE_URL}/resource/organization/logo?t=${+new Date()}`;
return data;
transformResponse: (data: Server) => {
const logo = `${BASE_URL}/resource/organization/logo?t=${+new Date()}`;
return { ...data, logo };
},
async onQueryStarted(data, { dispatch, queryFulfilled }) {
try {
@@ -31,98 +36,94 @@ export const serverApi = createApi({
}
}
}),
getThirdPartySecret: builder.query<GetThirdPartySecretResponse, void>({
getThirdPartySecret: builder.query<string, void>({
query: () => ({
// headers: {
// "content-type": "text/plain",
// accept: "text/plain",
// },
url: `/admin/system/third_party_secret`,
responseHandler: (response) => response.text()
responseHandler: (response: Response) => response.text()
}),
keepUnusedDataFor: 0
}),
updateThirdPartySecret: builder.mutation<UpdateThirdPartySecretResponse, void>({
updateThirdPartySecret: builder.mutation<string, void>({
query: () => ({
url: `/admin/system/third_party_secret`,
method: "POST",
responseHandler: (response) => response.text()
responseHandler: (response: Response) => response.text()
})
}),
getMetrics: builder.query({
query: () => ({ url: `/admin/system/metrics` })
}),
getServerVersion: builder.query<string, void>({
query: () => ({
headers: { accept: "text/plain" },
headers: {
// "content-type": "text/plain",
accept: "text/plain"
},
url: `/admin/system/version`,
responseHandler: (response: Response) => response.text()
})
}),
getFirebaseConfig: builder.query({
getFirebaseConfig: builder.query<FirebaseConfig, void>({
query: () => ({ url: `admin/fcm/config` })
}),
getGoogleAuthConfig: builder.query({
getGoogleAuthConfig: builder.query<GoogleAuthConfig, void>({
query: () => ({ url: `admin/google_auth/config` })
}),
updateGoogleAuthConfig: builder.mutation({
updateGoogleAuthConfig: builder.mutation<void, GoogleAuthConfig>({
query: (data) => ({
url: `admin/google_auth/config`,
method: "POST",
body: data
})
}),
getGithubAuthConfig: builder.query({
getGithubAuthConfig: builder.query<GithubAuthConfig, void>({
query: () => ({ url: `admin/github_auth/config` })
}),
updateGithubAuthConfig: builder.mutation({
updateGithubAuthConfig: builder.mutation<void, GithubAuthConfig>({
query: (data) => ({
url: `admin/github_auth/config`,
method: "POST",
body: data
})
}),
sendTestEmail: builder.mutation({
sendTestEmail: builder.mutation<void, TestEmailDTO>({
query: (data) => ({
url: `/admin/system/send_mail`,
method: "POST",
body: data
})
}),
updateFirebaseConfig: builder.mutation({
updateFirebaseConfig: builder.mutation<void, FirebaseConfig>({
query: (data) => ({
url: `admin/fcm/config`,
method: "POST",
body: data
})
}),
getAgoraConfig: builder.query({
getAgoraConfig: builder.query<AgoraConfig, void>({
query: () => ({ url: `admin/agora/config` })
}),
updateAgoraConfig: builder.mutation({
updateAgoraConfig: builder.mutation<void, AgoraConfig>({
query: (data) => ({
url: `admin/agora/config`,
method: "POST",
body: data
})
}),
getSMTPConfig: builder.query({
getSMTPConfig: builder.query<SMTPConfig, void>({
query: () => ({ url: `admin/smtp/config` })
}),
getSMTPStatus: builder.query({
getSMTPStatus: builder.query<boolean, void>({
query: () => ({ url: `/admin/smtp/enabled` })
}),
updateSMTPConfig: builder.mutation({
updateSMTPConfig: builder.mutation<void, SMTPConfig>({
query: (data) => ({
url: `admin/smtp/config`,
method: "POST",
body: data
})
}),
getLoginConfig: builder.query<GetLoginConfigResponse, void>({
getLoginConfig: builder.query<LoginConfig, void>({
query: () => ({ url: `admin/login/config` })
}),
updateLoginConfig: builder.mutation({
updateLoginConfig: builder.mutation<void, LoginConfig>({
query: (data) => ({
url: `admin/login/config`,
method: "POST",
@@ -151,29 +152,30 @@ export const serverApi = createApi({
}
}
}),
createInviteLink: builder.query({
createInviteLink: builder.query<string, number>({
query: (expired_in = defaultExpireDuration) => ({
headers: {
"content-type": "text/plain",
accept: "text/plain"
},
url: `/admin/system/create_invite_link?expired_in=${expired_in}`,
responseHandler: (response) => response.text()
responseHandler: (response: Response) => response.text()
}),
transformResponse: (link) => {
transformResponse: (link: string) => {
// 替换掉域名
const invite = new URL(link);
return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`;
}
}),
updateServer: builder.mutation({
updateServer: builder.mutation<void, Server>({
query: (data) => ({
url: `admin/system/organization`,
method: "POST",
body: data
}),
async onQueryStarted(data, { dispatch, queryFulfilled, getState }) {
const { name: prevName, description: prevDesc } = getState().server;
const rootStore = getState() as RootState;
const { name: prevName, description: prevDesc } = rootStore.server;
dispatch(updateInfo(data));
try {
await queryFulfilled;
@@ -182,14 +184,14 @@ export const serverApi = createApi({
}
}
}),
createAdmin: builder.mutation({
createAdmin: builder.mutation<User, NewAdminDTO>({
query: (data) => ({
url: `/admin/system/create_admin`,
method: "POST",
body: data
})
}),
getInitialized: builder.query({
getInitialized: builder.query<boolean, void>({
query: () => ({
url: `/admin/system/initialized`
})
@@ -210,15 +212,12 @@ export const {
useLazyGetAgoraConfigQuery,
useLazyGetSMTPConfigQuery,
useLazyGetLoginConfigQuery,
// useGetFirebaseConfigQuery,
// useGetAgoraConfigQuery,
useGetLoginConfigQuery,
useUpdateLoginConfigMutation,
useGetSMTPConfigQuery,
useUpdateSMTPConfigMutation,
useUpdateAgoraConfigMutation,
useGetServerQuery,
useGetMetricsQuery,
useLazyGetServerQuery,
useUpdateServerMutation,
useUpdateLogoMutation,
+6 -8
View File
@@ -1,16 +1,14 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { Server } from "../../types/server";
interface State {
name: string;
description: string;
export interface StoredServer extends Server {
logo: string;
inviteLink: {
inviteLink?: {
link: string;
expire: number;
};
}
const initialState: State = {
const initialState: StoredServer = {
name: "",
description: "",
logo: "",
@@ -27,7 +25,7 @@ const serverSlice = createSlice({
resetServer() {
return initialState;
},
fullfillServer(state, action: PayloadAction<State>) {
fullfillServer(state, action: PayloadAction<StoredServer>) {
const {
inviteLink = {
link: "",
@@ -39,7 +37,7 @@ const serverSlice = createSlice({
} = action.payload || {};
return { name, logo, description, inviteLink };
},
updateInfo(state, action: PayloadAction<Partial<State>>) {
updateInfo(state, action: PayloadAction<Partial<StoredServer>>) {
const values = action.payload || {};
// todo: check and remove old logic
// Object.keys(values).forEach((_key) => {