Compare commits

...

157 commits

Author SHA1 Message Date
Till Faelligen 084181332b
Fix link 2024-11-25 11:04:10 +01:00
Till Faelligen 79b87c7a08
Merge branch 'main' of github.com:matrix-org/dendrite 2024-11-14 13:42:51 +01:00
Till Faelligen 488009ca90
Update README 2024-11-14 09:24:36 +01:00
Till Faelligen 95d93b32e3
Update docs 2024-11-04 15:34:08 +01:00
Till Faelligen 4cc68ef922
Add link to the new repo 2024-10-30 15:04:29 +01:00
idk 6cd1285ca0
Adds support for listening on and connecting to I2P and Onion services securely (#3293)
This PR adds 2 `dendrite-demo` main's, each designed expressly to serve
a Hidden Service/Overlay network.

The first, `dendrite-demo-i2p` add self-configuration for use of
dendrite as an I2P hidden service(eepsite) and to connect to I2P
services(federate) as an I2P client. It further disables the `dendrite`
server from communicating with non-anonymous servers by
federation(because I2P does not canonically have the ability to exit, we
rely on donors for exit traffic), and enables the use of self-signed TLS
certificates([because I2P services are self-authenticating but TLS is
still required for other aspects of the system to work
reliably](https://tor.stackexchange.com/questions/13887/registering-onion-with-certificate-authority)).
This demo turns the system into an "pseudonymous" homeserver which
people can connect to using an I2P-enabled Matrix client(I like `cinny`
and it's what I tested with).

The second, `dendrite-demo-tor` adds self-configuration for the use of
dendrite as an Onion service and to connect to other onion services and
non-anonymous web sites using Tor to obfuscate it's physical location
and providing, optionally, pseudonymity. It also enables the use of
self-signed TLS certificates, for the same reason as with I2P, because
onion services aren't typically eligible for TLS certificates. It has
also been tested with `cinny`.

These services are both pseudonymous like myself, not anonymous. I will
be meeting members of the element team at the CCC assembly shortly to
discuss contributing under my pseudonym.

As none of the other `dendrite-demo` have unit tests I did not add them
to these checkins.

* [*] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests

---------

Co-authored-by: eyedeekay <idk@mulder>
Co-authored-by: Till Faelligen <2353100+S7evinK@users.noreply.github.com>
2024-09-23 19:28:28 +02:00
arenekosreal df770dae0a
Make OPTIONS method on MSC3916 endpoints available without auth (#3431)
OPTIONS method is usually sent by browser in preflight requests, most of
the time we cannot control preflight request to add auth header.

Synapse will return a 204 response directly without authentication for
those OPTIONS method.

According to firefox's documentation, both 200 and 204 are acceptable so
I think there is no need to change handler in dendrite.

This closes https://github.com/matrix-org/dendrite/issues/3424

No need to add a test because this is just a fix and I have tested on my
Cinny Web client personally.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `arenekosreal
<17194552+arenekosreal@users.noreply.github.com>`

Signed-off-by: arenekosreal <17194552+arenekosreal@users.noreply.github.com>
2024-09-22 10:33:54 +02:00
Rhea Danzey 07e59d0ba9
Helm Chart - Add configuration for node selector / tolerations / affi… (#3433)
For some experimentation I'm doing, I need to pin Dendrite to a specific
node pool. This should be available configuration within the chart
ideally, and this should do it in theory.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Rhea Danzey <rdanzey@element.io>`

---------

Signed-off-by: Rhea Danzey <rdanzey@element.io>
2024-09-20 13:56:27 -05:00
Rhea Danzey c914f062e6
Helm chart - Fix image pull secrets for signing-key job (#3430)
Forgotten in https://github.com/matrix-org/dendrite/pull/3428 - Pull
secrets need to be used for signing-key job since it uses Dendrite
container as well

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Rhea Danzey <rdanzey@element.io>`

---------

Signed-off-by: Rhea Danzey <rdanzey@element.io>
2024-09-20 07:44:50 +02:00
Till Faelligen f2db7cbcb8
Bump version to trigger CI 2024-09-18 21:46:33 +02:00
Rhea Danzey 40dd2c0400
Use chart-releaser-action tag v1.6.0 (#3429)
Context:
https://github.com/matrix-org/dendrite/pull/3427#issuecomment-2359139622

Try tagged version of chart-releaser-action now that mark_latest option
is available

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Rhea Danzey <rdanzey@element.io>`
2024-09-18 21:41:22 +02:00
Rhea Danzey 152626c87e
Helm chart - Add configuration for image pull secrets (#3428)
This minor change should allow the use of private container images with
this chart by specifying image pull secrets.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Rhea Danzey <rdanzey@element.io>`

---------

Signed-off-by: Rhea Danzey <rdanzey@element.io>
2024-09-18 20:22:18 +02:00
Rhea Danzey 3530d2997f
Ensure Helm packages generated end up in docs/ subpath that's hosted (#3427)
I've noticed that Chart Releaser is behaving improperly, and not
successfully putting the charts where gh-pages will hots them and
generating invalid index.

This change should ensure built charts end up in the `docs/` subpath,
which should ensure that `gh-pages` branch isn't getting an invalid
`index.yaml` and new charts should be automatically available.

### Pull Request Checklist

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Rhea Danzey <rdanzey@element.io>`
2024-09-18 20:21:23 +02:00
Rhea Danzey aa8d10a62d
Pinecone test image - Explicitly select Alpine golang image (#3426)
I've noticed when trying to build the Dendrite Pinecone test image, the
build fails due to `apk` not being available:

<img width="837" alt="image"
src="https://github.com/user-attachments/assets/8b483010-a037-4499-b925-a806ae8a82cb">

Checking out the [Docker Hub](https://hub.docker.com/_/golang/) repo for
the `golang` image it looks like this can resovle to `1.22-bookworm`, so
this should ensure we get an Alpine-based image for this build.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Rhea Danzey <rdanzey@element.io>`

Signed-off-by: Rhea Danzey <rdanzey@element.io>
2024-09-18 09:16:33 +02:00
Till 763c79f142
Version 0.13.8 (#3421) 2024-09-13 15:06:07 +02:00
Till ed6d964e5d
Fix function signature, use default random boundary (#3422)
Fixes the function signature of `parseMultipartResponse` and uses the
default random boundary when creating a new multipart response.
2024-09-13 09:39:30 +02:00
Till 002fed3cb9
Bump GMSL (#3419)
Adds
https://github.com/matrix-org/gomatrixserverlib/pull/436
https://github.com/matrix-org/gomatrixserverlib/pull/438
https://github.com/matrix-org/gomatrixserverlib/pull/432
2024-09-10 19:45:31 +00:00
Paige Thompson 1e0e935699
add option for credentials file for NATS; more info: https://docs.nat… (#3415)
Not 100% on how you would want to test this; you would need a NATS
server configured with NKey:

https://docs.nats.io/using-nats/developer/connecting/creds

This was tested with Synadia's free NATS SaaS and it does appear to be
working, however there's an issue with how NATS is used in general:

```
time="2024-09-10T14:40:05.105105731Z" level=fatal msg="Unable to add in-memory stream" error="nats: account requires a stream config to have max bytes set" stream=DendriteInputRoomEvent subjects="[DendriteInputRoomEvent DendriteInputRoomEvent.>]"
```

I tried creating the topic manually, however dendrite insists on
deleting/recreating the topic, so getting this to work is an issue I'm
going ot have to deal with later unless somebody gets to it before then.

If you feel more competent than me and wanna draw from this PR as an
example (if you have another way you'd prefer to see this done) go ahead
feel free I just wanna see it get done and I'm not particularly good at
working with golang.

Signed-off-by: `Paige Thompson <paige@paige.bio>`
2024-09-10 21:28:04 +02:00
Neil 117ed66037
Update NATS to 2.10.20, use SyncAlways (#3418)
The internal NATS instance is definitely convenient but it does have one
problem: its lifecycle is tied to the Dendrite process. That means if
Dendrite panics or OOMs, it takes out NATS with it. I suspect this is
sometimes contributing to what people see with stuck streams, as some
operations or state might not be written to disk fully before it gets
interrupted.

Using `SyncAlways` means that NATS will effectively use `O_SYNC` and
block writes on flushes, which should improve resiliency against this
kind of failure considerably. It might affect performance a little but
shouldn't be significant.

Also updates NATS to 2.10.20 as there have been all sorts of fixes since
2.10.7, including better `SyncAlways` handling.

Signed-off-by: Neil Alexander <git@neilalexander.dev>

---------

Signed-off-by: Neil Alexander <git@neilalexander.dev>
Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
2024-09-10 20:54:38 +02:00
Till 3a2eadcc36
Speed up purging rooms (#3381)
[skip CI]
2024-09-10 20:43:50 +02:00
Werner 7bbec19a6a
cosmetics nginx sample config (#3385)
- fix typo
- fix spaces
- full sentence

Not tests required since no functional change happens

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Werner <werner@armbian.com>`

[skip CI]
2024-09-10 20:40:35 +02:00
Till 7a4ef240fc
Implement MSC3916 (#3397)
Needs https://github.com/matrix-org/gomatrixserverlib/pull/437
2024-08-16 12:37:59 +02:00
jjj333_p 8c6cf51b8f
Fixing Presence Conflicts (#3320)
This is meant to cache client presence for a moment so that it doesn't
oscillate.

Currently Dendrite just federates out whatever presence it gets from the
sync loop, which means if theres any clients attempting to sync without
setting the user online, and there is an online client, it will just
flip back and forth each time one of the clients polls /sync.

This pull request essentially stores in a map when the client last set
online ideally to allow the online client to sync again and set an
online presence before setting idle or offline.

I am not great at programming nor am I familiar with this codebase so if
this pr is just shitwater feel free to discard, just trying to fix an
issue that severely bothers me. If it is easier you can also steal the
code and write it in yourself. I ran the linter, not sure that it did
anything, the vscode go extension seems to format and lint anyways.

I tried to run unit tests but I have no idea any of this thing. it
errors on
`TestRequestPool_updatePresence/same_presence_is_not_published_dummy2
(10m0s)` which I think making this change broke. I am unsure how to
comply, if y'all point me in the right direction ill try to fix it. I
have tested it with all the situations I can think of on my personal
instance pain.agency, and this seems to stand up under all the
previously bugged situations.

~~My go also decided to update a bunch of the dependencies, I hate git
and github and have no idea how to fix that, it was not intentional.~~ i
just overwrote them with the ones from the main repo and committed it,
seems to have done what was needed.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Joseph Winkie <jjj333.p.1325@gmail.com>`

---------

Co-authored-by: Till Faelligen <2353100+S7evinK@users.noreply.github.com>
2024-08-03 22:03:39 +02:00
guoguangwu 5216e74b9a
fix: close resp body (#3364)
### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [ ] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [ ] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Your Name <your@email.example.org>`

Signed-off-by: guoguangwu <guoguangwug@gmail.com>
2024-08-03 21:20:43 +02:00
Till 4d116ff0db
Bump yggdrasil (#3407) 2024-08-03 20:26:28 +02:00
dependabot[bot] c876790f08
Bump github.com/docker/docker from 24.0.9+incompatible to 25.0.6+incompatible (#3405)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from
24.0.9+incompatible to 25.0.6+incompatible.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/docker/releases">github.com/docker/docker's
releases</a>.</em></p>
<blockquote>
<h2>v25.0.6</h2>
<h2>25.0.6</h2>
<p>For a full list of pull requests and changes in this release, refer
to the relevant GitHub milestones:</p>
<ul>
<li><a
href="https://github.com/docker/cli/issues?q=is%3Aclosed+milestone%3A25.0.6">docker/cli,
25.0.6 milestone</a></li>
<li><a
href="https://github.com/moby/moby/issues?q=is%3Aclosed+milestone%3A25.0.6">moby/moby,
25.0.6 milestone</a></li>
<li>Deprecated and removed features, see <a
href="https://github.com/docker/cli/blob/v25.0.6/docs/deprecated.md">Deprecated
Features</a>.</li>
<li>Changes to the Engine API, see <a
href="https://github.com/moby/moby/blob/v25.0.6/docs/api/version-history.md">API
version history</a>.</li>
</ul>
<h3>Security</h3>
<p>This release contains a fix for <a
href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-41110">CVE-2024-41110</a>
/ <a
href="https://github.com/moby/moby/security/advisories/GHSA-v23v-6jw2-98fq">GHSA-v23v-6jw2-98fq</a>
that impacted setups using <a
href="https://docs.docker.com/engine/extend/plugins_authorization/">authorization
plugins (AuthZ)</a> for access control.</p>
<h3>Bug fixes and enhancements</h3>
<ul>
<li>[25.0] remove erroneous <code>platform</code> from image
<code>config</code> OCI descriptor in <code>docker save</code> output.
<a
href="https://redirect.github.com/moby/moby/pull/47695">moby/moby#47695</a></li>
<li>[25.0 backport] Fix a nil dereference when getting image history for
images having layers without the <code>Created</code> value set. <a
href="https://redirect.github.com/moby/moby/pull/47759">moby/moby#47759</a></li>
<li>[25.0 backport] apparmor: Allow confined runc to kill containers. <a
href="https://redirect.github.com/moby/moby/pull/47830">moby/moby#47830</a></li>
<li>[25.0 backport] Fix an issue where rapidly promoting a Swarm node
after another node was demoted could cause the promoted node to fail its
promotion. <a
href="https://redirect.github.com/moby/moby/pull/47869">moby/moby#47869</a></li>
<li>[25.0 backport] don't depend on containerd platform.Parse to return
a typed error. <a
href="https://redirect.github.com/moby/moby/pull/47890">moby/moby#47890</a></li>
<li>[25.0 backport] builder/mobyexporter: Add missing nil check <a
href="https://redirect.github.com/moby/moby/pull/47987">moby/moby#47987</a></li>
</ul>
<h3>Packaging updates</h3>
<ul>
<li>Update AWS SDK Go v2 to v1.24.1 for AWS CloudWatch logging driver.
<a
href="https://redirect.github.com/moby/moby/pull/47724">moby/moby#47724</a></li>
<li>Update Go runtime to 1.21.12, which contains security fixes for <a
href="https://github.com/advisories/GHSA-hw49-2p59-3mhj">CVE-2024-24791</a>
<a
href="https://redirect.github.com/moby/moby/pull/48146">moby/moby#48146</a></li>
<li>Update Containerd (static binaries only) to <a
href="https://github.com/containerd/containerd/releases/tag/v1.7.20">v1.7.20</a>.
<a
href="https://redirect.github.com/moby/moby/pull/48199">moby/moby#48199</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/moby/moby/compare/v25.0.5...v25.0.6">https://github.com/moby/moby/compare/v25.0.5...v25.0.6</a></p>
<h2>v25.0.5</h2>
<h2>25.0.5</h2>
<p>For a full list of pull requests and changes in this release, refer
to the relevant GitHub milestones:</p>
<ul>
<li><a
href="https://github.com/docker/cli/issues?q=is%3Aclosed+milestone%3A25.0.5">docker/cli,
25.0.5 milestone</a></li>
<li><a
href="https://github.com/moby/moby/issues?q=is%3Aclosed+milestone%3A25.0.5">moby/moby,
25.0.5 milestone</a></li>
<li>Deprecated and removed features, see <a
href="https://github.com/docker/cli/blob/v25.0.5/docs/deprecated.md">Deprecated
Features</a>.</li>
<li>Changes to the Engine API, see <a
href="https://github.com/moby/moby/blob/v25.0.5/docs/api/version-history.md">API
version history</a>.</li>
</ul>
<h3>Security</h3>
<p>This release contains a security fix for <a
href="https://github.com/moby/moby/security/advisories/GHSA-mq39-4gv4-mvpx">CVE-2024-29018</a>,
a potential data exfiltration from 'internal' networks via authoritative
DNS servers.</p>
<h3>Bug fixes and enhancements</h3>
<ul>
<li>
<p><a
href="https://github.com/moby/moby/security/advisories/GHSA-mq39-4gv4-mvpx">CVE-2024-29018</a>:
Do not forward requests to external DNS servers for a container that is
only connected to an 'internal' network. Previously, requests were
forwarded if the host's DNS server was running on a loopback address,
like systemd's 127.0.0.53. <a
href="https://redirect.github.com/moby/moby/pull/47589">moby/moby#47589</a></p>
</li>
<li>
<p>plugin: fix mounting /etc/hosts when running in UserNS. <a
href="https://redirect.github.com/moby/moby/pull/47588">moby/moby#47588</a></p>
</li>
<li>
<p>rootless: fix <code>open /etc/docker/plugins: permission
denied</code>. <a
href="https://redirect.github.com/moby/moby/pull/47587">moby/moby#47587</a></p>
</li>
<li>
<p>Fix multiple parallel <code>docker build</code> runs leaking disk
space. <a
href="https://redirect.github.com/moby/moby/pull/47527">moby/moby#47527</a></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b08a51fe16"><code>b08a51f</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/48231">#48231</a>
from austinvazquez/backport-vendor-otel-v0.46.1-to-...</li>
<li><a
href="d151b0f87f"><code>d151b0f</code></a>
vendor: OTEL v0.46.1 / v1.21.0</li>
<li><a
href="c6ba9a5124"><code>c6ba9a5</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/48225">#48225</a>
from austinvazquez/backport-workflow-artifact-reten...</li>
<li><a
href="4673a3ca2c"><code>4673a3c</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/48227">#48227</a>
from austinvazquez/backport-backport-branch-check-t...</li>
<li><a
href="30f8908102"><code>30f8908</code></a>
github/ci: Check if backport is opened against the expected branch</li>
<li><a
href="7454d6a2e6"><code>7454d6a</code></a>
ci: update workflow artifacts retention</li>
<li><a
href="65cc597cea"><code>65cc597</code></a>
Merge commit from fork</li>
<li><a
href="b722836927"><code>b722836</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/48199">#48199</a>
from austinvazquez/update-containerd-binary-to-1.7.20</li>
<li><a
href="e8ecb9c76d"><code>e8ecb9c</code></a>
update containerd binary to v1.7.20</li>
<li><a
href="e6cae1f237"><code>e6cae1f</code></a>
update containerd binary to v1.7.19</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/docker/compare/v24.0.9...v25.0.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/docker/docker&package-manager=go_modules&previous-version=24.0.9+incompatible&new-version=25.0.6+incompatible)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Till Faelligen <2353100+S7evinK@users.noreply.github.com>
2024-08-02 08:56:24 +02:00
Till a37d317958
Bump go to 1.21 (#3360) 2024-08-02 08:35:38 +02:00
Alex 9897959731
Fix: Edited messages appear twice in fulltext search (#3363)
As stated in https://github.com/matrix-org/dendrite/issues/3358 the
search response contains both original and edited message.
This PR fixes it by removing of the original message from the fulltext
index after indexing the edit message event.
I also made some cosmetic changes/fixes i found in the code

Signed-off-by: `Alexander Dubovikov <d.lexand@gmail.com>`
2024-07-27 22:30:17 +02:00
Till affb6977e4
Fix nil pointer derefernce issues (#3379)
Discovered while running
https://gitlab.futo.org/load-testing/matrix-goose.

Dendrite locks up and runs into `context cancelled`, so the error is not
`sql.ErrNoRows` nor "default" (and definitely shouldn't return that the
account exists in this case)
2024-07-27 22:29:34 +02:00
Till 795c4a9453
Fix media DB possibly leaking connections (#3372)
Grafana Pyroscope unveiled that we are hitting
ad10fbd3c4/src/database/sql/sql.go (L2739-L2742)
for media DB queries.

Making the methods pointer receivers fixes this.

(Also some minor `error` cosmetic updates)
2024-07-27 22:29:19 +02:00
Till a2e56dccb0
Don't bother hitting the DB if we got everything from cache (#3376)
Yet another finding where we hit the DB with a useless query. [skip ci]
2024-07-27 22:28:52 +02:00
dependabot[bot] 38549e649e
Bump rexml from 3.2.5 to 3.3.2 in /docs (#3398)
Bumps [rexml](https://github.com/ruby/rexml) from 3.2.5 to 3.3.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/rexml/releases">rexml's
releases</a>.</em></p>
<blockquote>
<h2>REXML 3.3.2 - 2024-07-16</h2>
<h3>Improvements</h3>
<ul>
<li>
<p>Improved parse performance.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/160">GH-160</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Improved parse performance.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/169">GH-169</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/170">GH-170</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/171">GH-171</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/172">GH-172</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/173">GH-173</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/174">GH-174</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/175">GH-175</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/176">GH-176</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/177">GH-177</a></li>
<li>Patch by Watson.</li>
</ul>
</li>
<li>
<p>Added support for raising a parse exception when an XML has extra
content after the root element.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/161">GH-161</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Added support for raising a parse exception when an XML
declaration exists in wrong position.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/162">GH-162</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Removed needless a space after XML declaration in pretty print
mode.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/164">GH-164</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Stopped to emit <code>:text</code> event after the root element.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/167">GH-167</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Fixed a bug that SAX2 parser doesn't expand predefined entities for
<code>characters</code> callback.
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/168">GH-168</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
</ul>
<h3>Thanks</h3>
<ul>
<li>
<p>NAITOH Jun</p>
</li>
<li>
<p>Watson</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/rexml/blob/master/NEWS.md">rexml's
changelog</a>.</em></p>
<blockquote>
<h2>3.3.2 - 2024-07-16 {#version-3-3-2}</h2>
<h3>Improvements</h3>
<ul>
<li>
<p>Improved parse performance.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/160">GH-160</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Improved parse performance.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/169">GH-169</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/170">GH-170</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/171">GH-171</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/172">GH-172</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/173">GH-173</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/174">GH-174</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/175">GH-175</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/176">GH-176</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/177">GH-177</a></li>
<li>Patch by Watson.</li>
</ul>
</li>
<li>
<p>Added support for raising a parse exception when an XML has extra
content after the root element.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/161">GH-161</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Added support for raising a parse exception when an XML
declaration exists in wrong position.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/162">GH-162</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Removed needless a space after XML declaration in pretty print
mode.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/164">GH-164</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
<li>
<p>Stopped to emit <code>:text</code> event after the root element.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/167">GH-167</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Fixed a bug that SAX2 parser doesn't expand predefined entities for
<code>characters</code> callback.
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/168">GH-168</a></li>
<li>Patch by NAITOH Jun.</li>
</ul>
</li>
</ul>
<h3>Thanks</h3>
<ul>
<li>
<p>NAITOH Jun</p>
</li>
<li>
<p>Watson</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2b285ac080"><code>2b285ac</code></a>
Add 3.3.2 entry</li>
<li><a
href="0e33d3adfb"><code>0e33d3a</code></a>
test: improve linear performance test names</li>
<li><a
href="910e5a2b48"><code>910e5a2</code></a>
Fix performance issue caused by using repeated <code>&gt;</code>
characters inside `&lt;xml&gt;&lt;!...</li>
<li><a
href="1f1e6e9b40"><code>1f1e6e9</code></a>
Fix ReDoS by using repeated space characters inside `&lt;!DOCTYPE name
[&lt;!ATTLIS...</li>
<li><a
href="1cc1d9a74e"><code>1cc1d9a</code></a>
Suppress have_root not initialized warnings on Ruby &lt; 3</li>
<li><a
href="67efb5951e"><code>67efb59</code></a>
Fix performance issue caused by using repeated <code>&gt;</code>
characters inside `&lt;!DOCTY...</li>
<li><a
href="a79ac8b4b4"><code>a79ac8b</code></a>
Fix performance issue caused by using repeated <code>&gt;</code>
characters inside `&lt;!DOCTY...</li>
<li><a
href="c33ea49810"><code>c33ea49</code></a>
Fix performance issue caused by using repeated <code>&gt;</code>
characters after ` &lt;!DOCTY...</li>
<li><a
href="9f1415a261"><code>9f1415a</code></a>
Fix performance issue caused by using repeated <code>&gt;</code>
characters inside `CDATA [...</li>
<li><a
href="c1b64c174e"><code>c1b64c1</code></a>
Fix performance issue caused by using repeated <code>&gt;</code>
characters inside comments...</li>
<li>Additional commits viewable in <a
href="https://github.com/ruby/rexml/compare/v3.2.5...v3.3.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rexml&package-manager=bundler&previous-version=3.2.5&new-version=3.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-27 21:33:38 +02:00
dependabot[bot] 7d8516838d
Bump golang.org/x/image from 0.10.0 to 0.18.0 (#3390)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.10.0
to 0.18.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3bbf4a659e"><code>3bbf4a6</code></a>
tiff: Validate palette indices when parsing palette-color images</li>
<li><a
href="6c5fa462eb"><code>6c5fa46</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="55c4ab6bd6"><code>55c4ab6</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="0057a939a5"><code>0057a93</code></a>
tiff: fix function name in comment</li>
<li><a
href="9e190ae4a3"><code>9e190ae</code></a>
webp: disallow multiple VP8X chunks</li>
<li><a
href="445ab0e75e"><code>445ab0e</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="240a51ac9f"><code>240a51a</code></a>
font/sfnt: support early version 0 OS/2 tables</li>
<li><a
href="c20bbc3713"><code>c20bbc3</code></a>
draw: simplify some calls to fmt.Fprintf</li>
<li><a
href="491771c681"><code>491771c</code></a>
draw: merge draw_go117.go into draw.go</li>
<li><a
href="4aa0222fac"><code>4aa0222</code></a>
go.mod: update go directive to 1.18</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/image/compare/v0.10.0...v0.18.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/image&package-manager=go_modules&previous-version=0.10.0&new-version=0.18.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-27 20:49:18 +02:00
dependabot[bot] b79bafb702
Bump ws from 7.5.2 to 7.5.10 in /test/wasm (#3388)
Bumps [ws](https://github.com/websockets/ws) from 7.5.2 to 7.5.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/websockets/ws/releases">ws's
releases</a>.</em></p>
<blockquote>
<h2>7.5.10</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported e55e5106 to the 7.x release line (22c28763).</li>
</ul>
<h2>7.5.9</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported bc8bd34e to the 7.x release line (0435e6e1).</li>
</ul>
<h2>7.5.8</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported 0fdcc0af to the 7.x release line (2758ed35).</li>
<li>Backported d68ba9e1 to the 7.x release line (dc1781bc).</li>
</ul>
<h2>7.5.7</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported 6946f5fe to the 7.x release line (1f72e2e1).</li>
</ul>
<h2>7.5.6</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported b8186dd1 to the 7.x release line (73dec34b).</li>
<li>Backported ed2b8039 to the 7.x release line (22a26afb).</li>
</ul>
<h2>7.5.5</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported ec9377ca to the 7.x release line (0e274acd).</li>
</ul>
<h2>7.5.4</h2>
<h1>Bug fixes</h1>
<ul>
<li>Backported 6a72da3e to the 7.x release line (76087fbf).</li>
<li>Backported 869c9892 to the 7.x release line (27997933).</li>
</ul>
<h2>7.5.3</h2>
<h1>Bug fixes</h1>
<ul>
<li>The <code>WebSocketServer</code> constructor now throws an error if
more than one of the
<code>noServer</code>, <code>server</code>, and <code>port</code>
options are specefied (66e58d27).</li>
<li>Fixed a bug where a <code>'close'</code> event was emitted by a
<code>WebSocketServer</code> before
the internal HTTP/S server was actually closed (5a587304).</li>
<li>Fixed a bug that allowed WebSocket connections to be established
after
<code>WebSocketServer.prototype.close()</code> was called
(772236a1).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d962d70649"><code>d962d70</code></a>
[dist] 7.5.10</li>
<li><a
href="22c2876323"><code>22c2876</code></a>
[security] Fix crash when the Upgrade header cannot be read (<a
href="https://redirect.github.com/websockets/ws/issues/2231">#2231</a>)</li>
<li><a
href="8a78f87706"><code>8a78f87</code></a>
[dist] 7.5.9</li>
<li><a
href="0435e6e12b"><code>0435e6e</code></a>
[security] Fix same host check for ws+unix: redirects</li>
<li><a
href="4271f07cfc"><code>4271f07</code></a>
[dist] 7.5.8</li>
<li><a
href="dc1781bc31"><code>dc1781b</code></a>
[security] Drop sensitive headers when following insecure redirects</li>
<li><a
href="2758ed3550"><code>2758ed3</code></a>
[fix] Abort the handshake if the Upgrade header is invalid</li>
<li><a
href="a370613fab"><code>a370613</code></a>
[dist] 7.5.7</li>
<li><a
href="1f72e2e14f"><code>1f72e2e</code></a>
[security] Drop sensitive headers when following redirects (<a
href="https://redirect.github.com/websockets/ws/issues/2013">#2013</a>)</li>
<li><a
href="8ecd890800"><code>8ecd890</code></a>
[dist] 7.5.6</li>
<li>Additional commits viewable in <a
href="https://github.com/websockets/ws/compare/7.5.2...7.5.10">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ws&package-manager=npm_and_yarn&previous-version=7.5.2&new-version=7.5.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-27 20:48:51 +02:00
Tulir Asokan 9566cc6359
Fix parsing ?ts query param (#3396)
Signed-off-by: Tulir Asokan <tulir@maunium.net>
2024-07-27 20:48:15 +02:00
Josh Simmons acfc36f697
add DCO (#3395)
The Matrix.org Foundation is rolling out this DCO across all public
repositories in its namespace. Of note, this DCO does not require the
use of "real" or "legally identifiable" names.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [X] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [X] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Josh Simmons <josh@foundation.matrix.org>`

Co-authored-by: Josh Simmons <git@josh.tel>
2024-07-25 15:24:35 +00:00
Richard van der Hoff 3e62b986d1
Blacklist sytests that require MSC3967 (#3384)
https://github.com/matrix-org/sytest/pull/1383 updates some sytests in
line with MSC3967. Dendrite does not support MSC3967, so these tests
fail.
2024-06-13 23:55:02 +00:00
0x1a8510f2 46902e5766
Take advantage of changes in recent Go versions (#3361)
Given that #2714 wasn't merged but we are now at a minimum supported Go
version of 1.20 (soon to be 1.21), I wanted to carry over some of the
changes. Namely:
- Fix the log typo
- Simplify build constraints for unix
- Use stdlib atomic package

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `0x1a8510f2 <admin@0x1a8510f2.space>`

---------

Co-authored-by: devonh <devon.dmytro@gmail.com>
2024-05-01 00:38:36 +00:00
dependabot[bot] 5547bf8ca6
Bump golang.org/x/net from 0.21.0 to 0.23.0 (#3365)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to
0.23.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="c48da13158"><code>c48da13</code></a>
http2: fix TestServerContinuationFlood flakes</li>
<li><a
href="762b58d1cf"><code>762b58d</code></a>
http2: fix tipos in comment</li>
<li><a
href="ba872109ef"><code>ba87210</code></a>
http2: close connections when receiving too many headers</li>
<li><a
href="ebc8168ac8"><code>ebc8168</code></a>
all: fix some typos</li>
<li><a
href="3678185f8a"><code>3678185</code></a>
http2: make TestCanonicalHeaderCacheGrowth faster</li>
<li><a
href="448c44f928"><code>448c44f</code></a>
http2: remove clientTester</li>
<li><a
href="c7877ac421"><code>c7877ac</code></a>
http2: convert the remaining clientTester tests to testClientConn</li>
<li><a
href="d8870b0bf2"><code>d8870b0</code></a>
http2: use synthetic time in TestIdleConnTimeout</li>
<li><a
href="d73acffdc9"><code>d73acff</code></a>
http2: only set up deadline when Server.IdleTimeout is positive</li>
<li><a
href="89f602b7bb"><code>89f602b</code></a>
http2: validate client/outgoing trailers</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/net/compare/v0.21.0...v0.23.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/net&package-manager=go_modules&previous-version=0.21.0&new-version=0.23.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-30 23:12:52 +00:00
Till 14a6c10097
Version 0.13.7 (#3349) 2024-04-09 10:24:27 +02:00
Till 5c0ceec2a6
Don't attempt to send transactions if Dendrite is shutting down (#3356)
This should avoid confusions with logs like:

```
time="2024-04-08T08:38:45.104235081Z" level=error msg="Failed to set \"scs.ems.host\" as assumed offline" func="github.com/matrix-org/dendrite/federationapi/statistics.(*ServerStatistics).Failure" file="github.com/matrix-org/dendrite/federationapi/statistics/statistics.go:204" error="sqlutil.WithTransaction.Begin: sql: database is closed"
time="2024-04-08T08:38:45.104239201Z" level=error msg="Failed to set \"obermui.de\" as assumed offline" func="github.com/matrix-org/dendrite/federationapi/statistics.(*ServerStatistics).Failure" file="github.com/matrix-org/dendrite/federationapi/statistics/statistics.go:204" error="sqlutil.WithTransaction.Begin: sql: database is closed"
```

or 

```
time="2024-04-08T08:38:45.105235411Z" level=error msg="Failed to get pending EDUs for \"retro76.net\"" func="github.com/matrix-org/dendrite/federationapi/queue.(*destinationQueue).getPendingFromDatabase" file="github.com/matrix-org/dendritefederationapi/queue/destinationqueue.go:258" error="sqlutil.WithTransaction.Begin: sql: database is closed"
```

[skip ci]
2024-04-09 07:49:56 +02:00
Till 8aa088f713
Return correct Content-Type for unrecognized requests (#3355)
Fixes #3354
2024-04-08 07:51:04 +02:00
Till b732eede27
Fix spaces over federation (#3347)
Fixes #2504

 A few issues with the previous iteration:
- We never returned `inaccessible_children`, which (if I read the code
correctly), made Synapse raise an error and thus not returning the
requested rooms
- For restricted rooms, we didn't return the list of allowed rooms
2024-03-28 20:40:45 +01:00
Till ad0a7d09e8
Add getting/deleting single event report (#3344)
Based on https://github.com/matrix-org/dendrite/pull/3342

Adds `GET /_synapse/admin/v1/event_reports/{reportID}` and `DELETE
/_synapse/admin/v1/event_reports/{reportID}`
2024-03-22 21:54:29 +00:00
Till 81f73c9f8d
Reuse existing NATS connection (#3345)
If using external NATS, we opened unnecessary connections. This now
re-uses existing connections.

[skip ci]
2024-03-22 22:33:23 +01:00
Till 79072c3dcd
Add /_synapse/admin/v1/event_reports endpoint (#3342)
Based on #3340 

This adds a `/_synapse/admin/v1/event_reports` endpoint, the same
Synapse has. This way existing tools also work with Dendrite.
Given this is already getting huge (even though many test lines),
splitting this into two PRs. (The next adds "getting one report" and
"deleting reports")

[skip ci]
2024-03-22 22:32:30 +01:00
dependabot[bot] 1bdf0cc541
Bump github.com/docker/docker from 24.0.7+incompatible to 24.0.9+incompatible (#3341)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from
24.0.7+incompatible to 24.0.9+incompatible.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/docker/releases">github.com/docker/docker's
releases</a>.</em></p>
<blockquote>
<h2>v24.0.9</h2>
<h2>24.0.9</h2>
<p>For a full list of pull requests and changes in this release, refer
to the relevant GitHub milestones:</p>
<ul>
<li><a
href="https://github.com/docker/cli/issues?q=is%3Aclosed+milestone%3A24.0.9">docker/cli,
24.0.9 milestone</a></li>
<li><a
href="https://github.com/moby/moby/issues?q=is%3Aclosed+milestone%3A24.0.9">moby/moby,
24.0.9 milestone</a></li>
</ul>
<h2>Security</h2>
<p>This release contains security fixes for the following CVEs affecting
Docker Engine and its components.</p>
<table>
<thead>
<tr>
<th>CVE</th>
<th>Component</th>
<th>Fix version</th>
<th>Severity</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://scout.docker.com/v/CVE-2024-21626">CVE-2024-21626</a></td>
<td>runc</td>
<td>1.1.12</td>
<td>High, CVSS 8.6</td>
</tr>
<tr>
<td><a
href="https://scout.docker.com/v/CVE-2024-24557">CVE-2024-24557</a></td>
<td>Docker Engine</td>
<td>24.0.9</td>
<td>Medium, CVSS 6.9</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>Important</strong> ⚠️</p>
<p>Note that this release of Docker Engine doesn't include fixes for the
following known vulnerabilities in BuildKit:</p>
<ul>
<li><a
href="https://scout.docker.com/v/CVE-2024-23651">CVE-2024-23651</a></li>
<li><a
href="https://scout.docker.com/v/CVE-2024-23652">CVE-2024-23652</a></li>
<li><a
href="https://scout.docker.com/v/CVE-2024-23653">CVE-2024-23653</a></li>
<li><a
href="https://scout.docker.com/v/CVE-2024-23650">CVE-2024-23650</a></li>
</ul>
<p>To address these vulnerabilities, upgrade to <a
href="https://github.com/docker/docker/blob/HEAD/25.0.md#2502">Docker
Engine v25.0.2</a>.</p>
</blockquote>
<p>For more information about the security issues addressed in this
release, and the unaddressed vulnerabilities in BuildKit, refer to the
<a
href="https://www.docker.com/blog/docker-security-advisory-multiple-vulnerabilities-in-runc-buildkit-and-moby/">blog
post</a>. For details about each vulnerability, see the relevant
security advisory:</p>
<ul>
<li><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv">CVE-2024-21626</a></li>
<li><a
href="https://github.com/moby/moby/security/advisories/GHSA-xw73-rw38-6vjc">CVE-2024-24557</a></li>
</ul>
<h3>Packaging updates</h3>
<ul>
<li>Upgrade runc to <a
href="https://github.com/opencontainers/runc/releases/tag/v1.1.12">v1.1.12</a>.
<a
href="https://redirect.github.com/moby/moby/pull/47269">moby/moby#47269</a></li>
<li>Upgrade containerd to <a
href="https://github.com/containerd/containerd/releases/tag/v1.7.13">v1.7.13</a>
(static binaries only). <a
href="https://redirect.github.com/moby/moby/pull/47280">moby/moby#47280</a></li>
</ul>
<h2>v24.0.8</h2>
<h2>24.0.8</h2>
<p>For a full list of pull requests and changes in this release, refer
to the relevant GitHub milestones:</p>
<ul>
<li><a
href="https://github.com/docker/cli/issues?q=is%3Aclosed+milestone%3A24.0.8">docker/cli,
24.0.8 milestone</a></li>
<li><a
href="https://github.com/moby/moby/issues?q=is%3Aclosed+milestone%3A24.0.8">moby/moby,
24.0.8 milestone</a></li>
</ul>
<h3>Bug fixes and enhancements</h3>
<ul>
<li>Live restore: Containers with auto remove (<code>docker run
--rm</code>) are no longer forcibly removed on engine restart. <a
href="https://redirect.github.com/moby/moby/pull/46869">moby/moby#46857</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fca702de7f"><code>fca702d</code></a>
Merge pull request from GHSA-xw73-rw38-6vjc</li>
<li><a
href="f78a7726d7"><code>f78a772</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/47281">#47281</a>
from thaJeztah/24.0_backport_bump_containerd_binary...</li>
<li><a
href="61afffeeb3"><code>61afffe</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/47270">#47270</a>
from thaJeztah/24.0_backport_bump_runc_binary_1.1.12</li>
<li><a
href="b38e74c4e0"><code>b38e74c</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/47276">#47276</a>
from thaJeztah/24.0_backport_bump_runc_1.1.12</li>
<li><a
href="dac56638ad"><code>dac5663</code></a>
update containerd binary to v1.7.13</li>
<li><a
href="20e1af3616"><code>20e1af3</code></a>
vendor: github.com/opencontainers/runc v1.1.12</li>
<li><a
href="858919d399"><code>858919d</code></a>
update runc binary to v1.1.12</li>
<li><a
href="141ad39e38"><code>141ad39</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/47266">#47266</a>
from vvoland/ci-fix-makeps1-templatefail-24</li>
<li><a
href="db968c672b"><code>db968c6</code></a>
hack/make.ps1: Fix go list pattern</li>
<li><a
href="61c51fbb5a"><code>61c51fb</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/47221">#47221</a>
from vvoland/pkg-pools-close-noop-24</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/docker/compare/v24.0.7...v24.0.9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/docker/docker&package-manager=go_modules&previous-version=24.0.7+incompatible&new-version=24.0.9+incompatible)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-22 22:30:28 +01:00
dependabot[bot] a00b976a00
Bump google.golang.org/protobuf from 1.30.0 to 1.33.0 (#3339)
Bumps google.golang.org/protobuf from 1.30.0 to 1.33.0.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/protobuf&package-manager=go_modules&previous-version=1.30.0&new-version=1.33.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-22 22:29:53 +01:00
Till b9abbf7b20
Add event reporting (#3340)
Part of #3216 and #3226 

There will be a follow up PR which is going to add the same admin
endpoints Synapse has, so existing tools also work for Dendrite.
2024-03-21 19:27:34 +01:00
Till de95499178
Update golangci config (#3343)
`deadline` is now deprecated in favor of `timeout` and currently breaks
CI.
The other changes remove some warnings produced.
2024-03-21 10:24:53 +01:00
Till 928c8c8c4a
Query rooms with ACLs instead of all rooms (#3338)
This now should actually speed up startup times.
This is because _many_ rooms (like DMs) don't have room ACLs, this means
that we had around 95% pointless DB queries. (as queried on d.m.org)
2024-03-05 20:41:35 +01:00
Till Faelligen 09f15a3d3f
[Helm] Update Postgres image to 16.2.0, update readme 2024-02-29 08:58:25 +01:00
Varac ad3a3e7bed
[helm] Update postgresql chart to 14.2.3 (#3292)
This change introduces a major Postgresql upgrade
(from 15.1.0 to 16.1.0).

From

https://artifacthub.io/packages/helm/bitnami/postgresql/13.2.24#to-13-0-0:

This major version changes the default PostgreSQL image from 15.x to
16.x. Follow the [official
instructions](https://www.postgresql.org/docs/15/upgrading.html) to
upgrade to 16.x.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

This PR doesn't need a Go unit tests since it doesn't touch any code,
only the helm chart is affected.

Signed-off-by: Varac Anero <varac@varac.net>

---------

Signed-off-by: Varac Anero <varac@varac.net>
Co-authored-by: Till Faelligen <2353100+S7evinK@users.noreply.github.com>

[skip ci]
2024-02-29 08:46:40 +01:00
Alexandre Oliveira 66865597e2
Use port number instead of name for k8s service port (#3256)
I've found an issue when deploying Dendrite's Helm chart on my local
cluster. The template for generating an Ingress resource tries to find
the service port using a name (`http`), but the template that generates
the Service resource, instead, identifies the resource with a port
number.

According to the [Kubernetes
ServiceSpec](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/),
`ports.targetPort` can be either a number or a string; if it's the
latter, it will be looked up as a named port in the pod's container
ports.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

[skip ci]
2024-02-29 08:13:59 +01:00
WrenIX 4452833099
chore(helm): use empty/nil storageClass for helm-docs (#3245)
i believe that `nil` would be false in the if :
```yaml
storageClass:
```
is still handled correct.

---
In past ( #3191 ), will have the problem with an empty string `""`:
```yaml
storageClass: ""
```

---
do you take another look @S7evinK ?

Signed-off-by: WrenIX <dev.github@wrenix.eu>
2024-02-29 08:04:40 +01:00
WrenIX 4892b08dd5
fix(helm): change strategy to Recreate (#3325)
Current dendrite needs an PVC and replica of 1 is forced, so best way of
update and change of configuration is to stop and start (instatt of
start multiple dendrite pod with deadlock of binding pvc)

see: #3258

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

 Signed-off-by: `Your Name <your@email.example.org>`
 - [x] version bump of helm Chart

Signed-off-by: WrenIX <dev.github@wrenix.eu>

[skip ci]
2024-02-28 21:20:41 +01:00
dependabot[bot] 58bc289a37
Bump nokogiri from 1.14.3 to 1.16.2 in /docs (#3319)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.14.3
to 1.16.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sparklemotion/nokogiri/releases">nokogiri's
releases</a>.</em></p>
<blockquote>
<h2>v1.16.2 / 2024-02-04</h2>
<h3>Security</h3>
<ul>
<li>[CRuby] Vendored libxml2 is updated to address CVE-2024-25062. See
<a
href="https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j">GHSA-xc9x-jj77-9p9j</a>
for more information.</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>[CRuby] Vendored libxml2 is updated to <a
href="https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.5">v2.12.5</a>
from v2.12.4. (<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
</ul>
<hr />
<p>sha256 checksums:</p>

<pre><code>69ba15d2a2498324489ed63850997f0b8f684260114ea81116d3082f16551d2d
nokogiri-1.16.2-aarch64-linux.gem
6a05ce42e3587a40cf8936ece0beaa5d32922254215d2e8cf9ad40588bb42e57
nokogiri-1.16.2-arm-linux.gem
c957226c8e36b31be6a3afb8602e2128282bf8b40ea51016c4cd21aa2608d3f8
nokogiri-1.16.2-arm64-darwin.gem
122652bfc338cd8a54a692ac035e245e41fd3b8283299202ca26e7a7d50db310
nokogiri-1.16.2-java.gem
7344b5072ca69fc5bedb61cb01a3b765b93a27aae5a2a845c2ba7200e4345074
nokogiri-1.16.2-x64-mingw-ucrt.gem
a2a5e184a424111a0d5b77947986484920ad708009c667f061e8d02035c562dd
nokogiri-1.16.2-x64-mingw32.gem
833efddeb51a6c2c9f6356295623c2b2e0d50050d468695c59bd929162953323
nokogiri-1.16.2-x86-linux.gem
e67fc0418dffaff9dc8b1dc65f0605282c3fee9488832d0223b620b4319e0b53
nokogiri-1.16.2-x86-mingw32.gem
5def799e5f139f21a79d7cf71172313a7b6fb0e4b2a31ab9bd5d4ad305994539
nokogiri-1.16.2-x86_64-darwin.gem
5b146240ac6ec6c40fd4367623e74442bca45a542bd3282b1d4d18b07b8e5dfe
nokogiri-1.16.2-x86_64-linux.gem
68922ee5cde27497d995c46f2821957bae961947644eed2822d173daf7567f9c
nokogiri-1.16.2.gem
</code></pre>
<h2>v1.16.1 / 2024-02-03</h2>
<h3>Dependencies</h3>
<ul>
<li>[CRuby] Vendored libxml2 is updated to <a
href="https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.4">v2.12.4</a>
from v2.12.3. (<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>[CRuby] <code>XML::Reader</code> defaults the encoding to UTF-8 if
it's not specified in either the document or as a method parameter.
Previously non-ASCII characters were serialized as NCRs in this case. <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/2891">#2891</a>
(<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
<li>[CRuby] Restored support for compilation by GCC versions earlier
than 4.6, which was broken in v1.15.0 (540e9aee). <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3090">#3090</a>
(<a
href="https://github.com/adfoster-r7"><code>@​adfoster-r7</code></a>)</li>
<li>[CRuby] Patched upstream libxml2 to allow parsing HTML5 in the
context of a namespaced node (e.g., foreign content like MathML).
[#3112, <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3116">#3116</a>]
(<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
<li>[CRuby] Fixed a small memory leak in libgumbo (HTML5 parser) when
the maximum tree depth limit is hit. [#3098, <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3100">#3100</a>]
(<a
href="https://github.com/stevecheckoway"><code>@​stevecheckoway</code></a>)</li>
</ul>
<hr />
<p>sha256 checksums:</p>

<pre><code>a541f35e5b9798a0c97300f9ee18f4217da2a2945a6d5499e4123b9018f9cafc
nokogiri-1.16.1-aarch64-linux.gem
6b82affd195000ab2f9c36cc08744ec2d2fcf6d8da88d59a2db67e83211f7c69
nokogiri-1.16.1-arm-linux.gem
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md">nokogiri's
changelog</a>.</em></p>
<blockquote>
<h2>v1.16.2 / 2024-02-04</h2>
<h3>Security</h3>
<ul>
<li>[CRuby] Vendored libxml2 is updated to address CVE-2024-25062. See
<a
href="https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j">GHSA-xc9x-jj77-9p9j</a>
for more information.</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>[CRuby] Vendored libxml2 is updated to <a
href="https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.5">v2.12.5</a>
from v2.12.4. (<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
</ul>
<h2>v1.16.1 / 2024-02-03</h2>
<h3>Dependencies</h3>
<ul>
<li>[CRuby] Vendored libxml2 is updated to <a
href="https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.4">v2.12.4</a>
from v2.12.3. (<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>[CRuby] <code>XML::Reader</code> defaults the encoding to UTF-8 if
it's not specified in either the document or as a method parameter.
Previously non-ASCII characters were serialized as NCRs in this case. <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/2891">#2891</a>
(<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
<li>[CRuby] Restored support for compilation by GCC versions earlier
than 4.6, which was broken in v1.15.0 (540e9aee). <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3090">#3090</a>
(<a
href="https://github.com/adfoster-r7"><code>@​adfoster-r7</code></a>)</li>
<li>[CRuby] Patched upstream libxml2 to allow parsing HTML5 in the
context of a namespaced node (e.g., foreign content like MathML).
[#3112, <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3116">#3116</a>]
(<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</li>
<li>[CRuby] Fixed a small memory leak in libgumbo (HTML5 parser) when
the maximum tree depth limit is hit. [#3098, <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3100">#3100</a>]
(<a
href="https://github.com/stevecheckoway"><code>@​stevecheckoway</code></a>)</li>
</ul>
<h2>v1.16.0 / 2023-12-27</h2>
<h3>Notable Changes</h3>
<h4>Ruby</h4>
<p>This release introduces native gem support for Ruby 3.3.</p>
<p>This release ends support for Ruby 2.7, for which <a
href="https://www.ruby-lang.org/en/downloads/branches/">upstream support
ended 2023-03-31</a>.</p>
<h4>Pattern matching</h4>
<p>This version marks <em>official support</em> for the pattern matching
API in <code>XML::Attr</code>, <code>XML::Document</code>,
<code>XML::DocumentFragment</code>, <code>XML::Namespace</code>,
<code>XML::Node</code>, and <code>XML::NodeSet</code> (and their
subclasses), originally introduced as an experimental feature in
v1.14.0. (<a
href="https://github.com/flavorjones"><code>@​flavorjones</code></a>)</p>
<p>Documentation on what can be matched:</p>
<ul>
<li><a
href="https://nokogiri.org/rdoc/Nokogiri/XML/Attr.html?h=deconstruct#method-i-deconstruct_keys"><code>XML::Attr#deconstruct_keys</code></a></li>
<li><a
href="https://nokogiri.org/rdoc/Nokogiri/XML/Document.html?h=deconstruct#method-i-deconstruct_keys"><code>XML::Document#deconstruct_keys</code></a></li>
<li><a
href="https://nokogiri.org/rdoc/Nokogiri/XML/Namespace.html?h=deconstruct+namespace#method-i-deconstruct_keys"><code>XML::Namespace#deconstruct_keys</code></a></li>
<li><a
href="https://nokogiri.org/rdoc/Nokogiri/XML/Node.html?h=deconstruct#method-i-deconstruct_keys"><code>XML::Node#deconstruct_keys</code></a></li>
<li><a
href="https://nokogiri.org/rdoc/Nokogiri/XML/DocumentFragment.html?h=deconstruct#method-i-deconstruct"><code>XML::DocumentFragment#deconstruct</code></a></li>
<li><a
href="https://nokogiri.org/rdoc/Nokogiri/XML/NodeSet.html?h=deconstruct#method-i-deconstruct"><code>XML::NodeSet#deconstruct</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="673756fdd6"><code>673756f</code></a>
version bump to v1.16.2</li>
<li><a
href="74ffd67a8e"><code>74ffd67</code></a>
dep: update libxml to 2.12.5 (branch v1.16.x) (<a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3122">#3122</a>)</li>
<li><a
href="0d4018dc70"><code>0d4018d</code></a>
dep: update libxml2 to v2.12.5</li>
<li><a
href="f33a25f437"><code>f33a25f</code></a>
dep: remove patch from <a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3112">#3112</a>
which has been released upstream</li>
<li><a
href="e99416896a"><code>e994168</code></a>
version bump to v1.16.1</li>
<li><a
href="77ea2f228c"><code>77ea2f2</code></a>
dev: add files to manifest ignore list</li>
<li><a
href="756f27c6b7"><code>756f27c</code></a>
build(deps): bump actions/{download,upload}-artifact from 3 to 4</li>
<li><a
href="464f8d41eb"><code>464f8d4</code></a>
.gitignore: clangd-related files</li>
<li><a
href="2beeb96069"><code>2beeb96</code></a>
doc: update CHANGELOG</li>
<li><a
href="a26536d7a4"><code>a26536d</code></a>
fix: apply upstream patch for in-context parsing (<a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3116">#3116</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/sparklemotion/nokogiri/compare/v1.14.3...v1.16.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nokogiri&package-manager=bundler&previous-version=1.14.3&new-version=1.16.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

[skip ci]
2024-02-28 21:03:35 +01:00
Anton Molyboha e4a579f10f
FAQ.md: jetstream needs to be backed up too. (#3327)
In the section "What data needs to be kept if transferring/backing up
Dendrite?" of the FAQ, add jetstream directory to the list.

It seems to be a common mistake when moving dendrite to a different
computer, that the jetstream directory is not copied.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [ ] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Anton Molyboha <anton.molyboha@gmail.com>`
2024-02-28 21:02:25 +01:00
Till 865fff5f03
Make usage of relays optional, avoid DB roundtrips (#3337)
This should avoid 2 additional DB roundtrips if we don't want to use
relays.

So instead of possibly doing roughly 20k trips to the DB, we are now
"only" doing ~6600.

---------

Co-authored-by: devonh <devon.dmytro@gmail.com>
2024-02-28 20:59:34 +01:00
Till 4ccf6d6f67
Cache ACLs regexes (#3336)
Since #3334 didn't change much on d.m.org, this is another attempt to
speed up startup.

Given moderation bots like Mjolnir/Draupnir are in many rooms with quite
often the same or similar ACLs, caching the compiled regexes _should_
reduce the startup time.

Using a pointer to the `*regexp.Regex` ensures we only store _one_
instance of a regex in memory, instead of potentially storing it hundred
of times. This should reduce memory consumption on servers with many
rooms with ACLs drastically. (5.1MB vs 1.7MB with this change on my
server with 8 ACL'd rooms [3 using the same ACLs])

[skip ci]
2024-02-28 20:58:56 +01:00
Till f4e77453cb
Speed up start up time by batch querying ACL events (#3334)
This should significantly speed up start up times on servers with many
rooms.
2024-02-21 14:10:22 +01:00
Till 8f944f6434
Limit filter to limit/2 for before/after events on /context (#3332)
Part of https://github.com/matrix-org/dendrite/issues/3224
2024-02-20 07:38:51 +00:00
Till ecb7b383e9
Remove unused token (#3331)
Part of https://github.com/matrix-org/dendrite/issues/3225
2024-02-19 19:19:06 +00:00
Till e9deb5244e
Fix /createRoom and /invite containing displayname/avatarURL of inviter (#3326)
Fixes #3324
2024-02-13 19:28:52 +01:00
Till be0c27e688
Update all the CI actions (#3323)
Also adds a job for the scheduled CI run to only run if there has been a
commit in the last 24h
([StackOverflow](https://stackoverflow.com/questions/63014786/how-to-schedule-a-github-actions-nightly-build-but-run-it-only-when-there-where))

[skip ci]
2024-02-08 09:58:59 +01:00
Till Faelligen 436773ab71
Disable Element Web tests, only run csapi and federation tests 2024-02-07 10:28:10 +01:00
Tulir Asokan 0f6b81f456
Modernize appservice paths and authentication (#3316)
This brings Dendrite's appservice spec support up to v1.4, from the
previous level of pre-release-spec support only (even r0.1.0 wasn't
supported for pushing transactions 🙃). There are config options to
revert to the old behavior, but the default is v1.4+ only. [Synapse also
does
that](https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html#use_appservice_legacy_authorization)

mautrix bridges will drop support for legacy paths and authentication
soon (and possibly also require matrix v1.4 to be advertised, but I
might add some workaround to not require that for dendrite)

Signed-off-by: Tulir Asokan <tulir@maunium.net>
2024-02-03 18:56:13 +01:00
Till a3a18fbcce
Fix x86 tests (#3317)
x86 tests broke with #3298
(Not exactly the tests modified here, but
`TestMessageHistoryVisibility`)
2024-01-29 20:44:43 +01:00
Till 87f028db27
Version 0.13.6 (#3315) 2024-01-26 14:41:34 +01:00
Till 8f68f1ff53
Move /joined_members back to the clientapi/roomserver (#3312)
Partly reverts #2827 by moving `/joined_members` back to the
clientAPI/roomserver
2024-01-25 21:35:05 +01:00
Matthew Strapp a4817f31c0
Allow + in MIDs as per MSC4009 (#3313)
This PR adds `+` to the username regex, per MSC4009.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Matt Strapp <matt@mattstrapp.net>`
2024-01-25 21:17:20 +01:00
Joakim Recht 00217a69d1
Only fetch events once for all rooms (#3311)
This refactors `PDUStreamProvider` a bit so that it doesn't trigger a
database query per room, but instead utilizes the fact that it's
possible to bulk query. This improves sync performance significantly
when you have 1000s of rooms.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Joakim Recht <joakim@beyondwork.ai>`
2024-01-25 20:10:46 +01:00
Till d58daf9665
Update sentry reporting (#3305)
This hopefully reduces the garbage we currently produce.
(Using [GlitchTip](https://glitchtip.com/) on my personal instance, this
seems to look better)
2024-01-24 19:24:04 +01:00
Till 8e4dc6b4ae
Optimize PrevEventIDs when getting thousands of backwards extremeties (#3308)
Changes how many `PrevEventIDs` we send to other servers when
backfilling, capped to 100 events.

Unsure about how representative this benchmark is..
```
goos: linux
goarch: amd64
pkg: github.com/matrix-org/dendrite/roomserver/api
cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
                            │    old.txt     │               new.txt               │
                            │     sec/op     │   sec/op     vs base                │
PrevEventIDs/Original1-8         264.9n ± 5%   237.4n ± 7%  -10.36% (p=0.000 n=10)
PrevEventIDs/Original10-8        3.101µ ± 4%   1.590µ ± 2%  -48.72% (p=0.000 n=10)
PrevEventIDs/Original100-8       44.32µ ± 2%   12.80µ ± 4%  -71.11% (p=0.000 n=10)
PrevEventIDs/Original500-8     263.835µ ± 4%   7.907µ ± 4%  -97.00% (p=0.000 n=10)
PrevEventIDs/Original1000-8    578.798µ ± 2%   7.620µ ± 2%  -98.68% (p=0.000 n=10)
PrevEventIDs/Original2000-8   1272.039µ ± 2%   8.241µ ± 9%  -99.35% (p=0.000 n=10)
geomean                          43.81µ        3.659µ       -91.65%

                            │    old.txt     │               new.txt                │
                            │      B/op      │     B/op      vs base                │
PrevEventIDs/Original1-8          72.00 ± 0%     48.00 ± 0%  -33.33% (p=0.000 n=10)
PrevEventIDs/Original10-8        1512.0 ± 0%     500.0 ± 0%  -66.93% (p=0.000 n=10)
PrevEventIDs/Original100-8     11.977Ki ± 0%   7.023Ki ± 0%  -41.36% (p=0.000 n=10)
PrevEventIDs/Original500-8     67.227Ki ± 0%   7.023Ki ± 0%  -89.55% (p=0.000 n=10)
PrevEventIDs/Original1000-8   163.227Ki ± 0%   7.023Ki ± 0%  -95.70% (p=0.000 n=10)
PrevEventIDs/Original2000-8   347.227Ki ± 0%   7.023Ki ± 0%  -97.98% (p=0.000 n=10)
geomean                         12.96Ki        1.954Ki       -84.92%

                            │   old.txt   │              new.txt               │
                            │  allocs/op  │ allocs/op   vs base                │
PrevEventIDs/Original1-8       2.000 ± 0%   1.000 ± 0%  -50.00% (p=0.000 n=10)
PrevEventIDs/Original10-8      6.000 ± 0%   2.000 ± 0%  -66.67% (p=0.000 n=10)
PrevEventIDs/Original100-8     9.000 ± 0%   3.000 ± 0%  -66.67% (p=0.000 n=10)
PrevEventIDs/Original500-8    12.000 ± 0%   3.000 ± 0%  -75.00% (p=0.000 n=10)
PrevEventIDs/Original1000-8   14.000 ± 0%   3.000 ± 0%  -78.57% (p=0.000 n=10)
PrevEventIDs/Original2000-8   16.000 ± 0%   3.000 ± 0%  -81.25% (p=0.000 n=10)
geomean                        8.137        2.335       -71.31%
```
2024-01-20 22:26:57 +01:00
Till d357615452
Don't send device list updates upon registration (#3307)
Fixes https://github.com/matrix-org/dendrite/issues/3273

As we otherwise send down device list updates which are merely useful
for the user and causes tests to be flakey:

```
 TestPushSync/Adding_a_push_rule_wakes_up_an_incremental_/sync (10ms)
      push_test.go:57: no pushrules found in sync response: {"next_batch":"s0_0_0_0_0_1_1_0_1","device_lists":{"changed":["@user-1:hs1"]}}
```

What this does: If a `PerformDeviceCreation` request is coming from
registering an account, it does **not** send device list updates, as
they are merely useful (no joined rooms, no one to inform) . In all
other cases, the behavior is unchanged and device list updates are sent
as usual.
2024-01-20 21:20:37 +01:00
Till bebf701dce
Add login fallback (#3302)
Part of https://github.com/matrix-org/dendrite/issues/3216

The files are basically copied from Synapse, with minor changes to the
called endpoints. We never seem to have had the
`/_matrix/static/client/login/` endpoint, this adds it.
2024-01-17 17:08:57 +01:00
Till dae1ef2e46
Update GMSL (#3303)
If I didn't miss anything, this should add fixes from:
https://github.com/matrix-org/gomatrixserverlib/pull/424
https://github.com/matrix-org/gomatrixserverlib/pull/426
https://github.com/matrix-org/gomatrixserverlib/pull/427
https://github.com/matrix-org/gomatrixserverlib/pull/428
https://github.com/matrix-org/gomatrixserverlib/pull/429
https://github.com/matrix-org/gomatrixserverlib/pull/430
2024-01-15 20:12:34 +00:00
dependabot[bot] 3a4b5f49ac
Bump github.com/quic-go/quic-go from 0.37.4 to 0.37.7 (#3300)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go)
from 0.37.4 to 0.37.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/quic-go/quic-go/releases">github.com/quic-go/quic-go's
releases</a>.</em></p>
<blockquote>
<h2>v0.37.7</h2>
<p>This release contains fixes for the Honeybadger vulnerability
(CVE-2023-49295):</p>
<ul>
<li>limit the number of queued PATH_RESPONSE frames to 256 (<a
href="https://redirect.github.com/quic-go/quic-go/issues/4199">#4199</a>)</li>
<li>don't retransmit PATH_CHALLENGE and PATH_RESPONSE frames (<a
href="https://redirect.github.com/quic-go/quic-go/issues/4200">#4200</a>)</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/quic-go/quic-go/compare/v0.37.6...v0.37.7">https://github.com/quic-go/quic-go/compare/v0.37.6...v0.37.7</a></p>
<h2>v0.37.6</h2>
<p>This patch release contains a backport of <a
href="https://redirect.github.com/quic-go/quic-go/pull/4038">quic-go/quic-go#4038</a>.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/quic-go/quic-go/compare/v0.37.5...v0.37.6">https://github.com/quic-go/quic-go/compare/v0.37.5...v0.37.6</a></p>
<h2>v0.37.5</h2>
<p>This patch release contains the backport of 3 fixes:</p>
<ul>
<li>fix handshake failure if <code>tls.Config.SessionTicketDisabled =
false</code>, but <code>tls.Config.GetConfigForClient</code> returns a
config that disables session tickets: <a
href="https://redirect.github.com/quic-go/quic-go/issues/4030">#4030</a></li>
<li>use the correct hash function for TLS_AES_256_GCM_SHA384: <a
href="https://redirect.github.com/quic-go/quic-go/issues/4031">#4031</a></li>
<li>automatically set the <code>tls.Config.ServerName</code>: <a
href="https://redirect.github.com/quic-go/quic-go/issues/4032">#4032</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/quic-go/quic-go/compare/v0.37.4...v0.37.5">https://github.com/quic-go/quic-go/compare/v0.37.4...v0.37.5</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="21609ddfef"><code>21609dd</code></a>
don't retransmit PATH_CHALLENGE and PATH_RESPONSE frames (<a
href="https://redirect.github.com/quic-go/quic-go/issues/4200">#4200</a>)</li>
<li><a
href="d7aa627ebd"><code>d7aa627</code></a>
limit the number of queued PATH_RESPONSE frames to 256 (<a
href="https://redirect.github.com/quic-go/quic-go/issues/4199">#4199</a>)</li>
<li><a
href="e2c360ceec"><code>e2c360c</code></a>
reassemble post-handshake TLS messages before passing them to crypto/tls
(<a
href="https://redirect.github.com/quic-go/quic-go/issues/4038">#4038</a>)</li>
<li><a
href="e9f7f460bc"><code>e9f7f46</code></a>
automatically set the tls.Config.ServerName if unset (<a
href="https://redirect.github.com/quic-go/quic-go/issues/4032">#4032</a>)</li>
<li><a
href="12d84c4196"><code>12d84c4</code></a>
handshake: use the correct hash function for TLS_AES_256_GCM_SHA384 (<a
href="https://redirect.github.com/quic-go/quic-go/issues/4031">#4031</a>)</li>
<li><a
href="b1635df2f5"><code>b1635df</code></a>
ignore QUICConn.SendSessionTicket error if session tickets are disabled
(<a
href="https://redirect.github.com/quic-go/quic-go/issues/4030">#4030</a>)</li>
<li>See full diff in <a
href="https://github.com/quic-go/quic-go/compare/v0.37.4...v0.37.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/quic-go/quic-go&package-manager=go_modules&previous-version=0.37.4&new-version=0.37.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-10 18:55:35 +01:00
Till e34242008b
Add CORP header to /download and /thumbnail (#3299)
Part of #3222 

https://github.com/matrix-org/matrix-spec-proposals/pull/3828
2024-01-10 09:39:13 +01:00
devonh 57646d5b86
Handle empty from in /messages as per MSC3567 (#3298) 2024-01-09 19:06:02 +00:00
Till 9510fa00cc
Return M_INVALID_PARAM instead of M_BAD_JSON when setting aliases (#3297)
Part of https://github.com/matrix-org/dendrite/issues/3223
(https://github.com/matrix-org/matrix-spec/pull/1286)

(For `DELETE` we don't validate the alias, but just return a 404 if we
can't find it)
2024-01-09 20:05:45 +01:00
Till 13c5173273
Fix notary keys requests for all keys (#3296)
This should be more spec compliant:
> If no key IDs are given to be queried, the notary server should query
for all keys.
2024-01-08 19:14:29 +01:00
Till edd02ec468
Fix panic if unable to assign a state key NID (#3294) 2023-12-30 18:34:36 +01:00
dependabot[bot] 9a5a56718e
Bump golang.org/x/crypto from 0.14.0 to 0.17.0 (#3290)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from
0.14.0 to 0.17.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9d2ee975ef"><code>9d2ee97</code></a>
ssh: implement strict KEX protocol changes</li>
<li><a
href="4e5a26183e"><code>4e5a261</code></a>
ssh: close net.Conn on all NewServerConn errors</li>
<li><a
href="152cdb1503"><code>152cdb1</code></a>
x509roots/fallback: update bundle</li>
<li><a
href="fdfe1f8531"><code>fdfe1f8</code></a>
ssh: defer channel window adjustment</li>
<li><a
href="b8ffc16e10"><code>b8ffc16</code></a>
blake2b: drop Go 1.6, Go 1.8 compatibility</li>
<li><a
href="7e6fbd82c8"><code>7e6fbd8</code></a>
ssh: wrap errors from client handshake</li>
<li><a
href="bda2f3f5cf"><code>bda2f3f</code></a>
argon2: avoid clobbering BP</li>
<li><a
href="325b735346"><code>325b735</code></a>
ssh/test: skip TestSSHCLIAuth on Windows</li>
<li><a
href="1eadac50a5"><code>1eadac5</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="b2d7c26edb"><code>b2d7c26</code></a>
ssh: add (*Client).DialContext method</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/crypto/compare/v0.14.0...v0.17.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/crypto&package-manager=go_modules&previous-version=0.14.0&new-version=0.17.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-19 08:39:22 +01:00
Till f93d1c4790
Use AckExplicitPolicy instead of AckAllPolicy (#3288)
Fixes https://github.com/matrix-org/dendrite/issues/3240 and potentially
a root cause for state resets.

While testing, I've had added some more debug logging:
```
time="2023-12-16T18:13:11.319458084Z" level=warning msg="already processed event" event_id="$qFYMl_F2vb1N0yxmvlFAMhqhGhLKq4kA-o_YCQKH7tQ" kind=KindNew times=2
time="2023-12-16T18:13:14.537389126Z" level=warning msg="already processed event" event_id="$EU-LTsKErT6Mt1k12-p_3xOHfiLaK6gtwVDlZ35lSuo" kind=KindNew times=5
time="2023-12-16T18:13:16.789551206Z" level=warning msg="already processed event" event_id="$dIPuAfTL5x0VyG873LKPslQeljCSxFT1WKxUtjIMUGE" kind=KindNew times=5
time="2023-12-16T18:13:17.383838767Z" level=warning msg="already processed event" event_id="$7noSZiCkzerpkz_UBO3iatpRnaOiPx-3IXc0GPDQVGE" kind=KindNew times=2
time="2023-12-16T18:13:22.091946597Z" level=warning msg="already processed event" event_id="$3Lvo3Wbi2ol9-nNbQ93N-E2MuGQCJZo5397KkFH-W6E" kind=KindNew times=1
time="2023-12-16T18:13:23.026417446Z" level=warning msg="already processed event" event_id="$lj1xS46zsLBCChhKOLJEG-bu7z-_pq9i_Y2DUIjzGy4" kind=KindNew times=4
```

So we did receive the same event over and over again. Given they are
`KindNew`, we don't short circuit if we already processed them, which
potentially caused the state to be calculated with a now wrong state
snapshot.

Also fixes the back pressure metric. We now correctly increment the
counter once we sent the message to NATS and decrement it once we
actually processed an event.
2023-12-19 08:25:47 +01:00
Till Faelligen d65449c782
Also pin Pinecone and Yggdrasil demo 2023-12-12 17:31:36 +01:00
Till b7054f4274
Version 0.13.5 (#3285) 2023-12-12 16:55:03 +01:00
Till 1555b3542d
Introduce a new stream for the appservice consumer (#3277)
This introduces a new stream the syncAPI produces to once it processed a
`OutputRoomEvent` and the appservices consumes.
This is to work around a race condition where appservices receive an
event before the syncAPI has handled it, this can result in e.g. calls
to `/joined_members` returning a wrong membership list.
2023-12-12 12:13:55 +01:00
Till 185ad6b00d
Allow some content types to be inlined (#3274)
"Shamelessly" stolen from
https://github.com/matrix-org/synapse/pull/15988
2023-12-12 11:15:50 +01:00
Joseph Alvarenga Beech fd11e65a9d
added a warning log , for well_known_server_name,well_known_server_name when they dont have prefix (#3205)
closing this https://github.com/matrix-org/dendrite/issues/3180

added a warning log when either well_known_server_name,
well_known_server_name: dont have a prefix in them

josephalvarengabeech@pm.me

---------

Co-authored-by: Till Faelligen <2353100+S7evinK@users.noreply.github.com>
2023-11-25 22:19:22 +01:00
Cat 61e5dc47d7
Added Docker commands for Windows (#3267)
### Pull Request Checklist

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

No tests were added due to it being a small documentation addition

Signed-off-by: `Cat Catry <denperidge@gmail.com>`
2023-11-25 20:24:13 +01:00
Till Faelligen 210bce9938
Update GMSL to avoid logging unnecessary messages 2023-11-25 19:12:21 +01:00
KuhnChris 4f943771fa
Appservice Login (2nd attempt) (#3078)
Rebase of #2936 as @vijfhoek wrote he got no time to work on this, and I
kind of needed it for my experiments.
I checked the tests, and it is working with my example code (i.e.
impersonating, registering, creating channel, invite people, write
messages).
I'm not a huge `go` pro, and still learning, but I tried to fix and/or
integrate the changes as best as possible with the current `main` branch
changes.
If there is anything left, let me know and I'll try to figure it out.

Signed-off-by: `Kuhn Christopher <kuhnchris+git@kuhnchris.eu>`

---------

Signed-off-by: Sijmen <me@sijman.nl>
Signed-off-by: Sijmen Schoon <me@sijman.nl>
Co-authored-by: Sijmen Schoon <me@sijman.nl>
Co-authored-by: Sijmen Schoon <me@vijf.life>
Co-authored-by: Till <2353100+S7evinK@users.noreply.github.com>
2023-11-24 22:34:13 +01:00
Till b8f91485b4
Update ACLs when received as outliers (#3008)
This should fix #3004 by making sure we also update our in-memory ACLs
after joining a new room.
Also makes use of more caching in `GetStateEvent`

Bonus: Adds some tests, as I was about to use `GetBulkStateContent`, but
turns out that `GetStateEvent` is basically doing the same, just that it
only gets the `eventTypeNID`/`eventStateKeyNID` once and not for every
call.
2023-11-22 15:38:04 +01:00
BtbN c4528b2de8
Allow users to kick themselves (#3157)
As per the spec:
https://spec.matrix.org/v1.7/rooms/v10/#authorization-rules

"If membership is leave"
->
"If the sender matches state_key, allow if and only if that user’s
current membership state is invite, join, or knock."

I.e. a user can kick themselves. Bridges use this to make a user leave
while giving a reason.

Some recent change (likely
8ea1a11105
but I'm not 100% sure) changed that behaviour, resulting in heisenbridge
being unable to make users leave while giving a reason.
This works fine on Synapse.

Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
Co-authored-by: kegsay <7190048+kegsay@users.noreply.github.com>
2023-11-22 12:15:45 +00:00
CicadaCinema f25cce237e
Refactor registration tests, remove hard-coded username validation (#3138)
### Pull Request Checklist

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] I have already signed off privately

This PR is in preparation for #3137 and removes the hard-coded username
validation (previously only dependent on `forceEmpty`).

---------

Co-authored-by: kegsay <7190048+kegsay@users.noreply.github.com>
2023-11-22 12:15:16 +00:00
Till 210123bab5
Add keydb_server_keys table tests (#3270)
Also moves some of the variable declarations out of the loop to,
hopefully, reduce allocations.
2023-11-22 13:05:24 +01:00
notassigned 06e079abac
Fix broken links in FAQ.md (#3259)
The links to CONTRUBITING.md and 4_adminapi.md were broken.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [ X] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [X ] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: <Private>

Co-authored-by: kegsay <kegan@matrix.org>
2023-11-22 11:14:49 +00:00
Nikolai Patrick fde4225469
fix typo (#3266)
Fix a tiny spelling mistake in the Grafana dashboard.
Literally a 1 character commit lol
### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x ] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [ x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Nikolai Patrick nikolaipatrick@wws.sa.edu.au`
2023-11-22 11:13:41 +00:00
Till 7863a405a5
Use IsBlacklistedOrBackingOff to determine if we should try to fetch devices (#3254)
Use `IsBlacklistedOrBackingOff` from the federation API to check if we
should fetch devices.

To reduce back pressure, we now only queue retrying servers if there's
space in the channel.
2023-11-09 08:43:27 +01:00
Till 699f5ca8c1
More rows.Close() and rows.Err() (#3262)
Looks like we missed some `rows.Close()`

Even though `rows.Err()` is mostly not necessary, we should be more
consistent in the DB layer.

[skip ci]
2023-11-09 08:42:33 +01:00
Till ee73a90aea
Fix potential connection leak (#3247)
We didn't rollback/commit after getting events, now we're rolling back
since we didn't change anything.
2023-11-08 14:22:20 +01:00
Till 5f872f4a82
Fix panic in QueryNextRoomHierarchyPage (#3253)
Sentry reported the following panic:
```
time="2023-11-01T01:33:56.220583478Z" level=error msg="Request panicked!
goroutine 43763845 [running]:
runtime/debug.Stack()
	runtime/debug/stack.go:24 +0x5e
github.com/matrix-org/dendrite/internal/httputil.MakeExternalAPI.MakeJSONAPI.Protect.func3.1()
	github.com/matrix-org/util@v0.0.0-20221111132719-399730281e66/json.go:98 +0x13e
panic({0x15b5540?, 0x2453560?})
	runtime/panic.go:914 +0x21f
github.com/matrix-org/dendrite/internal/httputil.MakeAuthAPI.func1.1()
	github.com/matrix-org/dendrite/internal/httputil/httpapi.go:91 +0x4a
panic({0x15b5540?, 0x2453560?})
	runtime/panic.go:914 +0x21f
github.com/matrix-org/dendrite/roomserver/internal/query.(*Queryer).QueryNextRoomHierarchyPage(0x413185?, {0x1a576e0, 0xc0436705a0}, {{{0xc01e5fd260, 0x1f}, {0xc01e5fd261, 0x12}, {0xc01e5fd274, 0xb}}, {0xc145cb5200, ...}, ...}, ...)
	github.com/matrix-org/dendrite/roomserver/internal/query/query_room_hierarchy.go:116 +0xbfe
github.com/matrix-org/dendrite/clientapi/routing.QueryRoomHierarchy(0xc0be13b200, 0xc144e65dd0, {0xc01e5fd260?, 0x6?}, {0x7faf140639c8, 0xc00059af20}, 0xc08adca000?)
	github.com/matrix-org/dendrite/clientapi/routing/room_hierarchy.go:141 +0x68b
github.com/matrix-org/dendrite/clientapi/routing.Setup.func35(0xc03e7d5c20?, 0x17c3a57?)
	github.com/matrix-org/dendrite/clientapi/routing/routing.go:534 +0xbe
github.com/matrix-org/dendrite/internal/httputil.MakeAuthAPI.func1(0xc0bd097300)
	github.com/matrix-org/dendrite/internal/httputil/httpapi.go:108 +0x5ed
github.com/matrix-org/util.(*jsonRequestHandlerWrapper).OnIncomingRequest(0xc0bd097200?, 0xc13b7d6fc0?)
	github.com/matrix-org/util@v0.0.0-20221111132719-399730281e66/json.go:79 +0x19
github.com/matrix-org/dendrite/internal/httputil.MakeExternalAPI.MakeJSONAPI.func2({0x1a54880, 0xc138f28b60}, 0xc0bd097200?)
	github.com/matrix-org/util@v0.0.0-20221111132719-399730281e66/json.go:141 +0xaa
github.com/matrix-org/dendrite/internal/httputil.MakeExternalAPI.MakeJSONAPI.Protect.func3({0x1a54880?, 0xc138f28b60?}, 0x17c01d9?)
	github.com/matrix-org/util@v0.0.0-20221111132719-399730281e66/json.go:103 +0x63
net/http.HandlerFunc.ServeHTTP(...)
	net/http/server.go:2136
github.com/matrix-org/dendrite/internal/httputil.MakeExternalAPI.func1({0x1a54880?, 0xc138f28b60?}, 0xc0bd097100)
	github.com/matrix-org/dendrite/internal/httputil/httpapi.go:191 +0x411
net/http.HandlerFunc.ServeHTTP(0xc0bd097000?, {0x1a54880?, 0xc138f28b60?}, 0xbe1348905308878e?)
	net/http/server.go:2136 +0x29
github.com/gorilla/mux.(*Router).ServeHTTP(0xc000000000, {0x1a54880, 0xc138f28b60}, 0xc0bd096f00)
	github.com/gorilla/mux@v1.8.0/mux.go:210 +0x1c5
github.com/matrix-org/dendrite/setup/base.SetupAndServeHTTP.(*Handler).Handle.(*Handler).handle.func5({0x1a54880, 0xc138f28b60}, 0xc0bd096e00)
	github.com/getsentry/sentry-go@v0.14.0/http/sentryhttp.go:103 +0x298
net/http.HandlerFunc.ServeHTTP(0xc0bd096a00?, {0x1a54880?, 0xc138f28b60?}, 0x7fae6812f5d0?)
	net/http/server.go:2136 +0x29
github.com/gorilla/mux.(*Router).ServeHTTP(0xc000000a80, {0x1a54880, 0xc138f28b60}, 0xc0bd096900)
	github.com/gorilla/mux@v1.8.0/mux.go:210 +0x1c5
net/http.serverHandler.ServeHTTP({0xc02884c4e0?}, {0x1a54880?, 0xc138f28b60?}, 0x6?)
	net/http/server.go:2938 +0x8e
net/http.(*conn).serve(0xc1926922d0, {0x1a576e0, 0xc024a6ec90})
	net/http/server.go:2009 +0x5f4
created by net/http.(*Server).Serve in goroutine 16979
	net/http/server.go:3086 +0x5cb
" context=missing panic="runtime error: invalid memory address or nil pointer dereference"
```

[skip ci]
2023-11-08 14:22:02 +01:00
dependabot[bot] 5c67eb99b3
Bump golang.org/x/image from 0.5.0 to 0.10.0 (#3257)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.5.0
to 0.10.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="cb227cd2c9"><code>cb227cd</code></a>
tiff: limit work when decoding malicious images</li>
<li><a
href="a5392f068b"><code>a5392f0</code></a>
bmp: support to decode 8-bit format with up to 256 color palette</li>
<li><a
href="f9550b04a5"><code>f9550b0</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="81c166c49c"><code>81c166c</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="ed5dba0ea2"><code>ed5dba0</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="08ca817286"><code>08ca817</code></a>
font: have Glyph return !ok for U+FFFD substitute</li>
<li><a
href="b6ac75bc59"><code>b6ac75b</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="1b7441254c"><code>1b74412</code></a>
font/sfnt: set type for all NameID constants</li>
<li><a
href="f632f7f87c"><code>f632f7f</code></a>
tiff, tiff/lzw, vector: use single space in comments</li>
<li>See full diff in <a
href="https://github.com/golang/image/compare/v0.5.0...v0.10.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/image&package-manager=go_modules&previous-version=0.5.0&new-version=0.10.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-03 08:13:34 +01:00
dependabot[bot] 8b4043473c
Bump github.com/nats-io/nkeys from 0.4.4 to 0.4.6 (#3252)
Bumps [github.com/nats-io/nkeys](https://github.com/nats-io/nkeys) from
0.4.4 to 0.4.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nats-io/nkeys/releases">github.com/nats-io/nkeys's
releases</a>.</em></p>
<blockquote>
<h2>v0.4.5</h2>
<h2>What's Changed</h2>
<ul>
<li>[CI] bump staticcheck GHAction by <a
href="https://github.com/philpennock"><code>@​philpennock</code></a> in
<a
href="https://redirect.github.com/nats-io/nkeys/pull/49">nats-io/nkeys#49</a></li>
<li>[FIX] added windows binary by <a
href="https://github.com/aricart"><code>@​aricart</code></a> in <a
href="https://redirect.github.com/nats-io/nkeys/pull/51">nats-io/nkeys#51</a></li>
<li>[FIX] YAML Enginering: quote go-version string by <a
href="https://github.com/philpennock"><code>@​philpennock</code></a> in
<a
href="https://redirect.github.com/nats-io/nkeys/pull/53">nats-io/nkeys#53</a></li>
<li>[FEAT] Use readKeyFile to read both seed file and public key file by
<a href="https://github.com/nanjj"><code>@​nanjj</code></a> in <a
href="https://redirect.github.com/nats-io/nkeys/pull/54">nats-io/nkeys#54</a></li>
<li>[FEAT] Made <code>decode</code> a little fast by <a
href="https://github.com/nanjj"><code>@​nanjj</code></a> in <a
href="https://redirect.github.com/nats-io/nkeys/pull/55">nats-io/nkeys#55</a></li>
<li>[REPO] Add issue forms by <a
href="https://github.com/bruth"><code>@​bruth</code></a> in <a
href="https://redirect.github.com/nats-io/nkeys/pull/56">nats-io/nkeys#56</a></li>
<li>[FIX] added binaries to match nats-server by <a
href="https://github.com/aricart"><code>@​aricart</code></a> in <a
href="https://redirect.github.com/nats-io/nkeys/pull/58">nats-io/nkeys#58</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nats-io/nkeys/compare/v0.4.4...v0.4.5">https://github.com/nats-io/nkeys/compare/v0.4.4...v0.4.5</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="62e5d8c7c4"><code>62e5d8c</code></a>
Merge pull request <a
href="https://redirect.github.com/nats-io/nkeys/issues/60">#60</a> from
nats-io/0_4_6</li>
<li><a
href="f63761b84d"><code>f63761b</code></a>
[BUMP] release version and dependencies</li>
<li><a
href="d2e442ebad"><code>d2e442e</code></a>
Merge pull request <a
href="https://redirect.github.com/nats-io/nkeys/issues/59">#59</a> from
nats-io/empty</li>
<li><a
href="58fb9d69f4"><code>58fb9d6</code></a>
Make sure to use byte slice to receive proper copy, otherwise empty
public ke...</li>
<li><a
href="3e454c8ca1"><code>3e454c8</code></a>
Merge pull request <a
href="https://redirect.github.com/nats-io/nkeys/issues/58">#58</a> from
nats-io/arch-bins</li>
<li><a
href="53c0777667"><code>53c0777</code></a>
bump go to 1.21.x</li>
<li><a
href="d935834966"><code>d935834</code></a>
bump version number</li>
<li><a
href="6b488b3078"><code>6b488b3</code></a>
[FIX] added binaries to match nats-server</li>
<li><a
href="9fb41511a9"><code>9fb4151</code></a>
Merge pull request <a
href="https://redirect.github.com/nats-io/nkeys/issues/56">#56</a> from
nats-io/add-issue-forms</li>
<li><a
href="4647ec0912"><code>4647ec0</code></a>
Fix issue config discussions link</li>
<li>Additional commits viewable in <a
href="https://github.com/nats-io/nkeys/compare/v0.4.4...v0.4.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/nats-io/nkeys&package-manager=go_modules&previous-version=0.4.4&new-version=0.4.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 12:00:59 +01:00
Till da7bca0224
Some tweaks for the device list updater (#3251)
This makes the following changes:
- Adds two new metrics observing the usage of the `DeviceListUpdater`
workers
- Makes the number of workers configurable
- Adds a 30s timeout for DB requests when receiving a device list update
over federation
2023-10-31 16:39:45 +01:00
dependabot[bot] 32f7c4b166
Bump github.com/docker/docker from 24.0.5+incompatible to 24.0.7+incompatible (#3250)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from
24.0.5+incompatible to 24.0.7+incompatible.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/docker/releases">github.com/docker/docker's
releases</a>.</em></p>
<blockquote>
<h2>v24.0.7</h2>
<h2>24.0.7</h2>
<p>For a full list of pull requests and changes in this release, refer
to the relevant GitHub milestones:</p>
<ul>
<li><a
href="https://github.com/docker/cli/issues?q=is%3Aclosed+milestone%3A24.0.7">docker/cli,
24.0.7 milestone</a></li>
<li><a
href="https://github.com/moby/moby/issues?q=is%3Aclosed+milestone%3A24.0.7">moby/moby,
24.0.7 milestone</a></li>
</ul>
<h3>Bug fixes and enhancements</h3>
<ul>
<li>Write overlay2 layer metadata atomically. <a
href="https://redirect.github.com/moby/moby/pull/46703">moby/moby#46703</a></li>
<li>Fix &quot;Rootful-in-Rootless&quot; Docker-in-Docker on systemd
version 250 and later. <a
href="https://redirect.github.com/moby/moby/pull/46626">moby/moby#46626</a></li>
<li>Fix <code>dockerd-rootless-setuptools.sh</code> when username
contains a backslash. <a
href="https://redirect.github.com/moby/moby/pull/46407">moby/moby#46407</a></li>
<li>Fix a bug that would prevent network sandboxes to be fully deleted
when stopping containers with no network attachments and when
<code>dockerd --bridge=none</code> is used. <a
href="https://redirect.github.com/moby/moby/pull/46702">moby/moby#46702</a></li>
<li>Fix a bug where cancelling an API request could interrupt container
restart. <a
href="https://redirect.github.com/moby/moby/pull/46697">moby/moby#46697</a></li>
<li>Fix an issue where containers would fail to start when providing
<code>--ip-range</code> with a range larger than the subnet. <a
href="https://redirect.github.com/docker/for-mac/issues/6870">docker/for-mac#6870</a></li>
<li>Fix data corruption with zstd output. <a
href="https://redirect.github.com/moby/moby/pull/46709">moby/moby#46709</a></li>
<li>Fix the conditions under which the container's MAC address is
applied. <a
href="https://redirect.github.com/moby/moby/pull/46478">moby/moby#46478</a></li>
<li>Improve the performance of the stats collector. <a
href="https://redirect.github.com/moby/moby/pull/46448">moby/moby#46448</a></li>
<li>Fix an issue with source policy rules ending up in the wrong order.
<a
href="https://redirect.github.com/moby/moby/pull/46441">moby/moby#46441</a></li>
</ul>
<h3>Packaging updates</h3>
<ul>
<li>Add support for Fedora 39 and Ubuntu 23.10. <a
href="https://redirect.github.com/docker/docker-ce-packaging/pull/940">docker/docker-ce-packaging#940</a>,
<a
href="https://redirect.github.com/docker/docker-ce-packaging/pull/955">docker/docker-ce-packaging#955</a></li>
<li>Fix <code>docker.socket</code> not getting disabled when
uninstalling the <code>docker-ce</code> RPM package. <a
href="https://redirect.github.com/docker/docker-ce-packaging/pull/852">docker/docker-ce-packaging#852</a></li>
<li>Upgrade Go to <code>go1.20.10</code>. <a
href="https://redirect.github.com/docker/docker-ce-packaging/pull/951">docker/docker-ce-packaging#951</a></li>
<li>Upgrade containerd to <code>v1.7.6</code> (static binaries only). <a
href="https://redirect.github.com/moby/moby/pull/46103">moby/moby#46103</a></li>
<li>Upgrade the <code>containerd.io</code> package to <a
href="https://github.com/containerd/containerd/releases/tag/v1.6.24"><code>v1.6.24</code></a>.</li>
</ul>
<h3>Security</h3>
<ul>
<li>Deny containers access to <code>/sys/devices/virtual/powercap</code>
by default. This change hardens against <a
href="https://scout.docker.com/v/CVE-2020-8694">CVE-2020-8694</a>, <a
href="https://scout.docker.com/v/CVE-2020-8695">CVE-2020-8695</a>, and
<a href="https://scout.docker.com/v/CVE-2020-12912">CVE-2020-12912</a>,
and an attack known as <a href="https://platypusattack.com/">the
PLATYPUS attack</a>. For more details, see <a
href="https://github.com/moby/moby/security/advisories/GHSA-jq35-85cj-fj4p">advisory</a>,
<a
href="c9ccbfad11">commit</a>.</li>
</ul>
<h2>v24.0.6</h2>
<h2>24.0.6</h2>
<p>For a full list of pull requests and changes in this release, refer
to the relevant GitHub milestones:</p>
<ul>
<li><a
href="https://github.com/docker/cli/issues?q=is%3Aclosed+milestone%3A24.0.6">docker/cli,
24.0.6 milestone</a></li>
<li><a
href="https://github.com/moby/moby/issues?q=is%3Aclosed+milestone%3A24.0.6">moby/moby,
24.0.6 milestone</a></li>
</ul>
<h3>Bug fixes and enhancements</h3>
<ul>
<li>containerd storage backend: Fix <code>docker ps</code> failing when
a container image is no longer present in the content store. <a
href="https://redirect.github.com/moby/moby/pull/46095">moby/moby#46095</a></li>
<li>containerd storage backend: Fix <code>docker ps -s -a</code> and
<code>docker container prune</code> failing when a container image
config is no longer present in the content store. <a
href="https://redirect.github.com/moby/moby/pull/46097">moby/moby#46097</a></li>
<li>containerd storage backend: Fix <code>docker inspect</code> failing
when a container image config is no longer (or was never) present in the
content store. <a
href="https://redirect.github.com/moby/moby/pull/46244">moby/moby#46244</a></li>
<li>containerd storage backend: Fix diff and export with the
<code>overlayfs</code> snapshotter by using reference-counted rootfs
mounts. <a
href="https://redirect.github.com/moby/moby/pull/46266">moby/moby#46266</a></li>
<li>containerd storage backend: Fix a misleading error message when the
image platforms available locally do not match the desired platform. <a
href="https://redirect.github.com/moby/moby/pull/46300">moby/moby#46300</a></li>
<li>containerd storage backend: Fix the <code>FROM scratch</code>
Dockerfile instruction with the classic builder. <a
href="https://redirect.github.com/moby/moby/pull/46302">moby/moby#46302</a></li>
<li>containerd storage backend: Fix <code>mismatched image rootfs and
manifest layers</code> errors with the classic builder. <a
href="https://redirect.github.com/moby/moby/pull/46310">moby/moby#46310</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="311b9ff0aa"><code>311b9ff</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/46697">#46697</a>
from thaJeztah/24.0_backport_restart_nocancel</li>
<li><a
href="af608045ee"><code>af60804</code></a>
Merge pull request from GHSA-jq35-85cj-fj4p</li>
<li><a
href="3cf363e1ee"><code>3cf363e</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/46709">#46709</a>
from thaJeztah/24.0_backport_bump_compress</li>
<li><a
href="05d7386665"><code>05d7386</code></a>
daemon: daemon.containerRestart: don't cancel restart on context
cancel</li>
<li><a
href="649c9440f2"><code>649c944</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/46703">#46703</a>
from thaJeztah/24.0_backport_atomic-layer-data-write</li>
<li><a
href="9b20b1a5fe"><code>9b20b1a</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker/issues/46702">#46702</a>
from thaJeztah/24.0_backport_releaseNetwork_Network...</li>
<li><a
href="dd37b0b960"><code>dd37b0b</code></a>
vendor: github.com/klauspost/compress v1.17.2</li>
<li><a
href="7058c0d24d"><code>7058c0d</code></a>
vendor: github.com/klauspost/compress v1.16.5</li>
<li><a
href="57bd388582"><code>57bd388</code></a>
daemon: overlay2: Write layer metadata atomically</li>
<li><a
href="05d95fd503"><code>05d95fd</code></a>
daemon: release sandbox even when NetworkDisabled</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/docker/compare/v24.0.5...v24.0.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/docker/docker&package-manager=go_modules&previous-version=24.0.5+incompatible&new-version=24.0.7+incompatible)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 07:59:19 +01:00
Till 317b1018a3
Version 0.13.4 (#3244)
If I didn't mess up the workflow, this should remove some ugliness from
the version string (e.g. 0.13.2+57ddbe0.57ddbe0, dupe commit hash, as a
result of https://github.com/matrix-org/dendrite/pull/3147)
2023-10-25 13:53:40 +02:00
CicadaCinema 89482ad790
clean up dead links, fix typo (#3130)
I fixed any dead links beginning https://matrix.org/speculator and some
issues I found along the way.


https://web.archive.org/web/20190329152312/https://matrix.org/speculator/spec/HEAD/client_server/unstable.html#user-interactive-authentication-api
is now found at

https://spec.matrix.org/v1.7/client-server-api/#user-interactive-authentication-api


https://web.archive.org/web/20170620093435/https://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register
is now found at

https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3register


2a8d64fef7/specification/intro.rst?plain=1#L443
is now found at
https://spec.matrix.org/v1.7/appendices/#user-identifiers
2023-10-25 10:24:06 +02:00
devonh a0375d41fb
Add simple test for one time keys (#3239) 2023-10-25 10:13:18 +02:00
WrenIX e02a7948d8
fix(helm): empty storage class in pvcs (#3191)
fix #3103 

---

not yet tested

[skip ci]
2023-10-25 10:08:54 +02:00
Till 4fa8512d57
Check event is not rejected (#3243)
Companion PR to https://github.com/matrix-org/gomatrixserverlib/pull/421
2023-10-25 09:47:21 +02:00
Till 1b124fe9cb
Implement MSC3987, fix setting Element Android notifications (#3242)
Should fix https://github.com/matrix-org/dendrite/issues/3183, since
Element Android already implements
[MSC3987](https://github.com/vector-im/element-android/pull/8530)

This is also part of https://github.com/matrix-org/dendrite/issues/3225
2023-10-24 11:51:08 +02:00
dependabot[bot] c1d6b9aa8e
Bump github.com/nats-io/nats-server/v2 from 2.9.19 to 2.9.23 (#3238)
Bumps
[github.com/nats-io/nats-server/v2](https://github.com/nats-io/nats-server)
from 2.9.19 to 2.9.23.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nats-io/nats-server/releases">github.com/nats-io/nats-server/v2's
releases</a>.</em></p>
<blockquote>
<h2>Release v2.9.23</h2>
<h2>Changelog</h2>
<h3>Go Version</h3>
<ul>
<li>1.20.10</li>
</ul>
<h3>Fixed</h3>
<p>Accounts</p>
<ul>
<li>Prevent bypassing authorization block when enabling system account
access in accounts block (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4605">#4605</a>).
Backport from v2.10.2</li>
</ul>
<p>Leafnodes</p>
<ul>
<li>Prevent a leafnode cluster from receiving a message multiple times
in a queue subscription (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4578">#4578</a>).
Backport from v2.10.2</li>
</ul>
<p>JetStream</p>
<ul>
<li>Hold lock when calculating the first message for subject in a
message block (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4531">#4531</a>).
Backport from v2.10.0</li>
<li>Add self-healing mechanism to detect and delete orphaned Raft groups
(<a
href="https://redirect.github.com/nats-io/nats-server/issues/4647">#4647</a>).
Backport from v2.10.0</li>
<li>Prevent forward proposals in consumers after scaling down a stream
(<a
href="https://redirect.github.com/nats-io/nats-server/issues/4647">#4647</a>).
Backport from v2.10.0</li>
<li>Fix race condition during leader failover scenarios resulting in
potential duplicate messages being sourced (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4592">#4592</a>).
Backport from v2.10.2</li>
</ul>
<h3>Complete Changes</h3>
<p><a
href="https://github.com/nats-io/nats-server/compare/v2.9.22...v2.9.23">https://github.com/nats-io/nats-server/compare/v2.9.22...v2.9.23</a></p>
<h2>Release v2.9.22</h2>
<h2>Changelog</h2>
<h3>Go Version</h3>
<ul>
<li>1.20.8 (updated out-of-cycle since Go 1.19 is now EOL)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>github.com/nats-io/jwt/v2 v2.5.0</li>
<li>golang.org/x/crypto v0.12.0</li>
<li>golang.org/x/sys v0.11.0</li>
</ul>
<h3>Improved</h3>
<p>Monitoring</p>
<ul>
<li>CORS Allow-Origin passthrough for monitoring server (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4423">#4423</a>)
Thanks to <a href="https://github.com/mdawar"><code>@​mdawar</code></a>
for the contribution!</li>
</ul>
<p>JetStream</p>
<ul>
<li>Improve consumer scaling reliability with filters and cluster
restart (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4404">#4404</a>)</li>
<li>Send event on lame duck mode (LDM) to avoid placing assets on
shutting down nodes (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4405">#4405</a>)</li>
<li>Skip filestore tombstones if downgrade from 2.10 occurs (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4452">#4452</a>)</li>
<li>Adjust delivered and waiting count when consumer message delivery
fails (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4472">#4472</a>)</li>
</ul>
<h3>Fixed</h3>
<p>Config</p>
<ul>
<li>Allow empty configs and fix JSON compatibility (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4394">#4394</a>,
<a
href="https://redirect.github.com/nats-io/nats-server/issues/4418">#4418</a>)</li>
<li>Remove TLS OCSP debug log on reload (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4453">#4453</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="45436e1e50"><code>45436e1</code></a>
Release v2.9.23 (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4652">#4652</a>)</li>
<li><a
href="72ffa38b05"><code>72ffa38</code></a>
Release v2.9.23</li>
<li><a
href="05fe77fd08"><code>05fe77f</code></a>
Backport <a
href="https://redirect.github.com/nats-io/nats-server/issues/4592">#4592</a>
to 2.9 (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4651">#4651</a>)</li>
<li><a
href="6a73e6824a"><code>6a73e68</code></a>
[2.9.x] Bump Travis Go version to 1.20.10 (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4650">#4650</a>)</li>
<li><a
href="8b981a2621"><code>8b981a2</code></a>
Backports from v2.10 for v2.9.23 release (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4647">#4647</a>)</li>
<li><a
href="28eb7c0ac2"><code>28eb7c0</code></a>
Only setup auto no-auth for $G account iff no authorization block was
defined.</li>
<li><a
href="9f16edd431"><code>9f16edd</code></a>
Make sure to not forward a message across a route for dq sub when we are
a sp...</li>
<li><a
href="0ac7895b98"><code>0ac7895</code></a>
Add in utility to detect and delete any NRG orphans.</li>
<li><a
href="50722e9ec1"><code>50722e9</code></a>
When scaling a consumer down make sure to pop the
loopAndForwardProposals go ...</li>
<li><a
href="770cf2edd6"><code>770cf2e</code></a>
Backport JetStream benchmarks improvements to 2.9.x (<a
href="https://redirect.github.com/nats-io/nats-server/issues/4644">#4644</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/nats-io/nats-server/compare/v2.9.19...v2.9.23">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/nats-io/nats-server/v2&package-manager=go_modules&previous-version=2.9.19&new-version=2.9.23)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Till <2353100+S7evinK@users.noreply.github.com>
2023-10-24 09:11:58 +02:00
Till 8b3adaf244
Fix state resets (#3231)
Needs https://github.com/matrix-org/gomatrixserverlib/pull/419

May fix: https://github.com/matrix-org/dendrite/issues/2508,
https://github.com/matrix-org/dendrite/issues/1760
2023-10-23 15:17:21 +02:00
Till 8c23c1150c
Tweaks around the device list updater (#3227)
I hope the comments explain the changes.

`notifyWorkers` notifies a worker which then calls `processServer`,
which in turn gets all users and calls `processServerUser`. There is no
need to call `processServer` for the same domain on startup.
2023-10-23 11:09:05 +02:00
dependabot[bot] fe2955a4db
Bump golang.org/x/net from 0.14.0 to 0.17.0 (#3233)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.14.0 to
0.17.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b225e7ca6d"><code>b225e7c</code></a>
http2: limit maximum handler goroutines to MaxConcurrentStreams</li>
<li><a
href="88194ad8ab"><code>88194ad</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="2b60a61f1e"><code>2b60a61</code></a>
quic: fix several bugs in flow control accounting</li>
<li><a
href="73d82efb96"><code>73d82ef</code></a>
quic: handle DATA_BLOCKED frames</li>
<li><a
href="5d5a036a50"><code>5d5a036</code></a>
quic: handle streams moving from the data queue to the meta queue</li>
<li><a
href="350aad2603"><code>350aad2</code></a>
quic: correctly extend peer's flow control window after MAX_DATA</li>
<li><a
href="21814e71db"><code>21814e7</code></a>
quic: validate connection id transport parameters</li>
<li><a
href="a600b3518e"><code>a600b35</code></a>
quic: avoid redundant MAX_DATA updates</li>
<li><a
href="ea633599b5"><code>ea63359</code></a>
http2: check stream body is present on read timeout</li>
<li><a
href="ddd8598e56"><code>ddd8598</code></a>
quic: version negotiation</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/net/compare/v0.14.0...v0.17.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/net&package-manager=go_modules&previous-version=0.14.0&new-version=0.17.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 09:40:21 +02:00
devonh 933ae2db91
Update bug report to reflect current team members (#3234) 2023-10-12 18:03:06 +00:00
kegsay 5888329b13
Update Complement to match new public API shape (#3232)
Sister PR to matrix-org/complement#666

Context:
https://github.com/matrix-org/complement/issues/654#issuecomment-1746613495
2023-10-11 17:41:12 +01:00
Till 2259e71c0c
Fix resolve-state (#3229)
Previously we would "start" the roomserver API, which isn't the best
idea, given it also starts processing Jetstream events. We now use a
`dummyQuerier` to implement the needed interface for "converting"
userID/senderIDs. As per the comment, this **DOES NOT** do any magic for
pseudoID rooms.
2023-10-05 10:33:04 +02:00
Till 3d02c81031
Fix tests for x86 (#3214) 2023-09-28 14:50:31 +02:00
Till Faelligen 1853f58cb4
Add missing sliding sync config 2023-09-28 12:38:53 +02:00
Till b341a66152
Version 0.13.3 (#3213) 2023-09-28 12:06:21 +02:00
Tracker-Friendly 4d344b65b2
Fixed typo in documentation (#3212)
### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [ ] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests

This PR doesn't need tests because it's a documentation update

* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed off privately

Co-authored-by: Tracker-Friendly <jliwin98@pm.me>
2023-09-28 07:40:12 +02:00
jahway603 f1db57c7f8
Updated minimum required go version in README.md (#3194)
Updated minimum required go version in README.md

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `jahway603 <jahway603@protonmail.com>`

Co-authored-by: Till <2353100+S7evinK@users.noreply.github.com>
2023-09-28 07:38:29 +02:00
Till f02d998253
Remove the creator field when upgrading to v11 (#3210)
Minor oversight
2023-09-28 07:36:57 +02:00
Till 10b4fbc66d
Fix m.direct only being partially upgraded (#3209)
Previously we would update `m.direct` once we found the old room ID. If
the roomID is found somewhere in the middle, we would never add the rest
of the users, resulting in only partially upgraded `m.direct` and chats
loosing their 1:1 flag.
2023-09-28 07:36:34 +02:00
Till 05a8f1ede3
Support for room version v11 (#3204)
Fixes #3203
2023-09-27 08:27:08 +02:00
devonh 16d922de70
Complement fixes for pseudoIDs (#3206) 2023-09-26 17:44:49 +00:00
Till d065219de1
Fix invitations not sending push notifications (#3207)
The tests added in https://github.com/matrix-org/sytest/pull/1356
uncovered that we don't consider invitations as events the userapi
should handle and thus just don't notify the client about any new
invitations received over federation.
2023-09-26 15:47:37 +02:00
devonh db83789654
Move pseudoID ClientEvent hotswapping to a common location (#3199)
Fixes a variety of issues where clients were receiving pseudoIDs in
places that should be userIDs.
This change makes pseudoIDs work with sliding sync & element x.

---------

Co-authored-by: Till <2353100+S7evinK@users.noreply.github.com>
2023-09-15 15:25:09 +00:00
devonh 8245b24100
Update gmsl to use new validated RoomID on PDUs (#3200)
GMSL returns a `spec.RoomID` when calling `PDU.RoomID()`
2023-09-15 14:39:06 +00:00
Sam Wedgwood 058081e68e
[pseudoIDs] changing event ID fix (#3195)
power levels events in pseudo IDs sometimes changed event IDs (this was
already fixed earlier, but one of the edgecases was not covered, and is
now covered)

Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-09-12 16:32:24 +01:00
Tulir Asokan bea73c765a
Fix user_id query param breaking auth for non-appservices (#3196)
The `user_id` query param only has defined behavior when authenticating
with an `as_token`. For any other tokens, the presence of the parameter
should simply be ignored.

Fixes #1738

Signed-off-by: Tulir Asokan <tulir@maunium.net>
Co-authored-by: devonh <devon.dmytro@gmail.com>
2023-09-12 14:44:51 +00:00
Sam Wedgwood 478827459c
bump GMSL back to main (#3197)
In a [previous PR](https://github.com/matrix-org/dendrite/pull/3181) I
accidentally left GMSL on a dev branch, this PR fixes it by bringing it
back to the main branch of GMSL

Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-09-08 16:30:21 +01:00
devonh bb2ab62cbf
Handle event_format federation in /sync responses (#3192) 2023-08-31 15:33:38 +00:00
Till Faelligen 11fd2f019b
Fix Complement scheduled CI
[skip CI]
2023-08-30 07:37:14 +02:00
Omar Pakker b538f237df
[helm] Update Ingress hosts to account for IPv6 (server+client) and scheme (client) (#3182)
This updates the matchers for deriving the host values from the dendrite
config. The original version turned out to have 2 complications:
- It did not support IPv6 addresses as host value
- It failed for `well_known_client_host` which is a (base) URL instead
of a hostname+port.

I've verified `well_known_server_name` with
```
dendrite.example.net:443
dendrite.example.net
192.168.1.1
192.168.1.1:1324
[dead::beef]:1234
[dead::beef]
[ffff:dead::beef]
```
and `well_known_client_name` with:
```
https://dendrite.example.net:443
https://dendrite.example.net
https://dendrite.example.net/
http://dendrite.example.net:8080/
http://192.168.1.1
http://192.168.1.1:8080/
http://[dead::beef]:1234
http://[dead::beef]/
http://[ffff:dead::beef]
```

Fixes #3175

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Omar Pakker <Omar007@users.noreply.github.com>`

---------

Signed-off-by: Omar Pakker <Omar007@users.noreply.github.com>

[skip CI]
2023-08-29 08:20:37 +02:00
Till e3a7039c81
Fix CI, upgrade image used for upgrade tests (#3151) 2023-08-28 13:28:22 +02:00
dependabot[bot] 43b1ddb89b
Bump commonmarker from 0.23.9 to 0.23.10 in /docs (#3172)
Bumps [commonmarker](https://github.com/gjtorikian/commonmarker) from
0.23.9 to 0.23.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gjtorikian/commonmarker/releases">commonmarker's
releases</a>.</em></p>
<blockquote>
<h2>v0.23.10</h2>
<h2>What's Changed</h2>
<ul>
<li>Update to 0.29.0.gfm.13 by <a
href="https://github.com/anticomputer"><code>@​anticomputer</code></a>
in <a
href="https://redirect.github.com/gjtorikian/commonmarker/pull/247">gjtorikian/commonmarker#247</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/gjtorikian/commonmarker/compare/v0.23.9...v0.23.10">https://github.com/gjtorikian/commonmarker/compare/v0.23.9...v0.23.10</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/gjtorikian/commonmarker/blob/v0.23.10/CHANGELOG.md">commonmarker's
changelog</a>.</em></p>
<blockquote>
<h2>[v0.23.10] (2023-07-31)</h2>
<ul>
<li>Update GFM release to <a
href="https://github.com/github/cmark-gfm/releases/tag/0.29.0.gfm.12"><code>0.29.0.gfm.12</code></a>
and <a
href="https://github.com/github/cmark-gfm/releases/tag/0.29.0.gfm.13"><code>0.29.0.gfm.13</code></a>,
thereby <a
href="https://github.com/github/cmark-gfm/security/advisories/GHSA-w4qg-3vf7-m9x5">fixing
a polynomial time complexity security vulnerability</a>.</li>
<li>Of note to users of this library, GFM releases
<code>0.29.0.gfm.12</code> and <code>0.29.0.gfm.13</code> also:
<ul>
<li>Normalized marker row vs. delimiter row nomenclature (<a
href="https://redirect.github.com/github/cmark-gfm/pull/273">#273</a>)</li>
<li>Exposed CMARK_NODE_FOOTNOTE_DEFINITION literal value (<a
href="https://redirect.github.com/github/cmark-gfm/pull/336">#336</a>)</li>
</ul>
</li>
</ul>
<h2><a
href="https://github.com/gjtorikian/commonmarker/tree/v0.23.4">v0.23.4</a>
(2022-03-03)</h2>
<p><a
href="https://github.com/gjtorikian/commonmarker/compare/v0.23.2...v0.23.4">Full
Changelog</a></p>
<p><strong>Fixed bugs:</strong></p>
<ul>
<li><code>#render_html</code> way slower than
<code>#render_doc.to_html</code> <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/141">#141</a></li>
</ul>
<p><strong>Closed issues:</strong></p>
<ul>
<li>allow keeping text content of unknown tags <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/169">#169</a></li>
<li>STRIKETHROUGH_DOUBLE_TILDE not working <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/168">#168</a></li>
<li>Allow disabling 4-space code blocks <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/167">#167</a></li>
<li>tables with escaped pipes are not recognized <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/166">#166</a></li>
</ul>
<p><strong>Merged pull requests:</strong></p>
<ul>
<li>CI: Drop a duplicate 'bundle install' <a
href="https://redirect.github.com/gjtorikian/commonmarker/pull/173">#173</a>
(<a href="https://github.com/olleolleolle">olleolleolle</a>)</li>
<li>CI: Drop duplicate bundle install <a
href="https://redirect.github.com/gjtorikian/commonmarker/pull/172">#172</a>
(<a href="https://github.com/olleolleolle">olleolleolle</a>)</li>
<li>Fixup benchmark and speedup a little, fixes <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/141">#141</a>
<a
href="https://redirect.github.com/gjtorikian/commonmarker/pull/171">#171</a>
(<a href="https://github.com/ojab">ojab</a>)</li>
</ul>
<h2><a
href="https://github.com/gjtorikian/commonmarker/tree/v0.23.2">v0.23.2</a>
(2021-09-17)</h2>
<p><a
href="https://github.com/gjtorikian/commonmarker/compare/v0.23.1...v0.23.2">Full
Changelog</a></p>
<p><strong>Merged pull requests:</strong></p>
<ul>
<li>Update GFM release to <code>0.29.0.gfm.2</code> <a
href="https://redirect.github.com/gjtorikian/commonmarker/pull/148">#148</a>
(<a href="https://github.com/phillmv">phillmv</a>)</li>
</ul>
<h2><a
href="https://github.com/gjtorikian/commonmarker/tree/v0.23.1">v0.23.1</a>
(2021-09-03)</h2>
<p><a
href="https://github.com/gjtorikian/commonmarker/compare/v0.23.0...v0.23.1">Full
Changelog</a></p>
<p><strong>Closed issues:</strong></p>
<ul>
<li>Incorrect processing of list and next block of code <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/146">#146</a></li>
</ul>
<p><strong>Merged pull requests:</strong></p>
<ul>
<li>Normalize parse and render options <a
href="https://redirect.github.com/gjtorikian/commonmarker/pull/145">#145</a>
(<a href="https://github.com/phillmv">phillmv</a>)</li>
</ul>
<h2><a
href="https://github.com/gjtorikian/commonmarker/tree/v0.23.0">v0.23.0</a>
(2021-08-30)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="db8cd377b5"><code>db8cd37</code></a>
Merge pull request <a
href="https://redirect.github.com/gjtorikian/commonmarker/issues/247">#247</a>
from anticomputer/update-to-0.29.0.gfm.13</li>
<li><a
href="e1e450c381"><code>e1e450c</code></a>
💎 release 0.23.10</li>
<li><a
href="08b7c4b96c"><code>08b7c4b</code></a>
Update cmark-upstream to <a
href="https://github.com/github/cmark-gfm/commit/587a12bb5">https://github.com/github/cmark-gfm/commit/587a12bb5</a>...</li>
<li><a
href="d0e81e2392"><code>d0e81e2</code></a>
I've used this version of the update_submodules script for several
releases, ...</li>
<li>See full diff in <a
href="https://github.com/gjtorikian/commonmarker/compare/v0.23.9...v0.23.10">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=commonmarker&package-manager=bundler&previous-version=0.23.9&new-version=0.23.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/matrix-org/dendrite/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

[skip ci]
2023-08-28 12:51:47 +02:00
devonh 1c4ec67bb6
Add configuration option for sliding sync when hosting /.well-known/matrix/client (#3189)
Adds the `org.matrix.msc3575.proxy` field (used for configuring sliding
sync) to /.well-known/matrix/client when Dendrite is serving that
endpoint and `well_known_sliding_sync_proxy` has been configured.

ie. Config values of:
``` yaml
global:
    well_known_client_name: https://example.com
    well_known_sliding_sync_proxy: https://syncv3.example.com
```
results in a /.well-known/matrix/client of:
``` json
{
    "m.homeserver": {
        "base_url": "https://example.com"
    },
    "org.matrix.msc3575.proxy": {
        "url": "https://syncv3.example.com"
    }
}
```

If `well_known_sliding_sync_proxy` is not provided, the json provided by
/.well-known/matrix/client does not include the proxy field.
ie.
``` json
{
    "m.homeserver": {
        "base_url": "https://example.com"
    }
}
```
2023-08-24 21:08:40 +00:00
Sam Wedgwood 9b5be6b9c5
[pseudoIDs] More pseudo ID fixes - Part 2 (#3181)
Fixes include:
- Translating state keys that contain user IDs to their respective room
keys for both querying and sending state events
- **NOTE**: there may be design discussion needed on what should happen
when sender keys cannot be found for users
- A simple fix for kicking guests from rooms properly
- Logic for boundary history visibilities was slightly off (I'm
surprised this only manifested in pseudo ID room versions)

Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-08-24 16:43:51 +01:00
Devon Hudson a721294e2b
Bump pinecone docker go version 2023-08-23 08:56:44 -06:00
Till Faelligen 845800abfa
Bump helm chart version 2023-08-23 16:44:52 +02:00
Till 57ddbe015d
Version 0.13.2 (#3187) 2023-08-23 16:24:16 +02:00
Sam Wedgwood 9a12420428
[pseudoID] More pseudo ID fixes (#3167)
Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-08-15 12:37:04 +01:00
devonh fa6c7ba456
Update pinecone to use new quic version (#3174) 2023-08-11 14:29:48 +00:00
Sam Wedgwood 35804f8493
Add config key for default room version (#3171)
This PR adds a config key `room_server.default_config_key` to set the
default room version for the room server.

Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-08-08 14:20:05 +01:00
maxberger 294eff8a7f
Add ID in error messages for ApplicationServices (#3162)
This is to easier identify which service caused the error.

Feature is just improving logging, thus no tests added.

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [X]  I have justified why this PR doesn't need tests
* [X] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `Maximilian Berger <max@berger.name>`

Co-authored-by: Till <2353100+S7evinK@users.noreply.github.com>
2023-08-03 09:26:42 +02:00
Sam Wedgwood c7193e24d0
Use *spec.SenderID for QuerySenderIDForUser (#3164)
There are cases where a dendrite instance is unaware of a pseudo ID for
a user, the user is not a member of that room. To represent this case,
we currently use the 'zero' value, which is often not checked and so
causes errors later down the line. To make this case more explict, and
to be consistent with `QueryUserIDForSender`, this PR changes this to
use a pointer (and `nil` to mean no sender ID).

Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-08-02 11:12:14 +01:00
Sam Wedgwood af13fa1c75
[pseudoIDs] Fixes for room alias tests (#3159)
Some (deceptively) simple fixes for some bugs that caused room alias
tests to fail (sytext `tests/30rooms/05aliases.pl`). Each commit has
details about what it fixes.

Sytest results:

- Sytest before (79d4a0e):
https://gist.github.com/swedgwood/972ac4ef93edd130d3db0930703d6c82
- Sytest after (4b09bed):
https://gist.github.com/swedgwood/504b00ac4ee892acb757b7fac55fa28a

Room aliases go from `8/15` to `15/15`, but looks like these fixes also
managed to fix about `4` other tests, which is a nice bonus :)

Signed-off-by: `Sam Wedgwood <sam@wedgwood.dev>`
2023-07-31 14:39:41 +01:00
Till 3f727485d6
Send a more generic error message to clients if the file can't be found (#3161)
Fixes #3160
2023-07-28 08:40:05 +02:00
Till Faelligen 79d4a0e399
Restore old behaviour of PurgeRoom 2023-07-26 09:09:04 +02:00
George Antoniadis 7899f47e71
add deployment strategy option to helm chart (re #3021) (#3155)
@S7evinK sorry for the spam but any chance we get get this merged into
main at some point? It was previously merged in
https://github.com/matrix-org/dendrite/pull/3021 into a temp branch that
never made it into main. If there is an issue with this being merged let
me know.

---

Minor update to the helm chart to allow setting the update strategy as
the default `RollingUpdate` one is a bit annoying if using
`ReadWriteOnce` volumes for media. Hope this makes sense.

---

### Pull Request Checklist

<!-- Please read
https://matrix-org.github.io/dendrite/development/contributing before
submitting your pull request -->

* [x] ~~I have added Go unit tests or [Complement integration
tests](https://github.com/matrix-org/complement) for this PR _or_ I have
justified why this PR doesn't need tests~~ Haven't touched any go files.
* [x] Pull request includes a [sign off below using a legally
identifiable
name](https://matrix-org.github.io/dendrite/development/contributing#sign-off)
_or_ I have already signed off privately

Signed-off-by: `George Antoniadis <george@noodles.gr>` [skip ci]
2023-07-26 08:16:43 +02:00
Devon Hudson a48c7d33a5
Don't quit if unknown msc in config, log it and keep going 2023-07-21 13:08:28 -06:00
devonh c809e95335
Fix event federation with pseudoID rooms (#3156) 2023-07-21 16:08:40 +00:00
Till e216c2fbf0
Update ConnectionManager to still allow component defined connections (#3154) 2023-07-21 08:34:01 +02:00
349 changed files with 11181 additions and 2807 deletions

View file

@ -62,6 +62,6 @@ If you can identify any relevant log snippets from server logs, please include
those (please be careful to remove any personal or private data). Please surround them with
``` (three backticks, on a line on their own), so that they are formatted legibly.
Alternatively, please send logs to @kegan:matrix.org or @neilalexander:matrix.org
Alternatively, please send logs to @kegan:matrix.org, @s7evink:matrix.org or @devonh:one.ems.host
with a link to the respective Github issue, thanks!
-->

View file

@ -7,7 +7,7 @@ coverage:
project:
default:
target: auto
threshold: 0%
threshold: 0.1%
base: auto
flags:
- unittests

View file

@ -28,12 +28,12 @@ jobs:
runs-on: ubuntu-latest
if: ${{ false }} # disable for now
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
go-version-file: 'go.mod'
cache: true
- name: Install Node
@ -41,7 +41,7 @@ jobs:
with:
node-version: 14
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
@ -66,13 +66,13 @@ jobs:
name: Linting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install libolm
run: sudo apt-get install libolm-dev libolm3
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
go-version-file: 'go.mod'
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
@ -102,14 +102,14 @@ jobs:
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install libolm
run: sudo apt-get install libolm-dev libolm3
- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
- uses: actions/cache@v3
go-version-file: 'go.mod'
- uses: actions/cache@v4
# manually set up caches, as they otherwise clash with different steps using setup-go with cache=true
with:
path: |
@ -123,7 +123,7 @@ jobs:
with:
# Optional: pass GITHUB_TOKEN to avoid rate limiting.
token: ${{ secrets.GITHUB_TOKEN }}
- run: go test -json -v ./... 2>&1 | gotestfmt
- run: go test -json -v ./... 2>&1 | gotestfmt -hide all
env:
POSTGRES_HOST: localhost
POSTGRES_USER: postgres
@ -141,12 +141,12 @@ jobs:
goos: ["linux"]
goarch: ["amd64", "386"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
- uses: actions/cache@v3
go-version-file: 'go.mod'
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
@ -174,12 +174,12 @@ jobs:
goos: ["windows"]
goarch: ["amd64"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
- uses: actions/cache@v3
go-version-file: 'go.mod'
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
@ -235,19 +235,19 @@ jobs:
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install libolm
run: sudo apt-get install libolm-dev libolm3
- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
go-version-file: 'go.mod'
- name: Set up gotestfmt
uses: gotesttools/gotestfmt-action@v2
with:
# Optional: pass GITHUB_TOKEN to avoid rate limiting.
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
@ -255,17 +255,18 @@ jobs:
key: ${{ runner.os }}-go-stable-test-race-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-stable-test-race-
- run: go test -race -json -v -coverpkg=./... -coverprofile=cover.out $(go list ./... | grep -v /cmd/dendrite*) 2>&1 | gotestfmt
- run: go test -race -json -v -coverpkg=./... -coverprofile=cover.out $(go list ./... | grep -v /cmd/dendrite*) 2>&1 | gotestfmt -hide all
env:
POSTGRES_HOST: localhost
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: dendrite
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
flags: unittests
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
# run database upgrade tests
upgrade_test:
@ -274,12 +275,22 @@ jobs:
needs: initial-tests-done
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
go-version-file: 'go.mod'
cache: true
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-upgrade-test-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-upgrade-test-
- name: Docker version
run: docker version
- name: Build upgrade-tests
run: go build ./cmd/dendrite-upgrade-tests
- name: Test upgrade (PostgreSQL)
@ -294,12 +305,22 @@ jobs:
needs: initial-tests-done
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: "stable"
go-version-file: 'go.mod'
cache: true
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-upgrade-direct-test-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-upgrade-direct-test-
- name: Docker version
run: docker version
- name: Build upgrade-tests
run: go build ./cmd/dendrite-upgrade-tests
- name: Test upgrade (PostgreSQL)
@ -336,8 +357,8 @@ jobs:
SYTEST_BRANCH: ${{ github.head_ref }}
CGO_ENABLED: ${{ matrix.cgo && 1 }}
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
@ -360,7 +381,7 @@ jobs:
run: /src/are-we-synapse-yet.py /logs/results.tap -v
continue-on-error: true # not fatal
- name: Upload Sytest logs
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: Sytest Logs - ${{ job.status }} - (Dendrite, ${{ join(matrix.*, ', ') }})
@ -400,8 +421,8 @@ jobs:
run: |
sudo apt-get update && sudo apt-get install -y libolm3 libolm-dev
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
- name: Run actions/checkout@v3 for dendrite
uses: actions/checkout@v3
- name: Run actions/checkout@v4 for dendrite
uses: actions/checkout@v4
with:
path: dendrite
@ -436,7 +457,7 @@ jobs:
# Run Complement
- run: |
set -o pipefail &&
go test -v -json -tags dendrite_blacklist ./tests/... 2>&1 | gotestfmt
go test -v -json -tags dendrite_blacklist ./tests ./tests/csapi 2>&1 | gotestfmt -hide all
shell: bash
name: Run Complement Tests
env:

View file

@ -27,26 +27,22 @@ jobs:
security-events: write # To upload Trivy sarif files
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Get release tag & build flags
if: github.event_name == 'release' # Only for GitHub releases
run: |
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
echo "BUILD=$(git rev-parse --short HEAD || \"\")" >> $GITHUB_ENV
BRANCH=$(git symbolic-ref --short HEAD | tr -d \/)
[ ${BRANCH} == "main" ] && BRANCH=""
echo "BRANCH=${BRANCH}" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Containers
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@ -60,7 +56,6 @@ jobs:
cache-from: type=registry,ref=ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-monolith:buildcache
cache-to: type=registry,ref=ghcr.io/${{ env.GHCR_NAMESPACE }}/dendrite-monolith:buildcache,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
platforms: ${{ env.PLATFORMS }}
push: true
tags: |
@ -75,7 +70,6 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
platforms: ${{ env.PLATFORMS }}
push: true
tags: |
@ -104,26 +98,22 @@ jobs:
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Get release tag & build flags
if: github.event_name == 'release' # Only for GitHub releases
run: |
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
echo "BUILD=$(git rev-parse --short HEAD || \"\")" >> $GITHUB_ENV
BRANCH=$(git symbolic-ref --short HEAD | tr -d \/)
[ ${BRANCH} == "main" ] && BRANCH=""
echo "BRANCH=${BRANCH}" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Containers
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@ -137,7 +127,6 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
file: ./build/docker/Dockerfile.demo-pinecone
platforms: ${{ env.PLATFORMS }}
push: true
@ -153,7 +142,6 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
file: ./build/docker/Dockerfile.demo-pinecone
platforms: ${{ env.PLATFORMS }}
push: true
@ -171,26 +159,22 @@ jobs:
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Get release tag & build flags
if: github.event_name == 'release' # Only for GitHub releases
run: |
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
echo "BUILD=$(git rev-parse --short HEAD || \"\")" >> $GITHUB_ENV
BRANCH=$(git symbolic-ref --short HEAD | tr -d \/)
[ ${BRANCH} == "main" ] && BRANCH=""
echo "BRANCH=${BRANCH}" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Containers
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@ -204,7 +188,6 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
file: ./build/docker/Dockerfile.demo-yggdrasil
platforms: ${{ env.PLATFORMS }}
push: true
@ -220,7 +203,6 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
context: .
build-args: FLAGS=-X github.com/matrix-org/dendrite/internal.branch=${{ env.BRANCH }} -X github.com/matrix-org/dendrite/internal.build=${{ env.BUILD }}
file: ./build/docker/Dockerfile.demo-yggdrasil
platforms: ${{ env.PLATFORMS }}
push: true

View file

@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Build with Jekyll

View file

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -32,7 +32,7 @@ jobs:
version: v3.10.0
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.4.1
uses: helm/chart-releaser-action@v1.6.0
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
with:

View file

@ -17,7 +17,7 @@ jobs:
outputs:
changed: ${{ steps.list-changed.outputs.changed }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: azure/setup-helm@v3
@ -48,7 +48,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.checkoutCommit }}
@ -66,7 +66,7 @@ jobs:
- name: Create k3d cluster
uses: nolar/setup-k3d-k3s@v1
with:
version: v1.21
version: v1.28
- name: Remove node taints
run: |
kubectl taint --all=true nodes node.cloudprovider.kubernetes.io/uninitialized- || true

View file

@ -10,8 +10,26 @@ concurrency:
cancel-in-progress: true
jobs:
check_date: # https://stackoverflow.com/questions/63014786/how-to-schedule-a-github-actions-nightly-build-but-run-it-only-when-there-where
runs-on: ubuntu-latest
name: Check latest commit
outputs:
should_run: ${{ steps.should_run.outputs.should_run }}
steps:
- uses: actions/checkout@v4
- name: print latest_commit
run: echo ${{ github.sha }}
- id: should_run
continue-on-error: true
name: check latest commit is less than a day
if: ${{ github.event_name == 'schedule' }}
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"
# run Sytest in different variations
sytest:
needs: check_date
if: ${{ needs.check_date.outputs.should_run != 'false' }}
timeout-minutes: 60
name: "Sytest (${{ matrix.label }})"
runs-on: ubuntu-latest
@ -38,8 +56,8 @@ jobs:
RACE_DETECTION: 1
COVER: 1
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: |
~/.cache/go-build
@ -62,7 +80,7 @@ jobs:
run: /src/are-we-synapse-yet.py /logs/results.tap -v
continue-on-error: true # not fatal
- name: Upload Sytest logs
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: Sytest Logs - ${{ job.status }} - (Dendrite ${{ join(matrix.*, ' ') }})
@ -75,31 +93,34 @@ jobs:
timeout-minutes: 5
name: "Sytest Coverage"
runs-on: ubuntu-latest
needs: sytest # only run once Sytest is done
if: ${{ always() }}
needs: [ sytest, check_date ] # only run once Sytest is done and there was a commit
if: ${{ always() && needs.check_date.outputs.should_run != 'false' }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: 'stable'
cache: true
- name: Download all artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
- name: Collect coverage
run: |
go tool covdata textfmt -i="$(find Sytest* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)" -o sytest.cov
grep -Ev 'relayapi|setup/mscs|api_trace' sytest.cov > final.cov
go tool covdata func -i="$(find Sytest* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)"
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
files: ./final.cov
flags: sytest
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
# run Complement
complement:
needs: check_date
if: ${{ needs.check_date.outputs.should_run != 'false' }}
name: "Complement (${{ matrix.label }})"
timeout-minutes: 60
runs-on: ubuntu-latest
@ -128,9 +149,9 @@ jobs:
# See https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md specifically GOROOT_1_17_X64
run: |
sudo apt-get update && sudo apt-get install -y libolm3 libolm-dev
go get -v github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
- name: Run actions/checkout@v3 for dendrite
uses: actions/checkout@v3
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
- name: Run actions/checkout@v4 for dendrite
uses: actions/checkout@v4
with:
path: dendrite
@ -174,7 +195,7 @@ jobs:
# Run Complement
- run: |
set -o pipefail &&
go test -v -json -tags dendrite_blacklist ./tests/... 2>&1 | gotestfmt
go test -v -json -tags dendrite_blacklist ./tests ./tests/csapi 2>&1 | gotestfmt -hide all
shell: bash
name: Run Complement Tests
env:
@ -185,7 +206,7 @@ jobs:
working-directory: complement
- name: Upload Complement logs
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: Complement Logs - (Dendrite ${{ join(matrix.*, ' ') }})
@ -196,30 +217,32 @@ jobs:
timeout-minutes: 5
name: "Complement Coverage"
runs-on: ubuntu-latest
needs: complement # only run once Complement is done
if: ${{ always() }}
needs: [ complement, check_date ] # only run once Complements is done and there was a commit
if: ${{ always() && needs.check_date.outputs.should_run != 'false' }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: 'stable'
cache: true
- name: Download all artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
- name: Collect coverage
run: |
go tool covdata textfmt -i="$(find Complement* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)" -o complement.cov
grep -Ev 'relayapi|setup/mscs|api_trace' complement.cov > final.cov
go tool covdata func -i="$(find Complement* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)"
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
files: ./final.cov
flags: complement
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }} # required
element-web:
if: ${{ false }} # disable for now, as Cypress has been replaced by Playwright
timeout-minutes: 120
runs-on: ubuntu-latest
steps:
@ -228,7 +251,7 @@ jobs:
# Our test suite includes some screenshot tests with unusual diacritics, which are
# supposed to be covered by STIXGeneral.
tools: fonts-stix
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
repository: matrix-org/matrix-react-sdk
- uses: actions/setup-node@v3
@ -259,6 +282,7 @@ jobs:
TMPDIR: ${{ runner.temp }}
element-web-pinecone:
if: ${{ false }} # disable for now, as Cypress has been replaced by Playwright
timeout-minutes: 120
runs-on: ubuntu-latest
steps:
@ -267,7 +291,7 @@ jobs:
# Our test suite includes some screenshot tests with unusual diacritics, which are
# supposed to be covered by STIXGeneral.
tools: fonts-stix
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
repository: matrix-org/matrix-react-sdk
- uses: actions/setup-node@v3

5
.gitignore vendored
View file

@ -77,4 +77,7 @@ media_store/
build
# golang workspaces
go.work*
go.work*
# helm chart
helm/dendrite/charts/

View file

@ -6,7 +6,7 @@ run:
concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
deadline: 30m
timeout: 5m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
@ -18,24 +18,6 @@ run:
#build-tags:
# - mytag
# which dirs to skip: they won't be analyzed;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but next dirs are always skipped independently
# from this option's value:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs:
- bin
- docs
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
skip-files:
- ".*\\.md$"
- ".*\\.sh$"
- "^cmd/syncserver-integration-tests/testdata.go$"
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes
@ -50,7 +32,8 @@ run:
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: colored-line-number
formats:
- format: colored-line-number
# print lines of code with issue, default is true
print-issued-lines: true
@ -79,9 +62,8 @@ linters-settings:
# see https://github.com/kisielk/errcheck#excluding-functions for details
#exclude: /path/to/file.txt
govet:
# report about shadowed variables
check-shadowing: true
enable:
- shadow
# settings per analyzer
settings:
printf: # analyzer name, run `go tool vet help` to see all analyzers
@ -180,7 +162,6 @@ linters-settings:
linters:
enable:
- errcheck
- goconst
- gocyclo
- goimports # Does everything gofmt does
- gosimple
@ -211,12 +192,31 @@ linters:
- stylecheck
- typecheck # Should turn back on soon
- unconvert # Should turn back on soon
- goconst # Slightly annoying, as it reports "issues" in SQL statements
disable-all: false
presets:
fast: false
issues:
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
exclude-files:
- ".*\\.md$"
- ".*\\.sh$"
- "^cmd/syncserver-integration-tests/testdata.go$"
# which dirs to skip: they won't be analyzed;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but next dirs are always skipped independently
# from this option's value:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
exclude-dirs:
- bin
- docs
# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all

View file

@ -1,5 +1,155 @@
# Changelog
## Dendrite 0.13.8 (2024-09-13)
### Features
- The required Go version to build Dendrite is now 1.21
- Support for authenticated media ([MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916)) has been added
- NATS can now connect to servers requiring authentication (contributed by [paigeadelethompson](https://github.com/paigeadelethompson))
- Updated dependencies
- Internal NATS Server has been updated from v2.10.7 to v2.10.20 (contributed by [neilalexander](https://github.com/neilalexander))
### Fixes
- Fix parsing `?ts` query param (contributed by [tulir](https://github.com/tulir))
- Don't query the database if we could fetch all keys from cache
- Fix media DB potentially leaking connections
- Fixed a bug where we would return that an account exists if we encountered an unhandled error case
- Fixed an issues where edited message could appear twice in search results (contributed by [adnull](https://github.com/adnull))
- Outgoing threepid HTTP requests now correctly close the returned body (contributed by [ testwill](https://github.com/testwill))
- Presence conflicts are handled better, reducing the amount of outgoing federation requests (contributed by [jjj333-p](https://github.com/jjj333-p))
- Internal NATS now uses `SyncAlways` which should improve resilience against crashes (contributed by [neilalexander](https://github.com/neilalexander))
- Whitespaces in the `X-Matrix` header are now handled correctly
- `/.well-known/matrix/server` lookups now timeout after 30 seconds
- Purging rooms has seen a huge speed-up
## Dendrite 0.13.7 (2024-04-09)
### Fixes
- Fixed an issue where the displayname/avatar of an invited user was replaced with the inviter's details
- Improved server startup performance by avoiding unnecessary room ACL queries
- This change reduces memory footprint as it caches ACL regex patterns once instead of for each room
- Unnecessary Relay related queries have been removed. **Note**: To use relays, you now need to explicitly enable them using the `federation_api.enable_relays` config
- Fixed space summaries over federation
- Improved usage of external NATS JetStream by reusing existing connections instead of opening new ones unnecessarily
### Features
- Modernized Appservices (contributed by [tulir](https://github.com/tulir))
- Added event reporting with Synapse Admin endpoints for querying them
- Updated dependencies
## Dendrite 0.13.6 (2024-01-26)
Upgrading to this version is **highly** recommended, as it contains several QoL improvements.
### Fixes
- Use `AckExplicitPolicy` for JetStream consumers, so messages don't pile up in NATS
- A rare panic when assigning a state key NID has been fixed
- A rare panic when checking powerlevels has been fixed
- Notary keys requests for all keys now work correctly
- Spec compliance:
- Return `M_INVALID_PARAM` when querying room aliases
- Handle empty `from` parameter when requesting `/messages`
- Add CORP headers on media endpoints
- Remove `aliases` from `/publicRooms` responses
- Allow `+` in MXIDs (Contributed by [RosstheRoss](https://github.com/RosstheRoss))
- Fixes membership transitions from `knock` to `join` in `knock_restricted` rooms
- Incremental syncs now batch querying events (Contributed by [recht](https://github.com/recht))
- Move `/joined_members` back to the clientAPI/roomserver, which should make bridges happier again
- Backfilling from other servers now only uses at max 100 events instead of potentially thousands
## Dendrite 0.13.5 (2023-12-12)
Upgrading to this version is **highly** recommended, as it fixes several long-standing bugs in
our CanonicalJSON implementation.
### Fixes
- Convert unicode escapes to lowercase (gomatrixserverlib)
- Fix canonical json utf-16 surrogate pair detection logic (gomatrixserverlib)
- Handle negative zero and exponential numbers in Canonical JSON verification (gomatrixserverlib)
- Avoid logging unnecessary messages when unable to fetch server keys if multiple fetchers are used (gomatrixserverlib)
- Issues around the device list updater have been fixed, which should ensure that there are always
workers available to process incoming device list updates.
- A panic in the `/hierarchy` endpoints used for spaces has been fixed (client-server and server-server API)
- Fixes around the way we handle database transactions (including a potential connection leak)
- ACLs are now updated when received as outliers
- A race condition, which could lead to bridges instantly leaving a room after joining it, between the SyncAPI and
Appservices has been fixed
### Features
- **Appservice login is now supported!**
- Users can now kick themselves (used by some bridges)
## Dendrite 0.13.4 (2023-10-25)
Upgrading to this version is **highly** recommended, as it fixes a long-standing bug in the state resolution
algorithm.
### Fixes:
- The "device list updater" now de-duplicates the servers to fetch devices from on startup. (This also
avoids spamming the logs when shutting down.)
- A bug in the state resolution algorithm has been fixed. This bug could result in users "being reset"
out of rooms and other missing state events due to calculating the wrong state.
- A bug when setting notifications from Element Android has been fixed by implementing MSC3987
### Features
- Updated dependencies
- Internal NATS Server has been updated from v2.9.19 to v2.9.23
## Dendrite 0.13.3 (2023-09-28)
### Fixes:
- The `user_id` query parameter when authenticating is now used correctly (contributed by [tulir](https://github.com/tulir))
- Invitations are now correctly pushed to devices
- A bug which could result in the corruption of `m.direct` account data has been fixed
### Features
- [Sliding Sync proxy](https://github.com/matrix-org/sliding-sync) can be configured in the `/.well-known/matrix/client` response
- Room version 11 is now supported
- Clients can request the `federation` `event_format` when creating filters
- Many under the hood improvements for [MSC4014: Pseudonymous Identities](https://github.com/matrix-org/matrix-spec-proposals/blob/kegan/pseudo-ids/proposals/4014-pseudonymous-identities.md)
### Other
- Dendrite now requires Go 1.20 if building from source
## Dendrite 0.13.2 (2023-08-23)
### Fixes:
- Migrations in SQLite are now prepared on the correct context (transaction or database)
- The `InputRoomEvent` stream now has a maximum age of 24h, which should help with slow start up times of NATS JetStream (contributed by [neilalexander](https://github.com/neilalexander))
- Event size checks are more in line with Synapse
- Requests to `/messages` have been optimized, possibly reducing database round trips
- Re-add the revision of Dendrite when building from source (Note: This only works if git is installed)
- Getting local members to notify has been optimized, which should significantly reduce memory allocation and cache usage
- When getting queried about user profiles, we now return HTTP404 if the user/profiles does not exist
- Background federated joins should now be fixed and not timeout after a short time
- Database connections are now correctly re-used
- Restored the old behavior of the `/purgeRoom` admin endpoint (does not evacuate the room before purging)
- Don't expose information about the system when trying to download files that don't exist
### Features
- Further improvements and fixes for [MSC4014: Pseudonymous Identities](https://github.com/matrix-org/matrix-spec-proposals/blob/kegan/pseudo-ids/proposals/4014-pseudonymous-identities.md)
- Lookup correct prev events in the sync API
- Populate `prev_sender` correctly in the sync API
- Event federation should work better
- Added new `dendrite_up` Prometheus metric, containing the version of Dendrite
- Space summaries ([MSC2946](https://github.com/matrix-org/matrix-spec-proposals/pull/2946)) have been moved from MSC to being natively supported
- For easier issue investigation, logs for application services now contain the application service ID (contributed by [maxberger](https://github.com/maxberger))
- The default room version to use when creating rooms can now be configured using `room_server.default_room_version`
## Dendrite 0.13.1 (2023-07-06)
This releases fixes a long-standing "off-by-one" error which could result in state resets. Upgrading to this version is **highly** recommended.

59
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,59 @@
# Contributing to Dendrite
Thank you for taking the time to contribute to Matrix!
This is the repository for Dendrite, a second-generation Matrix homeserver written in Go.
## Sign off
We ask that everybody who contributes to this project signs off their contributions, as explained below.
We follow a simple 'inbound=outbound' model for contributions: the act of submitting an 'inbound' contribution means that the contributor agrees to license their contribution under the same terms as the project's overall 'outbound' license - in our case, this is Apache Software License v2 (see [LICENSE](./LICENSE)).
In order to have a concrete record that your contribution is intentional and you agree to license it under the same terms as the project's license, we've adopted the same lightweight approach used by the [Linux Kernel](https://www.kernel.org/doc/html/latest/process/submitting-patches.html), [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other projects: the [Developer Certificate of Origin](https://developercertificate.org/) (DCO). This is a simple declaration that you wrote the contribution or otherwise have the right to contribute it to Matrix:
```
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
If you agree to this for your contribution, then all that's needed is to include the line in your commit or pull request comment:
```
Signed-off-by: Your Name <your@email.example.org>
```
Git allows you to add this signoff automatically when using the `-s` flag to `git commit`, which uses the name and email set in your `user.name` and `user.email` git configs.

View file

@ -3,7 +3,7 @@
#
# base installs required dependencies and runs go mod download to cache dependencies
#
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.20-alpine AS base
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.22-alpine AS base
RUN apk --update --no-cache add bash build-base curl git
#
@ -13,7 +13,6 @@ FROM --platform=${BUILDPLATFORM} base AS build
WORKDIR /src
ARG TARGETOS
ARG TARGETARCH
ARG FLAGS
RUN --mount=target=. \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
@ -21,7 +20,7 @@ RUN --mount=target=. \
GOARCH="$TARGETARCH" \
GOOS="linux" \
CGO_ENABLED=$([ "$TARGETARCH" = "$USERARCH" ] && echo "1" || echo "0") \
go build -v -ldflags="${FLAGS}" -trimpath -o /out/ ./cmd/...
go build -v -trimpath -o /out/ ./cmd/...
#

View file

@ -1,5 +1,13 @@
# Dendrite
## Dendrite is now maintained at [element-hq/dendrite](https://github.com/element-hq/dendrite)
Dendrite is an open-source [Matrix](https://matrix.org/) homeserver developed from 2019 through 2023 as part of the Matrix.org Foundation.
The Matrix.org Foundation is not able to resource maintenance of Dendrite and it [continues to be developed by Element](https://github.com/element-hq/dendrite)
additionally you have the choice of [other Matrix homeservers](https://matrix.org/ecosystem/servers/)
See [The future of Synapse and Dendrite](https://matrix.org/blog/2023/11/06/future-of-synapse-dendrite/) blog post for more information.
[![Build status](https://github.com/matrix-org/dendrite/actions/workflows/dendrite.yml/badge.svg?event=push)](https://github.com/matrix-org/dendrite/actions/workflows/dendrite.yml) [![Dendrite](https://img.shields.io/matrix/dendrite:matrix.org.svg?label=%23dendrite%3Amatrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#dendrite:matrix.org) [![Dendrite Dev](https://img.shields.io/matrix/dendrite-dev:matrix.org.svg?label=%23dendrite-dev%3Amatrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#dendrite-dev:matrix.org)
Dendrite is a second-generation Matrix homeserver written in Go.
@ -36,7 +44,7 @@ If you have further questions, please take a look at [our FAQ](docs/FAQ.md) or j
See the [Planning your Installation](https://matrix-org.github.io/dendrite/installation/planning) page for
more information on requirements.
To build Dendrite, you will need Go 1.18 or later.
To build Dendrite, you will need Go 1.21 or later.
For a usable federating Dendrite deployment, you will also need:

View file

@ -82,9 +82,17 @@ type UserIDExistsResponse struct {
}
const (
ASProtocolPath = "/_matrix/app/unstable/thirdparty/protocol/"
ASUserPath = "/_matrix/app/unstable/thirdparty/user"
ASLocationPath = "/_matrix/app/unstable/thirdparty/location"
ASProtocolLegacyPath = "/_matrix/app/unstable/thirdparty/protocol/"
ASUserLegacyPath = "/_matrix/app/unstable/thirdparty/user"
ASLocationLegacyPath = "/_matrix/app/unstable/thirdparty/location"
ASRoomAliasExistsLegacyPath = "/rooms/"
ASUserExistsLegacyPath = "/users/"
ASProtocolPath = "/_matrix/app/v1/thirdparty/protocol/"
ASUserPath = "/_matrix/app/v1/thirdparty/user"
ASLocationPath = "/_matrix/app/v1/thirdparty/location"
ASRoomAliasExistsPath = "/_matrix/app/v1/rooms/"
ASUserExistsPath = "/_matrix/app/v1/users/"
)
type ProtocolRequest struct {

View file

@ -14,7 +14,18 @@ import (
"testing"
"time"
"github.com/matrix-org/dendrite/clientapi"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/federationapi/statistics"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/syncapi"
uapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
"github.com/nats-io/nats.go"
"github.com/stretchr/testify/assert"
"github.com/tidwall/gjson"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/appservice/api"
@ -32,6 +43,10 @@ import (
"github.com/matrix-org/dendrite/test/testrig"
)
var testIsBlacklistedOrBackingOff = func(s spec.ServerName) (*statistics.ServerStatistics, error) {
return &statistics.ServerStatistics{}, nil
}
func TestAppserviceInternalAPI(t *testing.T) {
// Set expected results
@ -144,7 +159,7 @@ func TestAppserviceInternalAPI(t *testing.T) {
cm := sqlutil.NewConnectionManager(ctx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(ctx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
usrAPI := userapi.NewInternalAPI(ctx, cfg, cm, &natsInstance, rsAPI, nil)
usrAPI := userapi.NewInternalAPI(ctx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(ctx, cfg, &natsInstance, usrAPI, rsAPI)
runCases(t, asAPI)
@ -239,7 +254,7 @@ func TestAppserviceInternalAPI_UnixSocket_Simple(t *testing.T) {
cm := sqlutil.NewConnectionManager(ctx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(ctx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
usrAPI := userapi.NewInternalAPI(ctx, cfg, cm, &natsInstance, rsAPI, nil)
usrAPI := userapi.NewInternalAPI(ctx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(ctx, cfg, &natsInstance, usrAPI, rsAPI)
t.Run("UserIDExists", func(t *testing.T) {
@ -378,7 +393,7 @@ func TestRoomserverConsumerOneInvite(t *testing.T) {
// Create required internal APIs
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
usrAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil)
usrAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// start the consumer
appservice.NewInternalAPI(processCtx, cfg, natsInstance, usrAPI, rsAPI)
@ -402,3 +417,190 @@ func TestRoomserverConsumerOneInvite(t *testing.T) {
close(evChan)
})
}
// Note: If this test panics, it is because we timed out waiting for the
// join event to come through to the appservice and we close the DB/shutdown Dendrite. This makes the
// syncAPI unhappy, as it is unable to write to the database.
func TestOutputAppserviceEvent(t *testing.T) {
alice := test.NewUser(t)
bob := test.NewUser(t)
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
cfg, processCtx, closeDB := testrig.CreateConfig(t, dbType)
defer closeDB()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
natsInstance := &jetstream.NATSInstance{}
evChan := make(chan struct{})
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
// Create required internal APIs
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
// Create the router, so we can hit `/joined_members`
routers := httputil.NewRouters()
accessTokens := map[*test.User]userDevice{
bob: {},
}
usrAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
clientapi.AddPublicRoutes(processCtx, routers, cfg, natsInstance, nil, rsAPI, nil, nil, nil, usrAPI, nil, nil, caching.DisableMetrics)
createAccessTokens(t, accessTokens, usrAPI, processCtx.Context(), routers)
room := test.NewRoom(t, alice)
// Invite Bob
room.CreateAndInsert(t, alice, spec.MRoomMember, map[string]interface{}{
"membership": "invite",
}, test.WithStateKey(bob.ID))
// create a dummy AS url, handling the events
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var txn consumers.ApplicationServiceTransaction
err := json.NewDecoder(r.Body).Decode(&txn)
if err != nil {
t.Fatal(err)
}
for _, ev := range txn.Events {
if ev.Type != spec.MRoomMember {
continue
}
if ev.StateKey != nil && *ev.StateKey == bob.ID {
membership := gjson.GetBytes(ev.Content, "membership").Str
t.Logf("Processing membership: %s", membership)
switch membership {
case spec.Invite:
// Accept the invite
joinEv := room.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
"membership": "join",
}, test.WithStateKey(bob.ID))
if err := rsapi.SendEvents(context.Background(), rsAPI, rsapi.KindNew, []*types.HeaderedEvent{joinEv}, "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
case spec.Join: // the AS has received the join event, now hit `/joined_members` to validate that
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/_matrix/client/v3/rooms/"+room.ID+"/joined_members", nil)
req.Header.Set("Authorization", "Bearer "+accessTokens[bob].accessToken)
routers.Client.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected HTTP 200, got %d: %s", rec.Code, rec.Body.String())
}
// Both Alice and Bob should be joined. If not, we have a race condition
if !gjson.GetBytes(rec.Body.Bytes(), "joined."+alice.ID).Exists() {
t.Errorf("Alice is not joined to the room") // in theory should not happen
}
if !gjson.GetBytes(rec.Body.Bytes(), "joined."+bob.ID).Exists() {
t.Errorf("Bob is not joined to the room")
}
evChan <- struct{}{}
default:
t.Fatalf("Unexpected membership: %s", membership)
}
}
}
}))
defer srv.Close()
as := &config.ApplicationService{
ID: "someID",
URL: srv.URL,
ASToken: "",
HSToken: "",
SenderLocalpart: "senderLocalPart",
NamespaceMap: map[string][]config.ApplicationServiceNamespace{
"users": {{RegexpObject: regexp.MustCompile(bob.ID)}},
"aliases": {{RegexpObject: regexp.MustCompile(room.ID)}},
},
}
as.CreateHTTPClient(cfg.AppServiceAPI.DisableTLSValidation)
// Create a dummy application service
cfg.AppServiceAPI.Derived.ApplicationServices = []config.ApplicationService{*as}
// Prepare AS Streams on the old topic to validate that they get deleted
jsCtx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
token := jetstream.Tokenise(as.ID)
if err := jetstream.JetStreamConsumer(
processCtx.Context(), jsCtx, cfg.Global.JetStream.Prefixed(jetstream.OutputRoomEvent),
cfg.Global.JetStream.Durable("Appservice_"+token),
50, // maximum number of events to send in a single transaction
func(ctx context.Context, msgs []*nats.Msg) bool {
return true
},
); err != nil {
t.Fatal(err)
}
// Start the syncAPI to have `/joined_members` available
syncapi.AddPublicRoutes(processCtx, routers, cfg, cm, natsInstance, usrAPI, rsAPI, caches, caching.DisableMetrics)
// start the consumer
appservice.NewInternalAPI(processCtx, cfg, natsInstance, usrAPI, rsAPI)
// At this point, the old JetStream consumers should be deleted
for consumer := range jsCtx.Consumers(cfg.Global.JetStream.Prefixed(jetstream.OutputRoomEvent)) {
if consumer.Name == cfg.Global.JetStream.Durable("Appservice_"+token)+"Pull" {
t.Fatalf("Consumer still exists")
}
}
// Create the room, this triggers the AS to receive an invite for Bob.
if err := rsapi.SendEvents(context.Background(), rsAPI, rsapi.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
select {
// Pretty generous timeout duration...
case <-time.After(time.Millisecond * 1000): // wait for the AS to process the events
t.Errorf("Timed out waiting for join event")
case <-evChan:
}
close(evChan)
})
}
type userDevice struct {
accessToken string
deviceID string
password string
}
func createAccessTokens(t *testing.T, accessTokens map[*test.User]userDevice, userAPI uapi.UserInternalAPI, ctx context.Context, routers httputil.Routers) {
t.Helper()
for u := range accessTokens {
localpart, serverName, _ := gomatrixserverlib.SplitID('@', u.ID)
userRes := &uapi.PerformAccountCreationResponse{}
password := util.RandomString(8)
if err := userAPI.PerformAccountCreation(ctx, &uapi.PerformAccountCreationRequest{
AccountType: u.AccountType,
Localpart: localpart,
ServerName: serverName,
Password: password,
}, userRes); err != nil {
t.Errorf("failed to create account: %s", err)
}
req := test.NewRequest(t, http.MethodPost, "/_matrix/client/v3/login", test.WithJSONBody(t, map[string]interface{}{
"type": authtypes.LoginTypePassword,
"identifier": map[string]interface{}{
"type": "m.id.user",
"user": u.ID,
},
"password": password,
}))
rec := httptest.NewRecorder()
routers.Client.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("failed to login: %s", rec.Body.String())
}
accessTokens[u] = userDevice{
accessToken: gjson.GetBytes(rec.Body.Bytes(), "access_token").String(),
deviceID: gjson.GetBytes(rec.Body.Bytes(), "device_id").String(),
password: password,
}
}
}

View file

@ -71,13 +71,14 @@ func NewOutputRoomEventConsumer(
ctx: process.Context(),
cfg: cfg,
jetstream: js,
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputRoomEvent),
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputAppserviceEvent),
rsAPI: rsAPI,
}
}
// Start consuming from room servers
func (s *OutputRoomEventConsumer) Start() error {
durableNames := make([]string, 0, len(s.cfg.Derived.ApplicationServices))
for _, as := range s.cfg.Derived.ApplicationServices {
appsvc := as
state := &appserviceState{
@ -95,6 +96,15 @@ func (s *OutputRoomEventConsumer) Start() error {
); err != nil {
return fmt.Errorf("failed to create %q consumer: %w", token, err)
}
durableNames = append(durableNames, s.cfg.Matrix.JetStream.Durable("Appservice_"+token))
}
// Cleanup any consumers still existing on the OutputRoomEvent stream
// to avoid messages not being deleted
for _, consumerName := range durableNames {
err := s.jetstream.DeleteConsumer(s.cfg.Matrix.JetStream.Prefixed(jetstream.OutputRoomEvent), consumerName+"Pull")
if err != nil && err != nats.ErrConsumerNotFound {
return err
}
}
return nil
}
@ -128,7 +138,7 @@ func (s *OutputRoomEventConsumer) onMessage(
if len(output.NewRoomEvent.AddsStateEventIDs) > 0 {
newEventID := output.NewRoomEvent.Event.EventID()
eventsReq := &api.QueryEventsByIDRequest{
RoomID: output.NewRoomEvent.Event.RoomID(),
RoomID: output.NewRoomEvent.Event.RoomID().String(),
EventIDs: make([]string, 0, len(output.NewRoomEvent.AddsStateEventIDs)),
}
eventsRes := &api.QueryEventsByIDResponse{}
@ -196,13 +206,21 @@ func (s *OutputRoomEventConsumer) sendEvents(
}
// Send the transaction to the appservice.
// https://matrix.org/docs/spec/application_service/r0.1.2#put-matrix-app-v1-transactions-txnid
address := fmt.Sprintf("%s/transactions/%s?access_token=%s", state.RequestUrl(), txnID, url.QueryEscape(state.HSToken))
// https://spec.matrix.org/v1.9/application-service-api/#pushing-events
path := "_matrix/app/v1/transactions"
if s.cfg.LegacyPaths {
path = "transactions"
}
address := fmt.Sprintf("%s/%s/%s", state.RequestUrl(), path, txnID)
if s.cfg.LegacyAuth {
address += "?access_token=" + url.QueryEscape(state.HSToken)
}
req, err := http.NewRequestWithContext(ctx, "PUT", address, bytes.NewBuffer(transaction))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", state.HSToken))
resp, err := state.HTTPClient.Do(req)
if err != nil {
return state.backoffAndPause(err)
@ -236,11 +254,7 @@ func (s *appserviceState) backoffAndPause(err error) error {
// TODO: This should be cached, see https://github.com/matrix-org/dendrite/issues/1682
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event *types.HeaderedEvent, appservice *config.ApplicationService) bool {
user := ""
validRoomID, err := spec.NewRoomID(event.RoomID())
if err != nil {
return false
}
userID, err := s.rsAPI.QueryUserIDForSender(ctx, *validRoomID, event.SenderID())
userID, err := s.rsAPI.QueryUserIDForSender(ctx, event.RoomID(), event.SenderID())
if err == nil {
user = userID.String()
}
@ -250,7 +264,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
return false
case appservice.IsInterestedInUserID(user):
return true
case appservice.IsInterestedInRoomID(event.RoomID()):
case appservice.IsInterestedInRoomID(event.RoomID().String()):
return true
}
@ -261,7 +275,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
}
// Check all known room aliases of the room the event came from
queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID()}
queryReq := api.GetAliasesForRoomIDRequest{RoomID: event.RoomID().String()}
var queryRes api.GetAliasesForRoomIDResponse
if err := s.rsAPI.GetAliasesForRoomID(ctx, &queryReq, &queryRes); err == nil {
for _, alias := range queryRes.Aliases {
@ -272,7 +286,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
} else {
log.WithFields(log.Fields{
"appservice": appservice.ID,
"room_id": event.RoomID(),
"room_id": event.RoomID().String(),
}).WithError(err).Errorf("Unable to get aliases for room")
}
@ -288,7 +302,7 @@ func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, e
// until we have a lighter way of checking the state before the event that
// doesn't involve state res, then this is probably OK.
membershipReq := &api.QueryMembershipsForRoomRequest{
RoomID: event.RoomID(),
RoomID: event.RoomID().String(),
JoinedOnly: true,
}
membershipRes := &api.QueryMembershipsForRoomResponse{}
@ -317,7 +331,7 @@ func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, e
} else {
log.WithFields(log.Fields{
"appservice": appservice.ID,
"room_id": event.RoomID(),
"room_id": event.RoomID().String(),
}).WithError(err).Errorf("Unable to get membership for room")
}
return false

View file

@ -19,10 +19,10 @@ package query
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"sync"
log "github.com/sirupsen/logrus"
@ -32,9 +32,6 @@ import (
"github.com/matrix-org/dendrite/setup/config"
)
const roomAliasExistsPath = "/rooms/"
const userIDExistsPath = "/users/"
// AppServiceQueryAPI is an implementation of api.AppServiceQueryAPI
type AppServiceQueryAPI struct {
Cfg *config.AppServiceAPI
@ -55,14 +52,23 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
// Determine which application service should handle this request
for _, appservice := range a.Cfg.Derived.ApplicationServices {
if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) {
path := api.ASRoomAliasExistsPath
if a.Cfg.LegacyPaths {
path = api.ASRoomAliasExistsLegacyPath
}
// The full path to the rooms API, includes hs token
URL, err := url.Parse(appservice.RequestUrl() + roomAliasExistsPath)
URL, err := url.Parse(appservice.RequestUrl() + path)
if err != nil {
return err
}
URL.Path += request.Alias
apiURL := URL.String() + "?access_token=" + appservice.HSToken
if a.Cfg.LegacyAuth {
q := URL.Query()
q.Set("access_token", appservice.HSToken)
URL.RawQuery = q.Encode()
}
apiURL := URL.String()
// Send a request to each application service. If one responds that it has
// created the room, immediately return.
@ -70,6 +76,7 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
if err != nil {
return err
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", appservice.HSToken))
req = req.WithContext(ctx)
resp, err := appservice.HTTPClient.Do(req)
@ -123,12 +130,21 @@ func (a *AppServiceQueryAPI) UserIDExists(
for _, appservice := range a.Cfg.Derived.ApplicationServices {
if appservice.URL != "" && appservice.IsInterestedInUserID(request.UserID) {
// The full path to the rooms API, includes hs token
URL, err := url.Parse(appservice.RequestUrl() + userIDExistsPath)
path := api.ASUserExistsPath
if a.Cfg.LegacyPaths {
path = api.ASUserExistsLegacyPath
}
URL, err := url.Parse(appservice.RequestUrl() + path)
if err != nil {
return err
}
URL.Path += request.UserID
apiURL := URL.String() + "?access_token=" + appservice.HSToken
if a.Cfg.LegacyAuth {
q := URL.Query()
q.Set("access_token", appservice.HSToken)
URL.RawQuery = q.Encode()
}
apiURL := URL.String()
// Send a request to each application service. If one responds that it has
// created the user, immediately return.
@ -136,6 +152,7 @@ func (a *AppServiceQueryAPI) UserIDExists(
if err != nil {
return err
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", appservice.HSToken))
resp, err := appservice.HTTPClient.Do(req.WithContext(ctx))
if resp != nil {
defer func() {
@ -176,25 +193,22 @@ type thirdpartyResponses interface {
api.ASProtocolResponse | []api.ASUserResponse | []api.ASLocationResponse
}
func requestDo[T thirdpartyResponses](client *http.Client, url string, response *T) (err error) {
origURL := url
// try v1 and unstable appservice endpoints
for _, version := range []string{"v1", "unstable"} {
var resp *http.Response
var body []byte
asURL := strings.Replace(origURL, "unstable", version, 1)
resp, err = client.Get(asURL)
if err != nil {
continue
}
defer resp.Body.Close() // nolint: errcheck
body, err = io.ReadAll(resp.Body)
if err != nil {
continue
}
return json.Unmarshal(body, &response)
func requestDo[T thirdpartyResponses](as *config.ApplicationService, url string, response *T) error {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err
}
return err
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", as.HSToken))
resp, err := as.HTTPClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close() // nolint: errcheck
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
return json.Unmarshal(body, &response)
}
func (a *AppServiceQueryAPI) Locations(
@ -207,17 +221,23 @@ func (a *AppServiceQueryAPI) Locations(
return err
}
path := api.ASLocationPath
if a.Cfg.LegacyPaths {
path = api.ASLocationLegacyPath
}
for _, as := range a.Cfg.Derived.ApplicationServices {
var asLocations []api.ASLocationResponse
params.Set("access_token", as.HSToken)
if a.Cfg.LegacyAuth {
params.Set("access_token", as.HSToken)
}
url := as.RequestUrl() + api.ASLocationPath
url := as.RequestUrl() + path
if req.Protocol != "" {
url += "/" + req.Protocol
}
if err := requestDo[[]api.ASLocationResponse](as.HTTPClient, url+"?"+params.Encode(), &asLocations); err != nil {
log.WithError(err).Error("unable to get 'locations' from application service")
if err := requestDo[[]api.ASLocationResponse](&as, url+"?"+params.Encode(), &asLocations); err != nil {
log.WithError(err).WithField("application_service", as.ID).Error("unable to get 'locations' from application service")
continue
}
@ -242,17 +262,23 @@ func (a *AppServiceQueryAPI) User(
return err
}
path := api.ASUserPath
if a.Cfg.LegacyPaths {
path = api.ASUserLegacyPath
}
for _, as := range a.Cfg.Derived.ApplicationServices {
var asUsers []api.ASUserResponse
params.Set("access_token", as.HSToken)
if a.Cfg.LegacyAuth {
params.Set("access_token", as.HSToken)
}
url := as.RequestUrl() + api.ASUserPath
url := as.RequestUrl() + path
if req.Protocol != "" {
url += "/" + req.Protocol
}
if err := requestDo[[]api.ASUserResponse](as.HTTPClient, url+"?"+params.Encode(), &asUsers); err != nil {
log.WithError(err).Error("unable to get 'user' from application service")
if err := requestDo[[]api.ASUserResponse](&as, url+"?"+params.Encode(), &asUsers); err != nil {
log.WithError(err).WithField("application_service", as.ID).Error("unable to get 'user' from application service")
continue
}
@ -272,6 +298,10 @@ func (a *AppServiceQueryAPI) Protocols(
req *api.ProtocolRequest,
resp *api.ProtocolResponse,
) error {
protocolPath := api.ASProtocolPath
if a.Cfg.LegacyPaths {
protocolPath = api.ASProtocolLegacyPath
}
// get a single protocol response
if req.Protocol != "" {
@ -289,8 +319,8 @@ func (a *AppServiceQueryAPI) Protocols(
response := api.ASProtocolResponse{}
for _, as := range a.Cfg.Derived.ApplicationServices {
var proto api.ASProtocolResponse
if err := requestDo[api.ASProtocolResponse](as.HTTPClient, as.RequestUrl()+api.ASProtocolPath+req.Protocol, &proto); err != nil {
log.WithError(err).Error("unable to get 'protocol' from application service")
if err := requestDo[api.ASProtocolResponse](&as, as.RequestUrl()+protocolPath+req.Protocol, &proto); err != nil {
log.WithError(err).WithField("application_service", as.ID).Error("unable to get 'protocol' from application service")
continue
}
@ -319,8 +349,8 @@ func (a *AppServiceQueryAPI) Protocols(
for _, as := range a.Cfg.Derived.ApplicationServices {
for _, p := range as.Protocols {
var proto api.ASProtocolResponse
if err := requestDo[api.ASProtocolResponse](as.HTTPClient, as.RequestUrl()+api.ASProtocolPath+p, &proto); err != nil {
log.WithError(err).Error("unable to get 'protocol' from application service")
if err := requestDo[api.ASProtocolResponse](&as, as.RequestUrl()+protocolPath+p, &proto); err != nil {
log.WithError(err).WithField("application_service", as.ID).Error("unable to get 'protocol' from application service")
continue
}
existing, ok := response[p]

View file

@ -944,4 +944,12 @@ rmv remote user can join room with version 10
rmv User can invite remote user to room with version 10
rmv Remote user can backfill in a room with version 10
rmv Can reject invites over federation for rooms with version 10
rmv Can receive redactions from regular users over federation in room version 10
rmv Can receive redactions from regular users over federation in room version 10
rmv User can create and send/receive messages in a room with version 11
rmv local user can join room with version 11
rmv User can invite local user to room with version 11
rmv remote user can join room with version 11
rmv User can invite remote user to room with version 11
rmv Remote user can backfill in a room with version 11
rmv Can reject invites over federation for rooms with version 11
rmv Can receive redactions from regular users over federation in room version 11

View file

@ -38,6 +38,7 @@ import (
"github.com/matrix-org/dendrite/setup/jetstream"
"github.com/matrix-org/dendrite/setup/process"
"github.com/matrix-org/dendrite/userapi"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/gomatrixserverlib"
@ -190,13 +191,13 @@ func startup() {
serverKeyAPI := &signing.YggdrasilKeys{}
keyRing := serverKeyAPI.KeyRing()
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation)
fedSenderAPI := federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, federation, rsAPI, caches, keyRing, true)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation, caching.EnableMetrics, fedSenderAPI.IsBlacklistedOrBackingOff)
asQuery := appservice.NewInternalAPI(
processCtx, cfg, &natsInstance, userAPI, rsAPI,
)
rsAPI.SetAppserviceAPI(asQuery)
fedSenderAPI := federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, federation, rsAPI, caches, keyRing, true)
rsAPI.SetFederationAPI(fedSenderAPI, keyRing)
monolith := setup.Monolith{

View file

@ -1,4 +1,4 @@
FROM docker.io/golang:1.19-alpine AS base
FROM docker.io/golang:1.22-alpine AS base
#
# Needs to be separate from the main Dockerfile for OpenShift,

View file

@ -1,4 +1,4 @@
FROM docker.io/golang:1.19-alpine AS base
FROM docker.io/golang:1.22 AS base
#
# Needs to be separate from the main Dockerfile for OpenShift,

View file

@ -216,7 +216,7 @@ func (m *DendriteMonolith) Start() {
processCtx, cfg, cm, &natsInstance, federation, rsAPI, caches, keyRing, true,
)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation, caching.EnableMetrics, fsAPI.IsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
rsAPI.SetAppserviceAPI(asAPI)

View file

@ -1,6 +1,6 @@
#syntax=docker/dockerfile:1.2
FROM golang:1.20-bullseye as build
FROM golang:1.22-bookworm as build
RUN apt-get update && apt-get install -y sqlite3
WORKDIR /build

View file

@ -8,7 +8,7 @@
#
# Use these mounts to make use of this dockerfile:
# COMPLEMENT_HOST_MOUNTS='/your/local/dendrite:/dendrite:ro;/your/go/path:/go:ro'
FROM golang:1.18-stretch
FROM golang:1.22-bookworm
RUN apt-get update && apt-get install -y sqlite3
ENV SERVER_NAME=localhost

View file

@ -1,19 +1,19 @@
#syntax=docker/dockerfile:1.2
FROM golang:1.20-bullseye as build
FROM golang:1.22-bookworm as build
RUN apt-get update && apt-get install -y postgresql
WORKDIR /build
# No password when connecting over localhost
RUN sed -i "s%127.0.0.1/32 md5%127.0.0.1/32 trust%g" /etc/postgresql/13/main/pg_hba.conf && \
# No password when connecting to Postgres
RUN sed -i "s%peer%trust%g" /etc/postgresql/15/main/pg_hba.conf && \
# Bump up max conns for moar concurrency
sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/13/main/postgresql.conf
sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/15/main/postgresql.conf
# This entry script starts postgres, waits for it to be up then starts dendrite
RUN echo '\
#!/bin/bash -eu \n\
pg_lsclusters \n\
pg_ctlcluster 13 main start \n\
pg_ctlcluster 15 main start \n\
\n\
until pg_isready \n\
do \n\
@ -50,7 +50,7 @@ EXPOSE 8008 8448
# At runtime, generate TLS cert based on the CA now mounted at /ca
# At runtime, replace the SERVER_NAME with what we are told
CMD /build/run_postgres.sh && ./generate-keys --keysize 1024 --server $SERVER_NAME --tls-cert server.crt --tls-key server.key --tls-authority-cert /complement/ca/ca.crt --tls-authority-key /complement/ca/ca.key && \
./generate-config -server $SERVER_NAME --ci --db postgresql://postgres@localhost/postgres?sslmode=disable > dendrite.yaml && \
./generate-config -server $SERVER_NAME --ci --db "user=postgres database=postgres host=/var/run/postgresql/" > dendrite.yaml && \
# Bump max_open_conns up here in the global database config
sed -i 's/max_open_conns:.*$/max_open_conns: 1990/g' dendrite.yaml && \
cp /complement/ca/ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates && \

View file

@ -15,5 +15,5 @@ tar -xzf master.tar.gz
# Run the tests!
cd complement-master
COMPLEMENT_BASE_IMAGE=complement-dendrite:latest go test -v -count=1 ./tests
COMPLEMENT_BASE_IMAGE=complement-dendrite:latest go test -v -count=1 ./tests ./tests/csapi

View file

@ -2,10 +2,12 @@ package clientapi
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
@ -45,7 +47,7 @@ func TestAdminCreateToken(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
aliceAdmin: {},
@ -196,7 +198,7 @@ func TestAdminListRegistrationTokens(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
aliceAdmin: {},
@ -314,7 +316,7 @@ func TestAdminGetRegistrationToken(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
aliceAdmin: {},
@ -415,7 +417,7 @@ func TestAdminDeleteRegistrationToken(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
aliceAdmin: {},
@ -509,7 +511,7 @@ func TestAdminUpdateRegistrationToken(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
aliceAdmin: {},
@ -693,7 +695,7 @@ func TestAdminResetPassword(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
// Needed for changing the password/login
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the userAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -791,7 +793,7 @@ func TestPurgeRoom(t *testing.T) {
fsAPI := federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, rsAPI, caches, nil, true)
rsAPI.SetFederationAPI(fsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
syncapi.AddPublicRoutes(processCtx, routers, cfg, cm, &natsInstance, userAPI, rsAPI, caches, caching.DisableMetrics)
// Create the room
@ -863,7 +865,7 @@ func TestAdminEvacuateRoom(t *testing.T) {
fsAPI := federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, rsAPI, caches, nil, true)
rsAPI.SetFederationAPI(fsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// Create the room
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", api.DoNotSendToOtherServers, nil, false); err != nil {
@ -964,7 +966,7 @@ func TestAdminEvacuateUser(t *testing.T) {
fsAPI := federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, basepkg.CreateFederationClient(cfg, nil), rsAPI, caches, nil, true)
rsAPI.SetFederationAPI(fsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// Create the room
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", api.DoNotSendToOtherServers, nil, false); err != nil {
@ -1055,7 +1057,7 @@ func TestAdminMarkAsStale(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -1092,3 +1094,382 @@ func TestAdminMarkAsStale(t *testing.T) {
}
})
}
func TestAdminQueryEventReports(t *testing.T) {
alice := test.NewUser(t, test.WithAccountType(uapi.AccountTypeAdmin))
bob := test.NewUser(t)
room := test.NewRoom(t, alice)
room2 := test.NewRoom(t, alice)
// room2 has a name and canonical alias
room2.CreateAndInsert(t, alice, spec.MRoomName, map[string]string{"name": "Testing"}, test.WithStateKey(""))
room2.CreateAndInsert(t, alice, spec.MRoomCanonicalAlias, map[string]string{"alias": "#testing"}, test.WithStateKey(""))
// Join the rooms with Bob
room.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
"membership": "join",
}, test.WithStateKey(bob.ID))
room2.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
"membership": "join",
}, test.WithStateKey(bob.ID))
// Create a few events to report
eventsToReportPerRoom := make(map[string][]string)
for i := 0; i < 10; i++ {
ev1 := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": "hello world"})
ev2 := room2.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": "hello world"})
eventsToReportPerRoom[room.ID] = append(eventsToReportPerRoom[room.ID], ev1.EventID())
eventsToReportPerRoom[room2.ID] = append(eventsToReportPerRoom[room2.ID], ev2.EventID())
}
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
/*if dbType == test.DBTypeSQLite {
t.Skip()
}*/
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
routers := httputil.NewRouters()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
defer close()
natsInstance := jetstream.NATSInstance{}
jsctx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &cfg.Global.JetStream)
// Use an actual roomserver for this
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
if err := api.SendEvents(context.Background(), rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
if err := api.SendEvents(context.Background(), rsAPI, api.KindNew, room2.Events(), "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
alice: {},
bob: {},
}
createAccessTokens(t, accessTokens, userAPI, processCtx.Context(), routers)
reqBody := map[string]any{
"reason": "baaad",
"score": -100,
}
body, err := json.Marshal(reqBody)
if err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
var req *http.Request
// Report all events
for roomID, eventIDs := range eventsToReportPerRoom {
for _, eventID := range eventIDs {
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/_matrix/client/v3/rooms/%s/report/%s", roomID, eventID), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[bob].accessToken)
routers.Client.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected report to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
}
}
type response struct {
EventReports []api.QueryAdminEventReportsResponse `json:"event_reports"`
Total int64 `json:"total"`
NextToken *int64 `json:"next_token,omitempty"`
}
t.Run("Can query all reports", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/_synapse/admin/v1/event_reports", strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting reports to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
var resp response
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
wantCount := 20
// Only validating the count
if len(resp.EventReports) != wantCount {
t.Fatalf("expected %d events, got %d", wantCount, len(resp.EventReports))
}
if resp.Total != int64(wantCount) {
t.Fatalf("expected total to be %d, got %d", wantCount, resp.Total)
}
})
t.Run("Can filter on room", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/_synapse/admin/v1/event_reports?room_id=%s", room.ID), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting reports to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
var resp response
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
wantCount := 10
// Only validating the count
if len(resp.EventReports) != wantCount {
t.Fatalf("expected %d events, got %d", wantCount, len(resp.EventReports))
}
if resp.Total != int64(wantCount) {
t.Fatalf("expected total to be %d, got %d", wantCount, resp.Total)
}
})
t.Run("Can filter on user_id", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/_synapse/admin/v1/event_reports?user_id=%s", "@doesnotexist:test"), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting reports to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
var resp response
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
// The user does not exist, so we expect no results
wantCount := 0
// Only validating the count
if len(resp.EventReports) != wantCount {
t.Fatalf("expected %d events, got %d", wantCount, len(resp.EventReports))
}
if resp.Total != int64(wantCount) {
t.Fatalf("expected total to be %d, got %d", wantCount, resp.Total)
}
})
t.Run("Can set direction=f", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/_synapse/admin/v1/event_reports?room_id=%s&dir=f", room.ID), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting reports to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
var resp response
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
wantCount := 10
// Only validating the count
if len(resp.EventReports) != wantCount {
t.Fatalf("expected %d events, got %d", wantCount, len(resp.EventReports))
}
if resp.Total != int64(wantCount) {
t.Fatalf("expected total to be %d, got %d", wantCount, resp.Total)
}
// we now should have the first reported event
wantEventID := eventsToReportPerRoom[room.ID][0]
gotEventID := resp.EventReports[0].EventID
if gotEventID != wantEventID {
t.Fatalf("expected eventID to be %v, got %v", wantEventID, gotEventID)
}
})
t.Run("Can limit and paginate", func(t *testing.T) {
var from int64 = 0
var limit int64 = 5
var wantTotal int64 = 10 // We expect there to be 10 events in total
var resp response
for from+limit <= wantTotal {
resp = response{}
t.Logf("Getting reports starting from %d", from)
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/_synapse/admin/v1/event_reports?room_id=%s&limit=%d&from=%d", room2.ID, limit, from), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting reports to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
wantCount := 5 // we are limited to 5
if len(resp.EventReports) != wantCount {
t.Fatalf("expected %d events, got %d", wantCount, len(resp.EventReports))
}
if resp.Total != int64(wantTotal) {
t.Fatalf("expected total to be %d, got %d", wantCount, resp.Total)
}
// We've reached the end
if (from + int64(len(resp.EventReports))) == wantTotal {
return
}
// The next_token should be set
if resp.NextToken == nil {
t.Fatal("expected nextToken to be set")
}
from = *resp.NextToken
}
})
})
}
func TestEventReportsGetDelete(t *testing.T) {
alice := test.NewUser(t, test.WithAccountType(uapi.AccountTypeAdmin))
bob := test.NewUser(t)
room := test.NewRoom(t, alice)
// Add a name and alias
roomName := "Testing"
alias := "#testing"
room.CreateAndInsert(t, alice, spec.MRoomName, map[string]string{"name": roomName}, test.WithStateKey(""))
room.CreateAndInsert(t, alice, spec.MRoomCanonicalAlias, map[string]string{"alias": alias}, test.WithStateKey(""))
// Join the rooms with Bob
room.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
"membership": "join",
}, test.WithStateKey(bob.ID))
// Create a few events to report
eventIDToReport := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": "hello world"})
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
routers := httputil.NewRouters()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
defer close()
natsInstance := jetstream.NATSInstance{}
jsctx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &cfg.Global.JetStream)
// Use an actual roomserver for this
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
if err := api.SendEvents(context.Background(), rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
alice: {},
bob: {},
}
createAccessTokens(t, accessTokens, userAPI, processCtx.Context(), routers)
reqBody := map[string]any{
"reason": "baaad",
"score": -100,
}
body, err := json.Marshal(reqBody)
if err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
var req *http.Request
// Report the event
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/_matrix/client/v3/rooms/%s/report/%s", room.ID, eventIDToReport.EventID()), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[bob].accessToken)
routers.Client.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected report to succeed, got HTTP %d instead: %s", w.Code, w.Body.String())
}
t.Run("Can not query with invalid ID", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/_synapse/admin/v1/event_reports/abc", strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Fatalf("expected getting report to fail, got HTTP %d instead: %s", w.Code, w.Body.String())
}
})
t.Run("Can query with valid ID", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/_synapse/admin/v1/event_reports/1", strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting report to fail, got HTTP %d instead: %s", w.Code, w.Body.String())
}
resp := api.QueryAdminEventReportResponse{}
if err = json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
// test a few things
if resp.EventID != eventIDToReport.EventID() {
t.Fatalf("expected eventID to be %s, got %s instead", eventIDToReport.EventID(), resp.EventID)
}
if resp.RoomName != roomName {
t.Fatalf("expected roomName to be %s, got %s instead", roomName, resp.RoomName)
}
if resp.CanonicalAlias != alias {
t.Fatalf("expected alias to be %s, got %s instead", alias, resp.CanonicalAlias)
}
if reflect.DeepEqual(resp.EventJSON, eventIDToReport.JSON()) {
t.Fatal("mismatching eventJSON")
}
})
t.Run("Can delete with a valid ID", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodDelete, "/_synapse/admin/v1/event_reports/1", strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected getting report to fail, got HTTP %d instead: %s", w.Code, w.Body.String())
}
})
t.Run("Can not query deleted report", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/_synapse/admin/v1/event_reports/1", strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.SynapseAdmin.ServeHTTP(w, req)
if w.Code == http.StatusOK {
t.Fatalf("expected getting report to fail, got HTTP %d instead: %s", w.Code, w.Body.String())
}
})
})
}

View file

@ -15,7 +15,6 @@
package auth
import (
"context"
"encoding/json"
"io"
"net/http"
@ -32,8 +31,13 @@ import (
// called after authorization has completed, with the result of the authorization.
// If the final return value is non-nil, an error occurred and the cleanup function
// is nil.
func LoginFromJSONReader(ctx context.Context, r io.Reader, useraccountAPI uapi.UserLoginAPI, userAPI UserInternalAPIForLogin, cfg *config.ClientAPI) (*Login, LoginCleanupFunc, *util.JSONResponse) {
reqBytes, err := io.ReadAll(r)
func LoginFromJSONReader(
req *http.Request,
useraccountAPI uapi.UserLoginAPI,
userAPI UserInternalAPIForLogin,
cfg *config.ClientAPI,
) (*Login, LoginCleanupFunc, *util.JSONResponse) {
reqBytes, err := io.ReadAll(req.Body)
if err != nil {
err := &util.JSONResponse{
Code: http.StatusBadRequest,
@ -65,6 +69,20 @@ func LoginFromJSONReader(ctx context.Context, r io.Reader, useraccountAPI uapi.U
UserAPI: userAPI,
Config: cfg,
}
case authtypes.LoginTypeApplicationService:
token, err := ExtractAccessToken(req)
if err != nil {
err := &util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.MissingToken(err.Error()),
}
return nil, nil, err
}
typ = &LoginTypeApplicationService{
Config: cfg,
Token: token,
}
default:
err := util.JSONResponse{
Code: http.StatusBadRequest,
@ -73,7 +91,7 @@ func LoginFromJSONReader(ctx context.Context, r io.Reader, useraccountAPI uapi.U
return nil, nil, &err
}
return typ.LoginFromJSON(ctx, reqBytes)
return typ.LoginFromJSON(req.Context(), reqBytes)
}
// UserInternalAPIForLogin contains the aspects of UserAPI required for logging in.

View file

@ -0,0 +1,55 @@
// Copyright 2023 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package auth
import (
"context"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/util"
)
// LoginTypeApplicationService describes how to authenticate as an
// application service
type LoginTypeApplicationService struct {
Config *config.ClientAPI
Token string
}
// Name implements Type
func (t *LoginTypeApplicationService) Name() string {
return authtypes.LoginTypeApplicationService
}
// LoginFromJSON implements Type
func (t *LoginTypeApplicationService) LoginFromJSON(
ctx context.Context, reqBytes []byte,
) (*Login, LoginCleanupFunc, *util.JSONResponse) {
var r Login
if err := httputil.UnmarshalJSON(reqBytes, &r); err != nil {
return nil, nil, err
}
_, err := internal.ValidateApplicationServiceRequest(t.Config, r.Identifier.User, t.Token)
if err != nil {
return nil, nil, err
}
cleanup := func(ctx context.Context, j *util.JSONResponse) {}
return &r, cleanup, nil
}

View file

@ -17,7 +17,9 @@ package auth
import (
"context"
"net/http"
"net/http/httptest"
"reflect"
"regexp"
"strings"
"testing"
@ -33,8 +35,9 @@ func TestLoginFromJSONReader(t *testing.T) {
ctx := context.Background()
tsts := []struct {
Name string
Body string
Name string
Body string
Token string
WantUsername string
WantDeviceID string
@ -62,6 +65,30 @@ func TestLoginFromJSONReader(t *testing.T) {
WantDeviceID: "adevice",
WantDeletedTokens: []string{"atoken"},
},
{
Name: "appServiceWorksUserID",
Body: `{
"type": "m.login.application_service",
"identifier": { "type": "m.id.user", "user": "@alice:example.com" },
"device_id": "adevice"
}`,
Token: "astoken",
WantUsername: "@alice:example.com",
WantDeviceID: "adevice",
},
{
Name: "appServiceWorksLocalpart",
Body: `{
"type": "m.login.application_service",
"identifier": { "type": "m.id.user", "user": "alice" },
"device_id": "adevice"
}`,
Token: "astoken",
WantUsername: "alice",
WantDeviceID: "adevice",
},
}
for _, tst := range tsts {
t.Run(tst.Name, func(t *testing.T) {
@ -72,11 +99,35 @@ func TestLoginFromJSONReader(t *testing.T) {
ServerName: serverName,
},
},
Derived: &config.Derived{
ApplicationServices: []config.ApplicationService{
{
ID: "anapplicationservice",
ASToken: "astoken",
NamespaceMap: map[string][]config.ApplicationServiceNamespace{
"users": {
{
Exclusive: true,
Regex: "@alice:example.com",
RegexpObject: regexp.MustCompile("@alice:example.com"),
},
},
},
},
},
},
}
login, cleanup, err := LoginFromJSONReader(ctx, strings.NewReader(tst.Body), &userAPI, &userAPI, cfg)
if err != nil {
t.Fatalf("LoginFromJSONReader failed: %+v", err)
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(tst.Body))
if tst.Token != "" {
req.Header.Add("Authorization", "Bearer "+tst.Token)
}
login, cleanup, jsonErr := LoginFromJSONReader(req, &userAPI, &userAPI, cfg)
if jsonErr != nil {
t.Fatalf("LoginFromJSONReader failed: %+v", jsonErr)
}
cleanup(ctx, &util.JSONResponse{Code: http.StatusOK})
if login.Username() != tst.WantUsername {
@ -104,8 +155,9 @@ func TestBadLoginFromJSONReader(t *testing.T) {
ctx := context.Background()
tsts := []struct {
Name string
Body string
Name string
Body string
Token string
WantErrCode spec.MatrixErrorCode
}{
@ -142,6 +194,45 @@ func TestBadLoginFromJSONReader(t *testing.T) {
}`,
WantErrCode: spec.ErrorInvalidParam,
},
{
Name: "noASToken",
Body: `{
"type": "m.login.application_service",
"identifier": { "type": "m.id.user", "user": "@alice:example.com" },
"device_id": "adevice"
}`,
WantErrCode: "M_MISSING_TOKEN",
},
{
Name: "badASToken",
Token: "badastoken",
Body: `{
"type": "m.login.application_service",
"identifier": { "type": "m.id.user", "user": "@alice:example.com" },
"device_id": "adevice"
}`,
WantErrCode: "M_UNKNOWN_TOKEN",
},
{
Name: "badASNamespace",
Token: "astoken",
Body: `{
"type": "m.login.application_service",
"identifier": { "type": "m.id.user", "user": "@bob:example.com" },
"device_id": "adevice"
}`,
WantErrCode: "M_EXCLUSIVE",
},
{
Name: "badASUserID",
Token: "astoken",
Body: `{
"type": "m.login.application_service",
"identifier": { "type": "m.id.user", "user": "@alice:wrong.example.com" },
"device_id": "adevice"
}`,
WantErrCode: "M_INVALID_USERNAME",
},
}
for _, tst := range tsts {
t.Run(tst.Name, func(t *testing.T) {
@ -152,8 +243,30 @@ func TestBadLoginFromJSONReader(t *testing.T) {
ServerName: serverName,
},
},
Derived: &config.Derived{
ApplicationServices: []config.ApplicationService{
{
ID: "anapplicationservice",
ASToken: "astoken",
NamespaceMap: map[string][]config.ApplicationServiceNamespace{
"users": {
{
Exclusive: true,
Regex: "@alice:example.com",
RegexpObject: regexp.MustCompile("@alice:example.com"),
},
},
},
},
},
},
}
_, cleanup, errRes := LoginFromJSONReader(ctx, strings.NewReader(tst.Body), &userAPI, &userAPI, cfg)
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(tst.Body))
if tst.Token != "" {
req.Header.Add("Authorization", "Bearer "+tst.Token)
}
_, cleanup, errRes := LoginFromJSONReader(req, &userAPI, &userAPI, cfg)
if errRes == nil {
cleanup(ctx, nil)
t.Fatalf("LoginFromJSONReader err: got %+v, want code %q", errRes, tst.WantErrCode)

View file

@ -55,7 +55,7 @@ type LoginCleanupFunc func(context.Context, *util.JSONResponse)
// https://matrix.org/docs/spec/client_server/r0.6.1#identifier-types
type LoginIdentifier struct {
Type string `json:"type"`
// when type = m.id.user
// when type = m.id.user or m.id.application_service
User string `json:"user"`
// when type = m.id.thirdparty
Medium string `json:"medium"`

View file

@ -17,6 +17,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/routing"
"github.com/matrix-org/dendrite/clientapi/threepid"
"github.com/matrix-org/dendrite/federationapi/statistics"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/internal/pushrules"
@ -49,6 +50,10 @@ type userDevice struct {
password string
}
var testIsBlacklistedOrBackingOff = func(s spec.ServerName) (*statistics.ServerStatistics, error) {
return &statistics.ServerStatistics{}, nil
}
func TestGetPutDevices(t *testing.T) {
alice := test.NewUser(t)
bob := test.NewUser(t)
@ -121,7 +126,7 @@ func TestGetPutDevices(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -170,7 +175,7 @@ func TestDeleteDevice(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI/ for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -275,7 +280,7 @@ func TestDeleteDevices(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI/ for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -442,7 +447,7 @@ func TestSetDisplayname(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
asPI := appservice.NewInternalAPI(processCtx, cfg, natsInstance, userAPI, rsAPI)
AddPublicRoutes(processCtx, routers, cfg, natsInstance, base.CreateFederationClient(cfg, nil), rsAPI, asPI, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -554,7 +559,7 @@ func TestSetAvatarURL(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
asPI := appservice.NewInternalAPI(processCtx, cfg, natsInstance, userAPI, rsAPI)
AddPublicRoutes(processCtx, routers, cfg, natsInstance, base.CreateFederationClient(cfg, nil), rsAPI, asPI, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -632,7 +637,7 @@ func TestTyping(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
// Needed to create accounts
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -716,7 +721,7 @@ func TestMembership(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
// Needed to create accounts
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
rsAPI.SetUserAPI(userAPI)
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -923,13 +928,17 @@ func TestCapabilities(t *testing.T) {
}
}
var tempRoomServerCfg config.RoomServer
tempRoomServerCfg.Defaults(config.DefaultOpts{})
defaultRoomVersion := tempRoomServerCfg.DefaultRoomVersion
expectedMap := map[string]interface{}{
"capabilities": map[string]interface{}{
"m.change_password": map[string]bool{
"enabled": true,
},
"m.room_versions": map[string]interface{}{
"default": version.DefaultRoomVersion(),
"default": defaultRoomVersion,
"available": versionsMap,
},
},
@ -949,9 +958,10 @@ func TestCapabilities(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
// Needed to create accounts
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, caching.DisableMetrics)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -996,9 +1006,10 @@ func TestTurnserver(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
// Needed to create accounts
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, caching.DisableMetrics)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
//rsAPI.SetUserAPI(userAPI)
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -1094,9 +1105,10 @@ func Test3PID(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
// Needed to create accounts
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, caching.DisableMetrics)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -1272,7 +1284,7 @@ func TestPushRules(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -1414,7 +1426,7 @@ func TestPushRules(t *testing.T) {
validateFunc: func(t *testing.T, respBody *bytes.Buffer) {
actions := gjson.GetBytes(respBody.Bytes(), "actions").Array()
// only a basic check
assert.Equal(t, 1, len(actions))
assert.Equal(t, 0, len(actions))
},
},
{
@ -1659,7 +1671,7 @@ func TestKeys(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -2121,7 +2133,7 @@ func TestKeyBackup(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
@ -2142,3 +2154,284 @@ func TestKeyBackup(t *testing.T) {
}
})
}
func TestGetMembership(t *testing.T) {
alice := test.NewUser(t)
bob := test.NewUser(t)
testCases := []struct {
name string
roomID string
user *test.User
additionalEvents func(t *testing.T, room *test.Room)
request func(t *testing.T, room *test.Room, accessToken string) *http.Request
wantOK bool
wantMemberCount int
}{
{
name: "/joined_members - Bob never joined",
user: bob,
request: func(t *testing.T, room *test.Room, accessToken string) *http.Request {
return test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/joined_members", room.ID), test.WithQueryParams(map[string]string{
"access_token": accessToken,
}))
},
wantOK: false,
},
{
name: "/joined_members - Alice joined",
user: alice,
request: func(t *testing.T, room *test.Room, accessToken string) *http.Request {
return test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/joined_members", room.ID), test.WithQueryParams(map[string]string{
"access_token": accessToken,
}))
},
wantOK: true,
wantMemberCount: 1,
},
{
name: "/joined_members - Alice leaves, shouldn't be able to see members ",
user: alice,
request: func(t *testing.T, room *test.Room, accessToken string) *http.Request {
return test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/joined_members", room.ID), test.WithQueryParams(map[string]string{
"access_token": accessToken,
}))
},
additionalEvents: func(t *testing.T, room *test.Room) {
room.CreateAndInsert(t, alice, spec.MRoomMember, map[string]interface{}{
"membership": "leave",
}, test.WithStateKey(alice.ID))
},
wantOK: false,
},
{
name: "/joined_members - Bob joins, Alice sees two members",
user: alice,
request: func(t *testing.T, room *test.Room, accessToken string) *http.Request {
return test.NewRequest(t, "GET", fmt.Sprintf("/_matrix/client/v3/rooms/%s/joined_members", room.ID), test.WithQueryParams(map[string]string{
"access_token": accessToken,
}))
},
additionalEvents: func(t *testing.T, room *test.Room) {
room.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
"membership": "join",
}, test.WithStateKey(bob.ID))
},
wantOK: true,
wantMemberCount: 2,
},
}
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
routers := httputil.NewRouters()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
defer close()
natsInstance := jetstream.NATSInstance{}
jsctx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &cfg.Global.JetStream)
// Use an actual roomserver for this
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
alice: {},
bob: {},
}
createAccessTokens(t, accessTokens, userAPI, processCtx.Context(), routers)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
room := test.NewRoom(t, alice)
t.Cleanup(func() {
t.Logf("running cleanup for %s", tc.name)
})
// inject additional events
if tc.additionalEvents != nil {
tc.additionalEvents(t, room)
}
if err := api.SendEvents(context.Background(), rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
w := httptest.NewRecorder()
routers.Client.ServeHTTP(w, tc.request(t, room, accessTokens[tc.user].accessToken))
if w.Code != 200 && tc.wantOK {
t.Logf("%s", w.Body.String())
t.Fatalf("got HTTP %d want %d", w.Code, 200)
}
t.Logf("[%s] Resp: %s", tc.name, w.Body.String())
// check we got the expected events
if tc.wantOK {
memberCount := len(gjson.GetBytes(w.Body.Bytes(), "joined").Map())
if memberCount != tc.wantMemberCount {
t.Fatalf("expected %d members, got %d", tc.wantMemberCount, memberCount)
}
}
})
}
})
}
func TestCreateRoomInvite(t *testing.T) {
alice := test.NewUser(t)
bob := test.NewUser(t)
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
routers := httputil.NewRouters()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
defer close()
natsInstance := jetstream.NATSInstance{}
jsctx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &cfg.Global.JetStream)
// Use an actual roomserver for this
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
alice: {},
}
createAccessTokens(t, accessTokens, userAPI, processCtx.Context(), routers)
reqBody := map[string]any{
"invite": []string{bob.ID},
}
body, err := json.Marshal(reqBody)
if err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/_matrix/client/v3/createRoom", strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[alice].accessToken)
routers.Client.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected room creation to be successful, got HTTP %d instead: %s", w.Code, w.Body.String())
}
roomID := gjson.GetBytes(w.Body.Bytes(), "room_id").Str
validRoomID, _ := spec.NewRoomID(roomID)
// Now ask the roomserver about the membership event of Bob
ev, err := rsAPI.CurrentStateEvent(context.Background(), *validRoomID, spec.MRoomMember, bob.ID)
if err != nil {
t.Fatal(err)
}
if ev == nil {
t.Fatal("Membership event for Bob does not exist")
}
// Validate that there is NO displayname in content
if gjson.GetBytes(ev.Content(), "displayname").Exists() {
t.Fatal("Found displayname in invite")
}
})
}
func TestReportEvent(t *testing.T) {
alice := test.NewUser(t)
bob := test.NewUser(t)
charlie := test.NewUser(t)
room := test.NewRoom(t, alice)
room.CreateAndInsert(t, charlie, spec.MRoomMember, map[string]interface{}{
"membership": "join",
}, test.WithStateKey(charlie.ID))
eventToReport := room.CreateAndInsert(t, alice, "m.room.message", map[string]interface{}{"body": "hello world"})
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
routers := httputil.NewRouters()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
defer close()
natsInstance := jetstream.NATSInstance{}
jsctx, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
defer jetstream.DeleteAllStreams(jsctx, &cfg.Global.JetStream)
// Use an actual roomserver for this
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
if err := api.SendEvents(context.Background(), rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
t.Fatalf("failed to send events: %v", err)
}
// We mostly need the rsAPI for this test, so nil for other APIs/caches etc.
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
accessTokens := map[*test.User]userDevice{
alice: {},
bob: {},
charlie: {},
}
createAccessTokens(t, accessTokens, userAPI, processCtx.Context(), routers)
reqBody := map[string]any{
"reason": "baaad",
"score": -100,
}
body, err := json.Marshal(reqBody)
if err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
var req *http.Request
t.Run("Bob is not joined and should not be able to report the event", func(t *testing.T) {
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/_matrix/client/v3/rooms/%s/report/%s", room.ID, eventToReport.EventID()), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[bob].accessToken)
routers.Client.ServeHTTP(w, req)
if w.Code != http.StatusNotFound {
t.Fatalf("expected report to fail, got HTTP %d instead: %s", w.Code, w.Body.String())
}
})
t.Run("Charlie is joined but the event does not exist", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/_matrix/client/v3/rooms/%s/report/$doesNotExist", room.ID), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[charlie].accessToken)
routers.Client.ServeHTTP(w, req)
if w.Code != http.StatusNotFound {
t.Fatalf("expected report to fail, got HTTP %d instead: %s", w.Code, w.Body.String())
}
})
t.Run("Charlie is joined and allowed to report the event", func(t *testing.T) {
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("/_matrix/client/v3/rooms/%s/report/%s", room.ID, eventToReport.EventID()), strings.NewReader(string(body)))
req.Header.Set("Authorization", "Bearer "+accessTokens[charlie].accessToken)
routers.Client.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected report to be successful, got HTTP %d instead: %s", w.Code, w.Body.String())
}
})
})
}

View file

@ -35,5 +35,5 @@ func ParseTSParam(req *http.Request) (time.Time, error) {
return time.Time{}, fmt.Errorf("param 'ts' is no valid int (%s)", err.Error())
}
return time.Unix(ts/1000, 0), nil
return time.UnixMilli(ts), nil
}

View file

@ -328,7 +328,7 @@ func AdminPurgeRoom(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI)
}
}
func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.Device, userAPI api.ClientUserAPI) util.JSONResponse {
func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
if req.Body == nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
@ -423,7 +423,7 @@ func AdminReindex(req *http.Request, cfg *config.ClientAPI, device *api.Device,
}
}
func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.ClientKeyAPI) util.JSONResponse {
func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI userapi.ClientKeyAPI) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@ -495,3 +495,93 @@ func AdminDownloadState(req *http.Request, device *api.Device, rsAPI roomserverA
JSON: struct{}{},
}
}
// GetEventReports returns reported events for a given user/room.
func GetEventReports(
req *http.Request,
rsAPI roomserverAPI.ClientRoomserverAPI,
from, limit uint64,
backwards bool,
userID, roomID string,
) util.JSONResponse {
eventReports, count, err := rsAPI.QueryAdminEventReports(req.Context(), from, limit, backwards, userID, roomID)
if err != nil {
logrus.WithError(err).Error("failed to query event reports")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
resp := map[string]any{
"event_reports": eventReports,
"total": count,
}
// Add a next_token if there are still reports
if int64(from+limit) < count {
resp["next_token"] = int(from) + len(eventReports)
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: resp,
}
}
func GetEventReport(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI, reportID string) util.JSONResponse {
parsedReportID, err := strconv.ParseUint(reportID, 10, 64)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
// Given this is an admin endpoint, let them know what didn't work.
JSON: spec.InvalidParam(err.Error()),
}
}
report, err := rsAPI.QueryAdminEventReport(req.Context(), parsedReportID)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown(err.Error()),
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: report,
}
}
func DeleteEventReport(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI, reportID string) util.JSONResponse {
parsedReportID, err := strconv.ParseUint(reportID, 10, 64)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
// Given this is an admin endpoint, let them know what didn't work.
JSON: spec.InvalidParam(err.Error()),
}
}
err = rsAPI.PerformAdminDeleteEventReport(req.Context(), parsedReportID)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown(err.Error()),
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct{}{},
}
}
func parseUint64OrDefault(input string, defaultValue uint64) uint64 {
v, err := strconv.ParseUint(input, 10, 64)
if err != nil {
return defaultValue
}
return v
}

View file

@ -17,6 +17,7 @@ package routing
import (
"net/http"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/version"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
@ -24,7 +25,7 @@ import (
// GetCapabilities returns information about the server's supported feature set
// and other relevant capabilities to an authenticated user.
func GetCapabilities() util.JSONResponse {
func GetCapabilities(rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
versionsMap := map[gomatrixserverlib.RoomVersion]string{}
for v, desc := range version.SupportedRoomVersions() {
if desc.Stable() {
@ -40,7 +41,7 @@ func GetCapabilities() util.JSONResponse {
"enabled": true,
},
"m.room_versions": map[string]interface{}{
"default": version.DefaultRoomVersion(),
"default": rsAPI.DefaultRoomVersion(),
"available": versionsMap,
},
},

View file

@ -171,7 +171,7 @@ func createRoom(
// Clobber keys: creator, room_version
roomVersion := roomserverVersion.DefaultRoomVersion()
roomVersion := rsAPI.DefaultRoomVersion()
if createRequest.RoomVersion != "" {
candidateVersion := gomatrixserverlib.RoomVersion(createRequest.RoomVersion)
_, roomVersionError := roomserverVersion.SupportedRoomVersion(candidateVersion)

View file

@ -55,7 +55,7 @@ func DirectoryRoom(
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.BadJSON("Room alias must be in the form '#localpart:domain'"),
JSON: spec.InvalidParam("Room alias must be in the form '#localpart:domain'"),
}
}
@ -134,7 +134,7 @@ func SetLocalAlias(
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.BadJSON("Room alias must be in the form '#localpart:domain'"),
JSON: spec.InvalidParam("Room alias must be in the form '#localpart:domain'"),
}
}
@ -181,13 +181,39 @@ func SetLocalAlias(
return *resErr
}
queryReq := roomserverAPI.SetRoomAliasRequest{
UserID: device.UserID,
RoomID: r.RoomID,
Alias: alias,
roomID, err := spec.NewRoomID(r.RoomID)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("invalid room ID"),
}
}
var queryRes roomserverAPI.SetRoomAliasResponse
if err := rsAPI.SetRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
userID, err := spec.NewUserID(device.UserID, true)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *roomID, *userID)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("QuerySenderIDForUser failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
} else if senderID == nil {
util.GetLogger(req.Context()).WithField("roomID", *roomID).WithField("userID", *userID).Error("Sender ID not found")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
aliasAlreadyExists, err := rsAPI.SetRoomAlias(req.Context(), *senderID, *roomID, alias)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
@ -195,7 +221,7 @@ func SetLocalAlias(
}
}
if queryRes.AliasExists {
if aliasAlreadyExists {
return util.JSONResponse{
Code: http.StatusConflict,
JSON: spec.Unknown("The alias " + alias + " already exists."),
@ -240,6 +266,31 @@ func RemoveLocalAlias(
JSON: spec.NotFound("The alias does not exist."),
}
}
// This seems like the kind of auth check that should be done in the roomserver, but
// if this check fails (user is not in the room), then there will be no SenderID for the user
// for pseudo-ID rooms - it will just return "". However, we can't use lack of a sender ID
// as meaning they are not in the room, since lacking a sender ID could be caused by other bugs.
// TODO: maybe have QuerySenderIDForUser return richer errors?
var queryResp roomserverAPI.QueryMembershipForUserResponse
err = rsAPI.QueryMembershipForUser(req.Context(), &roomserverAPI.QueryMembershipForUserRequest{
RoomID: validRoomID.String(),
UserID: *userID,
}, &queryResp)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("roomserverAPI.QueryMembershipForUser failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
if !queryResp.IsInRoom {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You do not have permission to remove this alias."),
}
}
deviceSenderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *userID)
if err != nil {
return util.JSONResponse{
@ -247,28 +298,31 @@ func RemoveLocalAlias(
JSON: spec.NotFound("The alias does not exist."),
}
}
queryReq := roomserverAPI.RemoveRoomAliasRequest{
Alias: alias,
SenderID: deviceSenderID,
}
var queryRes roomserverAPI.RemoveRoomAliasResponse
if err := rsAPI.RemoveRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed")
// TODO: how to handle this case? missing user/room keys seem to be a whole new class of errors
if deviceSenderID == nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
JSON: spec.Unknown("internal server error"),
}
}
if !queryRes.Found {
aliasFound, aliasRemoved, err := rsAPI.RemoveRoomAlias(req.Context(), *deviceSenderID, alias)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
if !aliasFound {
return util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.NotFound("The alias does not exist."),
}
}
if !queryRes.Removed {
if !aliasRemoved {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You do not have permission to remove this alias."),
@ -337,7 +391,7 @@ func SetVisibility(
}
}
senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *deviceUserID)
if err != nil {
if err != nil || senderID == nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.Unknown("failed to find senderID for this user"),
@ -368,7 +422,7 @@ func SetVisibility(
// NOTSPEC: Check if the user's power is greater than power required to change m.room.canonical_alias event
power, _ := gomatrixserverlib.NewPowerLevelContentFromEvent(queryEventsRes.StateEvents[0].PDU)
if power.UserLevel(senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) {
if power.UserLevel(*senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("userID doesn't have power level to change visibility"),

View file

@ -33,23 +33,36 @@ func GetJoinedRooms(
device *userapi.Device,
rsAPI api.ClientRoomserverAPI,
) util.JSONResponse {
var res api.QueryRoomsForUserResponse
err := rsAPI.QueryRoomsForUser(req.Context(), &api.QueryRoomsForUserRequest{
UserID: device.UserID,
WantMembership: "join",
}, &res)
deviceUserID, err := spec.NewUserID(device.UserID, true)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("Invalid device user ID")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
rooms, err := rsAPI.QueryRoomsForUser(req.Context(), *deviceUserID, "join")
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("QueryRoomsForUser failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
JSON: spec.Unknown("internal server error"),
}
}
if res.RoomIDs == nil {
res.RoomIDs = []string{}
var roomIDStrs []string
if rooms == nil {
roomIDStrs = []string{}
} else {
roomIDStrs = make([]string, len(rooms))
for i, roomID := range rooms {
roomIDStrs[i] = roomID.String()
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: getJoinedRoomsResponse{res.RoomIDs},
JSON: getJoinedRoomsResponse{roomIDStrs},
}
}

View file

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/matrix-org/dendrite/federationapi/statistics"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/setup/jetstream"
@ -21,6 +22,10 @@ import (
uapi "github.com/matrix-org/dendrite/userapi/api"
)
var testIsBlacklistedOrBackingOff = func(s spec.ServerName) (*statistics.ServerStatistics, error) {
return &statistics.ServerStatistics{}, nil
}
func TestJoinRoomByIDOrAlias(t *testing.T) {
alice := test.NewUser(t)
bob := test.NewUser(t)
@ -36,7 +41,7 @@ func TestJoinRoomByIDOrAlias(t *testing.T) {
natsInstance := jetstream.NATSInstance{}
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil) // creates the rs.Inputer etc
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
// Create the users in the userapi

View file

@ -93,7 +93,6 @@ func UploadKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *api.Device)
type queryKeysRequest struct {
Timeout int `json:"timeout"`
Token string `json:"token"`
DeviceKeys map[string][]string `json:"device_keys"`
}
@ -119,7 +118,6 @@ func QueryKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *api.Device) u
UserID: device.UserID,
UserToDevices: r.DeviceKeys,
Timeout: r.GetTimeout(),
// TODO: Token?
}, &queryRes)
return util.JSONResponse{
Code: 200,

View file

@ -19,6 +19,7 @@ import (
"net/http"
"github.com/matrix-org/dendrite/clientapi/auth"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/userutil"
"github.com/matrix-org/dendrite/setup/config"
userapi "github.com/matrix-org/dendrite/userapi/api"
@ -40,28 +41,25 @@ type flow struct {
Type string `json:"type"`
}
func passwordLogin() flows {
f := flows{}
s := flow{
Type: "m.login.password",
}
f.Flows = append(f.Flows, s)
return f
}
// Login implements GET and POST /login
func Login(
req *http.Request, userAPI userapi.ClientUserAPI,
cfg *config.ClientAPI,
) util.JSONResponse {
if req.Method == http.MethodGet {
// TODO: support other forms of login other than password, depending on config options
loginFlows := []flow{{Type: authtypes.LoginTypePassword}}
if len(cfg.Derived.ApplicationServices) > 0 {
loginFlows = append(loginFlows, flow{Type: authtypes.LoginTypeApplicationService})
}
// TODO: support other forms of login, depending on config options
return util.JSONResponse{
Code: http.StatusOK,
JSON: passwordLogin(),
JSON: flows{
Flows: loginFlows,
},
}
} else if req.Method == http.MethodPost {
login, cleanup, authErr := auth.LoginFromJSONReader(req.Context(), req.Body, userAPI, userAPI, cfg)
login, cleanup, authErr := auth.LoginFromJSONReader(req, userAPI, userAPI, cfg)
if authErr != nil {
return *authErr
}

View file

@ -49,7 +49,7 @@ func TestLogin(t *testing.T) {
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
// Needed for /login
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
// We mostly need the userAPI for this test, so nil for other APIs/caches etc.
Setup(routers, cfg, nil, nil, userAPI, nil, nil, nil, nil, nil, nil, nil, caching.DisableMetrics)
@ -114,6 +114,44 @@ func TestLogin(t *testing.T) {
ctx := context.Background()
// Inject a dummy application service, so we have a "m.login.application_service"
// in the login flows
as := &config.ApplicationService{}
cfg.AppServiceAPI.Derived.ApplicationServices = []config.ApplicationService{*as}
t.Run("Supported log-in flows are returned", func(t *testing.T) {
req := test.NewRequest(t, http.MethodGet, "/_matrix/client/v3/login")
rec := httptest.NewRecorder()
routers.Client.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("failed to get log-in flows: %s", rec.Body.String())
}
t.Logf("response: %s", rec.Body.String())
resp := flows{}
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatal(err)
}
appServiceFound := false
passwordFound := false
for _, flow := range resp.Flows {
if flow.Type == "m.login.password" {
passwordFound = true
} else if flow.Type == "m.login.application_service" {
appServiceFound = true
} else {
t.Fatalf("got unknown login flow: %s", flow.Type)
}
}
if !appServiceFound {
t.Fatal("m.login.application_service missing from login flows")
}
if !passwordFound {
t.Fatal("m.login.password missing from login flows")
}
})
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
req := test.NewRequest(t, http.MethodPost, "/_matrix/client/v3/login", test.WithJSONBody(t, map[string]interface{}{

View file

@ -71,7 +71,7 @@ func SendBan(
}
}
senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *deviceUserID)
if err != nil {
if err != nil || senderID == nil {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You don't have permission to ban this user, unknown senderID"),
@ -87,7 +87,7 @@ func SendBan(
if errRes != nil {
return *errRes
}
allowedToBan := pl.UserLevel(senderID) >= pl.Ban
allowedToBan := pl.UserLevel(*senderID) >= pl.Ban
if !allowedToBan {
return util.JSONResponse{
Code: http.StatusForbidden,
@ -169,7 +169,7 @@ func SendKick(
}
}
senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *deviceUserID)
if err != nil {
if err != nil || senderID == nil {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You don't have permission to kick this user, unknown senderID"),
@ -181,18 +181,6 @@ func SendKick(
return *errRes
}
pl, errRes := getPowerlevels(req, rsAPI, roomID)
if errRes != nil {
return *errRes
}
allowedToKick := pl.UserLevel(senderID) >= pl.Kick
if !allowedToKick {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You don't have permission to kick this user, power level too low."),
}
}
bodyUserID, err := spec.NewUserID(body.UserID, true)
if err != nil {
return util.JSONResponse{
@ -200,6 +188,19 @@ func SendKick(
JSON: spec.BadJSON("body userID is invalid"),
}
}
pl, errRes := getPowerlevels(req, rsAPI, roomID)
if errRes != nil {
return *errRes
}
allowedToKick := pl.UserLevel(*senderID) >= pl.Kick || bodyUserID.String() == deviceUserID.String()
if !allowedToKick {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You don't have permission to kick this user, power level too low."),
}
}
var queryRes roomserverAPI.QueryMembershipForUserResponse
err = rsAPI.QueryMembershipForUser(req.Context(), &roomserverAPI.QueryMembershipForUserRequest{
RoomID: roomID,
@ -323,19 +324,18 @@ func SendInvite(
}
// We already received the return value, so no need to check for an error here.
response, _ := sendInvite(req.Context(), profileAPI, device, roomID, body.UserID, body.Reason, cfg, rsAPI, asAPI, evTime)
response, _ := sendInvite(req.Context(), device, roomID, body.UserID, body.Reason, cfg, rsAPI, evTime)
return response
}
// sendInvite sends an invitation to a user. Returns a JSONResponse and an error
func sendInvite(
ctx context.Context,
profileAPI userapi.ClientUserAPI,
device *userapi.Device,
roomID, userID, reason string,
cfg *config.ClientAPI,
rsAPI roomserverAPI.ClientRoomserverAPI,
asAPI appserviceAPI.AppServiceInternalAPI, evTime time.Time,
evTime time.Time,
) (util.JSONResponse, error) {
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
@ -358,13 +358,7 @@ func sendInvite(
JSON: spec.InvalidParam("UserID is invalid"),
}, err
}
profile, err := loadProfile(ctx, userID, cfg, profileAPI, asAPI)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}, err
}
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
if err != nil {
return util.JSONResponse{
@ -374,16 +368,14 @@ func sendInvite(
}
err = rsAPI.PerformInvite(ctx, &api.PerformInviteRequest{
InviteInput: roomserverAPI.InviteInput{
RoomID: *validRoomID,
Inviter: *inviter,
Invitee: *invitee,
DisplayName: profile.DisplayName,
AvatarURL: profile.AvatarURL,
Reason: reason,
IsDirect: false,
KeyID: identity.KeyID,
PrivateKey: identity.PrivateKey,
EventTime: evTime,
RoomID: *validRoomID,
Inviter: *inviter,
Invitee: *invitee,
Reason: reason,
IsDirect: false,
KeyID: identity.KeyID,
PrivateKey: identity.PrivateKey,
EventTime: evTime,
},
InviteRoomState: nil, // ask the roomserver to draw up invite room state for us
SendAsServer: string(device.UserDomain()),
@ -476,6 +468,8 @@ func buildMembershipEvent(
senderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *userID)
if err != nil {
return nil, err
} else if senderID == nil {
return nil, fmt.Errorf("no sender ID for %s in %s", *userID, *validRoomID)
}
targetID, err := spec.NewUserID(targetUserID, true)
@ -485,6 +479,8 @@ func buildMembershipEvent(
targetSenderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *targetID)
if err != nil {
return nil, err
} else if targetSenderID == nil {
return nil, fmt.Errorf("no sender ID for %s in %s", *targetID, *validRoomID)
}
identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *userID)
@ -492,8 +488,8 @@ func buildMembershipEvent(
return nil, err
}
return buildMembershipEventDirect(ctx, targetSenderID, reason, profile.DisplayName, profile.AvatarURL,
senderID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI)
return buildMembershipEventDirect(ctx, *targetSenderID, reason, profile.DisplayName, profile.AvatarURL,
*senderID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI)
}
// loadProfile lookups the profile of a given user from the database and returns

View file

@ -0,0 +1,139 @@
// Copyright 2024 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package routing
import (
"encoding/json"
"net/http"
"github.com/matrix-org/dendrite/roomserver/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
)
// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-joined-members
type getJoinedMembersResponse struct {
Joined map[string]joinedMember `json:"joined"`
}
type joinedMember struct {
DisplayName string `json:"display_name"`
AvatarURL string `json:"avatar_url"`
}
// The database stores 'displayname' without an underscore.
// Deserialize into this and then change to the actual API response
type databaseJoinedMember struct {
DisplayName string `json:"displayname"`
AvatarURL string `json:"avatar_url"`
}
// GetJoinedMembers implements
//
// GET /rooms/{roomId}/joined_members
func GetJoinedMembers(
req *http.Request, device *userapi.Device, roomID string,
rsAPI api.ClientRoomserverAPI,
) util.JSONResponse {
// Validate the userID
userID, err := spec.NewUserID(device.UserID, true)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("Device UserID is invalid"),
}
}
// Validate the roomID
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("RoomID is invalid"),
}
}
// Get the current memberships for the requesting user to determine
// if they are allowed to query this endpoint.
queryReq := api.QueryMembershipForUserRequest{
RoomID: validRoomID.String(),
UserID: *userID,
}
var queryRes api.QueryMembershipForUserResponse
if queryErr := rsAPI.QueryMembershipForUser(req.Context(), &queryReq, &queryRes); queryErr != nil {
util.GetLogger(req.Context()).WithError(queryErr).Error("rsAPI.QueryMembershipsForRoom failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
if !queryRes.HasBeenInRoom {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You aren't a member of the room and weren't previously a member of the room."),
}
}
if !queryRes.IsInRoom {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("You aren't a member of the room and weren't previously a member of the room."),
}
}
// Get the current membership events
var membershipsForRoomResp api.QueryMembershipsForRoomResponse
if err = rsAPI.QueryMembershipsForRoom(req.Context(), &api.QueryMembershipsForRoomRequest{
JoinedOnly: true,
RoomID: validRoomID.String(),
}, &membershipsForRoomResp); err != nil {
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryEventsByID failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
var res getJoinedMembersResponse
res.Joined = make(map[string]joinedMember)
for _, ev := range membershipsForRoomResp.JoinEvents {
var content databaseJoinedMember
if err := json.Unmarshal(ev.Content, &content); err != nil {
util.GetLogger(req.Context()).WithError(err).Error("failed to unmarshal event content")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
userID, err := rsAPI.QueryUserIDForSender(req.Context(), *validRoomID, spec.SenderID(ev.Sender))
if err != nil || userID == nil {
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryUserIDForSender failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
res.Joined[userID.String()] = joinedMember(content)
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: res,
}
}

View file

@ -16,6 +16,7 @@ package routing
import (
"context"
"fmt"
"net/http"
"time"
@ -250,11 +251,15 @@ func updateProfile(
profile *authtypes.Profile,
userID string, evTime time.Time,
) (util.JSONResponse, error) {
var res api.QueryRoomsForUserResponse
err := rsAPI.QueryRoomsForUser(ctx, &api.QueryRoomsForUserRequest{
UserID: device.UserID,
WantMembership: "join",
}, &res)
deviceUserID, err := spec.NewUserID(device.UserID, true)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}, err
}
rooms, err := rsAPI.QueryRoomsForUser(ctx, *deviceUserID, "join")
if err != nil {
util.GetLogger(ctx).WithError(err).Error("QueryRoomsForUser failed")
return util.JSONResponse{
@ -263,6 +268,11 @@ func updateProfile(
}, err
}
roomIDStrs := make([]string, len(rooms))
for i, room := range rooms {
roomIDStrs[i] = room.String()
}
_, domain, err := gomatrixserverlib.SplitID('@', userID)
if err != nil {
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
@ -273,7 +283,7 @@ func updateProfile(
}
events, err := buildMembershipEvents(
ctx, res.RoomIDs, *profile, userID, evTime, rsAPI,
ctx, roomIDStrs, *profile, userID, evTime, rsAPI,
)
switch e := err.(type) {
case nil:
@ -290,7 +300,7 @@ func updateProfile(
}, e
}
if err := api.SendEvents(ctx, rsAPI, api.KindNew, events, device.UserDomain(), domain, domain, nil, true); err != nil {
if err := api.SendEvents(ctx, rsAPI, api.KindNew, events, device.UserDomain(), domain, domain, nil, false); err != nil {
util.GetLogger(ctx).WithError(err).Error("SendEvents failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
@ -362,8 +372,10 @@ func buildMembershipEvents(
senderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *fullUserID)
if err != nil {
return nil, err
} else if senderID == nil {
return nil, fmt.Errorf("sender ID not found for %s in %s", *fullUserID, *validRoomID)
}
senderIDString := string(senderID)
senderIDString := string(*senderID)
proto := gomatrixserverlib.ProtoEvent{
SenderID: senderIDString,
RoomID: roomID,

View file

@ -70,7 +70,7 @@ func GetPushRulesByKind(ctx context.Context, scope, kind string, device *userapi
}
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
// Even if rulesPtr is not nil, there may not be any rules for this kind
if rulesPtr == nil || (rulesPtr != nil && len(*rulesPtr) == 0) {
if rulesPtr == nil || len(*rulesPtr) == 0 {
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
}
return util.JSONResponse{

View file

@ -23,13 +23,12 @@ import (
"github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/dendrite/userapi/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/util"
"github.com/sirupsen/logrus"
)
func SetReceipt(req *http.Request, userAPI api.ClientUserAPI, syncProducer *producers.SyncAPIProducer, device *userapi.Device, roomID, receiptType, eventID string) util.JSONResponse {
func SetReceipt(req *http.Request, userAPI userapi.ClientUserAPI, syncProducer *producers.SyncAPIProducer, device *userapi.Device, roomID, receiptType, eventID string) util.JSONResponse {
timestamp := spec.AsTimestamp(time.Now())
logrus.WithFields(logrus.Fields{
"roomID": roomID,
@ -54,13 +53,13 @@ func SetReceipt(req *http.Request, userAPI api.ClientUserAPI, syncProducer *prod
}
}
dataReq := api.InputAccountDataRequest{
dataReq := userapi.InputAccountDataRequest{
UserID: device.UserID,
DataType: "m.fully_read",
RoomID: roomID,
AccountData: data,
}
dataRes := api.InputAccountDataResponse{}
dataRes := userapi.InputAccountDataResponse{}
if err := userAPI.InputAccountData(req.Context(), &dataReq, &dataRes); err != nil {
util.GetLogger(req.Context()).WithError(err).Error("userAPI.InputAccountData failed")
return util.ErrorResponse(err)

View file

@ -34,7 +34,8 @@ import (
)
type redactionContent struct {
Reason string `json:"reason"`
Reason string `json:"reason"`
Redacts string `json:"redacts"`
}
type redactionResponse struct {
@ -74,6 +75,16 @@ func SendRedaction(
return *resErr
}
// if user is member of room, and sender ID is nil, then this user doesn't have a pseudo ID for some reason,
// which is unexpected.
if senderID == nil {
util.GetLogger(req.Context()).WithField("userID", *deviceUserID).WithField("roomID", roomID).Error("missing sender ID for user, despite having membership")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
if txnID != nil {
// Try to fetch response from transactionsCache
if res, ok := txnCache.FetchTransaction(device.AccessToken, *txnID, req.URL); ok {
@ -88,7 +99,7 @@ func SendRedaction(
JSON: spec.NotFound("unknown event ID"), // TODO: is it ok to leak existence?
}
}
if ev.RoomID() != roomID {
if ev.RoomID().String() != roomID {
return util.JSONResponse{
Code: 400,
JSON: spec.NotFound("cannot redact event in another room"),
@ -98,7 +109,7 @@ func SendRedaction(
// "Users may redact their own events, and any user with a power level greater than or equal
// to the redact power level of the room may redact events there"
// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid
allowedToRedact := ev.SenderID() == senderID
allowedToRedact := ev.SenderID() == *senderID
if !allowedToRedact {
plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{
EventType: spec.MRoomPowerLevels,
@ -119,7 +130,7 @@ func SendRedaction(
),
}
}
allowedToRedact = pl.UserLevel(senderID) >= pl.Redact
allowedToRedact = pl.UserLevel(*senderID) >= pl.Redact
}
if !allowedToRedact {
return util.JSONResponse{
@ -136,11 +147,16 @@ func SendRedaction(
// create the new event and set all the fields we can
proto := gomatrixserverlib.ProtoEvent{
SenderID: string(senderID),
SenderID: string(*senderID),
RoomID: roomID,
Type: spec.MRoomRedaction,
Redacts: eventID,
}
// Room version 11 expects the "redacts" field on the
// content field, so add it here as well
r.Redacts = eventID
err = proto.SetContent(r)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("proto.SetContent failed")

View file

@ -236,7 +236,7 @@ type authDict struct {
// TODO: Lots of custom keys depending on the type
}
// http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#user-interactive-authentication-api
// https://spec.matrix.org/v1.7/client-server-api/#user-interactive-authentication-api
type userInteractiveResponse struct {
Flows []authtypes.Flow `json:"flows"`
Completed []authtypes.LoginType `json:"completed"`
@ -256,7 +256,7 @@ func newUserInteractiveResponse(
}
}
// http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register
// https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3register
type registerResponse struct {
UserID string `json:"user_id"`
AccessToken string `json:"access_token,omitempty"`
@ -462,7 +462,7 @@ func validateApplicationService(
}
// Register processes a /register request.
// http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register
// https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3register
func Register(
req *http.Request,
userAPI userapi.ClientUserAPI,
@ -630,6 +630,7 @@ func handleGuestRegistration(
AccessToken: token,
IPAddr: req.RemoteAddr,
UserAgent: req.UserAgent(),
FromRegistration: true,
}, &devRes)
if err != nil {
return util.JSONResponse{
@ -647,6 +648,16 @@ func handleGuestRegistration(
}
}
// localpartMatchesExclusiveNamespaces will check if a given username matches any
// application service's exclusive users namespace
func localpartMatchesExclusiveNamespaces(
cfg *config.ClientAPI,
localpart string,
) bool {
userID := userutil.MakeUserID(localpart, cfg.Matrix.ServerName)
return cfg.Derived.ExclusiveApplicationServicesUsernameRegexp.MatchString(userID)
}
// handleRegistrationFlow will direct and complete registration flow stages
// that the client has requested.
// nolint: gocyclo
@ -695,7 +706,7 @@ func handleRegistrationFlow(
// If an access token is provided, ignore this check this is an appservice
// request and we will validate in validateApplicationService
if len(cfg.Derived.ApplicationServices) != 0 &&
UsernameMatchesExclusiveNamespaces(cfg, r.Username) {
localpartMatchesExclusiveNamespaces(cfg, r.Username) {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.ASExclusive("This username is reserved by an application service."),
@ -772,7 +783,7 @@ func handleApplicationServiceRegistration(
// Check application service register user request is valid.
// The application service's ID is returned if so.
appserviceID, err := validateApplicationService(
appserviceID, err := internal.ValidateApplicationServiceRequest(
cfg, r.Username, accessToken,
)
if err != nil {
@ -909,6 +920,7 @@ func completeRegistration(
DeviceID: deviceID,
IPAddr: ipAddr,
UserAgent: userAgent,
FromRegistration: true,
}, &devRes)
if err != nil {
return util.JSONResponse{

View file

@ -298,25 +298,29 @@ func Test_register(t *testing.T) {
guestsDisabled bool
enableRecaptcha bool
captchaBody string
wantResponse util.JSONResponse
// in case of an error, the expected response
wantErrorResponse util.JSONResponse
// in case of success, the expected username assigned
wantUsername string
}{
{
name: "disallow guests",
kind: "guest",
guestsDisabled: true,
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden(`Guest registration is disabled on "test"`),
},
},
{
name: "allow guests",
kind: "guest",
name: "allow guests",
kind: "guest",
wantUsername: "1",
},
{
name: "unknown login type",
loginType: "im.not.known",
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusNotImplemented,
JSON: spec.Unknown("unknown/unimplemented auth type"),
},
@ -324,25 +328,33 @@ func Test_register(t *testing.T) {
{
name: "disabled registration",
registrationDisabled: true,
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden(`Registration is disabled on "test"`),
},
},
{
name: "successful registration, numeric ID",
username: "",
password: "someRandomPassword",
forceEmpty: true,
name: "successful registration, numeric ID",
username: "",
password: "someRandomPassword",
forceEmpty: true,
wantUsername: "2",
},
{
name: "successful registration",
username: "success",
},
{
name: "successful registration, sequential numeric ID",
username: "",
password: "someRandomPassword",
forceEmpty: true,
wantUsername: "3",
},
{
name: "failing registration - user already exists",
username: "success",
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.UserInUse("Desired user ID is already taken."),
},
@ -352,14 +364,14 @@ func Test_register(t *testing.T) {
username: "LOWERCASED", // this is going to be lower-cased
},
{
name: "invalid username",
username: "#totalyNotValid",
wantResponse: *internal.UsernameResponse(internal.ErrUsernameInvalid),
name: "invalid username",
username: "#totalyNotValid",
wantErrorResponse: *internal.UsernameResponse(internal.ErrUsernameInvalid),
},
{
name: "numeric username is forbidden",
username: "1337",
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidUsername("Numeric user IDs are reserved"),
},
@ -367,7 +379,7 @@ func Test_register(t *testing.T) {
{
name: "disabled recaptcha login",
loginType: authtypes.LoginTypeRecaptcha,
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Unknown(ErrCaptchaDisabled.Error()),
},
@ -376,7 +388,7 @@ func Test_register(t *testing.T) {
name: "enabled recaptcha, no response defined",
enableRecaptcha: true,
loginType: authtypes.LoginTypeRecaptcha,
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.BadJSON(ErrMissingResponse.Error()),
},
@ -386,7 +398,7 @@ func Test_register(t *testing.T) {
enableRecaptcha: true,
loginType: authtypes.LoginTypeRecaptcha,
captchaBody: `notvalid`,
wantResponse: util.JSONResponse{
wantErrorResponse: util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: spec.BadJSON(ErrInvalidCaptcha.Error()),
},
@ -398,11 +410,11 @@ func Test_register(t *testing.T) {
captchaBody: `success`,
},
{
name: "captcha invalid from remote",
enableRecaptcha: true,
loginType: authtypes.LoginTypeRecaptcha,
captchaBody: `i should fail for other reasons`,
wantResponse: util.JSONResponse{Code: http.StatusInternalServerError, JSON: spec.InternalServerError{}},
name: "captcha invalid from remote",
enableRecaptcha: true,
loginType: authtypes.LoginTypeRecaptcha,
captchaBody: `i should fail for other reasons`,
wantErrorResponse: util.JSONResponse{Code: http.StatusInternalServerError, JSON: spec.InternalServerError{}},
},
}
@ -416,7 +428,7 @@ func Test_register(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
@ -486,8 +498,8 @@ func Test_register(t *testing.T) {
t.Fatalf("unexpected registration flows: %+v, want %+v", r.Flows, cfg.Derived.Registration.Flows)
}
case spec.MatrixError:
if !reflect.DeepEqual(tc.wantResponse, resp) {
t.Fatalf("(%s), unexpected response: %+v, want: %+v", tc.name, resp, tc.wantResponse)
if !reflect.DeepEqual(tc.wantErrorResponse, resp) {
t.Fatalf("(%s), unexpected response: %+v, want: %+v", tc.name, resp, tc.wantErrorResponse)
}
return
case registerResponse:
@ -505,6 +517,13 @@ func Test_register(t *testing.T) {
if r.DeviceID == "" {
t.Fatalf("missing deviceID in response")
}
// if an expected username is provided, assert that it is a match
if tc.wantUsername != "" {
wantUserID := strings.ToLower(fmt.Sprintf("@%s:%s", tc.wantUsername, "test"))
if wantUserID != r.UserID {
t.Fatalf("unexpected userID: %s, want %s", r.UserID, wantUserID)
}
}
return
default:
t.Logf("Got response: %T", resp.JSON)
@ -541,44 +560,29 @@ func Test_register(t *testing.T) {
resp = Register(req, userAPI, &cfg.ClientAPI)
switch resp.JSON.(type) {
case spec.InternalServerError:
if !reflect.DeepEqual(tc.wantResponse, resp) {
t.Fatalf("unexpected response: %+v, want: %+v", resp, tc.wantResponse)
switch rr := resp.JSON.(type) {
case spec.InternalServerError, spec.MatrixError, util.JSONResponse:
if !reflect.DeepEqual(tc.wantErrorResponse, resp) {
t.Fatalf("unexpected response: %+v, want: %+v", resp, tc.wantErrorResponse)
}
return
case spec.MatrixError:
if !reflect.DeepEqual(tc.wantResponse, resp) {
t.Fatalf("unexpected response: %+v, want: %+v", resp, tc.wantResponse)
case registerResponse:
// validate the response
if tc.wantUsername != "" {
// if an expected username is provided, assert that it is a match
wantUserID := strings.ToLower(fmt.Sprintf("@%s:%s", tc.wantUsername, "test"))
if wantUserID != rr.UserID {
t.Fatalf("unexpected userID: %s, want %s", rr.UserID, wantUserID)
}
}
return
case util.JSONResponse:
if !reflect.DeepEqual(tc.wantResponse, resp) {
t.Fatalf("unexpected response: %+v, want: %+v", resp, tc.wantResponse)
if rr.DeviceID != *reg.DeviceID {
t.Fatalf("unexpected deviceID: %s, want %s", rr.DeviceID, *reg.DeviceID)
}
return
}
rr, ok := resp.JSON.(registerResponse)
if !ok {
t.Fatalf("expected a registerresponse, got %T", resp.JSON)
}
// validate the response
if tc.forceEmpty {
// when not supplying a username, one will be generated. Given this _SHOULD_ be
// the second user, set the username accordingly
reg.Username = "2"
}
wantUserID := strings.ToLower(fmt.Sprintf("@%s:%s", reg.Username, "test"))
if wantUserID != rr.UserID {
t.Fatalf("unexpected userID: %s, want %s", rr.UserID, wantUserID)
}
if rr.DeviceID != *reg.DeviceID {
t.Fatalf("unexpected deviceID: %s, want %s", rr.DeviceID, *reg.DeviceID)
}
if rr.AccessToken == "" {
t.Fatalf("missing accessToken in response")
if rr.AccessToken == "" {
t.Fatalf("missing accessToken in response")
}
default:
t.Fatalf("expected one of internalservererror, matrixerror, jsonresponse, registerresponse, got %T", resp.JSON)
}
})
}
@ -596,7 +600,7 @@ func TestRegisterUserWithDisplayName(t *testing.T) {
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
deviceName, deviceID := "deviceName", "deviceID"
expectedDisplayName := "DisplayName"
response := completeRegistration(
@ -637,7 +641,7 @@ func TestRegisterAdminUsingSharedSecret(t *testing.T) {
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
rsAPI.SetFederationAPI(nil, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
expectedDisplayName := "rabbit"
jsonStr := []byte(`{"admin":true,"mac":"24dca3bba410e43fe64b9b5c28306693bf3baa9f","nonce":"759f047f312b99ff428b21d581256f8592b8976e58bc1b543972dc6147e529a79657605b52d7becd160ff5137f3de11975684319187e06901955f79e5a6c5a79","password":"wonderland","username":"alice","displayname":"rabbit"}`)

View file

@ -0,0 +1,93 @@
// Copyright 2023 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package routing
import (
"net/http"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/roomserver/api"
userAPI "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
)
type reportEventRequest struct {
Reason string `json:"reason"`
Score int64 `json:"score"`
}
func ReportEvent(
req *http.Request,
device *userAPI.Device,
roomID, eventID string,
rsAPI api.ClientRoomserverAPI,
) util.JSONResponse {
defer req.Body.Close() // nolint: errcheck
deviceUserID, err := spec.NewUserID(device.UserID, true)
if err != nil {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.NotFound("You don't have permission to report this event, bad userID"),
}
}
// The requesting user must be a member of the room
errRes := checkMemberInRoom(req.Context(), rsAPI, *deviceUserID, roomID)
if errRes != nil {
return util.JSONResponse{
Code: http.StatusNotFound, // Spec demands this...
JSON: spec.NotFound("The event was not found or you are not joined to the room."),
}
}
// Parse the request
report := reportEventRequest{}
if resErr := httputil.UnmarshalJSONRequest(req, &report); resErr != nil {
return *resErr
}
queryRes := &api.QueryEventsByIDResponse{}
if err = rsAPI.QueryEventsByID(req.Context(), &api.QueryEventsByIDRequest{
RoomID: roomID,
EventIDs: []string{eventID},
}, queryRes); err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{Err: err.Error()},
}
}
// No event was found or it was already redacted
if len(queryRes.Events) == 0 || queryRes.Events[0].Redacted() {
return util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.NotFound("The event was not found or you are not joined to the room."),
}
}
_, err = rsAPI.InsertReportedEvent(req.Context(), roomID, eventID, device.UserID, report.Reason, report.Score)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{Err: err.Error()},
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct{}{},
}
}

View file

@ -138,7 +138,7 @@ func QueryRoomHierarchy(req *http.Request, device *userapi.Device, roomIDStr str
walker = *cachedWalker
}
discoveredRooms, nextWalker, err := rsAPI.QueryNextRoomHierarchyPage(req.Context(), walker, limit)
discoveredRooms, _, nextWalker, err := rsAPI.QueryNextRoomHierarchyPage(req.Context(), walker, limit)
if err != nil {
switch err.(type) {

View file

@ -44,6 +44,19 @@ import (
"github.com/matrix-org/dendrite/setup/jetstream"
)
type WellKnownClientHomeserver struct {
BaseUrl string `json:"base_url"`
}
type WellKnownSlidingSyncProxy struct {
Url string `json:"url"`
}
type WellKnownClientResponse struct {
Homeserver WellKnownClientHomeserver `json:"m.homeserver"`
SlidingSyncProxy *WellKnownSlidingSyncProxy `json:"org.matrix.msc3575.proxy,omitempty"`
}
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
// to clients which need to make outbound HTTP requests.
//
@ -81,6 +94,7 @@ func Setup(
unstableFeatures := map[string]bool{
"org.matrix.e2e_cross_signing": true,
"org.matrix.msc2285.stable": true,
"org.matrix.msc3916.stable": true,
}
for _, msc := range cfg.MSCs.MSCs {
unstableFeatures["org.matrix."+msc] = true
@ -96,20 +110,22 @@ func Setup(
if cfg.Matrix.WellKnownClientName != "" {
logrus.Infof("Setting m.homeserver base_url as %s at /.well-known/matrix/client", cfg.Matrix.WellKnownClientName)
if cfg.Matrix.WellKnownSlidingSyncProxy != "" {
logrus.Infof("Setting org.matrix.msc3575.proxy url as %s at /.well-known/matrix/client", cfg.Matrix.WellKnownSlidingSyncProxy)
}
wkMux.Handle("/client", httputil.MakeExternalAPI("wellknown", func(r *http.Request) util.JSONResponse {
response := WellKnownClientResponse{
Homeserver: WellKnownClientHomeserver{cfg.Matrix.WellKnownClientName},
}
if cfg.Matrix.WellKnownSlidingSyncProxy != "" {
response.SlidingSyncProxy = &WellKnownSlidingSyncProxy{
Url: cfg.Matrix.WellKnownSlidingSyncProxy,
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct {
HomeserverName struct {
BaseUrl string `json:"base_url"`
} `json:"m.homeserver"`
}{
HomeserverName: struct {
BaseUrl string `json:"base_url"`
}{
BaseUrl: cfg.Matrix.WellKnownClientName,
},
},
JSON: response,
}
})).Methods(http.MethodGet, http.MethodOptions)
}
@ -240,7 +256,7 @@ func Setup(
logrus.Info("Enabling server notices at /_synapse/admin/v1/send_server_notice")
serverNotificationSender, err := getSenderDevice(context.Background(), rsAPI, userAPI, cfg)
if err != nil {
logrus.WithError(err).Fatal("unable to get account for sending sending server notices")
logrus.WithError(err).Fatal("unable to get account for sending server notices")
}
synapseAdminRouter.Handle("/admin/v1/send_server_notice/{txnID}",
@ -717,7 +733,7 @@ func Setup(
).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
v3mux.Handle("/auth/{authType}/fallback/web",
httputil.MakeHTMLAPI("auth_fallback", enableMetrics, func(w http.ResponseWriter, req *http.Request) {
httputil.MakeHTTPAPI("auth_fallback", userAPI, enableMetrics, func(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
AuthFallback(w, req, vars["authType"], cfg)
}),
@ -1256,7 +1272,7 @@ func Setup(
if r := rateLimits.Limit(req, device); r != nil {
return *r
}
return GetCapabilities()
return GetCapabilities(rsAPI)
}, httputil.WithAllowGuests()),
).Methods(http.MethodGet, http.MethodOptions)
@ -1498,4 +1514,58 @@ func Setup(
return GetPresence(req, device, natsClient, cfg.Matrix.JetStream.Prefixed(jetstream.RequestPresence), vars["userId"])
}),
).Methods(http.MethodGet, http.MethodOptions)
v3mux.Handle("/rooms/{roomID}/joined_members",
httputil.MakeAuthAPI("rooms_members", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return GetJoinedMembers(req, device, vars["roomID"], rsAPI)
}),
).Methods(http.MethodGet, http.MethodOptions)
v3mux.Handle("/rooms/{roomID}/report/{eventID}",
httputil.MakeAuthAPI("report_event", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return ReportEvent(req, device, vars["roomID"], vars["eventID"], rsAPI)
}),
).Methods(http.MethodPost, http.MethodOptions)
synapseAdminRouter.Handle("/admin/v1/event_reports",
httputil.MakeAdminAPI("admin_report_events", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
from := parseUint64OrDefault(req.URL.Query().Get("from"), 0)
limit := parseUint64OrDefault(req.URL.Query().Get("limit"), 100)
dir := req.URL.Query().Get("dir")
userID := req.URL.Query().Get("user_id")
roomID := req.URL.Query().Get("room_id")
// Go backwards if direction is empty or "b"
backwards := dir == "" || dir == "b"
return GetEventReports(req, rsAPI, from, limit, backwards, userID, roomID)
}),
).Methods(http.MethodGet, http.MethodOptions)
synapseAdminRouter.Handle("/admin/v1/event_reports/{reportID}",
httputil.MakeAdminAPI("admin_report_event", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return GetEventReport(req, rsAPI, vars["reportID"])
}),
).Methods(http.MethodGet, http.MethodOptions)
synapseAdminRouter.Handle("/admin/v1/event_reports/{reportID}",
httputil.MakeAdminAPI("admin_report_event_delete", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return DeleteEventReport(req, rsAPI, vars["reportID"])
}),
).Methods(http.MethodDelete, http.MethodOptions)
}

View file

@ -29,6 +29,7 @@ import (
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/syncapi/synctypes"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
@ -92,6 +93,30 @@ func SendEvent(
}
}
// Translate user ID state keys to room keys in pseudo ID rooms
if roomVersion == gomatrixserverlib.RoomVersionPseudoIDs && stateKey != nil {
parsedRoomID, innerErr := spec.NewRoomID(roomID)
if innerErr != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("invalid room ID"),
}
}
newStateKey, innerErr := synctypes.FromClientStateKey(*parsedRoomID, *stateKey, func(roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) {
return rsAPI.QuerySenderIDForUser(req.Context(), roomID, userID)
})
if innerErr != nil {
// TODO: work out better logic for failure cases (e.g. sender ID not found)
util.GetLogger(req.Context()).WithError(innerErr).Error("synctypes.FromClientStateKey failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
stateKey = newStateKey
}
// create a mutex for the specific user in the specific room
// this avoids a situation where events that are received in quick succession are sent to the roomserver in a jumbled order
userID := device.UserID
@ -199,7 +224,7 @@ func SendEvent(
req.Context(), rsAPI,
api.KindNew,
[]*types.HeaderedEvent{
&types.HeaderedEvent{PDU: e},
{PDU: e},
},
device.UserDomain(),
domain,
@ -238,7 +263,11 @@ func SendEvent(
}
func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID string, rsAPI api.ClientRoomserverAPI) error {
userMap := r["users"].(map[string]interface{})
users, ok := r["users"]
if !ok {
return nil
}
userMap := users.(map[string]interface{})
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return err
@ -251,8 +280,11 @@ func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID strin
senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *uID)
if err != nil {
return err
} else if senderID == nil {
util.GetLogger(req.Context()).Warnf("sender ID not found for %s in %s", uID, *validRoomID)
continue
}
userMap[string(senderID)] = level
userMap[string(*senderID)] = level
delete(userMap, user)
}
r["users"] = userMap
@ -316,14 +348,21 @@ func generateSendEvent(
senderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *fullUserID)
if err != nil {
return nil, &util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.NotFound("Unable to find senderID for user"),
Code: http.StatusInternalServerError,
JSON: spec.NotFound("internal server error"),
}
} else if senderID == nil {
// TODO: is it always the case that lack of a sender ID means they're not joined?
// And should this logic be deferred to the roomserver somehow?
return nil, &util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden("not joined to room"),
}
}
// create the new event and set all the fields we can
proto := gomatrixserverlib.ProtoEvent{
SenderID: string(senderID),
SenderID: string(*senderID),
RoomID: roomID,
Type: eventType,
StateKey: stateKey,
@ -403,7 +442,7 @@ func generateSendEvent(
JSON: spec.BadJSON("Cannot unmarshal the event content."),
}
}
if content["replacement_room"] == e.RoomID() {
if content["replacement_room"] == e.RoomID().String() {
return nil, &util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("Cannot send tombstone event that points to the same room."),

View file

@ -0,0 +1,275 @@
package routing
import (
"context"
"crypto/ed25519"
"fmt"
"io"
"net/http"
"strings"
"testing"
rsapi "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/setup/config"
uapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"gotest.tools/v3/assert"
)
// Mock roomserver API for testing
//
// Currently pretty specialised for the pseudo ID test, so will need
// editing if future (other) sendevent tests are using this.
type sendEventTestRoomserverAPI struct {
rsapi.ClientRoomserverAPI
t *testing.T
roomIDStr string
roomVersion gomatrixserverlib.RoomVersion
roomState []*types.HeaderedEvent
// userID -> room key
senderMapping map[string]ed25519.PrivateKey
savedInputRoomEvents []rsapi.InputRoomEvent
}
func (s *sendEventTestRoomserverAPI) QueryRoomVersionForRoom(ctx context.Context, roomID string) (gomatrixserverlib.RoomVersion, error) {
if roomID == s.roomIDStr {
return s.roomVersion, nil
} else {
s.t.Logf("room version queried for %s", roomID)
return "", fmt.Errorf("unknown room")
}
}
func (s *sendEventTestRoomserverAPI) QueryCurrentState(ctx context.Context, req *rsapi.QueryCurrentStateRequest, res *rsapi.QueryCurrentStateResponse) error {
res.StateEvents = map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent{}
for _, stateKeyTuple := range req.StateTuples {
for _, stateEv := range s.roomState {
if stateEv.Type() == stateKeyTuple.EventType && stateEv.StateKey() != nil && *stateEv.StateKey() == stateKeyTuple.StateKey {
res.StateEvents[stateKeyTuple] = stateEv
}
}
}
return nil
}
func (s *sendEventTestRoomserverAPI) QueryLatestEventsAndState(ctx context.Context, req *rsapi.QueryLatestEventsAndStateRequest, res *rsapi.QueryLatestEventsAndStateResponse) error {
if req.RoomID == s.roomIDStr {
res.RoomExists = true
res.RoomVersion = s.roomVersion
res.StateEvents = make([]*types.HeaderedEvent, len(s.roomState))
copy(res.StateEvents, s.roomState)
res.LatestEvents = []string{}
res.Depth = 1
return nil
} else {
s.t.Logf("room event/state queried for %s", req.RoomID)
return fmt.Errorf("unknown room")
}
}
func (s *sendEventTestRoomserverAPI) QuerySenderIDForUser(
ctx context.Context,
roomID spec.RoomID,
userID spec.UserID,
) (*spec.SenderID, error) {
if roomID.String() == s.roomIDStr {
if s.roomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
roomKey, ok := s.senderMapping[userID.String()]
if ok {
sender := spec.SenderIDFromPseudoIDKey(roomKey)
return &sender, nil
} else {
return nil, nil
}
} else {
senderID := spec.SenderIDFromUserID(userID)
return &senderID, nil
}
}
return nil, fmt.Errorf("room not found")
}
func (s *sendEventTestRoomserverAPI) QueryUserIDForSender(
ctx context.Context,
roomID spec.RoomID,
senderID spec.SenderID,
) (*spec.UserID, error) {
if roomID.String() == s.roomIDStr {
if s.roomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
for uID, roomKey := range s.senderMapping {
if string(spec.SenderIDFromPseudoIDKey(roomKey)) == string(senderID) {
parsedUserID, err := spec.NewUserID(uID, true)
if err != nil {
s.t.Fatalf("Mock QueryUserIDForSender failed: %s", err)
}
return parsedUserID, nil
}
}
} else {
userID := senderID.ToUserID()
if userID == nil {
return nil, fmt.Errorf("bad sender ID")
}
return userID, nil
}
}
return nil, fmt.Errorf("room not found")
}
func (s *sendEventTestRoomserverAPI) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, sender spec.UserID) (fclient.SigningIdentity, error) {
if s.roomIDStr == roomID.String() {
if s.roomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
roomKey, ok := s.senderMapping[sender.String()]
if !ok {
s.t.Logf("SigningIdentityFor used with unknown user ID: %v", sender.String())
return fclient.SigningIdentity{}, fmt.Errorf("could not get signing identity for %v", sender.String())
}
return fclient.SigningIdentity{PrivateKey: roomKey}, nil
} else {
return fclient.SigningIdentity{PrivateKey: ed25519.NewKeyFromSeed(make([]byte, 32))}, nil
}
}
return fclient.SigningIdentity{}, fmt.Errorf("room not found")
}
func (s *sendEventTestRoomserverAPI) InputRoomEvents(ctx context.Context, req *rsapi.InputRoomEventsRequest, res *rsapi.InputRoomEventsResponse) {
s.savedInputRoomEvents = req.InputRoomEvents
}
// Test that user ID state keys are translated correctly
func Test_SendEvent_PseudoIDStateKeys(t *testing.T) {
nonpseudoIDRoomVersion := gomatrixserverlib.RoomVersionV10
pseudoIDRoomVersion := gomatrixserverlib.RoomVersionPseudoIDs
senderKeySeed := make([]byte, 32)
senderUserID := "@testuser:domain"
senderPrivKey := ed25519.NewKeyFromSeed(senderKeySeed)
senderPseudoID := string(spec.SenderIDFromPseudoIDKey(senderPrivKey))
eventType := "com.example.test"
roomIDStr := "!id:domain"
device := &uapi.Device{
UserID: senderUserID,
}
t.Run("user ID state key are not translated to room key in non-pseudo ID room", func(t *testing.T) {
eventsJSON := []string{
fmt.Sprintf(`{"type":"m.room.create","state_key":"","room_id":"%v","sender":"%v","content":{"creator":"%v","room_version":"%v"}}`, roomIDStr, senderUserID, senderUserID, nonpseudoIDRoomVersion),
fmt.Sprintf(`{"type":"m.room.member","state_key":"%v","room_id":"%v","sender":"%v","content":{"membership":"join"}}`, senderUserID, roomIDStr, senderUserID),
}
roomState, err := createEvents(eventsJSON, nonpseudoIDRoomVersion)
if err != nil {
t.Fatalf("failed to prepare state events: %s", err.Error())
}
rsAPI := &sendEventTestRoomserverAPI{
t: t,
roomIDStr: roomIDStr,
roomVersion: nonpseudoIDRoomVersion,
roomState: roomState,
}
req, err := http.NewRequest("POST", "https://domain", io.NopCloser(strings.NewReader("{}")))
if err != nil {
t.Fatalf("failed to make new request: %s", err.Error())
}
cfg := &config.ClientAPI{}
resp := SendEvent(req, device, roomIDStr, eventType, nil, &senderUserID, cfg, rsAPI, nil)
if resp.Code != http.StatusOK {
t.Fatalf("non-200 HTTP code returned: %v\nfull response: %v", resp.Code, resp)
}
assert.Equal(t, len(rsAPI.savedInputRoomEvents), 1)
ev := rsAPI.savedInputRoomEvents[0]
stateKey := ev.Event.StateKey()
if stateKey == nil {
t.Fatalf("submitted InputRoomEvent has nil state key, when it should be %v", senderUserID)
}
if *stateKey != senderUserID {
t.Fatalf("expected submitted InputRoomEvent to have user ID state key\nfound: %v\nexpected: %v", *stateKey, senderUserID)
}
})
t.Run("user ID state key are translated to room key in pseudo ID room", func(t *testing.T) {
eventsJSON := []string{
fmt.Sprintf(`{"type":"m.room.create","state_key":"","room_id":"%v","sender":"%v","content":{"creator":"%v","room_version":"%v"}}`, roomIDStr, senderPseudoID, senderPseudoID, pseudoIDRoomVersion),
fmt.Sprintf(`{"type":"m.room.member","state_key":"%v","room_id":"%v","sender":"%v","content":{"membership":"join"}}`, senderPseudoID, roomIDStr, senderPseudoID),
}
roomState, err := createEvents(eventsJSON, pseudoIDRoomVersion)
if err != nil {
t.Fatalf("failed to prepare state events: %s", err.Error())
}
rsAPI := &sendEventTestRoomserverAPI{
t: t,
roomIDStr: roomIDStr,
roomVersion: pseudoIDRoomVersion,
senderMapping: map[string]ed25519.PrivateKey{
senderUserID: senderPrivKey,
},
roomState: roomState,
}
req, err := http.NewRequest("POST", "https://domain", io.NopCloser(strings.NewReader("{}")))
if err != nil {
t.Fatalf("failed to make new request: %s", err.Error())
}
cfg := &config.ClientAPI{}
resp := SendEvent(req, device, roomIDStr, eventType, nil, &senderUserID, cfg, rsAPI, nil)
if resp.Code != http.StatusOK {
t.Fatalf("non-200 HTTP code returned: %v\nfull response: %v", resp.Code, resp)
}
assert.Equal(t, len(rsAPI.savedInputRoomEvents), 1)
ev := rsAPI.savedInputRoomEvents[0]
stateKey := ev.Event.StateKey()
if stateKey == nil {
t.Fatalf("submitted InputRoomEvent has nil state key, when it should be %v", senderPseudoID)
}
if *stateKey != senderPseudoID {
t.Fatalf("expected submitted InputRoomEvent to have pseudo ID state key\nfound: %v\nexpected: %v", *stateKey, senderPseudoID)
}
})
}
func createEvents(eventsJSON []string, roomVer gomatrixserverlib.RoomVersion) ([]*types.HeaderedEvent, error) {
events := make([]*types.HeaderedEvent, len(eventsJSON))
roomVerImpl, err := gomatrixserverlib.GetRoomVersion(roomVer)
if err != nil {
return nil, fmt.Errorf("no roomver impl: %s", err.Error())
}
for i, eventJSON := range eventsJSON {
pdu, evErr := roomVerImpl.NewEventFromTrustedJSON([]byte(eventJSON), false)
if evErr != nil {
return nil, fmt.Errorf("failed to make event: %s", evErr.Error())
}
ev := types.HeaderedEvent{PDU: pdu}
events[i] = &ev
}
return events, nil
}

View file

@ -28,7 +28,6 @@ import (
"github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/roomserver/version"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/clientapi/httputil"
@ -95,34 +94,42 @@ func SendServerNotice(
}
}
userID, err := spec.NewUserID(r.UserID, true)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: spec.InvalidParam("invalid user ID"),
}
}
// get rooms for specified user
allUserRooms := []string{}
userRooms := api.QueryRoomsForUserResponse{}
allUserRooms := []spec.RoomID{}
// Get rooms the user is either joined, invited or has left.
for _, membership := range []string{"join", "invite", "leave"} {
if err := rsAPI.QueryRoomsForUser(ctx, &api.QueryRoomsForUserRequest{
UserID: r.UserID,
WantMembership: membership,
}, &userRooms); err != nil {
userRooms, queryErr := rsAPI.QueryRoomsForUser(ctx, *userID, membership)
if queryErr != nil {
return util.ErrorResponse(err)
}
allUserRooms = append(allUserRooms, userRooms.RoomIDs...)
allUserRooms = append(allUserRooms, userRooms...)
}
// get rooms of the sender
senderUserID := fmt.Sprintf("@%s:%s", cfgNotices.LocalPart, cfgClient.Matrix.ServerName)
senderRooms := api.QueryRoomsForUserResponse{}
if err := rsAPI.QueryRoomsForUser(ctx, &api.QueryRoomsForUserRequest{
UserID: senderUserID,
WantMembership: "join",
}, &senderRooms); err != nil {
senderUserID, err := spec.NewUserID(fmt.Sprintf("@%s:%s", cfgNotices.LocalPart, cfgClient.Matrix.ServerName), true)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
senderRooms, err := rsAPI.QueryRoomsForUser(ctx, *senderUserID, "join")
if err != nil {
return util.ErrorResponse(err)
}
// check if we have rooms in common
commonRooms := []string{}
commonRooms := []spec.RoomID{}
for _, userRoomID := range allUserRooms {
for _, senderRoomID := range senderRooms.RoomIDs {
for _, senderRoomID := range senderRooms {
if userRoomID == senderRoomID {
commonRooms = append(commonRooms, senderRoomID)
}
@ -135,12 +142,12 @@ func SendServerNotice(
var (
roomID string
roomVersion = version.DefaultRoomVersion()
roomVersion = rsAPI.DefaultRoomVersion()
)
// create a new room for the user
if len(commonRooms) == 0 {
powerLevelContent := eventutil.InitialPowerLevelsContent(senderUserID)
powerLevelContent := eventutil.InitialPowerLevelsContent(senderUserID.String())
powerLevelContent.Users[r.UserID] = -10 // taken from Synapse
pl, err := json.Marshal(powerLevelContent)
if err != nil {
@ -196,7 +203,7 @@ func SendServerNotice(
}
}
roomID = commonRooms[0]
roomID = commonRooms[0].String()
membershipRes := api.QueryMembershipForUserResponse{}
err = rsAPI.QueryMembershipForUser(ctx, &api.QueryMembershipForUserRequest{UserID: *deviceUserID, RoomID: roomID}, &membershipRes)
if err != nil {
@ -208,7 +215,7 @@ func SendServerNotice(
}
if !membershipRes.IsInRoom {
// re-invite the user
res, err := sendInvite(ctx, userAPI, senderDevice, roomID, r.UserID, "Server notice room", cfgClient, rsAPI, asAPI, time.Now())
res, err := sendInvite(ctx, senderDevice, roomID, r.UserID, "Server notice room", cfgClient, rsAPI, time.Now())
if err != nil {
return res
}

View file

@ -172,28 +172,16 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
}
}
for _, ev := range stateAfterRes.StateEvents {
sender := spec.UserID{}
evRoomID, err := spec.NewRoomID(ev.RoomID())
clientEvent, err := synctypes.ToClientEvent(ev, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
})
if err != nil {
util.GetLogger(ctx).WithError(err).Error("Event roomID is invalid")
util.GetLogger(ctx).WithError(err).Error("Failed converting to ClientEvent")
continue
}
userID, err := rsAPI.QueryUserIDForSender(ctx, *evRoomID, ev.SenderID())
if err == nil && userID != nil {
sender = *userID
}
sk := ev.StateKey()
if sk != nil && *sk != "" {
skUserID, err := rsAPI.QueryUserIDForSender(ctx, *evRoomID, spec.SenderID(*ev.StateKey()))
if err == nil && skUserID != nil {
skString := skUserID.String()
sk = &skString
}
}
stateEvents = append(
stateEvents,
synctypes.ToClientEvent(ev, synctypes.FormatAll, sender, sk),
*clientEvent,
)
}
}
@ -217,6 +205,37 @@ func OnIncomingStateTypeRequest(
var worldReadable bool
var wantLatestState bool
roomVer, err := rsAPI.QueryRoomVersionForRoom(ctx, roomID)
if err != nil {
return util.JSONResponse{
Code: http.StatusForbidden,
JSON: spec.Forbidden(fmt.Sprintf("Unknown room %q or user %q has never joined this room", roomID, device.UserID)),
}
}
// Translate user ID state keys to room keys in pseudo ID rooms
if roomVer == gomatrixserverlib.RoomVersionPseudoIDs {
parsedRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return util.JSONResponse{
Code: http.StatusNotFound,
JSON: spec.InvalidParam("invalid room ID"),
}
}
newStateKey, err := synctypes.FromClientStateKey(*parsedRoomID, stateKey, func(roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) {
return rsAPI.QuerySenderIDForUser(ctx, roomID, userID)
})
if err != nil {
// TODO: work out better logic for failure cases (e.g. sender ID not found)
util.GetLogger(ctx).WithError(err).Error("synctypes.FromClientStateKey failed")
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.Unknown("internal server error"),
}
}
stateKey = *newStateKey
}
// Always fetch visibility so that we can work out whether to show
// the latest events or the last event from when the user was joined.
// Then include the requested event type and state key, assuming it

View file

@ -0,0 +1,253 @@
package routing
import (
"context"
"encoding/json"
"fmt"
"net/http"
"testing"
rsapi "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/setup/config"
uapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
"gotest.tools/v3/assert"
)
var ()
type stateTestRoomserverAPI struct {
rsapi.RoomserverInternalAPI
t *testing.T
roomState map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent
roomIDStr string
roomVersion gomatrixserverlib.RoomVersion
userIDStr string
// userID -> senderID
senderMapping map[string]string
}
func (s stateTestRoomserverAPI) QueryRoomVersionForRoom(ctx context.Context, roomID string) (gomatrixserverlib.RoomVersion, error) {
if roomID == s.roomIDStr {
return s.roomVersion, nil
} else {
s.t.Logf("room version queried for %s", roomID)
return "", fmt.Errorf("unknown room")
}
}
func (s stateTestRoomserverAPI) QueryLatestEventsAndState(
ctx context.Context,
req *rsapi.QueryLatestEventsAndStateRequest,
res *rsapi.QueryLatestEventsAndStateResponse,
) error {
res.RoomExists = req.RoomID == s.roomIDStr
if !res.RoomExists {
return nil
}
res.StateEvents = []*types.HeaderedEvent{}
for _, stateKeyTuple := range req.StateToFetch {
val, ok := s.roomState[stateKeyTuple]
if ok && val != nil {
res.StateEvents = append(res.StateEvents, val)
}
}
return nil
}
func (s stateTestRoomserverAPI) QueryMembershipForUser(
ctx context.Context,
req *rsapi.QueryMembershipForUserRequest,
res *rsapi.QueryMembershipForUserResponse,
) error {
if req.UserID.String() == s.userIDStr {
res.HasBeenInRoom = true
res.IsInRoom = true
res.RoomExists = true
res.Membership = spec.Join
}
return nil
}
func (s stateTestRoomserverAPI) QuerySenderIDForUser(
ctx context.Context,
roomID spec.RoomID,
userID spec.UserID,
) (*spec.SenderID, error) {
sID, ok := s.senderMapping[userID.String()]
if ok {
sender := spec.SenderID(sID)
return &sender, nil
} else {
return nil, nil
}
}
func (s stateTestRoomserverAPI) QueryUserIDForSender(
ctx context.Context,
roomID spec.RoomID,
senderID spec.SenderID,
) (*spec.UserID, error) {
for uID, sID := range s.senderMapping {
if sID == string(senderID) {
parsedUserID, err := spec.NewUserID(uID, true)
if err != nil {
s.t.Fatalf("Mock QueryUserIDForSender failed: %s", err)
}
return parsedUserID, nil
}
}
return nil, nil
}
func (s stateTestRoomserverAPI) QueryStateAfterEvents(
ctx context.Context,
req *rsapi.QueryStateAfterEventsRequest,
res *rsapi.QueryStateAfterEventsResponse,
) error {
return nil
}
func Test_OnIncomingStateTypeRequest(t *testing.T) {
var tempRoomServerCfg config.RoomServer
tempRoomServerCfg.Defaults(config.DefaultOpts{})
defaultRoomVersion := tempRoomServerCfg.DefaultRoomVersion
pseudoIDRoomVersion := gomatrixserverlib.RoomVersionPseudoIDs
nonPseudoIDRoomVersion := gomatrixserverlib.RoomVersionV10
userIDStr := "@testuser:domain"
eventType := "com.example.test"
stateKey := "testStateKey"
roomIDStr := "!id:domain"
device := &uapi.Device{
UserID: userIDStr,
}
t.Run("request simple state key", func(t *testing.T) {
ctx := context.Background()
rsAPI := stateTestRoomserverAPI{
roomVersion: defaultRoomVersion,
roomIDStr: roomIDStr,
roomState: map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent{
{
EventType: eventType,
StateKey: stateKey,
}: mustCreateStatePDU(t, defaultRoomVersion, roomIDStr, eventType, stateKey, map[string]interface{}{
"foo": "bar",
}),
},
userIDStr: userIDStr,
}
jsonResp := OnIncomingStateTypeRequest(ctx, device, rsAPI, roomIDStr, eventType, stateKey, false)
assert.DeepEqual(t, jsonResp, util.JSONResponse{
Code: http.StatusOK,
JSON: spec.RawJSON(`{"foo":"bar"}`),
})
})
t.Run("user ID key translated to room key in pseudo ID rooms", func(t *testing.T) {
ctx := context.Background()
stateSenderUserID := "@sender:domain"
stateSenderRoomKey := "testsenderkey"
rsAPI := stateTestRoomserverAPI{
roomVersion: pseudoIDRoomVersion,
roomIDStr: roomIDStr,
roomState: map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent{
{
EventType: eventType,
StateKey: stateSenderRoomKey,
}: mustCreateStatePDU(t, pseudoIDRoomVersion, roomIDStr, eventType, stateSenderRoomKey, map[string]interface{}{
"foo": "bar",
}),
{
EventType: eventType,
StateKey: stateSenderUserID,
}: mustCreateStatePDU(t, pseudoIDRoomVersion, roomIDStr, eventType, stateSenderUserID, map[string]interface{}{
"not": "thisone",
}),
},
userIDStr: userIDStr,
senderMapping: map[string]string{
stateSenderUserID: stateSenderRoomKey,
},
}
jsonResp := OnIncomingStateTypeRequest(ctx, device, rsAPI, roomIDStr, eventType, stateSenderUserID, false)
assert.DeepEqual(t, jsonResp, util.JSONResponse{
Code: http.StatusOK,
JSON: spec.RawJSON(`{"foo":"bar"}`),
})
})
t.Run("user ID key not translated to room key in non-pseudo ID rooms", func(t *testing.T) {
ctx := context.Background()
stateSenderUserID := "@sender:domain"
stateSenderRoomKey := "testsenderkey"
rsAPI := stateTestRoomserverAPI{
roomVersion: nonPseudoIDRoomVersion,
roomIDStr: roomIDStr,
roomState: map[gomatrixserverlib.StateKeyTuple]*types.HeaderedEvent{
{
EventType: eventType,
StateKey: stateSenderRoomKey,
}: mustCreateStatePDU(t, nonPseudoIDRoomVersion, roomIDStr, eventType, stateSenderRoomKey, map[string]interface{}{
"not": "thisone",
}),
{
EventType: eventType,
StateKey: stateSenderUserID,
}: mustCreateStatePDU(t, nonPseudoIDRoomVersion, roomIDStr, eventType, stateSenderUserID, map[string]interface{}{
"foo": "bar",
}),
},
userIDStr: userIDStr,
senderMapping: map[string]string{
stateSenderUserID: stateSenderUserID,
},
}
jsonResp := OnIncomingStateTypeRequest(ctx, device, rsAPI, roomIDStr, eventType, stateSenderUserID, false)
assert.DeepEqual(t, jsonResp, util.JSONResponse{
Code: http.StatusOK,
JSON: spec.RawJSON(`{"foo":"bar"}`),
})
})
}
func mustCreateStatePDU(t *testing.T, roomVer gomatrixserverlib.RoomVersion, roomID string, stateType string, stateKey string, stateContent map[string]interface{}) *types.HeaderedEvent {
t.Helper()
roomVerImpl := gomatrixserverlib.MustGetRoomVersion(roomVer)
evBytes, err := json.Marshal(map[string]interface{}{
"room_id": roomID,
"type": stateType,
"state_key": stateKey,
"content": stateContent,
})
if err != nil {
t.Fatalf("failed to create event: %v", err)
}
ev, err := roomVerImpl.NewEventFromTrustedJSON(evBytes, false)
if err != nil {
t.Fatalf("failed to create event: %v", err)
}
return &types.HeaderedEvent{PDU: ev}
}

View file

@ -366,9 +366,11 @@ func emit3PIDInviteEvent(
sender, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *userID)
if err != nil {
return err
} else if sender == nil {
return fmt.Errorf("sender ID not found for %s in %s", *userID, *validRoomID)
}
proto := &gomatrixserverlib.ProtoEvent{
SenderID: string(sender),
SenderID: string(*sender),
RoomID: roomID,
Type: "m.room.third_party_invite",
StateKey: &res.Token,

View file

@ -83,6 +83,7 @@ func CreateSession(
if err != nil {
return "", err
}
defer resp.Body.Close() // nolint: errcheck
// Error if the status isn't OK
if resp.StatusCode != http.StatusOK {

View file

@ -145,7 +145,7 @@ func (p *P2PMonolith) SetupDendrite(
)
rsAPI.SetFederationAPI(fsAPI, keyRing)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation, enableMetrics, fsAPI.IsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
@ -221,8 +221,8 @@ func (p *P2PMonolith) closeAllResources() {
p.httpServerMu.Lock()
if p.httpServer != nil {
_ = p.httpServer.Shutdown(context.Background())
p.httpServerMu.Unlock()
}
p.httpServerMu.Unlock()
select {
case p.stopHandlingEvents <- true:

View file

@ -17,13 +17,13 @@ package relay
import (
"context"
"sync"
"sync/atomic"
"time"
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
relayServerAPI "github.com/matrix-org/dendrite/relayapi/api"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/sirupsen/logrus"
"go.uber.org/atomic"
)
const (
@ -54,7 +54,7 @@ func NewRelayServerRetriever(
federationAPI: federationAPI,
relayAPI: relayAPI,
relayServersQueried: make(map[spec.ServerName]bool),
running: *atomic.NewBool(false),
running: atomic.Bool{},
quit: quit,
}
}

View file

@ -1,6 +1,6 @@
# Yggdrasil Demo
This is the Dendrite Yggdrasil demo! It's easy to get started - all you need is Go 1.18 or later.
This is the Dendrite Yggdrasil demo! It's easy to get started - all you need is Go 1.21 or later.
To run the homeserver, start at the root of the Dendrite repository and run:

View file

@ -59,7 +59,7 @@ var (
instanceName = flag.String("name", "dendrite-p2p-ygg", "the name of this P2P demo instance")
instancePort = flag.Int("port", 8008, "the port that the client API will listen on")
instancePeer = flag.String("peer", "", "the static Yggdrasil peers to connect to, comma separated-list")
instanceListen = flag.String("listen", "tcp://:0", "the port Yggdrasil peers can connect to")
instanceListen = flag.String("listen", "tls://:0", "the port Yggdrasil peers can connect to")
instanceDir = flag.String("dir", ".", "the directory to store the databases in (if --config not specified)")
)
@ -134,6 +134,7 @@ func main() {
cfg.RoomServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-roomserver.db", filepath.Join(*instanceDir, *instanceName)))
cfg.KeyServer.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-keyserver.db", filepath.Join(*instanceDir, *instanceName)))
cfg.FederationAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-federationapi.db", filepath.Join(*instanceDir, *instanceName)))
cfg.RelayAPI.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-relayapi.db", filepath.Join(*instanceDir, *instanceName)))
cfg.MSCs.MSCs = []string{"msc2836"}
cfg.MSCs.Database.ConnectionString = config.DataSource(fmt.Sprintf("file:%s-mscs.db", filepath.Join(*instanceDir, *instanceName)))
cfg.ClientAPI.RegistrationDisabled = false
@ -213,16 +214,16 @@ func main() {
natsInstance := jetstream.NATSInstance{}
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.EnableMetrics)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
rsAPI.SetAppserviceAPI(asAPI)
fsAPI := federationapi.NewInternalAPI(
processCtx, cfg, cm, &natsInstance, federation, rsAPI, caches, keyRing, true,
)
rsAPI.SetFederationAPI(fsAPI, keyRing)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federation, caching.EnableMetrics, fsAPI.IsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
rsAPI.SetAppserviceAPI(asAPI)
monolith := setup.Monolith{
Config: cfg,
Client: ygg.CreateClient(),

View file

@ -18,16 +18,15 @@ import (
"context"
"crypto/ed25519"
"encoding/hex"
"fmt"
"net"
"regexp"
"strings"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/neilalexander/utp"
"github.com/sirupsen/logrus"
"github.com/yggdrasil-network/yggquic"
ironwoodtypes "github.com/Arceliar/ironwood/types"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
"github.com/yggdrasil-network/yggdrasil-go/src/core"
yggdrasilcore "github.com/yggdrasil-network/yggdrasil-go/src/core"
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
@ -40,25 +39,23 @@ type Node struct {
core *yggdrasilcore.Core
multicast *yggdrasilmulticast.Multicast
log *gologme.Logger
utpSocket *utp.Socket
incoming chan net.Conn
*yggquic.YggdrasilTransport
}
func (n *Node) DialerContext(ctx context.Context, _, address string) (net.Conn, error) {
tokens := strings.Split(address, ":")
raw, err := hex.DecodeString(tokens[0])
if err != nil {
return nil, fmt.Errorf("hex.DecodeString: %w", err)
}
pk := make(ironwoodtypes.Addr, ed25519.PublicKeySize)
copy(pk, raw[:])
return n.utpSocket.DialAddrContext(ctx, pk)
return n.DialContext(ctx, "yggdrasil", tokens[0])
}
func Setup(sk ed25519.PrivateKey, instanceName, storageDirectory, peerURI, listenURI string) (*Node, error) {
n := &Node{
log: gologme.New(logrus.StandardLogger().Writer(), "", 0),
incoming: make(chan net.Conn),
log: gologme.New(logrus.StandardLogger().Writer(), "", 0),
}
cfg := config.GenerateConfig()
cfg.PrivateKey = config.KeyBytes(sk)
if err := cfg.GenerateSelfSignedCertificate(); err != nil {
panic(err)
}
n.log.EnableLevel("error")
@ -78,12 +75,12 @@ func Setup(sk ed25519.PrivateKey, instanceName, storageDirectory, peerURI, liste
})
}
}
if n.core, err = core.New(sk[:], n.log, options...); err != nil {
if n.core, err = core.New(cfg.Certificate, n.log, options...); err != nil {
panic(err)
}
n.core.SetLogger(n.log)
if n.utpSocket, err = utp.NewSocketFromPacketConnNoClose(n.core); err != nil {
if n.YggdrasilTransport, err = yggquic.New(n.core, *cfg.Certificate, nil); err != nil {
panic(err)
}
}
@ -106,8 +103,6 @@ func Setup(sk ed25519.PrivateKey, instanceName, storageDirectory, peerURI, liste
}
n.log.Printf("Public key: %x", n.core.PublicKey())
go n.listenFromYgg()
return n, nil
}

View file

@ -1,56 +0,0 @@
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package yggconn
import (
"context"
"net"
)
func (n *Node) listenFromYgg() {
for {
conn, err := n.utpSocket.Accept()
if err != nil {
n.log.Println("n.utpSocket.Accept:", err)
return
}
n.incoming <- conn
}
}
// Implements net.Listener
func (n *Node) Accept() (net.Conn, error) {
return <-n.incoming, nil
}
// Implements net.Listener
func (n *Node) Close() error {
return n.utpSocket.Close()
}
// Implements net.Listener
func (n *Node) Addr() net.Addr {
return n.utpSocket.Addr()
}
// Implements http.Transport.Dial
func (n *Node) Dial(network, address string) (net.Conn, error) {
return n.DialContext(context.TODO(), network, address)
}
// Implements http.Transport.DialContext
func (n *Node) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
return n.utpSocket.DialContext(ctx, network, address)
}

View file

@ -7,7 +7,6 @@ import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
@ -55,7 +54,7 @@ var latest, _ = semver.NewVersion("v6.6.6") // Dummy version, used as "HEAD"
// due to the error:
// When using COPY with more than one source file, the destination must be a directory and end with a /
// We need to run a postgres anyway, so use the dockerfile associated with Complement instead.
const DockerfilePostgreSQL = `FROM golang:1.18-buster as build
const DockerfilePostgreSQL = `FROM golang:1.22-bookworm as build
RUN apt-get update && apt-get install -y postgresql
WORKDIR /build
ARG BINARY
@ -68,22 +67,20 @@ RUN go build ./cmd/${BINARY}
RUN go build ./cmd/generate-keys
RUN go build ./cmd/generate-config
RUN go build ./cmd/create-account
RUN ./generate-config --ci > dendrite.yaml
RUN ./generate-config --ci --db "user=postgres database=postgres host=/var/run/postgresql/" > dendrite.yaml
RUN ./generate-keys --private-key matrix_key.pem --tls-cert server.crt --tls-key server.key
# Replace the connection string with a single postgres DB, using user/db = 'postgres' and no password
RUN sed -i "s%connection_string:.*$%connection_string: postgresql://postgres@localhost/postgres?sslmode=disable%g" dendrite.yaml
# No password when connecting over localhost
RUN sed -i "s%127.0.0.1/32 md5%127.0.0.1/32 trust%g" /etc/postgresql/11/main/pg_hba.conf
# No password when connecting to Postgres
RUN sed -i "s%peer%trust%g" /etc/postgresql/15/main/pg_hba.conf
# Bump up max conns for moar concurrency
RUN sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/11/main/postgresql.conf
RUN sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/15/main/postgresql.conf
RUN sed -i 's/max_open_conns:.*$/max_open_conns: 100/g' dendrite.yaml
# This entry script starts postgres, waits for it to be up then starts dendrite
RUN echo '\
#!/bin/bash -eu \n\
pg_lsclusters \n\
pg_ctlcluster 11 main start \n\
pg_ctlcluster 15 main start \n\
\n\
until pg_isready \n\
do \n\
@ -101,7 +98,7 @@ ENV BINARY=dendrite
EXPOSE 8008 8448
CMD /build/run_dendrite.sh`
const DockerfileSQLite = `FROM golang:1.18-buster as build
const DockerfileSQLite = `FROM golang:1.22-bookworm as build
RUN apt-get update && apt-get install -y postgresql
WORKDIR /build
ARG BINARY
@ -119,7 +116,7 @@ RUN ./generate-keys --private-key matrix_key.pem --tls-cert server.crt --tls-key
# Make sure the SQLite databases are in a persistent location, we're already mapping
# the postgresql folder so let's just use that for simplicity
RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postgresql\/11\/main\/%g" dendrite.yaml
RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postgresql\/15\/main\/%g" dendrite.yaml
# This entry script starts postgres, waits for it to be up then starts dendrite
RUN echo '\
@ -402,7 +399,7 @@ func runImage(dockerClient *client.Client, volumeName string, branchNameToImageI
{
Type: mount.TypeVolume,
Source: volumeName,
Target: "/var/lib/postgresql/11/main",
Target: "/var/lib/postgresql/15/main",
},
},
}, nil, nil, "dendrite_upgrade_test_"+branchName)
@ -411,7 +408,7 @@ func runImage(dockerClient *client.Client, volumeName string, branchNameToImageI
}
containerID = body.ID
err = dockerClient.ContainerStart(ctx, containerID, types.ContainerStartOptions{})
err = dockerClient.ContainerStart(ctx, containerID, container.StartOptions{})
if err != nil {
return "", "", fmt.Errorf("failed to ContainerStart: %s", err)
}
@ -443,7 +440,7 @@ func runImage(dockerClient *client.Client, volumeName string, branchNameToImageI
lastErr = nil
break
}
logs, err := dockerClient.ContainerLogs(context.Background(), containerID, types.ContainerLogsOptions{
logs, err := dockerClient.ContainerLogs(context.Background(), containerID, container.LogsOptions{
ShowStdout: true,
ShowStderr: true,
Follow: true,
@ -464,7 +461,7 @@ func runImage(dockerClient *client.Client, volumeName string, branchNameToImageI
}
func destroyContainer(dockerClient *client.Client, containerID string) {
err := dockerClient.ContainerRemove(context.TODO(), containerID, types.ContainerRemoveOptions{
err := dockerClient.ContainerRemove(context.TODO(), containerID, container.RemoveOptions{
Force: true,
})
if err != nil {
@ -515,7 +512,7 @@ func testCreateAccount(dockerClient *client.Client, version *semver.Version, con
}
defer response.Close()
data, err := ioutil.ReadAll(response.Reader)
data, err := io.ReadAll(response.Reader)
if err != nil {
return err
}
@ -551,15 +548,15 @@ func verifyTests(dockerClient *client.Client, volumeName string, versions []*sem
// cleanup old containers/volumes from a previous run
func cleanup(dockerClient *client.Client) {
// ignore all errors, we are just cleaning up and don't want to fail just because we fail to cleanup
containers, _ := dockerClient.ContainerList(context.Background(), types.ContainerListOptions{
containers, _ := dockerClient.ContainerList(context.Background(), container.ListOptions{
Filters: label(dendriteUpgradeTestLabel),
All: true,
})
for _, c := range containers {
log.Printf("Removing container: %v %v\n", c.ID, c.Names)
s := time.Second
_ = dockerClient.ContainerStop(context.Background(), c.ID, &s)
_ = dockerClient.ContainerRemove(context.Background(), c.ID, types.ContainerRemoveOptions{
timeout := 1
_ = dockerClient.ContainerStop(context.Background(), c.ID, container.StopOptions{Timeout: &timeout})
_ = dockerClient.ContainerRemove(context.Background(), c.ID, container.RemoveOptions{
Force: true,
})
}
@ -592,7 +589,7 @@ func main() {
branchToImageID := buildDendriteImages(httpClient, dockerClient, *flagTempDir, *flagBuildConcurrency, versions)
// make a shared postgres volume
volume, err := dockerClient.VolumeCreate(context.Background(), volume.VolumeCreateBody{
volume, err := dockerClient.VolumeCreate(context.Background(), volume.CreateOptions{
Name: "dendrite_upgrade_test",
Labels: map[string]string{
dendriteUpgradeTestLabel: "yes",

View file

@ -162,7 +162,7 @@ func main() {
// dependency. Other components also need updating after their dependencies are up.
rsAPI.SetFederationAPI(fsAPI, keyRing)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federationClient)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federationClient, caching.EnableMetrics, fsAPI.IsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
rsAPI.SetAppserviceAPI(asAPI)

View file

@ -11,13 +11,11 @@ import (
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/roomserver/state"
"github.com/matrix-org/dendrite/roomserver/storage"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/setup"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/jetstream"
"github.com/matrix-org/dendrite/setup/process"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
@ -35,6 +33,19 @@ var roomVersion = flag.String("roomversion", "5", "the room version to parse eve
var filterType = flag.String("filtertype", "", "the event types to filter on")
var difference = flag.Bool("difference", false, "whether to calculate the difference between snapshots")
// dummyQuerier implements QuerySenderIDAPI. Does **NOT** do any "magic" for pseudoID rooms
// to avoid having to "start" a full roomserver API.
type dummyQuerier struct{}
func (d dummyQuerier) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) {
s := spec.SenderIDFromUserID(userID)
return &s, nil
}
func (d dummyQuerier) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return senderID.ToUserID(), nil
}
// nolint:gocyclo
func main() {
ctx := context.Background()
@ -56,27 +67,32 @@ func main() {
}
}
fmt.Println("Fetching", len(snapshotNIDs), "snapshot NIDs")
processCtx := process.NewProcessContext()
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
dbOpts := cfg.RoomServer.Database
if dbOpts.ConnectionString == "" {
dbOpts = cfg.Global.DatabaseOptions
}
fmt.Println("Opening database")
roomserverDB, err := storage.Open(
processCtx.Context(), cm, &cfg.RoomServer.Database,
caching.NewRistrettoCache(128*1024*1024, time.Hour, true),
processCtx.Context(), cm, &dbOpts,
caching.NewRistrettoCache(8*1024*1024, time.Minute*5, caching.DisableMetrics),
)
if err != nil {
panic(err)
}
natsInstance := &jetstream.NATSInstance{}
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm,
natsInstance, caching.NewRistrettoCache(128*1024*1024, time.Hour, true), false)
rsAPI := dummyQuerier{}
roomInfo := &types.RoomInfo{
RoomVersion: gomatrixserverlib.RoomVersion(*roomVersion),
}
stateres := state.NewStateResolution(roomserverDB, roomInfo, rsAPI)
fmt.Println("Fetching", len(snapshotNIDs), "snapshot NIDs")
if *difference {
if len(snapshotNIDs) != 2 {
panic("need exactly two state snapshot NIDs to calculate difference")
@ -186,12 +202,25 @@ func main() {
authEvents[i] = authEventEntries[i].PDU
}
// Get the roomNID
roomInfo, err = roomserverDB.RoomInfo(ctx, authEvents[0].RoomID().String())
if err != nil {
panic(err)
}
fmt.Println("Resolving state")
var resolved Events
resolved, err = gomatrixserverlib.ResolveConflicts(
gomatrixserverlib.RoomVersion(*roomVersion), events, authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
},
func(eventID string) bool {
isRejected, rejectedErr := roomserverDB.IsEventRejected(ctx, roomInfo.RoomNID, eventID)
if rejectedErr != nil {
return true
}
return isRejected
},
)
if err != nil {
panic(err)

View file

@ -0,0 +1,185 @@
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"flag"
"os"
"time"
"github.com/getsentry/sentry-go"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/setup/jetstream"
"github.com/matrix-org/dendrite/setup/process"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/federationapi"
"github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/setup"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/mscs"
"github.com/matrix-org/dendrite/userapi"
)
var (
samAddr = flag.String("samaddr", "127.0.0.1:7656", "Address to connect to the I2P SAMv3 API")
_, skip = os.LookupEnv("CI")
)
func main() {
cfg := setup.ParseFlags(true)
if skip {
return
}
configErrors := &config.ConfigErrors{}
cfg.Verify(configErrors)
if len(*configErrors) > 0 {
for _, err := range *configErrors {
logrus.Errorf("Configuration error: %s", err)
}
logrus.Fatalf("Failed to start due to configuration errors")
}
processCtx := process.NewProcessContext()
internal.SetupStdLogging()
internal.SetupHookLogging(cfg.Logging)
internal.SetupPprof()
basepkg.PlatformSanityChecks()
logrus.Infof("Dendrite version %s", internal.VersionString())
if !cfg.ClientAPI.RegistrationDisabled && cfg.ClientAPI.OpenRegistrationWithoutVerificationEnabled {
logrus.Warn("Open registration is enabled")
}
// create DNS cache
var dnsCache *fclient.DNSCache
if cfg.Global.DNSCache.Enabled {
dnsCache = fclient.NewDNSCache(
cfg.Global.DNSCache.CacheSize,
cfg.Global.DNSCache.CacheLifetime,
)
logrus.Infof(
"DNS cache enabled (size %d, lifetime %s)",
cfg.Global.DNSCache.CacheSize,
cfg.Global.DNSCache.CacheLifetime,
)
}
// setup tracing
closer, err := cfg.SetupTracing()
if err != nil {
logrus.WithError(err).Panicf("failed to start opentracing")
}
defer closer.Close() // nolint: errcheck
// setup sentry
if cfg.Global.Sentry.Enabled {
logrus.Info("Setting up Sentry for debugging...")
err = sentry.Init(sentry.ClientOptions{
Dsn: cfg.Global.Sentry.DSN,
Environment: cfg.Global.Sentry.Environment,
Debug: true,
ServerName: string(cfg.Global.ServerName),
Release: "dendrite@" + internal.VersionString(),
AttachStacktrace: true,
})
if err != nil {
logrus.WithError(err).Panic("failed to start Sentry")
}
go func() {
processCtx.ComponentStarted()
<-processCtx.WaitForShutdown()
if !sentry.Flush(time.Second * 5) {
logrus.Warnf("failed to flush all Sentry events!")
}
processCtx.ComponentFinished()
}()
}
federationClient := basepkg.CreateFederationClient(cfg, dnsCache)
httpClient := basepkg.CreateClient(cfg, dnsCache)
// prepare required dependencies
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
routers := httputil.NewRouters()
caches := caching.NewRistrettoCache(cfg.Global.Cache.EstimatedMaxSize, cfg.Global.Cache.MaxAge, caching.EnableMetrics)
natsInstance := jetstream.NATSInstance{}
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.EnableMetrics)
fsAPI := federationapi.NewInternalAPI(
processCtx, cfg, cm, &natsInstance, federationClient, rsAPI, caches, nil, false,
)
keyRing := fsAPI.KeyRing()
// The underlying roomserver implementation needs to be able to call the fedsender.
// This is different to rsAPI which can be the http client which doesn't need this
// dependency. Other components also need updating after their dependencies are up.
rsAPI.SetFederationAPI(fsAPI, keyRing)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federationClient, caching.EnableMetrics, fsAPI.IsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
rsAPI.SetAppserviceAPI(asAPI)
rsAPI.SetUserAPI(userAPI)
monolith := setup.Monolith{
Config: cfg,
Client: httpClient,
FedClient: federationClient,
KeyRing: keyRing,
AppserviceAPI: asAPI,
// always use the concrete impl here even in -http mode because adding public routes
// must be done on the concrete impl not an HTTP client else fedapi will call itself
FederationAPI: fsAPI,
RoomserverAPI: rsAPI,
UserAPI: userAPI,
}
monolith.AddAllPublicRoutes(processCtx, cfg, routers, cm, &natsInstance, caches, caching.EnableMetrics)
if len(cfg.MSCs.MSCs) > 0 {
if err := mscs.Enable(cfg, cm, routers, &monolith, caches); err != nil {
logrus.WithError(err).Fatalf("Failed to enable MSCs")
}
}
upCounter := prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "dendrite",
Name: "up",
ConstLabels: map[string]string{
"version": internal.VersionString(),
},
})
upCounter.Add(1)
prometheus.MustRegister(upCounter)
// Expose the matrix APIs directly rather than putting them under a /api path.
go func() {
SetupAndServeHTTPS(processCtx, cfg, routers) //, httpsAddr, nil, nil)
}()
// We want to block forever to let the HTTP and HTTPS handler serve the APIs
basepkg.WaitForShutdown(processCtx)
}

View file

@ -0,0 +1,233 @@
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"bytes"
"context"
"crypto/tls"
"embed"
"net"
"net/http"
"net/url"
"strings"
"sync/atomic"
"text/template"
"github.com/cretz/bine/tor"
"github.com/eyedeekay/goSam"
"github.com/eyedeekay/onramp"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/gorilla/mux"
"github.com/kardianos/minwinsvc"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/setup/process"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func client() (*goSam.Client, error) {
if skip {
return nil, nil
}
return goSam.NewClient(*samAddr)
}
var sam, samError = client()
func start() (*tor.Tor, error) {
if skip {
return nil, nil
}
return tor.Start(context.Background(), nil)
}
func dialer() (*tor.Dialer, error) {
if skip {
return nil, nil
}
return t.Dialer(context.TODO(), nil)
}
var (
t, terr = start()
tdialer, tderr = dialer()
)
// Dial a network connection to an I2P server or a unix socket. Use Tor, or Fail for clearnet addresses.
func DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
if samError != nil {
return nil, samError
}
if network == "unix" {
return net.Dial(network, addr)
}
// convert the addr to a full URL
url, err := url.Parse(addr)
if err != nil {
return nil, err
}
if strings.HasSuffix(url.Host, ".i2p") {
return sam.DialContext(ctx, network, addr)
}
if terr != nil {
return nil, terr
}
if (tderr != nil) || (tdialer == nil) {
return nil, tderr
}
return tdialer.DialContext(ctx, network, addr)
}
//go:embed static/*.gotmpl
var staticContent embed.FS
// SetupAndServeHTTPS sets up the HTTPS server to serve client & federation APIs
// and adds a prometheus handler under /_dendrite/metrics.
func SetupAndServeHTTPS(
processContext *process.ProcessContext,
cfg *config.Dendrite,
routers httputil.Routers,
) {
// create a transport that uses SAM to dial TCP Connections
httpClient := &http.Client{
Transport: &http.Transport{
DialContext: DialContext,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
http.DefaultClient = httpClient
garlic, err := onramp.NewGarlic("dendrite", *samAddr, onramp.OPT_HUGE)
if err != nil {
logrus.WithError(err).Fatal("failed to create garlic")
}
defer garlic.Close() // nolint: errcheck
listener, err := garlic.ListenTLS()
if err != nil {
logrus.WithError(err).Fatal("failed to serve HTTPS")
}
defer listener.Close() // nolint: errcheck
externalHTTPSAddr := config.ServerAddress{}
https, err := config.HTTPAddress("https://" + listener.Addr().String())
if err != nil {
logrus.WithError(err).Fatalf("Failed to parse http address")
}
externalHTTPSAddr = https
externalRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
externalServ := &http.Server{
Addr: externalHTTPSAddr.Address,
WriteTimeout: basepkg.HTTPServerTimeout,
Handler: externalRouter,
BaseContext: func(_ net.Listener) context.Context {
return processContext.Context()
},
}
// Redirect for Landing Page
externalRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, httputil.PublicStaticPath, http.StatusFound)
})
if cfg.Global.Metrics.Enabled {
externalRouter.Handle("/metrics", httputil.WrapHandlerInBasicAuth(promhttp.Handler(), cfg.Global.Metrics.BasicAuth))
}
basepkg.ConfigureAdminEndpoints(processContext, routers)
// Parse and execute the landing page template
tmpl := template.Must(template.ParseFS(staticContent, "static/*.gotmpl"))
landingPage := &bytes.Buffer{}
if err := tmpl.ExecuteTemplate(landingPage, "index.gotmpl", map[string]string{
"Version": internal.VersionString(),
}); err != nil {
logrus.WithError(err).Fatal("failed to execute landing page template")
}
routers.Static.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(landingPage.Bytes())
})
var clientHandler http.Handler
clientHandler = routers.Client
if cfg.Global.Sentry.Enabled {
sentryHandler := sentryhttp.New(sentryhttp.Options{
Repanic: true,
})
clientHandler = sentryHandler.Handle(routers.Client)
}
var federationHandler http.Handler
federationHandler = routers.Federation
if cfg.Global.Sentry.Enabled {
sentryHandler := sentryhttp.New(sentryhttp.Options{
Repanic: true,
})
federationHandler = sentryHandler.Handle(routers.Federation)
}
externalRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(routers.DendriteAdmin)
externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(clientHandler)
if !cfg.Global.DisableFederation {
externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(routers.Keys)
externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(federationHandler)
}
externalRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(routers.SynapseAdmin)
externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(routers.Media)
externalRouter.PathPrefix(httputil.PublicWellKnownPrefix).Handler(routers.WellKnown)
externalRouter.PathPrefix(httputil.PublicStaticPath).Handler(routers.Static)
externalRouter.NotFoundHandler = httputil.NotFoundCORSHandler
externalRouter.MethodNotAllowedHandler = httputil.NotAllowedHandler
if externalHTTPSAddr.Enabled() {
go func() {
var externalShutdown atomic.Bool // RegisterOnShutdown can be called more than once
logrus.Infof("Starting external listener on https://%s", externalServ.Addr)
processContext.ComponentStarted()
externalServ.RegisterOnShutdown(func() {
if externalShutdown.CompareAndSwap(false, true) {
processContext.ComponentFinished()
logrus.Infof("Stopped external HTTPS listener")
}
})
addr := listener.Addr()
externalServ.Addr = addr.String()
if err := externalServ.Serve(listener); err != nil {
if err != http.ErrServerClosed {
logrus.WithError(err).Fatal("failed to serve HTTPS")
}
}
logrus.Infof("Stopped external listener on %s", externalServ.Addr)
}()
}
minwinsvc.SetOnExit(processContext.ShutdownDendrite)
<-processContext.WaitForShutdown()
logrus.Infof("Stopping HTTPS listeners")
_ = externalServ.Shutdown(context.Background())
logrus.Infof("Stopped HTTPS listeners")
}

View file

@ -0,0 +1,50 @@
package main
import (
"os"
"os/signal"
"strings"
"syscall"
"testing"
)
// This is an instrumented main, used when running integration tests (sytest) with code coverage.
// Compile: go test -c -race -cover -covermode=atomic -o monolith.debug -coverpkg "github.com/matrix-org/..." ./cmd/dendrite
// Run the monolith: ./monolith.debug -test.coverprofile=/somewhere/to/dump/integrationcover.out DEVEL --config dendrite.yaml
// Generate HTML with coverage: go tool cover -html=/somewhere/where/there/is/integrationcover.out -o cover.html
// Source: https://dzone.com/articles/measuring-integration-test-coverage-rate-in-pouchc
func TestMain(t *testing.T) {
var args []string
for _, arg := range os.Args {
switch {
case strings.HasPrefix(arg, "DEVEL"):
case strings.HasPrefix(arg, "-test"):
default:
args = append(args, arg)
}
}
// only run the tests if there are args to be passed
if len(args) <= 1 {
return
}
t.Log(args)
waitCh := make(chan int, 1)
os.Args = args
go func() {
main()
close(waitCh)
}()
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGHUP)
select {
case <-signalCh:
return
case <-waitCh:
return
}
}

View file

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dendrite is running</title>
<style>
body {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
max-width: 40em;
margin: auto;
text-align: center;
}
h1, p {
margin: 1.5em;
}
hr {
border: none;
background-color: #ccc;
color: #ccc;
height: 1px;
width: 7em;
margin-top: 4em;
}
.logo {
display: block;
width: 12em;
margin: 4em auto;
}
</style>
</head>
<body>
<div class="logo">
<svg role="img" aria-label="[Matrix logo]" viewBox="0 0 200 85" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="parent" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="child" transform="translate(-122.000000, -6.000000)" fill="#000000" fill-rule="nonzero">
<g id="matrix-logo" transform="translate(122.000000, 6.000000)">
<polygon id="left-bracket" points="2.24708861 1.93811009 2.24708861 82.7268844 8.10278481 82.7268844 8.10278481 84.6652459 0 84.6652459 0 0 8.10278481 0 8.10278481 1.93811009"></polygon>
<path d="M24.8073418,27.5493174 L24.8073418,31.6376991 L24.924557,31.6376991 C26.0227848,30.0814294 27.3455696,28.8730642 28.8951899,28.0163743 C30.4437975,27.1611927 32.2189873,26.7318422 34.218481,26.7318422 C36.1394937,26.7318422 37.8946835,27.102622 39.4825316,27.8416679 C41.0708861,28.5819706 42.276962,29.8856073 43.1005063,31.7548404 C44.0017722,30.431345 45.2270886,29.2629486 46.7767089,28.2506569 C48.3253165,27.2388679 50.158481,26.7318422 52.2764557,26.7318422 C53.8843038,26.7318422 55.3736709,26.9269101 56.7473418,27.3162917 C58.1189873,27.7056734 59.295443,28.3285835 60.2759494,29.185022 C61.255443,30.0422147 62.02,31.1615927 62.5701266,32.5426532 C63.1187342,33.9262275 63.3936709,35.5898349 63.3936709,37.5372459 L63.3936709,57.7443688 L55.0410127,57.7441174 L55.0410127,40.6319376 C55.0410127,39.6201486 55.0020253,38.6661761 54.9232911,37.7700202 C54.8440506,36.8751211 54.6293671,36.0968606 54.2764557,35.4339817 C53.9232911,34.772611 53.403038,34.2464807 52.7177215,33.8568477 C52.0313924,33.4689743 51.0997468,33.2731523 49.9235443,33.2731523 C48.7473418,33.2731523 47.7962025,33.4983853 47.0706329,33.944578 C46.344557,34.393033 45.7764557,34.9774826 45.3650633,35.6969211 C44.9534177,36.4181193 44.6787342,37.2353431 44.5417722,38.150855 C44.4037975,39.0653615 44.3356962,39.9904257 44.3356962,40.9247908 L44.3356962,57.7443688 L35.9835443,57.7443688 L35.9835443,40.8079009 C35.9835443,39.9124991 35.963038,39.0263982 35.9253165,38.150855 C35.8853165,37.2743064 35.7192405,36.4666349 35.424557,35.7263321 C35.1303797,34.9872862 34.64,34.393033 33.9539241,33.944578 C33.2675949,33.4983853 32.2579747,33.2731523 30.9248101,33.2731523 C30.5321519,33.2731523 30.0126582,33.3608826 29.3663291,33.5365945 C28.7192405,33.7118037 28.0913924,34.0433688 27.4840506,34.5292789 C26.875443,35.0164459 26.3564557,35.7172826 25.9250633,36.6315376 C25.4934177,37.5470495 25.2779747,38.7436 25.2779747,40.2229486 L25.2779747,57.7441174 L16.9260759,57.7443688 L16.9260759,27.5493174 L24.8073418,27.5493174 Z" id="m"></path>
<path d="M68.7455696,31.9886202 C69.6075949,30.7033339 70.7060759,29.672189 72.0397468,28.8926716 C73.3724051,28.1141596 74.8716456,27.5596239 76.5387342,27.2283101 C78.2050633,26.8977505 79.8817722,26.7315908 81.5678481,26.7315908 C83.0974684,26.7315908 84.6458228,26.8391798 86.2144304,27.0525982 C87.7827848,27.2675248 89.2144304,27.6865688 90.5086076,28.3087248 C91.8025316,28.9313835 92.8610127,29.7983798 93.6848101,30.9074514 C94.5083544,32.0170257 94.92,33.4870734 94.92,35.3173431 L94.92,51.026844 C94.92,52.3913138 94.998481,53.6941963 95.1556962,54.9400165 C95.3113924,56.1865908 95.5863291,57.120956 95.9787342,57.7436147 L87.5091139,57.7436147 C87.3518987,57.276055 87.2240506,56.7996972 87.1265823,56.3125303 C87.0278481,55.8266202 86.9592405,55.3301523 86.9207595,54.8236294 C85.5873418,56.1865908 84.0182278,57.1405633 82.2156962,57.6857982 C80.4113924,58.2295248 78.5683544,58.503022 76.6860759,58.503022 C75.2346835,58.503022 73.8817722,58.3275615 72.6270886,57.9776459 C71.3718987,57.6269761 70.2744304,57.082244 69.3334177,56.3411872 C68.3921519,55.602644 67.656962,54.6680275 67.1275949,53.5390972 C66.5982278,52.410167 66.3331646,51.065556 66.3331646,49.5087835 C66.3331646,47.7961578 66.6367089,46.384178 67.2455696,45.2756092 C67.8529114,44.1652807 68.6367089,43.2799339 69.5987342,42.6173064 C70.5589873,41.9556844 71.6567089,41.4592165 72.8924051,41.1284055 C74.1273418,40.7978459 75.3721519,40.5356606 76.6270886,40.3398385 C77.8820253,40.1457761 79.116962,39.9896716 80.3329114,39.873033 C81.5483544,39.7558917 82.6270886,39.5804312 83.5681013,39.3469028 C84.5093671,39.1133743 85.2536709,38.7732624 85.8032911,38.3250587 C86.3513924,37.8773578 86.6063291,37.2252881 86.5678481,36.3680954 C86.5678481,35.4731963 86.4210127,34.7620532 86.1268354,34.2366771 C85.8329114,33.7113009 85.4405063,33.3018092 84.9506329,33.0099615 C84.4602532,32.7181138 83.8916456,32.5232972 83.2450633,32.4255119 C82.5977215,32.3294862 81.9010127,32.2797138 81.156962,32.2797138 C79.5098734,32.2797138 78.2159494,32.6303835 77.2746835,33.3312202 C76.3339241,34.0320569 75.7837975,35.2007046 75.6275949,36.8354037 L67.275443,36.8354037 C67.3924051,34.8892495 67.8817722,33.2726495 68.7455696,31.9886202 Z M85.2440506,43.6984752 C84.7149367,43.873433 84.1460759,44.0189798 83.5387342,44.1361211 C82.9306329,44.253011 82.2936709,44.350545 81.6270886,44.4279688 C80.96,44.5066495 80.2934177,44.6034294 79.6273418,44.7203193 C78.9994937,44.8362037 78.3820253,44.9933138 77.7749367,45.1871248 C77.1663291,45.3829468 76.636962,45.6451321 76.1865823,45.9759431 C75.7349367,46.3070055 75.3724051,46.7263009 75.0979747,47.2313156 C74.8232911,47.7375872 74.6863291,48.380356 74.6863291,49.1588679 C74.6863291,49.8979138 74.8232911,50.5218294 75.0979747,51.026844 C75.3724051,51.5338697 75.7455696,51.9328037 76.2159494,52.2246514 C76.6863291,52.5164991 77.2349367,52.7213706 77.8632911,52.8375064 C78.4898734,52.9546477 79.136962,53.012967 79.8037975,53.012967 C81.4506329,53.012967 82.724557,52.740978 83.6273418,52.1952404 C84.5288608,51.6507596 85.1949367,50.9981872 85.6270886,50.2382771 C86.0579747,49.4793725 86.323038,48.7119211 86.4212658,47.9321523 C86.518481,47.1536404 86.5681013,46.5304789 86.5681013,46.063422 L86.5681013,42.9677248 C86.2146835,43.2799339 85.7736709,43.5230147 85.2440506,43.6984752 Z" id="a"></path>
<path d="M116.917975,27.5493174 L116.917975,33.0976917 L110.801266,33.0976917 L110.801266,48.0492936 C110.801266,49.4502128 111.036203,50.3850807 111.507089,50.8518862 C111.976962,51.3191945 112.918734,51.5527229 114.33038,51.5527229 C114.801013,51.5527229 115.251392,51.5336183 115.683038,51.4944037 C116.114177,51.4561945 116.526076,51.3968697 116.917975,51.3194459 L116.917975,57.7438661 C116.212152,57.860756 115.427595,57.9381798 114.565316,57.9778972 C113.702785,58.0153523 112.859747,58.0357138 112.036203,58.0357138 C110.742278,58.0357138 109.516456,57.9477321 108.36,57.7722716 C107.202785,57.5975651 106.183544,57.2577046 105.301519,56.7509303 C104.418987,56.2454128 103.722785,55.5242147 103.213418,54.5898495 C102.703038,53.6562385 102.448608,52.4292716 102.448608,50.9099541 L102.448608,33.0976917 L97.3903797,33.0976917 L97.3903797,27.5493174 L102.448608,27.5493174 L102.448608,18.4967596 L110.801013,18.4967596 L110.801013,27.5493174 L116.917975,27.5493174 Z" id="t"></path>
<path d="M128.857975,27.5493174 L128.857975,33.1565138 L128.975696,33.1565138 C129.367089,32.2213945 129.896203,31.3559064 130.563544,30.557033 C131.23038,29.7596679 131.99443,29.0776844 132.857215,28.5130936 C133.719241,27.9495083 134.641266,27.5113596 135.622532,27.1988991 C136.601772,26.8879468 137.622025,26.7315908 138.681013,26.7315908 C139.229873,26.7315908 139.836962,26.8296275 140.504304,27.0239413 L140.504304,34.7336477 C140.111646,34.6552183 139.641013,34.586844 139.092658,34.5290275 C138.543291,34.4704569 138.014177,34.4410459 137.504304,34.4410459 C135.974937,34.4410459 134.681013,34.6949358 133.622785,35.2004532 C132.564051,35.7067248 131.711392,36.397255 131.064051,37.2735523 C130.417215,38.1501009 129.955443,39.1714422 129.681266,40.3398385 C129.407089,41.5074807 129.269873,42.7736624 129.269873,44.1361211 L129.269873,57.7438661 L120.917722,57.7438661 L120.917722,27.5493174 L128.857975,27.5493174 Z" id="r"></path>
<path d="M144.033165,22.8767376 L144.033165,16.0435798 L152.386076,16.0435798 L152.386076,22.8767376 L144.033165,22.8767376 Z M152.386076,27.5493174 L152.386076,57.7438661 L144.033165,57.7438661 L144.033165,27.5493174 L152.386076,27.5493174 Z" id="i"></path>
<polygon id="x" points="156.738228 27.5493174 166.266582 27.5493174 171.619494 35.4337303 176.913418 27.5493174 186.147848 27.5493174 176.148861 41.6831927 187.383544 57.7441174 177.85443 57.7441174 171.501772 48.2245028 165.148861 57.7441174 155.797468 57.7441174 166.737468 41.8589046"></polygon>
<polygon id="right-bracket" points="197.580759 82.7268844 197.580759 1.93811009 191.725063 1.93811009 191.725063 0 199.828354 0 199.828354 84.6652459 191.725063 84.6652459 191.725063 82.7268844"></polygon>
</g>
</g>
</g>
</svg>
</div>
<h1>It works! Dendrite {{ .Version }} is running</h1>
<p>Your Dendrite server is listening on this port and is ready for messages.</p>
<p>To use this server you'll need <a href="https://matrix.org/docs/projects/try-matrix-now.html#clients" target="_blank" rel="noopener noreferrer">a Matrix client</a>.
</p>
<p>Welcome to the Matrix universe :)</p>
<hr>
<p>
<small>
<a href="https://matrix.org" target="_blank" rel="noopener noreferrer">
matrix.org
</a>
</small>
</p>
</body>
</html>

View file

@ -0,0 +1,180 @@
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"os"
"time"
"github.com/getsentry/sentry-go"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/internal/sqlutil"
"github.com/matrix-org/dendrite/setup/jetstream"
"github.com/matrix-org/dendrite/setup/process"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"github.com/matrix-org/dendrite/appservice"
"github.com/matrix-org/dendrite/federationapi"
"github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/setup"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/setup/mscs"
"github.com/matrix-org/dendrite/userapi"
)
var _, skip = os.LookupEnv("CI")
func main() {
cfg := setup.ParseFlags(true)
if skip {
return
}
configErrors := &config.ConfigErrors{}
cfg.Verify(configErrors)
if len(*configErrors) > 0 {
for _, err := range *configErrors {
logrus.Errorf("Configuration error: %s", err)
}
logrus.Fatalf("Failed to start due to configuration errors")
}
processCtx := process.NewProcessContext()
internal.SetupStdLogging()
internal.SetupHookLogging(cfg.Logging)
internal.SetupPprof()
basepkg.PlatformSanityChecks()
logrus.Infof("Dendrite version %s", internal.VersionString())
if !cfg.ClientAPI.RegistrationDisabled && cfg.ClientAPI.OpenRegistrationWithoutVerificationEnabled {
logrus.Warn("Open registration is enabled")
}
// create DNS cache
var dnsCache *fclient.DNSCache
if cfg.Global.DNSCache.Enabled {
dnsCache = fclient.NewDNSCache(
cfg.Global.DNSCache.CacheSize,
cfg.Global.DNSCache.CacheLifetime,
)
logrus.Infof(
"DNS cache enabled (size %d, lifetime %s)",
cfg.Global.DNSCache.CacheSize,
cfg.Global.DNSCache.CacheLifetime,
)
}
// setup tracing
closer, err := cfg.SetupTracing()
if err != nil {
logrus.WithError(err).Panicf("failed to start opentracing")
}
defer closer.Close() // nolint: errcheck
// setup sentry
if cfg.Global.Sentry.Enabled {
logrus.Info("Setting up Sentry for debugging...")
err = sentry.Init(sentry.ClientOptions{
Dsn: cfg.Global.Sentry.DSN,
Environment: cfg.Global.Sentry.Environment,
Debug: true,
ServerName: string(cfg.Global.ServerName),
Release: "dendrite@" + internal.VersionString(),
AttachStacktrace: true,
})
if err != nil {
logrus.WithError(err).Panic("failed to start Sentry")
}
go func() {
processCtx.ComponentStarted()
<-processCtx.WaitForShutdown()
if !sentry.Flush(time.Second * 5) {
logrus.Warnf("failed to flush all Sentry events!")
}
processCtx.ComponentFinished()
}()
}
federationClient := basepkg.CreateFederationClient(cfg, dnsCache)
httpClient := basepkg.CreateClient(cfg, dnsCache)
// prepare required dependencies
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
routers := httputil.NewRouters()
caches := caching.NewRistrettoCache(cfg.Global.Cache.EstimatedMaxSize, cfg.Global.Cache.MaxAge, caching.EnableMetrics)
natsInstance := jetstream.NATSInstance{}
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.EnableMetrics)
fsAPI := federationapi.NewInternalAPI(
processCtx, cfg, cm, &natsInstance, federationClient, rsAPI, caches, nil, false,
)
keyRing := fsAPI.KeyRing()
// The underlying roomserver implementation needs to be able to call the fedsender.
// This is different to rsAPI which can be the http client which doesn't need this
// dependency. Other components also need updating after their dependencies are up.
rsAPI.SetFederationAPI(fsAPI, keyRing)
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, federationClient, caching.EnableMetrics, fsAPI.IsBlacklistedOrBackingOff)
asAPI := appservice.NewInternalAPI(processCtx, cfg, &natsInstance, userAPI, rsAPI)
rsAPI.SetAppserviceAPI(asAPI)
rsAPI.SetUserAPI(userAPI)
monolith := setup.Monolith{
Config: cfg,
Client: httpClient,
FedClient: federationClient,
KeyRing: keyRing,
AppserviceAPI: asAPI,
// always use the concrete impl here even in -http mode because adding public routes
// must be done on the concrete impl not an HTTP client else fedapi will call itself
FederationAPI: fsAPI,
RoomserverAPI: rsAPI,
UserAPI: userAPI,
}
monolith.AddAllPublicRoutes(processCtx, cfg, routers, cm, &natsInstance, caches, caching.EnableMetrics)
if len(cfg.MSCs.MSCs) > 0 {
if err := mscs.Enable(cfg, cm, routers, &monolith, caches); err != nil {
logrus.WithError(err).Fatalf("Failed to enable MSCs")
}
}
upCounter := prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "dendrite",
Name: "up",
ConstLabels: map[string]string{
"version": internal.VersionString(),
},
})
upCounter.Add(1)
prometheus.MustRegister(upCounter)
// Expose the matrix APIs directly rather than putting them under a /api path.
go func() {
SetupAndServeHTTPS(processCtx, cfg, routers) //, httpsAddr, nil, nil)
}()
// We want to block forever to let the HTTP and HTTPS handler serve the APIs
basepkg.WaitForShutdown(processCtx)
}

View file

@ -0,0 +1,50 @@
package main
import (
"os"
"os/signal"
"strings"
"syscall"
"testing"
)
// This is an instrumented main, used when running integration tests (sytest) with code coverage.
// Compile: go test -c -race -cover -covermode=atomic -o monolith.debug -coverpkg "github.com/matrix-org/..." ./cmd/dendrite
// Run the monolith: ./monolith.debug -test.coverprofile=/somewhere/to/dump/integrationcover.out DEVEL --config dendrite.yaml
// Generate HTML with coverage: go tool cover -html=/somewhere/where/there/is/integrationcover.out -o cover.html
// Source: https://dzone.com/articles/measuring-integration-test-coverage-rate-in-pouchc
func TestMain(t *testing.T) {
var args []string
for _, arg := range os.Args {
switch {
case strings.HasPrefix(arg, "DEVEL"):
case strings.HasPrefix(arg, "-test"):
default:
args = append(args, arg)
}
}
// only run the tests if there are args to be passed
if len(args) <= 1 {
return
}
t.Log(args)
waitCh := make(chan int, 1)
os.Args = args
go func() {
main()
close(waitCh)
}()
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGHUP)
select {
case <-signalCh:
return
case <-waitCh:
return
}
}

View file

@ -0,0 +1,215 @@
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"bytes"
"context"
"crypto/tls"
"embed"
"net"
"net/http"
"net/url"
"sync/atomic"
"text/template"
"github.com/cretz/bine/tor"
"github.com/eyedeekay/onramp"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/gorilla/mux"
"github.com/kardianos/minwinsvc"
"github.com/matrix-org/dendrite/internal"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/setup/process"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
basepkg "github.com/matrix-org/dendrite/setup/base"
"github.com/matrix-org/dendrite/setup/config"
)
func start() (*tor.Tor, error) {
if skip {
return nil, nil
}
return tor.Start(context.Background(), nil)
}
func dialer() (*tor.Dialer, error) {
if skip {
return nil, nil
}
return t.Dialer(context.TODO(), nil)
}
var (
t, terr = start()
tdialer, tderr = dialer()
)
// Dial either a unix socket address, or connect to a remote address over Tor. Always uses Tor.
func DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
if terr != nil {
return nil, terr
}
if (tderr != nil) || (tdialer == nil) {
return nil, tderr
}
if network == "unix" {
return net.Dial(network, addr)
}
// convert the addr to a full URL
url, err := url.Parse(addr)
if err != nil {
return nil, err
}
return tdialer.DialContext(ctx, network, url.Host)
}
//go:embed static/*.gotmpl
var staticContent embed.FS
// SetupAndServeHTTPS sets up the HTTPS server to serve client & federation APIs
// and adds a prometheus handler under /_dendrite/metrics.
func SetupAndServeHTTPS(
processContext *process.ProcessContext,
cfg *config.Dendrite,
routers httputil.Routers,
) {
// create a transport that uses SAM to dial TCP Connections
httpClient := &http.Client{
Transport: &http.Transport{
DialContext: DialContext,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
http.DefaultClient = httpClient
onion, err := onramp.NewOnion("dendrite-onion")
if err != nil {
logrus.WithError(err).Fatal("failed to create onion")
}
defer onion.Close() // nolint: errcheck
listener, err := onion.ListenTLS()
if err != nil {
logrus.WithError(err).Fatal("failed to serve HTTPS")
}
defer listener.Close() // nolint: errcheck
externalHTTPSAddr := config.ServerAddress{}
https, err := config.HTTPAddress("https://" + listener.Addr().String())
if err != nil {
logrus.WithError(err).Fatalf("Failed to parse http address")
}
externalHTTPSAddr = https
externalRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
externalServ := &http.Server{
Addr: externalHTTPSAddr.Address,
WriteTimeout: basepkg.HTTPServerTimeout,
Handler: externalRouter,
BaseContext: func(_ net.Listener) context.Context {
return processContext.Context()
},
}
// Redirect for Landing Page
externalRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, httputil.PublicStaticPath, http.StatusFound)
})
if cfg.Global.Metrics.Enabled {
externalRouter.Handle("/metrics", httputil.WrapHandlerInBasicAuth(promhttp.Handler(), cfg.Global.Metrics.BasicAuth))
}
basepkg.ConfigureAdminEndpoints(processContext, routers)
// Parse and execute the landing page template
tmpl := template.Must(template.ParseFS(staticContent, "static/*.gotmpl"))
landingPage := &bytes.Buffer{}
if err := tmpl.ExecuteTemplate(landingPage, "index.gotmpl", map[string]string{
"Version": internal.VersionString(),
}); err != nil {
logrus.WithError(err).Fatal("failed to execute landing page template")
}
routers.Static.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(landingPage.Bytes())
})
var clientHandler http.Handler
clientHandler = routers.Client
if cfg.Global.Sentry.Enabled {
sentryHandler := sentryhttp.New(sentryhttp.Options{
Repanic: true,
})
clientHandler = sentryHandler.Handle(routers.Client)
}
var federationHandler http.Handler
federationHandler = routers.Federation
if cfg.Global.Sentry.Enabled {
sentryHandler := sentryhttp.New(sentryhttp.Options{
Repanic: true,
})
federationHandler = sentryHandler.Handle(routers.Federation)
}
externalRouter.PathPrefix(httputil.DendriteAdminPathPrefix).Handler(routers.DendriteAdmin)
externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(clientHandler)
if !cfg.Global.DisableFederation {
externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(routers.Keys)
externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(federationHandler)
}
externalRouter.PathPrefix(httputil.SynapseAdminPathPrefix).Handler(routers.SynapseAdmin)
externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(routers.Media)
externalRouter.PathPrefix(httputil.PublicWellKnownPrefix).Handler(routers.WellKnown)
externalRouter.PathPrefix(httputil.PublicStaticPath).Handler(routers.Static)
externalRouter.NotFoundHandler = httputil.NotFoundCORSHandler
externalRouter.MethodNotAllowedHandler = httputil.NotAllowedHandler
if externalHTTPSAddr.Enabled() {
go func() {
var externalShutdown atomic.Bool // RegisterOnShutdown can be called more than once
logrus.Infof("Starting external listener on https://%s", externalServ.Addr)
processContext.ComponentStarted()
externalServ.RegisterOnShutdown(func() {
if externalShutdown.CompareAndSwap(false, true) {
processContext.ComponentFinished()
logrus.Infof("Stopped external HTTPS listener")
}
})
addr := listener.Addr()
externalServ.Addr = addr.String()
if err := externalServ.Serve(listener); err != nil {
if err != http.ErrServerClosed {
logrus.WithError(err).Fatal("failed to serve HTTPS")
}
}
logrus.Infof("Stopped external listener on %s", externalServ.Addr)
}()
}
minwinsvc.SetOnExit(processContext.ShutdownDendrite)
<-processContext.WaitForShutdown()
logrus.Infof("Stopping HTTPS listeners")
_ = externalServ.Shutdown(context.Background())
logrus.Infof("Stopped HTTPS listeners")
}

View file

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dendrite is running</title>
<style>
body {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
max-width: 40em;
margin: auto;
text-align: center;
}
h1, p {
margin: 1.5em;
}
hr {
border: none;
background-color: #ccc;
color: #ccc;
height: 1px;
width: 7em;
margin-top: 4em;
}
.logo {
display: block;
width: 12em;
margin: 4em auto;
}
</style>
</head>
<body>
<div class="logo">
<svg role="img" aria-label="[Matrix logo]" viewBox="0 0 200 85" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="parent" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="child" transform="translate(-122.000000, -6.000000)" fill="#000000" fill-rule="nonzero">
<g id="matrix-logo" transform="translate(122.000000, 6.000000)">
<polygon id="left-bracket" points="2.24708861 1.93811009 2.24708861 82.7268844 8.10278481 82.7268844 8.10278481 84.6652459 0 84.6652459 0 0 8.10278481 0 8.10278481 1.93811009"></polygon>
<path d="M24.8073418,27.5493174 L24.8073418,31.6376991 L24.924557,31.6376991 C26.0227848,30.0814294 27.3455696,28.8730642 28.8951899,28.0163743 C30.4437975,27.1611927 32.2189873,26.7318422 34.218481,26.7318422 C36.1394937,26.7318422 37.8946835,27.102622 39.4825316,27.8416679 C41.0708861,28.5819706 42.276962,29.8856073 43.1005063,31.7548404 C44.0017722,30.431345 45.2270886,29.2629486 46.7767089,28.2506569 C48.3253165,27.2388679 50.158481,26.7318422 52.2764557,26.7318422 C53.8843038,26.7318422 55.3736709,26.9269101 56.7473418,27.3162917 C58.1189873,27.7056734 59.295443,28.3285835 60.2759494,29.185022 C61.255443,30.0422147 62.02,31.1615927 62.5701266,32.5426532 C63.1187342,33.9262275 63.3936709,35.5898349 63.3936709,37.5372459 L63.3936709,57.7443688 L55.0410127,57.7441174 L55.0410127,40.6319376 C55.0410127,39.6201486 55.0020253,38.6661761 54.9232911,37.7700202 C54.8440506,36.8751211 54.6293671,36.0968606 54.2764557,35.4339817 C53.9232911,34.772611 53.403038,34.2464807 52.7177215,33.8568477 C52.0313924,33.4689743 51.0997468,33.2731523 49.9235443,33.2731523 C48.7473418,33.2731523 47.7962025,33.4983853 47.0706329,33.944578 C46.344557,34.393033 45.7764557,34.9774826 45.3650633,35.6969211 C44.9534177,36.4181193 44.6787342,37.2353431 44.5417722,38.150855 C44.4037975,39.0653615 44.3356962,39.9904257 44.3356962,40.9247908 L44.3356962,57.7443688 L35.9835443,57.7443688 L35.9835443,40.8079009 C35.9835443,39.9124991 35.963038,39.0263982 35.9253165,38.150855 C35.8853165,37.2743064 35.7192405,36.4666349 35.424557,35.7263321 C35.1303797,34.9872862 34.64,34.393033 33.9539241,33.944578 C33.2675949,33.4983853 32.2579747,33.2731523 30.9248101,33.2731523 C30.5321519,33.2731523 30.0126582,33.3608826 29.3663291,33.5365945 C28.7192405,33.7118037 28.0913924,34.0433688 27.4840506,34.5292789 C26.875443,35.0164459 26.3564557,35.7172826 25.9250633,36.6315376 C25.4934177,37.5470495 25.2779747,38.7436 25.2779747,40.2229486 L25.2779747,57.7441174 L16.9260759,57.7443688 L16.9260759,27.5493174 L24.8073418,27.5493174 Z" id="m"></path>
<path d="M68.7455696,31.9886202 C69.6075949,30.7033339 70.7060759,29.672189 72.0397468,28.8926716 C73.3724051,28.1141596 74.8716456,27.5596239 76.5387342,27.2283101 C78.2050633,26.8977505 79.8817722,26.7315908 81.5678481,26.7315908 C83.0974684,26.7315908 84.6458228,26.8391798 86.2144304,27.0525982 C87.7827848,27.2675248 89.2144304,27.6865688 90.5086076,28.3087248 C91.8025316,28.9313835 92.8610127,29.7983798 93.6848101,30.9074514 C94.5083544,32.0170257 94.92,33.4870734 94.92,35.3173431 L94.92,51.026844 C94.92,52.3913138 94.998481,53.6941963 95.1556962,54.9400165 C95.3113924,56.1865908 95.5863291,57.120956 95.9787342,57.7436147 L87.5091139,57.7436147 C87.3518987,57.276055 87.2240506,56.7996972 87.1265823,56.3125303 C87.0278481,55.8266202 86.9592405,55.3301523 86.9207595,54.8236294 C85.5873418,56.1865908 84.0182278,57.1405633 82.2156962,57.6857982 C80.4113924,58.2295248 78.5683544,58.503022 76.6860759,58.503022 C75.2346835,58.503022 73.8817722,58.3275615 72.6270886,57.9776459 C71.3718987,57.6269761 70.2744304,57.082244 69.3334177,56.3411872 C68.3921519,55.602644 67.656962,54.6680275 67.1275949,53.5390972 C66.5982278,52.410167 66.3331646,51.065556 66.3331646,49.5087835 C66.3331646,47.7961578 66.6367089,46.384178 67.2455696,45.2756092 C67.8529114,44.1652807 68.6367089,43.2799339 69.5987342,42.6173064 C70.5589873,41.9556844 71.6567089,41.4592165 72.8924051,41.1284055 C74.1273418,40.7978459 75.3721519,40.5356606 76.6270886,40.3398385 C77.8820253,40.1457761 79.116962,39.9896716 80.3329114,39.873033 C81.5483544,39.7558917 82.6270886,39.5804312 83.5681013,39.3469028 C84.5093671,39.1133743 85.2536709,38.7732624 85.8032911,38.3250587 C86.3513924,37.8773578 86.6063291,37.2252881 86.5678481,36.3680954 C86.5678481,35.4731963 86.4210127,34.7620532 86.1268354,34.2366771 C85.8329114,33.7113009 85.4405063,33.3018092 84.9506329,33.0099615 C84.4602532,32.7181138 83.8916456,32.5232972 83.2450633,32.4255119 C82.5977215,32.3294862 81.9010127,32.2797138 81.156962,32.2797138 C79.5098734,32.2797138 78.2159494,32.6303835 77.2746835,33.3312202 C76.3339241,34.0320569 75.7837975,35.2007046 75.6275949,36.8354037 L67.275443,36.8354037 C67.3924051,34.8892495 67.8817722,33.2726495 68.7455696,31.9886202 Z M85.2440506,43.6984752 C84.7149367,43.873433 84.1460759,44.0189798 83.5387342,44.1361211 C82.9306329,44.253011 82.2936709,44.350545 81.6270886,44.4279688 C80.96,44.5066495 80.2934177,44.6034294 79.6273418,44.7203193 C78.9994937,44.8362037 78.3820253,44.9933138 77.7749367,45.1871248 C77.1663291,45.3829468 76.636962,45.6451321 76.1865823,45.9759431 C75.7349367,46.3070055 75.3724051,46.7263009 75.0979747,47.2313156 C74.8232911,47.7375872 74.6863291,48.380356 74.6863291,49.1588679 C74.6863291,49.8979138 74.8232911,50.5218294 75.0979747,51.026844 C75.3724051,51.5338697 75.7455696,51.9328037 76.2159494,52.2246514 C76.6863291,52.5164991 77.2349367,52.7213706 77.8632911,52.8375064 C78.4898734,52.9546477 79.136962,53.012967 79.8037975,53.012967 C81.4506329,53.012967 82.724557,52.740978 83.6273418,52.1952404 C84.5288608,51.6507596 85.1949367,50.9981872 85.6270886,50.2382771 C86.0579747,49.4793725 86.323038,48.7119211 86.4212658,47.9321523 C86.518481,47.1536404 86.5681013,46.5304789 86.5681013,46.063422 L86.5681013,42.9677248 C86.2146835,43.2799339 85.7736709,43.5230147 85.2440506,43.6984752 Z" id="a"></path>
<path d="M116.917975,27.5493174 L116.917975,33.0976917 L110.801266,33.0976917 L110.801266,48.0492936 C110.801266,49.4502128 111.036203,50.3850807 111.507089,50.8518862 C111.976962,51.3191945 112.918734,51.5527229 114.33038,51.5527229 C114.801013,51.5527229 115.251392,51.5336183 115.683038,51.4944037 C116.114177,51.4561945 116.526076,51.3968697 116.917975,51.3194459 L116.917975,57.7438661 C116.212152,57.860756 115.427595,57.9381798 114.565316,57.9778972 C113.702785,58.0153523 112.859747,58.0357138 112.036203,58.0357138 C110.742278,58.0357138 109.516456,57.9477321 108.36,57.7722716 C107.202785,57.5975651 106.183544,57.2577046 105.301519,56.7509303 C104.418987,56.2454128 103.722785,55.5242147 103.213418,54.5898495 C102.703038,53.6562385 102.448608,52.4292716 102.448608,50.9099541 L102.448608,33.0976917 L97.3903797,33.0976917 L97.3903797,27.5493174 L102.448608,27.5493174 L102.448608,18.4967596 L110.801013,18.4967596 L110.801013,27.5493174 L116.917975,27.5493174 Z" id="t"></path>
<path d="M128.857975,27.5493174 L128.857975,33.1565138 L128.975696,33.1565138 C129.367089,32.2213945 129.896203,31.3559064 130.563544,30.557033 C131.23038,29.7596679 131.99443,29.0776844 132.857215,28.5130936 C133.719241,27.9495083 134.641266,27.5113596 135.622532,27.1988991 C136.601772,26.8879468 137.622025,26.7315908 138.681013,26.7315908 C139.229873,26.7315908 139.836962,26.8296275 140.504304,27.0239413 L140.504304,34.7336477 C140.111646,34.6552183 139.641013,34.586844 139.092658,34.5290275 C138.543291,34.4704569 138.014177,34.4410459 137.504304,34.4410459 C135.974937,34.4410459 134.681013,34.6949358 133.622785,35.2004532 C132.564051,35.7067248 131.711392,36.397255 131.064051,37.2735523 C130.417215,38.1501009 129.955443,39.1714422 129.681266,40.3398385 C129.407089,41.5074807 129.269873,42.7736624 129.269873,44.1361211 L129.269873,57.7438661 L120.917722,57.7438661 L120.917722,27.5493174 L128.857975,27.5493174 Z" id="r"></path>
<path d="M144.033165,22.8767376 L144.033165,16.0435798 L152.386076,16.0435798 L152.386076,22.8767376 L144.033165,22.8767376 Z M152.386076,27.5493174 L152.386076,57.7438661 L144.033165,57.7438661 L144.033165,27.5493174 L152.386076,27.5493174 Z" id="i"></path>
<polygon id="x" points="156.738228 27.5493174 166.266582 27.5493174 171.619494 35.4337303 176.913418 27.5493174 186.147848 27.5493174 176.148861 41.6831927 187.383544 57.7441174 177.85443 57.7441174 171.501772 48.2245028 165.148861 57.7441174 155.797468 57.7441174 166.737468 41.8589046"></polygon>
<polygon id="right-bracket" points="197.580759 82.7268844 197.580759 1.93811009 191.725063 1.93811009 191.725063 0 199.828354 0 199.828354 84.6652459 191.725063 84.6652459 191.725063 82.7268844"></polygon>
</g>
</g>
</g>
</svg>
</div>
<h1>It works! Dendrite {{ .Version }} is running</h1>
<p>Your Dendrite server is listening on this port and is ready for messages.</p>
<p>To use this server you'll need <a href="https://matrix.org/docs/projects/try-matrix-now.html#clients" target="_blank" rel="noopener noreferrer">a Matrix client</a>.
</p>
<p>Welcome to the Matrix universe :)</p>
<hr>
<p>
<small>
<a href="https://matrix.org" target="_blank" rel="noopener noreferrer">
matrix.org
</a>
</small>
</p>
</body>
</html>

View file

@ -72,6 +72,10 @@ global:
# The base URL to delegate client-server communications to e.g. https://localhost
well_known_client_name: ""
# The server name to delegate sliding sync communications to, with optional port.
# Requires `well_known_client_name` to also be configured.
well_known_sliding_sync_proxy: ""
# Lists of domains that the server will trust as identity servers to verify third
# party identifiers such as phone numbers and email addresses.
trusted_third_party_id_servers:
@ -150,6 +154,13 @@ app_service_api:
# to be sent to an insecure endpoint.
disable_tls_validation: false
# Send the access_token query parameter with appservice requests in addition
# to the Authorization header. This can cause hs_tokens to be saved to logs,
# so it should not be enabled unless absolutely necessary.
legacy_auth: false
# Use the legacy unprefixed paths for appservice requests.
legacy_paths: false
# Appservice configuration files to load into this homeserver.
config_files:
# - /path/to/appservice_registration.yaml
@ -321,6 +332,10 @@ user_api:
auto_join_rooms:
# - "#main:matrix.org"
# The number of workers to start for the DeviceListUpdater. Defaults to 8.
# This only needs updating if the "InputDeviceListUpdate" stream keeps growing indefinitely.
# worker_count: 8
# Configuration for Opentracing.
# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on
# how this works and how to set it up.

View file

@ -4,6 +4,8 @@ nav_order: 1
permalink: /faq
---
{% include deprecation.html %}
# FAQ
## Why does Dendrite exist?
@ -24,7 +26,7 @@ No, although a good portion of the Matrix specification has been implemented. Mo
Dendrite development is currently supported by a small team of developers and due to those limited resources, the majority of the effort is focused on getting Dendrite to be
specification complete. If there are major features you're requesting (e.g. new administration endpoints), we'd like to strongly encourage you to join the community in supporting
the development efforts through [contributing](../development/contributing).
the development efforts through [contributing](./development/CONTRIBUTING.md).
## Is there a migration path from Synapse to Dendrite?
@ -105,7 +107,7 @@ This can be done by performing a room upgrade. Use the command `/upgraderoom <ve
## How do I reset somebody's password on my server?
Use the admin endpoint [resetpassword](./administration/adminapi#post-_dendriteadminresetpassworduserid)
Use the admin endpoint [resetpassword](./administration/4_adminapi.md#post-_dendriteadminresetpassworduserid)
## Should I use PostgreSQL or SQLite for my databases?
@ -117,6 +119,7 @@ The list of files that need to be stored is:
- matrix-key.pem
- dendrite.yaml
- the postgres or sqlite DB
- the jetstream directory
- the media store
- the search index (although this can be regenerated)

View file

@ -14,7 +14,7 @@ GEM
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.23.9)
commonmarker (0.23.10)
concurrent-ruby (1.2.0)
dnsruby (1.61.9)
simpleidn (~> 0.1)
@ -231,9 +231,9 @@ GEM
jekyll-seo-tag (~> 2.1)
minitest (5.17.0)
multipart-post (2.1.1)
nokogiri (1.14.3-arm64-darwin)
nokogiri (1.16.2-arm64-darwin)
racc (~> 1.4)
nokogiri (1.14.3-x86_64-linux)
nokogiri (1.16.2-x86_64-linux)
racc (~> 1.4)
octokit (4.22.0)
faraday (>= 0.9)
@ -241,11 +241,12 @@ GEM
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.7)
racc (1.6.2)
racc (1.7.3)
rb-fsevent (0.11.1)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rexml (3.3.2)
strscan
rouge (3.26.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
@ -260,6 +261,7 @@ GEM
faraday (> 0.8, < 2.0)
simpleidn (0.2.1)
unf (~> 0.1.4)
strscan (3.1.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)

View file

@ -1,3 +1,6 @@
{% include deprecation.html %}
# Installation
Please note that new installation instructions can be found

View file

@ -0,0 +1,6 @@
{: .warning-title }
> This documentation is out of date!
>
> This documentation site is for the versions of Dendrite maintained by the <em>Matrix.org Foundation</em> (<a href="https://github.com/matrix-org/dendrite">github.com/matrix-org/dendrite</a>), available under the Apache 2.0 licence.
>
> If you are interested in the documentation for a later version of Dendrite, please refer to <a href="https://element-hq.github.io/dendrite/">https://element-hq.github.io/dendrite/</a>.

View file

@ -1,3 +0,0 @@
footer.site-footer {
opacity: 10%;
}

View file

@ -5,6 +5,8 @@ nav_order: 4
permalink: /administration
---
{% include deprecation.html %}
# Administration
This section contains documentation on managing your existing Dendrite deployment.

View file

@ -5,6 +5,8 @@ permalink: /administration/createusers
nav_order: 1
---
{% include deprecation.html %}
# Creating user accounts
User accounts can be created on a Dendrite instance in a number of ways.

View file

@ -5,6 +5,8 @@ permalink: /administration/registration
nav_order: 2
---
{% include deprecation.html %}
# Enabling registration
Enabling registration allows users to register their own user accounts on your

View file

@ -5,6 +5,8 @@ permalink: /administration/presence
nav_order: 3
---
{% include deprecation.html %}
# Enabling presence
Dendrite supports presence, which allows you to send your online/offline status

View file

@ -5,6 +5,8 @@ nav_order: 4
permalink: /administration/adminapi
---
{% include deprecation.html %}
# Supported admin APIs
Dendrite supports, at present, a very small number of endpoints that allow
@ -75,7 +77,7 @@ This endpoint instructs Dendrite to immediately query `/devices/{userID}` on a f
## POST `/_dendrite/admin/purgeRoom/{roomID}`
This endpoint instructs Dendrite to remove the given room from its database. Before doing so, it will evacuate all local users from the room. It does **NOT** remove media files. Depending on the size of the room, this may take a while. Will return an empty JSON once other components were instructed to delete the room.
This endpoint instructs Dendrite to remove the given room from its database. It does **NOT** remove media files. Depending on the size of the room, this may take a while. Will return an empty JSON once other components were instructed to delete the room.
## POST `/_synapse/admin/v1/send_server_notice`

View file

@ -6,6 +6,8 @@ nav_order: 5
permalink: /administration/optimisation
---
{% include deprecation.html %}
# Optimise your installation
Now that you have Dendrite running, the following tweaks will improve the reliability
@ -95,7 +97,7 @@ Consider enabling the DNS cache by modifying the `global` section of your config
## Time synchronisation
Matrix relies heavily on TLS which requires the system time to be correct. If the clock
drifts then you may find that federation no works reliably (or at all) and clients may
drifts then you may find that federation will not work reliably (or at all) and clients may
struggle to connect to your Dendrite server.
Ensure that the time is synchronised on your system by enabling NTP sync.

View file

@ -5,6 +5,8 @@ nav_order: 6
permalink: /administration/troubleshooting
---
{% include deprecation.html %}
# Troubleshooting
If your Dendrite installation is acting strangely, there are a few things you should

View file

@ -4,6 +4,10 @@ has_children: true
permalink: /development
---
{% include deprecation.html %}
{% include deprecation.html %}
# Development
This section contains documentation that may be useful when helping to develop

View file

@ -5,6 +5,8 @@ nav_order: 1
permalink: /development/contributing
---
{% include deprecation.html %}
# Contributing to Dendrite
Everyone is welcome to contribute to Dendrite! We aim to make it as easy as
@ -109,7 +111,7 @@ To configure the connection to a remote Postgres, you can use the following envi
```bash
POSTGRES_USER=postgres
POSTGERS_PASSWORD=yourPostgresPassword
POSTGRES_PASSWORD=yourPostgresPassword
POSTGRES_HOST=localhost
POSTGRES_DB=postgres # the superuser database to use
```

View file

@ -5,6 +5,8 @@ nav_order: 4
permalink: /development/profiling
---
{% include deprecation.html %}
# Profiling Dendrite
If you are running into problems with Dendrite using excessive resources (e.g. CPU or RAM) then you can use the profiler to work out what is happening.

View file

@ -5,6 +5,8 @@ nav_order: 3
permalink: /development/coverage
---
{% include deprecation.html %}
## Running unit tests with coverage enabled
Running unit tests with coverage enabled can be done with the following commands, this will generate a `integrationcover.log`

View file

@ -5,6 +5,8 @@ nav_order: 2
permalink: /development/sytest
---
{% include deprecation.html %}
# SyTest
Dendrite uses [SyTest](https://github.com/matrix-org/sytest) for its

View file

@ -3,6 +3,8 @@ layout: home
nav_exclude: true
---
{% include deprecation.html %}
# Dendrite
Dendrite is a second-generation Matrix homeserver written in Go! Following the microservice

View file

@ -5,6 +5,8 @@ nav_order: 2
permalink: /installation
---
{% include deprecation.html %}
# Installation
This section contains documentation on installing a new Dendrite deployment.

View file

@ -5,6 +5,8 @@ nav_order: 1
permalink: /installation/planning
---
{% include deprecation.html %}
# Planning your installation
## Database
@ -59,7 +61,7 @@ In order to install Dendrite, you will need to satisfy the following dependencie
### Go
At this time, Dendrite supports being built with Go 1.18 or later. We do not support building
At this time, Dendrite supports being built with Go 1.21 or later. We do not support building
Dendrite with older versions of Go than this. If you are installing Go using a package manager,
you should check (by running `go version`) that you are using a suitable version before you start.

View file

@ -5,6 +5,8 @@ nav_order: 2
permalink: /installation/domainname
---
{% include deprecation.html %}
# Setting up the domain
Every Matrix server deployment requires a server name which uniquely identifies it. For

Some files were not shown because too many files have changed in this diff Show more