feat: destroy session after delete user (#1441)

* fix: destroy session after delete user

* feat: visual session

* fix: go lint

* feat: add translation

* feat: auto flush after offline

* fix: delete one session

* fix: move 403 page to baseListPage
This commit is contained in:
Yaodong Yu 2023-01-06 15:04:13 +08:00 committed by GitHub
parent 4ab2ca7a25
commit b525210835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 12349 additions and 11686 deletions

View File

@ -242,6 +242,7 @@ func (c *ApiController) Signup() {
// @router /logout [get,post]
func (c *ApiController) Logout() {
user := c.GetSessionUsername()
object.DeleteSessionId(user, c.Ctx.Input.CruSession.SessionID())
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
application := c.GetSessionApplication()

View File

@ -139,6 +139,10 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
})
}
if resp.Status == "ok" {
object.SetSession(user.GetId(), c.Ctx.Input.CruSession.SessionID())
}
return resp
}

68
controllers/session.go Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// DeleteSession
// @Title DeleteSession
// @Tag Session API
// @Description Delete session by userId
// @Param ID query string true "The ID(owner/name) of user."
// @Success 200 {array} string The Response object
// @router /delete-session [post]
func (c *ApiController) DeleteSession() {
var session object.Session
err := json.Unmarshal(c.Ctx.Input.RequestBody, &session)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteSession(util.GetId(session.Owner, session.Name)))
c.ServeJSON()
}
// GetSessions
// @Title GetSessions
// @Tag Session API
// @Description Get organization user sessions
// @Param owner query string true "The organization name"
// @Success 200 {array} string The Response object
// @router /get-sessions [get]
func (c *ApiController) GetSessions() {
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
owner := c.Input().Get("owner")
if limit == "" || page == "" {
c.Data["json"] = object.GetSessions(owner)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSessionCount(owner, field, value)))
sessions := object.GetPaginationSessions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseOk(sessions, paginator.Nums())
}
}

View File

@ -222,6 +222,11 @@ func (a *Adapter) createTable() {
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Session))
if err != nil {
panic(err)
}
}
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {

132
object/session.go Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"time"
"github.com/beego/beego"
"github.com/casdoor/casdoor/util"
"xorm.io/core"
)
type Session struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
SessionId []string `json:"sessionId"`
}
func SetSession(id string, sessionId string) {
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
session := &Session{Owner: owner, Name: name}
get, err := adapter.Engine.Get(session)
if err != nil {
panic(err)
}
session.SessionId = append(session.SessionId, sessionId)
if get {
_, err = adapter.Engine.ID(core.PK{owner, name}).Update(session)
} else {
session.CreatedTime = time.Now().Format(time.RFC3339)
_, err = adapter.Engine.Insert(session)
}
if err != nil {
panic(err)
}
}
func DeleteSession(id string) bool {
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
session := &Session{Owner: owner, Name: name}
_, err := adapter.Engine.ID(core.PK{owner, name}).Get(session)
if err != nil {
return false
}
DeleteBeegoSession(session.SessionId)
affected, err := adapter.Engine.ID(core.PK{owner, name}).Delete(session)
return affected != 0
}
func DeleteSessionId(id string, sessionId string) bool {
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
session := &Session{Owner: owner, Name: name}
_, err := adapter.Engine.ID(core.PK{owner, name}).Get(session)
if err != nil {
return false
}
DeleteBeegoSession([]string{sessionId})
session.SessionId = util.DeleteVal(session.SessionId, sessionId)
if len(session.SessionId) < 1 {
affected, _ := adapter.Engine.ID(core.PK{owner, name}).Delete(session)
return affected != 0
} else {
affected, _ := adapter.Engine.ID(core.PK{owner, name}).Update(session)
return affected != 0
}
}
func DeleteBeegoSession(sessionIds []string) {
for _, sessionId := range sessionIds {
err := beego.GlobalSessions.GetProvider().SessionDestroy(sessionId)
if err != nil {
return
}
}
}
func GetSessions(owner string) []*Session {
sessions := []*Session{}
var err error
if owner != "" {
err = adapter.Engine.Desc("created_time").Where("owner = ?", owner).Find(&sessions)
} else {
err = adapter.Engine.Desc("created_time").Find(&sessions)
}
if err != nil {
panic(err)
}
return sessions
}
func GetPaginationSessions(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Session {
sessions := []*Session{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&sessions)
if err != nil {
panic(err)
}
return sessions
}
func GetSessionCount(owner, field, value string) int {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Session{})
if err != nil {
panic(err)
}
return int(count)
}

View File

