Skip to content

OAuth updates for third party login options. #389

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions client/packages/lowcoder-cli/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ declare var LOWCODER_NODE_SERVICE_URL: string;
declare var LOWCODER_SHOW_BRAND: string;
declare var LOWCODER_CUSTOM_LOGO: string;
declare var LOWCODER_CUSTOM_LOGO_SQUARE: string;
declare var LOWCODER_CUSTOM_AUTH_WELCOME_TEXT: string;
declare var REACT_APP_ENV: string;
declare var REACT_APP_BUILD_ID: string;
declare var REACT_APP_LOG_LEVEL: string;
Expand Down
4 changes: 4 additions & 0 deletions client/packages/lowcoder-dev-utils/buildVars.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const buildVars = [
name: "LOWCODER_NODE_SERVICE_URL",
defaultValue: "",
},
{
name: "LOWCODER_CUSTOM_AUTH_WELCOME_TEXT",
defaultValue: "",
},
{
name: "REACT_APP_ENV",
defaultValue: "production",
Expand Down
10 changes: 7 additions & 3 deletions client/packages/lowcoder/src/api/configApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ export interface ConfigResponse extends ApiResponse {
}

class ConfigApi extends Api {
static configURL = "/v1/configs";
static configURL = "/configs";

static fetchConfig(): AxiosPromise<ConfigResponse> {
return Api.get(ConfigApi.configURL);
static fetchConfig(orgId?: string): AxiosPromise<ConfigResponse> {
let authConfigURL = ConfigApi.configURL;
if(orgId?.length) {
authConfigURL += `?orgId?=${orgId}`;
}
return Api.get(authConfigURL);
}
}

Expand Down
3 changes: 2 additions & 1 deletion client/packages/lowcoder/src/api/inviteApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ export type InviteInfo = {
inviteCode: string;
createUserName: string;
invitedOrganizationName: string;
invitedOrganizationId: string;
};

class InviteApi extends Api {
static getInviteURL = "/v1/invitation";
static getInviteURL = "/invitation";
static acceptInviteURL = (invitationId: string) => `/v1/invitation/${invitationId}/invite`;

// generate invitation
Expand Down
5 changes: 3 additions & 2 deletions client/packages/lowcoder/src/api/userApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface CommonLoginParam {
invitationId?: string;
authId?: string;
source?: string;
orgId?: string;
}

export interface CommonBindParam {
Expand All @@ -17,8 +18,8 @@ export interface CommonBindParam {
source?: string;
}

interface ThirdPartyAuthRequest {
state: string;
export interface ThirdPartyAuthRequest {
state?: string;
code: string;
redirectUrl: string;
}
Expand Down
1 change: 1 addition & 0 deletions client/packages/lowcoder/src/app-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ declare var LOWCODER_NODE_SERVICE_URL: string;
declare var LOWCODER_SHOW_BRAND: string;
declare var LOWCODER_CUSTOM_LOGO: string;
declare var LOWCODER_CUSTOM_LOGO_SQUARE: string;
declare var LOWCODER_CUSTOM_AUTH_WELCOME_TEXT: string;
declare var REACT_APP_ENV: string;
declare var REACT_APP_BUILD_ID: string;
declare var REACT_APP_LOG_LEVEL: string;
Expand Down
28 changes: 20 additions & 8 deletions client/packages/lowcoder/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
IMPORT_APP_FROM_TEMPLATE_URL,
INVITE_LANDING_URL,
isAuthUnRequired,
ORG_AUTH_LOGIN_URL,
ORG_AUTH_REGISTER_URL,
QUERY_LIBRARY_URL,
SETTING,
TRASH_URL,
Expand Down Expand Up @@ -70,10 +72,11 @@ const Wrapper = (props: { children: React.ReactNode }) => (
type AppIndexProps = {
isFetchUserFinished: boolean;
isFetchHomeFinished: boolean;
isFetchingConfig: boolean;
// isFetchingConfig: boolean;
currentOrgId?: string;
orgDev: boolean;
defaultHomePage: string | null | undefined;
fetchConfig: () => void;
fetchConfig: (orgId?: string) => void;
getCurrentUser: () => void;
fetchHome: () => void;
favicon: string;
Expand All @@ -83,16 +86,22 @@ type AppIndexProps = {
class AppIndex extends React.Component<AppIndexProps, any> {
componentDidMount() {
this.props.getCurrentUser();
this.props.fetchConfig();
if (history.location.pathname === BASE_URL) {
const { pathname } = history.location;

this.props.fetchConfig(this.props.currentOrgId);

if (pathname === BASE_URL) {
this.props.fetchHome();
}
}

componentDidUpdate() {
componentDidUpdate(prevProps: AppIndexProps) {
if (history.location.pathname === BASE_URL) {
this.props.fetchHome();
}
if(prevProps.currentOrgId !== this.props.currentOrgId) {
this.props.fetchConfig(this.props.currentOrgId);
}
}

render() {
Expand All @@ -101,7 +110,7 @@ class AppIndex extends React.Component<AppIndexProps, any> {
// make sure all users in this app have checked login info
if (
!this.props.isFetchUserFinished ||
this.props.isFetchingConfig ||
// this.props.isFetchingConfig ||
(pathname === BASE_URL && !this.props.isFetchHomeFinished)
) {
const hideLoadingHeader = isTemplate || isAuthUnRequired(pathname);
Expand Down Expand Up @@ -151,6 +160,8 @@ class AppIndex extends React.Component<AppIndexProps, any> {
component={ApplicationHome}
/>
<LazyRoute path={USER_AUTH_URL} component={LazyUserAuthComp} />
<LazyRoute path={ORG_AUTH_LOGIN_URL} component={LazyUserAuthComp} />
<LazyRoute path={ORG_AUTH_REGISTER_URL} component={LazyUserAuthComp} />
<LazyRoute path={INVITE_LANDING_URL} component={LazyInviteLanding} />
<LazyRoute path={`${COMPONENT_DOC_URL}/:name`} component={LazyComponentDoc} />
<LazyRoute path={`/playground/:name/:dsl`} component={LazyComponentPlayground} />
Expand All @@ -174,8 +185,9 @@ class AppIndex extends React.Component<AppIndexProps, any> {

const mapStateToProps = (state: AppState) => ({
isFetchUserFinished: isFetchUserFinished(state),
isFetchingConfig: getSystemConfigFetching(state),
// isFetchingConfig: getSystemConfigFetching(state),
orgDev: state.ui.users.user.orgDev,
currentOrgId: state.ui.users.user.currentOrgId,
defaultHomePage: state.ui.application.homeOrg?.commonSettings.defaultHomePage,
isFetchHomeFinished: state.ui.application.loadingStatus.fetchHomeDataFinished,
favicon: getBrandingConfig(state)?.favicon
Expand All @@ -188,7 +200,7 @@ const mapDispatchToProps = (dispatch: any) => ({
getCurrentUser: () => {
dispatch(fetchUserAction());
},
fetchConfig: () => dispatch(fetchConfigAction()),
fetchConfig: (orgId?: string) => dispatch(fetchConfigAction(orgId)),
fetchHome: () => dispatch(fetchHomeData({})),
});

Expand Down
7 changes: 6 additions & 1 deletion client/packages/lowcoder/src/constants/authConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
AUTH_LOGIN_URL,
AUTH_REGISTER_URL,
OAUTH_REDIRECT,
ORG_AUTH_LOGIN_URL,
ORG_AUTH_REGISTER_URL,
} from "constants/routesURL";
import { InviteInfo } from "api/inviteApi";
import Login, { ThirdPartyBindCard } from "pages/userAuth/login";
Expand Down Expand Up @@ -56,6 +58,7 @@ export type AuthSessionStoreParams = {
afterLoginRedirect: string | null;
sourceType: string;
invitationId?: string;
invitedOrganizationId?: string;
routeLink?: boolean;
name: string;
authId?: string;
Expand All @@ -65,13 +68,15 @@ export type AuthSessionStoreParams = {
* action after third party auth
* bind & innerBind has different redirect action
*/
export type ThirdPartyAuthGoal = "login" | "bind" | "innerBind";
export type ThirdPartyAuthGoal = "register" | "login" | "bind" | "innerBind";

export const AuthRoutes: Array<{ path: string; component: React.ComponentType<any> }> = [
{ path: AUTH_LOGIN_URL, component: Login },
{ path: AUTH_BIND_URL, component: ThirdPartyBindCard },
{ path: AUTH_REGISTER_URL, component: UserRegister },
{ path: OAUTH_REDIRECT, component: AuthRedirect },
{ path: ORG_AUTH_LOGIN_URL, component: Login },
{ path: ORG_AUTH_REGISTER_URL, component: UserRegister },
];

export type ServerAuthType = "GOOGLE" | "GITHUB" | "FORM";
Expand Down
4 changes: 4 additions & 0 deletions client/packages/lowcoder/src/constants/routesURL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export const CAS_AUTH_REDIRECT = `${USER_AUTH_URL}/cas/redirect`;
export const LDAP_AUTH_LOGIN_URL = `${USER_AUTH_URL}/ldap/login`;
export const USER_INFO_COMPLETION = `${USER_AUTH_URL}/completion`;
export const INVITE_LANDING_URL = "/invite/:invitationId";
export const ORG_AUTH_LOGIN_URL = `/org/:orgId/auth/login`;
export const ORG_AUTH_REGISTER_URL = `/org/:orgId/auth/register`;

export const APPLICATION_VIEW_URL = (appId: string, viewMode: AppViewMode) =>
`${ALL_APPLICATIONS_URL}/${appId}/${viewMode}`;
Expand All @@ -49,6 +51,8 @@ export const isAuthUnRequired = (pathname: string): boolean => {
return (
pathname.startsWith("/invite/") ||
pathname.startsWith(USER_AUTH_URL) ||
pathname.endsWith('/auth/login') ||
pathname.endsWith('/auth/register') ||
pathname.startsWith(COMPONENT_DOC_URL)
);
};
Expand Down
1 change: 1 addition & 0 deletions client/packages/lowcoder/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1960,6 +1960,7 @@ export const en = {
resetSuccess: "Reset succeeded",
resetSuccessDesc: "Password reset succeeded. The new password is: {password}",
copyPassword: "Copy password",
poweredByLowcoder: "Powered by Lowcoder.cloud"
},
preLoad: {
jsLibraryHelpText:
Expand Down
1 change: 1 addition & 0 deletions client/packages/lowcoder/src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,7 @@ userAuth: {
resetSuccess: "重置成功",
resetSuccessDesc: "密码重置成功.新密码为:{password}",
copyPassword: "复制密码",
poweredByLowcoder: "供电 Lowcoder.cloud"
},
preLoad: {
jsLibraryHelpText: "通过URL链接向当前应用程序添加JavaScript库.lodash、day.js、uuid、numbro内置于系统中,可立即使用.JavaScript库在应用程序初始化之前加载,这可能会影响应用程序的性能.",
Expand Down
17 changes: 14 additions & 3 deletions client/packages/lowcoder/src/pages/common/inviteLanding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import { RouteComponentProps } from "react-router-dom";
import { AppState } from "redux/reducers";
import history from "util/history";
import { isFetchUserFinished } from "redux/selectors/usersSelectors";
import { fetchConfigAction } from "redux/reduxActions/configActions";
import { trans } from "i18n";
import { messageInstance } from "lowcoder-design";

type InviteLandingProp = RouteComponentProps<{ invitationId: string }, StaticContext, any> & {
invitationId: string;
fetchConfig: (orgId?: string) => void;
};

function InviteLanding(props: InviteLandingProp) {
const { invitationId } = props;
const { invitationId, fetchConfig } = props;
const fetchUserFinished = useSelector(isFetchUserFinished);
useEffect(() => {
if (!fetchUserFinished) {
Expand All @@ -27,6 +29,7 @@ function InviteLanding(props: InviteLandingProp) {
history.push(BASE_URL);
return;
}
let orgId:string | undefined = undefined;
// accept the invitation
InviteApi.acceptInvite({ invitationId })
.then((resp) => {
Expand All @@ -39,6 +42,7 @@ function InviteLanding(props: InviteLandingProp) {
resp?.status === API_STATUS_CODES.REQUEST_NOT_AUTHORISED
) {
const inviteInfo = resp.data.data;
orgId = inviteInfo.invitedOrganizationId;
const inviteState = inviteInfo ? { ...inviteInfo, invitationId } : { invitationId };
history.push({
pathname: AUTH_LOGIN_URL,
Expand All @@ -53,8 +57,10 @@ function InviteLanding(props: InviteLandingProp) {
.catch((errorResp) => {
messageInstance.error(errorResp.message);
history.push(BASE_URL);
}).finally(() => {
// fetchConfig(orgId);
});
}, [fetchUserFinished, invitationId]);
}, [fetchUserFinished, invitationId, fetchConfig]);
return null;
}

Expand All @@ -64,4 +70,9 @@ const mapStateToProps = (state: AppState, props: InviteLandingProp) => {
};
};

export default connect(mapStateToProps)(InviteLanding);
const mapDispatchToProps = (dispatch: any) => ({
fetchConfig: (orgId?: string) => dispatch(fetchConfigAction(orgId)),
});


export default connect(mapStateToProps, mapDispatchToProps)(InviteLanding);
Loading