Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Login flow for SingleWorkspace/Enterprise mode#1643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
FalkWolsky merged 4 commits intodevfromoauth_updates
Apr 19, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletionclient/packages/lowcoder/src/api/apiUtils.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -122,7 +122,14 @@ export const apiFailureResponseInterceptor = (error: any) => {
if (!notAuthRequiredPath(error.config?.url)) {
if (error.response.status === API_STATUS_CODES.REQUEST_NOT_AUTHORISED) {
// get x-org-id from failed request
const organizationId = error.response.headers['x-org-id'] || undefined;
let organizationId;
if (error.response.headers['x-org-id']) {
organizationId = error.response.headers['x-org-id'];
}
if (localStorage.getItem('lowcoder_login_orgId')) {
organizationId = localStorage.getItem('lowcoder_login_orgId');
localStorage.removeItem('lowcoder_login_orgId');
}
// Redirect to login and set a redirect url.
StoreRegistry.getStore().dispatch(
logoutAction({
Expand Down
1 change: 1 addition & 0 deletionsclient/packages/lowcoder/src/i18n/locales/en.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3205,6 +3205,7 @@ export const en = {
"enterPassword": "Enter your password",
"selectAuthProvider": "Select Authentication Provider",
"selectWorkspace": "Select your workspace",
"userNotFound": "User not found. Please make sure you entered the correct email."
},
"preLoad": {
"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.",
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -150,7 +150,13 @@ export default function ProfileDropdown(props: DropDownProps) {
dispatch(profileSettingModalVisible(true));
} else if (e.key === "logout") {
// logout
dispatch(logoutAction({}));
const organizationId = localStorage.getItem('lowcoder_login_orgId');
if (organizationId) {
localStorage.removeItem('lowcoder_login_orgId');
}
dispatch(logoutAction({
organizationId: organizationId || undefined,
}));
} else if (e.keyPath.includes("switchOrg")) {
if (e.key === "newOrganization") {
// create new organization
Expand Down
96 changes: 75 additions & 21 deletionsclient/packages/lowcoder/src/pages/userAuth/formLoginSteps.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,7 @@ import {
ConfirmButton,
StyledRouteLink,
} from "pages/userAuth/authComponents";
import React, { useContext, useEffect, useState } from "react";
import React, { useContext, useEffect,useMemo,useState } from "react";
import styled from "styled-components";
import UserApi from "api/userApi";
import { useRedirectUrl } from "util/hooks";
Expand All@@ -19,7 +19,7 @@ import { Divider } from "antd";
import Flex from "antd/es/flex";
import { validateResponse } from "@lowcoder-ee/api/apiUtils";
import OrgApi from "@lowcoder-ee/api/orgApi";
import { AccountLoginWrapper } from "./formLoginAdmin";
importFormLogin,{ AccountLoginWrapper } from "./formLoginAdmin";
import { default as Button } from "antd/es/button";
import LeftOutlined from "@ant-design/icons/LeftOutlined";
import { fetchConfigAction } from "@lowcoder-ee/redux/reduxActions/configActions";
Expand All@@ -28,6 +28,9 @@ import history from "util/history";
import { getServerSettings } from "@lowcoder-ee/redux/selectors/applicationSelector";
import {fetchOrgPaginationByEmail} from "@lowcoder-ee/util/pagination/axios";
import PaginationComp from "@lowcoder-ee/util/pagination/Pagination";
import { getSystemConfigFetching } from "@lowcoder-ee/redux/selectors/configSelectors";
import Spin from "antd/es/spin";
import LoadingOutlined from "@ant-design/icons/LoadingOutlined";

const StyledCard = styled.div<{$selected: boolean}>`
display: flex;
Expand DownExpand Up@@ -107,18 +110,28 @@ export default function FormLoginSteps(props: FormLoginProps) {
const { systemConfig, inviteInfo, fetchUserAfterAuthSuccess } = useContext(AuthContext);
const invitationId = inviteInfo?.invitationId;
const authId = systemConfig?.form.id;
const isFormLoginEnabled = systemConfig?.form.enableLogin;
const isFormLoginEnabled = systemConfig?.form.enableLogin; // check from configs
const [orgLoading, setOrgLoading] = useState(false);
const [orgList, setOrgList] = useState<OrgItem[]>([]);
const [currentStep, setCurrentStep] = useState<CurrentStepEnum>(CurrentStepEnum.EMAIL);
const [organizationId, setOrganizationId] = useState<string|undefined>(props.organizationId);
const [skipWorkspaceStep, setSkipWorkspaceStep] = useState<boolean>(false);
const [signupEnabled, setSignupEnabled] = useState<boolean>(true);
const [signinEnabled, setSigninEnabled] = useState<boolean>(true); // check from server settings
const serverSettings = useSelector(getServerSettings);
const isFetchingConfig = useSelector(getSystemConfigFetching);
const [elements, setElements] = useState<ElementsState>({ elements: [], total: 0 });
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);

const isEmailLoginEnabled = useMemo(() => {
return isFormLoginEnabled && signinEnabled;
}, [isFormLoginEnabled, signinEnabled]);

const isEnterpriseMode = useMemo(() => {
return serverSettings?.LOWCODER_WORKSPACE_MODE === "ENTERPRISE" || serverSettings?.LOWCODER_WORKSPACE_MODE === "SINGLEWORKSPACE";
}, [serverSettings]);

useEffect(() => {
if (account)
fetchOrgPaginationByEmail({
Expand All@@ -133,13 +146,22 @@ export default function FormLoginSteps(props: FormLoginProps) {
}, [pageSize, currentPage])

useEffect(() => {
const { LOWCODER_EMAIL_SIGNUP_ENABLED } = serverSettings;
if (!LOWCODER_EMAIL_SIGNUP_ENABLED) {
return setSignupEnabled(true);
}
const {
LOWCODER_EMAIL_SIGNUP_ENABLED,
LOWCODER_EMAIL_AUTH_ENABLED,
} = serverSettings;

setSignupEnabled(LOWCODER_EMAIL_SIGNUP_ENABLED === 'true');
setSigninEnabled(LOWCODER_EMAIL_AUTH_ENABLED === 'true');
}, [serverSettings]);

const afterLoginSuccess = () => {
if (props.organizationId) {
localStorage.setItem("lowcoder_login_orgId", props.organizationId);
}
fetchUserAfterAuthSuccess?.();
}

const { onSubmit, loading } = useAuthSubmit(
() =>
UserApi.formLogin({
Expand All@@ -153,7 +175,7 @@ export default function FormLoginSteps(props: FormLoginProps) {
}),
false,
redirectUrl,
fetchUserAfterAuthSuccess,
afterLoginSuccess,
);

const fetchOrgsByEmail = () => {
Expand All@@ -167,8 +189,9 @@ export default function FormLoginSteps(props: FormLoginProps) {
}

setOrgLoading(true);
// for enterprise mode, we will not ask for email in first step
fetchOrgPaginationByEmail({
email: account,
email:isEnterpriseMode ? ' ' :account,
pageNum: currentPage,
pageSize: pageSize
})
Expand All@@ -177,15 +200,13 @@ export default function FormLoginSteps(props: FormLoginProps) {
setElements({elements: resp.data || [], total: resp.total || 1})
setOrgList(resp.data);
if (!resp.data.length) {
history.push(
AUTH_REGISTER_URL,
{...location.state || {}, email: account},
)
return;
throw new Error(trans("userAuth.userNotFound"));
}
if (resp.data.length === 1) {
setOrganizationId(resp.data[0].orgId);
dispatch(fetchConfigAction(resp.data[0].orgId));
// in Enterprise mode, we will get org data in different format
const selectedOrgId = isEnterpriseMode ? resp.data[0].id : resp.data[0].orgId;
setOrganizationId(selectedOrgId);
dispatch(fetchConfigAction(selectedOrgId));
setCurrentStep(CurrentStepEnum.AUTH_PROVIDERS);
return;
}
Expand All@@ -202,6 +223,39 @@ export default function FormLoginSteps(props: FormLoginProps) {
});
}

useEffect(() => {
if (isEnterpriseMode) {
// dispatch(fetchConfigAction());
fetchOrgsByEmail();
}
}, [isEnterpriseMode]);

if (isEnterpriseMode) {
return (
<Spin indicator={<LoadingOutlined style={{ fontSize: 30 }} />} spinning={isFetchingConfig}>
{ isEmailLoginEnabled && <FormLogin /> }
<ThirdPartyAuth
invitationId={invitationId}
invitedOrganizationId={organizationId}
authGoal="login"
/>
{signupEnabled && (
<>
<Divider/>
<AuthBottomView>
<StyledRouteLink to={{
pathname: AUTH_REGISTER_URL,
state: {...location.state || {}, email: account}
}}>
{trans("userAuth.register")}
</StyledRouteLink>
</AuthBottomView>
</>
)}
</Spin>
);
}

if(currentStep === CurrentStepEnum.EMAIL) {
return (
<>
Expand All@@ -227,8 +281,8 @@ export default function FormLoginSteps(props: FormLoginProps) {
<Divider/>
<AuthBottomView>
<StyledRouteLink to={{
pathname: AUTH_REGISTER_URL,
state: location.state
pathname:props.organizationId ? `/org/${props.organizationId}/auth/register` :AUTH_REGISTER_URL,
state:{...location.state || {}, email: account}
}}>
{trans("userAuth.register")}
</StyledRouteLink>
Expand DownExpand Up@@ -280,10 +334,10 @@ export default function FormLoginSteps(props: FormLoginProps) {
}} />
<StepHeader
title={
isFormLoginEnabled ? trans("userAuth.enterPassword") : trans("userAuth.selectAuthProvider")
isEmailLoginEnabled ? trans("userAuth.enterPassword") : trans("userAuth.selectAuthProvider")
}
/>
{isFormLoginEnabled && (
{isEmailLoginEnabled && (
<>
<PasswordInput
className="form-input password-input"
Expand DownExpand Up@@ -315,7 +369,7 @@ export default function FormLoginSteps(props: FormLoginProps) {
/>
)}
</AccountLoginWrapper>
{isFormLoginEnabled && signupEnabled && (
{isEmailLoginEnabled && signupEnabled && (
<>
<Divider/>
<AuthBottomView>
Expand Down
17 changes: 14 additions & 3 deletionsclient/packages/lowcoder/src/pages/userAuth/register.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,12 +63,16 @@ function UserRegister() {
return inviteInfo?.invitedOrganizationId;
}
return orgId;
}, [ inviteInfo, orgId ])
}, [ inviteInfo, orgId ]);

const authId = systemConfig?.form.id;

const serverSettings = useSelector(getServerSettings);

const isEnterpriseMode = useMemo(() => {
return serverSettings?.LOWCODER_WORKSPACE_MODE === "ENTERPRISE" || serverSettings?.LOWCODER_WORKSPACE_MODE === "SINGLEWORKSPACE";
}, [serverSettings]);

useEffect(() => {
const { LOWCODER_EMAIL_SIGNUP_ENABLED } = serverSettings;
if(
Expand All@@ -82,6 +86,13 @@ function UserRegister() {
};
}, [serverSettings]);

const afterLoginSuccess = () => {
if (organizationId) {
localStorage.setItem("lowcoder_login_orgId", organizationId);
}
fetchUserAfterAuthSuccess?.();
}

const { loading, onSubmit } = useAuthSubmit(
() =>
UserApi.formLogin({
Expand All@@ -95,7 +106,7 @@ function UserRegister() {
}),
false,
redirectUrl,
fetchUserAfterAuthSuccess,
afterLoginSuccess,
);

const checkEmailExist = () => {
Expand DownExpand Up@@ -160,7 +171,7 @@ function UserRegister() {
{trans("userAuth.register")}
</ConfirmButton>
<TermsAndPrivacyInfo onCheckChange={(e) => setSubmitBtnDisable(!e.target.checked)} />
{organizationId && (
{(organizationId || isEnterpriseMode) && (
<ThirdPartyAuth
invitationId={invitationId}
invitedOrganizationId={organizationId}
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,7 @@ import history from "util/history";
import { LoginLogoStyle, LoginLabelStyle, StyledLoginButton } from "pages/userAuth/authComponents";
import { useSelector } from "react-redux";
import { getSystemConfigFetching, selectSystemConfig } from "redux/selectors/configSelectors";
import React from "react";
import React, { useMemo } from "react";
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";
import styled from "styled-components";
import { trans } from "i18n";
Expand All@@ -19,6 +19,7 @@ import { useRedirectUrl } from "util/hooks";
import { MultiIconDisplay } from "../../../comps/comps/multiIconDisplay";
import Spin from "antd/es/spin";
import { LoadingOutlined } from "@ant-design/icons";
import { getServerSettings } from "@lowcoder-ee/redux/selectors/applicationSelector";

const { Text } = Typography;

Expand DownExpand Up@@ -111,7 +112,16 @@ export function ThirdPartyAuth(props: {
}) {
const systemConfigFetching = useSelector(getSystemConfigFetching);
const systemConfig = useSelector(selectSystemConfig);
const serverSettings = useSelector(getServerSettings);
const isFormLoginEnabled = systemConfig?.form.enableLogin;

const isEmailLoginEnabled = useMemo(() => {
return isFormLoginEnabled && serverSettings.LOWCODER_EMAIL_AUTH_ENABLED === 'true';
}, [isFormLoginEnabled, serverSettings]);

const isEmailSignupEnabled = useMemo(() => {
return serverSettings.LOWCODER_EMAIL_SIGNUP_ENABLED === 'true';
}, [serverSettings]);

if (systemConfigFetching) {
return <Spin indicator={<LoadingOutlined style={{ fontSize: 15, marginTop: '16px' }} spin />} />;
Expand DownExpand Up@@ -140,7 +150,10 @@ export function ThirdPartyAuth(props: {
});
return (
<ThirdPartyLoginButtonWrapper>
{ isFormLoginEnabled && Boolean(socialLoginButtons.length) && (
{ (
(isEmailLoginEnabled && props.authGoal === 'login')
|| (isEmailSignupEnabled && props.authGoal === 'register')
) && Boolean(socialLoginButtons.length) && (
<Divider plain>
<Text type="secondary">or</Text>
</Divider>
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp