feat: add user management system with roles and permissions
Some checks failed
/ build ushare (push) Failing after 1m40s
/ clean (push) Successful in 2s

- Introduce SQLite persistence via GORM (stored at <data>/.ushare.db)
- Add Role model with two built-in roles: admin (all perms) and user (upload only)
- Add three permissions: user_manage, upload, token_manage (reserved)
- Rewrite UserManager: DB-backed login with in-memory session tokens
- Auto-seed default roles and admin user on first startup
- Add AuthPermission middleware for fine-grained permission checks
- Add /api/uauth/me endpoint for current session info
- Add /api/admin/* CRUD routes for user and role management
- Add admin console page (/admin) with user table and role permissions view
- Show admin console link in share page for users with user_manage permission

🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
loveuer
2026-02-27 19:40:31 -08:00
parent 909a016a44
commit 5f187bb5d6
13 changed files with 1119 additions and 93 deletions

View File

@@ -1,6 +1,6 @@
import {createUseStyles} from "react-jss";
import {UButton} from "../../../component/button/u-button.tsx";
import React, {useState} from "react";
import React, {useEffect, useState} from "react";
import {useStore} from "../../../store/share.ts";
import {message} from "../../../hook/message/u-message.tsx";
import {useFileUpload} from "../../../api/upload.ts";
@@ -59,7 +59,17 @@ const useUploadStyle = createUseStyles({
borderRadius: '50%',
cursor: 'pointer',
'&:hover': {}
}
},
adminLink: {
display: 'block',
textAlign: 'center',
marginTop: '16px',
color: '#2c9678',
fontSize: '12px',
textDecoration: 'none',
opacity: 0.8,
'&:hover': {opacity: 1, textDecoration: 'underline'},
},
})
const useShowStyle = createUseStyles({
@@ -179,6 +189,17 @@ const PanelLeftUpload: React.FC<{ set_code: (code:string) => void }> = ({set_cod
const style = useUploadStyle()
const {file, setFile} = useStore()
const {uploadFile, progress, loading} = useFileUpload();
const [isAdmin, setIsAdmin] = useState(false);
useEffect(() => {
fetch('/api/uauth/me').then(async res => {
if (res.ok) {
const json = await res.json();
const perms: string[] = json.data?.permissions ?? [];
setIsAdmin(perms.includes('user_manage'));
}
}).catch(() => {});
}, []);
function onFileSelect() {
// @ts-ignore
@@ -225,6 +246,9 @@ const PanelLeftUpload: React.FC<{ set_code: (code:string) => void }> = ({set_cod
<div className={style.name}>{file.name}</div>
</div>
}
{isAdmin && (
<a href="/admin" className={style.adminLink}></a>
)}
</div>
</div>
}