mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-06 17:59:11 +00:00
feat(web): add OIDC SSO login support (#1943)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||
import { Card, InputText, Password, Button, AutoComplete } from 'primevue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
@@ -68,8 +68,43 @@ const apiHostSearch = async (event: { query: string }) => {
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const oidcEnabled = ref(false);
|
||||
const lastCheckedHost = ref('');
|
||||
const oidcCheckTimer = ref<ReturnType<typeof setTimeout> | null>(null);
|
||||
const checkOidcConfig = () => {
|
||||
if (oidcCheckTimer.value) clearTimeout(oidcCheckTimer.value);
|
||||
oidcCheckTimer.value = setTimeout(async () => {
|
||||
const host = apiHost.value;
|
||||
if (host === lastCheckedHost.value) return;
|
||||
|
||||
const enabled = (await new ApiClient(host).getOidcConfig()).enabled;
|
||||
// If host changes while request is in-flight, do not overwrite UI state.
|
||||
if (apiHost.value !== host) return;
|
||||
|
||||
lastCheckedHost.value = host;
|
||||
oidcEnabled.value = enabled;
|
||||
}, 300);
|
||||
};
|
||||
|
||||
watch(apiHost, () => {
|
||||
checkOidcConfig();
|
||||
});
|
||||
|
||||
const onSsoLogin = () => {
|
||||
saveApiHost(apiHost.value);
|
||||
localStorage.setItem('apiHost', btoa(apiHost.value));
|
||||
window.location.href = api.value.oidcLoginUrl();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
checkOidcConfig();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (oidcCheckTimer.value) {
|
||||
clearTimeout(oidcCheckTimer.value);
|
||||
oidcCheckTimer.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -104,6 +139,10 @@ onMounted(() => {
|
||||
<Button :label="t('web.login.register')" type="button" class="w-full"
|
||||
@click="saveApiHost(apiHost); $router.replace({ name: 'register' })" severity="secondary" />
|
||||
</div>
|
||||
<div v-if="oidcEnabled" class="flex items-center justify-between">
|
||||
<Button :label="t('web.login.sso_login')" type="button" class="w-full" severity="info"
|
||||
@click="onSsoLogin" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form v-else @submit.prevent="onRegister" class="space-y-4">
|
||||
@@ -144,4 +183,4 @@ onMounted(() => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -6,6 +6,10 @@ export interface ValidateConfigResponse {
|
||||
toml_config: string;
|
||||
}
|
||||
|
||||
export interface OidcConfigResponse {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
// 定义接口返回的数据结构
|
||||
export interface LoginResponse {
|
||||
success: boolean;
|
||||
@@ -174,6 +178,19 @@ export class ApiClient {
|
||||
return this.client.defaults.baseURL + '/auth/captcha';
|
||||
}
|
||||
|
||||
public async getOidcConfig(): Promise<OidcConfigResponse> {
|
||||
try {
|
||||
const response = await this.client.get<any, OidcConfigResponse>('/auth/oidc/config');
|
||||
return response;
|
||||
} catch (error) {
|
||||
return { enabled: false };
|
||||
}
|
||||
}
|
||||
|
||||
public oidcLoginUrl() {
|
||||
return this.client.defaults.baseURL + '/auth/oidc/login';
|
||||
}
|
||||
|
||||
public get_remote_client(machine_id: string): Api.RemoteClient {
|
||||
return new WebRemoteClient(machine_id, this.client);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user