Compare commits

...

7 Commits

Author SHA1 Message Date
千石
79b934d6c2 feat: enforce acceptance of terms and conditions for social logins (#3087)
* feat: Enforce acceptance of terms and conditions for social logins (#2975)

* feat: add error message for agreement acceptance
2024-07-29 17:22:48 +08:00
DacongDA
365449695b fix: fix application field in invitationEditPage will use translation of "All" as value (#3085) 2024-07-29 01:35:28 +08:00
DacongDA
55a52093e8 feat: fix bug that user can signup without invitation code via OAuth (#3084)
* fix:fix user can signup without invitation code when using 3rd oauth

* fix:use correct i18n translation
2024-07-29 00:59:02 +08:00
Giang Dinh
e65fdeb1e0 feat: ABAC support for /api/batch-enforce endpoint (#3082) 2024-07-27 09:43:58 +08:00
千石
a46c1cc775 feat: update WeCom OAuth URLs (#3080) 2024-07-26 22:03:24 +08:00
DacongDA
5629343466 feat: fix missing extendApplicationWithSigninMethods() in getDefaultApplication() (#3076) 2024-07-24 22:30:15 +08:00
王天成
3718d2dc04 feat: improve name mapping in LarkIdProvider (#3075)
* fix: change user identifier to the `user_id` field in IdP Lark, and use Chinese name to be the display name

* Update lark.go

---------

Co-authored-by: Yang Luo <hsluoyz@qq.com>
2024-07-23 21:12:53 +08:00
8 changed files with 57 additions and 17 deletions

View File

@@ -665,6 +665,11 @@ func (c *ApiController) Login() {
return
}
if application.IsSignupItemRequired("Invitation code") {
c.ResponseError(c.T("check:Invitation code cannot be blank"))
return
}
// Handle username conflicts
var tmpUser *object.User
tmpUser, err = object.GetUser(util.GetId(application.Organization, userInfo.Username))

View File

@@ -213,8 +213,8 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
userInfo := UserInfo{
Id: larkUserInfo.Data.OpenId,
DisplayName: larkUserInfo.Data.EnName,
Username: larkUserInfo.Data.Name,
DisplayName: larkUserInfo.Data.Name,
Username: larkUserInfo.Data.UserId,
Email: larkUserInfo.Data.Email,
AvatarUrl: larkUserInfo.Data.AvatarUrl,
Phone: phoneNumber,

View File

@@ -356,6 +356,11 @@ func GetDefaultApplication(id string) (*Application, error) {
return nil, err
}
err = extendApplicationWithSigninMethods(defaultApplication)
if err != nil {
return nil, err
}
return defaultApplication, nil
}

View File

@@ -354,9 +354,16 @@ func StringToInterfaceArray(array []string) []interface{} {
func StringToInterfaceArray2d(arrays [][]string) [][]interface{} {
var interfaceArrays [][]interface{}
for _, req := range arrays {
var interfaceArray []interface{}
for _, r := range req {
interfaceArray = append(interfaceArray, r)
var (
interfaceArray []interface{}
elem interface{}
)
for _, elem = range req {
jStruct, err := TryJsonToAnonymousStruct(elem.(string))
if err == nil {
elem = jStruct
}
interfaceArray = append(interfaceArray, elem)
}
interfaceArrays = append(interfaceArrays, interfaceArray)
}

View File

@@ -199,7 +199,7 @@ class InvitationEditPage extends React.Component {
<Select virtual={false} style={{width: "100%"}} value={this.state.invitation.application}
onChange={(value => {this.updateInvitationField("application", value);})}
options={[
{label: "All", value: i18next.t("general:All")},
{label: i18next.t("general:All"), value: "All"},
...this.state.applications.map((application) => Setting.getOption(application.name, application.name)),
]} />
</Col>

View File

@@ -13,7 +13,7 @@
// limitations under the License.
import React, {Suspense, lazy} from "react";
import {Button, Checkbox, Col, Form, Input, Result, Spin, Tabs} from "antd";
import {Button, Checkbox, Col, Form, Input, Result, Spin, Tabs, message} from "antd";
import {ArrowLeftOutlined, LockOutlined, UserOutlined} from "@ant-design/icons";
import {withRouter} from "react-router-dom";
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
@@ -23,7 +23,6 @@ import * as AuthBackend from "./AuthBackend";
import * as OrganizationBackend from "../backend/OrganizationBackend";
import * as ApplicationBackend from "../backend/ApplicationBackend";
import * as Provider from "./Provider";
import * as ProviderButton from "./ProviderButton";
import * as Util from "./Util";
import * as Setting from "../Setting";
import * as AgreementModal from "../common/modal/AgreementModal";
@@ -36,6 +35,7 @@ import {CaptchaModal, CaptchaRule} from "../common/modal/CaptchaModal";
import RedirectForm from "../common/RedirectForm";
import {MfaAuthVerifyForm, NextMfa, RequiredMfa} from "./mfa/MfaAuthVerifyForm";
import {GoogleOneTapLoginVirtualButton} from "./GoogleLoginButton";
import * as ProviderButton from "./ProviderButton";
const FaceRecognitionModal = lazy(() => import("../common/modal/FaceRecognitionModal"));
class LoginPage extends React.Component {
@@ -746,8 +746,19 @@ class LoginPage extends React.Component {
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<Form.Item>
{
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
return ProviderButton.renderProviderLogo(providerItem.provider, application, null, null, signinItem.rule, this.props.location);
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map((providerItem, id) => {
return (
<span key ={id} onClick={(e) => {
if (!this.form.current.getFieldValue("agreement")) {
e.preventDefault();
message.error(i18next.t("signup:Please accept the agreement!"));
}
}}>
{
ProviderButton.renderProviderLogo(providerItem.provider, application, null, null, signinItem.rule, this.props.location)
}
</span>
);
})
}
{

View File

@@ -61,9 +61,9 @@ const authInfo = {
},
WeCom: {
scope: "snsapi_userinfo",
endpoint: "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect",
endpoint: "https://login.work.weixin.qq.com/wwlogin/sso/login",
silentEndpoint: "https://open.weixin.qq.com/connect/oauth2/authorize",
internalEndpoint: "https://open.work.weixin.qq.com/wwopen/sso/qrConnect",
internalEndpoint: "https://login.work.weixin.qq.com/wwlogin/sso/login",
},
Lark: {
// scope: "email",
@@ -433,7 +433,7 @@ export function getAuthUrl(application, provider, method, code) {
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&scope=${scope}&response_type=code#wechat_redirect`;
} else if (provider.method === "Normal") {
endpoint = authInfo[provider.type].internalEndpoint;
return `${endpoint}?appid=${provider.clientId}&agentid=${provider.appId}&redirect_uri=${redirectUri}&state=${state}&usertype=member`;
return `${endpoint}?login_type=CorpApp&appid=${provider.clientId}&agentid=${provider.appId}&redirect_uri=${redirectUri}&state=${state}`;
} else {
return `https://error:not-supported-provider-method:${provider.method}`;
}
@@ -442,7 +442,8 @@ export function getAuthUrl(application, provider, method, code) {
endpoint = authInfo[provider.type].silentEndpoint;
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&scope=${scope}&response_type=code#wechat_redirect`;
} else if (provider.method === "Normal") {
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&usertype=member`;
endpoint = authInfo[provider.type].endpoint;
return `${endpoint}?login_type=ServiceApp&appid=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}`;
} else {
return `https://error:not-supported-provider-method:${provider.method}`;
}

View File

@@ -13,7 +13,7 @@
// limitations under the License.
import React from "react";
import {Button, Form, Input, Radio, Result, Row} from "antd";
import {Button, Form, Input, Radio, Result, Row, message} from "antd";
import * as Setting from "../Setting";
import * as AuthBackend from "./AuthBackend";
import * as ProviderButton from "./ProviderButton";
@@ -653,8 +653,19 @@ class SignupPage extends React.Component {
}
return (
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map(providerItem => {
return ProviderButton.renderProviderLogo(providerItem.provider, application, null, null, signupItem.rule, this.props.location);
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map((providerItem, id) => {
return (
<span key={id} onClick={(e) => {
if (!this.form.current.getFieldValue("agreement")) {
e.preventDefault();
message.error(i18next.t("signup:Please accept the agreement!"));
}
}}>
{
ProviderButton.renderProviderLogo(providerItem.provider, application, null, null, signupItem.rule, this.props.location)
}
</span>
);
})
);