mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 04:17:23 +00:00
Add collelction permission.
This commit is contained in:
@@ -15,11 +15,16 @@ func handleCreateCollection(c fiber.Ctx) error {
|
||||
}
|
||||
title := c.FormValue("title")
|
||||
article := c.FormValue("article")
|
||||
publicStr := c.FormValue("public")
|
||||
public := false
|
||||
if publicStr == "true" || publicStr == "1" {
|
||||
public = true
|
||||
}
|
||||
if title == "" || article == "" {
|
||||
return model.NewRequestError("Title and article are required")
|
||||
}
|
||||
host := c.Hostname()
|
||||
col, err := service.CreateCollection(uid, title, article, host)
|
||||
col, err := service.CreateCollection(uid, title, article, host, public)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -38,6 +43,11 @@ func handleUpdateCollection(c fiber.Ctx) error {
|
||||
idStr := c.FormValue("id")
|
||||
title := c.FormValue("title")
|
||||
article := c.FormValue("article")
|
||||
publicStr := c.FormValue("public")
|
||||
public := false
|
||||
if publicStr == "true" || publicStr == "1" {
|
||||
public = true
|
||||
}
|
||||
if idStr == "" || title == "" || article == "" {
|
||||
return model.NewRequestError("ID, title and article are required")
|
||||
}
|
||||
@@ -46,7 +56,7 @@ func handleUpdateCollection(c fiber.Ctx) error {
|
||||
return model.NewRequestError("Invalid collection ID")
|
||||
}
|
||||
host := c.Hostname()
|
||||
if err := service.UpdateCollection(uid, uint(id), title, article, host); err != nil {
|
||||
if err := service.UpdateCollection(uid, uint(id), title, article, host, public); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(model.Response[any]{
|
||||
@@ -83,7 +93,11 @@ func handleGetCollection(c fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return model.NewRequestError("Invalid collection ID")
|
||||
}
|
||||
col, err := service.GetCollectionByID(uint(id))
|
||||
|
||||
// Get viewer UID (0 if not authenticated)
|
||||
viewerUID, _ := c.Locals("uid").(uint)
|
||||
|
||||
col, err := service.GetCollectionByID(uint(id), viewerUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,7 +118,11 @@ func handleListUserCollections(c fiber.Ctx) error {
|
||||
if username == "" {
|
||||
return model.NewRequestError("Username is required")
|
||||
}
|
||||
cols, total, err := service.ListUserCollections(username, page)
|
||||
|
||||
// Get viewer UID (0 if not authenticated)
|
||||
viewerUID, _ := c.Locals("uid").(uint)
|
||||
|
||||
cols, total, err := service.ListUserCollections(username, page, viewerUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -127,7 +145,11 @@ func handleListCollectionResources(c fiber.Ctx) error {
|
||||
if err != nil || page < 1 {
|
||||
page = 1
|
||||
}
|
||||
res, total, err := service.ListCollectionResources(uint(id), page)
|
||||
|
||||
// Get viewer UID (0 if not authenticated)
|
||||
viewerUID, _ := c.Locals("uid").(uint)
|
||||
|
||||
res, total, err := service.ListCollectionResources(uint(id), page, viewerUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -209,7 +231,11 @@ func handleSearchUserCollections(c fiber.Ctx) error {
|
||||
excludedRID = uint(rid)
|
||||
}
|
||||
}
|
||||
cols, err := service.SearchUserCollections(username, keyword, excludedRID)
|
||||
|
||||
// Get viewer UID (0 if not authenticated)
|
||||
viewerUID, _ := c.Locals("uid").(uint)
|
||||
|
||||
cols, err := service.SearchUserCollections(username, keyword, excludedRID, viewerUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -6,13 +6,14 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateCollection(uid uint, title string, article string, images []uint) (model.Collection, error) {
|
||||
func CreateCollection(uid uint, title string, article string, images []uint, public bool) (model.Collection, error) {
|
||||
var collection model.Collection
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
collection = model.Collection{
|
||||
UserID: uid,
|
||||
Title: title,
|
||||
Article: article,
|
||||
Public: public, // 新增
|
||||
}
|
||||
|
||||
if err := tx.Create(&collection).Error; err != nil {
|
||||
@@ -32,7 +33,7 @@ func CreateCollection(uid uint, title string, article string, images []uint) (mo
|
||||
return collection, nil
|
||||
}
|
||||
|
||||
func UpdateCollection(id uint, title string, article string, images []uint) error {
|
||||
func UpdateCollection(id uint, title string, article string, images []uint, public bool) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
collection := &model.Collection{
|
||||
Model: gorm.Model{
|
||||
@@ -40,6 +41,7 @@ func UpdateCollection(id uint, title string, article string, images []uint) erro
|
||||
},
|
||||
Title: title,
|
||||
Article: article,
|
||||
Public: public, // 新增
|
||||
}
|
||||
|
||||
if err := tx.Model(collection).Updates(collection).Error; err != nil {
|
||||
@@ -142,19 +144,22 @@ func GetCollectionByID(id uint) (*model.Collection, error) {
|
||||
return collection, nil
|
||||
}
|
||||
|
||||
func ListUserCollections(uid uint, page int, pageSize int) ([]*model.Collection, int64, error) {
|
||||
func ListUserCollections(uid uint, page int, pageSize int, showPrivate bool) ([]*model.Collection, int64, error) {
|
||||
var collections []*model.Collection
|
||||
var total int64
|
||||
|
||||
if err := db.Model(&model.Collection{}).Where("user_id = ?", uid).Count(&total).Error; err != nil {
|
||||
query := db.Model(&model.Collection{}).Where("user_id = ?", uid)
|
||||
if !showPrivate {
|
||||
query = query.Where("public = ?", true)
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := db.
|
||||
Model(&model.Collection{}).
|
||||
if err := query.
|
||||
Preload("Images").
|
||||
Preload("Resources").
|
||||
Where("user_id = ?", uid).
|
||||
Offset((page - 1) * pageSize).
|
||||
Limit(pageSize).
|
||||
Find(&collections).Error; err != nil {
|
||||
@@ -196,12 +201,16 @@ func ListCollectionResources(collectionID uint, page int, pageSize int) ([]*mode
|
||||
|
||||
// SearchUserCollections searches for collections by user ID and keyword limited to 10 results.
|
||||
// excludedRID: if >0, only return collections not containing this resource.
|
||||
func SearchUserCollections(uid uint, keyword string, excludedRID uint) ([]*model.Collection, error) {
|
||||
func SearchUserCollections(uid uint, keyword string, excludedRID uint, showPrivate bool) ([]*model.Collection, error) {
|
||||
var collections []*model.Collection
|
||||
|
||||
query := db.Model(&model.Collection{}).
|
||||
Where("user_id = ?", uid)
|
||||
|
||||
if !showPrivate {
|
||||
query = query.Where("public = ?", true)
|
||||
}
|
||||
|
||||
if keyword != "" {
|
||||
query = query.Where("title LIKE ?", "%"+keyword+"%")
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ type Collection struct {
|
||||
ResourcesCount int `gorm:"default:0"`
|
||||
Images []Image `gorm:"many2many:collection_images;"`
|
||||
Resources []Resource `gorm:"many2many:collection_resources;"`
|
||||
Public bool `gorm:"default:false"` // 新增公开/私有字段
|
||||
}
|
||||
|
||||
type CollectionView struct {
|
||||
@@ -20,6 +21,7 @@ type CollectionView struct {
|
||||
User UserView `json:"user"`
|
||||
ResourcesCount int `json:"resources_count"`
|
||||
Images []Image `json:"images"`
|
||||
IsPublic bool `json:"isPublic"` // 新增公开/私有字段
|
||||
}
|
||||
|
||||
func (c Collection) ToView() *CollectionView {
|
||||
@@ -30,5 +32,6 @@ func (c Collection) ToView() *CollectionView {
|
||||
User: c.User.ToView(),
|
||||
ResourcesCount: c.ResourcesCount,
|
||||
Images: c.Images,
|
||||
IsPublic: c.Public, // 新增
|
||||
}
|
||||
}
|
||||
|
@@ -6,11 +6,11 @@ import (
|
||||
)
|
||||
|
||||
// Create a new collection.
|
||||
func CreateCollection(uid uint, title, article string, host string) (*model.CollectionView, error) {
|
||||
func CreateCollection(uid uint, title, article string, host string, public bool) (*model.CollectionView, error) {
|
||||
if uid == 0 || title == "" || article == "" {
|
||||
return nil, model.NewRequestError("invalid parameters")
|
||||
}
|
||||
c, err := dao.CreateCollection(uid, title, article, findImagesInContent(article, host))
|
||||
c, err := dao.CreateCollection(uid, title, article, findImagesInContent(article, host), public)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func CreateCollection(uid uint, title, article string, host string) (*model.Coll
|
||||
}
|
||||
|
||||
// Update an existing collection with user validation.
|
||||
func UpdateCollection(uid, id uint, title, article string, host string) error {
|
||||
func UpdateCollection(uid, id uint, title, article string, host string, public bool) error {
|
||||
if uid == 0 || id == 0 || title == "" || article == "" {
|
||||
return model.NewRequestError("invalid parameters")
|
||||
}
|
||||
@@ -30,7 +30,7 @@ func UpdateCollection(uid, id uint, title, article string, host string) error {
|
||||
if collection.UserID != uid {
|
||||
return model.NewUnAuthorizedError("user does not have permission to update this collection")
|
||||
}
|
||||
return dao.UpdateCollection(id, title, article, findImagesInContent(article, host))
|
||||
return dao.UpdateCollection(id, title, article, findImagesInContent(article, host), public)
|
||||
}
|
||||
|
||||
// Delete a collection by ID.
|
||||
@@ -83,7 +83,7 @@ func RemoveResourceFromCollection(uid, collectionID, resourceID uint) error {
|
||||
}
|
||||
|
||||
// Get a collection by ID.
|
||||
func GetCollectionByID(id uint) (*model.CollectionView, error) {
|
||||
func GetCollectionByID(id uint, viewerUID uint) (*model.CollectionView, error) {
|
||||
if id == 0 {
|
||||
return nil, model.NewRequestError("invalid collection id")
|
||||
}
|
||||
@@ -91,11 +91,17 @@ func GetCollectionByID(id uint) (*model.CollectionView, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if collection is private and viewer is not the owner
|
||||
if !c.Public && c.UserID != viewerUID {
|
||||
return nil, model.NewUnAuthorizedError("you do not have permission to view this private collection")
|
||||
}
|
||||
|
||||
return c.ToView(), nil
|
||||
}
|
||||
|
||||
// List collections of a user with pagination.
|
||||
func ListUserCollections(username string, page int) ([]*model.CollectionView, int64, error) {
|
||||
func ListUserCollections(username string, page int, viewerUID uint) ([]*model.CollectionView, int64, error) {
|
||||
if username == "" || page < 1 {
|
||||
return nil, 0, model.NewRequestError("invalid parameters")
|
||||
}
|
||||
@@ -104,7 +110,11 @@ func ListUserCollections(username string, page int) ([]*model.CollectionView, in
|
||||
return nil, 0, err
|
||||
}
|
||||
uid := user.ID
|
||||
collections, total, err := dao.ListUserCollections(uid, page, pageSize)
|
||||
|
||||
// Check if viewer can see private collections (only owner can see their private collections)
|
||||
showPrivate := uid == viewerUID
|
||||
|
||||
collections, total, err := dao.ListUserCollections(uid, page, pageSize, showPrivate)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -116,10 +126,21 @@ func ListUserCollections(username string, page int) ([]*model.CollectionView, in
|
||||
}
|
||||
|
||||
// List resources in a collection with pagination.
|
||||
func ListCollectionResources(collectionID uint, page int) ([]*model.ResourceView, int64, error) {
|
||||
func ListCollectionResources(collectionID uint, page int, viewerUID uint) ([]*model.ResourceView, int64, error) {
|
||||
if collectionID == 0 || page < 1 {
|
||||
return nil, 0, model.NewRequestError("invalid parameters")
|
||||
}
|
||||
|
||||
// Check collection privacy first
|
||||
collection, err := dao.GetCollectionByID(collectionID)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if !collection.Public && collection.UserID != viewerUID {
|
||||
return nil, 0, model.NewUnAuthorizedError("you do not have permission to view this private collection")
|
||||
}
|
||||
|
||||
resources, total, err := dao.ListCollectionResources(collectionID, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -134,7 +155,7 @@ func ListCollectionResources(collectionID uint, page int) ([]*model.ResourceView
|
||||
|
||||
// Search user collections by keyword, limited to 10 results.
|
||||
// excludedRID: if >0, only return collections not containing this resource.
|
||||
func SearchUserCollections(username string, keyword string, excludedRID uint) ([]*model.CollectionView, error) {
|
||||
func SearchUserCollections(username string, keyword string, excludedRID uint, viewerUID uint) ([]*model.CollectionView, error) {
|
||||
if username == "" {
|
||||
return nil, model.NewRequestError("invalid parameters")
|
||||
}
|
||||
@@ -143,7 +164,11 @@ func SearchUserCollections(username string, keyword string, excludedRID uint) ([
|
||||
return nil, err
|
||||
}
|
||||
uid := user.ID
|
||||
collections, err := dao.SearchUserCollections(uid, keyword, excludedRID)
|
||||
|
||||
// Check if viewer can see private collections
|
||||
showPrivate := uid == viewerUID
|
||||
|
||||
collections, err := dao.SearchUserCollections(uid, keyword, excludedRID, showPrivate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user