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:
+20
-19
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user