feat: update login form

1. Change the domain option to input, requiring the user to enter <username>@<domain name>
2. update e2e case to support new login form

Change-Id: I55611abfc4d58278bddab24a958a1ec2de57e442
This commit is contained in:
zhangjingwei 2024-07-12 09:30:41 +08:00
parent 3465a2fb2f
commit a28eedf973
9 changed files with 74 additions and 41 deletions

View File

@ -0,0 +1,8 @@
---
features:
- |
Update login form:
* Change the domain selector to input, requiring the user to enter <username>@<domain name>, such as: admin@Default.
* If the user enters only <username>, the "Default" domain will be used, such as: admin.

View File

@ -29,6 +29,7 @@
"5min": "5min",
"8 to 16 characters, at least one uppercase letter, one lowercase letter, one number.": "8 to 16 characters, at least one uppercase letter, one lowercase letter, one number.",
"8 to 32 characters, at least one uppercase letter, one lowercase letter, one number and one special character.": "8 to 32 characters, at least one uppercase letter, one lowercase letter, one number and one special character.",
"<username>@<domain name>": "<username>@<domain name>",
"A command that will be sent to the container": "A command that will be sent to the container",
"A container with the same name already exists": "A container with the same name already exists",
"A dynamic scheduling algorithm that estimates the server load based on the number of currently active connections. The system allocates new connection requests to the server with the least number of current connections. Commonly used for long connection services, such as database connections and other services.": "A dynamic scheduling algorithm that estimates the server load based on the number of currently active connections. The system allocates new connection requests to the server with the least number of current connections. Commonly used for long connection services, such as database connections and other services.",
@ -1069,6 +1070,7 @@
"For GRE networks, valid segmentation IDs are 1 to 4294967295": "For GRE networks, valid segmentation IDs are 1 to 4294967295",
"For VLAN networks, valid segmentation IDs are 1 to 4094": "For VLAN networks, valid segmentation IDs are 1 to 4094",
"For VXLAN networks, valid segmentation IDs are 1 to 16777215": "For VXLAN networks, valid segmentation IDs are 1 to 16777215",
"For example: username@Default": "For example: username@Default",
"Forbidden": "Forbidden",
"Forbidden Domain": "Forbidden Domain",
"Forbidden Project": "Forbidden Project",
@ -1881,6 +1883,7 @@
"Please enter the server id to be reduced, and separate different id with \",\"": "Please enter the server id to be reduced, and separate different id with \",\"",
"Please fill in the peer network segment and subnet mask of CIDR format, the written subnets should be under the same router, one per line.": "Please fill in the peer network segment and subnet mask of CIDR format, the written subnets should be under the same router, one per line.",
"Please input": "Please input",
"Please input <username>@<domain name>!": "Please input <username>@<domain name>!",
"Please input ICMP code(0-255)": "Please input ICMP code(0-255)",
"Please input ICMP type(0-255)": "Please input ICMP type(0-255)",
"Please input IPv4 or IPv6 cidr": "Please input IPv4 or IPv6 cidr",
@ -1913,6 +1916,7 @@
"Please input protocol number if it absent in select list.": "Please input protocol number if it absent in select list.",
"Please input provider": "Please input provider",
"Please input snapshot name": "Please input snapshot name",
"Please input the correct format: <username>@<domain name>.": "Please input the correct format: <username>@<domain name>.",
"Please input transfer id": "Please input transfer id",
"Please input user name": "Please input user name",
"Please input value": "Please input value",
@ -1942,7 +1946,6 @@
"Please select source": "Please select source",
"Please select type": "Please select type",
"Please select volume type": "Please select volume type",
"Please select your Domain!": "Please select your Domain!",
"Please select your Region!": "Please select your Region!",
"Please select {label}!": "Please select {label}!",
"Please select {name} first": "Please select {name} first",
@ -2263,7 +2266,6 @@
"Select User Group": "Select User Group",
"Select Volume Snapshot": "Select Volume Snapshot",
"Select a QoS Policy": "Select a QoS Policy",
"Select a domain": "Select a domain",
"Select a login type": "Select a login type",
"Select a network": "Select a network",
"Select a project": "Select a project",

