refactor(server): auth (#5895)

Remove `next-auth` and implement our own Authorization/Authentication system from scratch.

## Server

- [x] tokens
  - [x] function
  - [x] encryption

- [x] AuthController
  - [x] /api/auth/sign-in
  - [x] /api/auth/sign-out
  - [x] /api/auth/session
  - [x] /api/auth/session (WE SUPPORT MULTI-ACCOUNT!)

- [x] OAuthPlugin
  - [x] OAuthController
  - [x] /oauth/login
  - [x] /oauth/callback
  - [x] Providers
    - [x] Google
    - [x] GitHub

## Client

- [x] useSession
- [x] cloudSignIn
- [x] cloudSignOut

## NOTE:

Tests will be adding in the future
This commit is contained in:
liuyi
2024-03-12 10:00:09 +00:00
parent af49e8cc41
commit fb3a0e7b8f
148 changed files with 3407 additions and 2851 deletions
@@ -216,9 +216,7 @@ export const SignOutConfirmModal = () => {
const onConfirm = useAsyncCallback(async () => {
setOpen(false);
await signOutCloud({
redirect: false,
});
await signOutCloud();
// if current workspace is affine cloud, switch to local workspace
if (currentWorkspace?.flavour === WorkspaceFlavour.AFFINE_CLOUD) {
@@ -1,11 +1,10 @@
import { pushNotificationAtom } from '@affine/component/notification-center';
import { useSession } from '@affine/core/hooks/affine/use-current-user';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { affine } from '@affine/electron-api';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { CLOUD_WORKSPACE_CHANGED_BROADCAST_CHANNEL_KEY } from '@affine/workspace-impl';
import { useAtom, useSetAtom } from 'jotai';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { SessionProvider, useSession } from 'next-auth/react';
import { useSetAtom } from 'jotai';
import {
type PropsWithChildren,
startTransition,
@@ -13,13 +12,11 @@ import {
useRef,
} from 'react';
import { sessionAtom } from '../atoms/cloud-user';
import { useOnceSignedInEvents } from '../atoms/event';
const SessionDefence = (props: PropsWithChildren) => {
export const CloudSessionProvider = (props: PropsWithChildren) => {
const session = useSession();
const prevSession = useRef<ReturnType<typeof useSession>>();
const [sessionInAtom, setSession] = useAtom(sessionAtom);
const pushNotification = useSetAtom(pushNotificationAtom);
const onceSignedInEvents = useOnceSignedInEvents();
const t = useAFFiNEI18N();
@@ -32,10 +29,6 @@ const SessionDefence = (props: PropsWithChildren) => {
}, [onceSignedInEvents]);
useEffect(() => {
if (sessionInAtom !== session && session.status === 'authenticated') {
setSession(session);
}
if (prevSession.current !== session && session.status !== 'loading') {
// unauthenticated -> authenticated
if (
@@ -55,22 +48,7 @@ const SessionDefence = (props: PropsWithChildren) => {
}
prevSession.current = session;
}
}, [
session,
sessionInAtom,
prevSession,
setSession,
pushNotification,
refreshAfterSignedInEvents,
t,
]);
}, [session, prevSession, pushNotification, refreshAfterSignedInEvents, t]);
return props.children;
};
export const CloudSessionProvider = ({ children }: PropsWithChildren) => {
return (
<SessionProvider refetchOnWindowFocus>
<SessionDefence>{children}</SessionDefence>
</SessionProvider>
);
};