feat:增加超管机制,超管可以查看所有人的帖子
This commit is contained in:
@@ -38,6 +38,7 @@ func migrate(db *sql.DB) error {
|
||||
avatar_url TEXT DEFAULT '',
|
||||
bio TEXT DEFAULT '',
|
||||
is_admin INTEGER DEFAULT 0,
|
||||
is_superadmin INTEGER DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
@@ -120,5 +121,11 @@ func migrate(db *sql.DB) error {
|
||||
// SQLite 不支持 IF NOT EXISTS 用于 ALTER TABLE,所以忽略错误
|
||||
db.Exec("ALTER TABLE posts ADD COLUMN updated_at DATETIME DEFAULT NULL")
|
||||
|
||||
// 迁移:添加 is_superadmin 字段
|
||||
db.Exec("ALTER TABLE users ADD COLUMN is_superadmin INTEGER DEFAULT 0")
|
||||
|
||||
// 设置 amos 为超管
|
||||
db.Exec("UPDATE users SET is_superadmin = 1 WHERE username = 'amos'")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ func (h *AuthHandler) Register(c *gin.Context) {
|
||||
|
||||
userID, _ := result.LastInsertId()
|
||||
|
||||
// 生成 token
|
||||
token, err := h.generateToken(userID, isAdmin)
|
||||
// 生成 token(新注册用户不是超管)
|
||||
token, err := h.generateToken(userID, isAdmin, false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
|
||||
return
|
||||
@@ -102,9 +102,9 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
|
||||
var user model.User
|
||||
err := h.db.QueryRow(
|
||||
"SELECT id, username, password_hash, nickname, avatar_url, bio, is_admin, created_at FROM users WHERE username = ?",
|
||||
"SELECT id, username, password_hash, nickname, avatar_url, bio, is_admin, COALESCE(is_superadmin, 0), created_at FROM users WHERE username = ?",
|
||||
req.Username,
|
||||
).Scan(&user.ID, &user.Username, &user.PasswordHash, &user.Nickname, &user.AvatarURL, &user.Bio, &user.IsAdmin, &user.CreatedAt)
|
||||
).Scan(&user.ID, &user.Username, &user.PasswordHash, &user.Nickname, &user.AvatarURL, &user.Bio, &user.IsAdmin, &user.IsSuperAdmin, &user.CreatedAt)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"})
|
||||
@@ -120,7 +120,7 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
token, err := h.generateToken(user.ID, user.IsAdmin)
|
||||
token, err := h.generateToken(user.ID, user.IsAdmin, user.IsSuperAdmin)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
|
||||
return
|
||||
@@ -132,10 +132,11 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) generateToken(userID int64, isAdmin bool) (string, error) {
|
||||
func (h *AuthHandler) generateToken(userID int64, isAdmin bool, isSuperAdmin bool) (string, error) {
|
||||
claims := &middleware.Claims{
|
||||
UserID: userID,
|
||||
IsAdmin: isAdmin,
|
||||
UserID: userID,
|
||||
IsAdmin: isAdmin,
|
||||
IsSuperAdmin: isSuperAdmin,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
|
||||
@@ -67,21 +67,44 @@ func (h *PostHandler) Create(c *gin.Context) {
|
||||
|
||||
func (h *PostHandler) List(c *gin.Context) {
|
||||
userID := middleware.GetUserID(c)
|
||||
isSuperAdmin, _ := c.Get("is_superadmin")
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
rows, err := h.db.Query(`
|
||||
SELECT p.id, p.user_id, p.content, p.created_at, p.updated_at,
|
||||
u.id, u.username, u.nickname, u.avatar_url,
|
||||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id) as like_count,
|
||||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id AND user_id = ?) as liked,
|
||||
(SELECT COUNT(*) FROM comments WHERE post_id = p.id) as comment_count
|
||||
FROM posts p
|
||||
JOIN users u ON p.user_id = u.id
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, pageSize, offset)
|
||||
// 超管可以看到所有帖子,普通用户看不到超管的帖子
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
|
||||
if isSuperAdmin != nil && isSuperAdmin.(bool) {
|
||||
// 超管:看到所有帖子
|
||||
rows, err = h.db.Query(`
|
||||
SELECT p.id, p.user_id, p.content, p.created_at, p.updated_at,
|
||||
u.id, u.username, u.nickname, u.avatar_url,
|
||||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id) as like_count,
|
||||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id AND user_id = ?) as liked,
|
||||
(SELECT COUNT(*) FROM comments WHERE post_id = p.id) as comment_count
|
||||
FROM posts p
|
||||
JOIN users u ON p.user_id = u.id
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, pageSize, offset)
|
||||
} else {
|
||||
// 普通用户:只能看到非超管的帖子
|
||||
rows, err = h.db.Query(`
|
||||
SELECT p.id, p.user_id, p.content, p.created_at, p.updated_at,
|
||||
u.id, u.username, u.nickname, u.avatar_url,
|
||||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id) as like_count,
|
||||
(SELECT COUNT(*) FROM likes WHERE post_id = p.id AND user_id = ?) as liked,
|
||||
(SELECT COUNT(*) FROM comments WHERE post_id = p.id) as comment_count
|
||||
FROM posts p
|
||||
JOIN users u ON p.user_id = u.id
|
||||
WHERE COALESCE(u.is_superadmin, 0) = 0
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, pageSize, offset)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "database error"})
|
||||
return
|
||||
|
||||
@@ -22,6 +22,7 @@ func NewSearchHandler(db *sql.DB, cfg *config.Config) *SearchHandler {
|
||||
|
||||
func (h *SearchHandler) Search(c *gin.Context) {
|
||||
userID := middleware.GetUserID(c)
|
||||
isSuperAdmin, _ := c.Get("is_superadmin")
|
||||
|
||||
var req model.SearchRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
@@ -50,6 +51,11 @@ func (h *SearchHandler) Search(c *gin.Context) {
|
||||
`
|
||||
args := []interface{}{userID}
|
||||
|
||||
// 普通用户看不到超管的帖子
|
||||
if isSuperAdmin == nil || !isSuperAdmin.(bool) {
|
||||
query += " AND COALESCE(u.is_superadmin, 0) = 0"
|
||||
}
|
||||
|
||||
if req.Query != "" {
|
||||
query += " AND p.content LIKE ?"
|
||||
args = append(args, "%"+req.Query+"%")
|
||||
|
||||
@@ -9,8 +9,9 @@ import (
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
UserID int64 `json:"user_id"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
IsSuperAdmin bool `json:"is_superadmin"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
@@ -49,6 +50,7 @@ func AuthMiddleware(jwtSecret string) gin.HandlerFunc {
|
||||
|
||||
c.Set("user_id", claims.UserID)
|
||||
c.Set("is_admin", claims.IsAdmin)
|
||||
c.Set("is_superadmin", claims.IsSuperAdmin)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ type User struct {
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
Bio string `json:"bio"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
IsSuperAdmin bool `json:"is_superadmin"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user