View File

@ -29,6 +29,7 @@
"5min": "5분",
"8 to 16 characters, at least one uppercase letter, one lowercase letter, one number.": "8 ~ 16 문자, 최소 대문자 한개, 소문자 한개, 숫자 한개, 특수 문자 한개",
"8 to 32 characters, at least one uppercase letter, one lowercase letter, one number and one special character.": "8 ~ 32 문자, 최소 대문자 한개, 소문자 한개, 숫자 한개, 특수 문자 한개",
"<username>@<domain name>": "<사용자 이름>@<도메인 이름>",
"A command that will be sent to the container": "컨테이너로 전송될 명령어",
"A container with the same name already exists": "동일한 이름의 컨테이너가 존재합니다.",
"A dynamic scheduling algorithm that estimates the server load based on the number of currently active connections. The system allocates new connection requests to the server with the least number of current connections. Commonly used for long connection services, such as database connections and other services.": "동적 스케쥴링 알고리즘은 현재 연결된 커넥션 수로 서버 로드를 예측합니다. 시스템은 최소 연결을 가진 서버로 새로운 연결을 할당합니다. 데이터베이스 연결 및 다른 서비스 처럼 오래 지속되는 연결을 갖는 서비스에 활용됩니다.",
@ -1069,6 +1070,7 @@
"For GRE networks, valid segmentation IDs are 1 to 4294967295": "GRE 네트워크의 경우, 유효한 segmentation ID는 1에서 4294967295까지 입니다.",
"For VLAN networks, valid segmentation IDs are 1 to 4094": "VLAN 네트워크의 경우, 유효한 segmentation ID는 1에서 4094까지 입니다.",
"For VXLAN networks, valid segmentation IDs are 1 to 16777215": "VXLAN 네트워크의 경우, 유효한 segmentation ID는 1에서 16777215까지 입니다.",
"For example: username@Default": "예: username@Default",
"Forbidden": "금지된",
"Forbidden Domain": "금지된 Domain",
"Forbidden Project": "금지된 Project",
@ -1881,6 +1883,7 @@
"Please enter the server id to be reduced, and separate different id with \",\"": "",
"Please fill in the peer network segment and subnet mask of CIDR format, the written subnets should be under the same router, one per line.": "",
"Please input": "",
"Please input <username>@<domain name>!": "<사용자 이름>@<도메인 이름>을 입력해주세요!",
"Please input ICMP code(0-255)": "",
"Please input ICMP type(0-255)": "",
"Please input IPv4 or IPv6 cidr": "",
@ -1913,6 +1916,7 @@
"Please input protocol number if it absent in select list.": "선택 목록에 없으면 프로토콜 번호를 입력하세요.",
"Please input provider": "제공자를 입력하세요.",
"Please input snapshot name": "snapshot 이름을 입력하세요.",
"Please input the correct format: <username>@<domain name>.": "올바른 형식(<사용자 이름>@<도메인 이름>)을 입력하세요.",
"Please input transfer id": "전송 ID를 입력하세요.",
"Please input user name": "사용자 이름을 입력하세요.",
"Please input value": "값을 입력하세요.",
@ -1942,7 +1946,6 @@
"Please select source": "소스를 선택하세요.",
"Please select type": "유형을 선택하세요.",
"Please select volume type": "볼륨 유형을 선택하세요.",
"Please select your Domain!": "도메인을 선택하세요!",
"Please select your Region!": "지역을 선택하세요!",
"Please select {label}!": "{label}을(를) 선택하세요!",
"Please select {name} first": "{name}을(를) 먼저 선택하세요.",
@ -2263,7 +2266,6 @@
"Select User Group": "",
"Select Volume Snapshot": "",
"Select a QoS Policy": "",
"Select a domain": "도메인 선택",
"Select a login type": "로그인 유형 선택",
"Select a network": "",
"Select a project": "",

View File

