Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed the FileInfo.BreadcrumbFolderURL in a collaboration api #10720

Merged
merged 3 commits into from
Dec 9, 2024

Conversation

2403905
Copy link
Contributor

@2403905 2403905 commented Dec 3, 2024

Description

Fixed the FileInfo.BreadcrumbFolderURL in a collaboration api"

Related Issue

Motivation and Context

How Has This Been Tested?

  • test environment:
  • test case 1:
  • test case 2:
  • ...

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist:

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation ticket raised:

@2403905 2403905 force-pushed the issue-e7004 branch 2 times, most recently from 8e3aead to c25ae0b Compare December 4, 2024 08:42
Copy link
Member

@jvillafanez jvillafanez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure the coverage.out file shouldn't be there... make sure it's deleted from the repo because it's quite big for something we don't want to keep.

parentFolderURL := &url.URL{}
*parentFolderURL = *ocisURL
parentFolderURL.Path = path.Join(ocisURL.Path, "f", storagespace.FormatResourceID(statRes.GetInfo().GetParentId()))
if publicShare := wopiContext.GetPublicShare(); publicShare != nil && isPublicShare {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the isPublicShare boolean obsolete now? I mean, you already have the publicShare variable.
Maybe we can use the publicShare variable, which has more info, instead of the isPublicShare

@@ -36,6 +38,7 @@ type WopiContext struct {
FileReference *providerv1beta1.Reference
TemplateReference *providerv1beta1.Reference
ViewMode appproviderv1beta1.ViewMode
publicShare *link.PublicShare
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this information will be sent around (encrypted) through the network in the URL. Please, double-check the size of the access token to ensure it doesn't increase by a lot.
We should try to minimize the amount of information we need to move around.

As an alternative, you could parse / decrypt / dismantle the WopiContext.AccessToken on demand. This might be better for consistency because there is only one source of truth (the access token), so it's impossible to have inconsistencies if the access token says one thing and the public share information says a different thing. It's true that there will be a performance penalty because we need to decrypt the access token twice, but hopefully it's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why publicShare will be added if it is a private field?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it would be added, but it seems it the json marshaller ignores the private fields, so it should be fine

Comment on lines 133 to 160
for k, v := range scope {
if strings.HasPrefix(k, "publicshare:") && v.Resource.Decoder == "json" {
share := &link.PublicShare{}
err := utils.UnmarshalJSONToProtoV1(v.Resource.Value, share)
if err == nil {
claims.WopiContext.publicShare = share
break
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might need some changes...
Do we need some debug log to know what public shares are we interested in, or how many scopes are detected? In any case, if there is some error unmarshaling the JSON, not only it will be skipped (which might be fine), but we don't know what happen (which is bad). The error needs to be logged at the very least.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the error logging

Copy link
Contributor Author

@2403905 2403905 Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need some debug log to know what public shares are we interested in, or how many scopes are detected?

I don't think so. we use the same approach in a publicstorage provider as well https://github.com/cs3org/reva/blob/bddf9f01f7decc0c839a3da26bacbac5a8a05156/internal/grpc/services/publicstorageprovider/publicstorageprovider.go#L525

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels weird that the last sentence is an unconditional error log. It seems the goal is to log the error and not filling the publicShare property.
What about

if strings.HasPrefix(k, "publicshare:") && ..... {
  err := utils.UnmarshalJSONToProtoV1(......)
  if err != nil {
    wopiLogger.Error().Err(err)......
  } else {
    claims.WopiContext.publicShare = share
  }
  break
}

Note that the usual pattern is if err != nil { return / break....}, so changing the pattern makes the code slower to read for a person.

@@ -230,6 +245,13 @@ func GenerateWopiToken(wopiContext WopiContext, cfg *config.Config, st microstor
return accessToken, claims.ExpiresAt.UnixMilli(), err
}

func (w *WopiContext) GetPublicShare() *link.PublicShare {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is questionable as it is at the moment. Why the publicShare property isn't public like the rest? That would make this method obsolete. At the moment, this method doesn't add anything of value other than getting the value, so making the property public to keep the consistency with the rest of the data seems fine to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the property needs to be private in order not to include it in the jwt token, and we need a public method to access to the private property.

A couple of additional things:

  • If the method is attached to the WopiContext, it's better to have the code as close as possible to the WopiContext definition, so the code should be move upwards. Reading the code should be easier this way.
  • This method just returns the private property, but it might not be set or evaluated yet (a bit weird scenario, but it could happen if we prepare a WopiContext outside of the http middleware). In this regard, it might be better to either include a public EvaluatePublicShare method that should be called before getting the public share (most of the code is already in the middleware, so it's moving things around), or extract the public share information on demand with the GetPublicShare method and let the private property act as a cache.
    I'd go with the EvaluatePublicShare in case the access token changes (which shouldn't happen under normal conditions) because it gives us extra flexibility. As long as it's documented that the EvaluatePublicShare must be called before the GetPublicShare, it should be fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that EvaluatePublicShare method will be good because it has some dependencies.
We could change the private field publicShare to scope and change the GetPublicShare to generic GetScope(keyPrefix string, m proto.Message) method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scope is only filled in the middleware, and I don't think it's a good idea. If you check the tests, we create a custom WopiContext, but even if we supply correct data to the public WopiContext properties, the scope won't return anything valuable. This is why a suggested to include the EvaluatePublicShare method: to fill and adjust the private properties.
Changing the WopiContext, in particular the access token inside, could also have negative consequences because the scope information isn't valid any longer and we can't update the information in any way. This means that the only valid context is the one supplied by the middleware, and changing or adjusting data in the WopiContext is discouraged.

Copy link
Contributor Author

@2403905 2403905 Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can try to do it another way, use the context like for the user.

ctx = ctxpkg.ContextSetScopes(ctx, scope)

user, _, err := tokenManager.DismantleToken(ctx, wopiContextAccessToken)
if err != nil {
wopiLogger.Error().Err(err).Msg("failed to dismantle reva token manager")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
claims.WopiContext.AccessToken = wopiContextAccessToken
ctx = context.WithValue(ctx, wopiContextKey, claims.WopiContext)
// authentication for the CS3 api
ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, claims.WopiContext.AccessToken)
ctx = ctxpkg.ContextSetUser(ctx, user)

In this case we can use existing functions ContextSetScopes, ContextGetScopes and add some scope extractor function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@2403905 2403905 force-pushed the issue-e7004 branch 3 times, most recently from c07323d to eee7a4e Compare December 5, 2024 06:46
@2403905 2403905 requested a review from jvillafanez December 5, 2024 07:08
Copy link
Member

@jvillafanez jvillafanez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remember to remove the coverage.out file!

scope map[string]*auth.Scope
}

// GetScope returns the scope from the WopiContext
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need some additional information to say that you need to provide a "message" and the result will be written there.

In general, parameters are treated as read-only, so nobody expects a parameter to change inside the function. The cases where this happens are limited. If the idea is that you just need to pass a placeholder where the result will be written, I think it's better to document it to avoid confusion.

@2403905 2403905 force-pushed the issue-e7004 branch 3 times, most recently from 39e42ce to 9d62fbc Compare December 6, 2024 11:16
@2403905 2403905 requested review from jvillafanez and micbar December 6, 2024 11:49
Copy link

sonarqubecloud bot commented Dec 9, 2024

@2403905 2403905 merged commit 6455f54 into owncloud:master Dec 9, 2024
4 checks passed
ownclouders pushed a commit that referenced this pull request Dec 9, 2024
fixed the FileInfo.BreadcrumbFolderURL in a collaboration api
@jvillafanez
Copy link
Member

We could move the GetScopeByKeyPrefix function as a private method of the fileConnector because it's only used there and I don't think there are plans to use the method elsewhere. Anyway, I don't think the change is worth a PR for now.
The rest of the code looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants