Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ISSUE#11957] Console support init password for nacos username #12148

Merged
merged 5 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions console-ui/src/globalLib.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ function goLogin() {
window.location = `${base_url}#/login`;
}

function goRegister() {
const url = window.location.href;
localStorage.removeItem('token');
const base_url = url.split('#')[0];
window.location = `${base_url}#/register`;
}

function generateRandomPassword(length) {
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let password = '';
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charset.length);
password += charset[randomIndex];
}
return password;
}

const global = window;

/**
Expand Down Expand Up @@ -564,5 +581,7 @@ export {
setParam,
setParams,
goLogin,
goRegister,
generateRandomPassword,
request,
};
2 changes: 2 additions & 0 deletions console-ui/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import Layout from './layouts/MainLayout';
import { LANGUAGE_KEY, REDUX_DEVTOOLS, THEME } from './constants';

import Login from './pages/Login';
import Register from './pages/Register';
import Namespace from './pages/NameSpace';
import Newconfig from './pages/ConfigurationManagement/NewConfig';
import Configsync from './pages/ConfigurationManagement/ConfigSync';
Expand Down Expand Up @@ -136,6 +137,7 @@ class App extends React.Component {
{loginPageEnabled && loginPageEnabled === 'false' ? null : (
<Route path="/login" component={Login} />
)}
<Route path="/register" component={Register} />
{/* <Route path="/login" component={Login} /> */}
<Layout>
{consoleUiEnable &&
Expand Down
2 changes: 2 additions & 0 deletions console-ui/src/locales/zh-CN.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ const I18N_CONF = {
},
Login: {
login: '登录',
initPassword: '初始化密码',
internalSysTip1: '内部系统,不可暴露到公网',
submit: '提交',
pleaseInputUsername: '请输入用户名',
pleaseInputPassword: '请输入密码',
pleaseInputPasswordTips: '请输入密码(若密码为空,将使用随机密码)',
invalidUsernameOrPassword: '用户名或密码错误',
passwordRequired: '密码不能为空',
usernameRequired: '用户名不能为空',
Expand Down
160 changes: 160 additions & 0 deletions console-ui/src/pages/Register/Register.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React from 'react';
import { Card, Form, Input, Message, ConfigProvider, Field, Dialog } from '@alifd/next';
import { withRouter } from 'react-router-dom';

import './index.scss';
import Header from '../../layouts/Header';
import PropTypes from 'prop-types';
import { admin, guide, state } from '../../reducers/base';
import { connect } from 'react-redux';
import { generateRandomPassword } from '../../globalLib';

const FormItem = Form.Item;

@withRouter
@ConfigProvider.config
@connect(state => ({ ...state.locale }))
class Register extends React.Component {
static displayName = 'Register';

static propTypes = {
locale: PropTypes.object,
history: PropTypes.object,
};

constructor(props) {
super(props);
this.state = {
consoleUiEnable: true,
guideMsg: '',
};
this.field = new Field(this);
}

componentDidMount() {
if (localStorage.getItem('token')) {
const [baseUrl] = location.href.split('#');
location.href = `${baseUrl}#/`;
}
this.handleSearch();
}

handleSearch = () => {
state().then(res => {
if (res?.console_ui_enabled === 'false') {
this.setState({ consoleUiEnable: true });
guide().then(res => {
this.setState({ guideMsg: res?.data });
});
} else {
this.setState({ consoleUiEnable: false });
}
});
};

handleSubmit = () => {
const { locale = {} } = this.props;
this.field.validate((errors, values) => {
if (errors) {
return;
}

const data = {
password: generateRandomPassword(10),
...values
};

admin(data)
.then(res => {
if (res.username && res.password) {
localStorage.setItem('token', JSON.stringify(res));
Dialog.alert({
title: locale.Login.initPassword + locale.ListeningToQuery.success,
content: locale.Password.newPassword + ':' + res.password,
onOk: () => {
this.props.history.push('/');
}
});
}
})
.catch(() => {
Message.error({
content: locale.Login.invalidUsernameOrPassword,
});
});
});
};

onKeyDown = event => {
// 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event
if (event.key === 'Enter') {
event.preventDefault();
event.stopPropagation();
this.handleSubmit();
}
};

render() {
const { locale = {} } = this.props;
const { consoleUiEnable, guideMsg } = this.state;

return (
<div className="home-page">
<Header />
<section
className="top-section"
style={{
background: 'url(img/black_dot.png) repeat',
backgroundSize: '14px 14px',
}}
>
<div className="vertical-middle product-area">
<img className="product-logo" src="img/nacos.png" />
<p className="product-desc">{locale.Login.productDesc}</p>
</div>
<div className="animation animation1" />
<div className="animation animation2" />
<div className="animation animation3" />
<div className="animation animation4" />
<div className="animation animation5" />
<Card className="login-panel" contentHeight="auto">
<div className="login-header">{locale.Login.initPassword}</div>
<div className="internal-sys-tip">
<div>{locale.Login.internalSysTip1}</div>
<div>{locale.Login.internalSysTip2}</div>
</div>
{!consoleUiEnable && (
<Form className="login-form" field={this.field}>
<FormItem>
<Input
value="nacos"
readOnly
placeholder={locale.Login.pleaseInputUsername}
/>
</FormItem>
<FormItem>
<Input
htmlType="password"
placeholder={locale.Login.pleaseInputPasswordTips}
{...this.field.init('password', {})}
onKeyDown={this.onKeyDown}
/>
</FormItem>
<FormItem label=" ">
<Form.Submit onClick={this.handleSubmit}>{locale.Login.submit}</Form.Submit>
</FormItem>
</Form>
)}
{consoleUiEnable && (
<Message type="notice" style={{ marginTop: 30 }}>
<div dangerouslySetInnerHTML={{ __html: guideMsg }} />
</Message>
)}
</Card>
</section>
</div>
);
}
}

export default Register;
4 changes: 4 additions & 0 deletions console-ui/src/pages/Register/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

import Register from './Register';

export default Register;
142 changes: 142 additions & 0 deletions console-ui/src/pages/Register/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

$animationDuration: 2s;

// 品牌色
$brandColor: #2e3034;
$mobileWidth: 640px;
// 页面主体最大宽度
$contentWidth: 1280px;

@keyframes slashStar {
0% {
opacity: 1;
}

100% {
opacity: 0;
}
}

.home-page {
.top-section {
position: relative;
height: 100vh;
.login-panel {
position: absolute;
right: 40px;
width: 480px;
height: 540px;
top: 90px;
border: 0px;
input,
input::-webkit-input-placeholder {
font-size: 16px;
}
.login-header {
width: 100%;
line-height: 45px;
font-size: 32px;
margin-top: 58px;
text-align: center;
}
.internal-sys-tip {
width: 100%;
line-height: 25px;
font-size: 20px;
margin-top: 25px;
text-align: center;
font-weight: 800;
color: #ff0000cc;
}
.login-form {
width: 360px;
margin: 40px auto auto auto;
input {
height: 60px;
}
button {
width: 100%;
height: 60px;
font-size: 16px;
background: #4190ff 100%;
color: white;
border: 0px;
}
}
}
.animation {
position: absolute;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #1be1f6;
&1 {
left: 15%;
top: 70%;
animation: slashStar $animationDuration ease-in-out 0.3s infinite;
}
&2 {
left: 34%;
top: 35%;
animation: slashStar $animationDuration ease-in-out 1.2s infinite;
}
&3 {
left: 53%;
top: 20%;
animation: slashStar $animationDuration ease-in-out 0.5s infinite;
}
&4 {
left: 72%;
top: 64%;
animation: slashStar $animationDuration ease-in-out 0.8s infinite;
}
&5 {
left: 87%;
top: 30%;
animation: slashStar $animationDuration ease-in-out 1.5s infinite;
}
}
.vertical-middle {
position: absolute;
left: 0;
top: 50%;
margin-top: -47px;
transform: translateY(-50%);
}
.product-area {
width: 600px;
margin-left: 40px;
}
.product-logo {
display: block;
width: 257px;
height: 50px;
margin: 0;
}
.product-desc {
opacity: 0.8;
font-family: Avenir-Medium;
font-size: 24px;
color: #fff;
max-width: 780px;
margin: 12px auto 30px;
text-align: left;
line-height: 30px;
}
}
}
10 changes: 9 additions & 1 deletion console-ui/src/pages/Welcome/Welcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,18 @@ import { Redirect } from 'react-router-dom';
class Welcome extends React.Component {
static propTypes = {
functionMode: PropTypes.string,
authAdminRequest: PropTypes.string,
};

render() {
const { functionMode } = this.props;
const { functionMode, authAdminRequest } = this.props;
if (authAdminRequest && authAdminRequest === 'true') {
return (
<>
<Redirect to="/register" />
</>
);
}
const path = functionMode === 'naming' ? 'serviceManagement' : 'configurationManagement';
return <>{functionMode !== '' && <Redirect to={`/${path}`} />}</>;
}
Expand Down
Loading
Loading