@ -529,6 +529,9 @@ func AddUsersInBatch(users []*User) bool {
}
func DeleteUser(user *User) bool {
// Forced offline the user first
DeleteSession(user.GetId())
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Delete(&User{})
if err != nil {
panic(err)

View File

@ -164,6 +164,9 @@ func initAPI() {
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")
beego.Router("/api/add-record", &controllers.ApiController{}, "POST:AddRecord")
beego.Router("/api/get-sessions", &controllers.ApiController{}, "GET:GetSessions")
beego.Router("/api/delete-session", &controllers.ApiController{}, "POST:DeleteSession")
beego.Router("/api/get-webhooks", &controllers.ApiController{}, "GET:GetWebhooks")
beego.Router("/api/get-webhook", &controllers.ApiController{}, "GET:GetWebhook")
beego.Router("/api/update-webhook", &controllers.ApiController{}, "POST:UpdateWebhook")

25
util/slice.go Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package util
func DeleteVal(values []string, val string) []string {
newValues := []string{}
for _, v := range values {
if v != val {
newValues = append(newValues, v)
}
}
return newValues
}

View File

@ -9,7 +9,7 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"antd": "5.0.5",
"antd": "5.1.2",
"codemirror": "^5.61.1",
"copy-to-clipboard": "^3.3.1",
"core-js": "^3.25.0",

View File

@ -260,6 +260,13 @@ class AdapterListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -70,6 +70,7 @@ import AdapterListPage from "./AdapterListPage";
import AdapterEditPage from "./AdapterEditPage";
import {withTranslation} from "react-i18next";
import SelectThemeBox from "./SelectThemeBox";
import SessionListPage from "./SessionListPage";
const {Header, Footer, Content} = Layout;
@ -421,6 +422,10 @@ class App extends Component {
"/tokens"
));
res.push(Setting.getItem(<Link to="/sessions">{i18next.t("general:Sessions")}</Link>,
"/sessions"
));
res.push(Setting.getItem(<Link to="/webhooks">{i18next.t("general:Webhooks")}</Link>,
"/webhooks"
));
@ -517,6 +522,7 @@ class App extends Component {
<Route exact path="/ldap/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapEditPage account={this.state.account} {...props} />)} />
<Route exact path="/ldap/sync/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapSyncPage account={this.state.account} {...props} />)} />
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)} />
<Route exact path="/sessions" render={(props) => this.renderLoginIfNotLoggedIn(<SessionListPage account={this.state.account} {...props} />)} />
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)} />
<Route exact path="/webhooks" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookListPage account={this.state.account} {...props} />)} />
<Route exact path="/webhooks/:webhookName" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookEditPage account={this.state.account} {...props} />)} />

View File

@ -13,7 +13,7 @@
// limitations under the License.
import React from "react";
import {Button, Card, Col, Input, Popover, Radio, Row, Select, Switch, Upload} from "antd";
import {Button, Card, Col, Input, Popover, Radio, Result, Row, Select, Switch, Upload} from "antd";
import {CopyOutlined, LinkOutlined, UploadOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as CertBackend from "./backend/CertBackend";
@ -103,6 +103,7 @@ class ApplicationEditPage extends React.Component {
uploading: false,
mode: props.location.mode !== undefined ? props.location.mode : "edit",
samlMetadata: null,
isAuthorized: true,
};
}
@ -129,9 +130,15 @@ class ApplicationEditPage extends React.Component {
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
if (res?.status === "error") {
this.setState({
isAuthorized: false,
});
} else {
this.setState({
organizations: (res.msg === undefined) ? res : [],
});
}
});
}
@ -838,6 +845,17 @@ class ApplicationEditPage extends React.Component {
}
render() {
if (!this.state.isAuthorized) {
return (
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);
}
return (
<div>
{

View File

@ -14,7 +14,7 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, List, Popconfirm, Row, Table, Tooltip} from "antd";
import {Button, Col, List, Popconfirm, Result, Row, Table, Tooltip} from "antd";
import {EditOutlined} from "@ant-design/icons";
import moment from "moment";
import * as Setting from "./Setting";
@ -36,6 +36,7 @@ class ApplicationListPage extends BaseListPage {
loading: false,
searchText: "",
searchedColumn: "",
isAuthorized: true,
};
}
@ -258,6 +259,17 @@ class ApplicationListPage extends BaseListPage {
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
};
if (!this.state.isAuthorized) {
return (
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);
}
return (
<div>
<Table scroll={{x: "max-content"}} columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={paginationProps}
@ -292,6 +304,13 @@ class ApplicationListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -13,9 +13,10 @@
// limitations under the License.
import React from "react";
import {Button, Input, Space} from "antd";
import {Button, Input, Result, Space} from "antd";
import {SearchOutlined} from "@ant-design/icons";
import Highlighter from "react-highlight-words";
import i18next from "i18next";
class BaseListPage extends React.Component {
constructor(props) {
@ -127,6 +128,17 @@ class BaseListPage extends React.Component {
};
render() {
if (!this.state.isAuthorized) {
return (
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);
}
return (
<div>
{

View File

@ -227,6 +227,13 @@ class CertListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -200,6 +200,13 @@ class ModelListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -251,7 +251,7 @@ class OrganizationListPage extends BaseListPage {
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page.")}
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);

View File

@ -278,6 +278,13 @@ class PaymentListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -358,6 +358,13 @@ class PermissionListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -295,6 +295,13 @@ class ProductListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -14,7 +14,7 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Popconfirm, Table} from "antd";
import {Button, Popconfirm, Result, Table} from "antd";
import moment from "moment";
import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend";
@ -36,6 +36,7 @@ class ProviderListPage extends BaseListPage {
loading: false,
searchText: "",
searchedColumn: "",
isAuthorized: true,
};
}
newProvider() {
@ -227,6 +228,17 @@ class ProviderListPage extends BaseListPage {
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
};
if (!this.state.isAuthorized) {
return (
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);
}
return (
<div>
<Table scroll={{x: "max-content"}} columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={paginationProps}
@ -268,6 +280,13 @@ class ProviderListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -222,6 +222,13 @@ class RecordListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.data.includes("Please login first")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -13,7 +13,7 @@
// limitations under the License.
import React from "react";
import {Button, Popconfirm, Table, Upload} from "antd";
import {Button, Popconfirm, Result, Table, Upload} from "antd";
import {UploadOutlined} from "@ant-design/icons";
import copy from "copy-to-clipboard";
import * as Setting from "./Setting";
@ -37,6 +37,7 @@ class ResourceListPage extends BaseListPage {
searchedColumn: "",
fileList: [],
uploading: false,
isAuthorized: true,
};
}
@ -272,6 +273,17 @@ class ResourceListPage extends BaseListPage {
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
};
if (!this.state.isAuthorized) {
return (
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);
}
return (
<div>
<Table scroll={{x: "max-content"}} columns={columns} dataSource={resources} rowKey="name" size="middle" bordered pagination={paginationProps}
@ -308,6 +320,13 @@ class ResourceListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.data.includes("Please login first")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -231,6 +231,13 @@ class RoleListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

162
web/src/SessionListPage.js Normal file
View File

@ -0,0 +1,162 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import BaseListPage from "./BaseListPage";
import * as Setting from "./Setting";
import i18next from "i18next";
import {Link} from "react-router-dom";
import {Button, Popconfirm, Table, Tag} from "antd";
import React from "react";
import * as SessionBackend from "./backend/SessionBackend";
class SessionListPage extends BaseListPage {
deleteSession(i) {
SessionBackend.deleteSession(this.state.data[i])
.then((res) => {
if (res.status === "ok") {
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
this.setState({
data: Setting.deleteRow(this.state.data, i),
pagination: {total: this.state.pagination.total - 1},
});
} else {
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
}
})
.catch(error => {
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
});
}
renderTable(sessions) {
const columns = [
{
title: i18next.t("general:Name"),
dataIndex: "name",
key: "name",
width: "150px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("name"),
},
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "organization",
width: "110px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",
key: "createdTime",
width: "180px",
sorter: true,
render: (text, record, index) => {
return Setting.getFormattedDate(text);
},
},
{
title: i18next.t("general:Session ID"),
dataIndex: "sessionId",
key: "sessionId",
width: "180px",
sorter: true,
render: (text, record, index) => {
return text.map((item, index) =>
<Tag key={index}>{item}</Tag>
);
},
},
{
title: i18next.t("general:Action"),
dataIndex: "",
key: "op",
width: "70px",
fixed: (Setting.isMobile()) ? "false" : "right",
render: (text, record, index) => {
return (
<div>
<Popconfirm
title={`Sure to delete session: ${record.name} ?`}
onConfirm={() => this.deleteSession(index)}
>
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
</Popconfirm>
</div>
);
},
},
];
const paginationProps = {
total: this.state.pagination.total,
showQuickJumper: true,
showSizeChanger: true,
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
};
return (
<div>
<Table scroll={{x: "max-content"}} columns={columns} dataSource={sessions} rowKey="name" size="middle" bordered pagination={paginationProps}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
</div>
);
}
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.contentType !== undefined && params.contentType !== null) {
field = "contentType";
value = params.contentType;
}
this.setState({loading: true});
SessionBackend.getSessions("", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
.then((res) => {
if (res.status === "ok") {
this.setState({
loading: false,
data: res.data,
pagination: {
...params.pagination,
total: res.data2,
},
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};
}
export default SessionListPage;

View File

@ -45,9 +45,9 @@ export const Countries = [{label: "English", key: "en", country: "US", alt: "Eng
const {defaultAlgorithm, darkAlgorithm, compactAlgorithm} = theme;
export const Themes = [{label: "Dark", key: "Dark", style: darkAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/dark.svg`},
{label: "Compact", key: "Compact", style: compactAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/compact.svg`},
{label: "Default", key: "Default", style: defaultAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/light.svg`},
export const Themes = [{label: i18next.t("general:Dark"), key: "Dark", style: darkAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/dark.svg`},
{label: i18next.t("general:Compact"), key: "Compact", style: compactAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/compact.svg`},
{label: i18next.t("general:Default"), key: "Default", style: defaultAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/light.svg`},
];
export const OtherProviderInfo = {

View File

@ -288,6 +288,13 @@ class SyncerListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -253,6 +253,13 @@ class TokenListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -14,7 +14,7 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Popconfirm, Switch, Table, Upload} from "antd";
import {Button, Popconfirm, Result, Switch, Table, Upload} from "antd";
import {UploadOutlined} from "@ant-design/icons";
import moment from "moment";
import * as OrganizationBackend from "./backend/OrganizationBackend";
@ -38,6 +38,7 @@ class UserListPage extends BaseListPage {
loading: false,
searchText: "",
searchedColumn: "",
isAuthorized: true,
};
}
@ -369,6 +370,17 @@ class UserListPage extends BaseListPage {
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
};
if (!this.state.isAuthorized) {
return (
<Result
status="403"
title="403 Unauthorized"
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
/>
);
}
return (
<div>
<Table scroll={{x: "max-content"}} columns={columns} dataSource={users} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
@ -411,6 +423,13 @@ class UserListPage extends BaseListPage {
if (users.length > 0) {
this.getOrganization(users[0].owner);
}
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
} else {
@ -432,6 +451,13 @@ class UserListPage extends BaseListPage {
if (users.length > 0) {
this.getOrganization(users[0].owner);
}
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
}

View File

@ -253,6 +253,13 @@ class WebhookListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
} else {
if (res.msg.includes("Unauthorized")) {
this.setState({
loading: false,
isAuthorized: false,
});
}
}
});
};

View File

@ -0,0 +1,36 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import * as Setting from "../Setting";
export function getSessions(owner, page = "", pageSize = "", field = "", value = "", sortField = "", sortOrder = "") {
return fetch(`${Setting.ServerUrl}/api/get-sessions?owner=${owner}&p=${page}&pageSize=${pageSize}&field=${field}&value=${value}&sortField=${sortField}&sortOrder=${sortOrder}`, {
method: "GET",
credentials: "include",
headers: {
"Accept-Language": Setting.getAcceptLanguage(),
},
}).then(res => res.json());
}
export function deleteSession(session) {
return fetch(`${Setting.ServerUrl}/api/delete-session`, {
method: "POST",
credentials: "include",
body: JSON.stringify(session),
headers: {
"Accept-Language": Setting.getAcceptLanguage(),
},
}).then(res => res.json());
}

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "Roles - Tooltip",
"Save": "Speichern",
"Save & Exit": "Speichern & Beenden",
"Session ID": "Session ID",
"Sessions": "Sessions",
"Signin URL": "Anmelde-URL",
"Signin URL - Tooltip": "sign in url",
"Signup URL": "Registrierungs-URL",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "Signup application - Tooltip",
"Sorry, the page you visited does not exist.": "Die von Ihnen besuchte Seite existiert leider nicht.",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
"Sorry, you do not have permission to access this page.": "Sorry, you do not have permission to access this page.",
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State - Tooltip",
"Successfully added": "Successfully added",

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "Roles - Tooltip",
"Save": "Save",
"Save & Exit": "Save & Exit",
"Session ID": "Session ID",
"Sessions": "Sessions",
"Signin URL": "Signin URL",
"Signin URL - Tooltip": "Signin URL - Tooltip",
"Signup URL": "Signup URL",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "Signup application - Tooltip",
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
"Sorry, you do not have permission to access this page.": "Sorry, you do not have permission to access this page.",
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State - Tooltip",
"Successfully added": "Successfully added",

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "Roles - Tooltip",
"Save": "Enregistrer",
"Save & Exit": "Enregistrer & Quitter",
"Session ID": "Session ID",
"Sessions": "Sessions",
"Signin URL": "URL de connexion",
"Signin URL - Tooltip": "sign in url",
"Signup URL": "URL d'inscription",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "Signup application - Tooltip",
"Sorry, the page you visited does not exist.": "Désolé, la page que vous avez visitée n'existe pas.",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
"Sorry, you do not have permission to access this page.": "Désolé, vous n'avez pas la permission d'accéder à cette page.",
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State - Tooltip",
"Successfully added": "Successfully added",

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "Roles - Tooltip",
"Save": "保存",
"Save & Exit": "保存して終了",
"Session ID": "Session ID",
"Sessions": "Sessions",
"Signin URL": "サインインURL",
"Signin URL - Tooltip": "sign in url",
"Signup URL": "サインアップURL",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "Signup application - Tooltip",
"Sorry, the page you visited does not exist.": "申し訳ありませんが、訪問したページは存在しません。",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
"Sorry, you do not have permission to access this page.": "申し訳ありませんが、このページにアクセスする権限がありません。",
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State - Tooltip",
"Successfully added": "Successfully added",

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "Roles - Tooltip",
"Save": "Save",
"Save & Exit": "Save & Exit",
"Session ID": "Session ID",
"Sessions": "Sessions",
"Signin URL": "Signin URL",
"Signin URL - Tooltip": "sign in url",
"Signup URL": "Signup URL",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "Signup application - Tooltip",
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
"Sorry, you do not have permission to access this page.": "Sorry, you do not have permission to access this page.",
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State - Tooltip",
"Successfully added": "Successfully added",

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "Roles - Tooltip",
"Save": "Сохранить",
"Save & Exit": "Сохранить и выйти",
"Session ID": "Session ID",
"Sessions": "Sessions",
"Signin URL": "URL входа",
"Signin URL - Tooltip": "sign in url",
"Signup URL": "URL регистрации",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "Signup application - Tooltip",
"Sorry, the page you visited does not exist.": "Извините, посещенная вами страница не существует.",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
"Sorry, you do not have permission to access this page.": "Извините, вы не имеете права доступа к этой странице.",
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
"State": "State",
"State - Tooltip": "State - Tooltip",
"Successfully added": "Successfully added",

View File

@ -236,6 +236,8 @@
"Roles - Tooltip": "角色",
"Save": "保存",
"Save & Exit": "保存 & 退出",
"Session ID": "会话 ID",
"Sessions": "会话",
"Signin URL": "登录URL",
"Signin URL - Tooltip": "用户的登录地址",
"Signup URL": "注册URL",
@ -244,7 +246,7 @@
"Signup application - Tooltip": "表示用户注册时通过哪个应用注册的",
"Sorry, the page you visited does not exist.": "抱歉,您访问的页面不存在",
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "抱歉,您访问的用户不存在或您无权访问该用户",
"Sorry, you do not have permission to access this page.": "抱歉,您无权访问该页面",
"Sorry, you do not have permission to access this page or logged in status invalid.": "抱歉,您无权访问该页面或登录状态失效",
"State": "状态",
"State - Tooltip": "状态",
"Successfully added": "添加成功",

View File

@ -17,17 +17,17 @@
dependencies:
"@ctrl/tinycolor" "^3.4.0"
"@ant-design/cssinjs@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.1.0.tgz#d7b5e0811e8241e66c2812c179bd7b7ef961f7ab"
integrity sha512-9kfWCnlcWZLMc184HL7zGUU3odKo/5HBMNxDxhSds2DoIzi/ojmmOU1A1butWVDSPcAbLyNQ85vxUI8mkkHrlA==
"@ant-design/cssinjs@^1.3.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.4.0.tgz#c66aa468322d6fdec7f43c8ebd0f3171630d2711"
integrity sha512-siFyX5VyiJWKBQAffI8zE0WZ4OWfI35QnqesbtHaVg49QxHFAcFN9VbJ+Qoos24JxABcxfopEwMWe2joZ2QVBQ==
dependencies:
"@babel/runtime" "^7.11.1"
"@emotion/hash" "^0.8.0"
"@emotion/unitless" "^0.7.5"
classnames "^2.3.1"
csstype "^3.0.10"
rc-util "^5.24.2"
rc-util "^5.27.0"
stylis "^4.0.13"
"@ant-design/icons-svg@^4.2.1":
@ -46,16 +46,16 @@
classnames "^2.2.6"
rc-util "^5.9.4"
"@ant-design/react-slick@~0.29.1":
version "0.29.2"
resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-0.29.2.tgz#53e6a7920ea3562eebb304c15a7fc2d7e619d29c"
integrity sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==
"@ant-design/react-slick@~1.0.0":
version "1.0.0"
resolved "https://registry.npmmirror.com/@ant-design/react-slick/-/react-slick-1.0.0.tgz#4696eecaa2dea0429e47ae24c267015cfd6df35c"
integrity sha512-OKxZsn8TAf8fYxP79rDXgLs9zvKMTslK6dJ4iLhDXOujUqC5zJPBRszyrcEHXcMPOm1Sgk40JgyF3yiL/Swd7w==
dependencies:
"@babel/runtime" "^7.10.4"
classnames "^2.2.5"
json2mq "^0.2.0"
lodash "^4.17.21"
resize-observer-polyfill "^1.5.1"
throttle-debounce "^5.0.0"
"@apideck/better-ajv-errors@^0.3.1":
version "0.3.6"
@ -1482,6 +1482,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.20.0":
version "7.20.7"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd"
integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/template@^7.18.10":
version "7.18.10"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
@ -2112,10 +2119,10 @@
classnames "^2.3.2"
rc-util "^5.24.4"
"@rc-component/tour@~1.0.1-2":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@rc-component/tour/-/tour-1.0.1.tgz#aa8ea890462eed43ee0fb33543995b342d87ee76"
integrity sha512-azbiWP0UwGDeWfGS7oCR0gHhbWJW7O6g4wFUaC19oY+eCjmY0RPY0u0p93BJ89D8NoxP9LhSSBuU/YQA5H5kbA==
"@rc-component/tour@~1.1.0":
version "1.1.0"
resolved "https://registry.npmmirror.com/@rc-component/tour/-/tour-1.1.0.tgz#17b43b5c0bdfb6a8ab3027b1977d960952616d9e"
integrity sha512-Cy45VnNEDq6DLF5eKonIflObDfofbPq7AJpSf18qLN+j9+wW+sNlRv3JnCMDUsCdhSlnM4+yJ1RMokKp9GCpOQ==
dependencies:
"@babel/runtime" "^7.18.0"
"@rc-component/portal" "^1.0.0-9"
@ -3141,57 +3148,57 @@ ansi-styles@^6.0.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3"
integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==
antd@5.0.5:
version "5.0.5"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.0.5.tgz#16f0ade8b2d2ea9f7bd47a8e0af81884dc504a7d"
integrity sha512-8jWUjZ65urNHZPg9/Ywa9V0PlNfqjhewKgSPF4nraN9X5v434lDJkRBQGN7meNixQ6aM2B/JhXPm9UaJ/tAQmA==
antd@5.1.2:
version "5.1.2"
resolved "https://registry.npmmirror.com/antd/-/antd-5.1.2.tgz#6c57c375e193ff77be1a8f6a132f5aacaf21d037"
integrity sha512-B6R6Bm0jIOb6v3JhS4DLKghJWqX0OufCOy99+R6F7QtGjbV/0wG/0rqH3DiQ4BHNIHsL+SDUYti9o3cT28lPww==
dependencies:
"@ant-design/colors" "^6.0.0"
"@ant-design/cssinjs" "^1.0.0"
"@ant-design/cssinjs" "^1.3.0"
"@ant-design/icons" "^4.7.0"
"@ant-design/react-slick" "~0.29.1"
"@ant-design/react-slick" "~1.0.0"
"@babel/runtime" "^7.18.3"
"@ctrl/tinycolor" "^3.4.0"
"@rc-component/tour" "~1.0.1-2"
"@rc-component/tour" "~1.1.0"
classnames "^2.2.6"
copy-to-clipboard "^3.2.0"
dayjs "^1.11.1"
lodash "^4.17.21"
rc-cascader "~3.7.0"
qrcode.react "^3.1.0"
rc-cascader "~3.8.0"
rc-checkbox "~2.3.0"
rc-collapse "~3.4.2"
rc-dialog "~9.0.2"
rc-drawer "~6.0.0"
rc-drawer "~6.1.1"
rc-dropdown "~4.0.0"
rc-field-form "~1.27.0"
rc-image "~5.12.0"
rc-image "~5.13.0"
rc-input "~0.1.4"
rc-input-number "~7.4.0"
rc-mentions "~1.13.1"
rc-menu "~9.8.0"
rc-motion "^2.6.1"
rc-notification "~5.0.0-alpha.9"
rc-notification "~5.0.0"
rc-pagination "~3.2.0"
rc-picker "~3.1.1"
rc-progress "~3.4.1"
rc-rate "~2.9.0"
rc-resize-observer "^1.2.0"
rc-segmented "~2.1.0"
rc-select "~14.1.13"
rc-select "~14.2.0"
rc-slider "~10.0.0"
rc-steps "~6.0.0-alpha.2"
rc-steps "~6.0.0"
rc-switch "~4.0.0"
rc-table "~7.26.0"
rc-tabs "~12.4.2"
rc-table "~7.28.3"
rc-tabs "~12.5.1"
rc-textarea "~0.4.5"
rc-tooltip "~5.2.0"
rc-tree "~5.7.0"
rc-tree-select "~5.5.4"
rc-tree-select "~5.6.0"
rc-trigger "^5.2.10"
rc-upload "~4.3.0"
rc-util "^5.25.2"
rc-util "^5.27.0"
scroll-into-view-if-needed "^3.0.3"
shallowequal "^1.1.0"
throttle-debounce "^5.0.0"
anymatch@^3.0.3, anymatch@~3.1.2:
version "3.1.2"
@ -8788,6 +8795,11 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
qrcode.react@^3.1.0:
version "3.1.0"
resolved "https://registry.npmmirror.com/qrcode.react/-/qrcode.react-3.1.0.tgz#5c91ddc0340f768316fbdb8fff2765134c2aecd8"
integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==
qs@6.10.3:
version "6.10.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
@ -8858,15 +8870,15 @@ rc-align@^4.0.0:
rc-util "^5.3.0"
resize-observer-polyfill "^1.5.1"
rc-cascader@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.7.0.tgz#98134df578ce1cca22be8fb4319b04df4f3dca36"
integrity sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A==
rc-cascader@~3.8.0:
version "3.8.0"
resolved "https://registry.npmmirror.com/rc-cascader/-/rc-cascader-3.8.0.tgz#5eaca8998b2e3f5692d13f16bfe2346eccc87c6a"
integrity sha512-zCz/NzsNRQ1TIfiR3rQNxjeRvgRHEkNdo0FjHQZ6Ay6n4tdCmMrM7+81ThNaf21JLQ1gS2AUG2t5uikGV78obA==
dependencies:
"@babel/runtime" "^7.12.5"
array-tree-filter "^2.1.0"
classnames "^2.3.1"
rc-select "~14.1.0"
rc-select "~14.2.0"
rc-tree "~5.7.0"
rc-util "^5.6.1"
@ -8900,10 +8912,10 @@ rc-dialog@~9.0.0, rc-dialog@~9.0.2:
rc-motion "^2.3.0"
rc-util "^5.21.0"
rc-drawer@~6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/rc-drawer/-/rc-drawer-6.0.1.tgz#437040ac7ba305b5d964ba51e88f30797671e8f8"
integrity sha512-ibWXGf8I+KRPXE03X4s0/xXzQI37YWXUV+oPy+R29GKxkjr98UTMgwvoQDKlZTm5AiaRuVFqhTKm0kNHqJh+TQ==
rc-drawer@~6.1.1:
version "6.1.2"
resolved "https://registry.npmmirror.com/rc-drawer/-/rc-drawer-6.1.2.tgz#032918a21bfa8a7d9e52ada1e7b8ed08c0ae6346"
integrity sha512-mYsTVT8Amy0LRrpVEv7gI1hOjtfMSO/qHAaCDzFx9QBLnms3cAQLJkaxRWM+Eq99oyLhU/JkgoqTg13bc4ogOQ==
dependencies:
"@babel/runtime" "^7.10.1"
"@rc-component/portal" "^1.0.0-6"
@ -8930,15 +8942,16 @@ rc-field-form@~1.27.0:
async-validator "^4.1.0"
rc-util "^5.8.0"
rc-image@~5.12.0:
version "5.12.1"
resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-5.12.1.tgz#1560eda00ef9d33ebdb3c8c74ab134eb00f973d4"
integrity sha512-FMldR/ODwQmlFlhjR4c6hsOHmnn4s9CxmW7PR/9XCYE1XHlGJ5OkSWOtJruoaLjVwt2tQYDRnLANf/mKZ9ReUg==
rc-image@~5.13.0:
version "5.13.0"
resolved "https://registry.npmmirror.com/rc-image/-/rc-image-5.13.0.tgz#1ed9b852a40b5eff34786ba7d2f0e9d26eeab874"
integrity sha512-iZTOmw5eWo2+gcrJMMcnd7SsxVHl3w5xlyCgsULUdJhJbnuI8i/AL0tVOsE7aLn9VfOh1qgDT3mC2G75/c7mqg==
dependencies:
"@babel/runtime" "^7.11.2"
"@rc-component/portal" "^1.0.2"
classnames "^2.2.6"
rc-dialog "~9.0.0"
rc-motion "^2.6.2"
rc-util "^5.0.6"
rc-input-number@~7.4.0:
@ -9003,10 +9016,10 @@ rc-motion@^2.6.0, rc-motion@^2.6.1, rc-motion@^2.6.2:
classnames "^2.2.1"
rc-util "^5.21.0"
rc-notification@~5.0.0-alpha.9:
version "5.0.0-alpha.9"
resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.0.0-alpha.9.tgz#e6fbf5cc786e508f022691a61a03c0473f5ca7b0"
integrity sha512-QPvq8VHe2M0SE5DHJf7ADWlvfWKnTsj5FVxcu39gdjX98kKmi+BHY1eTPAQkkdGqd6ZXv6xXHl8qKHyWhQcFPA==
rc-notification@~5.0.0:
version "5.0.0"
resolved "https://registry.npmmirror.com/rc-notification/-/rc-notification-5.0.0.tgz#afdaa86fdf9c96e767690f2e891747beb3100d19"
integrity sha512-mTqMD5Uip1tJhX74opHrmC/CG1wtkxuCcaiCaPDFWPJ/o50OgYYi3nPV10Pwgb8mK8dqg9DDQKISWAcKmcVlXQ==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "2.x"
@ -9090,10 +9103,10 @@ rc-segmented@~2.1.0:
rc-motion "^2.4.4"
rc-util "^5.17.0"
rc-select@~14.1.0:
version "14.1.8"
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.1.8.tgz#986dc9194212ea56c1acd8317a956c7c88e94f4a"
integrity sha512-1kU/7ZCggyR5r5jVEQfAiN6Sq3LGLD2b6FNz5GWel3TOEQZYyDn0o4FAoIRqS6Y5ldWmkFxtd834ilPnG6NV6w==
rc-select@~14.2.0:
version "14.2.0"
resolved "https://registry.npmmirror.com/rc-select/-/rc-select-14.2.0.tgz#60e83a7d5a5dae7fd9e3918d9b209074ea2c92d4"
integrity sha512-tvxHmbAA0EIhBkB7dyaRhcBUIWHocQbUFY/fBlezj2jg5p65a5VQ/UhBg2I9TA1wjpsr5CCx0ruZPkYcUMjDoQ==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "2.x"
@ -9101,20 +9114,7 @@ rc-select@~14.1.0:
rc-overflow "^1.0.0"
rc-trigger "^5.0.4"
rc-util "^5.16.1"
rc-virtual-list "^3.2.0"
rc-select@~14.1.13:
version "14.1.16"
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.1.16.tgz#0cc4b5a1fc551a2db7c96bc1ece0896317ecdd47"
integrity sha512-71XLHleuZmufpdV2vis5oituRkhg2WNvLpVMJBGWRar6WGAVOHXaY9DR5HvwWry3EGTn19BqnL6Xbybje6f8YA==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "2.x"
rc-motion "^2.0.1"
rc-overflow "^1.0.0"
rc-trigger "^5.0.4"
rc-util "^5.16.1"
rc-virtual-list "^3.2.0"
rc-virtual-list "^3.4.13"
rc-slider@~10.0.0:
version "10.0.0"
@ -9127,10 +9127,10 @@ rc-slider@~10.0.0:
rc-util "^5.18.1"
shallowequal "^1.1.0"
rc-steps@~6.0.0-alpha.2:
version "6.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/rc-steps/-/rc-steps-6.0.0-alpha.2.tgz#505e64177111becd911cef4d24f15477438c9e59"
integrity sha512-d/GPx7ATlPbtFeOVt5FB19W11OBCmRd7lLknt4aSoCI6ukwJqpEhWu2INN4pDOQqN04y3PDsWl1q9hnw+ZC5AA==
rc-steps@~6.0.0:
version "6.0.0"
resolved "https://registry.npmmirror.com/rc-steps/-/rc-steps-6.0.0.tgz#f7148f8097d5d135f19b96c1b4f4b50ad6093753"
integrity sha512-+KfMZIty40mYCQSDvYbZ1jwnuObLauTiIskT1hL4FFOBHP6ZOr8LK0m143yD3kEN5XKHSEX1DIwCj3AYZpoeNQ==
dependencies:
"@babel/runtime" "^7.16.7"
classnames "^2.2.3"
@ -9145,10 +9145,10 @@ rc-switch@~4.0.0:
classnames "^2.2.1"
rc-util "^5.0.1"
rc-table@~7.26.0:
version "7.26.0"
resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.26.0.tgz#9d517e7fa512e7571fdcc453eb1bf19edfac6fbc"
integrity sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ==
rc-table@~7.28.3:
version "7.28.3"
resolved "https://registry.npmmirror.com/rc-table/-/rc-table-7.28.3.tgz#826c789b1cf8ed93137aa488919cf6d9a5f0b9bc"
integrity sha512-jiPtBDqcs0wF0KOJgkhDgxN6+vq4jHbteddE15IR6RajlVkAk+kRIecyBY28b+vg199yQiu/NGuSRKJKEGOWBQ==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "^2.2.5"
@ -9156,10 +9156,10 @@ rc-table@~7.26.0:
rc-util "^5.22.5"
shallowequal "^1.1.0"
rc-tabs@~12.4.2:
version "12.4.2"
resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-12.4.2.tgz#487a1b3f8d8cf0bfc121224013dab00d4a8e0532"
integrity sha512-FFlGwuTjQUznWzJtyhmHc6KAp5lRQFxKUv9Aj1UtsOYe2e7WGmuzcrd+/LQchuPe0VjhaZPdGkmFGcqGqNO6ow==
rc-tabs@~12.5.1:
version "12.5.5"
resolved "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-12.5.5.tgz#8b34c2ea58f7d9fe141de252f24e69b26df34221"
integrity sha512-Y0k+JK4IN2cr0+MstkYK6MryvURhUc8JvHDCXujbUA6zHVTnWeTikOspGgvHPrlfZRl7WS+DPyMdEFE6RwlueQ==
dependencies:
"@babel/runtime" "^7.11.2"
classnames "2.x"
@ -9197,14 +9197,14 @@ rc-tooltip@~5.2.0:
classnames "^2.3.1"
rc-trigger "^5.0.0"
rc-tree-select@~5.5.4:
version "5.5.5"
resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-5.5.5.tgz#d28b3b45da1e820cd21762ba0ee93c19429bb369"
integrity sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw==
rc-tree-select@~5.6.0:
version "5.6.0"
resolved "https://registry.npmmirror.com/rc-tree-select/-/rc-tree-select-5.6.0.tgz#f34147f4c14341430bcece481804496d0abd3371"
integrity sha512-XG6pu0a9l6+mzhQqUYfR2VIONbe/3LjVc3wKt28k6uBMZsI1j+SSxRyt/7jWRq8Kok8jHJBQASlDg6ehr9Sp0w==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "2.x"
rc-select "~14.1.0"
rc-select "~14.2.0"
rc-tree "~5.7.0"
rc-util "^5.16.1"
@ -9259,7 +9259,7 @@ rc-util@^5.0.1, rc-util@^5.0.6, rc-util@^5.12.0, rc-util@^5.15.0, rc-util@^5.16.
react-is "^16.12.0"
shallowequal "^1.1.0"
rc-util@^5.16.0, rc-util@^5.24.2, rc-util@^5.24.4:
rc-util@^5.16.0, rc-util@^5.24.4:
version "5.24.8"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.24.8.tgz#4d234a5263f42080fb39b9c1b36f9df73af3497b"
integrity sha512-AS222gRVeH5RDdaRUd9ur9/E9MMQn5sZA3d4Z1vGU7JXW9dxD9kPijax00RG+dU2EJTfwySstFLDoSqpAPMNKw==
@ -9277,16 +9277,25 @@ rc-util@^5.21.2, rc-util@^5.23.0:
react-is "^16.12.0"
shallowequal "^1.1.0"
rc-util@^5.25.2:
version "5.25.2"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.25.2.tgz#09fd3ce88da7d2149427d51e40a84e3527f5a263"
integrity sha512-OyCO675K/rh4zG3e+LYaHw54WQFEYGV9ibkGawQxqCvf0G0PzUrLQjgZ6SfoHORdbEKN7eQMFn3hHQyA/P8Y5Q==
rc-util@^5.27.0:
version "5.27.1"
resolved "https://registry.npmmirror.com/rc-util/-/rc-util-5.27.1.tgz#d12f02b9577b04299c0f1a235c8acbcf56e2824b"
integrity sha512-PsjHA+f+KBCz+YTZxrl3ukJU5RoNKoe3KSNMh0xGiISbR67NaM9E9BiMjCwxa3AcCUOg/rZ+V0ZKLSimAA+e3w==
dependencies:
"@babel/runtime" "^7.18.3"
react-is "^16.12.0"
shallowequal "^1.1.0"
rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.8:
rc-virtual-list@^3.4.13:
version "3.4.13"
resolved "https://registry.npmmirror.com/rc-virtual-list/-/rc-virtual-list-3.4.13.tgz#20acc934b263abcf7b7c161f50ef82281b2f7e8d"
integrity sha512-cPOVDmcNM7rH6ANotanMDilW/55XnFPw0Jh/GQYtrzZSy3AmWvCnqVNyNC/pgg3lfVmX2994dlzAhuUrd4jG7w==
dependencies:
"@babel/runtime" "^7.20.0"
classnames "^2.2.6"
rc-resize-observer "^1.0.0"
rc-util "^5.15.0"
rc-virtual-list@^3.4.8:
version "3.4.8"
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.4.8.tgz#c24c10c6940546b7e2a5e9809402c6716adfd26c"
integrity sha512-qSN+Rv4i/E7RCTvTMr1uZo7f3crJJg/5DekoCagydo9zsXrxj07zsFSxqizqW+ldGA16lwa8So/bIbV9Ofjddg==
@ -10738,6 +10747,11 @@ throat@^6.0.1:
resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
throttle-debounce@^5.0.0:
version "5.0.0"
resolved "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz#a17a4039e82a2ed38a5e7268e4132d6960d41933"
integrity sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==
through@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"