fix: sso optimization (#1159)
* fix: update submodules * fix: improve code
This commit is contained in:
parent
37b4151da1
commit
205fafcd4a
@ -1,9 +1,9 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { Button, Space } from 'antd';
|
||||
import { LoginOutlined } from '@ant-design/icons';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { css } from '@emotion/css';
|
||||
import { useAPIClient, useRedirect } from '@nocobase/client';
|
||||
import { useAPIClient, useRedirect, useRequest } from '@nocobase/client';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { Button, Space } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
export interface OIDCProvider {
|
||||
clientId: string;
|
||||
@ -12,26 +12,14 @@ export interface OIDCProvider {
|
||||
}
|
||||
|
||||
export const OIDCList = () => {
|
||||
const [list, setList] = useState<OIDCProvider[]>([]);
|
||||
const [windowHandler, setWindowHandler] = useState<Window | undefined>();
|
||||
const api = useAPIClient();
|
||||
const redirect = useRedirect();
|
||||
|
||||
const getOidcList = async () => {
|
||||
const { data: pluginsRes } = await api.request({
|
||||
url: 'app:getPlugins',
|
||||
const { data, loading } = useRequest({
|
||||
resource: 'oidc',
|
||||
action: 'getEnabledProviders',
|
||||
});
|
||||
if (!(pluginsRes.data as string[]).includes('oidc')) return;
|
||||
const { data: providersRes } = await api.request({
|
||||
url: 'oidcProviders:list',
|
||||
params: {
|
||||
filter: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
setList(providersRes.data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开登录弹出框
|
||||
@ -80,10 +68,6 @@ export const OIDCList = () => {
|
||||
};
|
||||
}, [windowHandler]);
|
||||
|
||||
useEffect(() => {
|
||||
getOidcList();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Space
|
||||
direction="vertical"
|
||||
@ -91,9 +75,9 @@ export const OIDCList = () => {
|
||||
display: flex;
|
||||
`}
|
||||
>
|
||||
{list.map((item) => (
|
||||
{data?.data?.map?.((item) => (
|
||||
<Button shape="round" block key={item.clientId} icon={<LoginOutlined />} onClick={() => handleOpen(item)}>
|
||||
OIDC: {item.title}
|
||||
{item.buttonTitle}
|
||||
</Button>
|
||||
))}
|
||||
</Space>
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { i18n } from '@nocobase/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import zhCN from './zh-CN';
|
||||
import enUS from './en-US';
|
||||
import jaJP from './ja-JP';
|
||||
import ruRU from './ru-RU';
|
||||
import trTR from './tr-TR';
|
||||
import zhCN from './zh-CN';
|
||||
|
||||
export const NAMESPACE = 'workflow';
|
||||
export const NAMESPACE = 'oidc';
|
||||
|
||||
i18n.addResources('zh-CN', NAMESPACE, zhCN);
|
||||
i18n.addResources('en-US', NAMESPACE, enUS);
|
||||
|
@ -4,6 +4,7 @@ export default {
|
||||
Actions: '操作',
|
||||
Delete: '删除',
|
||||
Edit: '编辑',
|
||||
'Button title': '登录按钮标题',
|
||||
'OIDC manager': 'OIDC 管理',
|
||||
'OIDC Providers': 'OIDC 身份提供者',
|
||||
'Provider name': '名称',
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import { useActionContext, useRequest } from '@nocobase/client';
|
||||
import { IDTOKEN_SIGN_ALG } from '../../server/shared/types';
|
||||
|
||||
@ -17,6 +16,17 @@ const collection = {
|
||||
required: true,
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'buttonTitle',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: '{{t("Button title")}}',
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'clientId',
|
||||
@ -169,6 +179,10 @@ export const formProperties = {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
buttonTitle: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
clientId: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
|
@ -0,0 +1,12 @@
|
||||
import { Context } from '@nocobase/actions';
|
||||
|
||||
export const getEnabledProviders = async (ctx: Context, next) => {
|
||||
const repository = ctx.db.getRepository('oidcProviders');
|
||||
ctx.body = await repository.find({
|
||||
filter: {
|
||||
enabled: true,
|
||||
},
|
||||
fields: ['buttonTitle', 'clientId'],
|
||||
});
|
||||
return next();
|
||||
};
|
@ -10,6 +10,10 @@ export default {
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
},
|
||||
{
|
||||
name: 'buttonTitle',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
comment: '客户端id',
|
||||
type: 'string',
|
||||
|
@ -1,10 +1,10 @@
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
import { InstallOptions, Plugin } from '@nocobase/server';
|
||||
import { resolve } from 'path';
|
||||
import { generators } from 'openid-client';
|
||||
import { oidc } from './authenticators/oidc';
|
||||
import { resolve } from 'path';
|
||||
import { getAuthUrl } from './actions/getAuthUrl';
|
||||
import { getEnabledProviders } from './actions/getEnabledProviders';
|
||||
import { redirect } from './actions/redirect';
|
||||
import { oidc } from './authenticators/oidc';
|
||||
|
||||
export class OidcPlugin extends Plugin {
|
||||
#OIDC_NONCE = null;
|
||||
@ -20,7 +20,7 @@ export class OidcPlugin extends Plugin {
|
||||
});
|
||||
|
||||
// 获取 User 插件
|
||||
const userPlugin = this.app.getPlugin('users') as UsersPlugin;
|
||||
const userPlugin = this.app.getPlugin<any>('users');
|
||||
|
||||
// 注册 OIDC 验证器
|
||||
userPlugin.authenticators.register('oidc', oidc);
|
||||
@ -31,6 +31,7 @@ export class OidcPlugin extends Plugin {
|
||||
actions: {
|
||||
getAuthUrl,
|
||||
redirect,
|
||||
getEnabledProviders,
|
||||
},
|
||||
});
|
||||
|
||||
@ -46,7 +47,7 @@ export class OidcPlugin extends Plugin {
|
||||
});
|
||||
|
||||
// 开放访问权限
|
||||
this.app.acl.allow('oidcProviders', '*');
|
||||
this.app.acl.allow('oidcProviders', '*', 'allowConfigure');
|
||||
this.app.acl.allow('oidc', '*');
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { Button, Space } from 'antd';
|
||||
import { LoginOutlined } from '@ant-design/icons';
|
||||
import { css } from '@emotion/css';
|
||||
import { useAPIClient, useRedirect } from '@nocobase/client';
|
||||
import { useAPIClient, useRedirect, useRequest } from '@nocobase/client';
|
||||
import { Button, Space } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
export interface SAMLProvider {
|
||||
title: string;
|
||||
@ -11,26 +11,14 @@ export interface SAMLProvider {
|
||||
}
|
||||
|
||||
export const SAMLList = () => {
|
||||
const [list, setList] = useState<SAMLProvider[]>([]);
|
||||
const [windowHandler, setWindowHandler] = useState<Window | undefined>();
|
||||
const api = useAPIClient();
|
||||
const redirect = useRedirect();
|
||||
|
||||
const getSamlList = async () => {
|
||||
const { data: pluginsRes } = await api.request({
|
||||
url: 'app:getPlugins',
|
||||
const { data, loading } = useRequest({
|
||||
resource: 'saml',
|
||||
action: 'getEnabledProviders',
|
||||
});
|
||||
if (!(pluginsRes.data as string[]).includes('saml')) return;
|
||||
const { data: providersRes } = await api.request({
|
||||
url: 'samlProviders:list',
|
||||
params: {
|
||||
filter: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
setList(providersRes.data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开登录弹出框
|
||||
@ -79,10 +67,6 @@ export const SAMLList = () => {
|
||||
};
|
||||
}, [windowHandler]);
|
||||
|
||||
useEffect(() => {
|
||||
getSamlList();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Space
|
||||
direction="vertical"
|
||||
@ -90,9 +74,9 @@ export const SAMLList = () => {
|
||||
display: flex;
|
||||
`}
|
||||
>
|
||||
{list.map((item) => (
|
||||
{data?.data?.map?.((item) => (
|
||||
<Button shape="round" block key={item.clientId} icon={<LoginOutlined />} onClick={() => handleOpen(item)}>
|
||||
SAML: {item.title}
|
||||
{item.buttonTitle}
|
||||
</Button>
|
||||
))}
|
||||
</Space>
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { i18n } from '@nocobase/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import zhCN from './zh-CN';
|
||||
import enUS from './en-US';
|
||||
import jaJP from './ja-JP';
|
||||
import ruRU from './ru-RU';
|
||||
import trTR from './tr-TR';
|
||||
import zhCN from './zh-CN';
|
||||
|
||||
export const NAMESPACE = 'workflow';
|
||||
export const NAMESPACE = 'saml';
|
||||
|
||||
i18n.addResources('zh-CN', NAMESPACE, zhCN);
|
||||
i18n.addResources('en-US', NAMESPACE, enUS);
|
||||
|
@ -6,6 +6,7 @@ export default {
|
||||
Actions: '操作',
|
||||
Title: '身份提供者名称',
|
||||
Enable: '启用',
|
||||
'Button title': '登录按钮标题',
|
||||
'SAML manager': 'SAML 管理',
|
||||
'SAML Providers': 'SAML 身份提供者',
|
||||
'Redirect url': '重定向地址',
|
||||
|
@ -15,6 +15,17 @@ const collection = {
|
||||
required: true,
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'buttonTitle',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: '{{t("Button title")}}',
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'clientId',
|
||||
@ -98,6 +109,10 @@ export const formProperties = {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
buttonTitle: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
clientId: {
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
|
@ -0,0 +1,12 @@
|
||||
import { Context } from '@nocobase/actions';
|
||||
|
||||
export const getEnabledProviders = async (ctx: Context, next) => {
|
||||
const repository = ctx.db.getRepository('samlProviders');
|
||||
ctx.body = await repository.find({
|
||||
filter: {
|
||||
enabled: true,
|
||||
},
|
||||
fields: ['buttonTitle', 'clientId'],
|
||||
});
|
||||
return next();
|
||||
};
|
@ -9,6 +9,10 @@ export default {
|
||||
type: 'string',
|
||||
name: 'title',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'buttonTitle',
|
||||
},
|
||||
{
|
||||
comment: '客户端id',
|
||||
type: 'string',
|
||||
|
@ -1,10 +1,10 @@
|
||||
import UsersPlugin from 'packages/plugins/users/src/server';
|
||||
import { InstallOptions, Plugin } from '@nocobase/server';
|
||||
import { resolve } from 'path';
|
||||
import { saml } from './authenticators/saml';
|
||||
import { redirect } from './actions/redirect';
|
||||
import { metadata } from './actions/metadata';
|
||||
import { getAuthUrl } from './actions/getAuthUrl';
|
||||
import { getEnabledProviders } from './actions/getEnabledProviders';
|
||||
import { metadata } from './actions/metadata';
|
||||
import { redirect } from './actions/redirect';
|
||||
import { saml } from './authenticators/saml';
|
||||
|
||||
export class SAMLPlugin extends Plugin {
|
||||
afterAdd() {}
|
||||
@ -18,7 +18,7 @@ export class SAMLPlugin extends Plugin {
|
||||
});
|
||||
|
||||
// 获取 User 插件
|
||||
const userPlugin = this.app.getPlugin('users') as UsersPlugin;
|
||||
const userPlugin = this.app.getPlugin<any>('users');
|
||||
|
||||
// 注册 SAML 验证器
|
||||
userPlugin.authenticators.register('saml', saml);
|
||||
@ -30,11 +30,12 @@ export class SAMLPlugin extends Plugin {
|
||||
redirect,
|
||||
metadata,
|
||||
getAuthUrl,
|
||||
getEnabledProviders,
|
||||
},
|
||||
});
|
||||
|
||||
// 开放访问权限
|
||||
this.app.acl.allow('samlProviders', '*');
|
||||
this.app.acl.allow('samlProviders', '*', 'allowConfigure');
|
||||
this.app.acl.allow('saml', '*');
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5a5fba41ae1cecaf3b073fcb610e9dc68dad0b85
|
||||
Subproject commit cf44c47ff9b5ef41e8becde3f1c8b5b1c2af6cda
|
Loading…
Reference in New Issue
Block a user