@ -29,6 +29,7 @@
"5min": "5 минут",
"8 to 16 characters, at least one uppercase letter, one lowercase letter, one number.": "8 до 16 символов, как минимум одна заглавная буква, одна строчная буква и одна цифра.",
"8 to 32 characters, at least one uppercase letter, one lowercase letter, one number and one special character.": "",
"<username>@<domain name>": "<имя пользователя>@<имя домена>",
"A command that will be sent to the container": "Команда, которая будет отправлена в контейнер",
"A container with the same name already exists": "Контейнер с таким же именем уже существует",
"A dynamic scheduling algorithm that estimates the server load based on the number of currently active connections. The system allocates new connection requests to the server with the least number of current connections. Commonly used for long connection services, such as database connections and other services.": "Динамический алгоритм планирования, который оценивает нагрузку сервера на основе количества активных соединений. Система выделяет новые запросы на соединение серверу с наименьшим количеством текущих соединений. Часто используется для долгосрочных сервисов с соединением, таких как подключения к базам данных и другие сервисы.",
@ -1069,6 +1070,7 @@
"For GRE networks, valid segmentation IDs are 1 to 4294967295": "Для сетей GRE допустимыми идентификаторами сегментации являются числа от 1 до 4294967295",
"For VLAN networks, valid segmentation IDs are 1 to 4094": "Для сетей VLAN допустимыми идентификаторами сегментации являются числа от 1 до 4094",
"For VXLAN networks, valid segmentation IDs are 1 to 16777215": "Для сетей VXLAN допустимыми идентификаторами сегментации являются числа от 1 до 16777215",
"For example: username@Default": "Например: username@Default",
"Forbidden": "Запрещено",
"Forbidden Domain": "Запрещен домен",
"Forbidden Project": "Запрещен проект",
@ -1881,6 +1883,7 @@
"Please enter the server id to be reduced, and separate different id with \",\"": "Пожалуйста, введите идентификатор сервера, который необходимо уменьшить, и разделите разные идентификаторы запятой \",\"",
"Please fill in the peer network segment and subnet mask of CIDR format, the written subnets should be under the same router, one per line.": "Пожалуйста, заполните сегмент сети пира и маску подсети в формате CIDR, написанные подсети должны быть под одним маршрутизатором, по одной на строку.",
"Please input": "Пожалуйста, введите",
"Please input <username>@<domain name>!": "Пожалуйста, введите <имя пользователя>@<имя домена>!",
"Please input ICMP code(0-255)": "Пожалуйста, введите код ICMP (0-255)",
"Please input ICMP type(0-255)": "Пожалуйста, введите тип ICMP (0-255)",
"Please input IPv4 or IPv6 cidr": "Пожалуйста, введите CIDR IPv4 или IPv6",
@ -1913,6 +1916,7 @@
"Please input protocol number if it absent in select list.": "Пожалуйста, введите номер протокола, если его нет в списке выбора.",
"Please input provider": "Пожалуйста, введите провайдера",
"Please input snapshot name": "Пожалуйста, введите имя снимка",
"Please input the correct format: <username>@<domain name>.": "Пожалуйста, введите правильный формат: <имя пользователя>@<имя домена>.",
"Please input transfer id": "Пожалуйста, введите идентификатор передачи",
"Please input user name": "Пожалуйста, введите имя пользователя",
"Please input value": "Пожалуйста, введите значение",
@ -1942,7 +1946,6 @@
"Please select source": "Пожалуйста, выберите источник",
"Please select type": "Пожалуйста, выберите тип",
"Please select volume type": "Пожалуйста, выберите тип диска",
"Please select your Domain!": "Пожалуйста, выберите ваш домен!",
"Please select your Region!": "Пожалуйста, выберите ваш регион!",
"Please select {label}!": "Пожалуйста, выберите {label}!",
"Please select {name} first": "Пожалуйста, сначала выберите {name}",
@ -2263,7 +2266,6 @@
"Select User Group": "Выберите группу пользователей",
"Select Volume Snapshot": "Выберите снимок диска",
"Select a QoS Policy": "",
"Select a domain": "Выберите домен",
"Select a login type": "Выберите тип входа",
"Select a network": "",
"Select a project": "",

View File

