Compare commits
3 Commits
c80a950177
...
683973bd4f
Author | SHA1 | Date | |
---|---|---|---|
683973bd4f | |||
571541b34d | |||
f560099e38 |
@ -86,7 +86,7 @@ extern "C"
|
|||||||
auto value = std::string{};
|
auto value = std::string{};
|
||||||
auto status = user_db->Get(leveldb::ReadOptions{}, mangle_user_id(user_id), &value);
|
auto status = user_db->Get(leveldb::ReadOptions{}, mangle_user_id(user_id), &value);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
std::println(stderr, "Failed to login: {}", status.ToString());
|
if (!status.IsNotFound()) std::println(stderr, "Failed to login: {}", status.ToString());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*result = validate_password(password, value.data());
|
*result = validate_password(password, value.data());
|
||||||
@ -132,7 +132,7 @@ extern "C"
|
|||||||
if (status.ok()) {
|
if (status.ok()) {
|
||||||
*result = std::stoi(value);
|
*result = std::stoi(value);
|
||||||
} else {
|
} else {
|
||||||
std::println(stderr, "Failed to get user permission: {}", status.ToString());
|
if (!status.IsNotFound()) std::println(stderr, "Failed to get user permission: {}", status.ToString());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -55,6 +55,8 @@ static int field_get(const char* key, const char* value, size_t valuelen, void*
|
|||||||
form->user_id = kqm_strndup(value, valuelen);
|
form->user_id = kqm_strndup(value, valuelen);
|
||||||
} else if (strcmp(key, "raw_passwd") == 0) {
|
} else if (strcmp(key, "raw_passwd") == 0) {
|
||||||
form->raw_passwd = kqm_strndup(value, valuelen);
|
form->raw_passwd = kqm_strndup(value, valuelen);
|
||||||
|
} else if (strcmp(key, "new_passwd") == 0) {
|
||||||
|
form->new_passwd = kqm_strndup(value, valuelen);
|
||||||
} else if (strcmp(key, "permission") == 0) {
|
} else if (strcmp(key, "permission") == 0) {
|
||||||
form->permission = kqm_strndup(value, valuelen);
|
form->permission = kqm_strndup(value, valuelen);
|
||||||
}
|
}
|
||||||
@ -89,10 +91,12 @@ static void impl_repasswd(mg_connection* conn, admin_form_t* form)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
if (!admin_login(form->password, &result)) {
|
if (!admin_login(form->raw_passwd, &result)) {
|
||||||
res_unauth(conn);
|
res_unauth(conn);
|
||||||
|
return;
|
||||||
} else if (!result) {
|
} else if (!result) {
|
||||||
res_incorrect(conn);
|
res_incorrect(conn);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!set_admin_password(form->new_passwd)) {
|
if (!set_admin_password(form->new_passwd)) {
|
||||||
@ -113,7 +117,17 @@ static void impl_repasswd2(mg_connection* conn, admin_form_t* form)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flag = set_user_password(form->user_id, form->new_passwd);
|
int result;
|
||||||
|
int flag = check_user_exists(form->user_id, &result);
|
||||||
|
if (!flag) {
|
||||||
|
res_check_exist_fail(conn);
|
||||||
|
return;
|
||||||
|
} else if (!result) {
|
||||||
|
res_not_exist(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = set_user_password(form->user_id, form->new_passwd);
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
res_repasswd_fail(conn);
|
res_repasswd_fail(conn);
|
||||||
} else {
|
} else {
|
||||||
@ -147,7 +161,17 @@ static void impl_delete(mg_connection* conn, admin_form_t* form)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flag = delete_user(form->user_id);
|
int result;
|
||||||
|
int flag = check_user_exists(form->user_id, &result);
|
||||||
|
if (!flag) {
|
||||||
|
res_check_exist_fail(conn);
|
||||||
|
return;
|
||||||
|
} else if (!result) {
|
||||||
|
res_not_exist(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = delete_user(form->user_id);
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
res_delete_account_fail(conn);
|
res_delete_account_fail(conn);
|
||||||
} else {
|
} else {
|
||||||
@ -155,6 +179,11 @@ static void impl_delete(mg_connection* conn, admin_form_t* form)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void impl_auth(mg_connection* conn, admin_form_t* form)
|
||||||
|
{
|
||||||
|
res_auth(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int admin_handler(mg_connection* conn, void* cbdata)
|
int admin_handler(mg_connection* conn, void* cbdata)
|
||||||
{
|
{
|
||||||
@ -181,17 +210,20 @@ int admin_handler(mg_connection* conn, void* cbdata)
|
|||||||
|
|
||||||
mg_handle_form_request(conn, &admin_callback);
|
mg_handle_form_request(conn, &admin_callback);
|
||||||
|
|
||||||
if (form.action && !strcmp(form.action, "login")) {
|
if (!admin_session) {
|
||||||
form.token = strdup("");
|
|
||||||
admin_session = strdup("");
|
admin_session = strdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (form.action && !strcmp(form.action, "login")) {
|
||||||
|
form.token = strdup(admin_session);
|
||||||
|
}
|
||||||
|
|
||||||
if (!form.action) {
|
if (!form.action) {
|
||||||
res_need_action(conn);
|
res_need_action(conn);
|
||||||
} else if (!form.token) {
|
} else if (!form.token) {
|
||||||
res_need_token(conn);
|
res_need_token(conn);
|
||||||
} else if (!admin_session || strcmp(form.token, admin_session)) {
|
} else if (!admin_session || strcmp(form.token, admin_session)) {
|
||||||
res_permission_denied(conn);
|
res_auth_fail(conn);
|
||||||
} else {
|
} else {
|
||||||
if (!strcmp(form.action, "login")) {
|
if (!strcmp(form.action, "login")) {
|
||||||
impl_login(conn, &form);
|
impl_login(conn, &form);
|
||||||
@ -203,6 +235,8 @@ int admin_handler(mg_connection* conn, void* cbdata)
|
|||||||
impl_permission(conn, &form);
|
impl_permission(conn, &form);
|
||||||
} else if (!strcmp(form.action, "delete")) {
|
} else if (!strcmp(form.action, "delete")) {
|
||||||
impl_delete(conn, &form);
|
impl_delete(conn, &form);
|
||||||
|
} else if (!strcmp(form.action, "auth")) {
|
||||||
|
impl_auth(conn, &form);
|
||||||
} else {
|
} else {
|
||||||
res_bad_action(conn);
|
res_bad_action(conn);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "server/auth.h"
|
#include "server/auth.h"
|
||||||
#include "server/response.h"
|
#include "server/response.h"
|
||||||
|
#include "server/types.h"
|
||||||
#include "server/util.h"
|
#include "server/util.h"
|
||||||
|
|
||||||
|
|
||||||
@ -54,6 +55,60 @@ static int field_get(const char* key, const char* value, size_t valuelen, void*
|
|||||||
return MG_FORM_FIELD_HANDLE_GET;
|
return MG_FORM_FIELD_HANDLE_GET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void impl_self(mg_connection* conn, const char* user_id, repasswd_form_t* form)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
int flag = login(user_id, form->raw_passwd, &result);
|
||||||
|
if (!flag) {
|
||||||
|
res_repasswd_fail(conn);
|
||||||
|
} else {
|
||||||
|
if (result) {
|
||||||
|
flag = set_user_password(user_id, form->new_passwd);
|
||||||
|
if (!flag) {
|
||||||
|
res_repasswd_fail(conn);
|
||||||
|
} else {
|
||||||
|
res_repasswd(conn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res_incorrect(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void impl_others(mg_connection* conn, const char* user_id, repasswd_form_t* form)
|
||||||
|
{
|
||||||
|
int result1, result2;
|
||||||
|
int flag = check_user_exists(user_id, &result1);
|
||||||
|
flag &= check_user_exists(form->user_id, &result2);
|
||||||
|
if (!flag) {
|
||||||
|
res_check_exist_fail(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(result1 && result2)) {
|
||||||
|
res_not_exist(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int perm1, perm2;
|
||||||
|
flag = get_user_permission(user_id, &perm1);
|
||||||
|
flag &= get_user_permission(form->user_id, &perm2);
|
||||||
|
if (!flag) {
|
||||||
|
res_check_permission_fail(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (perm1 == 1 && perm2 == 2) {
|
||||||
|
int flag = set_user_password(form->user_id, form->new_passwd);
|
||||||
|
if (!flag) {
|
||||||
|
res_repasswd_fail(conn);
|
||||||
|
} else {
|
||||||
|
res_repasswd(conn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res_permission_denied(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int user_repasswd_handler(mg_connection* conn, void* cbdata)
|
int user_repasswd_handler(mg_connection* conn, void* cbdata)
|
||||||
{
|
{
|
||||||
const mg_request_info* post_body = mg_get_request_info(conn);
|
const mg_request_info* post_body = mg_get_request_info(conn);
|
||||||
@ -97,45 +152,9 @@ int user_repasswd_handler(mg_connection* conn, void* cbdata)
|
|||||||
char* user_id = get_payload(form.token);
|
char* user_id = get_payload(form.token);
|
||||||
|
|
||||||
if (form.user_id && strcmp(user_id, form.user_id)) {
|
if (form.user_id && strcmp(user_id, form.user_id)) {
|
||||||
int perm1;
|
impl_others(conn, user_id, &form);
|
||||||
int flag = get_user_permission(user_id, &perm1);
|
} else if (form.raw_passwd) {
|
||||||
if (!flag) {
|
impl_self(conn, user_id, &form);
|
||||||
res_check_permission_fail(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
int perm2;
|
|
||||||
flag = get_user_permission(form.user_id, &perm2);
|
|
||||||
if (!flag) {
|
|
||||||
res_check_permission_fail(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perm1 < perm2) {
|
|
||||||
int flag = set_user_password(form.user_id, form.new_passwd);
|
|
||||||
if (!flag) {
|
|
||||||
res_repasswd_fail(conn);
|
|
||||||
} else {
|
|
||||||
res_repasswd(conn);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res_permission_denied(conn);
|
|
||||||
}
|
|
||||||
} else if(form.raw_passwd) {
|
|
||||||
int result;
|
|
||||||
int flag = login(user_id, form.raw_passwd, &result);
|
|
||||||
if (!flag) {
|
|
||||||
res_repasswd_fail(conn);
|
|
||||||
} else {
|
|
||||||
if (result) {
|
|
||||||
flag = set_user_password(user_id, form.new_passwd);
|
|
||||||
if (!flag) {
|
|
||||||
res_repasswd_fail(conn);
|
|
||||||
} else {
|
|
||||||
res_repasswd(conn);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res_incorrect(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
res_need_password(conn);
|
res_need_password(conn);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
<v-chip class="chips" color="blue" @click="dialogRepasswd2Show = true">
|
<v-chip class="chips" color="blue" @click="dialogRepasswd2Show = true">
|
||||||
修改指定用户的密码
|
修改指定用户的密码
|
||||||
</v-chip>
|
</v-chip>
|
||||||
|
<v-chip class="chips" color="green" @click="dialogPermissionShow = true">
|
||||||
|
修改指定用户的身份
|
||||||
|
</v-chip>
|
||||||
<v-chip class="chips" color="red" @click="dialogDeleteAccountShow = true">
|
<v-chip class="chips" color="red" @click="dialogDeleteAccountShow = true">
|
||||||
删除指定用户的账号
|
删除指定用户的权限
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-card-item>
|
</v-card-item>
|
||||||
</v-card>
|
</v-card>
|
||||||
@ -32,6 +35,7 @@
|
|||||||
</v-dialog>
|
</v-dialog>
|
||||||
<RepasswdDialog v-model="dialogRepasswdShow"></RepasswdDialog>
|
<RepasswdDialog v-model="dialogRepasswdShow"></RepasswdDialog>
|
||||||
<Repasswd2Dialog v-model="dialogRepasswd2Show"></Repasswd2Dialog>
|
<Repasswd2Dialog v-model="dialogRepasswd2Show"></Repasswd2Dialog>
|
||||||
|
<Permission v-model="dialogPermissionShow"></Permission>
|
||||||
<DeleteAccountDialog v-model="dialogDeleteAccountShow"></DeleteAccountDialog>
|
<DeleteAccountDialog v-model="dialogDeleteAccountShow"></DeleteAccountDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -42,6 +46,7 @@ import axios, { AxiosError } from 'axios';
|
|||||||
import RepasswdDialog from './RepasswdDialog.vue';
|
import RepasswdDialog from './RepasswdDialog.vue';
|
||||||
import Repasswd2Dialog from './Repasswd2Dialog .vue';
|
import Repasswd2Dialog from './Repasswd2Dialog .vue';
|
||||||
import DeleteAccountDialog from './DeleteAccountDialog.vue';
|
import DeleteAccountDialog from './DeleteAccountDialog.vue';
|
||||||
|
import Permission from './Permission.vue';
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const storedAdminToken = ref(authStore.adminToken);
|
const storedAdminToken = ref(authStore.adminToken);
|
||||||
@ -53,6 +58,7 @@ const dialogClose = ref(() => { });
|
|||||||
|
|
||||||
const dialogRepasswdShow = ref(false);
|
const dialogRepasswdShow = ref(false);
|
||||||
const dialogRepasswd2Show = ref(false);
|
const dialogRepasswd2Show = ref(false);
|
||||||
|
const dialogPermissionShow = ref(false);
|
||||||
const dialogDeleteAccountShow = ref(false);
|
const dialogDeleteAccountShow = ref(false);
|
||||||
|
|
||||||
const dialog = (title: string, text: string) => {
|
const dialog = (title: string, text: string) => {
|
||||||
|
131
ui/src/components/admin/Permission.vue
Normal file
131
ui/src/components/admin/Permission.vue
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
<template>
|
||||||
|
<v-dialog v-model="dialogPermissionShow" max-width="448">
|
||||||
|
<v-card class="mx-auto pa-12 pb-8" elevation="8" width="100%" rounded="lg">
|
||||||
|
<v-form fast-fail @submit.prevent="submit">
|
||||||
|
|
||||||
|
<v-text-field v-model="userId" prepend-inner-icon="mdi-account-circle" :rules="userIdRules" label="账号"
|
||||||
|
@blur="updateUserPermission"></v-text-field>
|
||||||
|
|
||||||
|
<v-divider :thickness="10" class="border-opacity-0"></v-divider>
|
||||||
|
|
||||||
|
<v-select v-model="permission" label="权限" item-title="title" item-value="value" :items="permissions"></v-select>
|
||||||
|
|
||||||
|
<v-divider :thickness="10" class="border-opacity-0"></v-divider>
|
||||||
|
|
||||||
|
<v-btn :loading="loading" class="mb-8" color="blue" size="large" type="submit" variant="tonal" block>
|
||||||
|
修改权限
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
</v-form>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
<v-dialog v-model="dialogShow" width="auto">
|
||||||
|
<v-card max-width="400" prepend-icon="mdi-update" :text="dialogText" :title="dialogTitle">
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn class="ms-auto" text="Ok" @click="dialogShow = false, dialogClose()"></v-btn>
|
||||||
|
</template>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { useAuthStore } from '@/store/auth';
|
||||||
|
import axios, { AxiosError } from 'axios';
|
||||||
|
|
||||||
|
const dialogShow = ref(false);
|
||||||
|
const dialogTitle = ref('');
|
||||||
|
const dialogText = ref('');
|
||||||
|
const dialogClose = ref(() => { });
|
||||||
|
|
||||||
|
const dialog = (title: string, text: string) => {
|
||||||
|
dialogTitle.value = title;
|
||||||
|
dialogText.value = text;
|
||||||
|
dialogShow.value = true;
|
||||||
|
return new Promise(res => {
|
||||||
|
dialogClose.value = res as () => void;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const dialogPermissionShow = defineModel({ default: true });
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const userId = ref('');
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const storedAdminToken = ref(authStore.adminToken);
|
||||||
|
|
||||||
|
type UserPermissionResponse = { success?: string, permission?: string, error?: string };
|
||||||
|
|
||||||
|
const queryPermission = async () => {
|
||||||
|
try {
|
||||||
|
const formData = new FormData;
|
||||||
|
formData.append("user_id", userId.value);
|
||||||
|
let res = await axios.post('/api/auth/permission', formData);
|
||||||
|
return res.data as UserPermissionResponse;
|
||||||
|
} catch (e) {
|
||||||
|
let ex = e as AxiosError;
|
||||||
|
return ex.response?.data as UserPermissionResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissions = [
|
||||||
|
{ title: '老师', value: '1' },
|
||||||
|
{ title: '学生', value: '2' }
|
||||||
|
];
|
||||||
|
const permission = ref(permissions[0]);
|
||||||
|
|
||||||
|
const updateUserPermission = async () => {
|
||||||
|
if (userId.value == '') return;
|
||||||
|
let userPermission = '';
|
||||||
|
let res = await queryPermission();
|
||||||
|
if (res?.success) {
|
||||||
|
userPermission = res.permission as string;
|
||||||
|
}
|
||||||
|
permission.value = permissions[userPermission as any as number - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(userId, () => {
|
||||||
|
permission.value = undefined as any;
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
const userIdRules: any = [(value: string) => {
|
||||||
|
if (value?.length > 0) return true;
|
||||||
|
return '账号不能为空';
|
||||||
|
}];
|
||||||
|
|
||||||
|
type PermissionResponse = { success?: string, error?: string };
|
||||||
|
|
||||||
|
const requestPermission = async () => {
|
||||||
|
try {
|
||||||
|
const formData = new FormData;
|
||||||
|
formData.append("action", "permission");
|
||||||
|
formData.append("token", storedAdminToken.value);
|
||||||
|
formData.append("user_id", userId.value);
|
||||||
|
formData.append("permission", permission.value as any);
|
||||||
|
let res = await axios.post('/api/auth/admin', formData);
|
||||||
|
return res.data as PermissionResponse;
|
||||||
|
} catch (e) {
|
||||||
|
let ex = e as AxiosError;
|
||||||
|
if (ex.response?.data) {
|
||||||
|
return ex.response?.data as PermissionResponse;
|
||||||
|
} {
|
||||||
|
return { error: ex.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
let res = await requestPermission();
|
||||||
|
loading.value = false;
|
||||||
|
if (res?.error) {
|
||||||
|
await dialog('错误', `修改权限失败:${res.error}`);
|
||||||
|
} else {
|
||||||
|
await dialog('信息', `修改权限成功。`);
|
||||||
|
dialogPermissionShow.value = false;
|
||||||
|
userId.value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user