feat: add auth provider boundary
This commit is contained in:
@@ -6,6 +6,132 @@
|
||||
// @ts-ignore: Unused imports
|
||||
import {Create as $Create} from "@wailsio/runtime";
|
||||
|
||||
export class AuthProviderOption {
|
||||
/**
|
||||
* Creates a new AuthProviderOption instance.
|
||||
* @param {Partial<AuthProviderOption>} [$$source = {}] - The source object to create the AuthProviderOption.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("value" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["value"] = "";
|
||||
}
|
||||
if (!("label" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["label"] = "";
|
||||
}
|
||||
if (!("description" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["description"] = "";
|
||||
}
|
||||
if (!("enabled" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {boolean}
|
||||
*/
|
||||
this["enabled"] = false;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AuthProviderOption instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {AuthProviderOption}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new AuthProviderOption(/** @type {Partial<AuthProviderOption>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
export class AuthSession {
|
||||
/**
|
||||
* Creates a new AuthSession instance.
|
||||
* @param {Partial<AuthSession>} [$$source = {}] - The source object to create the AuthSession.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("id" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {number}
|
||||
*/
|
||||
this["id"] = 0;
|
||||
}
|
||||
if (!("userId" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["userId"] = "";
|
||||
}
|
||||
if (!("username" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["username"] = "";
|
||||
}
|
||||
if (!("provider" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["provider"] = "";
|
||||
}
|
||||
if (!("token" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["token"] = "";
|
||||
}
|
||||
if (!("createdAt" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["createdAt"] = "";
|
||||
}
|
||||
if (!("expiresAt" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["expiresAt"] = "";
|
||||
}
|
||||
if (!("active" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {boolean}
|
||||
*/
|
||||
this["active"] = false;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AuthSession instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {AuthSession}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new AuthSession(/** @type {Partial<AuthSession>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
export class Hotkey {
|
||||
/**
|
||||
* Creates a new Hotkey instance.
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import * as models$0 from "../models/models.js";
|
||||
|
||||
/**
|
||||
* @returns {Promise<string> & { cancel(): void }}
|
||||
*/
|
||||
export function GetAuthMode() {
|
||||
let $resultPromise = /** @type {any} */($Call.ByID(1527507258));
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<models$0.AuthProviderOption[]> & { cancel(): void }}
|
||||
*/
|
||||
export function GetAuthProviders() {
|
||||
let $resultPromise = /** @type {any} */($Call.ByID(2710846997));
|
||||
let $typingPromise = /** @type {any} */($resultPromise.then(($result) => {
|
||||
return $$createType1($result);
|
||||
}));
|
||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
||||
return $typingPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<models$0.AuthSession> & { cancel(): void }}
|
||||
*/
|
||||
export function GetCurrentSession() {
|
||||
let $resultPromise = /** @type {any} */($Call.ByID(2579662840));
|
||||
let $typingPromise = /** @type {any} */($resultPromise.then(($result) => {
|
||||
return $$createType2($result);
|
||||
}));
|
||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
||||
return $typingPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} provider
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
* @returns {Promise<models$0.AuthSession> & { cancel(): void }}
|
||||
*/
|
||||
export function Login(provider, username, password) {
|
||||
let $resultPromise = /** @type {any} */($Call.ByID(4113748438, provider, username, password));
|
||||
let $typingPromise = /** @type {any} */($resultPromise.then(($result) => {
|
||||
return $$createType2($result);
|
||||
}));
|
||||
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
||||
return $typingPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<void> & { cancel(): void }}
|
||||
*/
|
||||
export function Logout() {
|
||||
let $resultPromise = /** @type {any} */($Call.ByID(3585850903));
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} mode
|
||||
* @returns {Promise<void> & { cancel(): void }}
|
||||
*/
|
||||
export function SetAuthMode(mode) {
|
||||
let $resultPromise = /** @type {any} */($Call.ByID(3911115982, mode));
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
// Private type creation functions
|
||||
const $$createType0 = models$0.AuthProviderOption.createFrom;
|
||||
const $$createType1 = $Create.Array($$createType0);
|
||||
const $$createType2 = models$0.AuthSession.createFrom;
|
||||
@@ -4,12 +4,14 @@
|
||||
|
||||
import * as AppConfigService from "./appconfigservice.js";
|
||||
import * as AppService from "./appservice.js";
|
||||
import * as AuthService from "./authservice.js";
|
||||
import * as HotkeyService from "./hotkeyservice.js";
|
||||
import * as OCRService from "./ocrservice.js";
|
||||
import * as SystemInfo from "./systeminfo.js";
|
||||
export {
|
||||
AppConfigService,
|
||||
AppService,
|
||||
AuthService,
|
||||
HotkeyService,
|
||||
OCRService,
|
||||
SystemInfo
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from '@ant-design/icons-vue'
|
||||
import { Window } from '@wailsio/runtime'
|
||||
import { OpenSecondWindow } from '../../bindings/cmbone/internal/services/appservice'
|
||||
import { GetCurrentSession } from '../../bindings/cmbone/internal/services/authservice'
|
||||
import { getOS, OS_READY } from '../utils/osinfo'
|
||||
|
||||
type NavItem = {
|
||||
@@ -30,6 +31,8 @@ const route = useRoute()
|
||||
const isWindows = ref(false)
|
||||
const isMacOS = ref(false)
|
||||
const isMaximized = ref(false)
|
||||
const sessionUsername = ref('未登录')
|
||||
const sessionProvider = ref('Auth Provider')
|
||||
|
||||
const navItems: NavItem[] = [
|
||||
{ path: '/dashboard', label: '工作台', detail: '指标与近期任务', icon: DashboardOutlined },
|
||||
@@ -59,6 +62,11 @@ onMounted(async () => {
|
||||
if (isWindows.value) {
|
||||
isMaximized.value = await Window.IsMaximised()
|
||||
}
|
||||
const session = await GetCurrentSession()
|
||||
if (session.active) {
|
||||
sessionUsername.value = session.username
|
||||
sessionProvider.value = session.provider
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -102,10 +110,10 @@ onMounted(async () => {
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
<p class="mb-0 truncate text-sm font-medium text-slate-900 dark:text-white">
|
||||
本地演示用户
|
||||
{{ sessionUsername }}
|
||||
</p>
|
||||
<p class="mb-0 truncate text-xs text-slate-500 dark:text-slate-400">
|
||||
Local Provider
|
||||
{{ sessionProvider }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { RouterLink, useRouter } from 'vue-router'
|
||||
import { DashboardOutlined } from '@ant-design/icons-vue'
|
||||
import { GetAuthMode, GetAuthProviders, Login } from '../../../bindings/cmbone/internal/services/authservice'
|
||||
|
||||
type ProviderOption = {
|
||||
value: string
|
||||
label: string
|
||||
description: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const provider = ref('local')
|
||||
const providers = ref<ProviderOption[]>([])
|
||||
const errorMessage = ref('')
|
||||
const isSubmitting = ref(false)
|
||||
|
||||
function submitLogin() {
|
||||
router.push('/dashboard')
|
||||
onMounted(async () => {
|
||||
providers.value = await GetAuthProviders()
|
||||
provider.value = await GetAuthMode()
|
||||
})
|
||||
|
||||
async function submitLogin() {
|
||||
errorMessage.value = ''
|
||||
isSubmitting.value = true
|
||||
try {
|
||||
await Login(provider.value, username.value, password.value)
|
||||
await router.push('/dashboard')
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof Error ? error.message : String(error)
|
||||
} finally {
|
||||
isSubmitting.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -34,23 +59,31 @@ function submitLogin() {
|
||||
<label class="block">
|
||||
<span class="mb-1 block text-sm font-medium">Provider</span>
|
||||
<select v-model="provider" class="h-10 w-full rounded-md border border-slate-300 bg-white px-3 text-sm outline-none focus:border-slate-500 dark:border-slate-700 dark:bg-slate-950">
|
||||
<option value="local">Local</option>
|
||||
<option value="remote">Remote</option>
|
||||
<option v-for="item in providers" :key="item.value" :value="item.value" :disabled="!item.enabled">
|
||||
{{ item.label }}{{ item.enabled ? '' : '(未配置)' }}
|
||||
</option>
|
||||
</select>
|
||||
<span class="mt-1 block text-xs text-slate-500 dark:text-slate-400">
|
||||
{{ providers.find((item) => item.value === provider)?.description || '登录 provider' }}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label class="block">
|
||||
<span class="mb-1 block text-sm font-medium">账号</span>
|
||||
<input v-model="username" class="h-10 w-full rounded-md border border-slate-300 bg-white px-3 text-sm outline-none focus:border-slate-500 dark:border-slate-700 dark:bg-slate-950" autocomplete="username" />
|
||||
<input v-model="username" class="h-10 w-full rounded-md border border-slate-300 bg-white px-3 text-sm outline-none focus:border-slate-500 dark:border-slate-700 dark:bg-slate-950" autocomplete="username" placeholder="请输入账号" />
|
||||
</label>
|
||||
|
||||
<label class="block">
|
||||
<span class="mb-1 block text-sm font-medium">密码</span>
|
||||
<input v-model="password" class="h-10 w-full rounded-md border border-slate-300 bg-white px-3 text-sm outline-none focus:border-slate-500 dark:border-slate-700 dark:bg-slate-950" type="password" autocomplete="current-password" />
|
||||
<input v-model="password" class="h-10 w-full rounded-md border border-slate-300 bg-white px-3 text-sm outline-none focus:border-slate-500 dark:border-slate-700 dark:bg-slate-950" type="password" autocomplete="current-password" placeholder="请输入密码" />
|
||||
</label>
|
||||
|
||||
<button class="h-10 w-full rounded-md bg-slate-950 text-sm font-medium text-white hover:bg-slate-800 dark:bg-white dark:text-slate-950 dark:hover:bg-slate-200" type="submit">
|
||||
进入应用
|
||||
<p v-if="errorMessage" class="rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-sm text-rose-700 dark:border-rose-900/50 dark:bg-rose-950/40 dark:text-rose-200">
|
||||
{{ errorMessage }}
|
||||
</p>
|
||||
|
||||
<button class="h-10 w-full rounded-md bg-slate-950 text-sm font-medium text-white hover:bg-slate-800 disabled:cursor-not-allowed disabled:opacity-60 dark:bg-white dark:text-slate-950 dark:hover:bg-slate-200" type="submit" :disabled="isSubmitting">
|
||||
{{ isSubmitting ? '登录中' : '进入应用' }}
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user