@ -29,6 +29,7 @@
"5min": "5 Dk",
"8 to 16 characters, at least one uppercase letter, one lowercase letter, one number.": "8 ile 16 karakter, en az bir büyük harf, en az bir küçük harf, en az bir rakam.",
"8 to 32 characters, at least one uppercase letter, one lowercase letter, one number and one special character.": "",
"<username>@<domain name>": "<kullanıcı adı>@<alan adı>",
"A command that will be sent to the container": "Konteyner'a gönderilecek bir komut",
"A container with the same name already exists": "Aynı isme sahip bir konteyner bulunmaktadır.",
"A dynamic scheduling algorithm that estimates the server load based on the number of currently active connections. The system allocates new connection requests to the server with the least number of current connections. Commonly used for long connection services, such as database connections and other services.": "Dinamik zamanlama algoritması, sunucu yükünü o anda açık olan bağlantı sayısından tahmin eder. Sistem, o anda en az sayıda bağlantıya sahip sunucuya yeni bağlantılar tahsis eder. Veritabanı bağlantıları gibi uzun ömürlü bağlantılara sahip hizmetler için kullanılır.",
@ -1069,6 +1070,7 @@
"For GRE networks, valid segmentation IDs are 1 to 4294967295": "GRE ağları için geçerli segmentasyon kimlikleri 1 ile 4294967295 arasındadır.",
"For VLAN networks, valid segmentation IDs are 1 to 4094": "VLAN ağları için geçerli segmentasyon kimlikleri 1 ile 4094 arasındadır.",
"For VXLAN networks, valid segmentation IDs are 1 to 16777215": "VXLAN ağları için geçerli segmentasyon kimlikleri 1 ile 16777215 arasındadır.",
"For example: username@Default": "Örneğin: username@Default",
"Forbidden": "Yasaklanmış",
"Forbidden Domain": "Yasaklanmış Etki Alanı",
"Forbidden Project": "Yasaklanmış Proje",
@ -1881,6 +1883,7 @@
"Please enter the server id to be reduced, and separate different id with \",\"": "Azaltılacak sunucu ID'sini girin ve farklı ID'leri \",\" ile ayırın",
"Please fill in the peer network segment and subnet mask of CIDR format, the written subnets should be under the same router, one per line.": "CIDR biçimindeki eş ağ segmenti ve alt ağ maskesini doldurun, yazılı alt ağlar aynı yönlendirici altında satır başına bir adet olmalıdır.",
"Please input": "Lütfen girin",
"Please input <username>@<domain name>!": "Lütfen <kullanıcı adı>@<alan adı> girin!",
"Please input ICMP code(0-255)": "Lütfen ICMP kodu girin (0-255)",
"Please input ICMP type(0-255)": "Lütfen ICMP türü girin (0-255)",
"Please input IPv4 or IPv6 cidr": "Lütfen IPv4 veya IPv6 cidr girin",
@ -1913,6 +1916,7 @@
"Please input protocol number if it absent in select list.": "Eğer seçim listesinde yoksa, lütfen protokol numarasını girin.",
"Please input provider": "Lütfen sağlayıcı girin",
"Please input snapshot name": "Lütfen anlık görüntü adı girin",
"Please input the correct format: <username>@<domain name>.": "Lütfen doğru biçimi girin: <kullanıcı adı>@<etki alanı adı>.",
"Please input transfer id": "Lütfen transfer ID girin",
"Please input user name": "Lütfen kullanıcı adı girin",
"Please input value": "Lütfen değer girin",
@ -1942,7 +1946,6 @@
"Please select source": "Lütfen kaynak seçin",
"Please select type": "Lütfen tür seçin",
"Please select volume type": "Lütfen disk türü seçin",
"Please select your Domain!": "Lütfen alan adınızı seçin!",
"Please select your Region!": "Lütfen bölgenizi seçin!",
"Please select {label}!": "Lütfen {label} seçin!",
"Please select {name} first": "Lütfen önce {name} seçin",
@ -2263,7 +2266,6 @@
"Select User Group": "Kullanıcı Grubu Seçin",
"Select Volume Snapshot": "Disk Anlık Görüntüsü Seçin",
"Select a QoS Policy": "",
"Select a domain": "Bir etki alanı seçin",
"Select a login type": "Bir giriş türü seçin",
"Select a network": "",
"Select a project": "",

