diff --git a/web/src/App.js b/web/src/App.js
index 986f26e6..0955be69 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -33,6 +33,8 @@ import HomePage from "./basic/HomePage";
import CustomGithubCorner from "./CustomGithubCorner";
import * as Auth from "./auth/Auth";
+import RegisterPage from "./auth/RegisterPage";
+import ResultPage from "./auth/ResultPage";
import LoginPage from "./auth/LoginPage";
import SelfLoginPage from "./auth/SelfLoginPage";
import * as AuthBackend from "./auth/AuthBackend";
@@ -49,6 +51,7 @@ class App extends Component {
classes: props,
selectedMenuKey: 0,
account: undefined,
+ uri: null,
};
Setting.initServerUrl();
@@ -65,9 +68,20 @@ class App extends Component {
this.getAccount();
}
+ componentDidUpdate() {
+ // eslint-disable-next-line no-restricted-globals
+ const uri = location.pathname;
+ if (this.state.uri !== uri) {
+ this.updateMenuKey();
+ }
+ }
+
updateMenuKey() {
// eslint-disable-next-line no-restricted-globals
const uri = location.pathname;
+ this.setState({
+ uri: uri,
+ });
if (uri === '/') {
this.setState({ selectedMenuKey: 0 });
} else if (uri.includes('organizations')) {
@@ -80,6 +94,12 @@ class App extends Component {
this.setState({ selectedMenuKey: 4 });
} else if (uri.includes('tokens')) {
this.setState({ selectedMenuKey: 5 });
+ } else if (uri.includes('register')) {
+ this.setState({ selectedMenuKey: 100 });
+ } else if (uri.includes('login')) {
+ this.setState({ selectedMenuKey: 101 });
+ } else if (uri.includes('result')) {
+ this.setState({ selectedMenuKey: 100 });
} else {
this.setState({ selectedMenuKey: -1 });
}
@@ -116,7 +136,7 @@ class App extends Component {
Setting.goToLink("/");
} else {
- Setting.showMessage("error", `Logout failed: ${res.msg}`);
+ Setting.showMessage("error", `Failed to log out: ${res.msg}`);
}
});
}
@@ -277,7 +297,7 @@ class App extends Component {
+ this.renderHomeIfLoggedIn()}/>
+ this.renderHomeIfLoggedIn()}/>
this.renderHomeIfLoggedIn()}/>
this.renderLoginIfNotLoggedIn()}/>
diff --git a/web/src/auth/LoginPage.js b/web/src/auth/LoginPage.js
index 196b6afd..547cd96a 100644
--- a/web/src/auth/LoginPage.js
+++ b/web/src/auth/LoginPage.js
@@ -88,7 +88,7 @@ class LoginPage extends React.Component {
if (res.status === 'ok') {
const responseType = this.state.type;
if (responseType === "login") {
- this.props.onLoggedIn();
+ // this.props.onLoggedIn();
Util.showMessage("success", `Logged in successfully`);
Util.goToLink("/");
} else if (responseType === "code") {
@@ -97,7 +97,7 @@ class LoginPage extends React.Component {
// Util.showMessage("success", `Authorization code: ${res.data}`);
}
} else {
- Util.showMessage("error", `Log in failed:${res.msg}`);
+ Util.showMessage("error", `Failed to log in: ${res.msg}`);
}
});
};
diff --git a/web/src/auth/RegisterPage.js b/web/src/auth/RegisterPage.js
new file mode 100644
index 00000000..24e39dd6
--- /dev/null
+++ b/web/src/auth/RegisterPage.js
@@ -0,0 +1,249 @@
+// Copyright 2021 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import React from 'react';
+import {Form, Input, Select, Checkbox, Button, Row, Col} from 'antd';
+import * as Setting from "../Setting";
+import * as AuthBackend from "./AuthBackend";
+import i18next from "i18next";
+import {Link} from "react-router-dom";
+
+const { Option } = Select;
+
+const formItemLayout = {
+ labelCol: {
+ xs: {
+ span: 24,
+ },
+ sm: {
+ span: 8,
+ },
+ },
+ wrapperCol: {
+ xs: {
+ span: 24,
+ },
+ sm: {
+ span: 16,
+ },
+ },
+};
+
+const tailFormItemLayout = {
+ wrapperCol: {
+ xs: {
+ span: 24,
+ offset: 0,
+ },
+ sm: {
+ span: 16,
+ offset: 8,
+ },
+ },
+};
+
+class RegisterPage extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ classes: props,
+ };
+
+ this.form = React.createRef();
+ }
+
+ onFinish(values) {
+ AuthBackend.register(values)
+ .then((res) => {
+ if (res.status === 'ok') {
+ this.props.history.push('/result');
+ } else {
+ Setting.showMessage("error", `Failed to register: ${res.msg}`);
+ }
+ });
+ }
+
+ onFinishFailed(values, errorFields, outOfDate) {
+ this.form.current.scrollToField(errorFields[0].name);
+ }
+
+ renderForm() {
+ const prefixSelector = (
+
+
+
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ({
+ validator(rule, value) {
+ if (!value || getFieldValue('password') === value) {
+ return Promise.resolve();
+ }
+
+ return Promise.reject('Your confirmed password is inconsistent with the password');
+ },
+ }),
+ ]}
+ >
+
+
+
+
+
+
+
+ Accept Terms of Use
+
+
+
+
+ Have account?
+
+ sign in now
+
+
+
+ )
+ }
+
+ render() {
+ return (
+
+
+
+
+ {
+ this.renderForm()
+ }
+
+
+
+ )
+ }
+}
+
+export default RegisterPage;
diff --git a/web/src/auth/ResultPage.js b/web/src/auth/ResultPage.js
new file mode 100644
index 00000000..c9c87869
--- /dev/null
+++ b/web/src/auth/ResultPage.js
@@ -0,0 +1,46 @@
+// Copyright 2021 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import React from "react";
+import { Result, Button } from 'antd';
+
+class ResultPage extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ classes: props,
+ };
+ }
+
+ render() {
+ return (
+