Change CRLF to LF.

This commit is contained in:
Yang Luo 2021-02-13 12:15:19 +08:00
parent 7304e62f95
commit 09b39d69f6
19 changed files with 13694 additions and 13694 deletions

View File

@ -1,224 +1,224 @@
import React from "react";
import {Button, Card, Col, Input, Row, Select} from 'antd';
import {LinkOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import Face from "./Face";
const { Option } = Select;
class ApplicationEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
applicationName: props.match.params.applicationName,
application: null,
organizations: [],
providers: [],
};
}
componentWillMount() {
this.getApplication();
this.getOrganizations();
this.getProviders();
}
getApplication() {
ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => {
this.setState({
application: application,
});
});
}
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: res,
});
});
}
getProviders() {
ProviderBackend.getProviders("admin")
.then((res) => {
this.setState({
providers: res,
});
});
}
parseApplicationField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateApplicationField(key, value) {
value = this.parseApplicationField(key, value);
let application = this.state.application;
application[key] = value;
this.setState({
application: application,
});
}
renderApplication() {
return (
<Card size="small" title={
<div>
Edit Application&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.application.name} onChange={e => {
this.updateApplicationField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.application.displayName} onChange={e => {
this.updateApplicationField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Logo:
</Col>
<Col span={22} >
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={1}>
URL:
</Col>
<Col span={23} >
<Input prefix={<LinkOutlined/>} value={this.state.application.logo} onChange={e => {
this.updateApplicationField('logo', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={1}>
Preview:
</Col>
<Col span={23} >
<a target="_blank" href={this.state.application.logo}>
<img src={this.state.application.logo} alt={this.state.application.logo} height={90} style={{marginBottom: '20px'}}/>
</a>
</Col>
</Row>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Organization:
</Col>
<Col span={22} >
<Select virtual={false} style={{width: '100%'}} value={this.state.application.organization} onChange={(value => {this.updateApplicationField('organization', value);})}>
{
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Providers:
</Col>
<Col span={22} >
<Select mode="tags" style={{width: '100%'}}
value={this.state.application.providers}
onChange={value => {
this.updateApplicationField('providers', value);
}} >
{
this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Face Preview:
</Col>
<Col span={22} >
<a style={{marginBottom: '10px'}} target="_blank" href={`/doors/${this.state.application.name}`}>
{
`${window.location.host}/doors/${this.state.application.name}`
}
</a>
<br/>
<br/>
<div style={{width: "500px", height: "600px", border: "1px solid rgb(217,217,217)"}}>
<Face application={this.state.application} />
</div>
</Col>
</Row>
</Card>
)
}
submitApplicationEdit() {
let application = Setting.deepCopy(this.state.application);
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
applicationName: this.state.application.name,
});
this.props.history.push(`/applications/${this.state.application.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateApplicationField('name', this.state.applicationName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.application !== null ? this.renderApplication() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default ApplicationEditPage;
import React from "react";
import {Button, Card, Col, Input, Row, Select} from 'antd';
import {LinkOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import Face from "./Face";
const { Option } = Select;
class ApplicationEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
applicationName: props.match.params.applicationName,
application: null,
organizations: [],
providers: [],
};
}
componentWillMount() {
this.getApplication();
this.getOrganizations();
this.getProviders();
}
getApplication() {
ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => {
this.setState({
application: application,
});
});
}
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: res,
});
});
}
getProviders() {
ProviderBackend.getProviders("admin")
.then((res) => {
this.setState({
providers: res,
});
});
}
parseApplicationField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateApplicationField(key, value) {
value = this.parseApplicationField(key, value);
let application = this.state.application;
application[key] = value;
this.setState({
application: application,
});
}
renderApplication() {
return (
<Card size="small" title={
<div>
Edit Application&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.application.name} onChange={e => {
this.updateApplicationField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.application.displayName} onChange={e => {
this.updateApplicationField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Logo:
</Col>
<Col span={22} >
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={1}>
URL:
</Col>
<Col span={23} >
<Input prefix={<LinkOutlined/>} value={this.state.application.logo} onChange={e => {
this.updateApplicationField('logo', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={1}>
Preview:
</Col>
<Col span={23} >
<a target="_blank" href={this.state.application.logo}>
<img src={this.state.application.logo} alt={this.state.application.logo} height={90} style={{marginBottom: '20px'}}/>
</a>
</Col>
</Row>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Organization:
</Col>
<Col span={22} >
<Select virtual={false} style={{width: '100%'}} value={this.state.application.organization} onChange={(value => {this.updateApplicationField('organization', value);})}>
{
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Providers:
</Col>
<Col span={22} >
<Select mode="tags" style={{width: '100%'}}
value={this.state.application.providers}
onChange={value => {
this.updateApplicationField('providers', value);
}} >
{
this.state.providers.map((provider, index) => <Option key={index} value={provider.name}>{provider.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Face Preview:
</Col>
<Col span={22} >
<a style={{marginBottom: '10px'}} target="_blank" href={`/doors/${this.state.application.name}`}>
{
`${window.location.host}/doors/${this.state.application.name}`
}
</a>
<br/>
<br/>
<div style={{width: "500px", height: "600px", border: "1px solid rgb(217,217,217)"}}>
<Face application={this.state.application} />
</div>
</Col>
</Row>
</Card>
)
}
submitApplicationEdit() {
let application = Setting.deepCopy(this.state.application);
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
applicationName: this.state.application.name,
});
this.props.history.push(`/applications/${this.state.application.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateApplicationField('name', this.state.applicationName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.application !== null ? this.renderApplication() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitApplicationEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default ApplicationEditPage;

View File

@ -1,199 +1,199 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as ApplicationBackend from "./backend/ApplicationBackend";
class ApplicationListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
applications: null,
};
}
componentWillMount() {
this.getApplications();
}
getApplications() {
ApplicationBackend.getApplications("admin")
.then((res) => {
this.setState({
applications: res,
});
});
}
newApplication() {
return {
owner: "admin", // this.props.account.applicationname,
name: `application_${this.state.applications.length}`,
createdTime: moment().format(),
displayName: `New Application - ${this.state.applications.length}`,
logo: "https://cdn.jsdelivr.net/gh/casbin/static/img/logo@2x.png",
providers: [],
}
}
addApplication() {
const newApplication = this.newApplication();
ApplicationBackend.addApplication(newApplication)
.then((res) => {
Setting.showMessage("success", `Application added successfully`);
this.setState({
applications: Setting.prependRow(this.state.applications, newApplication),
});
}
)
.catch(error => {
Setting.showMessage("error", `Application failed to add: ${error}`);
});
}
deleteApplication(i) {
ApplicationBackend.deleteApplication(this.state.applications[i])
.then((res) => {
Setting.showMessage("success", `Application deleted successfully`);
this.setState({
applications: Setting.deleteRow(this.state.applications, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `Application failed to delete: ${error}`);
});
}
renderTable(applications) {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '150px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/applications/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Logo',
dataIndex: 'logo',
key: 'logo',
width: '250px',
render: (text, record, index) => {
return (
<a target="_blank" href={text}>
<img src={text} alt={text} width={150} />
</a>
)
}
},
{
title: 'Organization',
dataIndex: 'organization',
key: 'organization',
width: '200px',
sorter: (a, b) => a.organization.localeCompare(b.organization),
render: (text, record, index) => {
return (
<a href={`/organizations/${text}`}>
{text}
</a>
)
}
},
{
title: 'Providers',
dataIndex: 'providers',
key: 'providers',
width: '200px',
sorter: (a, b) => a.providers.localeCompare(b.providers),
render: (text, record, index) => {
return (
<a href={`/providers/${text}`}>
{text}
</a>
)
}
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete application: ${record.name} ?`}
onConfirm={() => this.deleteApplication(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Applications&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addApplication.bind(this)}>Add</Button>
</div>
)}
loading={applications === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.applications)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default ApplicationListPage;
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as ApplicationBackend from "./backend/ApplicationBackend";
class ApplicationListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
applications: null,
};
}
componentWillMount() {
this.getApplications();
}
getApplications() {
ApplicationBackend.getApplications("admin")
.then((res) => {
this.setState({
applications: res,
});
});
}
newApplication() {
return {
owner: "admin", // this.props.account.applicationname,
name: `application_${this.state.applications.length}`,
createdTime: moment().format(),
displayName: `New Application - ${this.state.applications.length}`,
logo: "https://cdn.jsdelivr.net/gh/casbin/static/img/logo@2x.png",
providers: [],
}
}
addApplication() {
const newApplication = this.newApplication();
ApplicationBackend.addApplication(newApplication)
.then((res) => {
Setting.showMessage("success", `Application added successfully`);
this.setState({
applications: Setting.prependRow(this.state.applications, newApplication),
});
}
)
.catch(error => {
Setting.showMessage("error", `Application failed to add: ${error}`);
});
}
deleteApplication(i) {
ApplicationBackend.deleteApplication(this.state.applications[i])
.then((res) => {
Setting.showMessage("success", `Application deleted successfully`);
this.setState({
applications: Setting.deleteRow(this.state.applications, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `Application failed to delete: ${error}`);
});
}
renderTable(applications) {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '150px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/applications/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Logo',
dataIndex: 'logo',
key: 'logo',
width: '250px',
render: (text, record, index) => {
return (
<a target="_blank" href={text}>
<img src={text} alt={text} width={150} />
</a>
)
}
},
{
title: 'Organization',
dataIndex: 'organization',
key: 'organization',
width: '200px',
sorter: (a, b) => a.organization.localeCompare(b.organization),
render: (text, record, index) => {
return (
<a href={`/organizations/${text}`}>
{text}
</a>
)
}
},
{
title: 'Providers',
dataIndex: 'providers',
key: 'providers',
width: '200px',
sorter: (a, b) => a.providers.localeCompare(b.providers),
render: (text, record, index) => {
return (
<a href={`/providers/${text}`}>
{text}
</a>
)
}
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete application: ${record.name} ?`}
onConfirm={() => this.deleteApplication(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Applications&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addApplication.bind(this)}>Add</Button>
</div>
)}
loading={applications === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.applications)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default ApplicationListPage;

View File

@ -1,129 +1,129 @@
import React from "react";
import {Button, Checkbox, Col, Form, Input, Row} from "antd";
import {LockOutlined, UserOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as AccountBackend from "./backend/AccountBackend";
import * as Setting from "./Setting";
class Face extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
application: null,
};
}
componentWillMount() {
this.getApplication();
}
getApplication() {
ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => {
this.setState({
application: application,
});
});
}
getApplicationObj() {
if (this.props.application !== undefined) {
return this.props.application;
} else {
return this.state.application;
}
}
onFinish(values) {
AccountBackend.login(values)
.then((res) => {
if (res.status === 'ok') {
this.props.onLoggedIn();
Setting.showMessage("success", `Logged in successfully`);
Setting.goToLink("/");
} else {
Setting.showMessage("error", `Log in failed${res.msg}`);
}
});
};
renderForm() {
return (
<Form
name="normal_login"
initialValues={{
organization: this.getApplicationObj().organization,
remember: true
}}
onFinish={this.onFinish.bind(this)}
style={{width: "250px"}}
size="large"
>
<Form.Item
name="username"
rules={[{ required: true, message: 'Please input your Username!' }]}
>
<Input
prefix={<UserOutlined className="site-form-item-icon" />}
placeholder="username"
/>
</Form.Item>
<Form.Item
name="password"
rules={[{ required: true, message: 'Please input your Password!' }]}
>
<Input
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
placeholder="password"
/>
</Form.Item>
<Form.Item>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox style={{float: "left"}}>Auto login</Checkbox>
</Form.Item>
<a style={{float: "right"}} href="">
Forgot password?
</a>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
style={{width: "100%"}}
>
Login
</Button>
<div style={{float: "right"}}>
No account yet, <a href="/register">sign up now</a>
</div>
</Form.Item>
</Form>
);
}
render() {
const application = this.getApplicationObj();
if (application === null) {
return null;
}
return (
<Row>
<Col span={24} style={{display: "flex", justifyContent: "center"}} >
<div style={{marginTop: "80px", textAlign: "center"}}>
<img src={application.logo} alt={application.displayName} style={{marginBottom: '50px'}}/>
{
this.renderForm(application)
}
</div>
</Col>
</Row>
)
}
}
export default Face;
import React from "react";
import {Button, Checkbox, Col, Form, Input, Row} from "antd";
import {LockOutlined, UserOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as AccountBackend from "./backend/AccountBackend";
import * as Setting from "./Setting";
class Face extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
application: null,
};
}
componentWillMount() {
this.getApplication();
}
getApplication() {
ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => {
this.setState({
application: application,
});
});
}
getApplicationObj() {
if (this.props.application !== undefined) {
return this.props.application;
} else {
return this.state.application;
}
}
onFinish(values) {
AccountBackend.login(values)
.then((res) => {
if (res.status === 'ok') {
this.props.onLoggedIn();
Setting.showMessage("success", `Logged in successfully`);
Setting.goToLink("/");
} else {
Setting.showMessage("error", `Log in failed${res.msg}`);
}
});
};
renderForm() {
return (
<Form
name="normal_login"
initialValues={{
organization: this.getApplicationObj().organization,
remember: true
}}
onFinish={this.onFinish.bind(this)}
style={{width: "250px"}}
size="large"
>
<Form.Item
name="username"
rules={[{ required: true, message: 'Please input your Username!' }]}
>
<Input
prefix={<UserOutlined className="site-form-item-icon" />}
placeholder="username"
/>
</Form.Item>
<Form.Item
name="password"
rules={[{ required: true, message: 'Please input your Password!' }]}
>
<Input
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
placeholder="password"
/>
</Form.Item>
<Form.Item>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox style={{float: "left"}}>Auto login</Checkbox>
</Form.Item>
<a style={{float: "right"}} href="">
Forgot password?
</a>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
style={{width: "100%"}}
>
Login
</Button>
<div style={{float: "right"}}>
No account yet, <a href="/register">sign up now</a>
</div>
</Form.Item>
</Form>
);
}
render() {
const application = this.getApplicationObj();
if (application === null) {
return null;
}
return (
<Row>
<Col span={24} style={{display: "flex", justifyContent: "center"}} >
<div style={{marginTop: "80px", textAlign: "center"}}>
<img src={application.logo} alt={application.displayName} style={{marginBottom: '50px'}}/>
{
this.renderForm(application)
}
</div>
</Col>
</Row>
)
}
}
export default Face;

View File

@ -1,18 +1,18 @@
import React from "react";
class HomePage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
};
}
render() {
return (
"home"
)
}
}
export default HomePage;
import React from "react";
class HomePage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
};
}
render() {
return (
"home"
)
}
}
export default HomePage;

