mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
merge: add pre-release install/update selection
This commit is contained in:
commit
9cfb747666
8 changed files with 261 additions and 56 deletions
59
install.sh
59
install.sh
|
|
@ -871,21 +871,60 @@ config_after_install() {
|
||||||
${xui_folder}/x-ui migrate
|
${xui_folder}/x-ui migrate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_releases() {
|
||||||
|
local releases_json
|
||||||
|
releases_json=$(curl -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases")
|
||||||
|
if [[ -z "$releases_json" ]]; then
|
||||||
|
echo -e "${yellow}正在尝试通过 IPv4 获取版本...${plain}"
|
||||||
|
releases_json=$(curl -4 -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases")
|
||||||
|
if [[ -z "$releases_json" ]]; then
|
||||||
|
echo -e "${red}获取 x-ui 版本失败,可能是 GitHub API 限制,请稍后重试${plain}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse first non-prerelease tag_name
|
||||||
|
latest_stable=$(echo "$releases_json" | tr '{' '\n' | grep '"prerelease":false' | head -1 | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
|
||||||
|
# Parse first prerelease tag_name
|
||||||
|
latest_prerelease=$(echo "$releases_json" | tr '{' '\n' | grep '"prerelease":true' | head -1 | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
|
||||||
|
if [[ -z "$latest_stable" && -z "$latest_prerelease" ]]; then
|
||||||
|
echo -e "${red}获取 x-ui 版本失败${plain}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
select_version() {
|
||||||
|
if [[ -n "$latest_stable" && -n "$latest_prerelease" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${green}请选择要安装的版本:${plain}"
|
||||||
|
echo -e "${green}1)${plain} 最新稳定版: ${latest_stable}"
|
||||||
|
echo -e "${green}2)${plain} 最新预发布版: ${latest_prerelease}"
|
||||||
|
read -rp "请输入选择 [1-2]: " version_choice
|
||||||
|
while [[ "$version_choice" != "1" && "$version_choice" != "2" ]]; do
|
||||||
|
read -rp "无效输入,请重新输入 [1-2]: " version_choice
|
||||||
|
done
|
||||||
|
if [[ "$version_choice" == "1" ]]; then
|
||||||
|
tag_version="$latest_stable"
|
||||||
|
else
|
||||||
|
tag_version="$latest_prerelease"
|
||||||
|
fi
|
||||||
|
elif [[ -n "$latest_stable" ]]; then
|
||||||
|
tag_version="$latest_stable"
|
||||||
|
else
|
||||||
|
tag_version="$latest_prerelease"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
install_x-ui() {
|
install_x-ui() {
|
||||||
cd ${xui_folder%/x-ui}/
|
cd ${xui_folder%/x-ui}/
|
||||||
|
|
||||||
# 下载资源
|
# 下载资源
|
||||||
if [ $# == 0 ]; then
|
if [ $# == 0 ]; then
|
||||||
tag_version=$(curl -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
get_releases
|
||||||
if [[ ! -n "$tag_version" ]]; then
|
select_version
|
||||||
echo -e "${yellow}正在尝试通过 IPv4 获取版本...${plain}"
|
echo -e "获取到 x-ui 版本:${tag_version},开始安装..."
|
||||||
tag_version=$(curl -4 -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
|
||||||
if [[ ! -n "$tag_version" ]]; then
|
|
||||||
echo -e "${red}获取 x-ui 版本失败,可能是 GitHub API 限制,请稍后重试${plain}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo -e "获取到 x-ui 最新版本:${tag_version},开始安装..."
|
|
||||||
curl -4fLRo ${xui_folder}-linux-$(arch).tar.gz https://github.com/Sora39831/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz
|
curl -4fLRo ${xui_folder}-linux-$(arch).tar.gz https://github.com/Sora39831/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo -e "${red}下载 x-ui 失败,请确保服务器可以访问 GitHub${plain}"
|
echo -e "${red}下载 x-ui 失败,请确保服务器可以访问 GitHub${plain}"
|
||||||
|
|
|
||||||
53
update.sh
53
update.sh
|
|
@ -745,6 +745,47 @@ config_after_update() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_releases() {
|
||||||
|
local releases_json
|
||||||
|
releases_json=$(${curl_bin} -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases" 2>/dev/null)
|
||||||
|
if [[ -z "$releases_json" ]]; then
|
||||||
|
echo -e "${yellow}Trying to fetch version with IPv4...${plain}"
|
||||||
|
releases_json=$(${curl_bin} -4 -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases" 2>/dev/null)
|
||||||
|
if [[ -z "$releases_json" ]]; then
|
||||||
|
_fail "ERROR: Failed to fetch x-ui version, it may be due to GitHub API restrictions, please try it later"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
latest_stable=$(echo "$releases_json" | tr '{' '\n' | grep '"prerelease":false' | head -1 | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
latest_prerelease=$(echo "$releases_json" | tr '{' '\n' | grep '"prerelease":true' | head -1 | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
|
||||||
|
if [[ -z "$latest_stable" && -z "$latest_prerelease" ]]; then
|
||||||
|
_fail "ERROR: Failed to fetch x-ui version"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
select_version() {
|
||||||
|
if [[ -n "$latest_stable" && -n "$latest_prerelease" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${green}Which version do you want to update to?${plain}"
|
||||||
|
echo -e "${green}1)${plain} Latest Stable: ${latest_stable}"
|
||||||
|
echo -e "${green}2)${plain} Latest Pre-release: ${latest_prerelease}"
|
||||||
|
read -rp "Please enter your choice [1-2]: " version_choice
|
||||||
|
while [[ "$version_choice" != "1" && "$version_choice" != "2" ]]; do
|
||||||
|
read -rp "Invalid input, please re-enter [1-2]: " version_choice
|
||||||
|
done
|
||||||
|
if [[ "$version_choice" == "1" ]]; then
|
||||||
|
tag_version="$latest_stable"
|
||||||
|
else
|
||||||
|
tag_version="$latest_prerelease"
|
||||||
|
fi
|
||||||
|
elif [[ -n "$latest_stable" ]]; then
|
||||||
|
tag_version="$latest_stable"
|
||||||
|
else
|
||||||
|
tag_version="$latest_prerelease"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
update_x-ui() {
|
update_x-ui() {
|
||||||
cd ${xui_folder%/x-ui}/
|
cd ${xui_folder%/x-ui}/
|
||||||
|
|
||||||
|
|
@ -757,15 +798,9 @@ update_x-ui() {
|
||||||
|
|
||||||
echo -e "${green}Downloading new x-ui version...${plain}"
|
echo -e "${green}Downloading new x-ui version...${plain}"
|
||||||
|
|
||||||
tag_version=$(${curl_bin} -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases/latest" 2>/dev/null | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
get_releases
|
||||||
if [[ ! -n "$tag_version" ]]; then
|
select_version
|
||||||
echo -e "${yellow}Trying to fetch version with IPv4...${plain}"
|
echo -e "Got x-ui version: ${tag_version}, beginning the installation..."
|
||||||
tag_version=$(${curl_bin} -4 -Ls "https://api.github.com/repos/Sora39831/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
|
||||||
if [[ ! -n "$tag_version" ]]; then
|
|
||||||
_fail "ERROR: Failed to fetch x-ui version, it may be due to GitHub API restrictions, please try it later"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo -e "Got x-ui latest version: ${tag_version}, beginning the installation..."
|
|
||||||
${curl_bin} -fLRo ${xui_folder}-linux-$(arch).tar.gz https://github.com/Sora39831/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz 2>/dev/null
|
${curl_bin} -fLRo ${xui_folder}-linux-$(arch).tar.gz https://github.com/Sora39831/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz 2>/dev/null
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo -e "${yellow}Trying to fetch version with IPv4...${plain}"
|
echo -e "${yellow}Trying to fetch version with IPv4...${plain}"
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ func (a *IndexController) initRouter(g *gin.RouterGroup) {
|
||||||
|
|
||||||
g.POST("/login", a.login)
|
g.POST("/login", a.login)
|
||||||
g.POST("/getTwoFactorEnable", a.getTwoFactorEnable)
|
g.POST("/getTwoFactorEnable", a.getTwoFactorEnable)
|
||||||
|
g.POST("/getTurnstileSiteKey", a.getTurnstileSiteKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// index handles the root route, redirecting logged-in users to the panel or showing the login page.
|
// index handles the root route, redirecting logged-in users to the panel or showing the login page.
|
||||||
|
|
@ -131,3 +132,11 @@ func (a *IndexController) getTwoFactorEnable(c *gin.Context) {
|
||||||
jsonObj(c, status, nil)
|
jsonObj(c, status, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getTurnstileSiteKey returns the Cloudflare Turnstile site key for the registration form.
|
||||||
|
func (a *IndexController) getTurnstileSiteKey(c *gin.Context) {
|
||||||
|
siteKey, err := a.settingService.GetTurnstileSiteKey()
|
||||||
|
if err == nil {
|
||||||
|
jsonObj(c, siteKey, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,9 @@ type AllSetting struct {
|
||||||
LdapDefaultTotalGB int `json:"ldapDefaultTotalGB" form:"ldapDefaultTotalGB"`
|
LdapDefaultTotalGB int `json:"ldapDefaultTotalGB" form:"ldapDefaultTotalGB"`
|
||||||
LdapDefaultExpiryDays int `json:"ldapDefaultExpiryDays" form:"ldapDefaultExpiryDays"`
|
LdapDefaultExpiryDays int `json:"ldapDefaultExpiryDays" form:"ldapDefaultExpiryDays"`
|
||||||
LdapDefaultLimitIP int `json:"ldapDefaultLimitIP" form:"ldapDefaultLimitIP"`
|
LdapDefaultLimitIP int `json:"ldapDefaultLimitIP" form:"ldapDefaultLimitIP"`
|
||||||
// JSON subscription routing rules
|
|
||||||
|
// Registration settings
|
||||||
|
TurnstileSiteKey string `json:"turnstileSiteKey" form:"turnstileSiteKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckValid validates all settings in the AllSetting struct, checking IP addresses, ports, SSL certificates, and other configuration values.
|
// CheckValid validates all settings in the AllSetting struct, checking IP addresses, ports, SSL certificates, and other configuration values.
|
||||||
|
|
|
||||||
|
|
@ -59,39 +59,83 @@
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row type="flex" justify="center">
|
<a-row type="flex" justify="center">
|
||||||
<a-col span="24">
|
<a-col span="24">
|
||||||
<a-form @submit.prevent="login">
|
<a-tabs :active-key="activeTab" @change="switchTab" centered>
|
||||||
<a-space direction="vertical" size="middle">
|
<a-tab-pane key="login" tab='{{ i18n "pages.login.loginTab" }}'>
|
||||||
<a-form-item>
|
<a-form @submit.prevent="doLogin">
|
||||||
<a-input autocomplete="username" name="username" v-model.trim="user.username"
|
<a-space direction="vertical" size="middle">
|
||||||
placeholder='{{ i18n "username" }}' autofocus required>
|
<a-form-item>
|
||||||
<a-icon slot="prefix" type="user" class="fs-1rem"></a-icon>
|
<a-input autocomplete="username" name="username" v-model.trim="user.username"
|
||||||
</a-input>
|
placeholder='{{ i18n "username" }}' autofocus required>
|
||||||
</a-form-item>
|
<a-icon slot="prefix" type="user" class="fs-1rem"></a-icon>
|
||||||
<a-form-item>
|
</a-input>
|
||||||
<a-input-password autocomplete="current-password" name="password" v-model.trim="user.password"
|
</a-form-item>
|
||||||
placeholder='{{ i18n "password" }}' required>
|
<a-form-item>
|
||||||
<a-icon slot="prefix" type="lock" class="fs-1rem"></a-icon>
|
<a-input-password autocomplete="current-password" name="password" v-model.trim="user.password"
|
||||||
</a-input-password>
|
placeholder='{{ i18n "password" }}' required>
|
||||||
</a-form-item>
|
<a-icon slot="prefix" type="lock" class="fs-1rem"></a-icon>
|
||||||
<a-form-item v-if="twoFactorEnable">
|
</a-input-password>
|
||||||
<a-input autocomplete="one-time-code" name="twoFactorCode" v-model.trim="user.twoFactorCode"
|
</a-form-item>
|
||||||
placeholder='{{ i18n "twoFactorCode" }}' required>
|
<a-form-item v-if="twoFactorEnable">
|
||||||
<a-icon slot="prefix" type="key" class="fs-1rem"></a-icon>
|
<a-input autocomplete="one-time-code" name="twoFactorCode" v-model.trim="user.twoFactorCode"
|
||||||
</a-input>
|
placeholder='{{ i18n "twoFactorCode" }}' required>
|
||||||
</a-form-item>
|
<a-icon slot="prefix" type="key" class="fs-1rem"></a-icon>
|
||||||
<a-form-item>
|
</a-input>
|
||||||
<a-row justify="center" class="centered">
|
</a-form-item>
|
||||||
<div class="wave-btn-bg wave-btn-bg-cl h-50px mt-1rem"
|
<a-form-item>
|
||||||
:style="loadingStates.spinning ? 'width: 52px' : 'display: inline-block'">
|
<a-row justify="center" class="centered">
|
||||||
<a-button class="ant-btn-primary-login" type="primary" :loading="loadingStates.spinning"
|
<div class="wave-btn-bg wave-btn-bg-cl h-50px mt-1rem"
|
||||||
:icon="loadingStates.spinning ? 'poweroff' : undefined" html-type="submit">
|
:style="loadingStates.spinning ? 'width: 52px' : 'display: inline-block'">
|
||||||
[[ loadingStates.spinning ? '' : '{{ i18n "login" }}' ]]
|
<a-button class="ant-btn-primary-login" type="primary" :loading="loadingStates.spinning"
|
||||||
</a-button>
|
:icon="loadingStates.spinning ? 'poweroff' : undefined" html-type="submit">
|
||||||
</div>
|
[[ loadingStates.spinning ? '' : '{{ i18n "login" }}' ]]
|
||||||
</a-row>
|
</a-button>
|
||||||
</a-form-item>
|
</div>
|
||||||
</a-space>
|
</a-row>
|
||||||
</a-form>
|
</a-form-item>
|
||||||
|
</a-space>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="register" tab='{{ i18n "pages.login.registerTab" }}'>
|
||||||
|
<a-form @submit.prevent="doRegister">
|
||||||
|
<a-space direction="vertical" size="middle">
|
||||||
|
<a-form-item>
|
||||||
|
<a-input autocomplete="username" name="reg-username" v-model.trim="regUser.username"
|
||||||
|
placeholder='{{ i18n "username" }}' required>
|
||||||
|
<a-icon slot="prefix" type="user" class="fs-1rem"></a-icon>
|
||||||
|
</a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-password autocomplete="new-password" name="reg-password" v-model.trim="regUser.password"
|
||||||
|
placeholder='{{ i18n "password" }}' required>
|
||||||
|
<a-icon slot="prefix" type="lock" class="fs-1rem"></a-icon>
|
||||||
|
</a-input-password>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-password autocomplete="new-password" name="reg-confirm-password" v-model.trim="regUser.confirmPassword"
|
||||||
|
placeholder='{{ i18n "pages.login.confirmPassword" }}' required>
|
||||||
|
<a-icon slot="prefix" type="lock" class="fs-1rem"></a-icon>
|
||||||
|
</a-input-password>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<div class="cf-turnstile-wrapper">
|
||||||
|
<div class="cf-turnstile" :data-sitekey="turnstileSiteKey" data-callback="onTurnstileCallback"></div>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-row justify="center" class="centered">
|
||||||
|
<div class="wave-btn-bg wave-btn-bg-cl h-50px mt-1rem"
|
||||||
|
:style="loadingStates.registerSpinning ? 'width: 52px' : 'display: inline-block'">
|
||||||
|
<a-button class="ant-btn-primary-login" type="primary" :loading="loadingStates.registerSpinning"
|
||||||
|
:icon="loadingStates.registerSpinning ? 'poweroff' : undefined" html-type="submit">
|
||||||
|
[[ loadingStates.registerSpinning ? '' : '{{ i18n "pages.login.registerTab" }}' ]]
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-row>
|
||||||
|
</a-form-item>
|
||||||
|
</a-space>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -103,23 +147,39 @@
|
||||||
{{template "page/body_scripts" .}}
|
{{template "page/body_scripts" .}}
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
<script>
|
<script>
|
||||||
|
var turnstileToken = '';
|
||||||
|
|
||||||
|
function onTurnstileCallback(token) {
|
||||||
|
turnstileToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
loadingStates: { fetched: false, spinning: false },
|
loadingStates: { fetched: false, spinning: false, registerSpinning: false },
|
||||||
|
activeTab: 'login',
|
||||||
user: { username: "", password: "", twoFactorCode: "" },
|
user: { username: "", password: "", twoFactorCode: "" },
|
||||||
|
regUser: { username: "", password: "", confirmPassword: "" },
|
||||||
twoFactorEnable: false,
|
twoFactorEnable: false,
|
||||||
lang: "",
|
lang: "",
|
||||||
animationStarted: false
|
animationStarted: false,
|
||||||
|
turnstileSiteKey: '',
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.lang = LanguageManager.getLanguage();
|
this.lang = LanguageManager.getLanguage();
|
||||||
this.twoFactorEnable = await this.getTwoFactorEnable();
|
this.twoFactorEnable = await this.getTwoFactorEnable();
|
||||||
|
this.turnstileSiteKey = await this.getTurnstileSiteKey();
|
||||||
|
if (this.turnstileSiteKey) {
|
||||||
|
this.loadTurnstileScript();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async login() {
|
switchTab(key) {
|
||||||
|
this.activeTab = key;
|
||||||
|
},
|
||||||
|
async doLogin() {
|
||||||
this.loadingStates.spinning = true;
|
this.loadingStates.spinning = true;
|
||||||
const msg = await HttpUtil.post('/login', this.user);
|
const msg = await HttpUtil.post('/login', this.user);
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
|
@ -127,6 +187,47 @@
|
||||||
}
|
}
|
||||||
this.loadingStates.spinning = false;
|
this.loadingStates.spinning = false;
|
||||||
},
|
},
|
||||||
|
async doRegister() {
|
||||||
|
if (this.regUser.password !== this.regUser.confirmPassword) {
|
||||||
|
this.$message.error('{{ i18n "pages.login.passwordMismatch" }}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!turnstileToken) {
|
||||||
|
this.$message.error('{{ i18n "pages.login.turnstileRequired" }}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loadingStates.registerSpinning = true;
|
||||||
|
const msg = await HttpUtil.post('/register', {
|
||||||
|
username: this.regUser.username,
|
||||||
|
password: this.regUser.password,
|
||||||
|
turnstileToken: turnstileToken,
|
||||||
|
});
|
||||||
|
if (msg.success) {
|
||||||
|
this.$message.success('{{ i18n "pages.login.toasts.successRegister" }}');
|
||||||
|
this.activeTab = 'login';
|
||||||
|
this.user.username = this.regUser.username;
|
||||||
|
this.regUser = { username: "", password: "", confirmPassword: "" };
|
||||||
|
turnstileToken = '';
|
||||||
|
if (window.turnstile) {
|
||||||
|
turnstile.reset('.cf-turnstile');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.loadingStates.registerSpinning = false;
|
||||||
|
},
|
||||||
|
loadTurnstileScript() {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
|
||||||
|
script.async = true;
|
||||||
|
script.defer = true;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
},
|
||||||
|
async getTurnstileSiteKey() {
|
||||||
|
const msg = await HttpUtil.post('/getTurnstileSiteKey');
|
||||||
|
if (msg.success) {
|
||||||
|
return msg.obj;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
async getTwoFactorEnable() {
|
async getTwoFactorEnable() {
|
||||||
const msg = await HttpUtil.post('/getTwoFactorEnable');
|
const msg = await HttpUtil.post('/getTwoFactorEnable');
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,9 @@ var defaultValueMap = map[string]string{
|
||||||
"ldapDefaultTotalGB": "0",
|
"ldapDefaultTotalGB": "0",
|
||||||
"ldapDefaultExpiryDays": "0",
|
"ldapDefaultExpiryDays": "0",
|
||||||
"ldapDefaultLimitIP": "0",
|
"ldapDefaultLimitIP": "0",
|
||||||
|
|
||||||
|
// Registration settings
|
||||||
|
"turnstileSiteKey": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadSettings reads the JSON settings file into a map.
|
// loadSettings reads the JSON settings file into a map.
|
||||||
|
|
@ -746,6 +749,10 @@ func (s *SettingService) GetLdapDefaultLimitIP() (int, error) {
|
||||||
return s.getInt("ldapDefaultLimitIP")
|
return s.getInt("ldapDefaultLimitIP")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SettingService) GetTurnstileSiteKey() (string, error) {
|
||||||
|
return s.getString("turnstileSiteKey")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
|
func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
|
||||||
if err := allSetting.CheckValid(); err != nil {
|
if err := allSetting.CheckValid(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,11 @@
|
||||||
"hello" = "Hello"
|
"hello" = "Hello"
|
||||||
"title" = "Welcome"
|
"title" = "Welcome"
|
||||||
"loginAgain" = "Your session has expired, please log in again"
|
"loginAgain" = "Your session has expired, please log in again"
|
||||||
|
"loginTab" = "Login"
|
||||||
|
"registerTab" = "Register"
|
||||||
|
"confirmPassword" = "Confirm Password"
|
||||||
|
"passwordMismatch" = "Passwords do not match"
|
||||||
|
"turnstileRequired" = "Please complete the verification"
|
||||||
|
|
||||||
[pages.login.toasts]
|
[pages.login.toasts]
|
||||||
"invalidFormData" = "The Input data format is invalid."
|
"invalidFormData" = "The Input data format is invalid."
|
||||||
|
|
@ -108,6 +113,7 @@
|
||||||
"emptyPassword" = "Password is required"
|
"emptyPassword" = "Password is required"
|
||||||
"wrongUsernameOrPassword" = "Invalid username or password or two-factor code."
|
"wrongUsernameOrPassword" = "Invalid username or password or two-factor code."
|
||||||
"successLogin" = " You have successfully logged into your account."
|
"successLogin" = " You have successfully logged into your account."
|
||||||
|
"successRegister" = "Registration successful, please log in."
|
||||||
|
|
||||||
[pages.index]
|
[pages.index]
|
||||||
"title" = "Overview"
|
"title" = "Overview"
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,11 @@
|
||||||
"hello" = "你好"
|
"hello" = "你好"
|
||||||
"title" = "欢迎"
|
"title" = "欢迎"
|
||||||
"loginAgain" = "登录时效已过,请重新登录"
|
"loginAgain" = "登录时效已过,请重新登录"
|
||||||
|
"loginTab" = "登录"
|
||||||
|
"registerTab" = "注册"
|
||||||
|
"confirmPassword" = "确认密码"
|
||||||
|
"passwordMismatch" = "两次输入的密码不一致"
|
||||||
|
"turnstileRequired" = "请完成验证"
|
||||||
|
|
||||||
[pages.login.toasts]
|
[pages.login.toasts]
|
||||||
"invalidFormData" = "数据格式错误"
|
"invalidFormData" = "数据格式错误"
|
||||||
|
|
@ -108,6 +113,7 @@
|
||||||
"emptyPassword" = "请输入密码"
|
"emptyPassword" = "请输入密码"
|
||||||
"wrongUsernameOrPassword" = "用户名、密码或双重验证码无效。"
|
"wrongUsernameOrPassword" = "用户名、密码或双重验证码无效。"
|
||||||
"successLogin" = "您已成功登录您的账户。"
|
"successLogin" = "您已成功登录您的账户。"
|
||||||
|
"successRegister" = "注册成功,请登录。"
|
||||||
|
|
||||||
[pages.index]
|
[pages.index]
|
||||||
"title" = "系统状态"
|
"title" = "系统状态"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue