Skip to content

feat: implement brute force protection for public links#460

Merged
jvillafanez merged 5 commits intomainfrom
brute_force_protection_links
Jan 23, 2026
Merged

feat: implement brute force protection for public links#460
jvillafanez merged 5 commits intomainfrom
brute_force_protection_links

Conversation

@jvillafanez
Copy link
Member

@jvillafanez jvillafanez commented Dec 5, 2025

Note: https://github.com/cs3org/go-cs3apis/blob/main/cs3/rpc/v1beta1/code.pb.go#L121-L125 has a recommended RPC matching for the "Too Many Requests" error, so we're following along.

Implement brute force protection for public shares. The implementation follows a rate-limit approach. This means that you can access the share while the access failure rate is below certain threshold. If such threshold is surpassed, the public share won't be accessible until the failure rate goes below the threshold.

By default, the failure rate is 5 failures per hour (configurable). This means that you're allowed to fail the password for the share up to 5 times per hour before the share is blocked.
The duration of the blockage will be undefined, but between 0 and the configuration duration:

  • If the configuration is 10 failures each 2 hours, and the failures come in a quick burst (10 failures in a couple of seconds), the share will be blocked for 2 hours.
  • With the same configuration, but with spaced failures, one every 10 minutes, the share will be blocked for around 30 minutes (20 minute gap for the last failure + 10 minutes until the first failure is out of the time scope)
  • The share might be blocked just for a few seconds if the last allowed failure comes right before the 2 hours pass for the first failure.

Note that this is an in-memory implementation, so the data won't be shared with other service replicas. This means that the protection will be effective per-server replica, which might not behave as expected: if there are 3 replicas, requests might block one replica but not others, and you might be allowed additional failures because requests will hit different replicas.

Current implementation will use a reva store to make the related data accessible to all the service's replicas.
The recommended environment for the replicas is below (adjust the values if needed):

      LANG: C.UTF-8
      LC_ALL: C.UTF-8
      MICRO_REGISTRY: "nats-js-kv"
      MICRO_REGISTRY_ADDRESS: "ocis:9233"
      OCIS_RUNTIME_HOST: "ocis"
      OCIS_CONFIG_DIR: /etc/ocis/
      OCIS_URL: https://${OCIS_DOMAIN:-ocis.owncloud.test}
      OCIS_INSECURE: true

      STORAGE_PUBLICLINK_GRPC_ADDR: 0.0.0.0:9178
      OCIS_PERSISTENT_STORE: "nats-js-kv"
      OCIS_PERSISTENT_STORE_NODES: "ocis:9233"

TODO:

  • It needs a way to disable the feature. Right now, we need to keep timestamps in memory to keep track of the failed attempts. The greater the maximum number of attempts is, the more memory we might need to use; this also applies to the duration we need to store the timestamps.
    Setting the configuration values with zeros will effectively disable the feature
  • When writing data into the store, the "check" implementation (areEqualLists) is too strict and could lead to excessive retries and / or failures.
  • Need to replace the RWLock for a regular mutex because the RWLock isn't needed any longer.
  • Consider to include some logs to know what's going on.
  • Consider to include an ID as part of the attempt data. At the moment, if 2 replicas try to write an attempt at the same exact second, it isn't possible to know which replica has written the attempt and both replicas will assume that the written attempt is theirs, so only one attempt will be registered instead of the expected 2 (one per replica).
  • Consider to increase the time resolution, currently at seconds. This might not be needed if we use IDs.

@jvillafanez jvillafanez self-assigned this Dec 5, 2025
@jvillafanez jvillafanez changed the title [WIP] feat: implement brute force protection for public links feat: implement brute force protection for public links Dec 16, 2025
@jvillafanez jvillafanez marked this pull request as ready for review December 16, 2025 17:32
Copy link
Collaborator

@kobergj kobergj left a comment

Choose a reason for hiding this comment

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

Some questions/remarks.

}

