YANG QIA 06f11a2d08
refactor(auth): move auth client from core to the plugin & refactor auth client api (#3215)
* refactor(auth): auth client api

* fix: build

* fix: dependencies

* fix: fix T-2777

* fix: fix T-2776

* chore: update type

* fix: build

* fix: allowSignUp

* fix: file name

* fix: file name

* refactor: client api

* fix: build

* chore: update name

* fix: tsx must be loaded with --import instead of --loader

* fix: type

* fix: type

* fix: type

* fix: type

* fix: bug

* chore: improve wording

* fix: test

---------

Co-authored-by: chenos <chenlinxh@gmail.com>
2023-12-21 20:19:25 +08:00

105 lines
3.1 KiB
TypeScript

import { ISchema } from '@formily/react';
import { SchemaComponent, useAPIClient, useCurrentUserContext } from '@nocobase/client';
import React, { useCallback } from 'react';
import { useAuthTranslation } from '../locale';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useForm } from '@formily/react';
import { useSignUpForms } from '../pages';
import { Authenticator } from '../authenticator';
export function useRedirect(next = '/admin') {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
return useCallback(() => {
navigate(searchParams.get('redirect') || '/admin', { replace: true });
}, [navigate, searchParams]);
}
export const useSignIn = (authenticator: string) => {
const form = useForm();
const api = useAPIClient();
const redirect = useRedirect();
const { refreshAsync } = useCurrentUserContext();
return {
async run() {
await form.submit();
await api.auth.signIn(form.values, authenticator);
await refreshAsync();
redirect();
},
};
};
const passwordForm: ISchema = {
type: 'object',
name: 'passwordForm',
'x-component': 'FormV2',
properties: {
account: {
type: 'string',
'x-component': 'Input',
'x-validator': `{{(value) => {
if (!value) {
return t("Please enter your username or email");
}
if (value.includes('@')) {
if (!/^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$/.test(value)) {
return t("Please enter a valid email");
}
} else {
return /^[^@.<>"'/]{2,16}$/.test(value) || t("Please enter a valid username");
}
}}}`,
'x-decorator': 'FormItem',
'x-component-props': { placeholder: '{{t("Username/Email")}}', style: {} },
},
password: {
type: 'string',
'x-component': 'Password',
required: true,
'x-decorator': 'FormItem',
'x-component-props': { placeholder: '{{t("Password")}}', style: {} },
},
actions: {
type: 'void',
'x-component': 'div',
properties: {
submit: {
title: '{{t("Sign in")}}',
type: 'void',
'x-component': 'Action',
'x-component-props': {
htmlType: 'submit',
block: true,
type: 'primary',
useAction: `{{ useBasicSignIn }}`,
style: { width: '100%' },
},
},
},
},
signUp: {
type: 'void',
'x-component': 'Link',
'x-component-props': {
to: '{{ signUpLink }}',
},
'x-content': '{{t("Create an account")}}',
'x-visible': '{{ allowSignUp }}',
},
},
};
export const SignInForm = (props: { authenticator: Authenticator }) => {
const { t } = useAuthTranslation();
const authenticator = props.authenticator;
const { authType, name, options } = authenticator;
const signUpPages = useSignUpForms();
const allowSignUp = !!signUpPages[authType] && options?.allowSignUp;
const signUpLink = `/signup?name=${name}`;
const useBasicSignIn = () => {
return useSignIn(name);
};
return <SchemaComponent schema={passwordForm} scope={{ useBasicSignIn, allowSignUp, signUpLink, t }} />;
};