Added the ShareUpdate activity in the space context.

This commit is contained in:
Roman Perekhod
2024-09-18 16:47:09 +02:00
parent 10a67114f1
commit b65355c03c
17 changed files with 70 additions and 103 deletions

View File

@@ -0,0 +1,6 @@
go Bugfix: Added ShareUpdate activity
Added the ShareUpdate activity in the space context.
https://github.com/owncloud/ocis/pull/10104
https://github.com/owncloud/ocis/issues/10011

2
go.mod
View File

@@ -368,3 +368,5 @@ replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/pl
// exclude the v2 line of go-sqlite3 which was released accidentally and prevents pulling in newer versions of go-sqlite3
// see https://github.com/mattn/go-sqlite3/issues/965 for more details
exclude github.com/mattn/go-sqlite3 v2.0.3+incompatible
replace github.com/cs3org/reva/v2 => github.com/2403905/reva/v2 v2.24.1-0.20240918144132-2e1d422f27f7

4
go.sum
View File

@@ -39,6 +39,8 @@ contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/2403905/reva/v2 v2.24.1-0.20240918144132-2e1d422f27f7 h1:hGa5dN1E/WgehwO6XRwYlMZGvfw6LExMFlGCqBSyZ3U=
github.com/2403905/reva/v2 v2.24.1-0.20240918144132-2e1d422f27f7/go.mod h1:p7CHBXcg6sSqB+0JMNDfC1S7TSh9FghXkw1kTV3KcJI=
github.com/Acconut/go-httptest-recorder v1.0.0 h1:TAv2dfnqp/l+SUvIaMAUK4GeN4+wqb6KZsFFFTGhoJg=
github.com/Acconut/go-httptest-recorder v1.0.0/go.mod h1:CwQyhTH1kq/gLyWiRieo7c0uokpu3PXeyF/nZjUNtmM=
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
@@ -255,8 +257,6 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
github.com/cs3org/go-cs3apis v0.0.0-20240724121416-062c4e3046cb h1:KmYZDReplv/yfwc1LNYpDcVhVujC3Pasv6WjXx1haSU=
github.com/cs3org/go-cs3apis v0.0.0-20240724121416-062c4e3046cb/go.mod h1:yyP8PRo0EZou3nSH7H4qjlzQwaydPeIRNgX50npQHpE=
github.com/cs3org/reva/v2 v2.24.2-0.20240918135034-5a494dc2ebf7 h1:htjWHMNWh1YLOArxMtjV9zvj9Uu214iyYOHn8wi/10Q=
github.com/cs3org/reva/v2 v2.24.2-0.20240918135034-5a494dc2ebf7/go.mod h1:p7CHBXcg6sSqB+0JMNDfC1S7TSh9FghXkw1kTV3KcJI=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=

View File

@@ -35,6 +35,7 @@ var _registeredEvents = []events.Unmarshaller{
events.ItemPurged{},
events.ItemMoved{},
events.ShareCreated{},
events.ShareUpdated{},
events.ShareRemoved{},
events.LinkCreated{},
events.LinkUpdated{},

View File

@@ -152,6 +152,13 @@ func (s *ActivitylogService) HandleGetItemActivities(w http.ResponseWriter, r *h
message = MessageShareCreated
ts = utils.TSToTime(ev.CTime)
vars, err = s.GetVars(ctx, WithResource(toRef(ev.ItemID), false), WithUser(ev.Executant, ""), WithSharee(ev.GranteeUserID, ev.GranteeGroupID))
case events.ShareUpdated:
if ev.Sharer != nil && ev.ItemID != nil && ev.Sharer.GetOpaqueId() == ev.ItemID.GetSpaceId() {
continue
}
message = MessageShareUpdated
ts = utils.TSToTime(ev.MTime)
vars, err = s.GetVars(ctx, WithResource(toRef(ev.ItemID), false), WithUser(ev.Executant, ""), WithFieldMask(ev.UpdateMask))
case events.ShareRemoved:
message = MessageShareDeleted
ts = ev.Timestamp
@@ -165,7 +172,7 @@ func (s *ActivitylogService) HandleGetItemActivities(w http.ResponseWriter, r *h
continue
}
message = MessageLinkUpdated
ts = utils.TSToTime(ev.CTime)
ts = utils.TSToTime(ev.MTime)
vars, err = s.GetVars(ctx,
WithResource(toRef(ev.ItemID), false),
WithUser(ev.Executant, ""),

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/cs3org/reva/v2/pkg/events"
"path/filepath"
"strings"
"time"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
@@ -27,6 +28,7 @@ var (
MessageResourceMoved = l10n.Template("{user} moved {resource} to {folder}")
MessageResourceRenamed = l10n.Template("{user} renamed {oldResource} to {resource}")
MessageShareCreated = l10n.Template("{user} shared {resource} with {sharee}")
MessageShareUpdated = l10n.Template("{user} updated {field} for the {resource}")
MessageShareDeleted = l10n.Template("{user} removed {sharee} from {resource}")
MessageLinkCreated = l10n.Template("{user} shared {resource} via link")
MessageLinkUpdated = l10n.Template("{user} updated {field} for a link {token} on {resource}")
@@ -256,6 +258,19 @@ func WithLinkFieldUpdated(e *events.LinkUpdated) ActivityOption {
}
}
func WithFieldMask(mask []string) ActivityOption {
return func(_ context.Context, _ gateway.GatewayAPIClient, vars map[string]interface{}) error {
f := "some field"
if len(mask) > 0 {
f = strings.Join(mask, ", ")
}
vars["field"] = Resource{
Name: f,
}
return nil
}
}
// NewActivity creates a new activity
func NewActivity(message string, ts time.Time, eventID string, vars map[string]interface{}) libregraph.Activity {
return libregraph.Activity{

View File

@@ -110,13 +110,17 @@ func (a *ActivitylogService) Run() {
err = a.AddActivity(ev.Ref, e.ID, utils.TSToTime(ev.Timestamp))
case events.ShareCreated:
err = a.AddActivity(toRef(ev.ItemID), e.ID, utils.TSToTime(ev.CTime))
case events.ShareUpdated:
if ev.Sharer != nil && ev.ItemID != nil && ev.Sharer.GetOpaqueId() != ev.ItemID.GetSpaceId() {
err = a.AddActivity(toRef(ev.ItemID), e.ID, utils.TSToTime(ev.MTime))
}
case events.ShareRemoved:
err = a.AddActivity(toRef(ev.ItemID), e.ID, ev.Timestamp)
case events.LinkCreated:
err = a.AddActivity(toRef(ev.ItemID), e.ID, utils.TSToTime(ev.CTime))
case events.LinkUpdated:
if ev.Sharer != nil && ev.ItemID != nil && ev.Sharer.GetOpaqueId() != ev.ItemID.GetSpaceId() {
err = a.AddActivity(toRef(ev.ItemID), e.ID, utils.TSToTime(ev.CTime))
err = a.AddActivity(toRef(ev.ItemID), e.ID, utils.TSToTime(ev.MTime))
}
case events.LinkRemoved:
err = a.AddActivity(toRef(ev.ItemID), e.ID, utils.TSToTime(ev.Timestamp))

View File

@@ -123,7 +123,7 @@ var testCases = []struct {
Sharer: userID("sharing-userid"),
ItemID: resourceID("provider-1", "storage-1", "itemid-1"),
Permissions: linkPermissions("stat"),
CTime: timestamp(10e8),
MTime: timestamp(10e8),
DisplayName: "link",
Expiration: timestamp(10e8 + 10e5),
PasswordProtected: true,

View File

@@ -115,7 +115,7 @@ func ShareUpdated(ev events.ShareUpdated) AuditEventShareUpdated {
func LinkUpdated(ev events.LinkUpdated) AuditEventShareUpdated {
uid := ev.Sharer.OpaqueId
with, typ := "", _linktype
base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageLinkUpdated(uid, ev.ShareID.OpaqueId, ev.FieldUpdated), updateType(ev.FieldUpdated))
base := BasicAuditEvent(uid, formatTime(ev.MTime), MessageLinkUpdated(uid, ev.ShareID.OpaqueId, ev.FieldUpdated), updateType(ev.FieldUpdated))
return AuditEventShareUpdated{
AuditEventSharing: SharingAuditEvent(ev.ShareID.GetOpaqueId(), ev.ItemID.OpaqueId, uid, base),
ShareOwner: uid,

View File

@@ -78,12 +78,6 @@ func ShareRemoved(r *collaboration.RemoveShareResponse, req *collaboration.Remov
// ShareUpdated converts the response to an event
func ShareUpdated(r *collaboration.UpdateShareResponse, req *collaboration.UpdateShareRequest, executant *user.UserId) events.ShareUpdated {
updated := ""
if req.Field.GetPermissions() != nil {
updated = "permissions"
} else if req.Field.GetDisplayName() != "" {
updated = "displayname"
}
return events.ShareUpdated{
Executant: executant,
ShareID: r.Share.Id,
@@ -93,7 +87,7 @@ func ShareUpdated(r *collaboration.UpdateShareResponse, req *collaboration.Updat
GranteeGroupID: r.Share.GetGrantee().GetGroupId(),
Sharer: r.Share.Creator,
MTime: r.Share.Mtime,
Updated: updated,
UpdateMask: req.GetUpdateMask().GetPaths(),
}
}
@@ -139,7 +133,7 @@ func LinkUpdated(r *link.UpdatePublicShareResponse, req *link.UpdatePublicShareR
DisplayName: r.Share.DisplayName,
Expiration: r.Share.Expiration,
PasswordProtected: r.Share.PasswordProtected,
CTime: r.Share.Ctime,
MTime: r.Share.Mtime,
Token: r.Share.Token,
FieldUpdated: link.UpdatePublicShareRequest_Update_Type_name[int32(req.Update.GetType())],
}

View File

@@ -35,13 +35,13 @@ import (
)
type appsHandler struct {
gatewaySelector *pool.Selector[gateway.GatewayAPIClient]
ocmMountPoint string
gatewayClient gateway.GatewayAPIClient
ocmMountPoint string
}
func (h *appsHandler) init(c *config) error {
var err error
h.gatewaySelector, err = pool.GatewaySelector(c.GatewaySvc)
h.gatewayClient, err = pool.GetGatewayServiceClient(c.GatewaySvc)
if err != nil {
return err
}
@@ -99,11 +99,7 @@ func (h *appsHandler) OpenInApp(w http.ResponseWriter, r *http.Request) {
}
func (h *appsHandler) webappTemplate(ctx context.Context, id *ocmpb.ShareId) (string, error) {
gc, err := h.gatewaySelector.Next()
if err != nil {
return "", err
}
res, err := gc.GetReceivedOCMShare(ctx, &ocmpb.GetReceivedOCMShareRequest{
res, err := h.gatewayClient.GetReceivedOCMShare(ctx, &ocmpb.GetReceivedOCMShareRequest{
Ref: &ocmpb.ShareReference{
Spec: &ocmpb.ShareReference_Id{
Id: id,

View File

@@ -32,12 +32,12 @@ import (
)
type providersHandler struct {
gatewaySelector *pool.Selector[gateway.GatewayAPIClient]
gatewayClient gateway.GatewayAPIClient
}
func (h *providersHandler) init(c *config) error {
var err error
h.gatewaySelector, err = pool.GatewaySelector(c.GatewaySvc)
h.gatewayClient, err = pool.GetGatewayServiceClient(c.GatewaySvc)
if err != nil {
return err
}
@@ -55,12 +55,7 @@ func (h *providersHandler) ListProviders(w http.ResponseWriter, r *http.Request)
ctx := r.Context()
term := strings.ToLower(r.URL.Query().Get("search"))
gc, err := h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
listRes, err := gc.ListAllProviders(ctx, &providerpb.ListAllProvidersRequest{})
listRes, err := h.gatewayClient.ListAllProviders(ctx, &providerpb.ListAllProvidersRequest{})
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error listing all providers", err)
return

View File

@@ -40,7 +40,7 @@ import (
)
type tokenHandler struct {
gatewaySelector *pool.Selector[gateway.GatewayAPIClient]
gatewayClient gateway.GatewayAPIClient
meshDirectoryURL string
providerDomain string
eventStream events.Stream
@@ -48,7 +48,7 @@ type tokenHandler struct {
func (h *tokenHandler) init(c *config) error {
var err error
h.gatewaySelector, err = pool.GatewaySelector(c.GatewaySvc)
h.gatewayClient, err = pool.GetGatewayServiceClient(c.GatewaySvc)
if err != nil {
return err
}
@@ -85,12 +85,7 @@ func (h *tokenHandler) Generate(w http.ResponseWriter, r *http.Request) {
}
ctx := r.Context()
gc, err := h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
genTokenRes, err := gc.GenerateInviteToken(ctx, &invitepb.GenerateInviteTokenRequest{
genTokenRes, err := h.gatewayClient.GenerateInviteToken(ctx, &invitepb.GenerateInviteTokenRequest{
Description: req.Description,
})
switch {
@@ -190,12 +185,7 @@ func (h *tokenHandler) AcceptInvite(w http.ResponseWriter, r *http.Request) {
return
}
gc, err := h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
providerInfo, err := gc.GetInfoByDomain(ctx, &ocmprovider.GetInfoByDomainRequest{
providerInfo, err := h.gatewayClient.GetInfoByDomain(ctx, &ocmprovider.GetInfoByDomainRequest{
Domain: req.ProviderDomain,
})
if err != nil {
@@ -207,18 +197,13 @@ func (h *tokenHandler) AcceptInvite(w http.ResponseWriter, r *http.Request) {
return
}
gc, err = h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
forwardInviteReq := &invitepb.ForwardInviteRequest{
InviteToken: &invitepb.InviteToken{
Token: req.Token,
},
OriginSystemProvider: providerInfo.ProviderInfo,
}
forwardInviteResponse, err := gc.ForwardInvite(ctx, forwardInviteReq)
forwardInviteResponse, err := h.gatewayClient.ForwardInvite(ctx, forwardInviteReq)
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error sending a grpc forward invite request", err)
return
@@ -273,12 +258,7 @@ type remoteUser struct {
func (h *tokenHandler) FindAccepted(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
gc, err := h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
res, err := gc.FindAcceptedUsers(ctx, &invitepb.FindAcceptedUsersRequest{})
res, err := h.gatewayClient.FindAcceptedUsers(ctx, &invitepb.FindAcceptedUsersRequest{})
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error sending a grpc find accepted users request", err)
return
@@ -312,12 +292,7 @@ func (h *tokenHandler) DeleteAccepted(w http.ResponseWriter, r *http.Request) {
return
}
gc, err := h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
res, err := gc.DeleteAcceptedUser(ctx, &invitepb.DeleteAcceptedUserRequest{
res, err := h.gatewayClient.DeleteAcceptedUser(ctx, &invitepb.DeleteAcceptedUserRequest{
RemoteUserId: &userpb.UserId{
Idp: req.Idp,
OpaqueId: req.UserID,
@@ -356,12 +331,7 @@ func getDeleteAcceptedRequest(r *http.Request) (*deleteAcceptedRequest, error) {
func (h *tokenHandler) ListInvite(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
gc, err := h.gatewaySelector.Next()
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error selecting gateway client", err)
return
}
res, err := gc.ListInviteTokens(ctx, &invitepb.ListInviteTokensRequest{})
res, err := h.gatewayClient.ListInviteTokens(ctx, &invitepb.ListInviteTokensRequest{})
if err != nil {
reqres.WriteError(w, r, reqres.APIErrorServerError, "error listing tokens", err)
return

View File

@@ -84,8 +84,9 @@ type ShareUpdated struct {
Sharer *user.UserId
MTime *types.Timestamp
// indicates what was updated - one of "displayname", "permissions"
Updated string
Updated string // Deprecated
// indicates what was updated
UpdateMask []string
}
// Unmarshal to fulfill umarshaller interface
@@ -165,7 +166,7 @@ type LinkUpdated struct {
DisplayName string
Expiration *types.Timestamp
PasswordProtected bool
CTime *types.Timestamp
MTime *types.Timestamp
Token string
FieldUpdated string

View File

@@ -26,8 +26,6 @@ import (
"strconv"
"time"
"github.com/google/renameio/v2"
"github.com/rogpeppe/go-internal/lockedfile"
tusd "github.com/tus/tusd/v2/pkg/handler"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
@@ -76,13 +74,7 @@ func (s *OcisSession) executantUser() *userpb.User {
// Purge deletes the upload session metadata and written binary data
func (s *OcisSession) Purge(ctx context.Context) error {
sessionPath := sessionPath(s.store.root, s.info.ID)
f, err := lockedfile.OpenFile(sessionPath+".lock", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0600)
if err != nil {
return err
}
defer f.Close()
if err := os.Remove(sessionPath); err != nil {
if err := os.Remove(sessionPath(s.store.root, s.info.ID)); err != nil {
return err
}
if err := os.Remove(s.binPath()); err != nil {
@@ -101,12 +93,10 @@ func (s *OcisSession) TouchBin() error {
}
// Persist writes the upload session metadata to disk
// events can update the scan outcome and the finished event might read an empty file because of race conditions
// so we need to lock the file while writing and use atomic writes
func (s *OcisSession) Persist(ctx context.Context) error {
sessionPath := sessionPath(s.store.root, s.info.ID)
uploadPath := sessionPath(s.store.root, s.info.ID)
// create folder structure (if needed)
if err := os.MkdirAll(filepath.Dir(sessionPath), 0700); err != nil {
if err := os.MkdirAll(filepath.Dir(uploadPath), 0700); err != nil {
return err
}
@@ -115,12 +105,8 @@ func (s *OcisSession) Persist(ctx context.Context) error {
if err != nil {
return err
}
f, err := lockedfile.OpenFile(sessionPath+".lock", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0600)
if err != nil {
return err
}
defer f.Close()
return renameio.WriteFile(sessionPath, d, 0600)
return os.WriteFile(uploadPath, d, 0600)
}
// ToFileInfo returns tus compatible FileInfo so the tus handler can access the upload offset

View File

@@ -119,7 +119,7 @@ func (store OcisStore) List(ctx context.Context) ([]*OcisSession, error) {
// Get returns the upload session for the given upload id
func (store OcisStore) Get(ctx context.Context, id string) (*OcisSession, error) {
sessionPath := sessionPath(store.root, id)
sessionPath := filepath.Join(store.root, "uploads", id+".info")
match := _idRegexp.FindStringSubmatch(sessionPath)
if match == nil || len(match) < 2 {
return nil, fmt.Errorf("invalid upload path")
@@ -129,15 +129,6 @@ func (store OcisStore) Get(ctx context.Context, id string) (*OcisSession, error)
store: store,
info: tusd.FileInfo{},
}
lock, err := lockedfile.Open(sessionPath + ".lock")
if err != nil {
if errors.Is(err, iofs.ErrNotExist) {
// Interpret os.ErrNotExist as 404 Not Found
err = tusd.ErrNotFound
}
return nil, err
}
defer lock.Close()
data, err := os.ReadFile(sessionPath)
if err != nil {
if errors.Is(err, iofs.ErrNotExist) {
@@ -146,8 +137,6 @@ func (store OcisStore) Get(ctx context.Context, id string) (*OcisSession, error)
}
return nil, err
}
lock.Close() // release lock asap
if err := json.Unmarshal(data, &session.info); err != nil {
return nil, err
}

3
vendor/modules.txt vendored
View File

@@ -367,7 +367,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
# github.com/cs3org/reva/v2 v2.24.2-0.20240918135034-5a494dc2ebf7
# github.com/cs3org/reva/v2 v2.24.2-0.20240918135034-5a494dc2ebf7 => github.com/2403905/reva/v2 v2.24.1-0.20240918144132-2e1d422f27f7
## explicit; go 1.21
github.com/cs3org/reva/v2/cmd/revad/internal/grace
github.com/cs3org/reva/v2/cmd/revad/runtime
@@ -2445,3 +2445,4 @@ stash.kopano.io/kgol/rndm
# github.com/egirna/icap-client => github.com/fschade/icap-client v0.0.0-20240802074440-aade4a234387
# github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
# github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/kobergj/plugins/v4/store/nats-js-kv v0.0.0-20240807130109-f62bb67e8c90
# github.com/cs3org/reva/v2 => github.com/2403905/reva/v2 v2.24.1-0.20240918144132-2e1d422f27f7