Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion dao/article.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ func GetArticleList(target string, page int, pageSize int, pin bool) ([]model.Ar
func DeleteArticle(id string) error {
db := database.GetArticleDatabase()

result := db.Where("id = ?", id).Delete(&model.Article{})
result := db.Unscoped().
Where("id = ?", id).
Delete(&model.Article{})
if result.Error != nil {
return result.Error
}
Expand Down
4 changes: 3 additions & 1 deletion dao/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ func DeleteDocumentNode(id string) error {
}

if err := db.Transaction(func(tx *gorm.DB) error {
result := tx.Where("id IN ?", ids).Delete(&model.DocumentNode{})
result := tx.Unscoped().
Where("id IN ?", ids).
Delete(&model.DocumentNode{})
if result.Error != nil {
return result.Error
}
Expand Down
1 change: 1 addition & 0 deletions dao/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func UpdateServer(server model.Server) error {

func DeleteServer(id string) error {
result := database.GetServerDatabase().
Unscoped().
Where("id = ?", id).
Delete(&model.Server{})

Expand Down
62 changes: 60 additions & 2 deletions dao/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package dao
import (
"encoding/json"
"errors"
"fmt"
"log"
"necore/config"
"necore/database"
"necore/model"
"slices"
"strings"
"time"

"github.com/golang-jwt/jwt/v5"
Expand Down Expand Up @@ -78,20 +80,63 @@ func GetUserByUsername(u string) (*model.User, error) {
}

func AddUserByUsername(username string, password string) error {
username = strings.TrimSpace(username)

if username == "" {
return fmt.Errorf("username cannot be empty")
}

if password == "" {
return fmt.Errorf("password cannot be empty")
}

hash, err := hashPassword(password)
if err != nil {
return err
}

db := database.GetUserDatabase()

var existingUser model.User

err = db.Unscoped().
Where("username = ?", username).
First(&existingUser).Error

if err == nil {
if !existingUser.DeletedAt.Valid {
return fmt.Errorf("user already exists")
}

// 这里不要新建用户,而是复活旧用户。
// 关键点:token_version 必须递增,避免旧 JWT 在同名用户重建后重新有效。
return db.Unscoped().
Model(&existingUser).
Updates(map[string]any{
"password": hash,
"group": `[]`,
"tags": `[]`,
"avatar": "",
"token_version": gorm.Expr("token_version + ?", 1),
"deleted_at": nil,
"updated_at": time.Now(),
}).Error
}

if !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}

user := model.User{
Username: username,
Password: hash,
Group: `[]`,
Tags: `[]`,
Avatar: "",
TokenVersion: 1,
}

return database.GetUserDatabase().Create(&user).Error
return db.Create(&user).Error
}

func GetAllUsers() ([]model.User, error) {
Expand All @@ -103,7 +148,20 @@ func GetAllUsers() ([]model.User, error) {

func DeleteUserByUsername(username string) error {
db := database.GetUserDatabase()
return db.Where(&model.User{Username: username}).Delete(&model.User{}).Error

result := db.
Where("username = ?", username).
Delete(&model.User{})

if result.Error != nil {
return result.Error
}

if result.RowsAffected == 0 {
return fmt.Errorf("user '%s' not found", username)
}

return nil
}

func CheckUserPassword(input string, password string) bool {
Expand Down
43 changes: 37 additions & 6 deletions service/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package service

import (
"encoding/json"
"errors"
"fmt"
"necore/dao"
"necore/model"
"strings"

"github.com/gofiber/fiber/v2"
)
Expand Down Expand Up @@ -80,24 +83,52 @@ func Login(c *fiber.Ctx) error {

// Register by admin
func AddUser(c *fiber.Ctx) error {
// Check if user is admin
currentUser := c.Locals("currentUser").(model.User)

if !dao.ContainsGroup(currentUser.Group, "admin") {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Forbidden"})
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
"error": "Forbidden",
})
}

// Parse body
type NewUser struct {
Username string `json:"username"`
Password string `json:"password"`
}

user := new(NewUser)

if err := c.BodyParser(user); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Review your input", "err": err})
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Review your input",
"err": err.Error(),
})
}

if err := dao.AddUserByUsername(user.Username, user.Password); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
username := strings.TrimSpace(user.Username)

if username == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Username cannot be empty",
})
}

if user.Password == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Password cannot be empty",
})
}

if err := dao.AddUserByUsername(username, user.Password); err != nil {
if errors.Is(err, fmt.Errorf("user already exists")) {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{
"error": "Username already exists",
})
}

return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": err.Error(),
})
}

return c.JSON(fiber.Map{})
Expand Down
7 changes: 4 additions & 3 deletions service/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"encoding/json"
"necore/dao"
"necore/model"
"net/url"
"slices"

"github.com/gofiber/fiber/v2"
)

func GetUserInfo(c *fiber.Ctx) error {
userId := c.Params("id")
userId, _ := url.PathUnescape(c.Params("id"))

userModel, err := dao.GetUserByUsername(userId)
if err != nil || userModel == nil {
Expand Down Expand Up @@ -91,7 +92,7 @@ func DeleteUser(c *fiber.Ctx) error {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Forbidden"})
}

username := c.Params("id")
username, _ := url.PathUnescape(c.Params("id"))
err := dao.UpdateUserPermissions(username)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": "Internal server error"})
Expand Down Expand Up @@ -189,7 +190,7 @@ func UpdateUserInfo(c *fiber.Ctx) error {
}

func GetUserAvatar(c *fiber.Ctx) error {
userId := c.Params("id")
userId, _ := url.PathUnescape(c.Params("id"))

avatar, err := dao.GetUserAvatar(userId)
if err != nil {
Expand Down
Loading