Skip to content

Commit b21c044

Browse files
authored
Merge pull request #1253 from lowcoder-org/feat_auth_flow
Update auth flow
2 parents 5022ecf + 012532f commit b21c044

File tree

24 files changed

+666
-235
lines changed

24 files changed

+666
-235
lines changed

client/packages/lowcoder-design/src/components/tacoInput.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,14 @@ const FormInput = (props: {
331331
check: (value: string) => boolean;
332332
};
333333
formName?: string;
334+
onBlur?: () => void;
334335
onChange?: (value: string, valid: boolean) => void;
335336
className?: string;
336337
inputRef?: Ref<InputRef>;
337338
msg?: string;
339+
defaultValue?: string;
338340
}) => {
339-
const { mustFill, checkRule, label, placeholder, onChange, formName, className, inputRef } =
341+
const { mustFill, checkRule, label, placeholder, onBlur, onChange, formName, className, inputRef, defaultValue } =
340342
props;
341343
const [valueValid, setValueValid] = useState(true);
342344
return (
@@ -350,6 +352,7 @@ const FormInput = (props: {
350352
ref={inputRef}
351353
name={formName}
352354
placeholder={placeholder}
355+
defaultValue={defaultValue}
353356
onChange={(e) => {
354357
let valid = true;
355358
if (checkRule) {
@@ -358,6 +361,7 @@ const FormInput = (props: {
358361
}
359362
onChange && onChange(e.target.value, valid);
360363
}}
364+
onBlur={() => onBlur?.()}
361365
/>
362366
</FormInputFiled>
363367
);

client/packages/lowcoder/src/api/applicationApi.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class ApplicationApi extends Api {
9898
static publicToMarketplaceURL = (applicationId: string) => `/applications/${applicationId}/public-to-marketplace`;
9999
static getMarketplaceAppURL = (applicationId: string) => `/applications/${applicationId}/view_marketplace`;
100100
static setAppEditingStateURL = (applicationId: string) => `/applications/editState/${applicationId}`;
101+
static serverSettingsURL = () => `/serverSettings`;
101102

102103
static fetchHomeData(request: HomeDataPayload): AxiosPromise<HomeDataResponse> {
103104
return Api.get(ApplicationApi.fetchHomeDataURL, request);
@@ -240,6 +241,10 @@ class ApplicationApi extends Api {
240241
editingFinished,
241242
});
242243
}
244+
245+
static fetchServerSettings(): AxiosPromise<any> {
246+
return Api.get(ApplicationApi.serverSettingsURL());
247+
}
243248
}
244249

245250
export default ApplicationApi;

client/packages/lowcoder/src/api/idSourceApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ class IdSourceApi extends Api {
4444
return Api.post(IdSourceApi.saveConfigURL, request);
4545
}
4646

47-
static deleteConfig(id: string): AxiosPromise<ApiResponse> {
48-
return Api.delete(IdSourceApi.deleteConfigURL(id));
47+
static deleteConfig(id: string, deleteConfig?: boolean): AxiosPromise<ApiResponse> {
48+
return Api.delete(IdSourceApi.deleteConfigURL(id), {delete: deleteConfig});
4949
}
5050

5151
static syncManual(authType: string): AxiosPromise<ApiResponse> {

client/packages/lowcoder/src/api/orgApi.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export class OrgApi extends Api {
5252
static deleteOrgURL = (orgId: string) => `/organizations/${orgId}`;
5353
static updateOrgURL = (orgId: string) => `/organizations/${orgId}/update`;
5454
static fetchUsage = (orgId: string) => `/organizations/${orgId}/api-usage`;
55+
static fetchOrgsByEmailURL = (email: string) => `organizations/byuser/${email}`;
5556

5657
static createGroup(request: { name: string }): AxiosPromise<GenericApiResponse<OrgGroup>> {
5758
return Api.post(OrgApi.createGroupURL, request);
@@ -141,6 +142,9 @@ export class OrgApi extends Api {
141142
return Api.get(OrgApi.fetchUsage(orgId), { lastMonthOnly: true });
142143
}
143144

145+
static fetchOrgsByEmail(email: string): AxiosPromise<ApiResponse> {
146+
return Api.get(OrgApi.fetchOrgsByEmailURL(email));
147+
}
144148
}
145149

146150
export default OrgApi;

client/packages/lowcoder/src/app.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
ADMIN_APP_URL,
2929
ORG_AUTH_FORGOT_PASSWORD_URL,
3030
ORG_AUTH_RESET_PASSWORD_URL,
31+
ADMIN_AUTH_URL,
3132
} from "constants/routesURL";
3233
import React from "react";
3334
import { createRoot } from "react-dom/client";
@@ -55,7 +56,7 @@ import { getBrandingConfig } from "./redux/selectors/configSelectors";
5556
import { buildMaterialPreviewURL } from "./util/materialUtils";
5657
import GlobalInstances from 'components/GlobalInstances';
5758
// import posthog from 'posthog-js'
58-
import { fetchHomeData } from "./redux/reduxActions/applicationActions";
59+
import { fetchHomeData, fetchServerSettingsAction } from "./redux/reduxActions/applicationActions";
5960
import { getNpmPackageMeta } from "./comps/utils/remote";
6061
import { packageMetaReadyAction, setLowcoderCompsLoading } from "./redux/reduxActions/npmPluginActions";
6162

@@ -94,6 +95,7 @@ type AppIndexProps = {
9495
fetchHomeData: (currentUserAnonymous?: boolean | undefined) => void;
9596
fetchLowcoderCompVersions: () => void;
9697
getCurrentUser: () => void;
98+
fetchServerSettings: () => void;
9799
favicon: string;
98100
brandName: string;
99101
uiLanguage: string;
@@ -102,6 +104,7 @@ type AppIndexProps = {
102104
class AppIndex extends React.Component<AppIndexProps, any> {
103105
componentDidMount() {
104106
this.props.getCurrentUser();
107+
this.props.fetchServerSettings();
105108
// if (!this.props.currentUserAnonymous) {
106109
// this.props.fetchHomeData(this.props.currentUserAnonymous);
107110
// }
@@ -337,6 +340,7 @@ class AppIndex extends React.Component<AppIndexProps, any> {
337340
// component={ApplicationListPage}
338341
component={LazyApplicationHome}
339342
/>
343+
<LazyRoute exact path={ADMIN_AUTH_URL} component={LazyUserAuthComp} />
340344
<LazyRoute path={USER_AUTH_URL} component={LazyUserAuthComp} />
341345
<LazyRoute
342346
path={ORG_AUTH_LOGIN_URL}
@@ -437,6 +441,9 @@ const mapDispatchToProps = (dispatch: any) => ({
437441
dispatch(setLowcoderCompsLoading(false));
438442
}
439443
},
444+
fetchServerSettings: () => {
445+
dispatch(fetchServerSettingsAction());
446+
}
440447
});
441448

442449
const AppIndexWithProps = connect(mapStateToProps, mapDispatchToProps)(AppIndex);

client/packages/lowcoder/src/constants/reduxActionConstants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ export const ReduxActionTypes = {
145145
FETCH_ALL_MARKETPLACE_APPS: "FETCH_ALL_MARKETPLACE_APPS",
146146
FETCH_ALL_MARKETPLACE_APPS_SUCCESS: "FETCH_ALL_MARKETPLACE_APPS_SUCCESS",
147147
SET_APP_EDITING_STATE: "SET_APP_EDITING_STATE",
148+
FETCH_SERVER_SETTINGS: "FETCH_SERVER_SETTINGS",
149+
FETCH_SERVER_SETTINGS_SUCCESS: "FETCH_SERVER_SETTINGS_SUCCESS",
148150

149151
/* user profile */
150152
SET_USER_PROFILE_SETTING_MODAL_VISIBLE: "SET_USER_PROFILE_SETTING_MODAL_VISIBLE",

client/packages/lowcoder/src/constants/routesURL.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { UserGuideLocationState } from "pages/tutorials/tutorialsConstant";
44
import { DatasourceType } from "@lowcoder-ee/constants/queryConstants";
55

66
export const BASE_URL = "/";
7+
export const ADMIN_AUTH_URL = "/admin/login";
78
export const USER_AUTH_URL = "/user/auth";
89
export const USER_PROFILE_URL = "/user/profile";
910
export const NEWS_URL = "/news";

client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3008,7 +3008,11 @@ export const en = {
30083008
"resetSuccessDesc": "Password Reset Succeeded. The New Password is: {password}",
30093009
"resetLostPasswordSuccess": "Password Reset Succeeded. Please login again.",
30103010
"copyPassword": "Copy Password",
3011-
"poweredByLowcoder": "Powered by: Lowcoder.cloud"
3011+
"poweredByLowcoder": "Powered by: Lowcoder.cloud",
3012+
"continue": "Continue",
3013+
"enterPassword": "Enter your password",
3014+
"selectAuthProvider": "Select Authentication Provider",
3015+
"selectWorkspace": "Select your workspace",
30123016
},
30133017
"preLoad": {
30143018
"jsLibraryHelpText": "Add JavaScript Libraries to Your Current Application via URL Addresses. lodash, day.js, uuid, numbro are Built into the System for Immediate Use. JavaScript Libraries are Loaded Before the Application is Initialized, Which Can Have an Impact on Application Performance.",
@@ -3542,12 +3546,13 @@ export const en = {
35423546
"formSelectPlaceholder": "Please Select the {label}",
35433547
"saveSuccess": "Saved Successfully",
35443548
"dangerLabel": "Danger Zone",
3545-
"dangerTip": "Disabling This ID Provider May Result in Some Users Being Unable to Log In. Proceed With Caution.",
3549+
"dangerTip": "Disabling or Deleting This ID Provider May Result in Some Users Being Unable to Log In. Proceed With Caution.",
3550+
"lastEnabledConfig": "You can't disable/delete config as this is the only enabled configuration.",
35463551
"disable": "Disable",
35473552
"disableSuccess": "Disabled Successfully",
35483553
"encryptedServer": "-------- Encrypted on the Server Side --------",
35493554
"disableTip": "Tips",
3550-
"disableContent": "Disabling This ID Provider May Result in Some Users Being Unable to Log In. Are You Sure to Proceed?",
3555+
"disableContent": "{action} This ID Provider May Result in Some Users Being Unable to Log In. Are You Sure to Proceed?",
35513556
"manualTip": "",
35523557
"lockTip": "The Content is Locked. To Make Changes, Please Click the {icon} to Unlock.",
35533558
"lockModalContent": "Changing the 'ID Attribute' Field Can Have Significant Impacts on User Identification. Please Confirm That You Understand the Implications of This Change Before Proceeding.",

client/packages/lowcoder/src/pages/setting/idSource/detail/deleteConfig.tsx

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,73 @@ import { trans } from "i18n";
44
import { useState } from "react";
55
import { validateResponse } from "api/apiUtils";
66
import IdSourceApi from "api/idSourceApi";
7-
import { DangerIcon, CustomModal } from "lowcoder-design";
7+
import { CustomModal } from "lowcoder-design";
88
import history from "util/history";
99
import { OAUTH_PROVIDER_SETTING } from "constants/routesURL";
1010
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
11+
import Flex from "antd/es/flex";
12+
import Alert from "antd/es/alert";
1113

12-
export const DeleteConfig = (props: { id: string }) => {
14+
export const DeleteConfig = (props: {
15+
id: string,
16+
allowDelete?: boolean,
17+
allowDisable?: boolean,
18+
isLastEnabledConfig?: boolean,
19+
}) => {
20+
const [disableLoading, setDisableLoading] = useState(false);
1321
const [deleteLoading, setDeleteLoading] = useState(false);
14-
const handleDelete = () => {
22+
23+
const handleDelete = (deleteConfig?: boolean) => {
24+
const setLoading = deleteConfig ? setDeleteLoading : setDisableLoading;
25+
const action = deleteConfig ? trans("delete") : trans("idSource.disable");
1526
CustomModal.confirm({
1627
title: trans("idSource.disableTip"),
17-
content: trans("idSource.disableContent"),
28+
content: trans("idSource.disableContent", {action}),
1829
onConfirm: () => {
19-
setDeleteLoading(true);
20-
IdSourceApi.deleteConfig(props.id)
21-
.then((resp) => {
22-
if (validateResponse(resp)) {
23-
messageInstance.success(trans("idSource.disableSuccess"), 0.8, () =>
30+
setLoading(true);
31+
IdSourceApi.deleteConfig(props.id, deleteConfig)
32+
.then((resp) => {
33+
if (validateResponse(resp)) {
34+
const successMsg = deleteConfig ? trans("home.deleteSuccessMsg") : trans("idSource.disableSuccess");
35+
messageInstance.success(successMsg, 0.8, () =>
2436
history.push(OAUTH_PROVIDER_SETTING)
2537
);
2638
}
2739
})
2840
.catch((e) => messageInstance.error(e.message))
29-
.finally(() => setDeleteLoading(false));
41+
.finally(() => setLoading(false));
3042
},
3143
});
3244
};
3345
return (
3446
<DeleteWrapper>
35-
<div>{trans("idSource.dangerLabel")}</div>
36-
<div className="danger-tip">
37-
<DangerIcon />
38-
{trans("idSource.dangerTip")}
39-
</div>
40-
<Button loading={deleteLoading} onClick={() => handleDelete()}>
41-
{trans("idSource.disable")}
42-
</Button>
47+
<h4>{trans("idSource.dangerLabel")}</h4>
48+
<Alert
49+
className="danger-tip"
50+
description={trans("idSource.dangerTip")}
51+
type="warning"
52+
showIcon
53+
/>
54+
{props.isLastEnabledConfig && (
55+
<Alert
56+
className="danger-tip"
57+
description={trans("idSource.lastEnabledConfig")}
58+
type="warning"
59+
showIcon
60+
/>
61+
)}
62+
<Flex gap={8}>
63+
{props.allowDisable && (
64+
<Button danger disabled={props.isLastEnabledConfig} loading={disableLoading} onClick={() => handleDelete()}>
65+
{trans("idSource.disable")}
66+
</Button>
67+
)}
68+
{props.allowDelete && (
69+
<Button type="primary" danger disabled={props.isLastEnabledConfig} loading={deleteLoading} onClick={() => handleDelete(true)}>
70+
{trans("delete")}
71+
</Button>
72+
)}
73+
</Flex>
4374
</DeleteWrapper>
4475
);
4576
};

client/packages/lowcoder/src/pages/setting/idSource/detail/index.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,22 @@ import { sourceMappingKeys } from "../OAuthForms/GenericOAuthForm";
4444
import Flex from "antd/es/flex";
4545

4646
type IdSourceDetailProps = {
47-
location: Location & { state: ConfigItem };
47+
location: Location & { state: { config: ConfigItem, totalEnabledConfigs: number }};
4848
};
4949

5050
export const IdSourceDetail = (props: IdSourceDetailProps) => {
51-
const configDetail = props.location.state;
51+
const {
52+
config: configDetail,
53+
totalEnabledConfigs,
54+
} = props.location.state;
5255
const [form] = useForm();
5356
const [lock, setLock] = useState(() => {
54-
const config = props.location.state;
57+
const { config } = props.location.state;
5558
return !config.ifLocal;
5659
});
5760
const [saveLoading, setSaveLoading] = useState(false);
5861
const [saveDisable, setSaveDisable] = useState(() => {
59-
const config = props.location.state;
62+
const { config } = props.location.state;
6063
if (
6164
(config.authType === AuthType.Form && !config.enable) ||
6265
(!config.ifLocal && !config.enable)
@@ -321,12 +324,15 @@ export const IdSourceDetail = (props: IdSourceDetailProps) => {
321324
<Manual type={configDetail.authType} />
322325
</>
323326
)}
324-
{configDetail.enable && (
325-
<>
326-
<Divider />
327-
<DeleteConfig id={configDetail.id} />
328-
</>
329-
)}
327+
<>
328+
<Divider />
329+
<DeleteConfig
330+
id={configDetail.id}
331+
allowDelete={configDetail.authType !== AuthType.Form}
332+
allowDisable={configDetail.enable}
333+
isLastEnabledConfig={totalEnabledConfigs === 1 && configDetail.enable}
334+
/>
335+
</>
330336
</Content>
331337
</DetailContainer>
332338
);

client/packages/lowcoder/src/pages/setting/idSource/list.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import { FreeTypes } from "pages/setting/idSource/idSourceConstants";
3333
import { messageInstance, AddIcon } from "lowcoder-design";
3434
import { currentOrgAdmin } from "../../../util/permissionUtils";
3535
import CreateModal from "./createModal";
36-
import _ from "lodash";
3736
import { HelpText } from "components/HelpText";
3837
import { IconControlView } from "@lowcoder-ee/comps/controls/iconControl";
3938

@@ -42,6 +41,7 @@ export const IdSourceList = (props: any) => {
4241
const config = useSelector(selectSystemConfig);
4342
const { currentOrgId} = user;
4443
const [configs, setConfigs] = useState<ConfigItem[]>([]);
44+
const [enabledConfigs, setEnabledConfigs] = useState<ConfigItem[]>([]);
4545
const [fetching, setFetching] = useState(false);
4646
const [modalVisible, setModalVisible] = useState(false);
4747
const enableEnterpriseLogin = useSelector(selectSystemConfig)?.featureFlag?.enableEnterpriseLogin;
@@ -76,8 +76,8 @@ export const IdSourceList = (props: any) => {
7676
let res: ConfigItem[] = resp.data.data.filter((item: ConfigItem) =>
7777
IdSource.includes(item.authType)
7878
);
79-
// res = _.uniqBy(res, 'authType');
8079
setConfigs(res);
80+
setEnabledConfigs(res.filter(item => item.enable));
8181
}
8282
})
8383
.catch((e) => {
@@ -126,7 +126,7 @@ export const IdSourceList = (props: any) => {
126126
}
127127
history.push({
128128
pathname: OAUTH_PROVIDER_DETAIL,
129-
state: record,
129+
state: { config: record, totalEnabledConfigs: enabledConfigs.length },
130130
});
131131
},
132132
})}

client/packages/lowcoder/src/pages/setting/idSource/styledComponents.tsx

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -258,35 +258,16 @@ export const DeleteWrapper = styled.div`
258258
line-height: 19px;
259259
260260
.danger-tip {
261-
height: 32px;
262-
padding: 0 16px 0 8px;
263-
margin: 5px 0 8px 0;
264-
background: #fff3f1;
261+
max-width: 440px;
262+
padding: 8px 16px;
263+
margin: 5px 0 12px 0;
265264
border-radius: 4px;
266-
display: inline-flex;
267265
align-items: center;
268266
269267
svg {
270268
margin-right: 8px;
271269
}
272270
}
273-
274-
.ant-btn {
275-
min-width: 84px;
276-
display: block;
277-
padding: 4px 8px;
278-
background: #fef4f4;
279-
border: 1px solid #fccdcd;
280-
font-size: 13px;
281-
color: #f73131;
282-
283-
&:hover,
284-
&.ant-btn-loading {
285-
background: #feecec;
286-
}
287-
288-
${btnLoadingCss}
289-
}
290271
`;
291272

292273
export const StatusSpan = styled.span`

0 commit comments

Comments
 (0)