Skip to content

Commit

Permalink
feat(project): support bind github (#1576)
Browse files Browse the repository at this point in the history
* feat(project): support bind github

* update binding github callback uri

* update styles
  • Loading branch information
hyrious authored Jun 17, 2022
1 parent c0b836a commit bdf8eed
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const FLAT_SERVER_LOGIN = {
} as const;

export const FLAT_SERVER_USER_BINDING = {
GITHUB_CALLBACK: `${FLAT_SERVER_VERSIONS.V1}/login/github/callback/binding`,
WECHAT_CALLBACK: `${FLAT_SERVER_VERSIONS.V1}/user/binding/platform/wechat/web`,
} as const;

Expand Down
12 changes: 6 additions & 6 deletions desktop/renderer-app/src/pages/LoginPage/githubLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,14 @@ export const githubLogin: LoginExecutor = onSuccess => {
let timer = NaN;
const authUUID = uuidv4();

function getGithubURL(authUUID: string): string {
const redirectURL = FLAT_SERVER_LOGIN.GITHUB_CALLBACK;
return `https://github.com/login/oauth/authorize?client_id=${GITHUB.CLIENT_ID}&redirect_uri=${redirectURL}&state=${authUUID}`;
}

void (async () => {
try {
await setAuthUUID(authUUID);
} catch (err) {
errorTips(err);
}

void shell.openExternal(getGithubURL(authUUID));
void shell.openExternal(getGithubURL(authUUID, FLAT_SERVER_LOGIN.GITHUB_CALLBACK));

const githubLoginProcessRequest = async (): Promise<void> => {
try {
Expand All @@ -46,3 +41,8 @@ export const githubLogin: LoginExecutor = onSuccess => {
window.clearTimeout(timer);
};
};

export function getGithubURL(authUUID: string, redirect_uri: string): string {
const redirectURL = encodeURIComponent(redirect_uri);
return `https://github.com/login/oauth/authorize?client_id=${GITHUB.CLIENT_ID}&redirect_uri=${redirectURL}&state=${authUUID}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { shell } from "electron";
import { v4 } from "uuid";
import classNames from "classnames";
import React, { useCallback, useEffect, useState } from "react";
import { message, Modal } from "antd";
import { useTranslation } from "react-i18next";
import { GithubFilled } from "@ant-design/icons";

import { GlobalStore } from "../../../../stores/global-store";
import { useSafePromise } from "../../../../utils/hooks/lifecycle";
import {
bindingProcess,
LoginPlatform,
removeBinding,
setBindingAuthUUID,
} from "../../../../api-middleware/flatServer";
import { FLAT_SERVER_USER_BINDING } from "../../../../api-middleware/flatServer/constants";
import { getGithubURL } from "../../../LoginPage/githubLogin";
import { errorTips } from "../../../../components/Tips/ErrorTips";

export interface BindGitHubProps {
isBind: boolean;
onRefresh: () => void;
globalStore: GlobalStore;
}

export const BindGitHub: React.FC<BindGitHubProps> = ({ isBind, onRefresh, globalStore }) => {
const sp = useSafePromise();
const { t } = useTranslation();
const [authUUID, setAuthUUID] = useState("");

const cancel = useCallback((): void => {
setAuthUUID("");
onRefresh();
}, [onRefresh]);

useEffect(() => {
let timer = NaN;
async function waitUntilBindFinish(): Promise<void> {
const result = await sp(bindingProcess(authUUID));
if (result.processing) {
timer = window.setTimeout(waitUntilBindFinish, 2000);
} else {
if (!result.status) {
message.info(t("bind-wechat-failed"));
}
cancel();
}
}
if (authUUID) {
waitUntilBindFinish();
return () => {
Number.isNaN(timer) || window.clearTimeout(timer);
};
}
return;
}, [authUUID, cancel, onRefresh, sp, t]);

const bindGitHub = async (): Promise<void> => {
const authUUID = v4();
setAuthUUID(authUUID);
await sp(setBindingAuthUUID(authUUID));
void shell.openExternal(getGithubURL(authUUID, FLAT_SERVER_USER_BINDING.GITHUB_CALLBACK));
};

const unbind = (): void => {
Modal.confirm({
content: t("unbind-confirm"),
onOk: async () => {
try {
const { token } = await sp(removeBinding(LoginPlatform.Github));
globalStore.updateUserToken(token);
onRefresh();
message.info(t("unbind-success"));
} catch (err) {
errorTips(err);
}
},
});
};

return (
<span
className={classNames("binding-github", {
"is-bind": isBind,
})}
title={isBind ? t("is-bind") : t("not-bind")}
onClick={isBind ? unbind : bindGitHub}
>
<GithubFilled style={{ color: "#fff" }} />
</span>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface BindingWeChatProps {
globalStore: GlobalStore;
}

export const BindingWeChat: React.FC<BindingWeChatProps> = ({ isBind, onRefresh, globalStore }) => {
export const BindWeChat: React.FC<BindingWeChatProps> = ({ isBind, onRefresh, globalStore }) => {
const sp = useSafePromise();
const { t } = useTranslation();
const [authUUID, setAuthUUID] = useState("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { loginCheck, rename } from "../../../api-middleware/flatServer";
import { ConfirmButtons } from "./ConfirmButtons";
import { UploadAvatar, uploadAvatar } from "./UploadAvatar";
import { useBindingList } from "./binding";
import { BindingWeChat } from "./binding/WeChat";
import { BindWeChat } from "./binding/WeChat";
import { BindGitHub } from "./binding/GitHub";

enum SelectLanguage {
Chinese,
Expand Down Expand Up @@ -101,11 +102,16 @@ export const GeneralSettingPage = observer(function GeneralSettingPage() {
<ConfirmButtons onConfirm={changeUserName} />
</div>
<div className="general-setting-binding-methods">
<BindingWeChat
<BindWeChat
globalStore={globalStore}
isBind={bindings.wechat}
onRefresh={refreshBindings}
/>
<BindGitHub
globalStore={globalStore}
isBind={bindings.github}
onRefresh={refreshBindings}
/>
</div>
</div>
<div className="general-setting-checkbox">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,20 @@
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 8px;
cursor: pointer;

&.is-bind {
background-color: var(--green-6);
}
}

.binding-github:extend(.binding-wechat) {
&.is-bind {
background-color: var(--grey-11);
}
}

.binding-wechat-modal {
.ant-modal-body {
text-align: center;
Expand Down
1 change: 1 addition & 0 deletions web/flat-web/src/api-middleware/flatServer/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const FLAT_SERVER_LOGIN = {
} as const;

export const FLAT_SERVER_USER_BINDING = {
GITHUB_CALLBACK: `${FLAT_SERVER_VERSIONS.V1}/login/github/callback/binding`,
WECHAT_CALLBACK: `${FLAT_SERVER_VERSIONS.V1}/user/binding/platform/wechat/web`,
} as const;

Expand Down
12 changes: 6 additions & 6 deletions web/flat-web/src/pages/LoginPage/agoraLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ import { AGORA_OAUTH } from "../../constants/process";
export const agoraLogin: LoginExecutor = () => {
const authUUID = uuidv4();

function getAgoraURL(authUUID: string): string {
const redirectURL = encodeURIComponent(FLAT_SERVER_LOGIN.AGORA_CALLBACK);
return `https://sso2.agora.io/api/v0/oauth/authorize?response_type=code&client_id=${AGORA_OAUTH.CLIENT_ID}&redirect_uri=${redirectURL}&scope=basic_info&state=${authUUID}&toPage=signup`;
}

void (async () => {
try {
await setAuthUUID(authUUID);
} catch (err) {
errorTips(err);
}

window.location.href = getAgoraURL(authUUID);
window.location.href = getAgoraURL(authUUID, FLAT_SERVER_LOGIN.AGORA_CALLBACK);
})();

// eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {};
};

export function getAgoraURL(authUUID: string, redirect_uri: string): string {
const redirectURL = encodeURIComponent(redirect_uri);
return `https://sso2.agora.io/api/v0/oauth/authorize?response_type=code&client_id=${AGORA_OAUTH.CLIENT_ID}&redirect_uri=${redirectURL}&scope=basic_info&state=${authUUID}&toPage=signup`;
}
12 changes: 6 additions & 6 deletions web/flat-web/src/pages/LoginPage/githubLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ export const githubLogin: LoginExecutor = onSuccess => {
let timer = NaN;
const authUUID = uuidv4();

function getGithubURL(authUUID: string): string {
const redirectURL = encodeURIComponent(FLAT_SERVER_LOGIN.GITHUB_CALLBACK);
return `https://github.com/login/oauth/authorize?client_id=${GITHUB.CLIENT_ID}&redirect_uri=${redirectURL}&state=${authUUID}`;
}

void (async () => {
try {
await setAuthUUID(authUUID);
} catch (err) {
errorTips(err);
}

void window.open(getGithubURL(authUUID));
void window.open(getGithubURL(authUUID, FLAT_SERVER_LOGIN.GITHUB_CALLBACK));

const githubLoginProcessRequest = async (): Promise<void> => {
try {
Expand All @@ -45,3 +40,8 @@ export const githubLogin: LoginExecutor = onSuccess => {
window.clearTimeout(timer);
};
};

export function getGithubURL(authUUID: string, redirect_uri: string): string {
const redirectURL = encodeURIComponent(redirect_uri);
return `https://github.com/login/oauth/authorize?client_id=${GITHUB.CLIENT_ID}&redirect_uri=${redirectURL}&state=${authUUID}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { v4 } from "uuid";
import classNames from "classnames";
import React, { useCallback, useEffect, useState } from "react";
import { message, Modal } from "antd";
import { useTranslation } from "react-i18next";
import { GithubFilled } from "@ant-design/icons";

import { GlobalStore } from "../../../../stores/GlobalStore";
import { useSafePromise } from "../../../../utils/hooks/lifecycle";
import {
bindingProcess,
LoginPlatform,
removeBinding,
setBindingAuthUUID,
} from "../../../../api-middleware/flatServer";
import { FLAT_SERVER_USER_BINDING } from "../../../../api-middleware/flatServer/constants";
import { getGithubURL } from "../../../LoginPage/githubLogin";
import { errorTips } from "../../../../components/Tips/ErrorTips";

export interface BindGitHubProps {
isBind: boolean;
onRefresh: () => void;
globalStore: GlobalStore;
}

export const BindGitHub: React.FC<BindGitHubProps> = ({ isBind, onRefresh, globalStore }) => {
const sp = useSafePromise();
const { t } = useTranslation();
const [authUUID, setAuthUUID] = useState("");

const cancel = useCallback((): void => {
setAuthUUID("");
onRefresh();
}, [onRefresh]);

useEffect(() => {
let timer = NaN;
async function waitUntilBindFinish(): Promise<void> {
const result = await sp(bindingProcess(authUUID));
if (result.processing) {
timer = window.setTimeout(waitUntilBindFinish, 2000);
} else {
if (!result.status) {
message.info(t("bind-wechat-failed"));
}
cancel();
}
}
if (authUUID) {
waitUntilBindFinish();
return () => {
Number.isNaN(timer) || window.clearTimeout(timer);
};
}
return;
}, [authUUID, cancel, onRefresh, sp, t]);

const bindGitHub = async (): Promise<void> => {
const authUUID = v4();
setAuthUUID(authUUID);
await sp(setBindingAuthUUID(authUUID));
void window.open(getGithubURL(authUUID, FLAT_SERVER_USER_BINDING.GITHUB_CALLBACK));
};

const unbind = (): void => {
Modal.confirm({
content: t("unbind-confirm"),
onOk: async () => {
try {
const { token } = await sp(removeBinding(LoginPlatform.Github));
globalStore.updateUserToken(token);
onRefresh();
message.info(t("unbind-success"));
} catch (err) {
errorTips(err);
}
},
});
};

return (
<span
className={classNames("binding-github", {
"is-bind": isBind,
})}
title={isBind ? t("is-bind") : t("not-bind")}
onClick={isBind ? unbind : bindGitHub}
>
<GithubFilled style={{ color: "#fff" }} />
</span>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface BindingWeChatProps {
globalStore: GlobalStore;
}

export const BindingWeChat: React.FC<BindingWeChatProps> = ({ isBind, onRefresh, globalStore }) => {
export const BindWeChat: React.FC<BindingWeChatProps> = ({ isBind, onRefresh, globalStore }) => {
const sp = useSafePromise();
const { t } = useTranslation();
const [authUUID, setAuthUUID] = useState("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,20 @@
width: 24px;
height: 24px;
border-radius: 50%;
margin-right: 8px;
cursor: pointer;

&.is-bind {
background-color: var(--green-6);
}
}

.binding-github:extend(.binding-wechat) {
&.is-bind {
background-color: var(--grey-11);
}
}

.binding-wechat-modal {
.ant-modal-body {
text-align: center;
Expand Down
Loading

0 comments on commit bdf8eed

Please sign in to comment.