func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user.User, map[string]*authpb.Scope, error) {
if !m.bfp.Verify(token) && !m.bfp.CleanInfo(token) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need two methods calls here? Isn't CleanInfo already checking max attempts?

Copy link
Member Author

@jvillafanez jvillafanez Dec 17, 2025

Choose a reason for hiding this comment

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

The Verify method is intended to provide a fast response (only read lock needed) while the CleanInfo might take more time (write lock plus more operations).

The expected scenario is that most of the requests will be successful, so only the Verify method is called, allowing better concurrency with just the read lock.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Makes sense. But couldn't that all be done by the Verify method? It could check with readlock and return if successful, otherwise writelock.

I don't see a scenario where we would only call one of the methods, or am I missing something?

Copy link
Member Author

Choose a reason for hiding this comment

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

It might be possible, but the code would be more complex. There are a couple of things to notice:

  • Current code uses the standard pattern of "lock + defer unlock" to ensure the lock is always released. If we put everything in the same method, this won't be possible because we must release the read lock before obtaining the write lock, and unlocking manually has its drawbacks.
  • Since we're dealing with locks, these are usually handled within public methods. Dealing with them in private methods might limit the reusability of those methods. It might cause problems with the previous point too because you might be forced to manually release the lock almost always.

I don't see a scenario where we would only call one of the methods, or am I missing something?

You can use just the CleanInfo method (now I see it's a bad name, maybe AccurateVerify fits better) if you don't really care about performance.
You can also use just the Verify method assuming you also have some background thread cleaning the information so the result is "accurate enough". However, this seems tricky and I'd rather not rely on a background thread that can't be easily controlled.

We can provide a convenience function such as the one below, but since the locks will be handled implicitly inside the Verify and CleanInfo methods it might cause issues if we need to make changes in that code later: you'd either assume the code isn't thread-safe because locks aren't explicitly handled in the method, or forget to handle the locks

func (bfp *BruteForceProtection) MasterVerify(token string) bool {
  if !bfp.Verify(token) && !bfp.CleanInfo(token) {
    return false
  }
  return true
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated info in this regard: the CleanInfo method has been removed because we'd need to read from the store twice. The updated code will use a write lock always and conditionally write into the store if there is obsolete data.

Comment on lines +44 to +63
// AddAttempt register a new failed attempt for the provided public share
// If the time gap or the max attempts are 0, the failed attempt won't be
// registered
func (bfp *BruteForceProtection) AddAttempt(shareToken string) {
if bfp.timeGap <= 0 || bfp.maxAttempts <= 0 {
return
}

bfp.rwmutex.Lock()
defer bfp.rwmutex.Unlock()

attempt := &attemptData{
Timestamp: time.Now().Unix(),
}

bfp.attemptMap[shareToken] = append(bfp.attemptMap[shareToken], attempt)

// clean data if needed
bfp.checkProtection(shareToken)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unfortunately this won't work so easy. In production we use multiple instances of this service. We need a global counter of this value so we are sure all intances behave the same at the same moment in time.

Copy link
Member Author

Choose a reason for hiding this comment

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

We'll have to move the counter to natsjs (not sure what alternatives we have inside reva). We need to ensure it's thread-safe too.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes. Or we store it as an additional property on the public link itself. Not sure what is more feasible.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll change the plans a bit

Discarded solutions:

  • Reva stores don't provide thread-safety. This means that there could be problems when multiple replicas try to store failed attempts over the same share.
  • The public link doesn't have a good place to store additional information.
    • Changing the public link definition in the cs3org API doesn't seem a good idea.
    • Adding the information at storage level implies changing all the implementations to prepare them to store random information.

Proposed solution:

We'll keep the current code. However, when a failed attempt happens, the service will emit a "public share password failed" event. The event will be received by all the replicas that will adjust the related information on their side.

The additional benefit is that other services like audit can also receive the event and act accordingly. For example, the audit service might want to log something about the failed attempt.

Copy link

@2403905 2403905 Jan 15, 2026

Choose a reason for hiding this comment

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

@jvillafanez Do we need to implement some event based logic if we already have the nats-kv in a reva/pkg/store ?
// Create initializes a new store func Create(opts ...microstore.Option) microstore.Store

Copy link

Choose a reason for hiding this comment

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

Can we just use the existing cache?

Copy link
Member Author

@jvillafanez jvillafanez Jan 15, 2026

Choose a reason for hiding this comment

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

The store doesn't provide any thread-safety mechanism, so there is a high risk of race conditions.
If there are 2 or more failures happening at the same time and going to different replicas, all the replicas will try to write the data at the same time. There is a high risk of one replica overwriting the data of any other and messing up with the failure count.
It's the classic "get and set" problem that doesn't have solution without thread-safety mechanisms, either (distributed) locks or atomic operations.

Copy link
Member Author

Choose a reason for hiding this comment

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

Final implementation will use the store. In order to mitigate (not completely prevent) the risk of overwriting data, we'll check that the data we've just written can be read from the store. If the data isn't there, we'll retry the operation several times (up to 10 at the moment) before failing.

Right now, the algorithm is pretty strict with the check (basically the data must match exactly), which might cause problems: replica A might fail to write despite the retries because replicas B and C keep overwriting the data.
It's probably fine to check if the failed attempt we want to add is present even if the full data isn't exactly the same. This should lead to less retries and faster responses in congested scenarios.

Copy link

Choose a reason for hiding this comment

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

I think this implementation is quite good since we don't need high accuracy.

case publicShareResponse.Status.Code == rpcv1beta1.Code_CODE_NOT_FOUND:
return nil, nil, errtypes.NotFound(publicShareResponse.Status.Message)
case publicShareResponse.Status.Code == rpcv1beta1.Code_CODE_PERMISSION_DENIED:
if secret != "" && secret != "|" && !CheckSkipAttempt(ctx, token) { // FIXME: needs better detection
Copy link
Collaborator

Choose a reason for hiding this comment

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

I do understand why secret != "". It makes no sense to increase wrong password counter if none was given. But I don't understand

  • Why secret != "|"? Why does anyone set the secret to "|"? Why do we need to care about this here?
  • What is the purpose of the CheckSkipAttempt functions? Why do we need them at all?

Copy link
Member Author

Choose a reason for hiding this comment

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

Why secret != "|"? Why does anyone set the secret to "|"? Why do we need to care about this here?

We get | as secret for empty password attempts, which happens when loading the share link in the web. The actual secret we get somewhere on top is publicshare|pass or signed|pass|expiration, so something is likely wrong and it isn't working properly in that scenario.

What is the purpose of the CheckSkipAttempt functions? Why do we need them at all?

That's for the duplicated authentication that happens in the server (owncloud/ocis#11862). There is one authentication happening in the proxy middleware to get a reva access token, plus the one to access the share.
Removing the authentication from the middleware didn't work because we need it if a user access to an office document via the public share.
This solution allows us to tell this code not to count the authentication coming from the middleware as a failed attempt.

Copy link
Collaborator

@kobergj kobergj Dec 17, 2025

Choose a reason for hiding this comment

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

We get | as secret for empty password attempts, which happens when loading the share link in the web. The actual secret we get somewhere on top is publicshare|pass or signed|pass|expiration, so something is likely wrong and it isn't working properly in that scenario.

So this means there is some error before where the publicshare|pass (or signed|pass|expiration) isn't converted properly to pass. The best option would be to fix it there, but I would be fine with a FIXME comment describing the problem if the actual fix is too cumbersome.

There is one authentication happening in the proxy middleware to get a reva access token, plus the one to access the share.

Why don't we just return immediately when the first one fails? This way second authentication would never happen and we don't have a problem with the counter.

Copy link
Member Author

Choose a reason for hiding this comment

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

Why don't we just return immediately when the first one fails? This way second authentication would never happen and we don't have a problem with the counter.

I don't think it's that easy... I've already tried removing the related code in the middleware, but it failed because we need the returned reva access token for the office integration (collaboration service). Access to office documents with collabora / onlyoffice through a public link wasn't possible with that change.

The only alternative I see is to move the brute force protection code to the middleware, but any internal request that bypasses the proxy would also bypass the brute force protection, and I don't think we want to do that.

@jvillafanez jvillafanez force-pushed the brute_force_protection_links branch from 82c8fa8 to 115854f Compare January 22, 2026 10:48
@jvillafanez jvillafanez requested a review from kobergj January 22, 2026 12:29
Copy link
Collaborator

@kobergj kobergj left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@jvillafanez jvillafanez merged commit 22a1be2 into main Jan 23, 2026
1 check passed
@jvillafanez jvillafanez deleted the brute_force_protection_links branch January 23, 2026 08:55
@mklos-kw mklos-kw mentioned this pull request Jan 23, 2026
9 tasks
spiceratops added a commit to spiceratops/k8s-gitops that referenced this pull request Feb 17, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [docker.io/owncloud/ocis](https://redirect.github.com/owncloud/ocis) |
major | `7.3.2` → `8.0.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>owncloud/ocis (docker.io/owncloud/ocis)</summary>

###
[`v8.0.0`](https://redirect.github.com/owncloud/ocis/blob/HEAD/CHANGELOG.md#Changelog-for-800-2026-02-13)

[Compare
Source](https://redirect.github.com/owncloud/ocis/compare/v7.3.2...v8.0.0)

The following sections list the changes for 8.0.0.

[8.0.0]:
https://redirect.github.com/owncloud/ocis/compare/v7.3.1...v8.0.0

#### Summary

- Bugfix - Fix user light creation:
[#&#8203;11765](https://redirect.github.com/owncloud/ocis/pull/11765)
- Bugfix - OCM Specification Compliance:
[#&#8203;11773](https://redirect.github.com/owncloud/ocis/pull/11773)
- Bugfix - Remove leading dot before checking disabled extension:
[#&#8203;11814](https://redirect.github.com/owncloud/ocis/pull/11814)
- Bugfix - Support pointer types in config environment variable
decoding:
[#&#8203;11815](https://redirect.github.com/owncloud/ocis/pull/11815)
- Bugfix - Replace obsolete docker image in the deployment example:
[#&#8203;11828](https://redirect.github.com/owncloud/ocis/pull/11828)
- Bugfix - Fix error code when a user can't disable a space:
[#&#8203;11845](https://redirect.github.com/owncloud/ocis/pull/11845)
- Bugfix - Fix Sharingroles:
[#&#8203;11898](https://redirect.github.com/owncloud/ocis/pull/11898)
- Bugfix - Fix the error handling for empty name on space update:
[#&#8203;11933](https://redirect.github.com/owncloud/ocis/pull/11933)
- Bugfix - Fix group creation in ocis-multi example:
[#&#8203;12019](https://redirect.github.com/owncloud/ocis/pull/12019)
- Change - Remove deprecated OCIS\_SHOW\_USER\_EMAIL\_IN\_RESULTS:
[#&#8203;11942](https://redirect.github.com/owncloud/ocis/pull/11942)
- Enhancement - Bump Reva:
[#&#8203;460](https://redirect.github.com/owncloud/reva/pull/460)
- Enhancement - Set Referrer-Policy to no-referrer:
[#&#8203;11722](https://redirect.github.com/owncloud/ocis/pull/11722)
- Enhancement - Bump Reva:
[#&#8203;11748](https://redirect.github.com/owncloud/ocis/pull/11748)
- Enhancement - Support disabling editors by extensions:
[#&#8203;11750](https://redirect.github.com/owncloud/ocis/pull/11750)
- Enhancement - Add CLI to move stuck uploads:
[#&#8203;11762](https://redirect.github.com/owncloud/ocis/pull/11762)
- Enhancement - Use externalID in Provisioning API:
[#&#8203;11799](https://redirect.github.com/owncloud/ocis/pull/11799)
- Enhancement - Add CLI to clean orphned grants:
[#&#8203;11804](https://redirect.github.com/owncloud/ocis/pull/11804)
- Enhancement - Bump Reva:
[#&#8203;11808](https://redirect.github.com/owncloud/ocis/pull/11808)
- Enhancement - Bump Web to v12.2.0:
[#&#8203;11834](https://redirect.github.com/owncloud/ocis/pull/11834)
- Enhancement - Introduce claims for multi-instance-ocis:
[#&#8203;11848](https://redirect.github.com/owncloud/ocis/pull/11848)
- Enhancement - Update the ocis\_full deployment example images:
[#&#8203;11860](https://redirect.github.com/owncloud/ocis/pull/11860)
- Enhancement - Implement brute force protection for public links:
[#&#8203;11864](https://redirect.github.com/owncloud/ocis/pull/11864)
- Enhancement - Update the ocis\_full deployment example traefik image:
[#&#8203;11867](https://redirect.github.com/owncloud/ocis/pull/11867)
- Enhancement - Added a graph endpoint alias:
[#&#8203;11871](https://redirect.github.com/owncloud/ocis/pull/11871)
- Enhancement - Force Strict-Transport-Security:
[#&#8203;11880](https://redirect.github.com/owncloud/ocis/pull/11880)
- Enhancement - Relocate Transifex resources:
[#&#8203;11889](https://redirect.github.com/owncloud/ocis/pull/11889)
- Enhancement - Update the ocis\_full deployment example images:
[#&#8203;11890](https://redirect.github.com/owncloud/ocis/pull/11890)
- Enhancement - Allow sharing between instances:
[#&#8203;11893](https://redirect.github.com/owncloud/ocis/pull/11893)
- Enhancement - Add photo EXIF metadata to search index and WebDAV
results:
[#&#8203;11912](https://redirect.github.com/owncloud/ocis/pull/11912)
- Enhancement - Update the traefik image for some deployment examples:
[#&#8203;11915](https://redirect.github.com/owncloud/ocis/pull/11915)
- Enhancement - Add users instances:
[#&#8203;11925](https://redirect.github.com/owncloud/ocis/pull/11925)
- Enhancement - Introduce external shares permission:
[#&#8203;11931](https://redirect.github.com/owncloud/ocis/pull/11931)
- Enhancement - Update to go 1.25:
[#&#8203;12011](https://redirect.github.com/owncloud/ocis/pull/12011)
- Enhancement - Bump Web to 12.3.1:
[#&#8203;12016](https://redirect.github.com/owncloud/ocis/pull/12016)
- Enhancement - Bump Web to 12.3.0:
[#&#8203;13519](https://redirect.github.com/owncloud/web/pull/13519)

#### Details

- Bugfix - Fix user light creation:
[#&#8203;11765](https://redirect.github.com/owncloud/ocis/pull/11765)

When trying to switch a user to user light before they logged in for the
first
time, an error would occur. The server now correctly handles this case
and
  allows switching to user light even before the first login.

  [#&#8203;11765](https://redirect.github.com/owncloud/ocis/pull/11765)

- Bugfix - OCM Specification Compliance:
[#&#8203;11773](https://redirect.github.com/owncloud/ocis/pull/11773)

  OCM Specification Compliance

  [#&#8203;11773](https://redirect.github.com/owncloud/ocis/pull/11773)

- Bugfix - Remove leading dot before checking disabled extension:
[#&#8203;11814](https://redirect.github.com/owncloud/ocis/pull/11814)

We have fixed a bug where the leading dot was not removed before
checking if an
  extension is disabled. The original behavior would have caused the
  `COLLABORATION_WOPI_DISABLED_EXTENSIONS` config to be ignored.

  [#&#8203;11814](https://redirect.github.com/owncloud/ocis/pull/11814)

- Bugfix - Support pointer types in config environment variable
decoding:
[#&#8203;11815](https://redirect.github.com/owncloud/ocis/pull/11815)

Added support for decoding pointer types (\*bool, \*int, \*string, etc.)
in the
envdecode package, allowing configuration fields to distinguish between
unset
(nil) and explicitly set values. Changed `WEB_OPTION_EMBED_ENABLED` from
string
  to \*bool type to enable explicit false values.

  [#&#8203;11815](https://redirect.github.com/owncloud/ocis/pull/11815)

- Bugfix - Replace obsolete docker image in the deployment example:
[#&#8203;11828](https://redirect.github.com/owncloud/ocis/pull/11828)

In the ocis\_ldap deployment example, we were using the bitnami/openldap
docker
image. This image isn't available any longer, so the example couldn't be
  deployed as intended.

We've replaced the docker image with the osixia/openldap image and we've
  adjusted some of the configuration of the openldap image.

  [#&#8203;11828](https://redirect.github.com/owncloud/ocis/pull/11828)

- Bugfix - Fix error code when a user can't disable a space:
[#&#8203;11845](https://redirect.github.com/owncloud/ocis/pull/11845)

Previously, if the user couldn't disable a space due to wrong
permissions, the
request returned a 404 error code, as if the space wasn't found even
though the
  space was visible. Now it will return the expected 403 error code.

  [#&#8203;11845](https://redirect.github.com/owncloud/ocis/pull/11845)

- Bugfix - Fix Sharingroles:
[#&#8203;11898](https://redirect.github.com/owncloud/ocis/pull/11898)

  Sharing roles were inconsistent, now they are fixed.

  [#&#8203;11898](https://redirect.github.com/owncloud/ocis/pull/11898)

- Bugfix - Fix the error handling for empty name on space update:
[#&#8203;11933](https://redirect.github.com/owncloud/ocis/pull/11933)

  Fix the error handling for empty name on space update.

[#&#8203;11887](https://redirect.github.com/owncloud/ocis/issues/11887)
  [#&#8203;11933](https://redirect.github.com/owncloud/ocis/pull/11933)

- Bugfix - Fix group creation in ocis-multi example:
[#&#8203;12019](https://redirect.github.com/owncloud/ocis/pull/12019)

  Group creation was not working in ocis.ocm instance

  [#&#8203;12019](https://redirect.github.com/owncloud/ocis/pull/12019)

- Change - Remove deprecated OCIS\_SHOW\_USER\_EMAIL\_IN\_RESULTS:
[#&#8203;11942](https://redirect.github.com/owncloud/ocis/pull/11942)

Deprecated OCIS\_SHOW\_USER\_EMAIL\_IN\_RESULTS environment variable was
removed from
frontend service config. Use OCIS\_USER\_SEARCH\_DISPLAYED\_ATTRIBUTES
instead to
  control which user attributes are displayed in search results.

  [#&#8203;11942](https://redirect.github.com/owncloud/ocis/pull/11942)

- Enhancement - Bump Reva:
[#&#8203;460](https://redirect.github.com/owncloud/reva/pull/460)

This updates the ownCloud Reva dependency to include brute force
protection for
public links. The feature implements rate-limiting that blocks access to
password-protected public shares after exceeding a configurable maximum
number
  of failed authentication attempts within a time window.

[owncloud/reva#460](https://redirect.github.com/owncloud/reva/pull/460)

- Enhancement - Set Referrer-Policy to no-referrer:
[#&#8203;11722](https://redirect.github.com/owncloud/ocis/pull/11722)

  Change the Referrer-Policy from 'strict-origin-when-cross-origin' to
  'no-referrer' to enhance user privacy and security.

Previously, the origin was sent on cross-origin requests. This change
completely
removes the Referrer header from all outgoing requests, preventing any
potential
leakage of browsing information to third parties. This is a more robust
approach
  to protecting user privacy.

  [#&#8203;11722](https://redirect.github.com/owncloud/ocis/pull/11722)

- Enhancement - Bump Reva:
[#&#8203;11748](https://redirect.github.com/owncloud/ocis/pull/11748)

  This updates the ownCloud Reva dependency to commit
  `82c22e954c1cdabb62a14fbe5c1a4ec3e1dabd45`. Changelog:

[owncloud/reva@`cb98fe5...82c22e9`](https://redirect.github.com/owncloud/reva/compare/cb98fe521deb55ae339d6ddc4a4b60d6d4da9e14...82c22e954c1cdabb62a14fbe5c1a4ec3e1dabd45)

  [#&#8203;11748](https://redirect.github.com/owncloud/ocis/pull/11748)

- Enhancement - Support disabling editors by extensions:
[#&#8203;11750](https://redirect.github.com/owncloud/ocis/pull/11750)

We have extended the configuration of collaboration service to support
disabling
  editors for specific file extensions.

  [#&#8203;11750](https://redirect.github.com/owncloud/ocis/pull/11750)

- Enhancement - Add CLI to move stuck uploads:
[#&#8203;11762](https://redirect.github.com/owncloud/ocis/pull/11762)

In some cases of saturated disk usage ocis metadata may get stuck. This
command
  relieves this case.

  [#&#8203;11762](https://redirect.github.com/owncloud/ocis/pull/11762)

- Enhancement - Use externalID in Provisioning API:
[#&#8203;11799](https://redirect.github.com/owncloud/ocis/pull/11799)

This PR adds the externalID as optional parameter to the Provisioning
API that
can be used as the primary identifier. It also contains a switch to
enable this
  setting.

  [#&#8203;11799](https://redirect.github.com/owncloud/ocis/pull/11799)

- Enhancement - Add CLI to clean orphned grants:
[#&#8203;11804](https://redirect.github.com/owncloud/ocis/pull/11804)

Add CLI `ocis shares clean-orphaned-grants` to find and optionally
remove
  storage grants without corresponding share-manager entries.

  [#&#8203;11804](https://redirect.github.com/owncloud/ocis/pull/11804)

- Enhancement - Bump Reva:
[#&#8203;11808](https://redirect.github.com/owncloud/ocis/pull/11808)

  This updates the ownCloud Reva dependency to commit
  `a122a9538794530267743edfd5dc67b48aa90325`. Changelog:

[owncloud/reva@`751223b...a122a95`](https://redirect.github.com/owncloud/reva/compare/751223b32d4852c73a43388f6f55308c2065afeb...a122a9538794530267743edfd5dc67b48aa90325)

  [#&#8203;11808](https://redirect.github.com/owncloud/ocis/pull/11808)

- Enhancement - Bump Web to v12.2.0:
[#&#8203;11834](https://redirect.github.com/owncloud/ocis/pull/11834)

- Bugfix
[owncloud/web#13177](https://redirect.github.com/owncloud/web/pull/13177):
Fix
    copying public link and password on Safari - Bugfix

[owncloud/web#13198](https://redirect.github.com/owncloud/web/pull/13198):
Fix incorrect
    translations - Bugfix

[owncloud/web#13203](https://redirect.github.com/owncloud/web/pull/13203):
Remove
    duplicate resource links - Bugfix

[owncloud/web#13213](https://redirect.github.com/owncloud/web/pull/13213):
Do not disable
    sharing of resources when managing spaces via claims - Bugfix

[owncloud/web#13223](https://redirect.github.com/owncloud/web/pull/13223):
Fix spinner
    loading continuously when resource is deleted - Bugfix

[owncloud/web#13233](https://redirect.github.com/owncloud/web/pull/13233):
Include Ubuntu
font - Bugfix
[owncloud/web#13253](https://redirect.github.com/owncloud/web/pull/13253):
    External share ID fallback - Bugfix

[owncloud/web#13274](https://redirect.github.com/owncloud/web/pull/13274):
Handle file
    loading error - Bugfix

[owncloud/web#13329](https://redirect.github.com/owncloud/web/pull/13329):
Use sticky
    header composable in deleted files - Enhancement

[owncloud/web#13168](https://redirect.github.com/owncloud/web/pull/13168):
Hide trashed
    spaces - Enhancement

[owncloud/web#13169](https://redirect.github.com/owncloud/web/pull/13169):
Drop beta
    badge from GeoGebra pinboards - Enhancement

[owncloud/web#13172](https://redirect.github.com/owncloud/web/pull/13172):
Add Excalidraw
    file icon - Enhancement

[owncloud/web#13197](https://redirect.github.com/owncloud/web/pull/13197):
Add Visio file
    icons - Enhancement

[owncloud/web#13224](https://redirect.github.com/owncloud/web/pull/13224):
Add table
    caption - Enhancement

[owncloud/web#13235](https://redirect.github.com/owncloud/web/pull/13235):
Use API groups
    search in admin settings - Enhancement

[owncloud/web#13296](https://redirect.github.com/owncloud/web/pull/13296):
Embed mode
    share links with password

  [#&#8203;11834](https://redirect.github.com/owncloud/ocis/pull/11834)
  <https://github.com/owncloud/web/releases/tag/v12.2.0>

- Enhancement - Introduce claims for multi-instance-ocis:
[#&#8203;11848](https://redirect.github.com/owncloud/ocis/pull/11848)

Reads claims from the oidc token to add users to ocis with specific
roles.

  [#&#8203;11848](https://redirect.github.com/owncloud/ocis/pull/11848)

- Enhancement - Update the ocis\_full deployment example images:
[#&#8203;11860](https://redirect.github.com/owncloud/ocis/pull/11860)

  - Traefik    3.6.2
  - Collabora  27.4.7.3
  - OnlyOffice 9.2.0
  - Mailpit    1.28.0

  [#&#8203;11860](https://redirect.github.com/owncloud/ocis/pull/11860)

- Enhancement - Implement brute force protection for public links:
[#&#8203;11864](https://redirect.github.com/owncloud/ocis/pull/11864)

Public links will be protected by default, allowing up to 5 wrong
password
attempts per hour. If such rate is exceeded, the link will be blocked
for all
the users until the failure rate goes below the configured threshold (5
failures
  per hour by default, as said).

The failure rate is configurable, so it can be 10 failures each 2 hours
or 3
  failures per minute.

  [#&#8203;11864](https://redirect.github.com/owncloud/ocis/pull/11864)
[owncloud/reva#460](https://redirect.github.com/owncloud/reva/pull/460)

- Enhancement - Update the ocis\_full deployment example traefik image:
[#&#8203;11867](https://redirect.github.com/owncloud/ocis/pull/11867)

  - Traefik: 3.6.4
  - Traefik fix for Collabora

  [#&#8203;11867](https://redirect.github.com/owncloud/ocis/pull/11867)

- Enhancement - Added a graph endpoint alias:
[#&#8203;11871](https://redirect.github.com/owncloud/ocis/pull/11871)

We added a graph endpoint alias that uses the unified roles instead of
cs3 roles

  [#&#8203;11871](https://redirect.github.com/owncloud/ocis/pull/11871)

- Enhancement - Force Strict-Transport-Security:
[#&#8203;11880](https://redirect.github.com/owncloud/ocis/pull/11880)

Added `PROXY_FORCE_STRICT_TRANSPORT_SECURITY` environment variable to
force
emission of `Strict-Transport-Security` header on all responses,
including plain
HTTP requests when TLS is terminated upstream. Useful when oCIS is
deployed
  behind a proxy.

  [#&#8203;11880](https://redirect.github.com/owncloud/ocis/pull/11880)

- Enhancement - Relocate Transifex resources:
[#&#8203;11889](https://redirect.github.com/owncloud/ocis/pull/11889)

The resources for services with translations are relocated in Transifex
from
owncloud to owncloud-web. Now all ocis related resources are in one
project.

  [#&#8203;11889](https://redirect.github.com/owncloud/ocis/pull/11889)

- Enhancement - Update the ocis\_full deployment example images:
[#&#8203;11890](https://redirect.github.com/owncloud/ocis/pull/11890)

  - Traefic:   v3.6.6
  - Collabora: 25.04.8.1.1
  - Onlyoffice: 9.2.1.1

  [#&#8203;11890](https://redirect.github.com/owncloud/ocis/pull/11890)

- Enhancement - Allow sharing between instances:
[#&#8203;11893](https://redirect.github.com/owncloud/ocis/pull/11893)

  In Multi-Instance ocis it is now possible to share between instances.

  [#&#8203;11893](https://redirect.github.com/owncloud/ocis/pull/11893)

- Enhancement - Add photo EXIF metadata to search index and WebDAV
results:
[#&#8203;11912](https://redirect.github.com/owncloud/ocis/pull/11912)

We've added support for photo metadata fields in the Bleve search index
and
WebDAV REPORT responses. This enables photo gallery applications to
efficiently
  query photos by their EXIF metadata and display camera information.

  The following photo metadata fields are now indexed and searchable: -
`photo.takenDateTime` - When the photo was taken (supports date range
queries) -
`photo.cameraMake` - Camera manufacturer (e.g., Canon, Nikon, Samsung) -
`photo.cameraModel` - Camera model name - `photo.fNumber` - Aperture
f-stop
value - `photo.focalLength` - Focal length in millimeters - `photo.iso`
- ISO
  sensitivity - `photo.orientation` - Image orientation -
  `photo.exposureNumerator` - Exposure time numerator (for shutter speed
calculation) - `photo.exposureDenominator` - Exposure time denominator
(for
  shutter speed calculation)

GPS location data is also included when available: -
`photo.location.latitude` -
  GPS latitude - `photo.location.longitude` - GPS longitude -
  `photo.location.altitude` - GPS altitude

These fields are returned in WebDAV search results using the
`oc:photo-*`
property namespace, allowing web extensions to build photo timeline
views,
  filter by camera, or show photos on a map.

  [#&#8203;11912](https://redirect.github.com/owncloud/ocis/pull/11912)

- Enhancement - Update the traefik image for some deployment examples:
[#&#8203;11915](https://redirect.github.com/owncloud/ocis/pull/11915)

  - Traefik: 3.6.6 --> 3.6.7

  [#&#8203;11915](https://redirect.github.com/owncloud/ocis/pull/11915)

- Enhancement - Add users instances:
[#&#8203;11925](https://redirect.github.com/owncloud/ocis/pull/11925)

The user endpoint now returns the instances that the user is either a
member or
  a guest of and the cross instance reference.

  [#&#8203;11925](https://redirect.github.com/owncloud/ocis/pull/11925)

- Enhancement - Introduce external shares permission:
[#&#8203;11931](https://redirect.github.com/owncloud/ocis/pull/11931)

Introduces a permission allowing to share between instances in
multi-instance
ocis. This permission is by default added to the admin and space-admin
role.

  [#&#8203;11931](https://redirect.github.com/owncloud/ocis/pull/11931)

- Enhancement - Update to go 1.25:
[#&#8203;12011](https://redirect.github.com/owncloud/ocis/pull/12011)

  We have updated go to version 1.25 and alpine to version 3.23.3

  [#&#8203;12011](https://redirect.github.com/owncloud/ocis/pull/12011)
  [#&#8203;12004](https://redirect.github.com/owncloud/ocis/pull/12004)

- Enhancement - Bump Web to 12.3.1:
[#&#8203;12016](https://redirect.github.com/owncloud/ocis/pull/12016)

Bugfix
[owncloud/web#13553](https://redirect.github.com/owncloud/web/pull/13553):
Search
  Text Overalps With Search Icon In The Search Bar

  [#&#8203;12016](https://redirect.github.com/owncloud/ocis/pull/12016)
  <https://github.com/owncloud/web/releases/tag/v12.3.1>

- Enhancement - Bump Web to 12.3.0:
[#&#8203;13519](https://redirect.github.com/owncloud/web/pull/13519)

Bugfix
[owncloud/web#13406](https://redirect.github.com/owncloud/web/pull/13406):
Prevent
  overlapping search content Bugfix

[owncloud/web#13415](https://redirect.github.com/owncloud/web/pull/13415)
Filter only
  personal trashed spaces Enhancement
[owncloud/web#5847](https://redirect.github.com/owncloud/web/pull/5847)
Dynamic
  theme-color meta tag based on loaded theme Enhancement

[owncloud/web#13412](https://redirect.github.com/owncloud/web/pull/13412)
Use beta
  endpoint for single drive operations Enhancement

[owncloud/web#13426](https://redirect.github.com/owncloud/web/pull/13426)
Add crash page
  Enhancement

[owncloud/web#13426](https://redirect.github.com/owncloud/web/pull/13426)Catch
spaces
  loading error Enhancement

[owncloud/web#13485](https://redirect.github.com/owncloud/web/pull/13485)Drop
custom
  share filters Enhancement

[owncloud/web#13499](https://redirect.github.com/owncloud/web/pull/13499)Add
  cross-instance reference Enhancement

[owncloud/web#13500](https://redirect.github.com/owncloud/web/pull/13500)Add
instance
  switcher


[owncloud/web#13519](https://redirect.github.com/owncloud/web/pull/13519)
  <https://github.com/owncloud/web/releases/tag/v12.3.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNS4zIiwidXBkYXRlZEluVmVyIjoiNDMuMTYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUvY29udGFpbmVyIiwidHlwZS9tYWpvciJdfQ==-->
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