View File

@ -1,135 +1,135 @@
import React from "react";
import {Button, Card, Col, Input, Row} from 'antd';
import {LinkOutlined} from "@ant-design/icons";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
class OrganizationEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
organizationName: props.match.params.organizationName,
organization: null,
};
}
componentWillMount() {
this.getOrganization();
}
getOrganization() {
OrganizationBackend.getOrganization("admin", this.state.organizationName)
.then((organization) => {
this.setState({
organization: organization,
});
});
}
parseOrganizationField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateOrganizationField(key, value) {
value = this.parseOrganizationField(key, value);
let organization = this.state.organization;
organization[key] = value;
this.setState({
organization: organization,
});
}
renderOrganization() {
return (
<Card size="small" title={
<div>
Edit Organization&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.organization.name} onChange={e => {
this.updateOrganizationField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.organization.displayName} onChange={e => {
this.updateOrganizationField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Website Url:
</Col>
<Col span={22} >
<Input value={this.state.organization.websiteUrl} onChange={e => {
this.updateOrganizationField('websiteUrl', e.target.value);
}} />
</Col>
</Row>
</Card>
)
}
submitOrganizationEdit() {
let organization = Setting.deepCopy(this.state.organization);
OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
organizationName: this.state.organization.name,
});
this.props.history.push(`/organizations/${this.state.organization.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateOrganizationField('name', this.state.organizationName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.organization !== null ? this.renderOrganization() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default OrganizationEditPage;
import React from "react";
import {Button, Card, Col, Input, Row} from 'antd';
import {LinkOutlined} from "@ant-design/icons";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
class OrganizationEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
organizationName: props.match.params.organizationName,
organization: null,
};
}
componentWillMount() {
this.getOrganization();
}
getOrganization() {
OrganizationBackend.getOrganization("admin", this.state.organizationName)
.then((organization) => {
this.setState({
organization: organization,
});
});
}
parseOrganizationField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateOrganizationField(key, value) {
value = this.parseOrganizationField(key, value);
let organization = this.state.organization;
organization[key] = value;
this.setState({
organization: organization,
});
}
renderOrganization() {
return (
<Card size="small" title={
<div>
Edit Organization&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.organization.name} onChange={e => {
this.updateOrganizationField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.organization.displayName} onChange={e => {
this.updateOrganizationField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Website Url:
</Col>
<Col span={22} >
<Input value={this.state.organization.websiteUrl} onChange={e => {
this.updateOrganizationField('websiteUrl', e.target.value);
}} />
</Col>
</Row>
</Card>
)
}
submitOrganizationEdit() {
let organization = Setting.deepCopy(this.state.organization);
OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
organizationName: this.state.organization.name,
});
this.props.history.push(`/organizations/${this.state.organization.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateOrganizationField('name', this.state.organizationName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.organization !== null ? this.renderOrganization() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitOrganizationEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default OrganizationEditPage;

View File

@ -1,171 +1,171 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as OrganizationBackend from "./backend/OrganizationBackend";
class OrganizationListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
organizations: null,
};
}
componentWillMount() {
this.getOrganizations();
}
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: res,
});
});
}
newOrganization() {
return {
owner: "admin", // this.props.account.organizationname,
name: `organization_${this.state.organizations.length}`,
createdTime: moment().format(),
displayName: `New Organization - ${this.state.organizations.length}`,
websiteUrl: "https://example.com",
}
}
addOrganization() {
const newOrganization = this.newOrganization();
OrganizationBackend.addOrganization(newOrganization)
.then((res) => {
Setting.showMessage("success", `Organization added successfully`);
this.setState({
organizations: Setting.prependRow(this.state.organizations, newOrganization),
});
}
)
.catch(error => {
Setting.showMessage("error", `Organization failed to add: ${error}`);
});
}
deleteOrganization(i) {
OrganizationBackend.deleteOrganization(this.state.organizations[i])
.then((res) => {
Setting.showMessage("success", `Organization deleted successfully`);
this.setState({
organizations: Setting.deleteRow(this.state.organizations, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `Organization failed to delete: ${error}`);
});
}
renderTable(organizations) {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Website Url',
dataIndex: 'websiteUrl',
key: 'websiteUrl',
width: '300px',
sorter: (a, b) => a.websiteUrl.localeCompare(b.websiteUrl),
render: (text, record, index) => {
return (
<a target="_blank" href={text}>
{text}
</a>
)
}
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete organization: ${record.name} ?`}
onConfirm={() => this.deleteOrganization(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Organizations&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addOrganization.bind(this)}>Add</Button>
</div>
)}
loading={organizations === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.organizations)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default OrganizationListPage;
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as OrganizationBackend from "./backend/OrganizationBackend";
class OrganizationListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
organizations: null,
};
}
componentWillMount() {
this.getOrganizations();
}
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: res,
});
});
}
newOrganization() {
return {
owner: "admin", // this.props.account.organizationname,
name: `organization_${this.state.organizations.length}`,
createdTime: moment().format(),
displayName: `New Organization - ${this.state.organizations.length}`,
websiteUrl: "https://example.com",
}
}
addOrganization() {
const newOrganization = this.newOrganization();
OrganizationBackend.addOrganization(newOrganization)
.then((res) => {
Setting.showMessage("success", `Organization added successfully`);
this.setState({
organizations: Setting.prependRow(this.state.organizations, newOrganization),
});
}
)
.catch(error => {
Setting.showMessage("error", `Organization failed to add: ${error}`);
});
}
deleteOrganization(i) {
OrganizationBackend.deleteOrganization(this.state.organizations[i])
.then((res) => {
Setting.showMessage("success", `Organization deleted successfully`);
this.setState({
organizations: Setting.deleteRow(this.state.organizations, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `Organization failed to delete: ${error}`);
});
}
renderTable(organizations) {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Website Url',
dataIndex: 'websiteUrl',
key: 'websiteUrl',
width: '300px',
sorter: (a, b) => a.websiteUrl.localeCompare(b.websiteUrl),
render: (text, record, index) => {
return (
<a target="_blank" href={text}>
{text}
</a>
)
}
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete organization: ${record.name} ?`}
onConfirm={() => this.deleteOrganization(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Organizations&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addOrganization.bind(this)}>Add</Button>
</div>
)}
loading={organizations === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.organizations)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default OrganizationListPage;

View File

@ -1,165 +1,165 @@
import React from "react";
import {Button, Card, Col, Input, Row} from 'antd';
import {LinkOutlined} from "@ant-design/icons";
import * as ProviderBackend from "./backend/ProviderBackend";
import * as Setting from "./Setting";
class ProviderEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
providerName: props.match.params.providerName,
provider: null,
};
}
componentWillMount() {
this.getProvider();
}
getProvider() {
ProviderBackend.getProvider("admin", this.state.providerName)
.then((provider) => {
this.setState({
provider: provider,
});
});
}
parseProviderField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateProviderField(key, value) {
value = this.parseProviderField(key, value);
let provider = this.state.provider;
provider[key] = value;
this.setState({
provider: provider,
});
}
renderProvider() {
return (
<Card size="small" title={
<div>
Edit Provider&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.provider.name} onChange={e => {
this.updateProviderField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.provider.displayName} onChange={e => {
this.updateProviderField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
type:
</Col>
<Col span={22} >
<Input value={this.state.provider.type} onChange={e => {
this.updateProviderField('type', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Client Id:
</Col>
<Col span={22} >
<Input value={this.state.provider.clientId} onChange={e => {
this.updateProviderField('clientId', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Client Secret:
</Col>
<Col span={22} >
<Input value={this.state.provider.clientSecret} onChange={e => {
this.updateProviderField('clientSecret', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Provider Url:
</Col>
<Col span={22} >
<Input value={this.state.provider.providerUrl} onChange={e => {
this.updateProviderField('providerUrl', e.target.value);
}} />
</Col>
</Row>
</Card>
)
}
submitProviderEdit() {
let provider = Setting.deepCopy(this.state.provider);
ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
providerName: this.state.provider.name,
});
this.props.history.push(`/providers/${this.state.provider.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateProviderField('name', this.state.providerName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.provider !== null ? this.renderProvider() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default ProviderEditPage;
import React from "react";
import {Button, Card, Col, Input, Row} from 'antd';
import {LinkOutlined} from "@ant-design/icons";
import * as ProviderBackend from "./backend/ProviderBackend";
import * as Setting from "./Setting";
class ProviderEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
providerName: props.match.params.providerName,
provider: null,
};
}
componentWillMount() {
this.getProvider();
}
getProvider() {
ProviderBackend.getProvider("admin", this.state.providerName)
.then((provider) => {
this.setState({
provider: provider,
});
});
}
parseProviderField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateProviderField(key, value) {
value = this.parseProviderField(key, value);
let provider = this.state.provider;
provider[key] = value;
this.setState({
provider: provider,
});
}
renderProvider() {
return (
<Card size="small" title={
<div>
Edit Provider&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.provider.name} onChange={e => {
this.updateProviderField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.provider.displayName} onChange={e => {
this.updateProviderField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
type:
</Col>
<Col span={22} >
<Input value={this.state.provider.type} onChange={e => {
this.updateProviderField('type', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Client Id:
</Col>
<Col span={22} >
<Input value={this.state.provider.clientId} onChange={e => {
this.updateProviderField('clientId', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Client Secret:
</Col>
<Col span={22} >
<Input value={this.state.provider.clientSecret} onChange={e => {
this.updateProviderField('clientSecret', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Provider Url:
</Col>
<Col span={22} >
<Input value={this.state.provider.providerUrl} onChange={e => {
this.updateProviderField('providerUrl', e.target.value);
}} />
</Col>
</Row>
</Card>
)
}
submitProviderEdit() {
let provider = Setting.deepCopy(this.state.provider);
ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
providerName: this.state.provider.name,
});
this.props.history.push(`/providers/${this.state.provider.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateProviderField('name', this.state.providerName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.provider !== null ? this.renderProvider() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitProviderEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default ProviderEditPage;

View File

@ -1,195 +1,195 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend";
class ProviderListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
providers: null,
};
}
componentWillMount() {
this.getProviders();
}
getProviders() {
ProviderBackend.getProviders("admin")
.then((res) => {
this.setState({
providers: res,
});
});
}
newProvider() {
return {
owner: "admin", // this.props.account.providername,
name: `provider_${this.state.providers.length}`,
createdTime: moment().format(),
displayName: `New Provider - ${this.state.providers.length}`,
type: "github",
clientId: "",
clientSecret: "",
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
}
}
addProvider() {
const newProvider = this.newProvider();
ProviderBackend.addProvider(newProvider)
.then((res) => {
Setting.showMessage("success", `Provider added successfully`);
this.setState({
providers: Setting.prependRow(this.state.providers, newProvider),
});
}
)
.catch(error => {
Setting.showMessage("error", `Provider failed to add: ${error}`);
});
}
deleteProvider(i) {
ProviderBackend.deleteProvider(this.state.providers[i])
.then((res) => {
Setting.showMessage("success", `Provider deleted successfully`);
this.setState({
providers: Setting.deleteRow(this.state.providers, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `Provider failed to delete: ${error}`);
});
}
renderTable(providers) {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/providers/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Type',
dataIndex: 'type',
key: 'type',
width: '150px',
sorter: (a, b) => a.type.localeCompare(b.type),
},
{
title: 'Client Id',
dataIndex: 'clientId',
key: 'clientId',
width: '150px',
sorter: (a, b) => a.clientId.localeCompare(b.clientId),
},
{
title: 'Client Secret',
dataIndex: 'clientSecret',
key: 'clientSecret',
width: '150px',
sorter: (a, b) => a.clientSecret.localeCompare(b.clientSecret),
},
{
title: 'Provider Url',
dataIndex: 'providerUrl',
key: 'providerUrl',
width: '150px',
sorter: (a, b) => a.providerUrl.localeCompare(b.providerUrl),
render: (text, record, index) => {
return (
<a target="_blank" href={text}>
{text}
</a>
)
}
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete provider: ${record.name} ?`}
onConfirm={() => this.deleteProvider(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Providers&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addProvider.bind(this)}>Add</Button>
</div>
)}
loading={providers === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.providers)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default ProviderListPage;
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as ProviderBackend from "./backend/ProviderBackend";
class ProviderListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
providers: null,
};
}
componentWillMount() {
this.getProviders();
}
getProviders() {
ProviderBackend.getProviders("admin")
.then((res) => {
this.setState({
providers: res,
});
});
}
newProvider() {
return {
owner: "admin", // this.props.account.providername,
name: `provider_${this.state.providers.length}`,
createdTime: moment().format(),
displayName: `New Provider - ${this.state.providers.length}`,
type: "github",
clientId: "",
clientSecret: "",
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
}
}
addProvider() {
const newProvider = this.newProvider();
ProviderBackend.addProvider(newProvider)
.then((res) => {
Setting.showMessage("success", `Provider added successfully`);
this.setState({
providers: Setting.prependRow(this.state.providers, newProvider),
});
}
)
.catch(error => {
Setting.showMessage("error", `Provider failed to add: ${error}`);
});
}
deleteProvider(i) {
ProviderBackend.deleteProvider(this.state.providers[i])
.then((res) => {
Setting.showMessage("success", `Provider deleted successfully`);
this.setState({
providers: Setting.deleteRow(this.state.providers, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `Provider failed to delete: ${error}`);
});
}
renderTable(providers) {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/providers/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Type',
dataIndex: 'type',
key: 'type',
width: '150px',
sorter: (a, b) => a.type.localeCompare(b.type),
},
{
title: 'Client Id',
dataIndex: 'clientId',
key: 'clientId',
width: '150px',
sorter: (a, b) => a.clientId.localeCompare(b.clientId),
},
{
title: 'Client Secret',
dataIndex: 'clientSecret',
key: 'clientSecret',
width: '150px',
sorter: (a, b) => a.clientSecret.localeCompare(b.clientSecret),
},
{
title: 'Provider Url',
dataIndex: 'providerUrl',
key: 'providerUrl',
width: '150px',
sorter: (a, b) => a.providerUrl.localeCompare(b.providerUrl),
render: (text, record, index) => {
return (
<a target="_blank" href={text}>
{text}
</a>
)
}
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete provider: ${record.name} ?`}
onConfirm={() => this.deleteProvider(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Providers&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addProvider.bind(this)}>Add</Button>
</div>
)}
loading={providers === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.providers)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default ProviderListPage;

View File

@ -1,125 +1,125 @@
// Copyright 2020 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 {message} from "antd";
import React from "react";
import {isMobile as isMobileDevice} from "react-device-detect";
export let ServerUrl = '';
export function initServerUrl() {
const hostname = window.location.hostname;
if (hostname === 'localhost') {
ServerUrl = `http://${hostname}:8000`;
}
}
export function parseJson(s) {
if (s === "") {
return null;
} else {
return JSON.parse(s);
}
}
export function myParseInt(i) {
const res = parseInt(i);
return isNaN(res) ? 0 : res;
}
export function openLink(link) {
// this.props.history.push(link);
const w = window.open('about:blank');
w.location.href = link;
}
export function goToLink(link) {
window.location.href = link;
}
export function showMessage(type, text) {
if (type === "") {
return;
} else if (type === "success") {
message.success(text);
} else if (type === "error") {
message.error(text);
}
}
export function deepCopy(obj) {
return Object.assign({}, obj);
}
export function addRow(array, row) {
return [...array, row];
}
export function prependRow(array, row) {
return [row, ...array];
}
export function deleteRow(array, i) {
// return array = array.slice(0, i).concat(array.slice(i + 1));
return [...array.slice(0, i), ...array.slice(i + 1)];
}
export function swapRow(array, i, j) {
return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)];
}
export function isMobile() {
// return getIsMobileView();
return isMobileDevice;
}
export function getFormattedDate(date) {
if (date === undefined) {
return null;
}
date = date.replace('T', ' ');
date = date.replace('+08:00', ' ');
return date;
}
export function getFormattedDateShort(date) {
return date.slice(0, 10);
}
export function getShortName(s) {
return s.split('/').slice(-1)[0];
}
function getRandomInt(s) {
let hash = 0;
if (s.length !== 0) {
for (let i = 0; i < s.length; i ++) {
let char = s.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
}
return hash;
}
export function getAvatarColor(s) {
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
let random = getRandomInt(s);
if (random < 0) {
random = -random;
}
return colorList[random % 4];
}
// Copyright 2020 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 {message} from "antd";
import React from "react";
import {isMobile as isMobileDevice} from "react-device-detect";
export let ServerUrl = '';
export function initServerUrl() {
const hostname = window.location.hostname;
if (hostname === 'localhost') {
ServerUrl = `http://${hostname}:8000`;
}
}
export function parseJson(s) {
if (s === "") {
return null;
} else {
return JSON.parse(s);
}
}
export function myParseInt(i) {
const res = parseInt(i);
return isNaN(res) ? 0 : res;
}
export function openLink(link) {
// this.props.history.push(link);
const w = window.open('about:blank');
w.location.href = link;
}
export function goToLink(link) {
window.location.href = link;
}
export function showMessage(type, text) {
if (type === "") {
return;
} else if (type === "success") {
message.success(text);
} else if (type === "error") {
message.error(text);
}
}
export function deepCopy(obj) {
return Object.assign({}, obj);
}
export function addRow(array, row) {
return [...array, row];
}
export function prependRow(array, row) {
return [row, ...array];
}
export function deleteRow(array, i) {
// return array = array.slice(0, i).concat(array.slice(i + 1));
return [...array.slice(0, i), ...array.slice(i + 1)];
}
export function swapRow(array, i, j) {
return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)];
}
export function isMobile() {
// return getIsMobileView();
return isMobileDevice;
}
export function getFormattedDate(date) {
if (date === undefined) {
return null;
}
date = date.replace('T', ' ');
date = date.replace('+08:00', ' ');
return date;
}
export function getFormattedDateShort(date) {
return date.slice(0, 10);
}
export function getShortName(s) {
return s.split('/').slice(-1)[0];
}
function getRandomInt(s) {
let hash = 0;
if (s.length !== 0) {
for (let i = 0; i < s.length; i ++) {
let char = s.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
}
return hash;
}
export function getAvatarColor(s) {
const colorList = ['#f56a00', '#7265e6', '#ffbf00', '#00a2ae'];
let random = getRandomInt(s);
if (random < 0) {
random = -random;
}
return colorList[random % 4];
}

View File

@ -1,193 +1,193 @@
import React from "react";
import {Button, Card, Col, Input, Row, Select} from 'antd';
import * as UserBackend from "./backend/UserBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
const { Option } = Select;
class UserEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
organizationName: props.match.params.organizationName,
userName: props.match.params.userName,
user: null,
organizations: [],
};
}
componentWillMount() {
this.getUser();
this.getOrganizations();
}
getUser() {
UserBackend.getUser(this.state.organizationName, this.state.userName)
.then((user) => {
this.setState({
user: user,
});
});
}
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: res,
});
});
}
parseUserField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateUserField(key, value) {
value = this.parseUserField(key, value);
let user = this.state.user;
user[key] = value;
this.setState({
user: user,
});
}
renderUser() {
return (
<Card size="small" title={
<div>
Edit User&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitUserEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Organization:
</Col>
<Col span={22} >
<Select virtual={false} style={{width: '100%'}} value={this.state.user.owner} onChange={(value => {this.updateUserField('owner', value);})}>
{
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.user.name} onChange={e => {
this.updateUserField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Password Type:
</Col>
<Col span={22} >
<Input value={this.state.user.passwordType} onChange={e => {
this.updateUserField('passwordType', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Password:
</Col>
<Col span={22} >
<Input value={this.state.user.password} onChange={e => {
this.updateUserField('password', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.user.displayName} onChange={e => {
this.updateUserField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Email:
</Col>
<Col span={22} >
<Input value={this.state.user.email} onChange={e => {
this.updateUserField('email', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Phone:
</Col>
<Col span={22} >
<Input value={this.state.user.phone} onChange={e => {
this.updateUserField('phone', e.target.value);
}} />
</Col>
</Row>
</Card>
)
}
submitUserEdit() {
let user = Setting.deepCopy(this.state.user);
UserBackend.updateUser(this.state.organizationName, this.state.userName, user)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
organizationName: this.state.user.owner,
userName: this.state.user.name,
});
this.props.history.push(`/users/${this.state.user.owner}/${this.state.user.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateUserField('owner', this.state.organizationName);
this.updateUserField('name', this.state.userName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.user !== null ? this.renderUser() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitUserEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default UserEditPage;
import React from "react";
import {Button, Card, Col, Input, Row, Select} from 'antd';
import * as UserBackend from "./backend/UserBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
const { Option } = Select;
class UserEditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
organizationName: props.match.params.organizationName,
userName: props.match.params.userName,
user: null,
organizations: [],
};
}
componentWillMount() {
this.getUser();
this.getOrganizations();
}
getUser() {
UserBackend.getUser(this.state.organizationName, this.state.userName)
.then((user) => {
this.setState({
user: user,
});
});
}
getOrganizations() {
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: res,
});
});
}
parseUserField(key, value) {
// if ([].includes(key)) {
// value = Setting.myParseInt(value);
// }
return value;
}
updateUserField(key, value) {
value = this.parseUserField(key, value);
let user = this.state.user;
user[key] = value;
this.setState({
user: user,
});
}
renderUser() {
return (
<Card size="small" title={
<div>
Edit User&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" onClick={this.submitUserEdit.bind(this)}>Save</Button>
</div>
} style={{marginLeft: '5px'}} type="inner">
<Row style={{marginTop: '10px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Organization:
</Col>
<Col span={22} >
<Select virtual={false} style={{width: '100%'}} value={this.state.user.owner} onChange={(value => {this.updateUserField('owner', value);})}>
{
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Name:
</Col>
<Col span={22} >
<Input value={this.state.user.name} onChange={e => {
this.updateUserField('name', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Password Type:
</Col>
<Col span={22} >
<Input value={this.state.user.passwordType} onChange={e => {
this.updateUserField('passwordType', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Password:
</Col>
<Col span={22} >
<Input value={this.state.user.password} onChange={e => {
this.updateUserField('password', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Display Name:
</Col>
<Col span={22} >
<Input value={this.state.user.displayName} onChange={e => {
this.updateUserField('displayName', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Email:
</Col>
<Col span={22} >
<Input value={this.state.user.email} onChange={e => {
this.updateUserField('email', e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: '20px'}} >
<Col style={{marginTop: '5px'}} span={2}>
Phone:
</Col>
<Col span={22} >
<Input value={this.state.user.phone} onChange={e => {
this.updateUserField('phone', e.target.value);
}} />
</Col>
</Row>
</Card>
)
}
submitUserEdit() {
let user = Setting.deepCopy(this.state.user);
UserBackend.updateUser(this.state.organizationName, this.state.userName, user)
.then((res) => {
if (res) {
Setting.showMessage("success", `Successfully saved`);
this.setState({
organizationName: this.state.user.owner,
userName: this.state.user.name,
});
this.props.history.push(`/users/${this.state.user.owner}/${this.state.user.name}`);
} else {
Setting.showMessage("error", `failed to save: server side failure`);
this.updateUserField('owner', this.state.organizationName);
this.updateUserField('name', this.state.userName);
}
})
.catch(error => {
Setting.showMessage("error", `failed to save: ${error}`);
});
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.state.user !== null ? this.renderUser() : null
}
</Col>
<Col span={1}>
</Col>
</Row>
<Row style={{margin: 10}}>
<Col span={2}>
</Col>
<Col span={18}>
<Button type="primary" size="large" onClick={this.submitUserEdit.bind(this)}>Save</Button>
</Col>
</Row>
</div>
);
}
}
export default UserEditPage;

View File

@ -1,202 +1,202 @@
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as UserBackend from "./backend/UserBackend";
class UserListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
users: null,
};
}
componentWillMount() {
this.getUsers();
}
getUsers() {
UserBackend.getGlobalUsers()
.then((res) => {
this.setState({
users: res,
});
});
}
newUser() {
return {
owner: "admin", // this.props.account.username,
name: `user_${this.state.users.length}`,
createdTime: moment().format(),
password: "123456",
passwordType: "plain",
displayName: `New User - ${this.state.users.length}`,
email: "user@example.com",
phone: "1-12345678",
}
}
addUser() {
const newUser = this.newUser();
UserBackend.addUser(newUser)
.then((res) => {
Setting.showMessage("success", `User added successfully`);
this.setState({
users: Setting.prependRow(this.state.users, newUser),
});
}
)
.catch(error => {
Setting.showMessage("error", `User failed to add: ${error}`);
});
}
deleteUser(i) {
UserBackend.deleteUser(this.state.users[i])
.then((res) => {
Setting.showMessage("success", `User deleted successfully`);
this.setState({
users: Setting.deleteRow(this.state.users, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `User failed to delete: ${error}`);
});
}
renderTable(users) {
const columns = [
{
title: 'Organization',
dataIndex: 'owner',
key: 'owner',
width: '120px',
sorter: (a, b) => a.owner.localeCompare(b.owner),
render: (text, record, index) => {
return (
<a href={`/organizations/${text}`}>
{text}
</a>
)
}
},
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/users/${record.owner}/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'PasswordType',
dataIndex: 'passwordType',
key: 'passwordType',
width: '150px',
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
},
{
title: 'Password',
dataIndex: 'password',
key: 'password',
width: '150px',
sorter: (a, b) => a.password.localeCompare(b.password),
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Email',
dataIndex: 'email',
key: 'email',
width: '150px',
sorter: (a, b) => a.email.localeCompare(b.email),
},
{
title: 'Phone',
dataIndex: 'phone',
key: 'phone',
width: '120px',
sorter: (a, b) => a.phone.localeCompare(b.phone),
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete user: ${record.name} ?`}
onConfirm={() => this.deleteUser(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Users&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addUser.bind(this)}>Add</Button>
</div>
)}
loading={users === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.users)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default UserListPage;
import React from "react";
import {Link} from "react-router-dom";
import {Button, Col, Popconfirm, Row, Table} from 'antd';
import moment from "moment";
import * as Setting from "./Setting";
import * as UserBackend from "./backend/UserBackend";
class UserListPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
users: null,
};
}
componentWillMount() {
this.getUsers();
}
getUsers() {
UserBackend.getGlobalUsers()
.then((res) => {
this.setState({
users: res,
});
});
}
newUser() {
return {
owner: "admin", // this.props.account.username,
name: `user_${this.state.users.length}`,
createdTime: moment().format(),
password: "123456",
passwordType: "plain",
displayName: `New User - ${this.state.users.length}`,
email: "user@example.com",
phone: "1-12345678",
}
}
addUser() {
const newUser = this.newUser();
UserBackend.addUser(newUser)
.then((res) => {
Setting.showMessage("success", `User added successfully`);
this.setState({
users: Setting.prependRow(this.state.users, newUser),
});
}
)
.catch(error => {
Setting.showMessage("error", `User failed to add: ${error}`);
});
}
deleteUser(i) {
UserBackend.deleteUser(this.state.users[i])
.then((res) => {
Setting.showMessage("success", `User deleted successfully`);
this.setState({
users: Setting.deleteRow(this.state.users, i),
});
}
)
.catch(error => {
Setting.showMessage("error", `User failed to delete: ${error}`);
});
}
renderTable(users) {
const columns = [
{
title: 'Organization',
dataIndex: 'owner',
key: 'owner',
width: '120px',
sorter: (a, b) => a.owner.localeCompare(b.owner),
render: (text, record, index) => {
return (
<a href={`/organizations/${text}`}>
{text}
</a>
)
}
},
{
title: 'Name',
dataIndex: 'name',
key: 'name',
width: '120px',
sorter: (a, b) => a.name.localeCompare(b.name),
render: (text, record, index) => {
return (
<Link to={`/users/${record.owner}/${text}`}>
{text}
</Link>
)
}
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
width: '160px',
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
render: (text, record, index) => {
return Setting.getFormattedDate(text);
}
},
{
title: 'PasswordType',
dataIndex: 'passwordType',
key: 'passwordType',
width: '150px',
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
},
{
title: 'Password',
dataIndex: 'password',
key: 'password',
width: '150px',
sorter: (a, b) => a.password.localeCompare(b.password),
},
{
title: 'Display Name',
dataIndex: 'displayName',
key: 'displayName',
// width: '100px',
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
},
{
title: 'Email',
dataIndex: 'email',
key: 'email',
width: '150px',
sorter: (a, b) => a.email.localeCompare(b.email),
},
{
title: 'Phone',
dataIndex: 'phone',
key: 'phone',
width: '120px',
sorter: (a, b) => a.phone.localeCompare(b.phone),
},
{
title: 'Action',
dataIndex: '',
key: 'op',
width: '170px',
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>Edit</Button>
<Popconfirm
title={`Sure to delete user: ${record.name} ?`}
onConfirm={() => this.deleteUser(index)}
>
<Button style={{marginBottom: '10px'}} type="danger">Delete</Button>
</Popconfirm>
</div>
)
}
},
];
return (
<div>
<Table columns={columns} dataSource={users} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
title={() => (
<div>
Users&nbsp;&nbsp;&nbsp;&nbsp;
<Button type="primary" size="small" onClick={this.addUser.bind(this)}>Add</Button>
</div>
)}
loading={users === null}
/>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderTable(this.state.users)
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
);
}
}
export default UserListPage;

View File

@ -1,77 +1,77 @@
import React from "react";
import {Col, Descriptions, Row} from 'antd';
import * as AccountBackend from "../backend/AccountBackend";
import * as Setting from "../Setting";
class AccountPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
username: props.match.params.username,
user: null,
};
}
componentWillMount() {
this.getUser();
}
getUser() {
if (this.state.username !== undefined) {
AccountBackend.getUser(this.state.username)
.then((user) => {
this.setState({
user: user,
});
});
}
}
renderValue(key) {
if (this.props.account === null || this.props.account === undefined) {
return <a href={"/login"}>Please sign in first</a>
} else if (this.state.user !== null) {
return this.state.user[key];
} else {
return this.props.account[key];
}
}
renderContent() {
return (
<div>
&nbsp;
<Descriptions title="My Account" bordered>
<Descriptions.Item label="Username">{this.renderValue("name")}</Descriptions.Item>
<Descriptions.Item label="Organization">{this.renderValue("owner")}</Descriptions.Item>
<Descriptions.Item label="Created At">{Setting.getFormattedDate(this.renderValue("createdTime"))}</Descriptions.Item>
<Descriptions.Item label="Password Type">{this.renderValue("passwordType")}</Descriptions.Item>
<Descriptions.Item label="Display Name">{this.renderValue("displayName")}</Descriptions.Item>
<Descriptions.Item label="E-mail">{this.renderValue("email")}</Descriptions.Item>
<Descriptions.Item label="Phone">{this.renderValue("phone")}</Descriptions.Item>
</Descriptions>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderContent()
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
)
}
}
export default AccountPage;
import React from "react";
import {Col, Descriptions, Row} from 'antd';
import * as AccountBackend from "../backend/AccountBackend";
import * as Setting from "../Setting";
class AccountPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
username: props.match.params.username,
user: null,
};
}
componentWillMount() {
this.getUser();
}
getUser() {
if (this.state.username !== undefined) {
AccountBackend.getUser(this.state.username)
.then((user) => {
this.setState({
user: user,
});
});
}
}
renderValue(key) {
if (this.props.account === null || this.props.account === undefined) {
return <a href={"/login"}>Please sign in first</a>
} else if (this.state.user !== null) {
return this.state.user[key];
} else {
return this.props.account[key];
}
}
renderContent() {
return (
<div>
&nbsp;
<Descriptions title="My Account" bordered>
<Descriptions.Item label="Username">{this.renderValue("name")}</Descriptions.Item>
<Descriptions.Item label="Organization">{this.renderValue("owner")}</Descriptions.Item>
<Descriptions.Item label="Created At">{Setting.getFormattedDate(this.renderValue("createdTime"))}</Descriptions.Item>
<Descriptions.Item label="Password Type">{this.renderValue("passwordType")}</Descriptions.Item>
<Descriptions.Item label="Display Name">{this.renderValue("displayName")}</Descriptions.Item>
<Descriptions.Item label="E-mail">{this.renderValue("email")}</Descriptions.Item>
<Descriptions.Item label="Phone">{this.renderValue("phone")}</Descriptions.Item>
</Descriptions>
</div>
);
}
render() {
return (
<div>
<Row style={{width: "100%"}}>
<Col span={1}>
</Col>
<Col span={22}>
{
this.renderContent()
}
</Col>
<Col span={1}>
</Col>
</Row>
</div>
)
}
}
export default AccountPage;

View File

@ -1,12 +1,12 @@
import React from 'react';
import Face from "../Face";
class LoginPage extends React.Component {
render() {
return (
<Face applicationName={"app-built-in"} account={this.props.account} onLoggedIn={this.props.onLoggedIn.bind(this)} {...this.props} />
)
}
}
export default LoginPage;
import React from 'react';
import Face from "../Face";
class LoginPage extends React.Component {
render() {
return (
<Face applicationName={"app-built-in"} account={this.props.account} onLoggedIn={this.props.onLoggedIn.bind(this)} {...this.props} />
)
}
}
export default LoginPage;

View File

@ -1,52 +1,52 @@
// Copyright 2020 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 getUser(username) {
return fetch(`${Setting.ServerUrl}/api/get-user?username=${username}`, {
method: 'GET',
credentials: 'include'
}).then(res => res.json());
}
export function getAccount() {
return fetch(`${Setting.ServerUrl}/api/get-account`, {
method: 'GET',
credentials: 'include'
}).then(res => res.json());
}
export function register(values) {
return fetch(`${Setting.ServerUrl}/api/register`, {
method: 'POST',
credentials: "include",
body: JSON.stringify(values),
}).then(res => res.json());
}
export function login(values) {
return fetch(`${Setting.ServerUrl}/api/login`, {
method: 'POST',
credentials: "include",
body: JSON.stringify(values),
}).then(res => res.json());
}
export function logout() {
return fetch(`${Setting.ServerUrl}/api/logout`, {
method: 'POST',
credentials: "include",
}).then(res => res.json());
}
// Copyright 2020 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 getUser(username) {
return fetch(`${Setting.ServerUrl}/api/get-user?username=${username}`, {
method: 'GET',
credentials: 'include'
}).then(res => res.json());
}
export function getAccount() {
return fetch(`${Setting.ServerUrl}/api/get-account`, {
method: 'GET',
credentials: 'include'
}).then(res => res.json());
}
export function register(values) {
return fetch(`${Setting.ServerUrl}/api/register`, {
method: 'POST',
credentials: "include",
body: JSON.stringify(values),
}).then(res => res.json());
}
export function login(values) {
return fetch(`${Setting.ServerUrl}/api/login`, {
method: 'POST',
credentials: "include",
body: JSON.stringify(values),
}).then(res => res.json());
}
export function logout() {
return fetch(`${Setting.ServerUrl}/api/logout`, {
method: 'POST',
credentials: "include",
}).then(res => res.json());
}

View File

@ -1,42 +1,42 @@
import * as Setting from "../Setting";
export function getApplications(owner) {
return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getApplication(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateApplication(owner, name, application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newApplication),
}).then(res => res.json());
}
export function addApplication(application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/add-application`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newApplication),
}).then(res => res.json());
}
export function deleteApplication(application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/delete-application`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newApplication),
}).then(res => res.json());
}
import * as Setting from "../Setting";
export function getApplications(owner) {
return fetch(`${Setting.ServerUrl}/api/get-applications?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getApplication(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-application?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateApplication(owner, name, application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/update-application?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newApplication),
}).then(res => res.json());
}
export function addApplication(application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/add-application`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newApplication),
}).then(res => res.json());
}
export function deleteApplication(application) {
let newApplication = Setting.deepCopy(application);
return fetch(`${Setting.ServerUrl}/api/delete-application`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newApplication),
}).then(res => res.json());
}

