Files
QSfera/Server/services/graph/pkg/service/v0/follow.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

174 lines
4.7 KiB
Go

package svc
import (
"net/http"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/go-chi/render"
"github.com/qsfera/server/services/graph/pkg/errorcode"
revaCtx "github.com/opencloud-eu/reva/v2/pkg/ctx"
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
"github.com/opencloud-eu/reva/v2/pkg/events"
)
const _favoriteLabel = "favorite"
// FollowDriveItem marks a drive item as favorite.
func (g Graph) FollowDriveItem(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
itemID, err := parseIDParam(r, "itemID")
if err != nil {
g.logger.Debug().Err(err).Msg("could not parse itemID")
return
}
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusServiceUnavailable, "could not select next gateway client")
return
}
ref := &provider.Reference{
ResourceId: &itemID,
}
u, ok := revactx.ContextGetUser(ctx)
if !ok {
errorcode.GeneralException.Render(w, r, http.StatusUnauthorized, "User not found in context")
return
}
statReq := &provider.StatRequest{
Ref: ref,
}
statRes, err := gatewayClient.Stat(ctx, statReq)
if err != nil {
g.logger.Error().Err(err).Msg("could not stat resource")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not stat resource")
return
}
switch statRes.GetStatus().GetCode() {
case rpc.Code_CODE_OK:
// continue
case rpc.Code_CODE_NOT_FOUND:
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "resource not found")
return
default:
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not stat resource")
return
}
req := &provider.AddLabelRequest{
Ref: ref,
UserId: u.Id,
Label: _favoriteLabel,
}
res, err := gatewayClient.AddLabel(ctx, req)
if err != nil {
g.logger.Error().Err(err).Msg("could not add label")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not add label")
return
}
if res.Status.Code != rpc.Code_CODE_OK {
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not add label")
return
}
if g.eventsPublisher != nil {
ev := events.LabelAdded{
Ref: &provider.Reference{
ResourceId: &itemID,
Path: ".",
},
Label: _favoriteLabel,
UserID: u.Id,
Executant: revaCtx.ContextMustGetUser(r.Context()).Id,
}
if err := events.Publish(r.Context(), g.eventsPublisher, ev); err != nil {
g.logger.Error().Err(err).Msg("Failed to publish LabelAdded event")
}
}
driveItem, err := cs3ResourceToDriveItem(g.logger, g.publicBaseURL, statRes.GetInfo())
if err != nil {
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error())
return
}
render.Status(r, http.StatusCreated)
render.JSON(w, r, &driveItem)
}
// UnfollowDriveItem unmarks a drive item as favorite.
func (g Graph) UnfollowDriveItem(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
itemID, err := parseIDParam(r, "itemID")
if err != nil {
g.logger.Debug().Err(err).Msg("could not parse itemID")
return
}
gatewayClient, err := g.gatewaySelector.Next()
if err != nil {
g.logger.Error().Err(err).Msg("could not select next gateway client")
errorcode.ServiceNotAvailable.Render(w, r, http.StatusServiceUnavailable, "could not select next gateway client")
return
}
ref := &provider.Reference{
ResourceId: &itemID,
}
u, ok := revactx.ContextGetUser(ctx)
if !ok {
errorcode.GeneralException.Render(w, r, http.StatusUnauthorized, "User not found in context")
return
}
req := &provider.RemoveLabelRequest{
Ref: ref,
UserId: u.Id,
Label: _favoriteLabel,
}
res, err := gatewayClient.RemoveLabel(ctx, req)
if err != nil {
g.logger.Error().Err(err).Msg("could not remove label")
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not remove label")
return
}
switch res.Status.Code {
case rpc.Code_CODE_OK:
// continue
case rpc.Code_CODE_NOT_FOUND:
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "favorite not found")
return
default:
errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "could not remove favorite")
return
}
if g.eventsPublisher != nil {
ev := events.LabelRemoved{
Ref: &provider.Reference{
ResourceId: &itemID,
Path: ".",
},
Label: _favoriteLabel,
UserID: u.Id,
Executant: revaCtx.ContextMustGetUser(r.Context()).Id,
}
if err := events.Publish(r.Context(), g.eventsPublisher, ev); err != nil {
g.logger.Error().Err(err).Msg("Failed to publish LabelRemoved event")
}
}
w.WriteHeader(http.StatusNoContent)
}