feat: improve OAuth2 support

This commit is contained in:
aslost
2026-08-25 12:02:22 +08:00
parent 50f1142a53
commit f9ddd7b88e
19 changed files with 108 additions and 214 deletions
-9
View File
@@ -28,10 +28,6 @@ jobs:
AI_MODEL: ${{ secrets.AI_MODEL || vars.AI_MODEL || '@cf/meta/llama-3.1-8b-instruct-fast' }}
CLOUDFLARE_EMAIL: ${{ secrets.CF_EMAIL || vars.CF_EMAIL || false }}
ANALYSIS_CACHE: ${{ secrets.ANALYSIS_CACHE || vars.ANALYSIS_CACHE || false }}
LINUXDO_SWITCH: ${{ secrets.LINUXDO_SWITCH || vars.LINUXDO_SWITCH }}
GITHUB_SWITCH: ${{ secrets.GITHUB_SWITCH || vars.GITHUB_SWITCH }}
GITLAB_SWITCH: ${{ secrets.GITLAB_SWITCH || vars.GITLAB_SWITCH }}
GOOGLE_SWITCH: ${{ secrets.GOOGLE_SWITCH || vars.GOOGLE_SWITCH }}
outputs:
@@ -107,10 +103,6 @@ jobs:
sed -i '/^project_link = /d' "$CONFIG_FILE"
fi
if [ -z "$LINUXDO_CLIENT_ID" ] || [ -z "$LINUXDO_CLIENT_SECRET" ]; then
sed -i '/^linuxdo_client_id = /,/^linuxdo_switch = /d' "$CONFIG_FILE"
fi
if [ -z "$CUSTOM_DOMAIN" ]; then
sed -i '/\[\[routes\]\]/,/^$/d' "$CONFIG_FILE"
fi
@@ -135,7 +127,6 @@ jobs:
sed -i "s|\${LINUXDO_CLIENT_ID}|${LINUXDO_CLIENT_ID}|g" "$CONFIG_FILE"
sed -i "s|\${LINUXDO_CLIENT_SECRET}|${LINUXDO_CLIENT_SECRET}|g" "$CONFIG_FILE"
sed -i "s|\${LINUXDO_CALLBACK_URL}|${LINUXDO_CALLBACK_URL}|g" "$CONFIG_FILE"
sed -i "s|\${LINUXDO_SWITCH}|${LINUXDO_SWITCH}|g" "$CONFIG_FILE"
echo "✅ Environment setup completed."
+1 -1
View File
@@ -65,7 +65,7 @@ With only one domain, you can create multiple different email addresses, similar
- **🤖 CAPTCHA**: Integrated with Turnstile CAPTCHA to prevent automated registration.
- **🔑 OAuth2 Login**: Support LinuxDo / GitHub / GitLab / Google third-party login.
- **🔑 OAuth2 Login**: Support LinuxDo / GitHub / Google third-party login.
- **📜 More Features**: Under development...
+1 -1
View File
@@ -70,7 +70,7 @@
- **🤖 人机验证**:集成Turnstile人机验证,防止人机批量注册
- **🔑 OAuth2 登录**:支持 LinuxDo / GitHub / GitLab / Google 第三方登录
- **🔑 OAuth2 登录**:支持 LinuxDo / GitHub / Google 第三方登录
- **📜 更多功能**:正在开发中...
-4
View File
@@ -18,10 +18,6 @@
| `ADMIN` | ✅ | 您的管理员邮箱地址(例如 `[email protected]`) |
| `JWT_SECRET` | ✅ | 用于生成和验证 JWT 的随机长字符串 |
| `PROJECT_LINK` | ❌ | (可选)是否在登录页显示 GitHub 项目链接(`true` / `false`) | |
| `LINUXDO_SWITCH` | ❌ | LinuxDo OAuth 启用开关(`true` / `false`) | |
| `GITHUB_SWITCH` | ❌ | GitHub OAuth 启用开关(`true` / `false`) | |
| `GITLAB_SWITCH` | ❌ | GitLab OAuth 启用开关(`true` / `false`) | |
| `GOOGLE_SWITCH` | ❌ | Google OAuth 启用开关(`true` / `false`) |
| `INIT_URL` | ❌ | (可选)部署后用于初始化数据库的 Worker URL(格式参考下述手动初始化) |
---
-1
View File
@@ -343,7 +343,6 @@ const en = {
oauthSetting: 'OAuth',
clientId: 'Client ID',
clientSecret: 'Client Secret',
callbackBase: 'https://domain',
notOwner: 'Base email does not belong to you',
}
-1
View File
@@ -343,7 +343,6 @@ const zh = {
oauthSetting: 'OAuth',
clientId: '客户端 ID',
clientSecret: '客户端密钥',
callbackBase: 'https://domain',
notOwner: '基础邮箱不属于您',
}
export default zh
+6 -10
View File
@@ -1,19 +1,15 @@
import http from '@/axios/index.js';
export function oauthLinuxDoLogin(code) {
return http.post('/oauth/linuxDo/login',{code})
export function oauthLinuxDoLogin(code, redirectUri) {
return http.post('/oauth/linuxDo/login',{code, redirectUri})
}
export function oauthGithubLogin(code) {
return http.post('/oauth/github/login',{code})
export function oauthGithubLogin(code, redirectUri) {
return http.post('/oauth/github/login',{code, redirectUri})
}
export function oauthGitlabLogin(code) {
return http.post('/oauth/gitlab/login',{code})
}
export function oauthGoogleLogin(code) {
return http.post('/oauth/google/login',{code})
export function oauthGoogleLogin(code, redirectUri) {
return http.post('/oauth/google/login',{code, redirectUri})
}
export function oauthBindUser(form) {
-20
View File
@@ -59,26 +59,6 @@ const routes = [
name: 'login',
component: () => import('@/views/login/index.vue')
},
{
path: '/login/github',
name: 'loginGithub',
component: () => import('@/views/login/index.vue')
},
{
path: '/login/gitlab',
name: 'loginGitlab',
component: () => import('@/views/login/index.vue')
},
{
path: '/login/google',
name: 'loginGoogle',
component: () => import('@/views/login/index.vue')
},
{
path: '/login/linuxdo',
name: 'loginLinuxdo',
component: () => import('@/views/login/index.vue')
},
{
path: '/test',
name: 'test',
+19 -20
View File
@@ -167,7 +167,7 @@ import {cvtR2Url} from "@/utils/convert.js";
import {loginUserInfo} from "@/request/my.js";
import {permsToRouter} from "@/perm/perm.js";
import {useI18n} from "vue-i18n";
import {oauthBindUser, oauthLinuxDoLogin, oauthGithubLogin, oauthGitlabLogin, oauthGoogleLogin} from "@/request/ouath.js";
import {oauthBindUser, oauthLinuxDoLogin, oauthGithubLogin, oauthGoogleLogin} from "@/request/ouath.js";
const {t} = useI18n();
const accountStore = useAccountStore();
@@ -181,19 +181,22 @@ const oauthLoading = ref(false);
const showBindForm = ref(false);
const show = ref('login')
const oauthKeys = ['linuxdo', 'github', 'google']
const oauthProvider = computed(() => {
const match = route.path.match(/^\/login\/(.+)/)
return match ? match[1] : null
const fromState = route.query.state
if (oauthKeys.includes(fromState)) return fromState
const fromStore = sessionStorage.getItem('oauthProvider')
return oauthKeys.includes(fromStore) ? fromStore : null
})
const oauthProviders = computed(() => {
const allProviders = [
{ key: 'linuxdo', label: 'LinuxDo', icon: '/image/linuxdo.webp', iconType: 'image' },
{ key: 'github', label: 'GitHub', icon: 'mingcute:github-fill', iconType: 'iconify' },
{ key: 'gitlab', label: 'GitLab', icon: 'mingcute:gitlab-fill', iconType: 'iconify' },
{ key: 'google', label: 'Google', icon: 'mingcute:google-fill', iconType: 'iconify' },
]
return allProviders.filter(p => settingStore.settings[p.key + 'Switch'])
return allProviders.filter(p => settingStore.settings[p.key + 'Switch'] === 0)
})
const bindForm = reactive({
@@ -284,12 +287,12 @@ const getEmailName = (email) => {
function oauthLogin(provider) {
const clientId = settingStore.settings[provider + 'ClientId']
const redirectUri = encodeURIComponent(window.location.origin + '/login/' + provider)
const redirectUri = encodeURIComponent(window.location.origin + '/login')
sessionStorage.setItem('oauthProvider', provider)
const authorizeUrls = {
linuxdo: `https://connect.linux.do/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=openid+profile+email`,
github: `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=user:email`,
gitlab: `https://gitlab.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=read_user`,
google: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=openid+profile+email`,
linuxdo: `https://connect.linux.do/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=openid+profile+email&state=${provider}`,
github: `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=user:email&state=${provider}`,
google: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=openid+profile+email&state=${provider}`,
}
window.location.href = authorizeUrls[provider]
}
@@ -297,7 +300,6 @@ function oauthLogin(provider) {
const loginFns = {
linuxdo: oauthLinuxDoLogin,
github: oauthGithubLogin,
gitlab: oauthGitlabLogin,
google: oauthGoogleLogin,
}
@@ -305,15 +307,16 @@ oauthGetUser();
async function oauthGetUser() {
if (!oauthProvider.value) return
const params = new URLSearchParams(window.location.search)
const code = params.get('code')
if (!code || !oauthProvider.value) return
if (code) {
const provider = oauthProvider.value
oauthLoading.value = true
loginFns[oauthProvider.value](code).then(data => {
sessionStorage.removeItem('oauthProvider')
window.history.replaceState({}, '', window.location.origin + window.location.pathname)
loginFns[provider](code, window.location.origin + '/login').then(data => {
bindForm.oauthUserId = data.userInfo.oauthUserId;
@@ -333,10 +336,6 @@ async function oauthGetUser() {
}).catch(() => {
oauthLoading.value = false
})
}
const cleanUrl = window.location.origin + window.location.pathname
window.history.replaceState({}, '', cleanUrl)
}
function bind() {
+27 -29
View File
@@ -353,22 +353,6 @@
</div>
</div>
<!-- OAuth Login Card -->
<div class="settings-card">
<div class="card-title">{{ $t('oauthLogin') }}</div>
<div class="card-content">
<div class="setting-item" v-for="p in oauthPlatforms" :key="p.key">
<div><span>{{ p.label }}</span></div>
<div class="forward">
<span>{{ setting[p.key + 'Switch'] ? $t('enabled') : $t('disabled') }}</span>
<el-button class="opt-button" size="small" type="primary" :disabled="!setting[p.key + 'Switch']" @click="openOauthSetting(p)">
<Icon icon="fluent:settings-48-regular" width="18" height="18"/>
</el-button>
</div>
</div>
</div>
</div>
<div class="settings-card">
<div class="card-title">{{ $t('noticeTitle') }}</div>
<div class="card-content">
@@ -413,6 +397,22 @@
</div>
</div>
<!-- OAuth Login Card -->
<div class="settings-card">
<div class="card-title">{{ $t('oauthLogin') }}</div>
<div class="card-content">
<div class="setting-item" v-for="p in oauthPlatforms" :key="p.key">
<div><span>{{ p.label }}</span></div>
<div class="forward">
<span>{{ setting[p.key + 'Switch'] === 0 ? $t('enabled') : $t('disabled') }}</span>
<el-button class="opt-button" size="small" type="primary" @click="openOauthSetting(p)">
<Icon icon="fluent:settings-48-regular" width="18" height="18"/>
</el-button>
</div>
</div>
</div>
</div>
<div class="settings-card about">
<div class="card-title">{{ $t('about') }}</div>
<div class="card-content">
@@ -504,17 +504,18 @@
</form>
</el-dialog>
<el-dialog v-model="oauthSettingShow" :title="$t('oauthSetting') + ' - ' + oauthForm.label" width="340"
@closed="oauthForm.clientId = ''; oauthForm.clientSecret = ''; oauthForm.callbackBase = ''">
@closed="oauthForm.clientId = ''; oauthForm.clientSecret = ''; oauthForm.switch = 1">
<div class="dialog-content">
<el-input type="text" :placeholder="$t('clientId')" v-model="oauthForm.clientId"/>
<el-input type="text" style="margin-top: 15px" :placeholder="$t('clientSecret')" v-model="oauthForm.clientSecret"/>
<el-input type="text" style="margin-top: 15px" :placeholder="$t('callbackBase')" v-model="oauthForm.callbackBase">
<template #append>/login/{{ oauthForm.key }}</template>
</el-input>
<div style="display: flex; justify-content: flex-end; margin-top: 15px;">
<el-button type="primary" @click="saveOauth">{{ $t('save') }}</el-button>
</div>
<template #footer>
<div class="dialog-footer">
<el-switch v-model="oauthForm.switch" :active-value="0" :inactive-value="1" :active-text="$t('enable')"
:inactive-text="$t('disable')"/>
<el-button type="primary" :loading="settingLoading" @click="saveOauth">{{ $t('save') }}</el-button>
</div>
</template>
</el-dialog>
<el-dialog
v-model="showSetBackground"
@@ -919,7 +920,6 @@ const turnstileForm = reactive({
const oauthPlatforms = [
{ key: 'linuxdo', label: 'LinuxDo' },
{ key: 'github', label: 'GitHub' },
{ key: 'gitlab', label: 'GitLab' },
{ key: 'google', label: 'Google' },
]
const oauthSettingShow = ref(false)
@@ -928,7 +928,7 @@ const oauthForm = reactive({
label: '',
clientId: '',
clientSecret: '',
callbackBase: '',
switch: 1,
})
const s3 = reactive({
@@ -1393,9 +1393,7 @@ function openOauthSetting(p) {
oauthForm.label = p.label
oauthForm.clientId = setting.value[p.key + 'ClientId'] || ''
oauthForm.clientSecret = setting.value[p.key + 'ClientSecret'] || ''
const suffix = '/login/' + p.key
const fullUrl = setting.value[p.key + 'CallbackUrl'] || ''
oauthForm.callbackBase = fullUrl.endsWith(suffix) ? fullUrl.slice(0, -suffix.length) : fullUrl
oauthForm.switch = setting.value[p.key + 'Switch'] ?? 1
oauthSettingShow.value = true
}
@@ -1403,9 +1401,8 @@ function saveOauth() {
const form = {}
form[oauthForm.key + 'ClientId'] = oauthForm.clientId
form[oauthForm.key + 'ClientSecret'] = oauthForm.clientSecret
form[oauthForm.key + 'CallbackUrl'] = oauthForm.callbackBase + '/login/' + oauthForm.key
form[oauthForm.key + 'Switch'] = oauthForm.switch
editSetting(form)
oauthSettingShow.value = false
}
function saveTurnstileKey() {
@@ -1571,6 +1568,7 @@ function editSetting(settingForm, refreshStatus = true) {
addS3Show.value = false
emailPrefixShow.value = false
aiCodeFilterShow.value = false
oauthSettingShow.value = false
}).catch((e) => {
loginOpacity.value = setting.value.loginOpacity
setting.value = {...setting.value, ...JSON.parse(backup)}
-5
View File
@@ -12,11 +12,6 @@ app.post('/oauth/github/login', async (c) => {
return c.json(result.ok(loginInfo))
});
app.post('/oauth/gitlab/login', async (c) => {
const loginInfo = await oauthService.gitlabLogin(c, await c.req.json());
return c.json(result.ok(loginInfo))
});
app.post('/oauth/google/login', async (c) => {
const loginInfo = await oauthService.googleLogin(c, await c.req.json());
return c.json(result.ok(loginInfo))
+3 -6
View File
@@ -55,15 +55,12 @@ export const setting = sqliteTable('setting', {
aiCodeFilter: text('ai_code_filter').default('').notNull(),
linuxdoClientId: text('linuxdo_client_id').default('').notNull(),
linuxdoClientSecret: text('linuxdo_client_secret').default('').notNull(),
linuxdoCallbackUrl: text('linuxdo_callback_url').default('').notNull(),
linuxdoSwitch: integer('linuxdo_switch').default(1).notNull(),
githubClientId: text('github_client_id').default('').notNull(),
githubClientSecret: text('github_client_secret').default('').notNull(),
githubCallbackUrl: text('github_callback_url').default('').notNull(),
gitlabClientId: text('gitlab_client_id').default('').notNull(),
gitlabClientSecret: text('gitlab_client_secret').default('').notNull(),
gitlabCallbackUrl: text('gitlab_callback_url').default('').notNull(),
githubSwitch: integer('github_switch').default(1).notNull(),
googleClientId: text('google_client_id').default('').notNull(),
googleClientSecret: text('google_client_secret').default('').notNull(),
googleCallbackUrl: text('google_callback_url').default('').notNull()
googleSwitch: integer('google_switch').default(1).notNull()
});
export default setting
+1
View File
@@ -15,6 +15,7 @@ const en = {
noOsDomainSendAtt: 'Cannot send attachments: object storage domain not configured',
noOsSendAtt: 'Cannot send attachments: object storage not configured',
disabledSend: 'Email sending feature is disabled',
oauthDisabled: 'This OAuth login is not enabled',
daySendLimit: 'Daily send limit reached',
totalSendLimit: 'Total send limit reached',
daySendLack: 'Not enough remaining sends today',
+1
View File
@@ -15,6 +15,7 @@ const zh = {
noOsDomainSendAtt: '对象存储域名未配置不能发送附件',
noOsSendAtt: '对象存储未配置不能发送附件',
disabledSend: '邮件发送功能已停用',
oauthDisabled: '该 OAuth 登录未启用',
daySendLimit: '发送次数已到达每日限制',
totalSendLimit: '发送次数已到达限制',
daySendLack: '当日剩余发送次数不足',
+17 -4
View File
@@ -31,16 +31,29 @@ const dbInit = {
await this.v3_0DB(c);
await this.v3_1DB(c);
await this.v3_2DB(c);
await this.v3_3DB(c);
await settingService.refresh(c);
return c.text('success');
},
async v3_3DB(c) {
const oauthSwitchFields = [
'linuxdo_switch', 'github_switch', 'google_switch',
];
for (const field of oauthSwitchFields) {
try {
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN ${field} INTEGER NOT NULL DEFAULT 1;`).run();
} catch (e) {
console.warn(`跳过字段:${e.message}`);
}
}
},
async v3_2DB(c) {
const oauthFields = [
'linuxdo_client_id', 'linuxdo_client_secret', 'linuxdo_callback_url',
'github_client_id', 'github_client_secret', 'github_callback_url',
'gitlab_client_id', 'gitlab_client_secret', 'gitlab_callback_url',
'google_client_id', 'google_client_secret', 'google_callback_url',
'linuxdo_client_id', 'linuxdo_client_secret',
'github_client_id', 'github_client_secret',
'google_client_id', 'google_client_secret',
];
for (const field of oauthFields) {
try {
+16 -52
View File
@@ -6,6 +6,7 @@ import userService from "./user-service";
import loginService from "./login-service";
import cryptoUtils from "../utils/crypto-utils";
import settingService from "./setting-service";
import {t} from '../i18n/i18n';
const oauthService = {
@@ -33,15 +34,16 @@ const oauthService = {
async linuxDoLogin(c, params) {
const { code } = params;
const { code, redirectUri } = params;
const setting = await settingService.query(c);
this.assertEnabled(setting, 'linuxdoSwitch');
const reqParams = new URLSearchParams()
reqParams.append('client_id', setting.linuxdoClientId)
reqParams.append('client_secret', setting.linuxdoClientSecret)
reqParams.append('code', code)
reqParams.append('redirect_uri', setting.linuxdoCallbackUrl)
reqParams.append('redirect_uri', redirectUri)
reqParams.append('grant_type', 'authorization_code')
const tokenRes = await fetch("https://connect.linux.do/oauth2/token", {
@@ -80,9 +82,10 @@ const oauthService = {
async githubLogin(c, params) {
const { code } = params;
const { code, redirectUri } = params;
const setting = await settingService.query(c);
this.assertEnabled(setting, 'githubSwitch');
const tokenRes = await fetch("https://github.com/login/oauth/access_token", {
method: "POST",
@@ -94,7 +97,7 @@ const oauthService = {
client_id: setting.githubClientId,
client_secret: setting.githubClientSecret,
code: code,
redirect_uri: setting.githubCallbackUrl
redirect_uri: redirectUri
})
});
@@ -129,63 +132,18 @@ const oauthService = {
return await this.saveAndLogin(c, userInfo);
},
async gitlabLogin(c, params) {
const { code } = params;
const setting = await settingService.query(c);
const reqParams = new URLSearchParams()
reqParams.append('client_id', setting.gitlabClientId)
reqParams.append('client_secret', setting.gitlabClientSecret)
reqParams.append('code', code)
reqParams.append('redirect_uri', setting.gitlabCallbackUrl)
reqParams.append('grant_type', 'authorization_code')
const tokenRes = await fetch("https://gitlab.com/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: reqParams.toString()
});
if (!tokenRes.ok) {
throw new BizError(tokenRes.statusText);
}
const token = await tokenRes.json();
const userRes = await fetch('https://gitlab.com/api/v4/user', {
headers: {
Authorization: 'Bearer ' + token.access_token
}
});
if (!userRes.ok) {
throw new BizError(userRes.statusText);
}
const userInfo = await userRes.json();
userInfo.oauthUserId = String(userInfo.id);
userInfo.username = userInfo.username;
userInfo.name = userInfo.name;
userInfo.avatar = userInfo.avatar_url;
userInfo.platform = 'gitlab';
return await this.saveAndLogin(c, userInfo);
},
async googleLogin(c, params) {
const { code } = params;
const { code, redirectUri } = params;
const setting = await settingService.query(c);
this.assertEnabled(setting, 'googleSwitch');
const reqParams = new URLSearchParams()
reqParams.append('client_id', setting.googleClientId)
reqParams.append('client_secret', setting.googleClientSecret)
reqParams.append('code', code)
reqParams.append('redirect_uri', setting.googleCallbackUrl)
reqParams.append('redirect_uri', redirectUri)
reqParams.append('grant_type', 'authorization_code')
const tokenRes = await fetch("https://oauth2.googleapis.com/token", {
@@ -246,6 +204,12 @@ const oauthService = {
},
assertEnabled(setting, switchKey) {
if (setting[switchKey] !== 0) {
throw new BizError(t('oauthDisabled'));
}
},
async getById(c, oauthUserId) {
return await orm(c).select().from(oauth).where(eq(oauth.oauthUserId, oauthUserId)).get();
},
@@ -59,11 +59,6 @@ const settingService = {
setting.projectLink = projectLink;
setting.linuxdoSwitch = this.parseBoolean(c.env.linuxdo_switch);
setting.githubSwitch = this.parseBoolean(c.env.github_switch);
setting.gitlabSwitch = this.parseBoolean(c.env.gitlab_switch);
setting.googleSwitch = this.parseBoolean(c.env.google_switch);
setting.emailPrefixFilter = setting.emailPrefixFilter.split(",").filter(Boolean);
c.set?.('setting', setting);
@@ -131,15 +126,6 @@ const settingService = {
params.resendTokens = JSON.stringify(resendTokens);
const callbackPlatforms = ['linuxdo', 'github', 'gitlab', 'google'];
for (const platform of callbackPlatforms) {
const key = platform + 'CallbackUrl';
const expectedSuffix = '/login/' + platform;
if (params[key] && !params[key].endsWith(expectedSuffix)) {
throw new BizError(`Invalid callback URL for ${platform}: must end with ${expectedSuffix}`);
}
}
await orm(c).update(setting).set({ ...params }).returning().get();
await this.refresh(c);
},
@@ -229,28 +215,16 @@ const settingService = {
notice: settingRow.notice,
loginDomain: settingRow.loginDomain,
linuxdoClientId: settingRow.linuxdoClientId,
linuxdoCallbackUrl: settingRow.linuxdoCallbackUrl,
linuxdoSwitch: settingRow.linuxdoSwitch,
githubClientId: settingRow.githubClientId,
githubCallbackUrl: settingRow.githubCallbackUrl,
githubSwitch: settingRow.githubSwitch,
gitlabClientId: settingRow.gitlabClientId,
gitlabCallbackUrl: settingRow.gitlabCallbackUrl,
gitlabSwitch: settingRow.gitlabSwitch,
googleClientId: settingRow.googleClientId,
googleCallbackUrl: settingRow.googleCallbackUrl,
googleSwitch: settingRow.googleSwitch,
minEmailPrefix: settingRow.minEmailPrefix,
projectLink: settingRow.projectLink
};
},
parseBoolean(value) {
if (typeof value === 'string' && value === 'true') return true;
if (value === true) return true;
return false;
},
};
export default settingService;
-5
View File
@@ -44,10 +44,5 @@ admin = "${ADMIN}"
jwt_secret = "${JWT_SECRET}"
project_link = "${PROJECT_LINK}"
linuxdo_switch = "${LINUXDO_SWITCH}"
github_switch = "${GITHUB_SWITCH}"
gitlab_switch = "${GITLAB_SWITCH}"
google_switch = "${GOOGLE_SWITCH}"
[build]
command = "pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build"
-4
View File
@@ -42,10 +42,6 @@ crons = ["0 16 * * *"] #每天晚上12点执行每日任务,刷新分析缓存
#domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"]
#admin = "" #管理员的邮箱 示例: [email protected]
#jwt_secret = "" #jwt令牌的密钥,随便填一串字符串
#linuxdo_switch = "" #LinuxDo OAuth 开关
#github_switch = "" #GitHub OAuth 开关
#gitlab_switch = "" #GitLab OAuth 开关
#google_switch = "" #Google OAuth 开关
[build]
command = "pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build"