mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 20:50:19 +08:00
@ -29,6 +29,7 @@ import ApplicationListPage from "./ApplicationListPage";
|
||||
import ApplicationEditPage from "./ApplicationEditPage";
|
||||
import TokenListPage from "./TokenListPage";
|
||||
import TokenEditPage from "./TokenEditPage";
|
||||
import RecordListPage from "./RecordListPage";
|
||||
import AccountPage from "./account/AccountPage";
|
||||
import HomePage from "./basic/HomePage";
|
||||
import CustomGithubCorner from "./CustomGithubCorner";
|
||||
@ -317,6 +318,13 @@ class App extends Component {
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
);
|
||||
res.push(
|
||||
<Menu.Item key="7">
|
||||
<Link to="/records">
|
||||
{i18next.t("general:Records")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
);
|
||||
}
|
||||
res.push(
|
||||
<Menu.Item key="6" onClick={() => window.location.href = "/swagger"}>
|
||||
@ -392,6 +400,7 @@ class App extends Component {
|
||||
<Route exact path="/applications/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)}/>
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
|
159
web/src/RecordListPage.js
Normal file
159
web/src/RecordListPage.js
Normal file
@ -0,0 +1,159 @@
|
||||
// Copyright 2021 The casbin 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 React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Col, Row, Table} from 'antd';
|
||||
import * as Setting from "./Setting";
|
||||
import * as RecordBackend from "./backend/RecordBackend";
|
||||
import i18next from "i18next";
|
||||
|
||||
class RecordListPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
records: null,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getRecords();
|
||||
}
|
||||
|
||||
getRecords() {
|
||||
RecordBackend.getRecords()
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
records: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
newRecord() {
|
||||
return {
|
||||
id : "",
|
||||
Record:{
|
||||
clientIp:"",
|
||||
timestamp:"",
|
||||
organization:"",
|
||||
username:"",
|
||||
requestUri:"",
|
||||
action:"login",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
renderTable(records) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Client ip"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.Record.clientIp.localeCompare(b.Record.clientIp),
|
||||
render: (text, record, index) => {
|
||||
return text.clientIp;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Timestamp"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.timestamp.localeCompare(b.Record.timestamp),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text.timestamp);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '120px',
|
||||
sorter: (a, b) => a.Record.organization.localeCompare(b.Record.organization),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text.organization}`}>
|
||||
{text.organization}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Username"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.username.localeCompare(b.Record.username),
|
||||
render: (text, record, index) => {
|
||||
return text.username;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Request uri"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.requestUri.localeCompare(b.Record.requestUri),
|
||||
render: (text, record, index) => {
|
||||
return text.requestUri;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: 'Record',
|
||||
key: 'Record',
|
||||
width: '160px',
|
||||
sorter: (a, b) => a.Record.action.localeCompare(b.Record.action),
|
||||
render: (text, record, index) => {
|
||||
return text.action;
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table columns={columns} dataSource={records} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
|
||||
title={() => (
|
||||
<div>
|
||||
{i18next.t("general:Records")}
|
||||
</div>
|
||||
)}
|
||||
loading={records === null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.records)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default RecordListPage;
|
22
web/src/backend/RecordBackend.js
Normal file
22
web/src/backend/RecordBackend.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2021 The casbin 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 getRecords() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-records`, {
|
||||
method: "GET",
|
||||
credentials: "include"
|
||||
}).then(res => res.json());
|
||||
}
|
@ -13,6 +13,11 @@
|
||||
"User": "User",
|
||||
"Applications": "Applications",
|
||||
"Application": "Application",
|
||||
"Records": "Records",
|
||||
"Client ip": "Client ip",
|
||||
"Timestamp": "Timestamp",
|
||||
"Username": "Username",
|
||||
"Request uri": "Request uri",
|
||||
"Save": "Save",
|
||||
"Add": "Add",
|
||||
"Action": "Action",
|
||||
|
Reference in New Issue
Block a user