View File

@ -29,6 +29,7 @@
"5min": "5分钟",
"8 to 16 characters, at least one uppercase letter, one lowercase letter, one number.": "8个到16个字符至少一个大写字母一个小写字母一个数字。",
"8 to 32 characters, at least one uppercase letter, one lowercase letter, one number and one special character.": "8个到32个字符至少一个大写字母一个小写字母一个数字和一个特殊字符。",
"<username>@<domain name>": "<用户名>@<用户域名>",
"A command that will be sent to the container": "将发送到容器的命令",
"A container with the same name already exists": "已存在同名容器",
"A dynamic scheduling algorithm that estimates the server load based on the number of currently active connections. The system allocates new connection requests to the server with the least number of current connections. Commonly used for long connection services, such as database connections and other services.": "通过当前活跃的连接数来估计服务器负载情况的一种动态调度算法,系统把新的连接请求分配给当前连接数目最少的服务器。常用于长连接服务,例如数据库连接等服务。",
@ -1069,6 +1070,7 @@
"For GRE networks, valid segmentation IDs are 1 to 4294967295": "对于GRE网络有效的段ID范围是从1到4294967295",
"For VLAN networks, valid segmentation IDs are 1 to 4094": "对于VLAN网络有效的段ID范围是从1到4094",
"For VXLAN networks, valid segmentation IDs are 1 to 16777215": "对于VXLAN网络有效的段ID范围是从1到16777215",
"For example: username@Default": "例如username@Default",
"Forbidden": "禁用",
"Forbidden Domain": "禁用域",
"Forbidden Project": "禁用项目",
@ -1881,6 +1883,7 @@
"Please enter the server id to be reduced, and separate different id with \",\"": "请输入指定缩减的server ID并且不同ID之间用 ',' 分隔",
"Please fill in the peer network segment and subnet mask of CIDR format, the written subnets should be under the same router, one per line.": "请填写CIDR格式的对端网段且填写的网段需在同一个路由下每行一个。",
"Please input": "请输入",
"Please input <username>@<domain name>!": "请输入<用户名>@<用户域名>",
"Please input ICMP code(0-255)": "请输入ICMP编码(0-255)",
"Please input ICMP type(0-255)": "请输入ICMP类型(0-255)",
"Please input IPv4 or IPv6 cidr": "请输入IPv4或IPv6网段地址",
@ -1913,6 +1916,7 @@
"Please input protocol number if it absent in select list.": "如果选择列表中没有,请输入协议号。",
"Please input provider": "请输入提供者",
"Please input snapshot name": "请输入快照名称",
"Please input the correct format: <username>@<domain name>.": "请输入正确格式:<用户名>@<用户域名>",
"Please input transfer id": "请输入转让Id",
"Please input user name": "请输入用户名称",
"Please input value": "请输入值",
@ -1942,7 +1946,6 @@
"Please select source": "请选择源",
"Please select type": "请选择类型",
"Please select volume type": "请选择云硬盘类型",
"Please select your Domain!": "请选择Domain",
"Please select your Region!": "请选择Region",
"Please select {label}!": "请选择{label}",
"Please select {name} first": "请先选择{name}",
@ -2263,7 +2266,6 @@
"Select User Group": "选择用户组",
"Select Volume Snapshot": "选择云硬盘快照",
"Select a QoS Policy": "请选择Qos策略",
"Select a domain": "请选择Domain",
"Select a login type": "请选择登录方式",
"Select a network": "请选择网络",
"Select a project": "请选择项目",

View File