View File

@ -1,42 +1,42 @@
import * as Setting from "../Setting";
export function getOrganizations(owner) {
return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getOrganization(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-organization?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateOrganization(owner, name, organization) {
let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/update-organization?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newOrganization),
}).then(res => res.json());
}
export function addOrganization(organization) {
let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/add-organization`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newOrganization),
}).then(res => res.json());
}
export function deleteOrganization(organization) {
let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/delete-organization`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newOrganization),
}).then(res => res.json());
}
import * as Setting from "../Setting";
export function getOrganizations(owner) {
return fetch(`${Setting.ServerUrl}/api/get-organizations?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getOrganization(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-organization?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateOrganization(owner, name, organization) {
let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/update-organization?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newOrganization),
}).then(res => res.json());
}
export function addOrganization(organization) {
let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/add-organization`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newOrganization),
}).then(res => res.json());
}
export function deleteOrganization(organization) {
let newOrganization = Setting.deepCopy(organization);
return fetch(`${Setting.ServerUrl}/api/delete-organization`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newOrganization),
}).then(res => res.json());
}

View File

@ -1,42 +1,42 @@
import * as Setting from "../Setting";
export function getProviders(owner) {
return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getProvider(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateProvider(owner, name, provider) {
let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/update-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newProvider),
}).then(res => res.json());
}
export function addProvider(provider) {
let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/add-provider`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newProvider),
}).then(res => res.json());
}
export function deleteProvider(provider) {
let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/delete-provider`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newProvider),
}).then(res => res.json());
}
import * as Setting from "../Setting";
export function getProviders(owner) {
return fetch(`${Setting.ServerUrl}/api/get-providers?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getProvider(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateProvider(owner, name, provider) {
let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/update-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newProvider),
}).then(res => res.json());
}
export function addProvider(provider) {
let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/add-provider`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newProvider),
}).then(res => res.json());
}
export function deleteProvider(provider) {
let newProvider = Setting.deepCopy(provider);
return fetch(`${Setting.ServerUrl}/api/delete-provider`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newProvider),
}).then(res => res.json());
}

