mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2026-03-06 14:00:52 -08:00
feat: try load token upon form open
This commit is contained in:
parent
60bfe7631b
commit
df7b661ef3
5 changed files with 105 additions and 72 deletions
|
|
@ -10,6 +10,7 @@ import { useUserInfoObservable } from '@services/auth/hooks';
|
|||
import { usePromiseValueAndSetter } from '@/helpers/useServiceValue';
|
||||
import { APP_ID, APP_DOMAIN } from '@/constants/auth';
|
||||
import { ServiceEmailTypes, ServiceTokenTypes, ServiceUserNameTypes } from '@services/auth/interface';
|
||||
import { useAuthing } from './gitTokenHooks';
|
||||
|
||||
const AuthingLoginButton = styled(Button)`
|
||||
white-space: nowrap;
|
||||
|
|
@ -28,80 +29,12 @@ export function GitTokenForm(props: {
|
|||
const { children, storageService } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
/**
|
||||
* Update tiddlywiki's editor user name when first time creating new workspace
|
||||
*/
|
||||
const [userName, userNameSetter] = usePromiseValueAndSetter(
|
||||
async () => await window.service.auth.get('userName'),
|
||||
async (newUserName) => await window.service.auth.set('userName', newUserName),
|
||||
);
|
||||
|
||||
const authing = useMemo(
|
||||
() =>
|
||||
new AuthingSSO({
|
||||
appId: APP_ID,
|
||||
appDomain: APP_DOMAIN,
|
||||
redirectUrl: 'http://localhost:3000',
|
||||
}),
|
||||
[],
|
||||
);
|
||||
const authing = useAuthing();
|
||||
|
||||
const onFailure = useCallback((error: Error) => {
|
||||
console.error(error);
|
||||
}, []);
|
||||
|
||||
const onLoginSuccessResponse = useCallback(
|
||||
async (response: ITrackSessionResult) => {
|
||||
// DEBUG: console
|
||||
console.log(`response`, response);
|
||||
if ('userInfo' in response && response.userInfo?.thirdPartyIdentity?.accessToken !== undefined) {
|
||||
const accessTokenToSet = response?.userInfo?.thirdPartyIdentity?.accessToken;
|
||||
const authDataString = response?.userInfo?.oauth;
|
||||
// all data we need
|
||||
if (accessTokenToSet !== undefined && authDataString !== undefined) {
|
||||
const authData = JSON.parse(authDataString);
|
||||
// DEBUG: console
|
||||
console.log(`authData`, authData);
|
||||
const nextUserInfo: IAuthingUserInfo = {
|
||||
...response.userInfo,
|
||||
...authData,
|
||||
...response.userInfo?.thirdPartyIdentity,
|
||||
};
|
||||
void window.service.auth.set(`${storageService}-token` as ServiceTokenTypes, accessTokenToSet);
|
||||
void window.service.auth.set(`${storageService}-userName` as ServiceUserNameTypes, nextUserInfo.username);
|
||||
void window.service.auth.set(`${storageService}-email` as ServiceEmailTypes, nextUserInfo.email);
|
||||
if (userName === undefined || (userName === '' && nextUserInfo.username !== userName)) {
|
||||
userNameSetter(nextUserInfo.username);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[storageService, userName, userNameSetter],
|
||||
);
|
||||
|
||||
const onClickLogout = useCallback(async () => {
|
||||
const { code, message } = await authing.logout();
|
||||
await window.service.window.clearStorageData();
|
||||
if (code === 200) {
|
||||
// TODO: clear the input
|
||||
} else {
|
||||
onFailure(new Error(message));
|
||||
}
|
||||
}, [authing, onFailure]);
|
||||
|
||||
// after authing redirect to 3rd party page and success, it will redirect back, we then check if login is success on component mount
|
||||
useEffect(() => {
|
||||
void (async () => {
|
||||
const response = await authing.trackSession();
|
||||
// we logout so login into github won't block use from login into gitlab
|
||||
await onClickLogout();
|
||||
const isLogin = response?.session !== undefined && response?.session !== null;
|
||||
if (isLogin) {
|
||||
await onLoginSuccessResponse(response);
|
||||
}
|
||||
})();
|
||||
}, [authing, onLoginSuccessResponse, onClickLogout]);
|
||||
|
||||
const onClickLogin = useCallback(async () => {
|
||||
// clear token first, otherwise github login window won't give us a chance to see the form
|
||||
// void this.auth.logout();
|
||||
|
|
@ -114,8 +47,6 @@ export function GitTokenForm(props: {
|
|||
}, [authing, onFailure]);
|
||||
|
||||
const userInfo = useUserInfoObservable();
|
||||
// DEBUG: console
|
||||
console.log(`userInfo`, JSON.stringify(userInfo));
|
||||
if (userInfo === undefined) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
|
|
|||
92
src/components/TokenForm/gitTokenHooks.ts
Normal file
92
src/components/TokenForm/gitTokenHooks.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import AuthingSSO, { ITrackSessionResult } from '@authing/sso';
|
||||
import { ServiceTokenTypes, ServiceUserNameTypes, ServiceEmailTypes } from '@services/auth/interface';
|
||||
import { SupportedStorageServices, IAuthingUserInfo } from '@services/types';
|
||||
import { APP_ID, APP_DOMAIN } from '@/constants/auth';
|
||||
import { usePromiseValueAndSetter } from '@/helpers/useServiceValue';
|
||||
|
||||
export function useTokenFromAuthingRedirect(authing: AuthingSSO, callback?: () => void): void {
|
||||
/**
|
||||
* Update tiddlywiki's editor user name when first time creating new workspace
|
||||
*/
|
||||
const [userName, userNameSetter] = usePromiseValueAndSetter(
|
||||
async () => await window.service.auth.get('userName'),
|
||||
async (newUserName) => await window.service.auth.set('userName', newUserName),
|
||||
);
|
||||
|
||||
const onLoginSuccessResponse = useCallback(
|
||||
async (response: ITrackSessionResult) => {
|
||||
// DEBUG: console
|
||||
console.log(`response`, response);
|
||||
if (!('userInfo' in response)) return;
|
||||
const accessTokenToSet = response?.userInfo?.thirdPartyIdentity?.accessToken;
|
||||
const provider = response?.userInfo?.thirdPartyIdentity?.provider as SupportedStorageServices;
|
||||
if (accessTokenToSet !== undefined && provider !== undefined) {
|
||||
if (!Object.values(SupportedStorageServices).includes(provider)) {
|
||||
throw new Error(`${provider} not in SupportedStorageServices`);
|
||||
}
|
||||
// DEBUG: console
|
||||
console.log(`provider`, provider);
|
||||
const authDataString = response?.userInfo?.oauth;
|
||||
// all data we need
|
||||
if (accessTokenToSet !== undefined && authDataString !== undefined) {
|
||||
const authData = JSON.parse(authDataString);
|
||||
// DEBUG: console
|
||||
console.log(`authData`, authData);
|
||||
const nextUserInfo: IAuthingUserInfo = {
|
||||
...response.userInfo,
|
||||
...authData,
|
||||
...response.userInfo?.thirdPartyIdentity,
|
||||
};
|
||||
await Promise.all([
|
||||
window.service.auth.set(`${provider}-token` as ServiceTokenTypes, accessTokenToSet),
|
||||
window.service.auth.set(`${provider}-userName` as ServiceUserNameTypes, nextUserInfo.username),
|
||||
window.service.auth.set(`${provider}-email` as ServiceEmailTypes, nextUserInfo.email),
|
||||
]);
|
||||
callback();
|
||||
if (userName === undefined || (userName === '' && nextUserInfo.username !== userName)) {
|
||||
userNameSetter(nextUserInfo.username);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[userName, userNameSetter],
|
||||
);
|
||||
|
||||
const onClickLogout = useCallback(async () => {
|
||||
const { code, message } = await authing.logout();
|
||||
await window.service.window.clearStorageData();
|
||||
if (code === 200) {
|
||||
// TODO: clear the input
|
||||
} else {
|
||||
throw new Error(message);
|
||||
}
|
||||
}, [authing]);
|
||||
|
||||
// after authing redirect to 3rd party page and success, it will redirect back, we then check if login is success on component mount
|
||||
useEffect(() => {
|
||||
void (async () => {
|
||||
const response = await authing.trackSession();
|
||||
// we logout so login into github won't block use from login into gitlab
|
||||
await onClickLogout();
|
||||
const isLogin = response?.session !== undefined && response?.session !== null;
|
||||
if (isLogin) {
|
||||
await onLoginSuccessResponse(response);
|
||||
}
|
||||
})();
|
||||
}, [authing, onLoginSuccessResponse, onClickLogout]);
|
||||
}
|
||||
|
||||
export function useAuthing(): AuthingSSO {
|
||||
const authing = useMemo(
|
||||
() =>
|
||||
new AuthingSSO({
|
||||
appId: APP_ID,
|
||||
appDomain: APP_DOMAIN,
|
||||
redirectUrl: 'http://localhost:3000',
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
return authing;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AppBar, Paper, Tab } from '@material-ui/core';
|
||||
|
|
@ -16,6 +16,7 @@ import { CloneWikiForm } from './CloneWikiForm';
|
|||
import { CloneWikiDoneButton } from './CloneWikiDoneButton';
|
||||
|
||||
import { useIsCreateMainWorkspace, useIsCreateSyncedWorkspace, useWikiWorkspaceForm } from './useForm';
|
||||
import { useAuthing, useTokenFromAuthingRedirect } from '@/components/TokenForm/gitTokenHooks';
|
||||
|
||||
enum CreateWorkspaceTabs {
|
||||
CloneOnlineWiki = 'CloneOnlineWiki',
|
||||
|
|
@ -50,6 +51,12 @@ export default function AddWorkspace(): JSX.Element {
|
|||
const [isCreateSyncedWorkspace, isCreateSyncedWorkspaceSetter] = useIsCreateSyncedWorkspace();
|
||||
const [isCreateMainWorkspace, isCreateMainWorkspaceSetter] = useIsCreateMainWorkspace();
|
||||
|
||||
const authing = useAuthing();
|
||||
useTokenFromAuthingRedirect(
|
||||
authing,
|
||||
useCallback(() => isCreateSyncedWorkspaceSetter(true), []),
|
||||
);
|
||||
|
||||
const form = useWikiWorkspaceForm();
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ interface IAuthingPostMessageEvent {
|
|||
window.addEventListener(
|
||||
'message',
|
||||
(event: MessageEvent<IAuthingPostMessageEvent>) => {
|
||||
// DEBUG: console
|
||||
console.log(`event`, event);
|
||||
if (typeof event?.data?.code === 'number' && typeof event?.data?.data?.token === 'string' && event?.data.from !== 'preload') {
|
||||
// This message will be catch by this handler again, so we add a 'from' to indicate that it is re-send by ourself
|
||||
// we re-send this, so authing in this window can catch it
|
||||
|
|
|
|||
1
src/type.d.ts
vendored
1
src/type.d.ts
vendored
|
|
@ -41,6 +41,7 @@ declare module '@authing/sso' {
|
|||
oauth?: string;
|
||||
thirdPartyIdentity?: {
|
||||
accessToken?: string;
|
||||
provider?: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue