✨ View auth factors in admin panel
This commit is contained in:
parent
13c26486b6
commit
8c7f255473
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,2 @@
|
|||||||
#n:public
|
#n:public
|
||||||
!<md> [7430, 0, null, null, -2147483648, -2147483648]
|
!<md> [10102, 0, null, null, -2147483648, -2147483648]
|
||||||
|
75
.idea/workspace.xml
generated
75
.idea/workspace.xml
generated
@ -4,17 +4,14 @@
|
|||||||
<option name="autoReloadType" value="ALL" />
|
<option name="autoReloadType" value="ALL" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":sparkles: Admin check users' auth factor">
|
<list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":bug: Fix clear function doesn't real clear items in slice">
|
||||||
<change afterPath="$PROJECT_DIR$/web/src/components/admin/UserAssignPermsPanel.vue" afterDir="false" />
|
<change afterPath="$PROJECT_DIR$/web/src/components/admin/UserFactorPanel.vue" afterDir="false" />
|
||||||
<change afterPath="$PROJECT_DIR$/web/src/components/admin/UserDetailPanel.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/dataSources/74bcf3ef-a2b9-435b-b9e5-f32902a33b25.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources/74bcf3ef-a2b9-435b-b9e5-f32902a33b25.xml" afterDir="false" />
|
||||||
<change afterPath="$PROJECT_DIR$/web/src/layouts/administrator.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/dataSources/74bcf3ef-a2b9-435b-b9e5-f32902a33b25/storage_v2/_src_/database/hy_passport.gNOKQQ/schema/public.abK9xQ.meta" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources/74bcf3ef-a2b9-435b-b9e5-f32902a33b25/storage_v2/_src_/database/hy_passport.gNOKQQ/schema/public.abK9xQ.meta" afterDir="false" />
|
||||||
<change afterPath="$PROJECT_DIR$/web/src/views/admin/dashboard.vue" afterDir="false" />
|
|
||||||
<change afterPath="$PROJECT_DIR$/web/src/views/admin/users.vue" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/web/src/components/navigation/AppBar.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/components/navigation/AppBar.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/web/src/components/admin/UserAssignPermsPanel.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/components/admin/UserAssignPermsPanel.vue" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/web/src/layouts/user-center.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/layouts/user-center.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/web/src/components/admin/UserDetailPanel.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/components/admin/UserDetailPanel.vue" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/web/src/router/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/router/index.ts" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/web/src/views/admin/users.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/views/admin/users.vue" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/web/src/views/security.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/views/security.vue" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@ -49,41 +46,41 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"DefaultGoTemplateProperty": "Go File",
|
"DefaultGoTemplateProperty": "Go File",
|
||||||
"Go Build.Backend.executor": "Run",
|
"Go Build.Backend.executor": "Run",
|
||||||
"Go 构建.Backend.executor": "Run",
|
"Go 构建.Backend.executor": "Run",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"RunOnceActivity.go.formatter.settings.were.checked": "true",
|
"RunOnceActivity.go.formatter.settings.were.checked": "true",
|
||||||
"RunOnceActivity.go.migrated.go.modules.settings": "true",
|
"RunOnceActivity.go.migrated.go.modules.settings": "true",
|
||||||
"RunOnceActivity.go.modules.automatic.dependencies.download": "true",
|
"RunOnceActivity.go.modules.automatic.dependencies.download": "true",
|
||||||
"RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
|
"RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
|
||||||
"git-widget-placeholder": "master",
|
"git-widget-placeholder": "master",
|
||||||
"go.import.settings.migrated": "true",
|
"go.import.settings.migrated": "true",
|
||||||
"go.sdk.automatically.set": "true",
|
"go.sdk.automatically.set": "true",
|
||||||
"last_opened_file_path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/src/views",
|
"last_opened_file_path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/src/components/admin",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"run.code.analysis.last.selected.profile": "pProject Default",
|
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||||
"ts.external.directory.path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/node_modules/typescript/lib",
|
"ts.external.directory.path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/node_modules/typescript/lib",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
},
|
},
|
||||||
"keyToStringList": {
|
"keyToStringList": {
|
||||||
"DatabaseDriversLRU": [
|
"DatabaseDriversLRU": [
|
||||||
"postgresql"
|
"postgresql"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}</component>
|
}]]></component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$/web/src/components/admin" />
|
||||||
<recent name="$PROJECT_DIR$/web/src/views" />
|
<recent name="$PROJECT_DIR$/web/src/views" />
|
||||||
<recent name="$PROJECT_DIR$/pkg/internal/server/api" />
|
<recent name="$PROJECT_DIR$/pkg/internal/server/api" />
|
||||||
<recent name="$PROJECT_DIR$/web" />
|
<recent name="$PROJECT_DIR$/web" />
|
||||||
<recent name="$PROJECT_DIR$/pkg/services" />
|
<recent name="$PROJECT_DIR$/pkg/services" />
|
||||||
<recent name="$PROJECT_DIR$/pkg/server/ui" />
|
|
||||||
</key>
|
</key>
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
<recent name="$PROJECT_DIR$/web/src/views/flow" />
|
<recent name="$PROJECT_DIR$/web/src/views/flow" />
|
||||||
@ -160,8 +157,6 @@
|
|||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="VcsManagerConfiguration">
|
<component name="VcsManagerConfiguration">
|
||||||
<MESSAGE value=":sparkles: Edit, delete current status" />
|
|
||||||
<MESSAGE value=":bug: Fix clear status affected the statutes cleared before" />
|
|
||||||
<MESSAGE value=":sparkles: Get self-current status API" />
|
<MESSAGE value=":sparkles: Get self-current status API" />
|
||||||
<MESSAGE value=":sparkles: Get myself current status API" />
|
<MESSAGE value=":sparkles: Get myself current status API" />
|
||||||
<MESSAGE value=":bug: Fix miscall function" />
|
<MESSAGE value=":bug: Fix miscall function" />
|
||||||
@ -185,7 +180,9 @@
|
|||||||
<MESSAGE value=":sparkles: Admin force confirm account" />
|
<MESSAGE value=":sparkles: Admin force confirm account" />
|
||||||
<MESSAGE value=":sparkles: Admin notify one user" />
|
<MESSAGE value=":sparkles: Admin notify one user" />
|
||||||
<MESSAGE value=":sparkles: Admin check users' auth factor" />
|
<MESSAGE value=":sparkles: Admin check users' auth factor" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value=":sparkles: Admin check users' auth factor" />
|
<MESSAGE value=":sparkles: Admin panel & users, users' permissions management" />
|
||||||
|
<MESSAGE value=":bug: Fix clear function doesn't real clear items in slice" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value=":bug: Fix clear function doesn't real clear items in slice" />
|
||||||
</component>
|
</component>
|
||||||
<component name="VgoProject">
|
<component name="VgoProject">
|
||||||
<settings-migrated>true</settings-migrated>
|
<settings-migrated>true</settings-migrated>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog class="max-w-[720px]" :model-value="data != null" @update:model-value="(val) => !val && emits('close')">
|
<v-dialog class="max-w-[720px]" :model-value="props.data != null" @update:model-value="(val) => !val && emits('close')">
|
||||||
<template v-slot:default="{ isActive }">
|
<template v-slot:default="{ isActive }">
|
||||||
<v-card title="Assign permissions" :subtitle="`To user @${props.data?.name}`" :loading="submitting">
|
<v-card title="Assign permissions" :subtitle="`To user @${props.data?.name}`" :loading="submitting">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog class="max-w-[720px]" :model-value="data != null" @update:model-value="(val) => !val && emits('close')">
|
<v-dialog class="max-w-[720px]" :model-value="props.data != null" @update:model-value="(val) => !val && emits('close')">
|
||||||
<template v-slot:default="{ isActive }">
|
<template v-slot:default="{ isActive }">
|
||||||
<v-card :title="`User @${props.data?.name}`">
|
<v-card :title="`User @${props.data?.name}`">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
|
74
web/src/components/admin/UserFactorPanel.vue
Normal file
74
web/src/components/admin/UserFactorPanel.vue
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<v-dialog class="max-w-[720px]" :model-value="props.data != null"
|
||||||
|
@update:model-value="(val) => !val && emits('close')"
|
||||||
|
:loading="reverting">
|
||||||
|
<template v-slot:default="{ isActive }">
|
||||||
|
<v-card title="Auth Factors" :subtitle="`Of user @${props.data?.name}`">
|
||||||
|
<v-card-text>
|
||||||
|
<v-sheet elevation="2" rounded="lg">
|
||||||
|
<v-table density="compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="text-left">
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th class="text-left">
|
||||||
|
Secret
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="item in factors"
|
||||||
|
:key="item.name"
|
||||||
|
>
|
||||||
|
<td class="w-1/2">{{ item.id }}</td>
|
||||||
|
<td class="w-1/2"><code>{{ item.secret }}</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</v-table>
|
||||||
|
</v-sheet>
|
||||||
|
</v-card-text>
|
||||||
|
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
text="Close"
|
||||||
|
@click="isActive.value = false"
|
||||||
|
></v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue"
|
||||||
|
import { request } from "@/scripts/request"
|
||||||
|
|
||||||
|
const props = defineProps<{ data: any }>()
|
||||||
|
const emits = defineEmits(["close", "error"])
|
||||||
|
|
||||||
|
const reverting = ref(false)
|
||||||
|
|
||||||
|
const factors = ref<any[]>([])
|
||||||
|
|
||||||
|
async function load() {
|
||||||
|
reverting.value = true
|
||||||
|
const res = await request(`/api/admin/users/${props.data.id}/factors`)
|
||||||
|
if (res.status !== 200) {
|
||||||
|
emits("error", await res.text())
|
||||||
|
} else {
|
||||||
|
factors.value = await res.json()
|
||||||
|
}
|
||||||
|
reverting.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(props, (v) => {
|
||||||
|
if (v.data != null) {
|
||||||
|
factors.value = []
|
||||||
|
load()
|
||||||
|
}
|
||||||
|
}, { immediate: true, deep: true })
|
||||||
|
</script>
|
@ -52,6 +52,18 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
|
<v-tooltip text="View Auth Factors">
|
||||||
|
<template #activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
v-bind="props"
|
||||||
|
variant="text"
|
||||||
|
size="x-small"
|
||||||
|
color="warning"
|
||||||
|
icon="mdi-lock"
|
||||||
|
@click="viewingFactorUser = item"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
@ -61,6 +73,7 @@
|
|||||||
<user-assign-perms-panel :data="assigningPermUser" @close="assigningPermUser = null"
|
<user-assign-perms-panel :data="assigningPermUser" @close="assigningPermUser = null"
|
||||||
@success="readUsers(pagination)"
|
@success="readUsers(pagination)"
|
||||||
@error="val => error = val" />
|
@error="val => error = val" />
|
||||||
|
<user-factor-panel :data="viewingFactorUser" @close="viewingFactorUser = null" @error="val => error = val" />
|
||||||
|
|
||||||
<v-snackbar :timeout="3000" :model-value="error != null" @update:model-value="_ => error = null">
|
<v-snackbar :timeout="3000" :model-value="error != null" @update:model-value="_ => error = null">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
@ -74,12 +87,14 @@ import { request } from "@/scripts/request"
|
|||||||
import { getAtk } from "@/stores/userinfo"
|
import { getAtk } from "@/stores/userinfo"
|
||||||
import UserDetailPanel from "@/components/admin/UserDetailPanel.vue"
|
import UserDetailPanel from "@/components/admin/UserDetailPanel.vue"
|
||||||
import UserAssignPermsPanel from "@/components/admin/UserAssignPermsPanel.vue"
|
import UserAssignPermsPanel from "@/components/admin/UserAssignPermsPanel.vue"
|
||||||
|
import UserFactorPanel from "@/components/admin/UserFactorPanel.vue"
|
||||||
|
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
const users = ref<any[]>([])
|
const users = ref<any[]>([])
|
||||||
|
|
||||||
const viewingUser = ref<any>(null)
|
const viewingUser = ref<any>(null)
|
||||||
|
const viewingFactorUser = ref<any>(null)
|
||||||
const assigningPermUser = ref<any>(null)
|
const assigningPermUser = ref<any>(null)
|
||||||
|
|
||||||
const dataDefinitions: { [id: string]: any[] } = {
|
const dataDefinitions: { [id: string]: any[] } = {
|
||||||
|
Loading…
Reference in New Issue
Block a user