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

Commitc75d935

Browse files
authored
Merge pull request#1643 from lowcoder-org/oauth_updates
Login flow for SingleWorkspace/Enterprise mode
2 parents41e2af2 +58268e7 commitc75d935

File tree

6 files changed

+120
-28
lines changed

6 files changed

+120
-28
lines changed

‎client/packages/lowcoder/src/api/apiUtils.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,14 @@ export const apiFailureResponseInterceptor = (error: any) => {
122122
if(!notAuthRequiredPath(error.config?.url)){
123123
if(error.response.status===API_STATUS_CODES.REQUEST_NOT_AUTHORISED){
124124
// get x-org-id from failed request
125-
constorganizationId=error.response.headers['x-org-id']||undefined;
125+
letorganizationId;
126+
if(error.response.headers['x-org-id']){
127+
organizationId=error.response.headers['x-org-id'];
128+
}
129+
if(localStorage.getItem('lowcoder_login_orgId')){
130+
organizationId=localStorage.getItem('lowcoder_login_orgId');
131+
localStorage.removeItem('lowcoder_login_orgId');
132+
}
126133
// Redirect to login and set a redirect url.
127134
StoreRegistry.getStore().dispatch(
128135
logoutAction({

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3205,6 +3205,7 @@ export const en = {
32053205
"enterPassword":"Enter your password",
32063206
"selectAuthProvider":"Select Authentication Provider",
32073207
"selectWorkspace":"Select your workspace",
3208+
"userNotFound":"User not found. Please make sure you entered the correct email."
32083209
},
32093210
"preLoad":{
32103211
"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.",

‎client/packages/lowcoder/src/pages/common/profileDropdown.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,13 @@ export default function ProfileDropdown(props: DropDownProps) {
150150
dispatch(profileSettingModalVisible(true));
151151
}elseif(e.key==="logout"){
152152
// logout
153-
dispatch(logoutAction({}));
153+
constorganizationId=localStorage.getItem('lowcoder_login_orgId');
154+
if(organizationId){
155+
localStorage.removeItem('lowcoder_login_orgId');
156+
}
157+
dispatch(logoutAction({
158+
organizationId:organizationId||undefined,
159+
}));
154160
}elseif(e.keyPath.includes("switchOrg")){
155161
if(e.key==="newOrganization"){
156162
// create new organization

‎client/packages/lowcoder/src/pages/userAuth/formLoginSteps.tsx

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
ConfirmButton,
55
StyledRouteLink,
66
}from"pages/userAuth/authComponents";
7-
importReact,{useContext,useEffect,useState}from"react";
7+
importReact,{useContext,useEffect,useMemo,useState}from"react";
88
importstyledfrom"styled-components";
99
importUserApifrom"api/userApi";
1010
import{useRedirectUrl}from"util/hooks";
@@ -19,7 +19,7 @@ import { Divider } from "antd";
1919
importFlexfrom"antd/es/flex";
2020
import{validateResponse}from"@lowcoder-ee/api/apiUtils";
2121
importOrgApifrom"@lowcoder-ee/api/orgApi";
22-
import{AccountLoginWrapper}from"./formLoginAdmin";
22+
importFormLogin,{AccountLoginWrapper}from"./formLoginAdmin";
2323
import{defaultasButton}from"antd/es/button";
2424
importLeftOutlinedfrom"@ant-design/icons/LeftOutlined";
2525
import{fetchConfigAction}from"@lowcoder-ee/redux/reduxActions/configActions";
@@ -28,6 +28,9 @@ import history from "util/history";
2828
import{getServerSettings}from"@lowcoder-ee/redux/selectors/applicationSelector";
2929
import{fetchOrgPaginationByEmail}from"@lowcoder-ee/util/pagination/axios";
3030
importPaginationCompfrom"@lowcoder-ee/util/pagination/Pagination";
31+
import{getSystemConfigFetching}from"@lowcoder-ee/redux/selectors/configSelectors";
32+
importSpinfrom"antd/es/spin";
33+
importLoadingOutlinedfrom"@ant-design/icons/LoadingOutlined";
3134

3235
constStyledCard=styled.div<{$selected:boolean}>`
3336
display: flex;
@@ -107,18 +110,28 @@ export default function FormLoginSteps(props: FormLoginProps) {
107110
const{ systemConfig, inviteInfo, fetchUserAfterAuthSuccess}=useContext(AuthContext);
108111
constinvitationId=inviteInfo?.invitationId;
109112
constauthId=systemConfig?.form.id;
110-
constisFormLoginEnabled=systemConfig?.form.enableLogin;
113+
constisFormLoginEnabled=systemConfig?.form.enableLogin;// check from configs
111114
const[orgLoading,setOrgLoading]=useState(false);
112115
const[orgList,setOrgList]=useState<OrgItem[]>([]);
113116
const[currentStep,setCurrentStep]=useState<CurrentStepEnum>(CurrentStepEnum.EMAIL);
114117
const[organizationId,setOrganizationId]=useState<string|undefined>(props.organizationId);
115118
const[skipWorkspaceStep,setSkipWorkspaceStep]=useState<boolean>(false);
116119
const[signupEnabled,setSignupEnabled]=useState<boolean>(true);
120+
const[signinEnabled,setSigninEnabled]=useState<boolean>(true);// check from server settings
117121
constserverSettings=useSelector(getServerSettings);
122+
constisFetchingConfig=useSelector(getSystemConfigFetching);
118123
const[elements,setElements]=useState<ElementsState>({elements:[],total:0});
119124
const[currentPage,setCurrentPage]=useState(1);
120125
const[pageSize,setPageSize]=useState(10);
121126

127+
constisEmailLoginEnabled=useMemo(()=>{
128+
returnisFormLoginEnabled&&signinEnabled;
129+
},[isFormLoginEnabled,signinEnabled]);
130+
131+
constisEnterpriseMode=useMemo(()=>{
132+
returnserverSettings?.LOWCODER_WORKSPACE_MODE==="ENTERPRISE"||serverSettings?.LOWCODER_WORKSPACE_MODE==="SINGLEWORKSPACE";
133+
},[serverSettings]);
134+
122135
useEffect(()=>{
123136
if(account)
124137
fetchOrgPaginationByEmail({
@@ -133,13 +146,22 @@ export default function FormLoginSteps(props: FormLoginProps) {
133146
},[pageSize,currentPage])
134147

135148
useEffect(()=>{
136-
const{LOWCODER_EMAIL_SIGNUP_ENABLED}=serverSettings;
137-
if(!LOWCODER_EMAIL_SIGNUP_ENABLED){
138-
returnsetSignupEnabled(true);
139-
}
149+
const{
150+
LOWCODER_EMAIL_SIGNUP_ENABLED,
151+
LOWCODER_EMAIL_AUTH_ENABLED,
152+
}=serverSettings;
153+
140154
setSignupEnabled(LOWCODER_EMAIL_SIGNUP_ENABLED==='true');
155+
setSigninEnabled(LOWCODER_EMAIL_AUTH_ENABLED==='true');
141156
},[serverSettings]);
142157

158+
constafterLoginSuccess=()=>{
159+
if(props.organizationId){
160+
localStorage.setItem("lowcoder_login_orgId",props.organizationId);
161+
}
162+
fetchUserAfterAuthSuccess?.();
163+
}
164+
143165
const{ onSubmit, loading}=useAuthSubmit(
144166
()=>
145167
UserApi.formLogin({
@@ -153,7 +175,7 @@ export default function FormLoginSteps(props: FormLoginProps) {
153175
}),
154176
false,
155177
redirectUrl,
156-
fetchUserAfterAuthSuccess,
178+
afterLoginSuccess,
157179
);
158180

159181
constfetchOrgsByEmail=()=>{
@@ -167,8 +189,9 @@ export default function FormLoginSteps(props: FormLoginProps) {
167189
}
168190

169191
setOrgLoading(true);
192+
// for enterprise mode, we will not ask for email in first step
170193
fetchOrgPaginationByEmail({
171-
email:account,
194+
email:isEnterpriseMode ?' ' :account,
172195
pageNum:currentPage,
173196
pageSize:pageSize
174197
})
@@ -177,15 +200,13 @@ export default function FormLoginSteps(props: FormLoginProps) {
177200
setElements({elements:resp.data||[],total:resp.total||1})
178201
setOrgList(resp.data);
179202
if(!resp.data.length){
180-
history.push(
181-
AUTH_REGISTER_URL,
182-
{...location.state||{},email:account},
183-
)
184-
return;
203+
thrownewError(trans("userAuth.userNotFound"));
185204
}
186205
if(resp.data.length===1){
187-
setOrganizationId(resp.data[0].orgId);
188-
dispatch(fetchConfigAction(resp.data[0].orgId));
206+
// in Enterprise mode, we will get org data in different format
207+
constselectedOrgId=isEnterpriseMode ?resp.data[0].id :resp.data[0].orgId;
208+
setOrganizationId(selectedOrgId);
209+
dispatch(fetchConfigAction(selectedOrgId));
189210
setCurrentStep(CurrentStepEnum.AUTH_PROVIDERS);
190211
return;
191212
}
@@ -202,6 +223,39 @@ export default function FormLoginSteps(props: FormLoginProps) {
202223
});
203224
}
204225

226+
useEffect(()=>{
227+
if(isEnterpriseMode){
228+
// dispatch(fetchConfigAction());
229+
fetchOrgsByEmail();
230+
}
231+
},[isEnterpriseMode]);
232+
233+
if(isEnterpriseMode){
234+
return(
235+
<Spinindicator={<LoadingOutlinedstyle={{fontSize:30}}/>}spinning={isFetchingConfig}>
236+
{isEmailLoginEnabled&&<FormLogin/>}
237+
<ThirdPartyAuth
238+
invitationId={invitationId}
239+
invitedOrganizationId={organizationId}
240+
authGoal="login"
241+
/>
242+
{signupEnabled&&(
243+
<>
244+
<Divider/>
245+
<AuthBottomView>
246+
<StyledRouteLinkto={{
247+
pathname:AUTH_REGISTER_URL,
248+
state:{...location.state||{},email:account}
249+
}}>
250+
{trans("userAuth.register")}
251+
</StyledRouteLink>
252+
</AuthBottomView>
253+
</>
254+
)}
255+
</Spin>
256+
);
257+
}
258+
205259
if(currentStep===CurrentStepEnum.EMAIL){
206260
return(
207261
<>
@@ -227,8 +281,8 @@ export default function FormLoginSteps(props: FormLoginProps) {
227281
<Divider/>
228282
<AuthBottomView>
229283
<StyledRouteLinkto={{
230-
pathname:AUTH_REGISTER_URL,
231-
state:location.state
284+
pathname:props.organizationId ?`/org/${props.organizationId}/auth/register` :AUTH_REGISTER_URL,
285+
state:{...location.state||{},email:account}
232286
}}>
233287
{trans("userAuth.register")}
234288
</StyledRouteLink>
@@ -280,10 +334,10 @@ export default function FormLoginSteps(props: FormLoginProps) {
280334
}}/>
281335
<StepHeader
282336
title={
283-
isFormLoginEnabled ?trans("userAuth.enterPassword") :trans("userAuth.selectAuthProvider")
337+
isEmailLoginEnabled ?trans("userAuth.enterPassword") :trans("userAuth.selectAuthProvider")
284338
}
285339
/>
286-
{isFormLoginEnabled&&(
340+
{isEmailLoginEnabled&&(
287341
<>
288342
<PasswordInput
289343
className="form-input password-input"
@@ -315,7 +369,7 @@ export default function FormLoginSteps(props: FormLoginProps) {
315369
/>
316370
)}
317371
</AccountLoginWrapper>
318-
{isFormLoginEnabled&&signupEnabled&&(
372+
{isEmailLoginEnabled&&signupEnabled&&(
319373
<>
320374
<Divider/>
321375
<AuthBottomView>

‎client/packages/lowcoder/src/pages/userAuth/register.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,16 @@ function UserRegister() {
6363
returninviteInfo?.invitedOrganizationId;
6464
}
6565
returnorgId;
66-
},[inviteInfo,orgId])
66+
},[inviteInfo,orgId]);
6767

6868
constauthId=systemConfig?.form.id;
6969

7070
constserverSettings=useSelector(getServerSettings);
7171

72+
constisEnterpriseMode=useMemo(()=>{
73+
returnserverSettings?.LOWCODER_WORKSPACE_MODE==="ENTERPRISE"||serverSettings?.LOWCODER_WORKSPACE_MODE==="SINGLEWORKSPACE";
74+
},[serverSettings]);
75+
7276
useEffect(()=>{
7377
const{LOWCODER_EMAIL_SIGNUP_ENABLED}=serverSettings;
7478
if(
@@ -82,6 +86,13 @@ function UserRegister() {
8286
};
8387
},[serverSettings]);
8488

89+
constafterLoginSuccess=()=>{
90+
if(organizationId){
91+
localStorage.setItem("lowcoder_login_orgId",organizationId);
92+
}
93+
fetchUserAfterAuthSuccess?.();
94+
}
95+
8596
const{ loading, onSubmit}=useAuthSubmit(
8697
()=>
8798
UserApi.formLogin({
@@ -95,7 +106,7 @@ function UserRegister() {
95106
}),
96107
false,
97108
redirectUrl,
98-
fetchUserAfterAuthSuccess,
109+
afterLoginSuccess,
99110
);
100111

101112
constcheckEmailExist=()=>{
@@ -160,7 +171,7 @@ function UserRegister() {
160171
{trans("userAuth.register")}
161172
</ConfirmButton>
162173
<TermsAndPrivacyInfoonCheckChange={(e)=>setSubmitBtnDisable(!e.target.checked)}/>
163-
{organizationId&&(
174+
{(organizationId||isEnterpriseMode)&&(
164175
<ThirdPartyAuth
165176
invitationId={invitationId}
166177
invitedOrganizationId={organizationId}

‎client/packages/lowcoder/src/pages/userAuth/thirdParty/thirdPartyAuth.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import history from "util/history";
88
import{LoginLogoStyle,LoginLabelStyle,StyledLoginButton}from"pages/userAuth/authComponents";
99
import{useSelector}from"react-redux";
1010
import{getSystemConfigFetching,selectSystemConfig}from"redux/selectors/configSelectors";
11-
importReactfrom"react";
11+
importReact,{useMemo}from"react";
1212
import{messageInstance}from"lowcoder-design/src/components/GlobalInstances";
1313
importstyledfrom"styled-components";
1414
import{trans}from"i18n";
@@ -19,6 +19,7 @@ import { useRedirectUrl } from "util/hooks";
1919
import{MultiIconDisplay}from"../../../comps/comps/multiIconDisplay";
2020
importSpinfrom"antd/es/spin";
2121
import{LoadingOutlined}from"@ant-design/icons";
22+
import{getServerSettings}from"@lowcoder-ee/redux/selectors/applicationSelector";
2223

2324
const{ Text}=Typography;
2425

@@ -111,7 +112,16 @@ export function ThirdPartyAuth(props: {
111112
}){
112113
constsystemConfigFetching=useSelector(getSystemConfigFetching);
113114
constsystemConfig=useSelector(selectSystemConfig);
115+
constserverSettings=useSelector(getServerSettings);
114116
constisFormLoginEnabled=systemConfig?.form.enableLogin;
117+
118+
constisEmailLoginEnabled=useMemo(()=>{
119+
returnisFormLoginEnabled&&serverSettings.LOWCODER_EMAIL_AUTH_ENABLED==='true';
120+
},[isFormLoginEnabled,serverSettings]);
121+
122+
constisEmailSignupEnabled=useMemo(()=>{
123+
returnserverSettings.LOWCODER_EMAIL_SIGNUP_ENABLED==='true';
124+
},[serverSettings]);
115125

116126
if(systemConfigFetching){
117127
return<Spinindicator={<LoadingOutlinedstyle={{fontSize:15,marginTop:'16px'}}spin/>}/>;
@@ -140,7 +150,10 @@ export function ThirdPartyAuth(props: {
140150
});
141151
return(
142152
<ThirdPartyLoginButtonWrapper>
143-
{isFormLoginEnabled&&Boolean(socialLoginButtons.length)&&(
153+
{(
154+
(isEmailLoginEnabled&&props.authGoal==='login')
155+
||(isEmailSignupEnabled&&props.authGoal==='register')
156+
)&&Boolean(socialLoginButtons.length)&&(
144157
<Dividerplain>
145158
<Texttype="secondary">or</Text>
146159
</Divider>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp