Compare commits

...

2 Commits

Author SHA1 Message Date
DacongDA
a0e2be7ba8 feat: support inserting user's field to SAML attribute (#4105) 2025-08-22 11:27:21 +08:00
IsAurora6
09b389b1f7 feat: add a loading animation in DashboardPage (#4117) 2025-08-22 00:11:08 +08:00
3 changed files with 84 additions and 9 deletions

View File

@@ -70,7 +70,9 @@ func NewSamlResponse(application *Application, user *User, host string, certific
if application.UseEmailAsSamlNameId {
nameIDValue = user.Email
}
subject.CreateElement("saml:NameID").SetText(nameIDValue)
nameId := subject.CreateElement("saml:NameID")
nameId.CreateAttr("Format", "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent")
nameId.SetText(nameIDValue)
subjectConfirmation := subject.CreateElement("saml:SubjectConfirmation")
subjectConfirmation.CreateAttr("Method", "urn:oasis:names:tc:SAML:2.0:cm:bearer")
subjectConfirmationData := subjectConfirmation.CreateElement("saml:SubjectConfirmationData")
@@ -108,20 +110,46 @@ func NewSamlResponse(application *Application, user *User, host string, certific
displayName.CreateAttr("NameFormat", "urn:oasis:names:tc:SAML:2.0:attrname-format:basic")
displayName.CreateElement("saml:AttributeValue").CreateAttr("xsi:type", "xs:string").Element().SetText(user.DisplayName)
err := ExtendUserWithRolesAndPermissions(user)
if err != nil {
return nil, err
}
for _, item := range application.SamlAttributes {
role := attributes.CreateElement("saml:Attribute")
role.CreateAttr("Name", item.Name)
role.CreateAttr("NameFormat", item.NameFormat)
role.CreateElement("saml:AttributeValue").CreateAttr("xsi:type", "xs:string").Element().SetText(item.Value)
valueList := []string{item.Value}
if strings.Contains(item.Value, "$user.roles") {
valueList = replaceSamlAttributeValuesWithList("$user.roles", getUserRoleNames(user), valueList)
}
if strings.Contains(item.Value, "$user.permissions") {
valueList = replaceSamlAttributeValuesWithList("$user.permissions", getUserPermissionNames(user), valueList)
}
if strings.Contains(item.Value, "$user.groups") {
valueList = replaceSamlAttributeValuesWithList("$user.groups", user.Groups, valueList)
}
valueList = replaceSamlAttributeValues("$user.owner", user.Owner, valueList)
valueList = replaceSamlAttributeValues("$user.name", user.Name, valueList)
valueList = replaceSamlAttributeValues("$user.email", user.Email, valueList)
valueList = replaceSamlAttributeValues("$user.id", user.Id, valueList)
valueList = replaceSamlAttributeValues("$user.phone", user.Phone, valueList)
for _, value := range valueList {
av := role.CreateElement("saml:AttributeValue")
av.CreateAttr("xmlns:xs", "http://www.w3.org/2001/XMLSchema")
av.CreateAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
av.CreateAttr("xsi:type", "xs:string").Element().SetText(value)
}
}
roles := attributes.CreateElement("saml:Attribute")
roles.CreateAttr("Name", "Roles")
roles.CreateAttr("NameFormat", "urn:oasis:names:tc:SAML:2.0:attrname-format:basic")
err := ExtendUserWithRolesAndPermissions(user)
if err != nil {
return nil, err
}
for _, role := range user.Roles {
roles.CreateElement("saml:AttributeValue").CreateAttr("xsi:type", "xs:string").Element().SetText(role.Name)
@@ -130,6 +158,26 @@ func NewSamlResponse(application *Application, user *User, host string, certific
return samlResponse, nil
}
func replaceSamlAttributeValues(val string, replaceVal string, values []string) []string {
newValues := []string{}
for _, value := range values {
newValues = append(newValues, strings.ReplaceAll(value, val, replaceVal))
}
return newValues
}
func replaceSamlAttributeValuesWithList(val string, replaceVals []string, values []string) []string {
newValues := []string{}
for _, value := range values {
for _, rVal := range replaceVals {
newValues = append(newValues, strings.ReplaceAll(value, val, rVal))
}
}
return newValues
}
type X509Key struct {
X509Certificate string
PrivateKey string

View File

@@ -248,6 +248,20 @@ func SetUserOAuthProperties(organization *Organization, user *User, providerType
return UpdateUserForAllFields(user.GetId(), user)
}
func getUserRoleNames(user *User) (res []string) {
for _, role := range user.Roles {
res = append(res, role.Name)
}
return res
}
func getUserPermissionNames(user *User) (res []string) {
for _, permission := range user.Permissions {
res = append(res, permission.Name)
}
return res
}
func ClearUserOAuthProperties(user *User, providerType string) (bool, error) {
for k := range user.Properties {
prefix := fmt.Sprintf("oauth_%s_", providerType)

View File

@@ -13,7 +13,7 @@
// limitations under the License.
import {ArrowUpOutlined} from "@ant-design/icons";
import {Card, Col, Row, Statistic, Tour} from "antd";
import {Card, Col, Row, Spin, Statistic, Tour} from "antd";
import * as echarts from "echarts";
import i18next from "i18next";
import React from "react";
@@ -74,6 +74,8 @@ const Dashboard = (props) => {
return;
}
setDashboardData(null);
const organization = getOrganizationName();
DashboardBackend.getDashboard(organization).then((res) => {
if (res.status === "ok") {
@@ -110,11 +112,22 @@ const Dashboard = (props) => {
};
const renderEChart = () => {
const chartDom = document.getElementById("echarts-chart");
if (dashboardData === null) {
return;
if (chartDom) {
const instance = echarts.getInstanceByDom(chartDom);
if (instance) {
instance.dispose();
}
}
return (
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
<Spin size="large" tip={i18next.t("login:Loading")} style={{paddingTop: "10%"}} />
</div>
);
}
const chartDom = document.getElementById("echarts-chart");
const myChart = echarts.init(chartDom);
const currentDate = new Date();
const dateArray = [];