mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-07-01 12:32:09 +00:00
Compare commits
5 commits
c5b9cb76b7
...
3247a2d2eb
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3247a2d2eb | ||
![]() |
cad07be847 | ||
![]() |
6ecdb6e03b | ||
![]() |
5546c27fea | ||
![]() |
bd80073402 |
19 changed files with 167 additions and 86 deletions
17
main.go
17
main.go
|
@ -232,7 +232,7 @@ func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime stri
|
|||
}
|
||||
}
|
||||
|
||||
func updateSetting(port int, username string, password string, webBasePath string, listenIP string) {
|
||||
func updateSetting(port int, username string, password string, webBasePath string, listenIP string, resetTwoFactor bool) {
|
||||
err := database.InitDB(config.GetDBPath())
|
||||
if err != nil {
|
||||
fmt.Println("Database initialization failed:", err)
|
||||
|
@ -269,6 +269,17 @@ func updateSetting(port int, username string, password string, webBasePath strin
|
|||
}
|
||||
}
|
||||
|
||||
if resetTwoFactor {
|
||||
err := settingService.SetTwoFactorEnable(false)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Failed to reset two-factor authentication:", err)
|
||||
} else {
|
||||
settingService.SetTwoFactorToken("")
|
||||
fmt.Println("Two-factor authentication reset successfully")
|
||||
}
|
||||
}
|
||||
|
||||
if listenIP != "" {
|
||||
err := settingService.SetListen(listenIP)
|
||||
if err != nil {
|
||||
|
@ -376,6 +387,7 @@ func main() {
|
|||
var reset bool
|
||||
var show bool
|
||||
var getCert bool
|
||||
var resetTwoFactor bool
|
||||
settingCmd.BoolVar(&reset, "reset", false, "Reset all settings")
|
||||
settingCmd.BoolVar(&show, "show", false, "Display current settings")
|
||||
settingCmd.IntVar(&port, "port", 0, "Set panel port number")
|
||||
|
@ -383,6 +395,7 @@ func main() {
|
|||
settingCmd.StringVar(&password, "password", "", "Set login password")
|
||||
settingCmd.StringVar(&webBasePath, "webBasePath", "", "Set base path for Panel")
|
||||
settingCmd.StringVar(&listenIP, "listenIP", "", "set panel listenIP IP")
|
||||
settingCmd.BoolVar(&resetTwoFactor, "resetTwoFactor", false, "Reset two-factor authentication settings")
|
||||
settingCmd.BoolVar(&getListen, "getListen", false, "Display current panel listenIP IP")
|
||||
settingCmd.BoolVar(&getCert, "getCert", false, "Display current certificate settings")
|
||||
settingCmd.StringVar(&webCertFile, "webCert", "", "Set path to public key file for panel")
|
||||
|
@ -427,7 +440,7 @@ func main() {
|
|||
if reset {
|
||||
resetSetting()
|
||||
} else {
|
||||
updateSetting(port, username, password, webBasePath, listenIP)
|
||||
updateSetting(port, username, password, webBasePath, listenIP, resetTwoFactor)
|
||||
}
|
||||
if show {
|
||||
showSetting(show)
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<p>{{ i18n "pages.settings.security.twoFactorModalSecondStep" }}</p>
|
||||
<a-input v-model.trim="twoFactorModal.enteredCode" :style="{ width: '100%' }"></a-input>
|
||||
</template>
|
||||
<template v-if="twoFactorModal.type === 'remove'">
|
||||
<p>{{ i18n "pages.settings.security.twoFactorModalRemoveStep" }}</p>
|
||||
<template v-if="twoFactorModal.type === 'confirm'">
|
||||
<p>[[ twoFactorModal.description ]]</p>
|
||||
<a-input v-model.trim="twoFactorModal.enteredCode" :style="{ width: '100%' }"></a-input>
|
||||
</template>
|
||||
<template slot="footer">
|
||||
|
@ -32,6 +32,7 @@
|
|||
<script>
|
||||
const twoFactorModal = {
|
||||
title: '',
|
||||
description: '',
|
||||
fileName: '',
|
||||
token: '',
|
||||
enteredCode: '',
|
||||
|
@ -45,17 +46,6 @@
|
|||
ObjectUtil.execute(twoFactorModal.confirm, true)
|
||||
|
||||
twoFactorModal.close()
|
||||
|
||||
switch (twoFactorModal.type) {
|
||||
case 'set':
|
||||
Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalSetSuccess" }}')
|
||||
break;
|
||||
case 'remove':
|
||||
Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalDeleteSuccess" }}')
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Vue.prototype.$message['error']('{{ i18n "pages.settings.security.twoFactorModalError" }}')
|
||||
}
|
||||
|
@ -67,11 +57,13 @@
|
|||
},
|
||||
show: function ({
|
||||
title = '',
|
||||
description = '',
|
||||
token = '',
|
||||
type = 'set',
|
||||
confirm = (success) => { }
|
||||
}) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.token = token;
|
||||
this.visible = true;
|
||||
this.confirm = confirm;
|
||||
|
|
|
@ -310,12 +310,30 @@
|
|||
}
|
||||
},
|
||||
async updateUser() {
|
||||
this.loading(true);
|
||||
const msg = await HttpUtil.post("/panel/setting/updateUser", this.user);
|
||||
this.loading(false);
|
||||
if (msg.success) {
|
||||
this.user = {};
|
||||
window.location.replace(basePath + "logout");
|
||||
const sendUpdateUserRequest = async () => {
|
||||
this.loading(true);
|
||||
const msg = await HttpUtil.post("/panel/setting/updateUser", this.user);
|
||||
this.loading(false);
|
||||
if (msg.success) {
|
||||
this.user = {};
|
||||
window.location.replace(basePath + "logout");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.allSetting.twoFactorEnable) {
|
||||
twoFactorModal.show({
|
||||
title: '{{ i18n "pages.settings.security.twoFactorModalChangeCredentialsTitle" }}',
|
||||
description: '{{ i18n "pages.settings.security.twoFactorModalChangeCredentialsStep" }}',
|
||||
token: this.allSetting.twoFactorToken,
|
||||
type: 'confirm',
|
||||
confirm: (success) => {
|
||||
if (success) {
|
||||
sendUpdateUserRequest();
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
sendUpdateUserRequest();
|
||||
}
|
||||
},
|
||||
async restartPanel() {
|
||||
|
@ -353,6 +371,8 @@
|
|||
type: 'set',
|
||||
confirm: (success) => {
|
||||
if (success) {
|
||||
Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalSetSuccess" }}')
|
||||
|
||||
this.allSetting.twoFactorToken = newTwoFactorToken
|
||||
}
|
||||
|
||||
|
@ -362,10 +382,13 @@
|
|||
} else {
|
||||
twoFactorModal.show({
|
||||
title: '{{ i18n "pages.settings.security.twoFactorModalDeleteTitle" }}',
|
||||
description: '{{ i18n "pages.settings.security.twoFactorModalRemoveStep" }}',
|
||||
token: this.allSetting.twoFactorToken,
|
||||
type: 'remove',
|
||||
type: 'confirm',
|
||||
confirm: (success) => {
|
||||
if (success) {
|
||||
Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalDeleteSuccess" }}')
|
||||
|
||||
this.allSetting.twoFactorEnable = false
|
||||
this.allSetting.twoFactorToken = ""
|
||||
}
|
||||
|
|
|
@ -322,10 +322,18 @@ func (s *SettingService) GetTwoFactorEnable() (bool, error) {
|
|||
return s.getBool("twoFactorEnable")
|
||||
}
|
||||
|
||||
func (s *SettingService) SetTwoFactorEnable(value bool) error {
|
||||
return s.setBool("twoFactorEnable", value)
|
||||
}
|
||||
|
||||
func (s *SettingService) GetTwoFactorToken() (string, error) {
|
||||
return s.getString("twoFactorToken")
|
||||
}
|
||||
|
||||
func (s *SettingService) SetTwoFactorToken(value string) error {
|
||||
return s.setString("twoFactorToken", value)
|
||||
}
|
||||
|
||||
func (s *SettingService) GetPort() (int, error) {
|
||||
return s.getInt("webPort")
|
||||
}
|
||||
|
|
|
@ -79,6 +79,16 @@ func (s *UserService) UpdateUser(id int, username string, password string) error
|
|||
return err
|
||||
}
|
||||
|
||||
twoFactorEnable, err := s.settingService.GetTwoFactorEnable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if twoFactorEnable {
|
||||
s.settingService.SetTwoFactorEnable(false)
|
||||
s.settingService.SetTwoFactorToken("")
|
||||
}
|
||||
|
||||
return db.Model(model.User{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]any{"username": username, "password": hashedPassword}).
|
||||
|
|
|
@ -542,6 +542,8 @@
|
|||
"twoFactorModalFirstStep" = "1. امسح رمز QR هذا في تطبيق المصادقة أو انسخ الرمز الموجود بجانب رمز QR والصقه في التطبيق"
|
||||
"twoFactorModalSecondStep" = "2. أدخل الرمز من التطبيق"
|
||||
"twoFactorModalRemoveStep" = "أدخل الرمز من التطبيق لإزالة المصادقة الثنائية."
|
||||
"twoFactorModalChangeCredentialsTitle" = "تغيير بيانات الاعتماد"
|
||||
"twoFactorModalChangeCredentialsStep" = "أدخل الرمز من التطبيق لتغيير بيانات اعتماد المسؤول."
|
||||
"twoFactorModalSetSuccess" = "تم إنشاء المصادقة الثنائية بنجاح"
|
||||
"twoFactorModalDeleteSuccess" = "تم حذف المصادقة الثنائية بنجاح"
|
||||
"twoFactorModalError" = "رمز خاطئ"
|
||||
|
|
|
@ -541,6 +541,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Scan this QR code in the app for authentication or copy the token near the QR code and paste it into the app"
|
||||
"twoFactorModalSecondStep" = "2. Enter the code from the app"
|
||||
"twoFactorModalRemoveStep" = "Enter the code from the application to remove two-factor authentication."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Change credentials"
|
||||
"twoFactorModalChangeCredentialsStep" = "Enter the code from the application to change administrator credentials."
|
||||
"twoFactorModalSetSuccess" = "Two-factor authentication has been successfully established"
|
||||
"twoFactorModalDeleteSuccess" = "Two-factor authentication has been successfully deleted"
|
||||
"twoFactorModalError" = "Wrong code"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Escanea este código QR en la aplicación de autenticación o copia el token cerca del código QR y pégalo en la aplicación"
|
||||
"twoFactorModalSecondStep" = "2. Ingresa el código de la aplicación"
|
||||
"twoFactorModalRemoveStep" = "Ingresa el código de la aplicación para eliminar la autenticación de dos factores."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Cambiar credenciales"
|
||||
"twoFactorModalChangeCredentialsStep" = "Ingrese el código de la aplicación para cambiar las credenciales del administrador."
|
||||
"twoFactorModalSetSuccess" = "La autenticación de dos factores se ha establecido con éxito"
|
||||
"twoFactorModalDeleteSuccess" = "La autenticación de dos factores se ha eliminado con éxito"
|
||||
"twoFactorModalError" = "Código incorrecto"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. این کد QR را در برنامه احراز هویت اسکن کنید یا توکن کنار کد QR را کپی کرده و در برنامه بچسبانید"
|
||||
"twoFactorModalSecondStep" = "2. کد را از برنامه وارد کنید"
|
||||
"twoFactorModalRemoveStep" = "برای حذف احراز هویت دو مرحلهای، کد را از برنامه وارد کنید."
|
||||
"twoFactorModalChangeCredentialsTitle" = "تغییر اعتبارنامهها"
|
||||
"twoFactorModalChangeCredentialsStep" = "برای تغییر اعتبارنامههای مدیر، کد را از برنامه وارد کنید."
|
||||
"twoFactorModalSetSuccess" = "احراز هویت دو مرحلهای با موفقیت برقرار شد"
|
||||
"twoFactorModalDeleteSuccess" = "احراز هویت دو مرحلهای با موفقیت حذف شد"
|
||||
"twoFactorModalError" = "کد نادرست"
|
||||
|
|
|
@ -545,6 +545,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Pindai kode QR ini di aplikasi autentikasi atau salin token di dekat kode QR dan tempelkan ke aplikasi"
|
||||
"twoFactorModalSecondStep" = "2. Masukkan kode dari aplikasi"
|
||||
"twoFactorModalRemoveStep" = "Masukkan kode dari aplikasi untuk menghapus autentikasi dua faktor."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Ubah kredensial"
|
||||
"twoFactorModalChangeCredentialsStep" = "Masukkan kode dari aplikasi untuk mengubah kredensial administrator."
|
||||
"twoFactorModalSetSuccess" = "Autentikasi dua faktor telah berhasil dibuat"
|
||||
"twoFactorModalDeleteSuccess" = "Autentikasi dua faktor telah berhasil dihapus"
|
||||
"twoFactorModalError" = "Kode salah"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. 認証アプリでこのQRコードをスキャンするか、QRコード近くのトークンをコピーしてアプリに貼り付けます"
|
||||
"twoFactorModalSecondStep" = "2. アプリからコードを入力してください"
|
||||
"twoFactorModalRemoveStep" = "二段階認証を削除するには、アプリからコードを入力してください。"
|
||||
"twoFactorModalChangeCredentialsTitle" = "認証情報の変更"
|
||||
"twoFactorModalChangeCredentialsStep" = "管理者の認証情報を変更するには、アプリケーションからコードを入力してください。"
|
||||
"twoFactorModalSetSuccess" = "二要素認証が正常に設定されました"
|
||||
"twoFactorModalDeleteSuccess" = "二要素認証が正常に削除されました"
|
||||
"twoFactorModalError" = "コードが間違っています"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Escaneie este QR code no aplicativo de autenticação ou copie o token próximo ao QR code e cole no aplicativo"
|
||||
"twoFactorModalSecondStep" = "2. Digite o código do aplicativo"
|
||||
"twoFactorModalRemoveStep" = "Digite o código do aplicativo para remover a autenticação de dois fatores."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Alterar credenciais"
|
||||
"twoFactorModalChangeCredentialsStep" = "Insira o código do aplicativo para alterar as credenciais do administrador."
|
||||
"twoFactorModalSetSuccess" = "A autenticação de dois fatores foi estabelecida com sucesso"
|
||||
"twoFactorModalDeleteSuccess" = "A autenticação de dois fatores foi excluída com sucesso"
|
||||
"twoFactorModalError" = "Código incorreto"
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"sure" = "Да"
|
||||
"encryption" = "Шифрование"
|
||||
"useIPv4ForHost" = "Использовать IPv4 для хоста"
|
||||
"transmission" = "Протокол"
|
||||
"transmission" = "Транспорт"
|
||||
"host" = "Хост"
|
||||
"path" = "Путь"
|
||||
"camouflage" = "Маскировка"
|
||||
|
@ -59,10 +59,10 @@
|
|||
"security" = "Безопасность"
|
||||
"secAlertTitle" = "Предупреждение системы безопасности"
|
||||
"secAlertSsl" = "Это соединение не защищено. Пожалуйста, не вводите конфиденциальную информацию, пока не установите SSL сертификат для защиты соединения"
|
||||
"secAlertConf" = "Некоторые настройки уязвимы для атак. Рекомендуем усилить протоколы безопасности, чтобы предотвратить проблемы в будущем."
|
||||
"secAlertSSL" = "Ваше подключение к панели небезопасно. Пожалуйста, установите SSL сертификат для защиты данных."
|
||||
"secAlertPanelPort" = "Порт, на котором работает панель небезопасен. Пожалуйста, установите случайный или просто другой порт."
|
||||
"secAlertPanelURI" = "URI-адрес панели по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
||||
"secAlertConf" = "Некоторые настройки уязвимы для атак. Чтобы в будущем не было проблем, нужно усилить защиту."
|
||||
"secAlertSSL" = "Ваше подключение к панели не защищено. Установите SSL сертификат для защиты данных."
|
||||
"secAlertPanelPort" = "Порт панели по умолчанию небезопасен. Установите случайный или просто другой порт."
|
||||
"secAlertPanelURI" = "Адрес панели по умолчанию небезопасен. Сделайте адрес сложным."
|
||||
"secAlertSubURI" = "URI-адрес подписки по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
||||
"secAlertSubJsonURI" = "URI-адрес по умолчанию для JSON подписки небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
||||
"emptyDnsDesc" = "Нет добавленных DNS-серверов."
|
||||
|
@ -75,8 +75,8 @@
|
|||
"theme" = "Тема"
|
||||
"dark" = "Темная"
|
||||
"ultraDark" = "Очень темная"
|
||||
"dashboard" = "Статус системы"
|
||||
"inbounds" = "Входящие подключения"
|
||||
"dashboard" = "Дашборд"
|
||||
"inbounds" = "Инбаунды"
|
||||
"settings" = "Настройки"
|
||||
"xray" = "Настройки Xray"
|
||||
"logout" = "Выход"
|
||||
|
@ -91,15 +91,15 @@
|
|||
"invalidFormData" = "Недопустимый формат данных"
|
||||
"emptyUsername" = "Введите имя пользователя"
|
||||
"emptyPassword" = "Введите пароль"
|
||||
"wrongUsernameOrPassword" = "Неверное имя пользователя, пароль или код двухфакторной аутентификации."
|
||||
"successLogin" = "Успешный вход"
|
||||
"wrongUsernameOrPassword" = "Неверные данные учетной записи."
|
||||
"successLogin" = "Вы успешно вошли в аккаунт"
|
||||
|
||||
[pages.index]
|
||||
"title" = "Статус системы"
|
||||
"title" = "Дашборд"
|
||||
"cpu" = "ЦП"
|
||||
"logicalProcessors" = "Логические процессоры"
|
||||
"frequency" = "Частота"
|
||||
"swap" = "Swap"
|
||||
"swap" = "Файл подкачки"
|
||||
"storage" = "Диск"
|
||||
"memory" = "ОЗУ"
|
||||
"threads" = "Потоки"
|
||||
|
@ -136,7 +136,7 @@
|
|||
"geofileUpdateDialogDesc" = "Это обновит файл #filename#."
|
||||
"geofileUpdatePopover" = "Геофайл успешно обновлён"
|
||||
"dontRefresh" = "Установка в процессе. Не обновляйте страницу"
|
||||
"logs" = "Логи"
|
||||
"logs" = "Журнал"
|
||||
"config" = "Конфигурация"
|
||||
"backup" = "Резервная копия"
|
||||
"backupTitle" = "Резервная копия базы данных"
|
||||
|
@ -151,10 +151,10 @@
|
|||
"getConfigError" = "Произошла ошибка при получении конфигурационного файла"
|
||||
|
||||
[pages.inbounds]
|
||||
"title" = "Входящие подключения"
|
||||
"title" = "Инбаунды"
|
||||
"totalDownUp" = "Объем отправленного/полученного трафика"
|
||||
"totalUsage" = "Всего трафика"
|
||||
"inboundCount" = "Всего подключений"
|
||||
"inboundCount" = "Всего инбаундов"
|
||||
"operate" = "Меню"
|
||||
"enable" = "Включить"
|
||||
"remark" = "Примечание"
|
||||
|
@ -165,18 +165,18 @@
|
|||
"transportConfig" = "Транспорт"
|
||||
"expireDate" = "Дата окончания"
|
||||
"resetTraffic" = "Сброс трафика"
|
||||
"addInbound" = "Создать новое подключение"
|
||||
"addInbound" = "Создать инбаунд"
|
||||
"generalActions" = "Общие действия"
|
||||
"autoRefresh" = "Автообновление"
|
||||
"autoRefreshInterval" = "Интервал"
|
||||
"modifyInbound" = "Изменить входящее подключение"
|
||||
"deleteInbound" = "Удалить входящее подключение"
|
||||
"deleteInboundContent" = "Вы уверены, что хотите удалить входящее подключение?"
|
||||
"modifyInbound" = "Изменить инбаунд"
|
||||
"deleteInbound" = "Удалить инбаунд"
|
||||
"deleteInboundContent" = "Вы уверены, что хотите удалить инбаунд?"
|
||||
"deleteClient" = "Удалить клиента"
|
||||
"deleteClientContent" = "Вы уверены, что хотите удалить клиента?"
|
||||
"resetTrafficContent" = "Вы уверены, что хотите сбросить трафик?"
|
||||
"inboundUpdateSuccess" = "Входящее подключение успешно обновлено."
|
||||
"inboundCreateSuccess" = "Входящее подключение успешно создано."
|
||||
"inboundUpdateSuccess" = "Инбаунд успешно обновлен."
|
||||
"inboundCreateSuccess" = "Инбаунд успешно создан."
|
||||
"copyLink" = "Копировать ссылку"
|
||||
"address" = "Адрес"
|
||||
"network" = "Сеть"
|
||||
|
@ -196,11 +196,11 @@
|
|||
"export" = "Экспорт ссылок"
|
||||
"clone" = "Клонировать"
|
||||
"cloneInbound" = "Клонировать"
|
||||
"cloneInboundContent" = "Будут клонированы все настройки входящих подключений, кроме списка клиентов, порта и IP-адреса прослушивания"
|
||||
"cloneInboundContent" = "Будут клонированы все настройки инбаундов, кроме списка клиентов, порта и IP-адреса прослушивания"
|
||||
"cloneInboundOk" = "Клонировано"
|
||||
"resetAllTraffic" = "Сброс трафика всех подключений"
|
||||
"resetAllTrafficTitle" = "Сброс трафика всех подключений"
|
||||
"resetAllTrafficContent" = "Вы уверены, что хотите сбросить трафик всех подключений?"
|
||||
"resetAllTraffic" = "Сброс трафика всех инбаундов"
|
||||
"resetAllTrafficTitle" = "Сброс трафика всех инбаундов"
|
||||
"resetAllTrafficContent" = "Вы уверены, что хотите сбросить трафик всех инбаундов?"
|
||||
"resetInboundClientTraffics" = "Сброс трафика клиента"
|
||||
"resetInboundClientTrafficTitle" = "Сброс трафика клиентов"
|
||||
"resetInboundClientTrafficContent" = "Вы уверены, что хотите сбросить трафик для этих клиентов?"
|
||||
|
@ -222,10 +222,10 @@
|
|||
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее'"
|
||||
"info" = "Информация"
|
||||
"same" = "Тот же"
|
||||
"inboundData" = "Данные подключений"
|
||||
"exportInbound" = "Экспорт входящих подключений"
|
||||
"inboundData" = "Данные инбаундов"
|
||||
"exportInbound" = "Экспорт инбаундов"
|
||||
"import" = "Импортировать"
|
||||
"importInbound" = "Импорт входящих подключений"
|
||||
"importInbound" = "Импорт инбаундов"
|
||||
|
||||
[pages.client]
|
||||
"add" = "Создать клиента"
|
||||
|
@ -249,13 +249,13 @@
|
|||
"obtain" = "Получить"
|
||||
"updateSuccess" = "Обновление прошло успешно"
|
||||
"logCleanSuccess" = "Лог был очищен"
|
||||
"inboundsUpdateSuccess" = "Входящие подключения успешно обновлены"
|
||||
"inboundUpdateSuccess" = "Входящее подключение успешно обновлено"
|
||||
"inboundCreateSuccess" = "Входящее подключение успешно создано"
|
||||
"inboundDeleteSuccess" = "Входящее подключение успешно удалено"
|
||||
"inboundClientAddSuccess" = "Клиент(ы) входящего подключения добавлен(ы)"
|
||||
"inboundClientDeleteSuccess" = "Клиент входящего подключения удалён"
|
||||
"inboundClientUpdateSuccess" = "Клиент входящего подключения обновлён"
|
||||
"inboundsUpdateSuccess" = "Инбаунды успешно обновлены"
|
||||
"inboundUpdateSuccess" = "Инбаунд успешно обновлено"
|
||||
"inboundCreateSuccess" = "Инбаунд успешно создано"
|
||||
"inboundDeleteSuccess" = "Инбаунд успешно удалено"
|
||||
"inboundClientAddSuccess" = "Клиент(ы) инбаунда добавлен(ы)"
|
||||
"inboundClientDeleteSuccess" = "Клиент инбаунда удалён"
|
||||
"inboundClientUpdateSuccess" = "Клиент инбаунда обновлён"
|
||||
"delDepletedClientsSuccess" = "Все исчерпанные клиенты удалены"
|
||||
"resetAllClientTrafficSuccess" = "Весь трафик клиента сброшен"
|
||||
"resetAllTrafficSuccess" = "Весь трафик сброшен"
|
||||
|
@ -281,15 +281,15 @@
|
|||
[pages.settings]
|
||||
"title" = "Настройки"
|
||||
"save" = "Сохранить"
|
||||
"infoDesc" = "Каждое выполненное изменение необходимо сохранить. Пожалуйста, перезапустите панель, чтобы изменения вступили в силу"
|
||||
"infoDesc" = "Каждое внесённое изменение должно быть сохранено. Пожалуйста, перезапустите панель, чтобы изменения вступили в силу."
|
||||
"restartPanel" = "Перезапуск панели"
|
||||
"restartPanelDesc" = "Вы уверены, что хотите перезапустить панель? Подтвердите, и перезапуск произойдёт через 3 секунды. Если панель будет недоступна, проверьте лог сервера"
|
||||
"restartPanelSuccess" = "Панель успешно перезапущена"
|
||||
"actions" = "Действия"
|
||||
"resetDefaultConfig" = "Восстановить настройки по умолчанию"
|
||||
"panelSettings" = "Настройки панели"
|
||||
"securitySettings" = "Настройки безопасности"
|
||||
"TGBotSettings" = "Настройки Telegram бота"
|
||||
"panelSettings" = "Панель"
|
||||
"securitySettings" = "Учетная запись"
|
||||
"TGBotSettings" = "Telegram"
|
||||
"panelListeningIP" = "IP-адрес для управления панелью"
|
||||
"panelListeningIPDesc" = "Оставьте пустым для подключения с любого IP"
|
||||
"panelListeningDomain" = "Домен панели"
|
||||
|
@ -303,7 +303,7 @@
|
|||
"panelUrlPath" = "Корневой путь URL адреса панели"
|
||||
"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться '/'"
|
||||
"pageSize" = "Размер нумерации страниц"
|
||||
"pageSizeDesc" = "Определить размер страницы для таблицы входящих подключений. Установите 0, чтобы отключить"
|
||||
"pageSizeDesc" = "Определить размер страницы для таблицы инбаундов. Установите 0, чтобы отключить"
|
||||
"remarkModel" = "Модель примечания и символ разделения"
|
||||
"datepicker" = "Выбор даты"
|
||||
"datepickerPlaceholder" = "Выберите дату"
|
||||
|
@ -391,7 +391,7 @@
|
|||
[pages.xray]
|
||||
"title" = "Настройки Xray"
|
||||
"save" = "Сохранить"
|
||||
"restart" = "Перезапустить Xray"
|
||||
"restart" = "Перезапуск Xray"
|
||||
"restartSuccess" = "Xray успешно перезапущен"
|
||||
"stopSuccess" = "Xray успешно остановлен"
|
||||
"restartError" = "Произошла ошибка при перезапуске Xray."
|
||||
|
@ -402,7 +402,7 @@
|
|||
"generalConfigsDesc" = "Эти параметры описывают общие настройки"
|
||||
"logConfigs" = "Логи"
|
||||
"logConfigsDesc" = "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!"
|
||||
"blockConfigsDesc" = "Настройте, чтобы клиенты не имели доступа к определенным протоколам и веб-сайтами"
|
||||
"blockConfigsDesc" = "Настройте, чтобы клиенты не имели доступа к определенным протоколам"
|
||||
"basicRouting" = "Базовые соединения"
|
||||
"blockConnectionsConfigsDesc" = "Эти параметры будут блокировать трафик в зависимости от страны назначения."
|
||||
"directConnectionsConfigsDesc" = "Прямое соединение означает, что определенный трафик не будет перенаправлен через другой сервер."
|
||||
|
@ -413,19 +413,19 @@
|
|||
"ipv4Routing" = "Правила IPv4"
|
||||
"ipv4RoutingDesc" = "Эти параметры позволят клиентам маршрутизироваться к целевым доменам только через IPv4"
|
||||
"warpRouting" = "Правила WARP"
|
||||
"warpRoutingDesc" = "Внимание: перед использованием этих параметров установите WARP в режиме прокси-сервера socks5 на свой сервер, следуя инструкциям на GitHub панели. WARP будет направлять трафик на веб-сайты через серверы Cloudflare"
|
||||
"warpRoutingDesc" = " Эти опции будут направлять трафик в зависимости от конкретного пункта назначения через WARP."
|
||||
"Template" = "Шаблон конфигурации Xray"
|
||||
"TemplateDesc" = "Создание файла конфигурации Xray на основе этого шаблона"
|
||||
"TemplateDesc" = "На основе шаблона создаётся конфигурационный файл Xray."
|
||||
"FreedomStrategy" = "Настройка стратегии протокола Freedom"
|
||||
"FreedomStrategyDesc" = "Установка стратегии вывода сети в протоколе Freedom"
|
||||
"RoutingStrategy" = "Настройка маршрутизации доменов"
|
||||
"RoutingStrategyDesc" = "Установка общей стратегии маршрутизации разрешения DNS"
|
||||
"Torrent" = "Заблокировать BitTorrent"
|
||||
"Inbounds" = "Входящее соединение"
|
||||
"Inbounds" = "Инбаунды"
|
||||
"InboundsDesc" = "Изменение шаблона конфигурации для подключения определенных клиентов"
|
||||
"Outbounds" = "Исходящее соединение"
|
||||
"Outbounds" = "Аутбаунды"
|
||||
"Balancers" = "Балансировщик"
|
||||
"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить исходящие соединения для этого сервера"
|
||||
"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить аутбаунды для этого сервера"
|
||||
"Routings" = "Маршрутизация"
|
||||
"RoutingsDesc" = "Важен приоритет каждого правила!"
|
||||
"completeTemplate" = "Все"
|
||||
|
@ -456,8 +456,8 @@
|
|||
"down" = "Опустить вниз"
|
||||
"source" = "Источник"
|
||||
"dest" = "Пункт назначения"
|
||||
"inbound" = "Входящее соединение"
|
||||
"outbound" = "Исходящее соединение"
|
||||
"inbound" = "Инбаунд"
|
||||
"outbound" = "Аутбаунд"
|
||||
"balancer" = "Балансировщик"
|
||||
"info" = "Информация"
|
||||
"add" = "Создать правило"
|
||||
|
@ -465,9 +465,9 @@
|
|||
"useComma" = "Элементы, разделённые запятыми"
|
||||
|
||||
[pages.xray.outbound]
|
||||
"addOutbound" = "Создать исходящее соединение"
|
||||
"addOutbound" = "Создать аутбаунд"
|
||||
"addReverse" = "Создать реверс-прокси"
|
||||
"editOutbound" = "Изменить исходящее соединение"
|
||||
"editOutbound" = "Изменить аутбаунд"
|
||||
"editReverse" = "Редактировать реверс-прокси"
|
||||
"tag" = "Тег"
|
||||
"tagDesc" = "Уникальный тег"
|
||||
|
@ -481,7 +481,7 @@
|
|||
"intercon" = "Соединение"
|
||||
"settings" = "Настройки"
|
||||
"accountInfo" = "Информация об учетной записи"
|
||||
"outboundStatus" = "Исходящий статус"
|
||||
"outboundStatus" = "Статус аутбаунда"
|
||||
"sendThrough" = "Отправить через"
|
||||
|
||||
[pages.xray.balancer]
|
||||
|
@ -494,7 +494,7 @@
|
|||
"balancerDesc" = "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
|
||||
|
||||
[pages.xray.wireguard]
|
||||
"secretKey" = "Приватный ключ"
|
||||
"secretKey" = "Секретный ключ"
|
||||
"publicKey" = "Публичный ключ"
|
||||
"allowedIPs" = "Разрешенные IP-адреса"
|
||||
"endpoint" = "Конечная точка"
|
||||
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Отсканируйте этот QR-код в приложении для аутентификации или скопируйте токен рядом с QR-кодом и вставьте его в приложение"
|
||||
"twoFactorModalSecondStep" = "2. Введите код из приложения"
|
||||
"twoFactorModalRemoveStep" = "Введите код из приложения, чтобы отключить двухфакторную аутентификацию."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Изменить учетные данные"
|
||||
"twoFactorModalChangeCredentialsStep" = "Введите код из приложения, чтобы изменить учетные данные администратора."
|
||||
"twoFactorModalSetSuccess" = "Двухфакторная аутентификация была успешно установлена"
|
||||
"twoFactorModalDeleteSuccess" = "Двухфакторная аутентификация была успешно удалена"
|
||||
"twoFactorModalError" = "Неверный код"
|
||||
|
@ -555,8 +557,8 @@
|
|||
"modifyUser" = "Вы успешно изменили учетные данные администратора."
|
||||
"originalUserPassIncorrect" = "Неверное имя пользователя или пароль"
|
||||
"userPassMustBeNotEmpty" = "Новое имя пользователя и новый пароль должны быть заполнены"
|
||||
"getOutboundTrafficError" = "Ошибка получения исходящего трафика"
|
||||
"resetOutboundTrafficError" = "Ошибка сброса исходящего трафика"
|
||||
"getOutboundTrafficError" = "Ошибка получения трафика аутбаунда"
|
||||
"resetOutboundTrafficError" = "Ошибка сброса трафика аутбаунда"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ Клавиатура закрыта."
|
||||
|
@ -564,7 +566,7 @@
|
|||
"noQuery" = "❌ Запрос не найден. Пожалуйста, повторите команду."
|
||||
"wentWrong" = "❌ Что-то пошло не так..."
|
||||
"noIpRecord" = "❗ Нет записей об IP-адресе."
|
||||
"noInbounds" = "❗ У вас не настроено ни одного подключения."
|
||||
"noInbounds" = "❗ У вас не настроено ни одного инбаунда."
|
||||
"unlimited" = "♾ Безлимит"
|
||||
"add" = "Добавить"
|
||||
"month" = "Месяц"
|
||||
|
@ -573,7 +575,7 @@
|
|||
"days" = "Дней"
|
||||
"hours" = "Часов"
|
||||
"unknown" = "Неизвестно"
|
||||
"inbounds" = "Подключения"
|
||||
"inbounds" = "Инбаунды"
|
||||
"clients" = "Клиенты"
|
||||
"offline" = "🔴 Офлайн"
|
||||
"online" = "🟢 Онлайн"
|
||||
|
@ -587,7 +589,7 @@
|
|||
"status" = "✅ Бот функционирует нормально."
|
||||
"usage" = "❗ Пожалуйста, укажите email для поиска."
|
||||
"getID" = "🆔 Ваш User ID: <code>{{ .ID }}</code>"
|
||||
"helpAdminCommands" = "🔃 Для перезапуска Xray Core:\r\n<code>/restart</code>\r\n\r\n🔎 Для поиска клиента по email:\r\n<code>/usage [Email]</code>\r\n\r\n📊 Для поиска подключений (со статистикой клиентов):\r\n<code>/inbound [имя подключения]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
||||
"helpAdminCommands" = "🔃 Для перезапуска Xray Core:\r\n<code>/restart</code>\r\n\r\n🔎 Для поиска клиента по email:\r\n<code>/usage [Email]</code>\r\n\r\n📊 Для поиска инбаундов (со статистикой клиентов):\r\n<code>/inbound [имя подключения]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
||||
"helpClientCommands" = "💲 Для просмотра информации о вашей подписке используйте команду:\r\n<code>/usage [Email]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
||||
"restartUsage" = "\r\n\r\n<code>/restart</code>"
|
||||
"restartSuccess" = "✅ Ядро Xray успешно перезапущено."
|
||||
|
@ -653,8 +655,8 @@
|
|||
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
|
||||
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
|
||||
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
|
||||
"inbound_client_data_id" = "🔄 Подключения: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в подключение!"
|
||||
"inbound_client_data_pass" = "🔄 Подключения: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в подключение!"
|
||||
"inbound_client_data_id" = "🔄 Инбаунды: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в инбаунд!"
|
||||
"inbound_client_data_pass" = "🔄 Инбаунды: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в инбаунд!"
|
||||
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
|
||||
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
|
||||
"using_default_value" = "Используется значение по умолчанию👌"
|
||||
|
@ -676,7 +678,7 @@
|
|||
"confirmToggle" = "✅ Подтвердить вкл/выкл пользователя?"
|
||||
"dbBackup" = "📂 Бэкап БД"
|
||||
"serverUsage" = "💻 Состояние сервера"
|
||||
"getInbounds" = "🔌 Подключения"
|
||||
"getInbounds" = "🔌 Инбаунды"
|
||||
"depleteSoon" = "⚠️ Скоро конец"
|
||||
"clientUsage" = "Статистика клиента"
|
||||
"onlines" = "🟢 Онлайн"
|
||||
|
@ -714,7 +716,7 @@
|
|||
[tgbot.answers]
|
||||
"successfulOperation" = "✅ Успешно!"
|
||||
"errorOperation" = "❗ Ошибка в операции."
|
||||
"getInboundsFailed" = "❌ Не удалось получить подключения."
|
||||
"getInboundsFailed" = "❌ Не удалось получить инбаунды."
|
||||
"getClientsFailed" = "❌ Не удалось получить клиентов."
|
||||
"canceled" = "❌ {{ .Email }}: Операция отменена."
|
||||
"clientRefreshSuccess" = "✅ {{ .Email }}: Клиент успешно обновлен."
|
||||
|
@ -731,5 +733,5 @@
|
|||
"enableSuccess" = "✅ {{ .Email }}: Включено успешно."
|
||||
"disableSuccess" = "✅ {{ .Email }}: Отключено успешно."
|
||||
"askToAddUserId" = "❌ Ваша конфигурация не найдена!\r\n💭 Пожалуйста, попросите администратора использовать ваш Telegram User ID в конфигурации.\r\n\r\n🆔 Ваш User ID: <code>{{ .TgUserID }}</code>"
|
||||
"chooseClient" = "Выберите клиента для подключения {{ .Inbound }}"
|
||||
"chooseInbound" = "Выберите подключение"
|
||||
"chooseClient" = "Выберите клиента для инбаунда {{ .Inbound }}"
|
||||
"chooseInbound" = "Выберите инбаунд"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Bu QR kodunu doğrulama uygulamasında tarayın veya QR kodunun yanındaki token'ı kopyalayıp uygulamaya yapıştırın"
|
||||
"twoFactorModalSecondStep" = "2. Uygulamadaki kodu girin"
|
||||
"twoFactorModalRemoveStep" = "İki adımlı doğrulamayı kaldırmak için uygulamadaki kodu girin."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Kimlik bilgilerini değiştir"
|
||||
"twoFactorModalChangeCredentialsStep" = "Yönetici kimlik bilgilerini değiştirmek için uygulamadaki kodu girin."
|
||||
"twoFactorModalSetSuccess" = "İki faktörlü kimlik doğrulama başarıyla kuruldu"
|
||||
"twoFactorModalDeleteSuccess" = "İki faktörlü kimlik doğrulama başarıyla silindi"
|
||||
"twoFactorModalError" = "Yanlış kod"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Відскануйте цей QR-код у програмі для аутентифікації або скопіюйте токен біля QR-коду та вставте його в програму"
|
||||
"twoFactorModalSecondStep" = "2. Введіть код з програми"
|
||||
"twoFactorModalRemoveStep" = "Введіть код з програми, щоб вимкнути двофакторну аутентифікацію."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Змінити облікові дані"
|
||||
"twoFactorModalChangeCredentialsStep" = "Введіть код з додатку, щоб змінити облікові дані адміністратора."
|
||||
"twoFactorModalSetSuccess" = "Двофакторна аутентифікація була успішно встановлена"
|
||||
"twoFactorModalDeleteSuccess" = "Двофакторна аутентифікація була успішно видалена"
|
||||
"twoFactorModalError" = "Невірний код"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. Quét mã QR này trong ứng dụng xác thực hoặc sao chép mã token gần mã QR và dán vào ứng dụng"
|
||||
"twoFactorModalSecondStep" = "2. Nhập mã từ ứng dụng"
|
||||
"twoFactorModalRemoveStep" = "Nhập mã từ ứng dụng để xóa xác thực hai yếu tố."
|
||||
"twoFactorModalChangeCredentialsTitle" = "Thay đổi thông tin xác thực"
|
||||
"twoFactorModalChangeCredentialsStep" = "Nhập mã từ ứng dụng để thay đổi thông tin xác thực quản trị viên."
|
||||
"twoFactorModalSetSuccess" = "Xác thực hai yếu tố đã được thiết lập thành công"
|
||||
"twoFactorModalDeleteSuccess" = "Xác thực hai yếu tố đã được xóa thành công"
|
||||
"twoFactorModalError" = "Mã sai"
|
||||
|
|
|
@ -544,6 +544,8 @@
|
|||
"twoFactorModalFirstStep" = "1. 在认证应用程序中扫描此QR码,或复制QR码附近的令牌并粘贴到应用程序中"
|
||||
"twoFactorModalSecondStep" = "2. 输入应用程序中的验证码"
|
||||
"twoFactorModalRemoveStep" = "输入应用程序中的验证码以移除双重认证。"
|
||||
"twoFactorModalChangeCredentialsTitle" = "更改凭据"
|
||||
"twoFactorModalChangeCredentialsStep" = "输入应用程序中的代码以更改管理员凭据。"
|
||||
"twoFactorModalSetSuccess" = "双因素认证已成功建立"
|
||||
"twoFactorModalDeleteSuccess" = "双因素认证已成功删除"
|
||||
"twoFactorModalError" = "验证码错误"
|
||||
|
|
|
@ -546,6 +546,8 @@
|
|||
"twoFactorModalFirstStep" = "1. 在認證應用程式中掃描此QR碼,或複製QR碼附近的令牌並貼到應用程式中"
|
||||
"twoFactorModalSecondStep" = "2. 輸入應用程式中的驗證碼"
|
||||
"twoFactorModalRemoveStep" = "輸入應用程式中的驗證碼以移除雙重認證。"
|
||||
"twoFactorModalChangeCredentialsTitle" = "更改憑證"
|
||||
"twoFactorModalChangeCredentialsStep" = "輸入應用程式中的代碼以更改管理員憑證。"
|
||||
"twoFactorModalSetSuccess" = "雙重身份驗證已成功建立"
|
||||
"twoFactorModalDeleteSuccess" = "雙重身份驗證已成功刪除"
|
||||
"twoFactorModalError" = "驗證碼錯誤"
|
||||
|
|
11
x-ui.sh
11
x-ui.sh
|
@ -179,11 +179,20 @@ reset_user() {
|
|||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
read -rp "Please set the login username [default is a random username]: " config_account
|
||||
[[ -z $config_account ]] && config_account=$(date +%s%N | md5sum | cut -c 1-8)
|
||||
read -rp "Please set the login password [default is a random password]: " config_password
|
||||
[[ -z $config_password ]] && config_password=$(date +%s%N | md5sum | cut -c 1-8)
|
||||
/usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} >/dev/null 2>&1
|
||||
|
||||
read -rp "Do you want to disable currently configured two-factor authentication? (y/n): " twoFactorConfirm
|
||||
if [[ $twoFactorConfirm != "y" && $twoFactorConfirm != "Y" ]]; then
|
||||
/usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} -resetTwoFactor false >/dev/null 2>&1
|
||||
else
|
||||
/usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} -resetTwoFactor true >/dev/null 2>&1
|
||||
echo -e "Two factor authentication has been disabled."
|
||||
fi
|
||||
|
||||
echo -e "Panel login username has been reset to: ${green} ${config_account} ${plain}"
|
||||
echo -e "Panel login password has been reset to: ${green} ${config_password} ${plain}"
|
||||
echo -e "${green} Please use the new login username and password to access the X-UI panel. Also remember them! ${plain}"
|
||||
|
|
Loading…
Reference in a new issue