Skip to content

Commit

Permalink
Feat: force reset password when first time login (kubevela#716)
Browse files Browse the repository at this point in the history
* Force reset password when first time login

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

Add test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

add initialize admin twice test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

use es6 braces code format

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

lint style and remove init admin

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

fix tests

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

remove the legacy admin init logic

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

remove all model.DefaultAdminUserName in non-test file

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* remove model.DefaultAdminUserName in test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* tidy code

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* reviewable

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* Fix unit test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* fix unit test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* Fix auth ut

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* fix dex login test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* fix broken configure admin ut

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* fix auth ut

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* reviewable

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* add debug log

remove addon enable process before e2e test

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

* remove debug info

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>

---------

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
Signed-off-by: liyanfang <liyanfang@cmss.chinamobile.com>
  • Loading branch information
chivalryq authored and liyanfang committed Apr 8, 2023
1 parent debed7e commit c68f3e7
Show file tree
Hide file tree
Showing 50 changed files with 805 additions and 704 deletions.
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ public

dist

pkg/
pkg/
8 changes: 6 additions & 2 deletions .github/workflows/server-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ jobs:
make e2e-setup-core
make start-addon-mock-server
make load-image
make enable-addon
make enable-addon-no-replicas
- name: Run server e2e test
run: |
Expand All @@ -174,6 +174,10 @@ jobs:
docker run --rm -v `pwd`/e2e-plugins:/plugins oamdev/velaux:latest cp -r -a /app/velaux/plugins/app-demo /plugins/app-demo
make e2e-server-test
- name: Test addon enable
run: |
make enable-addon
- name: Upload coverage report
uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
with:
Expand All @@ -199,4 +203,4 @@ jobs:
file: ./Dockerfile
platforms: linux/arm64
push: false
tags: oamdev/velaux:latest
tags: oamdev/velaux:latest
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,11 @@ start-addon-mock-server:
load-image:
k3d image import oamdev/velaux:latest || { echo >&2 "kind not installed or error loading image: $(VELA_CORE_TEST_IMAGE)"; exit 1; }

# Only try to install the addon.
enable-addon-no-replicas:
vela addon enable ./addon replicas=0

enable-addon:
vela addon enable ./addon
vela addon enable ./addon replicas=0

.PHONY: e2e-server-test
e2e-server-test:
Expand Down Expand Up @@ -132,4 +133,4 @@ check-diff: reviewable
@$(OK) branch is clean

run-server:
go run ./cmd/server/main.go
go run ./cmd/server/main.go
43 changes: 35 additions & 8 deletions e2e-test/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import (

"github.com/kubevela/velaux/pkg/server"
"github.com/kubevela/velaux/pkg/server/config"
"github.com/kubevela/velaux/pkg/server/domain/service"
"github.com/kubevela/velaux/pkg/server/infrastructure/clients"
"github.com/kubevela/velaux/pkg/server/infrastructure/datastore"
apisv1 "github.com/kubevela/velaux/pkg/server/interfaces/api/dto/v1"
Expand All @@ -47,9 +46,10 @@ var k8sClient client.Client
var token string

const (
baseDomain = "http://127.0.0.1:8001"
baseURL = "http://127.0.0.1:8001/api/v1"
testNSprefix = "api-test-"
baseDomain = "http://127.0.0.1:8001"
baseURL = "http://127.0.0.1:8001/api/v1"
testNSprefix = "api-test-"
fakeAdminName = "admin"
)

func TestE2eApiserverTest(t *testing.T) {
Expand Down Expand Up @@ -87,18 +87,45 @@ var _ = BeforeSuite(func() {
Expect(err).ShouldNot(HaveOccurred())
}()
By("wait for api server to start")
defaultAdminPassword := "VelaUX12345"
Eventually(
func() error {
password := os.Getenv("VELA_UX_PASSWORD")
if password == "" {
password = service.InitAdminPassword
password = defaultAdminPassword
}
// init admin user
var initReq = apisv1.InitAdminRequest{
Name: fakeAdminName,
Password: password,
Email: "fake@email.com",
}
bodyByte, err := json.Marshal(initReq)
Expect(err).Should(BeNil())
initHtpReq, err := http.NewRequest("PUT", baseURL+"/auth/init_admin", bytes.NewBuffer(bodyByte))
Expect(err).Should(BeNil())
initHtpReq.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(initHtpReq)
if err != nil {
return err
}
// either 200 or "admin user is already configured"
if res.StatusCode != 200 {
body, err := io.ReadAll(res.Body)
Expect(err).Should(BeNil())
if !strings.Contains(string(body), "admin user is already configured") {
return fmt.Errorf("init admin failed: %s", string(body))
}
}

// login
var req = apisv1.LoginRequest{
Username: "admin",
Username: fakeAdminName,
Password: password,
}
bodyByte, err := json.Marshal(req)
bodyByte, err = json.Marshal(req)
Expect(err).Should(BeNil())

resp, err := http.Post(baseURL+"/auth/login", "application/json", bytes.NewBuffer(bodyByte))
if err != nil {
return err
Expand All @@ -119,7 +146,7 @@ var _ = BeforeSuite(func() {
err = json.NewDecoder(resp.Body).Decode(code)
Expect(err).Should(BeNil())
return fmt.Errorf("rest service not ready code:%d message:%s", resp.StatusCode, code.Message)
}, time.Second*20, time.Millisecond*200).Should(BeNil())
}, time.Second*60, time.Millisecond*200).Should(Succeed())
var err error
k8sClient, err = clients.GetKubeClient()
Expect(err).ShouldNot(HaveOccurred())
Expand Down
18 changes: 15 additions & 3 deletions packages/velaux-ui/src/api/authentication.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
authenticationLogin,
authenticationAdminConfigured,
authenticationDexConfig,
authenticationSystemInfo,
authenticationInitAdmin,
authenticationLogin,
authenticationLoginType,
authenticationSystemInfo,
authenticationUserInfo,
} from './productionLink';
import { post, get, put } from './request';
import { get, post, put } from './request';

export function loginSSO(params: { code: string }) {
const url = authenticationLogin;
Expand Down Expand Up @@ -36,3 +38,13 @@ export function getLoginUserInfo() {
const url = authenticationUserInfo;
return get(url, {}).then((res) => res);
}

export function isAdminConfigured() {
const url = authenticationAdminConfigured
return get(url, {}).then((res) => res);
}

export function initAdmin(params: { name: string; password: string; email: string }) {
const url = authenticationInitAdmin
return put(url, params).then((res) => res);
}
2 changes: 2 additions & 0 deletions packages/velaux-ui/src/api/productionLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export const authenticationSystemInfo = `/api/v1/system_info`;
export const authenticationLoginType = `/api/v1/auth/login_type`;
export const authenticationRefreshToken = `/api/v1/auth/refresh_token`;
export const authenticationUserInfo = `/api/v1/auth/user_info`;
export const authenticationAdminConfigured = `/api/v1/auth/admin_configured`;
export const authenticationInitAdmin = `/api/v1/auth/init_admin`;
export const users = `/api/v1/users`;
export const roles = `/api/v1/roles`;
export const platformPermissions = `/api/v1/permissions`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { Grid, Form, Input, Field, Message, Dialog } from '@alifd/next';
import { Dialog, Field, Form, Grid, Input, Message } from '@alifd/next';
import React, { Component, Fragment } from 'react';
import { AiOutlineEye } from 'react-icons/ai';

import { updateUser } from '../../../../api/users';
import Translation from '../../../../components/Translation';
import i18n from '../../../../i18n';
import type { LoginUserInfo } from '../../../../interface/user';
import { checkUserPassword } from '../../../../utils/common';
import { checkName, checkUserPassword } from '../../../../utils/common';
import locale from '../../../../utils/locale';
import { initAdmin } from "../../../../api/authentication";

type Props = {
userInfo?: LoginUserInfo;
onClose: () => void;
};

Expand All @@ -21,6 +18,7 @@ type State = {

class EditPlatFormUserDialog extends Component<Props, State> {
field: Field;

constructor(props: Props) {
super(props);
this.field = new Field(this);
Expand All @@ -30,26 +28,24 @@ class EditPlatFormUserDialog extends Component<Props, State> {
};
}

onUpdateUser = async () => {
onInitAdmin = async () => {
this.field.validate((error: any, values: any) => {
if (error) {
return;
}
const { userInfo } = this.props;
const { email, password } = values;
const { name, password, email } = values;
const params = {
name: userInfo?.name || '',
alias: userInfo?.alias || '',
name,
email,
password,
};
this.setState({
isLoading: true,
});
updateUser(params)
.then((res) => {
if (res) {
Message.success(<Translation>User updated successfully</Translation>);
initAdmin(params)
.then((res: { success: boolean }) => {
if (res && res.success) {
Message.success(<Translation>Admin User Initialized Successfully</Translation>);
this.props.onClose();
}
})
Expand Down Expand Up @@ -91,11 +87,36 @@ class EditPlatFormUserDialog extends Component<Props, State> {
visible={true}
title={this.showTitle()}
style={{ width: '600px' }}
onOk={this.onUpdateUser}
onOk={this.onInitAdmin}
locale={locale().Dialog}
footerActions={['ok']}
>
<Form loading={isLoading} {...formItemLayout} field={this.field}>
<Row>
<Col span={24} style={{ padding: '0 8px' }}>
<FormItem label={<Translation>Admin Username</Translation>} required>
<Input
name="name"
htmlType=""
placeholder={i18n.t('Please input the admin username').toString()}
{...init('name', {
rules: [
{
required: true,
pattern: checkName,
message: (
<Translation>
You must input a valid name
</Translation>
),
},
],
})}
/>
</FormItem>
</Col>
</Row>

<Row>
<Col span={24} style={{ padding: '0 8px' }}>
<FormItem label={<Translation>Password</Translation>} required>
Expand Down
25 changes: 2 additions & 23 deletions packages/velaux-ui/src/layout/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ import type { LoginUserInfo } from '../../interface/user';
import { getData, setData } from '../../utils/cache';
import locale from '../../utils/locale';
import { checkPermission } from '../../utils/permission';
import { getBrowserNameAndVersion, isAdminUserCheck } from '../../utils/utils';
import { getBrowserNameAndVersion } from '../../utils/utils';
import CloudShell from '../CloudShell';
import { locationService } from '../../services/LocationService';

import EditPlatFormUserDialog from './components/EditPlatFormUserDialog';
import { LayoutMode, Workspace } from '@velaux/data';
import { Dispatch } from 'redux';
import { menuService } from '../../services/MenuService';
Expand All @@ -50,7 +49,6 @@ type Props = {

type State = {
platformSetting: boolean;
isEditAdminUser: boolean;
grafanaConfigs?: Config[];
workspaces: Workspace[];
};
Expand All @@ -65,7 +63,6 @@ class Header extends Component<Props, State> {
super(props);
this.state = {
platformSetting: false,
isEditAdminUser: false,
workspaces: [],
};
}
Expand Down Expand Up @@ -158,7 +155,6 @@ class Header extends Component<Props, State> {
this.props.dispatch({
type: 'user/getLoginUserInfo',
callback: () => {
this.isEditPlatForm();
this.loadGrafanaIntegration();
this.loadWorkspaces();
},
Expand Down Expand Up @@ -221,24 +217,10 @@ class Header extends Component<Props, State> {
this.setState({ platformSetting: true });
};

isEditPlatForm = () => {
const { userInfo } = this.props;
const isAdminUser = isAdminUserCheck(userInfo);
if (isAdminUser && userInfo && !userInfo.email) {
this.setState({
isEditAdminUser: true,
});
}
};

onCloseEditAdminUser = () => {
this.setState({ isEditAdminUser: false });
};

render() {
const { Row } = Grid;
const { systemInfo, dispatch, show, userInfo, mode, currentWorkspace } = this.props;
const { platformSetting, isEditAdminUser, grafanaConfigs, workspaces } = this.state;
const { platformSetting, grafanaConfigs, workspaces } = this.state;

return (
<div className="layout-top-bar" id="layout-top-bar">
Expand Down Expand Up @@ -425,9 +407,6 @@ class Header extends Component<Props, State> {
/>
)}
</If>
<If condition={isEditAdminUser}>
<EditPlatFormUserDialog userInfo={userInfo} onClose={this.onCloseEditAdminUser} />
</If>
<If condition={show}>
<CloudShell />
</If>
Expand Down
7 changes: 5 additions & 2 deletions packages/velaux-ui/src/locals/Zh/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@
"Logout": "退出登录",
"Please input the password": "请输入密码",
"Please input the username": "请输入用户账号",
"Please input the admin username": "请输入管理员账号",
"The password should be 8-16 bits and contain at least one number and one letter": "密码必须包含至少一个数字和字母,长度在8-16位之间",
"Config with external systems and configuration management.": "与外部系统和配置管理集成.",
"Please firstly select a version": "请先选择一个启用的版本",
Expand Down Expand Up @@ -533,6 +534,7 @@
"Please input a valid email": "请输入有效的电子邮件地址",
"Please input a email": "请输入电子邮箱地址",
"User updated successfully": "用户更新成功",
"Admin User Initialized Successfully": "管理员用户初始化成功",
"Reset the password and email for the administrator account": "重置管理员帐户的密码和电子邮件地址",
"Please input the alias": "请输入别名",
"User experience improvement plan": "用户体验提升计划",
Expand Down Expand Up @@ -622,5 +624,6 @@
"Show Values File": "查看 Value 文件",
"Showing all projects you are permitted": "你拥有权限的所有项目",
"More": "显示更多",
"Hide": "收起"
}
"Hide": "收起",
"Admin Username": "管理员账号名称"
}
1 change: 1 addition & 0 deletions packages/velaux-ui/src/pages/Login/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
color: #fff;
cursor: pointer;
transition: all 0.3s;
z-index: 2000;
a {
color: #fff;
cursor: pointer;
Expand Down
Loading

0 comments on commit c68f3e7

Please sign in to comment.