feat:增加封禁账号功能 & 退出时情况所有缓存
This commit is contained in:
@@ -13,11 +13,11 @@ android {
|
||||
applicationId = "com.memory.app"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 42
|
||||
versionName = "1.5.8"
|
||||
versionCode = 43
|
||||
versionName = "1.5.9"
|
||||
|
||||
buildConfigField("String", "API_BASE_URL", "\"https://x.amos.us.kg/api/\"")
|
||||
buildConfigField("int", "VERSION_CODE", "42")
|
||||
buildConfigField("int", "VERSION_CODE", "43")
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
|
||||
@@ -74,6 +74,11 @@ fun MainNavigation(
|
||||
val uploadProgress by homeViewModel.uploadProgress.collectAsState()
|
||||
|
||||
LaunchedEffect(user) {
|
||||
// 用户变化时清空旧数据并重新加载
|
||||
homeViewModel.clearData()
|
||||
profileViewModel.clearData()
|
||||
notificationViewModel.clearData()
|
||||
homeViewModel.loadPosts()
|
||||
profileViewModel.setUser(user)
|
||||
profileViewModel.loadProfile()
|
||||
notificationViewModel.loadUnreadCount()
|
||||
|
||||
@@ -228,6 +228,13 @@ class HomeViewModel : ViewModel() {
|
||||
loadPosts()
|
||||
}
|
||||
|
||||
fun clearData() {
|
||||
_posts.value = emptyList()
|
||||
_currentUser.value = null
|
||||
currentPage = 1
|
||||
hasMore = true
|
||||
}
|
||||
|
||||
fun createPost(context: Context, content: String, images: List<Uri>, visibility: Int = 0, musicUrl: String? = null) {
|
||||
if (_isPosting.value) return
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -76,4 +76,9 @@ class NotificationViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearData() {
|
||||
_notifications.value = emptyList()
|
||||
_unreadCount.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,4 +95,11 @@ class ProfileViewModel : ViewModel() {
|
||||
fun setUser(user: User?) {
|
||||
_user.value = user
|
||||
}
|
||||
|
||||
fun clearData() {
|
||||
_user.value = null
|
||||
_postCount.value = 0
|
||||
_likeCount.value = 0
|
||||
_dayCount.value = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,5 +181,8 @@ func migrate(db *sql.DB) error {
|
||||
)
|
||||
`)
|
||||
|
||||
// 迁移:添加 is_disabled 字段(账号禁用)
|
||||
db.Exec("ALTER TABLE users ADD COLUMN is_disabled INTEGER DEFAULT 0")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func (h *PostHandler) List(c *gin.Context) {
|
||||
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, COALESCE(p.visibility, 0),
|
||||
u.id, u.username, u.nickname, u.avatar_url, COALESCE(u.is_superadmin, 0),
|
||||
@@ -115,7 +115,7 @@ func (h *PostHandler) List(c *gin.Context) {
|
||||
(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(p.visibility, 0) = 0 OR p.user_id = ?
|
||||
WHERE (COALESCE(p.visibility, 0) = 0) OR (COALESCE(p.visibility, 0) = 1 AND p.user_id = ?)
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, userID, pageSize, offset)
|
||||
|
||||
@@ -2,6 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"memory/internal/config"
|
||||
@@ -155,3 +156,79 @@ func (h *UserHandler) UpdateSettings(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "settings updated"})
|
||||
}
|
||||
|
||||
// 获取所有用户列表(管理员)
|
||||
func (h *UserHandler) ListUsers(c *gin.Context) {
|
||||
rows, err := h.db.Query(`
|
||||
SELECT id, username, nickname, avatar_url, bio, is_admin, COALESCE(is_superadmin, 0), COALESCE(is_disabled, 0), created_at
|
||||
FROM users ORDER BY created_at DESC
|
||||
`)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "database error"})
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var users []model.User
|
||||
for rows.Next() {
|
||||
var user model.User
|
||||
err := rows.Scan(&user.ID, &user.Username, &user.Nickname, &user.AvatarURL, &user.Bio, &user.IsAdmin, &user.IsSuperAdmin, &user.IsDisabled, &user.CreatedAt)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
users = append(users, user)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"users": users})
|
||||
}
|
||||
|
||||
// 禁用用户账号
|
||||
func (h *UserHandler) DisableUser(c *gin.Context) {
|
||||
targetUserID := c.Param("id")
|
||||
currentUserID := middleware.GetUserID(c)
|
||||
|
||||
// 不能禁用自己
|
||||
if targetUserID == fmt.Sprintf("%d", currentUserID) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "不能禁用自己的账号"})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查目标用户是否是超管
|
||||
var isSuperAdmin bool
|
||||
err := h.db.QueryRow("SELECT COALESCE(is_superadmin, 0) FROM users WHERE id = ?", targetUserID).Scan(&isSuperAdmin)
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
|
||||
return
|
||||
}
|
||||
if isSuperAdmin {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "不能禁用超级管理员"})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = h.db.Exec("UPDATE users SET is_disabled = 1 WHERE id = ?", targetUserID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "禁用失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "账号已禁用"})
|
||||
}
|
||||
|
||||
// 启用用户账号
|
||||
func (h *UserHandler) EnableUser(c *gin.Context) {
|
||||
targetUserID := c.Param("id")
|
||||
|
||||
result, err := h.db.Exec("UPDATE users SET is_disabled = 0 WHERE id = ?", targetUserID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "启用失败"})
|
||||
return
|
||||
}
|
||||
|
||||
rowsAffected, _ := result.RowsAffected()
|
||||
if rowsAffected == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "账号已启用"})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -15,7 +16,7 @@ type Claims struct {
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func AuthMiddleware(jwtSecret string) gin.HandlerFunc {
|
||||
func AuthMiddleware(jwtSecret string, db *sql.DB) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
@@ -48,6 +49,20 @@ func AuthMiddleware(jwtSecret string) gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查账号是否被禁用
|
||||
var isDisabled bool
|
||||
err = db.QueryRow("SELECT COALESCE(is_disabled, 0) FROM users WHERE id = ?", claims.UserID).Scan(&isDisabled)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if isDisabled {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "account_disabled", "message": "您的账号已被禁用"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Set("user_id", claims.UserID)
|
||||
c.Set("is_admin", claims.IsAdmin)
|
||||
c.Set("is_superadmin", claims.IsSuperAdmin)
|
||||
|
||||
@@ -11,6 +11,7 @@ type User struct {
|
||||
Bio string `json:"bio"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
IsSuperAdmin bool `json:"is_superadmin"`
|
||||
IsDisabled bool `json:"is_disabled"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func Setup(db *sql.DB, cfg *config.Config) *gin.Engine {
|
||||
|
||||
// 需要认证的接口
|
||||
auth := r.Group("/api")
|
||||
auth.Use(middleware.AuthMiddleware(cfg.JWTSecret))
|
||||
auth.Use(middleware.AuthMiddleware(cfg.JWTSecret, db))
|
||||
{
|
||||
// 帖子
|
||||
auth.GET("/posts", postHandler.List)
|
||||
@@ -102,6 +102,9 @@ func Setup(db *sql.DB, cfg *config.Config) *gin.Engine {
|
||||
admin.GET("/settings", userHandler.GetSettings)
|
||||
admin.PUT("/settings", userHandler.UpdateSettings)
|
||||
admin.POST("/version", versionHandler.SetVersion)
|
||||
admin.GET("/users", userHandler.ListUsers)
|
||||
admin.PUT("/users/:id/disable", userHandler.DisableUser)
|
||||
admin.PUT("/users/:id/enable", userHandler.EnableUser)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user