View File

@ -1,49 +1,49 @@
import * as Setting from "../Setting";
export function getGlobalUsers() {
return fetch(`${Setting.ServerUrl}/api/get-global-users`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getUsers(owner) {
return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getUser(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-user?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateUser(owner, name, user) {
let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/update-user?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newUser),
}).then(res => res.json());
}
export function addUser(user) {
let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/add-user`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newUser),
}).then(res => res.json());
}
export function deleteUser(user) {
let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/delete-user`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newUser),
}).then(res => res.json());
}
import * as Setting from "../Setting";
export function getGlobalUsers() {
return fetch(`${Setting.ServerUrl}/api/get-global-users`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getUsers(owner) {
return fetch(`${Setting.ServerUrl}/api/get-users?owner=${owner}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getUser(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-user?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateUser(owner, name, user) {
let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/update-user?id=${owner}/${encodeURIComponent(name)}`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newUser),
}).then(res => res.json());
}
export function addUser(user) {
let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/add-user`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newUser),
}).then(res => res.json());
}
export function deleteUser(user) {
let newUser = Setting.deepCopy(user);
return fetch(`${Setting.ServerUrl}/api/delete-user`, {
method: 'POST',
credentials: 'include',
body: JSON.stringify(newUser),
}).then(res => res.json());
}

File diff suppressed because it is too large Load Diff