|
@@ -10,6 +10,7 @@ import (
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
|
"gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models"
|
|
"gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models"
|
|
|
|
|
+ "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/pointer"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
func encodeCursor(p *models.Place) string {
|
|
func encodeCursor(p *models.Place) string {
|
|
@@ -43,9 +44,14 @@ type ObjectStorager interface {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
var (
|
|
|
- ErrNotYourPlace = errors.New("not your place")
|
|
|
|
|
|
|
+ ErrNotYourPlace = errors.New("not your place")
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+type ModerationLogRepo interface {
|
|
|
|
|
+ Create(ctx context.Context, entry *models.ModerationLog) error
|
|
|
|
|
+ ListByTarget(ctx context.Context, targetType, targetID string) ([]*models.ModerationLog, error)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
type PlaceRepo interface {
|
|
type PlaceRepo interface {
|
|
|
Create(ctx context.Context, place *models.Place) error
|
|
Create(ctx context.Context, place *models.Place) error
|
|
|
GetByID(ctx context.Context, id string) (*models.Place, error)
|
|
GetByID(ctx context.Context, id string) (*models.Place, error)
|
|
@@ -65,12 +71,13 @@ type PlaceRepo interface {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type PlaceService struct {
|
|
type PlaceService struct {
|
|
|
- placeRepo PlaceRepo
|
|
|
|
|
- storage ObjectStorager
|
|
|
|
|
|
|
+ placeRepo PlaceRepo
|
|
|
|
|
+ storage ObjectStorager
|
|
|
|
|
+ moderationLogRepo ModerationLogRepo
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func NewPlaceService(placeRepo PlaceRepo, storage ObjectStorager) *PlaceService {
|
|
|
|
|
- return &PlaceService{placeRepo: placeRepo, storage: storage}
|
|
|
|
|
|
|
+func NewPlaceService(placeRepo PlaceRepo, storage ObjectStorager, moderationLogRepo ModerationLogRepo) *PlaceService {
|
|
|
|
|
+ return &PlaceService{placeRepo: placeRepo, storage: storage, moderationLogRepo: moderationLogRepo}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type CreatePlaceInput struct {
|
|
type CreatePlaceInput struct {
|
|
@@ -264,6 +271,14 @@ func (s *PlaceService) Update(ctx context.Context, input UpdatePlaceInput, isMod
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (s *PlaceService) Moderate(ctx context.Context, id, action, comment, moderatorID string) error {
|
|
func (s *PlaceService) Moderate(ctx context.Context, id, action, comment, moderatorID string) error {
|
|
|
|
|
+ place, err := s.placeRepo.GetByIDRaw(ctx, id)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ if place == nil {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var status string
|
|
var status string
|
|
|
switch action {
|
|
switch action {
|
|
|
case "approve":
|
|
case "approve":
|
|
@@ -278,14 +293,49 @@ func (s *PlaceService) Moderate(ctx context.Context, id, action, comment, modera
|
|
|
return fmt.Errorf("unknown action: %s", action)
|
|
return fmt.Errorf("unknown action: %s", action)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ entry := &models.ModerationLog{
|
|
|
|
|
+ ModeratorID: moderatorID,
|
|
|
|
|
+ TargetType: "place",
|
|
|
|
|
+ TargetID: id,
|
|
|
|
|
+ Action: action,
|
|
|
|
|
+ OldStatus: &place.Status,
|
|
|
|
|
+ NewStatus: &status,
|
|
|
|
|
+ }
|
|
|
|
|
+ if comment != "" {
|
|
|
|
|
+ entry.Comment = &comment
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := s.moderationLogRepo.Create(ctx, entry); err != nil {
|
|
|
|
|
+ return fmt.Errorf("log moderation: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return s.placeRepo.UpdateStatus(ctx, id, status, comment)
|
|
return s.placeRepo.UpdateStatus(ctx, id, status, comment)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (s *PlaceService) Delete(ctx context.Context, id string) error {
|
|
|
|
|
|
|
+func (s *PlaceService) Delete(ctx context.Context, id, userID string) error {
|
|
|
|
|
+ place, err := s.placeRepo.GetByIDRaw(ctx, id)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ if place == nil {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ entry := &models.ModerationLog{
|
|
|
|
|
+ ModeratorID: userID,
|
|
|
|
|
+ TargetType: "place",
|
|
|
|
|
+ TargetID: id,
|
|
|
|
|
+ Action: "soft_delete",
|
|
|
|
|
+ OldStatus: &place.Status,
|
|
|
|
|
+ NewStatus: pointer.Str("deleted"),
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := s.moderationLogRepo.Create(ctx, entry); err != nil {
|
|
|
|
|
+ return fmt.Errorf("log soft delete: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return s.placeRepo.SoftDelete(ctx, id)
|
|
return s.placeRepo.SoftDelete(ctx, id)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (s *PlaceService) HardDelete(ctx context.Context, id string) error {
|
|
|
|
|
|
|
+func (s *PlaceService) HardDelete(ctx context.Context, id, moderatorID string) error {
|
|
|
place, err := s.placeRepo.GetByIDRaw(ctx, id)
|
|
place, err := s.placeRepo.GetByIDRaw(ctx, id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|
|
@@ -313,5 +363,16 @@ func (s *PlaceService) HardDelete(ctx context.Context, id string) error {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ entry := &models.ModerationLog{
|
|
|
|
|
+ ModeratorID: moderatorID,
|
|
|
|
|
+ TargetType: "place",
|
|
|
|
|
+ TargetID: id,
|
|
|
|
|
+ Action: "hard_delete",
|
|
|
|
|
+ OldStatus: &place.Status,
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := s.moderationLogRepo.Create(ctx, entry); err != nil {
|
|
|
|
|
+ return fmt.Errorf("log hard delete: %w", err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return s.placeRepo.HardDelete(ctx, id)
|
|
return s.placeRepo.HardDelete(ctx, id)
|
|
|
}
|
|
}
|