@ -36,16 +36,10 @@ export class Login extends Component {
}
componentDidMount() {
this.getDomains();
this.getRegions();
this.getSSO();
}
async getDomains() {
await this.store.fetchDomainList();
this.updateDefaultValue();
}
async getRegions() {
await this.store.fetchRegionList();
this.updateDefaultValue();
@ -78,13 +72,6 @@ export class Login extends Component {
return t('Welcome, {name}', { name });
}
get domains() {
return (this.store.domains || []).map((it) => ({
label: it,
value: it,
}));
}
get regions() {
return (this.store.regions || []).map((it) => ({
label: it,
@ -92,6 +79,10 @@ export class Login extends Component {
}));
}
get domains() {
return [];
}
get nextPage() {
const { location = {} } = this.props;
const { search } = location;
@ -165,9 +156,6 @@ export class Login extends Component {
if (this.regions.length === 1) {
data.region = this.regions[0].value;
}
if (this.domains.length === 1) {
data.domain = this.domains[0].value;
}
return data;
}
@ -200,16 +188,16 @@ export class Login extends Component {
const domainItem = {
name: 'domain',
required: true,
message: t('Please select your Domain!'),
render: () => (
<Select placeholder={t('Select a domain')} options={this.domains} />
),
render: () => <Input placeholder={t('<username>@<domain name>')} />,
extra: t('For example: username@Default'),
rules: [{ required: true, validator: this.usernameDomainValidator }],
};
const usernameItem = {
name: 'username',
required: true,
required: false,
message: t('Please input your Username!'),
render: () => <Input placeholder={t('Username')} />,
hidden: true,
};
const passwordItem = {
name: 'password',
@ -327,8 +315,11 @@ export class Login extends Component {
message: '',
error: false,
});
const { domain, password, region, username } = values;
const body = { domain, password, region, username };
const { password, region, domain } = values;
const usernameDomain = this.getUsernameAndDomain({
usernameDomain: domain,
});
const body = { password, region, ...usernameDomain };
this.rootStore.login(body).then(
() => {
this.onLoginSuccess();
@ -359,6 +350,35 @@ export class Login extends Component {
return t('Username or password is incorrect');
}
getUsernameAndDomain = (values) => {
const { usernameDomain } = values;
const tmp = usernameDomain.trim().split('@');
return {
username: tmp[0],
domain: tmp[1] || 'Default',
};
};
usernameDomainValidator = (rule, value) => {
if (!value || !value.trim()) {
return Promise.reject(t('Please input <username>@<domain name>!'));
}
const tmp = value.trim().split('@');
const message = t(
'Please input the correct format: <username>@<domain name>.'
);
if (tmp.length > 2) {
return Promise.reject(new Error(message));
}
const { username, domain } = this.getUsernameAndDomain({
usernameDomain: value,
});
if (!username || !domain) {
return Promise.reject(new Error(message));
}
return Promise.resolve();
};
dealWithChangePassword = (detail, values) => {
const userId = this.getUserId(detail);
const data = {

View File

@ -14,20 +14,17 @@
describe('The Login Page', () => {
it('successfully loads', () => {
cy.intercept('GET', '/domains').as('domains');
cy.intercept('GET', '/regions').as('regions');
cy.visit('/');
cy.waitLoginFormLoading();
cy.wait('@domains');
cy.wait('@regions');
});
it('successfully error username and password', () => {
cy.wait(5000);
cy.loginFormSelect(0, 'RegionOne')
.loginFormSelect(1, 'Default')
.loginFormInput('username', `${Cypress.env('username')}1`)
.loginFormInput('domain', `${Cypress.env('username')}1`)
.loginFormInput('password', `${Cypress.env('password')}1`)
.loginFormSubmit()
.get('#normal_login_error')
@ -37,8 +34,7 @@ describe('The Login Page', () => {
it('successfully login and check menu', () => {
cy.wait(5000);
cy.loginFormSelect(0, 'RegionOne')
.loginFormSelect(1, 'Default')
.loginFormInput('username', Cypress.env('username'))
.loginFormInput('domain', Cypress.env('username'))
.loginFormInput('password', Cypress.env('password'))
.loginFormSubmit()
.wait(2000)

View File

@ -124,8 +124,7 @@ Cypress.Commands.add('loginByPage', (username, password) => {
cy.visit('/');
cy.waitLoginFormLoading().wait(5000);
cy.loginFormSelect(0, 'RegionOne')
.loginFormSelect(1, 'Default')
.loginFormInput('username', username || Cypress.env('username'))
.loginFormInput('domain', username || Cypress.env('username'))
.loginFormInput('password', password || Cypress.env('password'))
.loginFormSubmit();
});