feat(social): блокировка пользователей
- PUT/DELETE /users/@me/blocks/{id}: блокировка снимает дружбу и заявки в обе
стороны, разблокировка возвращает возможность писать (AGENT.md 7.2)
- блокировка запрещает личные сообщения (ошибка dm.blocked), открытие беседы и
заявки в друзья с любой стороны
- клиент: раздел «Заблокированные» в друзьях со снятием блокировки, действие
«Заблокировать» в меню строки друга и в меню модерации участника
- тесты: Go (блокировка, заявки, беседа, сообщение) и Vitest (список, снятие,
блокировка из меню)
This commit is contained in:
@@ -168,6 +168,12 @@ func (s *Server) registerSocialRoutes(api huma.API) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Блокировка сильнее заявки: переписка и дружба с ней невозможны.
|
||||
if blocked, err := s.store.IsBlocked(ctx, user.ID, target.ID); err != nil {
|
||||
return nil, humaError(err)
|
||||
} else if blocked {
|
||||
return nil, humaErrorStatus(http.StatusForbidden, "relationship.blocked", "user is blocked")
|
||||
}
|
||||
// Если встречная заявка уже есть — сразу становимся друзьями.
|
||||
reverse, err := s.store.GetRelationship(ctx, target.ID, user.ID)
|
||||
switch {
|
||||
@@ -252,6 +258,65 @@ func (s *Server) registerSocialRoutes(api huma.API) {
|
||||
return newOKOutput(), nil
|
||||
})
|
||||
|
||||
huma.Register(api, huma.Operation{
|
||||
OperationID: "blockUser",
|
||||
Method: http.MethodPut,
|
||||
Path: "/users/@me/blocks/{user_id}",
|
||||
Summary: "Заблокировать пользователя",
|
||||
Tags: []string{"Friends"},
|
||||
Security: security,
|
||||
}, func(ctx context.Context, input *struct {
|
||||
UserID string `path:"user_id"`
|
||||
},
|
||||
) (*okOutput, error) {
|
||||
user, _, err := requireUser(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
targetID, err := parseID("user_id", input.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if targetID == user.ID {
|
||||
return nil, humaErrorStatus(http.StatusUnprocessableEntity, "validation.failed", "you cannot block yourself")
|
||||
}
|
||||
if _, err := s.store.GetUser(ctx, targetID); err != nil {
|
||||
return nil, humaError(err)
|
||||
}
|
||||
// Блокировка снимает дружбу и заявки в обе стороны (AGENT.md 7.2).
|
||||
if err := s.store.BlockUser(ctx, user.ID, targetID); err != nil {
|
||||
return nil, humaError(err)
|
||||
}
|
||||
s.dispatchRelationshipUpdate(user.ID, targetID)
|
||||
return newOKOutput(), nil
|
||||
})
|
||||
|
||||
huma.Register(api, huma.Operation{
|
||||
OperationID: "unblockUser",
|
||||
Method: http.MethodDelete,
|
||||
Path: "/users/@me/blocks/{user_id}",
|
||||
Summary: "Снять блокировку",
|
||||
Tags: []string{"Friends"},
|
||||
Security: security,
|
||||
}, func(ctx context.Context, input *struct {
|
||||
UserID string `path:"user_id"`
|
||||
},
|
||||
) (*okOutput, error) {
|
||||
user, _, err := requireUser(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
targetID, err := parseID("user_id", input.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.store.UnblockUser(ctx, user.ID, targetID); err != nil {
|
||||
return nil, humaError(err)
|
||||
}
|
||||
s.dispatchRelationshipUpdate(user.ID, targetID)
|
||||
return newOKOutput(), nil
|
||||
})
|
||||
|
||||
huma.Register(api, huma.Operation{
|
||||
OperationID: "openDirectChannel",
|
||||
Method: http.MethodPost,
|
||||
@@ -280,6 +345,12 @@ func (s *Server) registerSocialRoutes(api huma.API) {
|
||||
if err != nil {
|
||||
return nil, humaError(err)
|
||||
}
|
||||
// С заблокированным беседа не открывается (AGENT.md 7.2).
|
||||
if blocked, err := s.store.IsBlocked(ctx, user.ID, recipientID); err != nil {
|
||||
return nil, humaError(err)
|
||||
} else if blocked {
|
||||
return nil, humaErrorStatus(http.StatusForbidden, "dm.blocked", "personal messages are blocked")
|
||||
}
|
||||
channel, err := s.store.FindDMChannel(ctx, user.ID, recipientID)
|
||||
if errors.Is(err, store.ErrNotFound) {
|
||||
channel, err = s.store.CreateDMChannel(ctx, user.ID, recipientID)
|
||||
|
||||
Reference in New Issue
Block a user