mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-11 16:13:10 -06:00
Merge branch 'main' of github.com:matrix-org/dendrite into s7evink/joinstatereset
This commit is contained in:
commit
2ca04d665f
8
.github/workflows/dendrite.yml
vendored
8
.github/workflows/dendrite.yml
vendored
|
|
@ -67,6 +67,8 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install libolm
|
||||
run: sudo apt-get install libolm-dev libolm3
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
|
|
@ -101,6 +103,8 @@ jobs:
|
|||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install libolm
|
||||
run: sudo apt-get install libolm-dev libolm3
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
|
|
@ -232,6 +236,8 @@ jobs:
|
|||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install libolm
|
||||
run: sudo apt-get install libolm-dev libolm3
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
|
|
@ -393,7 +399,7 @@ 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
|
||||
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
|
||||
- name: Run actions/checkout@v3 for dendrite
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
|
|
|
|||
2
.github/workflows/helm.yml
vendored
2
.github/workflows/helm.yml
vendored
|
|
@ -6,6 +6,7 @@ on:
|
|||
- main
|
||||
paths:
|
||||
- 'helm/**' # only execute if we have helm chart changes
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
|
|
@ -37,3 +38,4 @@ jobs:
|
|||
with:
|
||||
config: helm/cr.yaml
|
||||
charts_dir: helm/
|
||||
mark_as_latest: false
|
||||
|
|
|
|||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -74,3 +74,7 @@ complement/
|
|||
docs/_site
|
||||
|
||||
media_store/
|
||||
build
|
||||
|
||||
# golang workspaces
|
||||
go.work*
|
||||
|
|
@ -179,7 +179,6 @@ linters-settings:
|
|||
|
||||
linters:
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- goconst
|
||||
- gocyclo
|
||||
|
|
@ -191,10 +190,8 @@ linters:
|
|||
- misspell # Check code comments, whereas misspell in CI checks *.md files
|
||||
- nakedret
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
enable-all: false
|
||||
disable:
|
||||
- bodyclose
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ It intends to provide an **efficient**, **reliable** and **scalable** alternativ
|
|||
|
||||
Dendrite is **beta** software, which means:
|
||||
|
||||
- Dendrite is ready for early adopters. We recommend running in Monolith mode with a PostgreSQL database.
|
||||
- Dendrite is ready for early adopters. We recommend running Dendrite with a PostgreSQL database.
|
||||
- Dendrite has periodic releases. We intend to release new versions as we fix bugs and land significant features.
|
||||
- Dendrite supports database schema upgrades between releases. This means you should never lose your messages when upgrading Dendrite.
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ This does not mean:
|
|||
|
||||
- Dendrite is bug-free. It has not yet been battle-tested in the real world and so will be error prone initially.
|
||||
- Dendrite is feature-complete. There may be client or federation APIs that are not implemented.
|
||||
- Dendrite is ready for massive homeserver deployments. There is no sharding of microservices (although it is possible to run them on separate machines) and there is no high-availability/clustering support.
|
||||
- Dendrite is ready for massive homeserver deployments. There is no high-availability/clustering support.
|
||||
|
||||
Currently, we expect Dendrite to function well for small (10s/100s of users) homeserver deployments as well as P2P Matrix nodes in-browser or on mobile devices.
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ The following instructions are enough to get Dendrite started as a non-federatin
|
|||
```bash
|
||||
$ git clone https://github.com/matrix-org/dendrite
|
||||
$ cd dendrite
|
||||
$ ./build.sh
|
||||
$ go build -o bin/ ./cmd/...
|
||||
|
||||
# Generate a Matrix signing key for federation (required)
|
||||
$ ./bin/generate-keys --private-key matrix_key.pem
|
||||
|
|
@ -85,7 +85,7 @@ Then point your favourite Matrix client at `http://localhost:8008` or `https://l
|
|||
|
||||
## Progress
|
||||
|
||||
We use a script called Are We Synapse Yet which checks Sytest compliance rates. Sytest is a black-box homeserver
|
||||
We use a script called "Are We Synapse Yet" which checks Sytest compliance rates. Sytest is a black-box homeserver
|
||||
test rig with around 900 tests. The script works out how many of these tests are passing on Dendrite and it
|
||||
updates with CI. As of January 2023, we have 100% server-server parity with Synapse, and the client-server parity is at 93% , though check
|
||||
CI for the latest numbers. In practice, this means you can communicate locally and via federation with Synapse
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
)
|
||||
|
|
@ -150,6 +148,10 @@ type ASLocationResponse struct {
|
|||
Fields json.RawMessage `json:"fields"`
|
||||
}
|
||||
|
||||
// ErrProfileNotExists is returned when trying to lookup a user's profile that
|
||||
// doesn't exist locally.
|
||||
var ErrProfileNotExists = errors.New("no known profile for given user ID")
|
||||
|
||||
// RetrieveUserProfile is a wrapper that queries both the local database and
|
||||
// application services for a given user's profile
|
||||
// TODO: Remove this, it's called from federationapi and clientapi but is a pure function
|
||||
|
|
@ -157,25 +159,11 @@ func RetrieveUserProfile(
|
|||
ctx context.Context,
|
||||
userID string,
|
||||
asAPI AppServiceInternalAPI,
|
||||
profileAPI userapi.ClientUserAPI,
|
||||
profileAPI userapi.ProfileAPI,
|
||||
) (*authtypes.Profile, error) {
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Try to query the user from the local database
|
||||
res := &userapi.QueryProfileResponse{}
|
||||
err = profileAPI.QueryProfile(ctx, &userapi.QueryProfileRequest{UserID: userID}, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
profile := &authtypes.Profile{
|
||||
Localpart: localpart,
|
||||
DisplayName: res.DisplayName,
|
||||
AvatarURL: res.AvatarURL,
|
||||
}
|
||||
if res.UserExists {
|
||||
profile, err := profileAPI.QueryProfile(ctx, userID)
|
||||
if err == nil {
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
|
|
@ -188,19 +176,15 @@ func RetrieveUserProfile(
|
|||
|
||||
// If no user exists, return
|
||||
if !userResp.UserIDExists {
|
||||
return nil, errors.New("no known profile for given user ID")
|
||||
return nil, ErrProfileNotExists
|
||||
}
|
||||
|
||||
// Try to query the user from the local database again
|
||||
err = profileAPI.QueryProfile(ctx, &userapi.QueryProfileRequest{UserID: userID}, res)
|
||||
profile, err = profileAPI.QueryProfile(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// profile should not be nil at this point
|
||||
return &authtypes.Profile{
|
||||
Localpart: localpart,
|
||||
DisplayName: res.DisplayName,
|
||||
AvatarURL: res.AvatarURL,
|
||||
}, nil
|
||||
return profile, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,17 +16,13 @@ package appservice
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/setup/process"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/appservice/consumers"
|
||||
"github.com/matrix-org/dendrite/appservice/query"
|
||||
|
|
@ -44,20 +40,10 @@ func NewInternalAPI(
|
|||
userAPI userapi.AppserviceUserAPI,
|
||||
rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||
) appserviceAPI.AppServiceInternalAPI {
|
||||
client := &http.Client{
|
||||
Timeout: time.Second * 30,
|
||||
Transport: &http.Transport{
|
||||
DisableKeepAlives: true,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: cfg.AppServiceAPI.DisableTLSValidation,
|
||||
},
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
},
|
||||
}
|
||||
|
||||
// Create appserivce query API with an HTTP client that will be used for all
|
||||
// outbound and inbound requests (inbound only for the internal API)
|
||||
appserviceQueryAPI := &query.AppServiceQueryAPI{
|
||||
HTTPClient: client,
|
||||
Cfg: &cfg.AppServiceAPI,
|
||||
ProtocolCache: map[string]appserviceAPI.ASProtocolResponse{},
|
||||
CacheMu: sync.Mutex{},
|
||||
|
|
@ -84,7 +70,7 @@ func NewInternalAPI(
|
|||
js, _ := natsInstance.Prepare(processContext, &cfg.Global.JetStream)
|
||||
consumer := consumers.NewOutputRoomEventConsumer(
|
||||
processContext, &cfg.AppServiceAPI,
|
||||
client, js, rsAPI,
|
||||
js, rsAPI,
|
||||
)
|
||||
if err := consumer.Start(); err != nil {
|
||||
logrus.WithError(err).Panicf("failed to start appservice roomserver consumer")
|
||||
|
|
@ -99,7 +85,7 @@ func NewInternalAPI(
|
|||
func generateAppServiceAccount(
|
||||
userAPI userapi.AppserviceUserAPI,
|
||||
as config.ApplicationService,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
serverName spec.ServerName,
|
||||
) error {
|
||||
var accRes userapi.PerformAccountCreationResponse
|
||||
err := userAPI.PerformAccountCreation(context.Background(), &userapi.PerformAccountCreationRequest{
|
||||
|
|
|
|||
|
|
@ -3,16 +3,22 @@ package appservice_test
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/matrix-org/dendrite/appservice"
|
||||
"github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/appservice/consumers"
|
||||
"github.com/matrix-org/dendrite/internal/caching"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver"
|
||||
|
|
@ -21,7 +27,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/test"
|
||||
"github.com/matrix-org/dendrite/userapi"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/dendrite/test/testrig"
|
||||
)
|
||||
|
|
@ -114,20 +120,20 @@ func TestAppserviceInternalAPI(t *testing.T) {
|
|||
defer close()
|
||||
|
||||
// Create a dummy application service
|
||||
cfg.AppServiceAPI.Derived.ApplicationServices = []config.ApplicationService{
|
||||
{
|
||||
ID: "someID",
|
||||
URL: srv.URL,
|
||||
ASToken: "",
|
||||
HSToken: "",
|
||||
SenderLocalpart: "senderLocalPart",
|
||||
NamespaceMap: map[string][]config.ApplicationServiceNamespace{
|
||||
"users": {{RegexpObject: regexp.MustCompile("as-.*")}},
|
||||
"aliases": {{RegexpObject: regexp.MustCompile("asroom-.*")}},
|
||||
},
|
||||
Protocols: []string{existingProtocol},
|
||||
as := &config.ApplicationService{
|
||||
ID: "someID",
|
||||
URL: srv.URL,
|
||||
ASToken: "",
|
||||
HSToken: "",
|
||||
SenderLocalpart: "senderLocalPart",
|
||||
NamespaceMap: map[string][]config.ApplicationServiceNamespace{
|
||||
"users": {{RegexpObject: regexp.MustCompile("as-.*")}},
|
||||
"aliases": {{RegexpObject: regexp.MustCompile("asroom-.*")}},
|
||||
},
|
||||
Protocols: []string{existingProtocol},
|
||||
}
|
||||
as.CreateHTTPClient(cfg.AppServiceAPI.DisableTLSValidation)
|
||||
cfg.AppServiceAPI.Derived.ApplicationServices = []config.ApplicationService{*as}
|
||||
|
||||
t.Cleanup(func() {
|
||||
ctx.ShutdownDendrite()
|
||||
|
|
@ -145,6 +151,103 @@ func TestAppserviceInternalAPI(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAppserviceInternalAPI_UnixSocket_Simple(t *testing.T) {
|
||||
|
||||
// Set expected results
|
||||
existingProtocol := "irc"
|
||||
wantLocationResponse := []api.ASLocationResponse{{Protocol: existingProtocol, Fields: []byte("{}")}}
|
||||
wantUserResponse := []api.ASUserResponse{{Protocol: existingProtocol, Fields: []byte("{}")}}
|
||||
wantProtocolResponse := api.ASProtocolResponse{Instances: []api.ProtocolInstance{{Fields: []byte("{}")}}}
|
||||
|
||||
// create a dummy AS url, handling some cases
|
||||
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case strings.Contains(r.URL.Path, "location"):
|
||||
// Check if we've got an existing protocol, if so, return a proper response.
|
||||
if r.URL.Path[len(r.URL.Path)-len(existingProtocol):] == existingProtocol {
|
||||
if err := json.NewEncoder(w).Encode(wantLocationResponse); err != nil {
|
||||
t.Fatalf("failed to encode response: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode([]api.ASLocationResponse{}); err != nil {
|
||||
t.Fatalf("failed to encode response: %s", err)
|
||||
}
|
||||
return
|
||||
case strings.Contains(r.URL.Path, "user"):
|
||||
if r.URL.Path[len(r.URL.Path)-len(existingProtocol):] == existingProtocol {
|
||||
if err := json.NewEncoder(w).Encode(wantUserResponse); err != nil {
|
||||
t.Fatalf("failed to encode response: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode([]api.UserResponse{}); err != nil {
|
||||
t.Fatalf("failed to encode response: %s", err)
|
||||
}
|
||||
return
|
||||
case strings.Contains(r.URL.Path, "protocol"):
|
||||
if r.URL.Path[len(r.URL.Path)-len(existingProtocol):] == existingProtocol {
|
||||
if err := json.NewEncoder(w).Encode(wantProtocolResponse); err != nil {
|
||||
t.Fatalf("failed to encode response: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(nil); err != nil {
|
||||
t.Fatalf("failed to encode response: %s", err)
|
||||
}
|
||||
return
|
||||
default:
|
||||
t.Logf("hit location: %s", r.URL.Path)
|
||||
}
|
||||
}))
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
socket := path.Join(tmpDir, "socket")
|
||||
l, err := net.Listen("unix", socket)
|
||||
assert.NoError(t, err)
|
||||
_ = srv.Listener.Close()
|
||||
srv.Listener = l
|
||||
srv.Start()
|
||||
defer srv.Close()
|
||||
|
||||
cfg, ctx, tearDown := testrig.CreateConfig(t, test.DBTypeSQLite)
|
||||
defer tearDown()
|
||||
|
||||
// Create a dummy application service
|
||||
as := &config.ApplicationService{
|
||||
ID: "someID",
|
||||
URL: fmt.Sprintf("unix://%s", socket),
|
||||
ASToken: "",
|
||||
HSToken: "",
|
||||
SenderLocalpart: "senderLocalPart",
|
||||
NamespaceMap: map[string][]config.ApplicationServiceNamespace{
|
||||
"users": {{RegexpObject: regexp.MustCompile("as-.*")}},
|
||||
"aliases": {{RegexpObject: regexp.MustCompile("asroom-.*")}},
|
||||
},
|
||||
Protocols: []string{existingProtocol},
|
||||
}
|
||||
as.CreateHTTPClient(cfg.AppServiceAPI.DisableTLSValidation)
|
||||
cfg.AppServiceAPI.Derived.ApplicationServices = []config.ApplicationService{*as}
|
||||
|
||||
t.Cleanup(func() {
|
||||
ctx.ShutdownDendrite()
|
||||
ctx.WaitForShutdown()
|
||||
})
|
||||
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
|
||||
// Create required internal APIs
|
||||
natsInstance := jetstream.NATSInstance{}
|
||||
cm := sqlutil.NewConnectionManager(ctx, cfg.Global.DatabaseOptions)
|
||||
rsAPI := roomserver.NewInternalAPI(ctx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
|
||||
usrAPI := userapi.NewInternalAPI(ctx, cfg, cm, &natsInstance, rsAPI, nil)
|
||||
asAPI := appservice.NewInternalAPI(ctx, cfg, &natsInstance, usrAPI, rsAPI)
|
||||
|
||||
t.Run("UserIDExists", func(t *testing.T) {
|
||||
testUserIDExists(t, asAPI, "@as-testing:test", true)
|
||||
testUserIDExists(t, asAPI, "@as1-testing:test", false)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func testUserIDExists(t *testing.T, asAPI api.AppServiceInternalAPI, userID string, wantExists bool) {
|
||||
ctx := context.Background()
|
||||
userResp := &api.UserIDExistsResponse{}
|
||||
|
|
@ -223,7 +326,7 @@ func TestRoomserverConsumerOneInvite(t *testing.T) {
|
|||
room := test.NewRoom(t, alice)
|
||||
|
||||
// Invite Bob
|
||||
room.CreateAndInsert(t, alice, gomatrixserverlib.MRoomMember, map[string]interface{}{
|
||||
room.CreateAndInsert(t, alice, spec.MRoomMember, map[string]interface{}{
|
||||
"membership": "invite",
|
||||
}, test.WithStateKey(bob.ID))
|
||||
|
||||
|
|
@ -236,13 +339,13 @@ func TestRoomserverConsumerOneInvite(t *testing.T) {
|
|||
evChan := make(chan struct{})
|
||||
// create a dummy AS url, handling the events
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var txn gomatrixserverlib.ApplicationServiceTransaction
|
||||
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 != gomatrixserverlib.MRoomMember {
|
||||
if ev.Type != spec.MRoomMember {
|
||||
continue
|
||||
}
|
||||
// Usually we would check the event content for the membership, but since
|
||||
|
|
@ -254,20 +357,21 @@ func TestRoomserverConsumerOneInvite(t *testing.T) {
|
|||
}))
|
||||
defer srv.Close()
|
||||
|
||||
// Create a dummy application service
|
||||
cfg.AppServiceAPI.Derived.ApplicationServices = []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 := &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}
|
||||
|
||||
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
|
||||
// Create required internal APIs
|
||||
|
|
|
|||
|
|
@ -26,21 +26,29 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/nats-io/nats.go"
|
||||
|
||||
"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/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/setup/process"
|
||||
"github.com/matrix-org/dendrite/syncapi/synctypes"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ApplicationServiceTransaction is the transaction that is sent off to an
|
||||
// application service.
|
||||
type ApplicationServiceTransaction struct {
|
||||
Events []synctypes.ClientEvent `json:"events"`
|
||||
}
|
||||
|
||||
// OutputRoomEventConsumer consumes events that originated in the room server.
|
||||
type OutputRoomEventConsumer struct {
|
||||
ctx context.Context
|
||||
cfg *config.AppServiceAPI
|
||||
client *http.Client
|
||||
jetstream nats.JetStreamContext
|
||||
topic string
|
||||
rsAPI api.AppserviceRoomserverAPI
|
||||
|
|
@ -56,14 +64,12 @@ type appserviceState struct {
|
|||
func NewOutputRoomEventConsumer(
|
||||
process *process.ProcessContext,
|
||||
cfg *config.AppServiceAPI,
|
||||
client *http.Client,
|
||||
js nats.JetStreamContext,
|
||||
rsAPI api.AppserviceRoomserverAPI,
|
||||
) *OutputRoomEventConsumer {
|
||||
return &OutputRoomEventConsumer{
|
||||
ctx: process.Context(),
|
||||
cfg: cfg,
|
||||
client: client,
|
||||
jetstream: js,
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputRoomEvent),
|
||||
rsAPI: rsAPI,
|
||||
|
|
@ -99,7 +105,7 @@ func (s *OutputRoomEventConsumer) onMessage(
|
|||
ctx context.Context, state *appserviceState, msgs []*nats.Msg,
|
||||
) bool {
|
||||
log.WithField("appservice", state.ID).Tracef("Appservice worker received %d message(s) from roomserver", len(msgs))
|
||||
events := make([]*gomatrixserverlib.HeaderedEvent, 0, len(msgs))
|
||||
events := make([]*types.HeaderedEvent, 0, len(msgs))
|
||||
for _, msg := range msgs {
|
||||
// Only handle events we care about
|
||||
receivedType := api.OutputType(msg.Header.Get(jetstream.RoomEventType))
|
||||
|
|
@ -169,13 +175,13 @@ func (s *OutputRoomEventConsumer) onMessage(
|
|||
// endpoint. It will block for the backoff period if necessary.
|
||||
func (s *OutputRoomEventConsumer) sendEvents(
|
||||
ctx context.Context, state *appserviceState,
|
||||
events []*gomatrixserverlib.HeaderedEvent,
|
||||
events []*types.HeaderedEvent,
|
||||
txnID string,
|
||||
) error {
|
||||
// Create the transaction body.
|
||||
transaction, err := json.Marshal(
|
||||
gomatrixserverlib.ApplicationServiceTransaction{
|
||||
Events: gomatrixserverlib.HeaderedToClientEvents(events, gomatrixserverlib.FormatAll),
|
||||
ApplicationServiceTransaction{
|
||||
Events: synctypes.ToClientEvents(gomatrixserverlib.ToPDUs(events), synctypes.FormatAll),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -184,18 +190,18 @@ func (s *OutputRoomEventConsumer) sendEvents(
|
|||
|
||||
// If txnID is not defined, generate one from the events.
|
||||
if txnID == "" {
|
||||
txnID = fmt.Sprintf("%d_%d", events[0].Event.OriginServerTS(), len(transaction))
|
||||
txnID = fmt.Sprintf("%d_%d", events[0].PDU.OriginServerTS(), len(transaction))
|
||||
}
|
||||
|
||||
// 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.URL, txnID, url.QueryEscape(state.HSToken))
|
||||
address := fmt.Sprintf("%s/transactions/%s?access_token=%s", state.RequestUrl(), txnID, 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")
|
||||
resp, err := s.client.Do(req)
|
||||
resp, err := state.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return state.backoffAndPause(err)
|
||||
}
|
||||
|
|
@ -206,7 +212,7 @@ func (s *OutputRoomEventConsumer) sendEvents(
|
|||
case http.StatusOK:
|
||||
state.backoff = 0
|
||||
default:
|
||||
return state.backoffAndPause(fmt.Errorf("received HTTP status code %d from appservice", resp.StatusCode))
|
||||
return state.backoffAndPause(fmt.Errorf("received HTTP status code %d from appservice url %s", resp.StatusCode, address))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -226,7 +232,7 @@ func (s *appserviceState) backoffAndPause(err error) error {
|
|||
// event falls within one of a given application service's namespaces.
|
||||
//
|
||||
// TODO: This should be cached, see https://github.com/matrix-org/dendrite/issues/1682
|
||||
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event *gomatrixserverlib.HeaderedEvent, appservice *config.ApplicationService) bool {
|
||||
func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Context, event *types.HeaderedEvent, appservice *config.ApplicationService) bool {
|
||||
switch {
|
||||
case appservice.URL == "":
|
||||
return false
|
||||
|
|
@ -236,7 +242,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
|||
return true
|
||||
}
|
||||
|
||||
if event.Type() == gomatrixserverlib.MRoomMember && event.StateKey() != nil {
|
||||
if event.Type() == spec.MRoomMember && event.StateKey() != nil {
|
||||
if appservice.IsInterestedInUserID(*event.StateKey()) {
|
||||
return true
|
||||
}
|
||||
|
|
@ -264,7 +270,7 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
|
|||
|
||||
// appserviceJoinedAtEvent returns a boolean depending on whether a given
|
||||
// appservice has membership at the time a given event was created.
|
||||
func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, event *gomatrixserverlib.HeaderedEvent, appservice *config.ApplicationService) bool {
|
||||
func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, event *types.HeaderedEvent, appservice *config.ApplicationService) bool {
|
||||
// TODO: This is only checking the current room state, not the state at
|
||||
// the event in question. Pretty sure this is what Synapse does too, but
|
||||
// until we have a lighter way of checking the state before the event that
|
||||
|
|
@ -282,7 +288,7 @@ func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, e
|
|||
switch {
|
||||
case ev.StateKey == nil:
|
||||
continue
|
||||
case ev.Type != gomatrixserverlib.MRoomMember:
|
||||
case ev.Type != spec.MRoomMember:
|
||||
continue
|
||||
}
|
||||
var membership gomatrixserverlib.MemberContent
|
||||
|
|
@ -290,7 +296,7 @@ func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, e
|
|||
switch {
|
||||
case err != nil:
|
||||
continue
|
||||
case membership.Membership == gomatrixserverlib.Join:
|
||||
case membership.Membership == spec.Join:
|
||||
if appservice.IsInterestedInUserID(*ev.StateKey) {
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ const userIDExistsPath = "/users/"
|
|||
|
||||
// AppServiceQueryAPI is an implementation of api.AppServiceQueryAPI
|
||||
type AppServiceQueryAPI struct {
|
||||
HTTPClient *http.Client
|
||||
Cfg *config.AppServiceAPI
|
||||
ProtocolCache map[string]api.ASProtocolResponse
|
||||
CacheMu sync.Mutex
|
||||
|
|
@ -57,7 +56,7 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
|
|||
for _, appservice := range a.Cfg.Derived.ApplicationServices {
|
||||
if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) {
|
||||
// The full path to the rooms API, includes hs token
|
||||
URL, err := url.Parse(appservice.URL + roomAliasExistsPath)
|
||||
URL, err := url.Parse(appservice.RequestUrl() + roomAliasExistsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -73,7 +72,7 @@ func (a *AppServiceQueryAPI) RoomAliasExists(
|
|||
}
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
resp, err := a.HTTPClient.Do(req)
|
||||
resp, err := appservice.HTTPClient.Do(req)
|
||||
if resp != nil {
|
||||
defer func() {
|
||||
err = resp.Body.Close()
|
||||
|
|
@ -124,7 +123,7 @@ 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.URL + userIDExistsPath)
|
||||
URL, err := url.Parse(appservice.RequestUrl() + userIDExistsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -137,7 +136,7 @@ func (a *AppServiceQueryAPI) UserIDExists(
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := a.HTTPClient.Do(req.WithContext(ctx))
|
||||
resp, err := appservice.HTTPClient.Do(req.WithContext(ctx))
|
||||
if resp != nil {
|
||||
defer func() {
|
||||
err = resp.Body.Close()
|
||||
|
|
@ -212,12 +211,12 @@ func (a *AppServiceQueryAPI) Locations(
|
|||
var asLocations []api.ASLocationResponse
|
||||
params.Set("access_token", as.HSToken)
|
||||
|
||||
url := as.URL + api.ASLocationPath
|
||||
url := as.RequestUrl() + api.ASLocationPath
|
||||
if req.Protocol != "" {
|
||||
url += "/" + req.Protocol
|
||||
}
|
||||
|
||||
if err := requestDo[[]api.ASLocationResponse](a.HTTPClient, url+"?"+params.Encode(), &asLocations); err != nil {
|
||||
if err := requestDo[[]api.ASLocationResponse](as.HTTPClient, url+"?"+params.Encode(), &asLocations); err != nil {
|
||||
log.WithError(err).Error("unable to get 'locations' from application service")
|
||||
continue
|
||||
}
|
||||
|
|
@ -247,12 +246,12 @@ func (a *AppServiceQueryAPI) User(
|
|||
var asUsers []api.ASUserResponse
|
||||
params.Set("access_token", as.HSToken)
|
||||
|
||||
url := as.URL + api.ASUserPath
|
||||
url := as.RequestUrl() + api.ASUserPath
|
||||
if req.Protocol != "" {
|
||||
url += "/" + req.Protocol
|
||||
}
|
||||
|
||||
if err := requestDo[[]api.ASUserResponse](a.HTTPClient, url+"?"+params.Encode(), &asUsers); err != nil {
|
||||
if err := requestDo[[]api.ASUserResponse](as.HTTPClient, url+"?"+params.Encode(), &asUsers); err != nil {
|
||||
log.WithError(err).Error("unable to get 'user' from application service")
|
||||
continue
|
||||
}
|
||||
|
|
@ -290,7 +289,7 @@ func (a *AppServiceQueryAPI) Protocols(
|
|||
response := api.ASProtocolResponse{}
|
||||
for _, as := range a.Cfg.Derived.ApplicationServices {
|
||||
var proto api.ASProtocolResponse
|
||||
if err := requestDo[api.ASProtocolResponse](a.HTTPClient, as.URL+api.ASProtocolPath+req.Protocol, &proto); err != nil {
|
||||
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")
|
||||
continue
|
||||
}
|
||||
|
|
@ -320,7 +319,7 @@ 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](a.HTTPClient, as.URL+api.ASProtocolPath+p, &proto); err != nil {
|
||||
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")
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
51
build.cmd
51
build.cmd
|
|
@ -1,51 +0,0 @@
|
|||
@echo off
|
||||
|
||||
:ENTRY_POINT
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
REM script base dir
|
||||
set SCRIPTDIR=%~dp0
|
||||
set PROJDIR=%SCRIPTDIR:~0,-1%
|
||||
|
||||
REM Put installed packages into ./bin
|
||||
set GOBIN=%PROJDIR%\bin
|
||||
|
||||
set FLAGS=
|
||||
|
||||
REM Check if sources are under Git control
|
||||
if not exist ".git" goto :CHECK_BIN
|
||||
|
||||
REM set BUILD=`git rev-parse --short HEAD \\ ""`
|
||||
FOR /F "tokens=*" %%X IN ('git rev-parse --short HEAD') DO (
|
||||
set BUILD=%%X
|
||||
)
|
||||
|
||||
REM set BRANCH=`(git symbolic-ref --short HEAD \ tr -d \/ ) \\ ""`
|
||||
FOR /F "tokens=*" %%X IN ('git symbolic-ref --short HEAD') DO (
|
||||
set BRANCHRAW=%%X
|
||||
set BRANCH=!BRANCHRAW:/=!
|
||||
)
|
||||
if "%BRANCH%" == "main" set BRANCH=
|
||||
|
||||
set FLAGS=-X github.com/matrix-org/dendrite/internal.branch=%BRANCH% -X github.com/matrix-org/dendrite/internal.build=%BUILD%
|
||||
|
||||
:CHECK_BIN
|
||||
if exist "bin" goto :ALL_SET
|
||||
mkdir "bin"
|
||||
|
||||
:ALL_SET
|
||||
set CGO_ENABLED=1
|
||||
for /D %%P in (cmd\*) do (
|
||||
go build -trimpath -ldflags "%FLAGS%" -v -o ".\bin" ".\%%P"
|
||||
)
|
||||
|
||||
set CGO_ENABLED=0
|
||||
set GOOS=js
|
||||
set GOARCH=wasm
|
||||
go build -trimpath -ldflags "%FLAGS%" -o bin\main.wasm .\cmd\dendritejs-pinecone
|
||||
|
||||
goto :DONE
|
||||
|
||||
:DONE
|
||||
echo Done
|
||||
endlocal
|
||||
24
build.sh
24
build.sh
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/sh -eu
|
||||
|
||||
# Put installed packages into ./bin
|
||||
export GOBIN=$PWD/`dirname $0`/bin
|
||||
|
||||
if [ -d ".git" ]
|
||||
then
|
||||
export BUILD=`git rev-parse --short HEAD || ""`
|
||||
export BRANCH=`(git symbolic-ref --short HEAD | tr -d \/ ) || ""`
|
||||
if [ "$BRANCH" = main ]
|
||||
then
|
||||
export BRANCH=""
|
||||
fi
|
||||
|
||||
export FLAGS="-X github.com/matrix-org/dendrite/internal.branch=$BRANCH -X github.com/matrix-org/dendrite/internal.build=$BUILD"
|
||||
else
|
||||
export FLAGS=""
|
||||
fi
|
||||
|
||||
mkdir -p bin
|
||||
|
||||
CGO_ENABLED=1 go build -trimpath -ldflags "$FLAGS" -v -o "bin/" ./cmd/...
|
||||
|
||||
# CGO_ENABLED=0 GOOS=js GOARCH=wasm go build -trimpath -ldflags "$FLAGS" -o bin/main.wasm ./cmd/dendritejs-pinecone
|
||||
|
|
@ -171,7 +171,7 @@ func startup() {
|
|||
cfg.Global.TrustedIDServers = []string{}
|
||||
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||
cfg.Global.PrivateKey = sk
|
||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.ServerName = spec.ServerName(hex.EncodeToString(pk))
|
||||
cfg.ClientAPI.RegistrationDisabled = false
|
||||
cfg.ClientAPI.OpenRegistrationWithoutVerificationEnabled = true
|
||||
|
||||
|
|
|
|||
|
|
@ -6,23 +6,20 @@ They can be found on Docker Hub:
|
|||
|
||||
- [matrixdotorg/dendrite-monolith](https://hub.docker.com/r/matrixdotorg/dendrite-monolith) for monolith deployments
|
||||
|
||||
## Dockerfiles
|
||||
## Dockerfile
|
||||
|
||||
The `Dockerfile` is a multistage file which can build all four Dendrite
|
||||
images depending on the supplied `--target`. From the root of the Dendrite
|
||||
The `Dockerfile` is a multistage file which can build Dendrite. From the root of the Dendrite
|
||||
repository, run:
|
||||
|
||||
```
|
||||
docker build . --target monolith -t matrixdotorg/dendrite-monolith
|
||||
docker build . --target demo-pinecone -t matrixdotorg/dendrite-demo-pinecone
|
||||
docker build . --target demo-yggdrasil -t matrixdotorg/dendrite-demo-yggdrasil
|
||||
docker build . -t matrixdotorg/dendrite-monolith
|
||||
```
|
||||
|
||||
## Compose files
|
||||
## Compose file
|
||||
|
||||
There are two sample `docker-compose` files:
|
||||
There is one sample `docker-compose` files:
|
||||
|
||||
- `docker-compose.monolith.yml` which runs a monolith Dendrite deployment
|
||||
- `docker-compose.yml` which runs a Dendrite deployment with Postgres
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -55,7 +52,7 @@ Create your config based on the [`dendrite-sample.yaml`](https://github.com/matr
|
|||
Then start the deployment:
|
||||
|
||||
```
|
||||
docker-compose -f docker-compose.monolith.yml up
|
||||
docker-compose -f docker-compose.yml up
|
||||
```
|
||||
|
||||
## Building the images
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
version: "3.4"
|
||||
services:
|
||||
postgres:
|
||||
hostname: postgres
|
||||
image: postgres:14
|
||||
restart: always
|
||||
volumes:
|
||||
- ./postgres/create_db.sh:/docker-entrypoint-initdb.d/20-create_db.sh
|
||||
# To persist your PostgreSQL databases outside of the Docker image,
|
||||
# to prevent data loss, modify the following ./path_to path:
|
||||
- ./path_to/postgresql:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: itsasecret
|
||||
POSTGRES_USER: dendrite
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U dendrite"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- internal
|
||||
|
||||
monolith:
|
||||
hostname: monolith
|
||||
image: matrixdotorg/dendrite-monolith:latest
|
||||
command: [
|
||||
"--tls-cert=server.crt",
|
||||
"--tls-key=server.key"
|
||||
]
|
||||
ports:
|
||||
- 8008:8008
|
||||
- 8448:8448
|
||||
volumes:
|
||||
- ./config:/etc/dendrite
|
||||
- ./media:/var/dendrite/media
|
||||
depends_on:
|
||||
- postgres
|
||||
networks:
|
||||
- internal
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
internal:
|
||||
attachable: true
|
||||
52
build/docker/docker-compose.yml
Normal file
52
build/docker/docker-compose.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
version: "3.4"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
hostname: postgres
|
||||
image: postgres:15-alpine
|
||||
restart: always
|
||||
volumes:
|
||||
# This will create a docker volume to persist the database files in.
|
||||
# If you prefer those files to be outside of docker, you'll need to change this.
|
||||
- dendrite_postgres_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: itsasecret
|
||||
POSTGRES_USER: dendrite
|
||||
POSTGRES_DATABASE: dendrite
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U dendrite"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- internal
|
||||
|
||||
monolith:
|
||||
hostname: monolith
|
||||
image: matrixdotorg/dendrite-monolith:latest
|
||||
ports:
|
||||
- 8008:8008
|
||||
- 8448:8448
|
||||
volumes:
|
||||
- ./config:/etc/dendrite
|
||||
# The following volumes use docker volumes, change this
|
||||
# if you prefer to have those files outside of docker.
|
||||
- dendrite_media:/var/dendrite/media
|
||||
- dendrite_jetstream:/var/dendrite/jetstream
|
||||
- dendrite_search_index:/var/dendrite/searchindex
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- internal
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
internal:
|
||||
attachable: true
|
||||
|
||||
volumes:
|
||||
dendrite_postgres_data:
|
||||
dendrite_media:
|
||||
dendrite_jetstream:
|
||||
dendrite_search_index:
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
for db in userapi_accounts mediaapi syncapi roomserver keyserver federationapi appservice mscs; do
|
||||
createdb -U dendrite -O dendrite dendrite_$db
|
||||
done
|
||||
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/process"
|
||||
userapiAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/pinecone/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
|
|
@ -140,9 +141,9 @@ func (m *DendriteMonolith) SetStaticPeer(uri string) {
|
|||
}
|
||||
}
|
||||
|
||||
func getServerKeyFromString(nodeID string) (gomatrixserverlib.ServerName, error) {
|
||||
var nodeKey gomatrixserverlib.ServerName
|
||||
if userID, err := gomatrixserverlib.NewUserID(nodeID, false); err == nil {
|
||||
func getServerKeyFromString(nodeID string) (spec.ServerName, error) {
|
||||
var nodeKey spec.ServerName
|
||||
if userID, err := spec.NewUserID(nodeID, false); err == nil {
|
||||
hexKey, decodeErr := hex.DecodeString(string(userID.Domain()))
|
||||
if decodeErr != nil || len(hexKey) != ed25519.PublicKeySize {
|
||||
return "", fmt.Errorf("UserID domain is not a valid ed25519 public key: %v", userID.Domain())
|
||||
|
|
@ -154,7 +155,7 @@ func getServerKeyFromString(nodeID string) (gomatrixserverlib.ServerName, error)
|
|||
if decodeErr != nil || len(hexKey) != ed25519.PublicKeySize {
|
||||
return "", fmt.Errorf("Relay server uri is not a valid ed25519 public key: %v", nodeID)
|
||||
} else {
|
||||
nodeKey = gomatrixserverlib.ServerName(nodeID)
|
||||
nodeKey = spec.ServerName(nodeID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +163,7 @@ func getServerKeyFromString(nodeID string) (gomatrixserverlib.ServerName, error)
|
|||
}
|
||||
|
||||
func (m *DendriteMonolith) SetRelayServers(nodeID string, uris string) {
|
||||
relays := []gomatrixserverlib.ServerName{}
|
||||
relays := []spec.ServerName{}
|
||||
for _, uri := range strings.Split(uris, ",") {
|
||||
uri = strings.TrimSpace(uri)
|
||||
if len(uri) == 0 {
|
||||
|
|
@ -188,7 +189,7 @@ func (m *DendriteMonolith) SetRelayServers(nodeID string, uris string) {
|
|||
m.p2pMonolith.RelayRetriever.SetRelayServers(relays)
|
||||
} else {
|
||||
relay.UpdateNodeRelayServers(
|
||||
gomatrixserverlib.ServerName(nodeKey),
|
||||
spec.ServerName(nodeKey),
|
||||
relays,
|
||||
m.p2pMonolith.ProcessCtx.Context(),
|
||||
m.p2pMonolith.GetFederationAPI(),
|
||||
|
|
@ -215,7 +216,7 @@ func (m *DendriteMonolith) GetRelayServers(nodeID string) string {
|
|||
relaysString += string(relay)
|
||||
}
|
||||
} else {
|
||||
request := api.P2PQueryRelayServersRequest{Server: gomatrixserverlib.ServerName(nodeKey)}
|
||||
request := api.P2PQueryRelayServersRequest{Server: spec.ServerName(nodeKey)}
|
||||
response := api.P2PQueryRelayServersResponse{}
|
||||
err := m.p2pMonolith.GetFederationAPI().P2PQueryRelayServers(m.p2pMonolith.ProcessCtx.Context(), &request, &response)
|
||||
if err != nil {
|
||||
|
|
@ -291,7 +292,7 @@ func (m *DendriteMonolith) RegisterUser(localpart, password string) (string, err
|
|||
pubkey := m.p2pMonolith.Router.PublicKey()
|
||||
userID := userutil.MakeUserID(
|
||||
localpart,
|
||||
gomatrixserverlib.ServerName(hex.EncodeToString(pubkey[:])),
|
||||
spec.ServerName(hex.EncodeToString(pubkey[:])),
|
||||
)
|
||||
userReq := &userapiAPI.PerformAccountCreationRequest{
|
||||
AccountType: userapiAPI.AccountTypeUser,
|
||||
|
|
@ -342,7 +343,7 @@ func (m *DendriteMonolith) Start() {
|
|||
|
||||
prefix := hex.EncodeToString(pk)
|
||||
cfg := monolith.GenerateDefaultConfig(sk, m.StorageDirectory, m.CacheDirectory, prefix)
|
||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.ServerName = spec.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||
cfg.Global.JetStream.InMemory = false
|
||||
// NOTE : disabled for now since there is a 64 bit alignment panic on 32 bit systems
|
||||
|
|
|
|||
|
|
@ -18,11 +18,14 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
func TestMonolithStarts(t *testing.T) {
|
||||
monolith := DendriteMonolith{}
|
||||
monolith := DendriteMonolith{
|
||||
StorageDirectory: t.TempDir(),
|
||||
CacheDirectory: t.TempDir(),
|
||||
}
|
||||
monolith.Start()
|
||||
monolith.PublicKey()
|
||||
monolith.Stop()
|
||||
|
|
@ -60,7 +63,10 @@ func TestMonolithSetRelayServers(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
monolith := DendriteMonolith{}
|
||||
monolith := DendriteMonolith{
|
||||
StorageDirectory: t.TempDir(),
|
||||
CacheDirectory: t.TempDir(),
|
||||
}
|
||||
monolith.Start()
|
||||
|
||||
inputRelays := tc.relays
|
||||
|
|
@ -110,7 +116,7 @@ func TestParseServerKey(t *testing.T) {
|
|||
name string
|
||||
serverKey string
|
||||
expectedErr bool
|
||||
expectedKey gomatrixserverlib.ServerName
|
||||
expectedKey spec.ServerName
|
||||
}{
|
||||
{
|
||||
name: "valid userid as key",
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/test"
|
||||
"github.com/matrix-org/dendrite/userapi"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
_ "golang.org/x/mobile/bind"
|
||||
|
|
@ -134,7 +135,7 @@ func (m *DendriteMonolith) Start() {
|
|||
Generate: true,
|
||||
SingleDatabase: true,
|
||||
})
|
||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.ServerName = spec.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.PrivateKey = sk
|
||||
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||
cfg.Global.JetStream.StoragePath = config.Path(fmt.Sprintf("%s/", m.StorageDirectory))
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/federationapi"
|
||||
"github.com/matrix-org/dendrite/internal/caching"
|
||||
"github.com/matrix-org/dendrite/internal/httputil"
|
||||
|
|
@ -19,7 +18,8 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/syncapi"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ func TestAdminResetPassword(t *testing.T) {
|
|||
natsInstance := jetstream.NATSInstance{}
|
||||
// add a vhost
|
||||
cfg.Global.VirtualHosts = append(cfg.Global.VirtualHosts, &config.VirtualHost{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{ServerName: "vh1"},
|
||||
SigningIdentity: fclient.SigningIdentity{ServerName: "vh1"},
|
||||
})
|
||||
|
||||
routers := httputil.NewRouters()
|
||||
|
|
@ -54,10 +54,10 @@ func TestAdminResetPassword(t *testing.T) {
|
|||
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
|
||||
|
||||
// Create the users in the userapi and login
|
||||
accessTokens := map[*test.User]string{
|
||||
aliceAdmin: "",
|
||||
bob: "",
|
||||
vhUser: "",
|
||||
accessTokens := map[*test.User]userDevice{
|
||||
aliceAdmin: {},
|
||||
bob: {},
|
||||
vhUser: {},
|
||||
}
|
||||
createAccessTokens(t, accessTokens, userAPI, ctx, routers)
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ func TestAdminResetPassword(t *testing.T) {
|
|||
}
|
||||
|
||||
if tc.withHeader {
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[tc.requestingUser])
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[tc.requestingUser].accessToken)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
|
@ -123,7 +123,7 @@ func TestPurgeRoom(t *testing.T) {
|
|||
room := test.NewRoom(t, aliceAdmin, test.RoomPreset(test.PresetTrustedPrivateChat))
|
||||
|
||||
// Invite Bob
|
||||
room.CreateAndInsert(t, aliceAdmin, gomatrixserverlib.MRoomMember, map[string]interface{}{
|
||||
room.CreateAndInsert(t, aliceAdmin, spec.MRoomMember, map[string]interface{}{
|
||||
"membership": "invite",
|
||||
}, test.WithStateKey(bob.ID))
|
||||
|
||||
|
|
@ -133,7 +133,11 @@ func TestPurgeRoom(t *testing.T) {
|
|||
cfg, processCtx, close := testrig.CreateConfig(t, dbType)
|
||||
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
|
||||
natsInstance := jetstream.NATSInstance{}
|
||||
defer close()
|
||||
defer func() {
|
||||
// give components the time to process purge requests
|
||||
time.Sleep(time.Millisecond * 50)
|
||||
close()
|
||||
}()
|
||||
|
||||
routers := httputil.NewRouters()
|
||||
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
|
||||
|
|
@ -142,8 +146,8 @@ func TestPurgeRoom(t *testing.T) {
|
|||
|
||||
// this starts the JetStream consumers
|
||||
syncapi.AddPublicRoutes(processCtx, routers, cfg, cm, &natsInstance, userAPI, rsAPI, caches, caching.DisableMetrics)
|
||||
federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, rsAPI, caches, nil, true)
|
||||
rsAPI.SetFederationAPI(nil, nil)
|
||||
fsAPI := federationapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, rsAPI, caches, nil, true)
|
||||
rsAPI.SetFederationAPI(fsAPI, nil)
|
||||
|
||||
// Create the room
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, room.Events(), "test", "test", "test", nil, false); err != nil {
|
||||
|
|
@ -154,8 +158,8 @@ func TestPurgeRoom(t *testing.T) {
|
|||
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
|
||||
|
||||
// Create the users in the userapi and login
|
||||
accessTokens := map[*test.User]string{
|
||||
aliceAdmin: "",
|
||||
accessTokens := map[*test.User]userDevice{
|
||||
aliceAdmin: {},
|
||||
}
|
||||
createAccessTokens(t, accessTokens, userAPI, ctx, routers)
|
||||
|
||||
|
|
@ -174,7 +178,7 @@ func TestPurgeRoom(t *testing.T) {
|
|||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := test.NewRequest(t, http.MethodPost, "/_dendrite/admin/purgeRoom/"+tc.roomID)
|
||||
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin])
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin].accessToken)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
routers.DendriteAdmin.ServeHTTP(rec, req)
|
||||
|
|
@ -194,7 +198,7 @@ func TestAdminEvacuateRoom(t *testing.T) {
|
|||
room := test.NewRoom(t, aliceAdmin)
|
||||
|
||||
// Join Bob
|
||||
room.CreateAndInsert(t, bob, gomatrixserverlib.MRoomMember, map[string]interface{}{
|
||||
room.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
|
||||
"membership": "join",
|
||||
}, test.WithStateKey(bob.ID))
|
||||
|
||||
|
|
@ -224,8 +228,8 @@ func TestAdminEvacuateRoom(t *testing.T) {
|
|||
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
|
||||
|
||||
// Create the users in the userapi and login
|
||||
accessTokens := map[*test.User]string{
|
||||
aliceAdmin: "",
|
||||
accessTokens := map[*test.User]userDevice{
|
||||
aliceAdmin: {},
|
||||
}
|
||||
createAccessTokens(t, accessTokens, userAPI, ctx, routers)
|
||||
|
||||
|
|
@ -243,7 +247,7 @@ func TestAdminEvacuateRoom(t *testing.T) {
|
|||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := test.NewRequest(t, http.MethodPost, "/_dendrite/admin/evacuateRoom/"+tc.roomID)
|
||||
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin])
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin].accessToken)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
routers.DendriteAdmin.ServeHTTP(rec, req)
|
||||
|
|
@ -262,6 +266,25 @@ func TestAdminEvacuateRoom(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Wait for the FS API to have consumed every message
|
||||
js, _ := natsInstance.Prepare(processCtx, &cfg.Global.JetStream)
|
||||
timeout := time.After(time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-timeout:
|
||||
t.Fatalf("FS API didn't process all events in time")
|
||||
default:
|
||||
}
|
||||
info, err := js.ConsumerInfo(cfg.Global.JetStream.Prefixed(jetstream.OutputRoomEvent), cfg.Global.JetStream.Durable("FederationAPIRoomServerConsumer")+"Pull")
|
||||
if err != nil {
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
continue
|
||||
}
|
||||
if info.NumPending == 0 && info.NumAckPending == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -272,10 +295,10 @@ func TestAdminEvacuateUser(t *testing.T) {
|
|||
room2 := test.NewRoom(t, aliceAdmin)
|
||||
|
||||
// Join Bob
|
||||
room.CreateAndInsert(t, bob, gomatrixserverlib.MRoomMember, map[string]interface{}{
|
||||
room.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
|
||||
"membership": "join",
|
||||
}, test.WithStateKey(bob.ID))
|
||||
room2.CreateAndInsert(t, bob, gomatrixserverlib.MRoomMember, map[string]interface{}{
|
||||
room2.CreateAndInsert(t, bob, spec.MRoomMember, map[string]interface{}{
|
||||
"membership": "join",
|
||||
}, test.WithStateKey(bob.ID))
|
||||
|
||||
|
|
@ -308,8 +331,8 @@ func TestAdminEvacuateUser(t *testing.T) {
|
|||
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
|
||||
|
||||
// Create the users in the userapi and login
|
||||
accessTokens := map[*test.User]string{
|
||||
aliceAdmin: "",
|
||||
accessTokens := map[*test.User]userDevice{
|
||||
aliceAdmin: {},
|
||||
}
|
||||
createAccessTokens(t, accessTokens, userAPI, ctx, routers)
|
||||
|
||||
|
|
@ -329,7 +352,7 @@ func TestAdminEvacuateUser(t *testing.T) {
|
|||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := test.NewRequest(t, http.MethodPost, "/_dendrite/admin/evacuateUser/"+tc.userID)
|
||||
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin])
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin].accessToken)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
routers.DendriteAdmin.ServeHTTP(rec, req)
|
||||
|
|
@ -390,8 +413,8 @@ func TestAdminMarkAsStale(t *testing.T) {
|
|||
AddPublicRoutes(processCtx, routers, cfg, &natsInstance, nil, rsAPI, nil, nil, nil, userAPI, nil, nil, caching.DisableMetrics)
|
||||
|
||||
// Create the users in the userapi and login
|
||||
accessTokens := map[*test.User]string{
|
||||
aliceAdmin: "",
|
||||
accessTokens := map[*test.User]userDevice{
|
||||
aliceAdmin: {},
|
||||
}
|
||||
createAccessTokens(t, accessTokens, userAPI, ctx, routers)
|
||||
|
||||
|
|
@ -409,7 +432,7 @@ func TestAdminMarkAsStale(t *testing.T) {
|
|||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := test.NewRequest(t, http.MethodPost, "/_dendrite/admin/refreshDevices/"+tc.userID)
|
||||
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin])
|
||||
req.Header.Set("Authorization", "Bearer "+accessTokens[aliceAdmin].accessToken)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
routers.DendriteAdmin.ServeHTTP(rec, req)
|
||||
|
|
@ -421,35 +444,3 @@ func TestAdminMarkAsStale(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createAccessTokens(t *testing.T, accessTokens map[*test.User]string, 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] = gjson.GetBytes(rec.Body.Bytes(), "access_token").String()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
|
||||
package api
|
||||
|
||||
import "github.com/matrix-org/gomatrixserverlib"
|
||||
import "github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
|
||||
// ExtraPublicRoomsProvider provides a way to inject extra published rooms into /publicRooms requests.
|
||||
type ExtraPublicRoomsProvider interface {
|
||||
// Rooms returns the extra rooms. This is called on-demand by clients, so cache appropriately.
|
||||
Rooms() []gomatrixserverlib.PublicRoom
|
||||
Rooms() []fclient.PublicRoom
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ func VerifyUserFromRequest(
|
|||
if err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.MissingToken(err.Error()),
|
||||
JSON: spec.MissingToken(err.Error()),
|
||||
}
|
||||
}
|
||||
var res api.QueryAccessTokenResponse
|
||||
|
|
@ -68,21 +68,23 @@ func VerifyUserFromRequest(
|
|||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("userAPI.QueryAccessToken failed")
|
||||
jsonErr := jsonerror.InternalServerError()
|
||||
return nil, &jsonErr
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if res.Err != "" {
|
||||
if strings.HasPrefix(strings.ToLower(res.Err), "forbidden:") { // TODO: use actual error and no string comparison
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(res.Err),
|
||||
JSON: spec.Forbidden(res.Err),
|
||||
}
|
||||
}
|
||||
}
|
||||
if res.Device == nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.UnknownToken("Unknown token"),
|
||||
JSON: spec.UnknownToken("Unknown token"),
|
||||
}
|
||||
}
|
||||
return res.Device, nil
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ package authtypes
|
|||
|
||||
// ThreePID represents a third-party identifier
|
||||
type ThreePID struct {
|
||||
Address string `json:"address"`
|
||||
Medium string `json:"medium"`
|
||||
Address string `json:"address"`
|
||||
Medium string `json:"medium"`
|
||||
AddedAt int64 `json:"added_at"`
|
||||
ValidatedAt int64 `json:"validated_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
uapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ func LoginFromJSONReader(ctx context.Context, r io.Reader, useraccountAPI uapi.U
|
|||
if err != nil {
|
||||
err := &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Reading request body failed: " + err.Error()),
|
||||
JSON: spec.BadJSON("Reading request body failed: " + err.Error()),
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ func LoginFromJSONReader(ctx context.Context, r io.Reader, useraccountAPI uapi.U
|
|||
if err := json.Unmarshal(reqBytes, &header); err != nil {
|
||||
err := &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Reading request body failed: " + err.Error()),
|
||||
JSON: spec.BadJSON("Reading request body failed: " + err.Error()),
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ func LoginFromJSONReader(ctx context.Context, r io.Reader, useraccountAPI uapi.U
|
|||
default:
|
||||
err := util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("unhandled login type: " + header.Type),
|
||||
JSON: spec.InvalidParam("unhandled login type: " + header.Type),
|
||||
}
|
||||
return nil, nil, &err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
"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"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ func TestLoginFromJSONReader(t *testing.T) {
|
|||
var userAPI fakeUserInternalAPI
|
||||
cfg := &config.ClientAPI{
|
||||
Matrix: &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: serverName,
|
||||
},
|
||||
},
|
||||
|
|
@ -107,13 +107,13 @@ func TestBadLoginFromJSONReader(t *testing.T) {
|
|||
Name string
|
||||
Body string
|
||||
|
||||
WantErrCode string
|
||||
WantErrCode spec.MatrixErrorCode
|
||||
}{
|
||||
{Name: "empty", WantErrCode: "M_BAD_JSON"},
|
||||
{Name: "empty", WantErrCode: spec.ErrorBadJSON},
|
||||
{
|
||||
Name: "badUnmarshal",
|
||||
Body: `badsyntaxJSON`,
|
||||
WantErrCode: "M_BAD_JSON",
|
||||
WantErrCode: spec.ErrorBadJSON,
|
||||
},
|
||||
{
|
||||
Name: "badPassword",
|
||||
|
|
@ -123,7 +123,7 @@ func TestBadLoginFromJSONReader(t *testing.T) {
|
|||
"password": "invalidpassword",
|
||||
"device_id": "adevice"
|
||||
}`,
|
||||
WantErrCode: "M_FORBIDDEN",
|
||||
WantErrCode: spec.ErrorForbidden,
|
||||
},
|
||||
{
|
||||
Name: "badToken",
|
||||
|
|
@ -132,7 +132,7 @@ func TestBadLoginFromJSONReader(t *testing.T) {
|
|||
"token": "invalidtoken",
|
||||
"device_id": "adevice"
|
||||
}`,
|
||||
WantErrCode: "M_FORBIDDEN",
|
||||
WantErrCode: spec.ErrorForbidden,
|
||||
},
|
||||
{
|
||||
Name: "badType",
|
||||
|
|
@ -140,7 +140,7 @@ func TestBadLoginFromJSONReader(t *testing.T) {
|
|||
"type": "m.login.invalid",
|
||||
"device_id": "adevice"
|
||||
}`,
|
||||
WantErrCode: "M_INVALID_ARGUMENT_VALUE",
|
||||
WantErrCode: spec.ErrorInvalidParam,
|
||||
},
|
||||
}
|
||||
for _, tst := range tsts {
|
||||
|
|
@ -148,7 +148,7 @@ func TestBadLoginFromJSONReader(t *testing.T) {
|
|||
var userAPI fakeUserInternalAPI
|
||||
cfg := &config.ClientAPI{
|
||||
Matrix: &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: serverName,
|
||||
},
|
||||
},
|
||||
|
|
@ -157,7 +157,7 @@ func TestBadLoginFromJSONReader(t *testing.T) {
|
|||
if errRes == nil {
|
||||
cleanup(ctx, nil)
|
||||
t.Fatalf("LoginFromJSONReader err: got %+v, want code %q", errRes, tst.WantErrCode)
|
||||
} else if merr, ok := errRes.JSON.(*jsonerror.MatrixError); ok && merr.ErrCode != tst.WantErrCode {
|
||||
} else if merr, ok := errRes.JSON.(spec.MatrixError); ok && merr.ErrCode != tst.WantErrCode {
|
||||
t.Fatalf("LoginFromJSONReader err: got %+v, want code %q", errRes, tst.WantErrCode)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
uapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -48,13 +48,15 @@ func (t *LoginTypeToken) LoginFromJSON(ctx context.Context, reqBytes []byte) (*L
|
|||
var res uapi.QueryLoginTokenResponse
|
||||
if err := t.UserAPI.QueryLoginToken(ctx, &uapi.QueryLoginTokenRequest{Token: r.Token}, &res); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("UserAPI.QueryLoginToken failed")
|
||||
jsonErr := jsonerror.InternalServerError()
|
||||
return nil, nil, &jsonErr
|
||||
return nil, nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if res.Data == nil {
|
||||
return nil, nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("invalid login token"),
|
||||
JSON: spec.Forbidden("invalid login token"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -65,26 +65,26 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
|
|||
if username == "" {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.BadJSON("A username must be supplied."),
|
||||
JSON: spec.BadJSON("A username must be supplied."),
|
||||
}
|
||||
}
|
||||
if len(r.Password) == 0 {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.BadJSON("A password must be supplied."),
|
||||
JSON: spec.BadJSON("A password must be supplied."),
|
||||
}
|
||||
}
|
||||
localpart, domain, err := userutil.ParseUsernameParam(username, t.Config.Matrix)
|
||||
if err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.InvalidUsername(err.Error()),
|
||||
JSON: spec.InvalidUsername(err.Error()),
|
||||
}
|
||||
}
|
||||
if !t.Config.Matrix.IsLocalServerName(domain) {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.InvalidUsername("The server name is not known."),
|
||||
JSON: spec.InvalidUsername("The server name is not known."),
|
||||
}
|
||||
}
|
||||
// Squash username to all lowercase letters
|
||||
|
|
@ -97,7 +97,7 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
|
|||
if err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("Unable to fetch account by password."),
|
||||
JSON: spec.Unknown("Unable to fetch account by password."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
|
|||
if err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("Unable to fetch account by password."),
|
||||
JSON: spec.Unknown("Unable to fetch account by password."),
|
||||
}
|
||||
}
|
||||
// Technically we could tell them if the user does not exist by checking if err == sql.ErrNoRows
|
||||
|
|
@ -120,7 +120,7 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
|
|||
if !res.Exists {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("The username or password was incorrect or the account does not exist."),
|
||||
JSON: spec.Forbidden("The username or password was incorrect or the account does not exist."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import (
|
|||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
|
|
@ -178,8 +178,10 @@ func (u *UserInteractive) NewSession() *util.JSONResponse {
|
|||
sessionID, err := GenerateAccessToken()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to generate session ID")
|
||||
res := jsonerror.InternalServerError()
|
||||
return &res
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
u.Lock()
|
||||
u.Sessions[sessionID] = []string{}
|
||||
|
|
@ -193,15 +195,19 @@ func (u *UserInteractive) ResponseWithChallenge(sessionID string, response inter
|
|||
mixedObjects := make(map[string]interface{})
|
||||
b, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
ise := jsonerror.InternalServerError()
|
||||
return &ise
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
_ = json.Unmarshal(b, &mixedObjects)
|
||||
challenge := u.challenge(sessionID)
|
||||
b, err = json.Marshal(challenge.JSON)
|
||||
if err != nil {
|
||||
ise := jsonerror.InternalServerError()
|
||||
return &ise
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
_ = json.Unmarshal(b, &mixedObjects)
|
||||
|
||||
|
|
@ -234,7 +240,7 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
|
|||
if !ok {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Unknown auth.type: " + authType),
|
||||
JSON: spec.BadJSON("Unknown auth.type: " + authType),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +256,7 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
|
|||
if !u.IsSingleStageFlow(authType) {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown("The auth.session is missing or unknown."),
|
||||
JSON: spec.Unknown("The auth.session is missing or unknown."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
serverName = gomatrixserverlib.ServerName("example.com")
|
||||
serverName = spec.ServerName("example.com")
|
||||
// space separated localpart+password -> account
|
||||
lookup = make(map[string]*api.Account)
|
||||
device = &api.Device{
|
||||
|
|
@ -47,7 +48,7 @@ func (d *fakeAccountDatabase) QueryAccountByPassword(ctx context.Context, req *a
|
|||
func setup() *UserInteractive {
|
||||
cfg := &config.ClientAPI{
|
||||
Matrix: &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: serverName,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/process"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/api"
|
||||
|
|
@ -37,7 +37,7 @@ func AddPublicRoutes(
|
|||
routers httputil.Routers,
|
||||
cfg *config.Dendrite,
|
||||
natsInstance *jetstream.NATSInstance,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
transactionsCache *transactions.Cache,
|
||||
|
|
|
|||
2135
clientapi/clientapi_test.go
Normal file
2135
clientapi/clientapi_test.go
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -20,7 +20,7 @@ import (
|
|||
"net/http"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -32,8 +32,10 @@ func UnmarshalJSONRequest(req *http.Request, iface interface{}) *util.JSONRespon
|
|||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("io.ReadAll failed")
|
||||
resp := jsonerror.InternalServerError()
|
||||
return &resp
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return UnmarshalJSON(body, iface)
|
||||
|
|
@ -43,7 +45,7 @@ func UnmarshalJSON(body []byte, iface interface{}) *util.JSONResponse {
|
|||
if !utf8.Valid(body) {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotJSON("Body contains invalid UTF-8"),
|
||||
JSON: spec.NotJSON("Body contains invalid UTF-8"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +55,7 @@ func UnmarshalJSON(body []byte, iface interface{}) *util.JSONResponse {
|
|||
// valid JSON with incorrect types for values.
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("The request body could not be decoded into valid JSON. " + err.Error()),
|
||||
JSON: spec.BadJSON("The request body could not be decoded into valid JSON. " + err.Error()),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1,229 +0,0 @@
|
|||
// 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 jsonerror
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// MatrixError represents the "standard error response" in Matrix.
|
||||
// http://matrix.org/docs/spec/client_server/r0.2.0.html#api-standards
|
||||
type MatrixError struct {
|
||||
ErrCode string `json:"errcode"`
|
||||
Err string `json:"error"`
|
||||
}
|
||||
|
||||
func (e MatrixError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.ErrCode, e.Err)
|
||||
}
|
||||
|
||||
// InternalServerError returns a 500 Internal Server Error in a matrix-compliant
|
||||
// format.
|
||||
func InternalServerError() util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: Unknown("Internal Server Error"),
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown is an unexpected error
|
||||
func Unknown(msg string) *MatrixError {
|
||||
return &MatrixError{"M_UNKNOWN", msg}
|
||||
}
|
||||
|
||||
// Forbidden is an error when the client tries to access a resource
|
||||
// they are not allowed to access.
|
||||
func Forbidden(msg string) *MatrixError {
|
||||
return &MatrixError{"M_FORBIDDEN", msg}
|
||||
}
|
||||
|
||||
// BadJSON is an error when the client supplies malformed JSON.
|
||||
func BadJSON(msg string) *MatrixError {
|
||||
return &MatrixError{"M_BAD_JSON", msg}
|
||||
}
|
||||
|
||||
// BadAlias is an error when the client supplies a bad alias.
|
||||
func BadAlias(msg string) *MatrixError {
|
||||
return &MatrixError{"M_BAD_ALIAS", msg}
|
||||
}
|
||||
|
||||
// NotJSON is an error when the client supplies something that is not JSON
|
||||
// to a JSON endpoint.
|
||||
func NotJSON(msg string) *MatrixError {
|
||||
return &MatrixError{"M_NOT_JSON", msg}
|
||||
}
|
||||
|
||||
// NotFound is an error when the client tries to access an unknown resource.
|
||||
func NotFound(msg string) *MatrixError {
|
||||
return &MatrixError{"M_NOT_FOUND", msg}
|
||||
}
|
||||
|
||||
// MissingArgument is an error when the client tries to access a resource
|
||||
// without providing an argument that is required.
|
||||
func MissingArgument(msg string) *MatrixError {
|
||||
return &MatrixError{"M_MISSING_ARGUMENT", msg}
|
||||
}
|
||||
|
||||
// InvalidArgumentValue is an error when the client tries to provide an
|
||||
// invalid value for a valid argument
|
||||
func InvalidArgumentValue(msg string) *MatrixError {
|
||||
return &MatrixError{"M_INVALID_ARGUMENT_VALUE", msg}
|
||||
}
|
||||
|
||||
// MissingToken is an error when the client tries to access a resource which
|
||||
// requires authentication without supplying credentials.
|
||||
func MissingToken(msg string) *MatrixError {
|
||||
return &MatrixError{"M_MISSING_TOKEN", msg}
|
||||
}
|
||||
|
||||
// UnknownToken is an error when the client tries to access a resource which
|
||||
// requires authentication and supplies an unrecognised token
|
||||
func UnknownToken(msg string) *MatrixError {
|
||||
return &MatrixError{"M_UNKNOWN_TOKEN", msg}
|
||||
}
|
||||
|
||||
// WeakPassword is an error which is returned when the client tries to register
|
||||
// using a weak password. http://matrix.org/docs/spec/client_server/r0.2.0.html#password-based
|
||||
func WeakPassword(msg string) *MatrixError {
|
||||
return &MatrixError{"M_WEAK_PASSWORD", msg}
|
||||
}
|
||||
|
||||
// InvalidUsername is an error returned when the client tries to register an
|
||||
// invalid username
|
||||
func InvalidUsername(msg string) *MatrixError {
|
||||
return &MatrixError{"M_INVALID_USERNAME", msg}
|
||||
}
|
||||
|
||||
// UserInUse is an error returned when the client tries to register an
|
||||
// username that already exists
|
||||
func UserInUse(msg string) *MatrixError {
|
||||
return &MatrixError{"M_USER_IN_USE", msg}
|
||||
}
|
||||
|
||||
// RoomInUse is an error returned when the client tries to make a room
|
||||
// that already exists
|
||||
func RoomInUse(msg string) *MatrixError {
|
||||
return &MatrixError{"M_ROOM_IN_USE", msg}
|
||||
}
|
||||
|
||||
// ASExclusive is an error returned when an application service tries to
|
||||
// register an username that is outside of its registered namespace, or if a
|
||||
// user attempts to register a username or room alias within an exclusive
|
||||
// namespace.
|
||||
func ASExclusive(msg string) *MatrixError {
|
||||
return &MatrixError{"M_EXCLUSIVE", msg}
|
||||
}
|
||||
|
||||
// GuestAccessForbidden is an error which is returned when the client is
|
||||
// forbidden from accessing a resource as a guest.
|
||||
func GuestAccessForbidden(msg string) *MatrixError {
|
||||
return &MatrixError{"M_GUEST_ACCESS_FORBIDDEN", msg}
|
||||
}
|
||||
|
||||
// InvalidSignature is an error which is returned when the client tries
|
||||
// to upload invalid signatures.
|
||||
func InvalidSignature(msg string) *MatrixError {
|
||||
return &MatrixError{"M_INVALID_SIGNATURE", msg}
|
||||
}
|
||||
|
||||
// InvalidParam is an error that is returned when a parameter was invalid,
|
||||
// traditionally with cross-signing.
|
||||
func InvalidParam(msg string) *MatrixError {
|
||||
return &MatrixError{"M_INVALID_PARAM", msg}
|
||||
}
|
||||
|
||||
// MissingParam is an error that is returned when a parameter was incorrect,
|
||||
// traditionally with cross-signing.
|
||||
func MissingParam(msg string) *MatrixError {
|
||||
return &MatrixError{"M_MISSING_PARAM", msg}
|
||||
}
|
||||
|
||||
// UnableToAuthoriseJoin is an error that is returned when a server can't
|
||||
// determine whether to allow a restricted join or not.
|
||||
func UnableToAuthoriseJoin(msg string) *MatrixError {
|
||||
return &MatrixError{"M_UNABLE_TO_AUTHORISE_JOIN", msg}
|
||||
}
|
||||
|
||||
// LeaveServerNoticeError is an error returned when trying to reject an invite
|
||||
// for a server notice room.
|
||||
func LeaveServerNoticeError() *MatrixError {
|
||||
return &MatrixError{
|
||||
ErrCode: "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM",
|
||||
Err: "You cannot reject this invite",
|
||||
}
|
||||
}
|
||||
|
||||
type IncompatibleRoomVersionError struct {
|
||||
RoomVersion string `json:"room_version"`
|
||||
Error string `json:"error"`
|
||||
Code string `json:"errcode"`
|
||||
}
|
||||
|
||||
// IncompatibleRoomVersion is an error which is returned when the client
|
||||
// requests a room with a version that is unsupported.
|
||||
func IncompatibleRoomVersion(roomVersion gomatrixserverlib.RoomVersion) *IncompatibleRoomVersionError {
|
||||
return &IncompatibleRoomVersionError{
|
||||
Code: "M_INCOMPATIBLE_ROOM_VERSION",
|
||||
RoomVersion: string(roomVersion),
|
||||
Error: "Your homeserver does not support the features required to join this room",
|
||||
}
|
||||
}
|
||||
|
||||
// UnsupportedRoomVersion is an error which is returned when the client
|
||||
// requests a room with a version that is unsupported.
|
||||
func UnsupportedRoomVersion(msg string) *MatrixError {
|
||||
return &MatrixError{"M_UNSUPPORTED_ROOM_VERSION", msg}
|
||||
}
|
||||
|
||||
// LimitExceededError is a rate-limiting error.
|
||||
type LimitExceededError struct {
|
||||
MatrixError
|
||||
RetryAfterMS int64 `json:"retry_after_ms,omitempty"`
|
||||
}
|
||||
|
||||
// LimitExceeded is an error when the client tries to send events too quickly.
|
||||
func LimitExceeded(msg string, retryAfterMS int64) *LimitExceededError {
|
||||
return &LimitExceededError{
|
||||
MatrixError: MatrixError{"M_LIMIT_EXCEEDED", msg},
|
||||
RetryAfterMS: retryAfterMS,
|
||||
}
|
||||
}
|
||||
|
||||
// NotTrusted is an error which is returned when the client asks the server to
|
||||
// proxy a request (e.g. 3PID association) to a server that isn't trusted
|
||||
func NotTrusted(serverName string) *MatrixError {
|
||||
return &MatrixError{
|
||||
ErrCode: "M_SERVER_NOT_TRUSTED",
|
||||
Err: fmt.Sprintf("Untrusted server '%s'", serverName),
|
||||
}
|
||||
}
|
||||
|
||||
// InternalAPIError is returned when Dendrite failed to reach an internal API.
|
||||
func InternalAPIError(ctx context.Context, err error) util.JSONResponse {
|
||||
logrus.WithContext(ctx).WithError(err).Error("Error reaching an internal API")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: &MatrixError{
|
||||
ErrCode: "M_INTERNAL_SERVER_ERROR",
|
||||
Err: "Dendrite encountered an error reaching an internal API.",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// 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 jsonerror
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLimitExceeded(t *testing.T) {
|
||||
e := LimitExceeded("too fast", 5000)
|
||||
jsonBytes, err := json.Marshal(&e)
|
||||
if err != nil {
|
||||
t.Fatalf("TestLimitExceeded: Failed to marshal LimitExceeded error. %s", err.Error())
|
||||
}
|
||||
want := `{"errcode":"M_LIMIT_EXCEEDED","error":"too fast","retry_after_ms":5000}`
|
||||
if string(jsonBytes) != want {
|
||||
t.Errorf("TestLimitExceeded: want %s, got %s", want, string(jsonBytes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestForbidden(t *testing.T) {
|
||||
e := Forbidden("you shall not pass")
|
||||
jsonBytes, err := json.Marshal(&e)
|
||||
if err != nil {
|
||||
t.Fatalf("TestForbidden: Failed to marshal Forbidden error. %s", err.Error())
|
||||
}
|
||||
want := `{"errcode":"M_FORBIDDEN","error":"you shall not pass"}`
|
||||
if string(jsonBytes) != want {
|
||||
t.Errorf("TestForbidden: want %s, got %s", want, string(jsonBytes))
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/nats-io/nats.go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
|
|
@ -37,13 +38,13 @@ type SyncAPIProducer struct {
|
|||
TopicTypingEvent string
|
||||
TopicPresenceEvent string
|
||||
JetStream nats.JetStreamContext
|
||||
ServerName gomatrixserverlib.ServerName
|
||||
ServerName spec.ServerName
|
||||
UserAPI userapi.ClientUserAPI
|
||||
}
|
||||
|
||||
func (p *SyncAPIProducer) SendReceipt(
|
||||
ctx context.Context,
|
||||
userID, roomID, eventID, receiptType string, timestamp gomatrixserverlib.Timestamp,
|
||||
userID, roomID, eventID, receiptType string, timestamp spec.Timestamp,
|
||||
) error {
|
||||
m := &nats.Msg{
|
||||
Subject: p.TopicReceiptEvent,
|
||||
|
|
@ -154,7 +155,7 @@ func (p *SyncAPIProducer) SendPresence(
|
|||
m.Header.Set("status_msg", *statusMsg)
|
||||
}
|
||||
|
||||
m.Header.Set("last_active_ts", strconv.Itoa(int(gomatrixserverlib.AsTimestamp(time.Now()))))
|
||||
m.Header.Set("last_active_ts", strconv.Itoa(int(spec.AsTimestamp(time.Now()))))
|
||||
|
||||
_, err := p.JetStream.PublishMsg(m, nats.Context(ctx))
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
|
@ -38,7 +38,7 @@ func GetAccountData(
|
|||
if userID != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not match the current user"),
|
||||
JSON: spec.Forbidden("userID does not match the current user"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ func GetAccountData(
|
|||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("data not found"),
|
||||
JSON: spec.NotFound("data not found"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ func SaveAccountData(
|
|||
if userID != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not match the current user"),
|
||||
JSON: spec.Forbidden("userID does not match the current user"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,27 +90,30 @@ func SaveAccountData(
|
|||
if req.Body == http.NoBody {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotJSON("Content not JSON"),
|
||||
JSON: spec.NotJSON("Content not JSON"),
|
||||
}
|
||||
}
|
||||
|
||||
if dataType == "m.fully_read" || dataType == "m.push_rules" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(fmt.Sprintf("Unable to modify %q using this API", dataType)),
|
||||
JSON: spec.Forbidden(fmt.Sprintf("Unable to modify %q using this API", dataType)),
|
||||
}
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("io.ReadAll failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if !json.Valid(body) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Bad JSON content"),
|
||||
JSON: spec.BadJSON("Bad JSON content"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +160,10 @@ func SaveReadMarker(
|
|||
if r.FullyRead != "" {
|
||||
data, err := json.Marshal(fullyReadEvent{EventID: r.FullyRead})
|
||||
if err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
dataReq := api.InputAccountDataRequest{
|
||||
|
|
|
|||
|
|
@ -3,18 +3,20 @@ package routing
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/httputil"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
|
|
@ -27,88 +29,60 @@ func AdminEvacuateRoom(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAP
|
|||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
res := &roomserverAPI.PerformAdminEvacuateRoomResponse{}
|
||||
if err := rsAPI.PerformAdminEvacuateRoom(
|
||||
req.Context(),
|
||||
&roomserverAPI.PerformAdminEvacuateRoomRequest{
|
||||
RoomID: vars["roomID"],
|
||||
},
|
||||
res,
|
||||
); err != nil {
|
||||
|
||||
affected, err := rsAPI.PerformAdminEvacuateRoom(req.Context(), vars["roomID"])
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
case eventutil.ErrRoomNoExists:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: spec.NotFound(err.Error()),
|
||||
}
|
||||
default:
|
||||
logrus.WithError(err).WithField("roomID", vars["roomID"]).Error("Failed to evacuate room")
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
if err := res.Error; err != nil {
|
||||
return err.JSONResponse()
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: map[string]interface{}{
|
||||
"affected": res.Affected,
|
||||
"affected": affected,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func AdminEvacuateUser(req *http.Request, cfg *config.ClientAPI, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
func AdminEvacuateUser(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
userID := vars["userID"]
|
||||
|
||||
_, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
affected, err := rsAPI.PerformAdminEvacuateUser(req.Context(), vars["userID"])
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithField("userID", vars["userID"]).Error("Failed to evacuate user")
|
||||
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("User ID must belong to this server."),
|
||||
}
|
||||
}
|
||||
res := &roomserverAPI.PerformAdminEvacuateUserResponse{}
|
||||
if err := rsAPI.PerformAdminEvacuateUser(
|
||||
req.Context(),
|
||||
&roomserverAPI.PerformAdminEvacuateUserRequest{
|
||||
UserID: userID,
|
||||
},
|
||||
res,
|
||||
); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if err := res.Error; err != nil {
|
||||
return err.JSONResponse()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: map[string]interface{}{
|
||||
"affected": res.Affected,
|
||||
"affected": affected,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func AdminPurgeRoom(req *http.Request, cfg *config.ClientAPI, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
func AdminPurgeRoom(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
roomID := vars["roomID"]
|
||||
|
||||
res := &roomserverAPI.PerformAdminPurgeRoomResponse{}
|
||||
if err := rsAPI.PerformAdminPurgeRoom(
|
||||
context.Background(),
|
||||
&roomserverAPI.PerformAdminPurgeRoomRequest{
|
||||
RoomID: roomID,
|
||||
},
|
||||
res,
|
||||
); err != nil {
|
||||
if err = rsAPI.PerformAdminPurgeRoom(context.Background(), vars["roomID"]); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
if err := res.Error; err != nil {
|
||||
return err.JSONResponse()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: res,
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +90,7 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.De
|
|||
if req.Body == nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown("Missing request body"),
|
||||
JSON: spec.Unknown("Missing request body"),
|
||||
}
|
||||
}
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
|
@ -129,7 +103,7 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.De
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
accAvailableResp := &api.QueryAccountAvailabilityResponse{}
|
||||
|
|
@ -139,28 +113,29 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.De
|
|||
}, accAvailableResp); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalAPIError(req.Context(), err),
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if accAvailableResp.Available {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.Unknown("User does not exist"),
|
||||
JSON: spec.Unknown("User does not exist"),
|
||||
}
|
||||
}
|
||||
request := struct {
|
||||
Password string `json:"password"`
|
||||
Password string `json:"password"`
|
||||
LogoutDevices bool `json:"logout_devices"`
|
||||
}{}
|
||||
if err = json.NewDecoder(req.Body).Decode(&request); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown("Failed to decode request body: " + err.Error()),
|
||||
JSON: spec.Unknown("Failed to decode request body: " + err.Error()),
|
||||
}
|
||||
}
|
||||
if request.Password == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Expecting non-empty password."),
|
||||
JSON: spec.MissingParam("Expecting non-empty password."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,13 +147,13 @@ func AdminResetPassword(req *http.Request, cfg *config.ClientAPI, device *api.De
|
|||
Localpart: localpart,
|
||||
ServerName: serverName,
|
||||
Password: request.Password,
|
||||
LogoutDevices: true,
|
||||
LogoutDevices: request.LogoutDevices,
|
||||
}
|
||||
updateRes := &api.PerformPasswordUpdateResponse{}
|
||||
if err := userAPI.PerformPasswordUpdate(req.Context(), updateReq, updateRes); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown("Failed to perform password update: " + err.Error()),
|
||||
JSON: spec.Unknown("Failed to perform password update: " + err.Error()),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -195,7 +170,10 @@ func AdminReindex(req *http.Request, cfg *config.ClientAPI, device *api.Device,
|
|||
_, err := natsClient.RequestMsg(nats.NewMsg(cfg.Matrix.JetStream.Prefixed(jetstream.InputFulltextReindex)), time.Second*10)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to publish nats message")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -217,7 +195,7 @@ func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.Clien
|
|||
if cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam("Can not mark local device list as stale"),
|
||||
JSON: spec.InvalidParam("Can not mark local device list as stale"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +206,7 @@ func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.Clien
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown(fmt.Sprintf("Failed to mark device list as stale: %s", err)),
|
||||
JSON: spec.Unknown(fmt.Sprintf("Failed to mark device list as stale: %s", err)),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -237,7 +215,7 @@ func AdminMarkAsStale(req *http.Request, cfg *config.ClientAPI, keyAPI api.Clien
|
|||
}
|
||||
}
|
||||
|
||||
func AdminDownloadState(req *http.Request, cfg *config.ClientAPI, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
func AdminDownloadState(req *http.Request, device *api.Device, rsAPI roomserverAPI.ClientRoomserverAPI) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
|
|
@ -246,33 +224,32 @@ func AdminDownloadState(req *http.Request, cfg *config.ClientAPI, device *api.De
|
|||
if !ok {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Expecting room ID."),
|
||||
JSON: spec.MissingParam("Expecting room ID."),
|
||||
}
|
||||
}
|
||||
serverName, ok := vars["serverName"]
|
||||
if !ok {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Expecting remote server name."),
|
||||
JSON: spec.MissingParam("Expecting remote server name."),
|
||||
}
|
||||
}
|
||||
res := &roomserverAPI.PerformAdminDownloadStateResponse{}
|
||||
if err := rsAPI.PerformAdminDownloadState(
|
||||
req.Context(),
|
||||
&roomserverAPI.PerformAdminDownloadStateRequest{
|
||||
UserID: device.UserID,
|
||||
RoomID: roomID,
|
||||
ServerName: gomatrixserverlib.ServerName(serverName),
|
||||
},
|
||||
res,
|
||||
); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if err := res.Error; err != nil {
|
||||
return err.JSONResponse()
|
||||
if err = rsAPI.PerformAdminDownloadState(req.Context(), roomID, device.UserID, spec.ServerName(serverName)); err != nil {
|
||||
if errors.Is(err, eventutil.ErrRoomNoExists{}) {
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: spec.NotFound(err.Error()),
|
||||
}
|
||||
}
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"userID": device.UserID,
|
||||
"serverName": serverName,
|
||||
"roomID": roomID,
|
||||
}).Error("failed to download state")
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: map[string]interface{}{},
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
|
@ -51,7 +51,7 @@ func GetAdminWhois(
|
|||
if !allowed {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not match the current user"),
|
||||
JSON: spec.Forbidden("userID does not match the current user"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +61,10 @@ func GetAdminWhois(
|
|||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("GetAdminWhois failed to query user devices")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
devices := make(map[string]deviceInfo)
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ func GetAliases(
|
|||
req *http.Request, rsAPI api.ClientRoomserverAPI, device *userapi.Device, roomID string,
|
||||
) util.JSONResponse {
|
||||
stateTuple := gomatrixserverlib.StateKeyTuple{
|
||||
EventType: gomatrixserverlib.MRoomHistoryVisibility,
|
||||
EventType: spec.MRoomHistoryVisibility,
|
||||
StateKey: "",
|
||||
}
|
||||
stateReq := &api.QueryCurrentStateRequest{
|
||||
|
|
@ -47,13 +47,14 @@ func GetAliases(
|
|||
visibility := gomatrixserverlib.HistoryVisibilityInvited
|
||||
if historyVisEvent, ok := stateRes.StateEvents[stateTuple]; ok {
|
||||
var err error
|
||||
visibility, err = historyVisEvent.HistoryVisibility()
|
||||
if err != nil {
|
||||
var content gomatrixserverlib.HistoryVisibilityContent
|
||||
if err = json.Unmarshal(historyVisEvent.Content(), &content); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("historyVisEvent.HistoryVisibility failed")
|
||||
return util.ErrorResponse(fmt.Errorf("historyVisEvent.HistoryVisibility: %w", err))
|
||||
}
|
||||
visibility = content.HistoryVisibility
|
||||
}
|
||||
if visibility != gomatrixserverlib.WorldReadable {
|
||||
if visibility != spec.WorldReadable {
|
||||
queryReq := api.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: device.UserID,
|
||||
|
|
@ -61,12 +62,15 @@ func GetAliases(
|
|||
var queryRes api.QueryMembershipForUserResponse
|
||||
if err := rsAPI.QueryMembershipForUser(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryMembershipsForRoom failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !queryRes.IsInRoom {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("You aren't a member of this room."),
|
||||
JSON: spec.Forbidden("You aren't a member of this room."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,26 +17,21 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
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"
|
||||
)
|
||||
|
||||
// GetCapabilities returns information about the server's supported feature set
|
||||
// and other relevant capabilities to an authenticated user.
|
||||
func GetCapabilities(
|
||||
req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
) util.JSONResponse {
|
||||
roomVersionsQueryReq := roomserverAPI.QueryRoomVersionCapabilitiesRequest{}
|
||||
roomVersionsQueryRes := roomserverAPI.QueryRoomVersionCapabilitiesResponse{}
|
||||
if err := rsAPI.QueryRoomVersionCapabilities(
|
||||
req.Context(),
|
||||
&roomVersionsQueryReq,
|
||||
&roomVersionsQueryRes,
|
||||
); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("queryAPI.QueryRoomVersionCapabilities failed")
|
||||
return jsonerror.InternalServerError()
|
||||
func GetCapabilities() util.JSONResponse {
|
||||
versionsMap := map[gomatrixserverlib.RoomVersion]string{}
|
||||
for v, desc := range version.SupportedRoomVersions() {
|
||||
if desc.Stable() {
|
||||
versionsMap[v] = "stable"
|
||||
} else {
|
||||
versionsMap[v] = "unstable"
|
||||
}
|
||||
}
|
||||
|
||||
response := map[string]interface{}{
|
||||
|
|
@ -44,7 +39,10 @@ func GetCapabilities(
|
|||
"m.change_password": map[string]bool{
|
||||
"enabled": true,
|
||||
},
|
||||
"m.room_versions": roomVersionsQueryRes,
|
||||
"m.room_versions": map[string]interface{}{
|
||||
"default": version.DefaultRoomVersion(),
|
||||
"available": versionsMap,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,16 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
roomserverVersion "github.com/matrix-org/dendrite/roomserver/version"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
|
@ -46,7 +49,6 @@ type createRoomRequest struct {
|
|||
CreationContent json.RawMessage `json:"creation_content"`
|
||||
InitialState []fledglingEvent `json:"initial_state"`
|
||||
RoomAliasName string `json:"room_alias_name"`
|
||||
GuestCanJoin bool `json:"guest_can_join"`
|
||||
RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
|
||||
PowerLevelContentOverride json.RawMessage `json:"power_level_content_override"`
|
||||
IsDirect bool `json:"is_direct"`
|
||||
|
|
@ -72,7 +74,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
|
|||
if strings.ContainsAny(r.RoomAliasName, whitespace+":") {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("room_alias_name cannot contain whitespace or ':'"),
|
||||
JSON: spec.BadJSON("room_alias_name cannot contain whitespace or ':'"),
|
||||
}
|
||||
}
|
||||
for _, userID := range r.Invite {
|
||||
|
|
@ -84,7 +86,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
|
|||
if _, _, err := gomatrixserverlib.SplitID('@', userID); err != nil {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("user id must be in the form @localpart:domain"),
|
||||
JSON: spec.BadJSON("user id must be in the form @localpart:domain"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,7 +95,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
|
|||
default:
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("preset must be any of 'private_chat', 'trusted_private_chat', 'public_chat'"),
|
||||
JSON: spec.BadJSON("preset must be any of 'private_chat', 'trusted_private_chat', 'public_chat'"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +107,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
|
|||
if err != nil {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("malformed creation_content"),
|
||||
JSON: spec.BadJSON("malformed creation_content"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +116,7 @@ func (r createRoomRequest) Validate() *util.JSONResponse {
|
|||
if err != nil {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("malformed creation_content"),
|
||||
JSON: spec.BadJSON("malformed creation_content"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +155,7 @@ func CreateRoom(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
return createRoom(req.Context(), r, device, cfg, profileAPI, rsAPI, asAPI, evTime)
|
||||
|
|
@ -172,12 +174,15 @@ func createRoom(
|
|||
_, userDomain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !cfg.Matrix.IsLocalServerName(userDomain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(fmt.Sprintf("User domain %q not configured locally", userDomain)),
|
||||
JSON: spec.Forbidden(fmt.Sprintf("User domain %q not configured locally", userDomain)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +202,7 @@ func createRoom(
|
|||
if roomVersionError != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(roomVersionError.Error()),
|
||||
JSON: spec.UnsupportedRoomVersion(roomVersionError.Error()),
|
||||
}
|
||||
}
|
||||
roomVersion = candidateVersion
|
||||
|
|
@ -216,7 +221,10 @@ func createRoom(
|
|||
profile, err := appserviceAPI.RetrieveUserProfile(ctx, userID, asAPI, profileAPI)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
createContent := map[string]interface{}{}
|
||||
|
|
@ -225,7 +233,7 @@ func createRoom(
|
|||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for creation_content failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("invalid create content"),
|
||||
JSON: spec.BadJSON("invalid create content"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -233,7 +241,7 @@ func createRoom(
|
|||
createContent["room_version"] = roomVersion
|
||||
powerLevelContent := eventutil.InitialPowerLevelsContent(userID)
|
||||
joinRuleContent := gomatrixserverlib.JoinRuleContent{
|
||||
JoinRule: gomatrixserverlib.Invite,
|
||||
JoinRule: spec.Invite,
|
||||
}
|
||||
historyVisibilityContent := gomatrixserverlib.HistoryVisibilityContent{
|
||||
HistoryVisibility: historyVisibilityShared,
|
||||
|
|
@ -246,47 +254,50 @@ func createRoom(
|
|||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for power_level_content_override failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("malformed power_level_content_override"),
|
||||
JSON: spec.BadJSON("malformed power_level_content_override"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var guestsCanJoin bool
|
||||
switch r.Preset {
|
||||
case presetPrivateChat:
|
||||
joinRuleContent.JoinRule = gomatrixserverlib.Invite
|
||||
joinRuleContent.JoinRule = spec.Invite
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
guestsCanJoin = true
|
||||
case presetTrustedPrivateChat:
|
||||
joinRuleContent.JoinRule = gomatrixserverlib.Invite
|
||||
joinRuleContent.JoinRule = spec.Invite
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
for _, invitee := range r.Invite {
|
||||
powerLevelContent.Users[invitee] = 100
|
||||
}
|
||||
guestsCanJoin = true
|
||||
case presetPublicChat:
|
||||
joinRuleContent.JoinRule = gomatrixserverlib.Public
|
||||
joinRuleContent.JoinRule = spec.Public
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
}
|
||||
|
||||
createEvent := fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomCreate,
|
||||
Type: spec.MRoomCreate,
|
||||
Content: createContent,
|
||||
}
|
||||
powerLevelEvent := fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomPowerLevels,
|
||||
Type: spec.MRoomPowerLevels,
|
||||
Content: powerLevelContent,
|
||||
}
|
||||
joinRuleEvent := fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomJoinRules,
|
||||
Type: spec.MRoomJoinRules,
|
||||
Content: joinRuleContent,
|
||||
}
|
||||
historyVisibilityEvent := fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomHistoryVisibility,
|
||||
Type: spec.MRoomHistoryVisibility,
|
||||
Content: historyVisibilityContent,
|
||||
}
|
||||
membershipEvent := fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomMember,
|
||||
Type: spec.MRoomMember,
|
||||
StateKey: userID,
|
||||
Content: gomatrixserverlib.MemberContent{
|
||||
Membership: gomatrixserverlib.Join,
|
||||
Membership: spec.Join,
|
||||
DisplayName: profile.DisplayName,
|
||||
AvatarURL: profile.AvatarURL,
|
||||
},
|
||||
|
|
@ -299,7 +310,7 @@ func createRoom(
|
|||
|
||||
if r.Name != "" {
|
||||
nameEvent = &fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomName,
|
||||
Type: spec.MRoomName,
|
||||
Content: eventutil.NameContent{
|
||||
Name: r.Name,
|
||||
},
|
||||
|
|
@ -308,16 +319,16 @@ func createRoom(
|
|||
|
||||
if r.Topic != "" {
|
||||
topicEvent = &fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomTopic,
|
||||
Type: spec.MRoomTopic,
|
||||
Content: eventutil.TopicContent{
|
||||
Topic: r.Topic,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if r.GuestCanJoin {
|
||||
if guestsCanJoin {
|
||||
guestAccessEvent = &fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomGuestAccess,
|
||||
Type: spec.MRoomGuestAccess,
|
||||
Content: eventutil.GuestAccessContent{
|
||||
GuestAccess: "can_join",
|
||||
},
|
||||
|
|
@ -337,17 +348,20 @@ func createRoom(
|
|||
err = rsAPI.GetRoomIDForAlias(ctx, &hasAliasReq, &aliasResp)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if aliasResp.RoomID != "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.RoomInUse("Room ID already exists."),
|
||||
JSON: spec.RoomInUse("Room ID already exists."),
|
||||
}
|
||||
}
|
||||
|
||||
aliasEvent = &fledglingEvent{
|
||||
Type: gomatrixserverlib.MRoomCanonicalAlias,
|
||||
Type: spec.MRoomCanonicalAlias,
|
||||
Content: eventutil.CanonicalAlias{
|
||||
Alias: roomAlias,
|
||||
},
|
||||
|
|
@ -362,25 +376,25 @@ func createRoom(
|
|||
}
|
||||
|
||||
switch r.InitialState[i].Type {
|
||||
case gomatrixserverlib.MRoomCreate:
|
||||
case spec.MRoomCreate:
|
||||
continue
|
||||
|
||||
case gomatrixserverlib.MRoomPowerLevels:
|
||||
case spec.MRoomPowerLevels:
|
||||
powerLevelEvent = r.InitialState[i]
|
||||
|
||||
case gomatrixserverlib.MRoomJoinRules:
|
||||
case spec.MRoomJoinRules:
|
||||
joinRuleEvent = r.InitialState[i]
|
||||
|
||||
case gomatrixserverlib.MRoomHistoryVisibility:
|
||||
case spec.MRoomHistoryVisibility:
|
||||
historyVisibilityEvent = r.InitialState[i]
|
||||
|
||||
case gomatrixserverlib.MRoomGuestAccess:
|
||||
case spec.MRoomGuestAccess:
|
||||
guestAccessEvent = &r.InitialState[i]
|
||||
|
||||
case gomatrixserverlib.MRoomName:
|
||||
case spec.MRoomName:
|
||||
nameEvent = &r.InitialState[i]
|
||||
|
||||
case gomatrixserverlib.MRoomTopic:
|
||||
case spec.MRoomTopic:
|
||||
topicEvent = &r.InitialState[i]
|
||||
|
||||
default:
|
||||
|
|
@ -427,44 +441,71 @@ func createRoom(
|
|||
// TODO: invite events
|
||||
// TODO: 3pid invite events
|
||||
|
||||
var builtEvents []*gomatrixserverlib.HeaderedEvent
|
||||
verImpl, err := gomatrixserverlib.GetRoomVersion(roomVersion)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("unknown room version"),
|
||||
}
|
||||
}
|
||||
|
||||
var builtEvents []*types.HeaderedEvent
|
||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
||||
for i, e := range eventsToMake {
|
||||
depth := i + 1 // depth starts at 1
|
||||
|
||||
builder := gomatrixserverlib.EventBuilder{
|
||||
builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{
|
||||
Sender: userID,
|
||||
RoomID: roomID,
|
||||
Type: e.Type,
|
||||
StateKey: &e.StateKey,
|
||||
Depth: int64(depth),
|
||||
}
|
||||
})
|
||||
err = builder.SetContent(e.Content)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if i > 0 {
|
||||
builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
|
||||
builder.PrevEvents = []string{builtEvents[i-1].EventID()}
|
||||
}
|
||||
var ev *gomatrixserverlib.Event
|
||||
ev, err = buildEvent(&builder, userDomain, &authEvents, cfg, evTime, roomVersion)
|
||||
var ev gomatrixserverlib.PDU
|
||||
if err = builder.AddAuthEvents(&authEvents); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
ev, err = builder.Build(evTime, userDomain, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if err = gomatrixserverlib.Allowed(ev, &authEvents); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// Add the event to the list of auth events
|
||||
builtEvents = append(builtEvents, ev.Headered(roomVersion))
|
||||
builtEvents = append(builtEvents, &types.HeaderedEvent{PDU: ev})
|
||||
err = authEvents.AddEvent(ev)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("authEvents.AddEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -479,7 +520,10 @@ func createRoom(
|
|||
}
|
||||
if err = roomserverAPI.SendInputRoomEvents(ctx, rsAPI, device.UserDomain(), inputs, false); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(#269): Reserve room alias while we create the room. This stops us
|
||||
|
|
@ -496,13 +540,16 @@ func createRoom(
|
|||
err = rsAPI.SetRoomAlias(ctx, &aliasReq, &aliasResp)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("aliasAPI.SetRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if aliasResp.AliasExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.RoomInUse("Room alias already exists."),
|
||||
JSON: spec.RoomInUse("Room alias already exists."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -510,39 +557,40 @@ func createRoom(
|
|||
// If this is a direct message then we should invite the participants.
|
||||
if len(r.Invite) > 0 {
|
||||
// Build some stripped state for the invite.
|
||||
var globalStrippedState []gomatrixserverlib.InviteV2StrippedState
|
||||
var globalStrippedState []fclient.InviteV2StrippedState
|
||||
for _, event := range builtEvents {
|
||||
// Chosen events from the spec:
|
||||
// https://spec.matrix.org/v1.3/client-server-api/#stripped-state
|
||||
switch event.Type() {
|
||||
case gomatrixserverlib.MRoomCreate:
|
||||
case spec.MRoomCreate:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomName:
|
||||
case spec.MRoomName:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomAvatar:
|
||||
case spec.MRoomAvatar:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomTopic:
|
||||
case spec.MRoomTopic:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomCanonicalAlias:
|
||||
case spec.MRoomCanonicalAlias:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomEncryption:
|
||||
case spec.MRoomEncryption:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomMember:
|
||||
case spec.MRoomMember:
|
||||
fallthrough
|
||||
case gomatrixserverlib.MRoomJoinRules:
|
||||
ev := event.Event
|
||||
case spec.MRoomJoinRules:
|
||||
ev := event.PDU
|
||||
globalStrippedState = append(
|
||||
globalStrippedState,
|
||||
gomatrixserverlib.NewInviteV2StrippedState(ev),
|
||||
fclient.NewInviteV2StrippedState(ev),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Process the invites.
|
||||
var inviteEvent *types.HeaderedEvent
|
||||
for _, invitee := range r.Invite {
|
||||
// Build the invite event.
|
||||
inviteEvent, err := buildMembershipEvent(
|
||||
ctx, invitee, "", profileAPI, device, gomatrixserverlib.Invite,
|
||||
inviteEvent, err = buildMembershipEvent(
|
||||
ctx, invitee, "", profileAPI, device, spec.Invite,
|
||||
roomID, r.IsDirect, cfg, evTime, rsAPI, asAPI,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -551,41 +599,50 @@ func createRoom(
|
|||
}
|
||||
inviteStrippedState := append(
|
||||
globalStrippedState,
|
||||
gomatrixserverlib.NewInviteV2StrippedState(inviteEvent.Event),
|
||||
fclient.NewInviteV2StrippedState(inviteEvent.PDU),
|
||||
)
|
||||
// Send the invite event to the roomserver.
|
||||
var inviteRes roomserverAPI.PerformInviteResponse
|
||||
event := inviteEvent.Headered(roomVersion)
|
||||
if err := rsAPI.PerformInvite(ctx, &roomserverAPI.PerformInviteRequest{
|
||||
event := inviteEvent
|
||||
err = rsAPI.PerformInvite(ctx, &roomserverAPI.PerformInviteRequest{
|
||||
Event: event,
|
||||
InviteRoomState: inviteStrippedState,
|
||||
RoomVersion: event.RoomVersion,
|
||||
RoomVersion: event.Version(),
|
||||
SendAsServer: string(userDomain),
|
||||
}, &inviteRes); err != nil {
|
||||
})
|
||||
switch e := err.(type) {
|
||||
case roomserverAPI.ErrInvalidID:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.Unknown(e.Error()),
|
||||
}
|
||||
case roomserverAPI.ErrNotAllowed:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden(e.Error()),
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
|
||||
sentry.CaptureException(err)
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if inviteRes.Error != nil {
|
||||
return inviteRes.Error.JSONResponse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r.Visibility == "public" {
|
||||
if r.Visibility == spec.Public {
|
||||
// expose this room in the published room list
|
||||
var pubRes roomserverAPI.PerformPublishResponse
|
||||
if err := rsAPI.PerformPublish(ctx, &roomserverAPI.PerformPublishRequest{
|
||||
if err = rsAPI.PerformPublish(ctx, &roomserverAPI.PerformPublishRequest{
|
||||
RoomID: roomID,
|
||||
Visibility: "public",
|
||||
}, &pubRes); err != nil {
|
||||
return jsonerror.InternalAPIError(ctx, err)
|
||||
}
|
||||
if pubRes.Error != nil {
|
||||
// treat as non-fatal since the room is already made by this point
|
||||
util.GetLogger(ctx).WithError(pubRes.Error).Error("failed to visibility:public")
|
||||
Visibility: spec.Public,
|
||||
}); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed to publish room")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -599,31 +656,3 @@ func createRoom(
|
|||
JSON: response,
|
||||
}
|
||||
}
|
||||
|
||||
// buildEvent fills out auth_events for the builder then builds the event
|
||||
func buildEvent(
|
||||
builder *gomatrixserverlib.EventBuilder,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
provider gomatrixserverlib.AuthEventProvider,
|
||||
cfg *config.ClientAPI,
|
||||
evTime time.Time,
|
||||
roomVersion gomatrixserverlib.RoomVersion,
|
||||
) (*gomatrixserverlib.Event, error) {
|
||||
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refs, err := eventsNeeded.AuthEventReferences(provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.AuthEvents = refs
|
||||
event, err := builder.Build(
|
||||
evTime, serverName, cfg.Matrix.KeyID,
|
||||
cfg.Matrix.PrivateKey, roomVersion,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot build event %s : Builder failed to build. %w", builder.Type, err)
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ func Deactivate(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("The request body could not be read: " + err.Error()),
|
||||
JSON: spec.BadJSON("The request body could not be read: " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,19 +33,26 @@ func Deactivate(
|
|||
return *errRes
|
||||
}
|
||||
|
||||
localpart, _, err := gomatrixserverlib.SplitID('@', login.Username())
|
||||
localpart, serverName, err := gomatrixserverlib.SplitID('@', login.Username())
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
var res api.PerformAccountDeactivationResponse
|
||||
err = accountAPI.PerformAccountDeactivation(ctx, &api.PerformAccountDeactivationRequest{
|
||||
Localpart: localpart,
|
||||
Localpart: localpart,
|
||||
ServerName: serverName,
|
||||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.PerformAccountDeactivation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -15,15 +15,16 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
|
@ -59,7 +60,10 @@ func GetDeviceByID(
|
|||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryDevices failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
var targetDevice *api.Device
|
||||
for _, device := range queryRes.Devices {
|
||||
|
|
@ -71,7 +75,7 @@ func GetDeviceByID(
|
|||
if targetDevice == nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("Unknown device"),
|
||||
JSON: spec.NotFound("Unknown device"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +100,10 @@ func GetDevicesByLocalpart(
|
|||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryDevices failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
res := devicesJSON{}
|
||||
|
|
@ -138,18 +145,15 @@ func UpdateDeviceByID(
|
|||
}, &performRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformDeviceUpdate failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !performRes.DeviceExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.Forbidden("device does not exist"),
|
||||
}
|
||||
}
|
||||
if performRes.Forbidden {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("device not owned by current user"),
|
||||
JSON: spec.Forbidden("device does not exist"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,7 +183,7 @@ func DeleteDeviceById(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("The request body could not be read: " + err.Error()),
|
||||
JSON: spec.BadJSON("The request body could not be read: " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +193,7 @@ func DeleteDeviceById(
|
|||
if dev != deviceID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("session & device mismatch"),
|
||||
JSON: spec.Forbidden("session and device mismatch"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -211,7 +215,10 @@ func DeleteDeviceById(
|
|||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// make sure that the access token being used matches the login creds used for user interactive auth, else
|
||||
|
|
@ -219,7 +226,7 @@ func DeleteDeviceById(
|
|||
if login.Username() != localpart && login.Username() != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("Cannot delete another user's device"),
|
||||
JSON: spec.Forbidden("Cannot delete another user's device"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +236,10 @@ func DeleteDeviceById(
|
|||
DeviceIDs: []string{deviceID},
|
||||
}, &res); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.PerformDeviceDeletion failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
deleteOK = true
|
||||
|
|
@ -242,16 +252,40 @@ func DeleteDeviceById(
|
|||
|
||||
// DeleteDevices handles POST requests to /delete_devices
|
||||
func DeleteDevices(
|
||||
req *http.Request, userAPI api.ClientUserAPI, device *api.Device,
|
||||
req *http.Request, userInteractiveAuth *auth.UserInteractive, userAPI api.ClientUserAPI, device *api.Device,
|
||||
) util.JSONResponse {
|
||||
ctx := req.Context()
|
||||
payload := devicesDeleteJSON{}
|
||||
|
||||
if resErr := httputil.UnmarshalJSONRequest(req, &payload); resErr != nil {
|
||||
return *resErr
|
||||
bodyBytes, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("The request body could not be read: " + err.Error()),
|
||||
}
|
||||
}
|
||||
defer req.Body.Close() // nolint:errcheck
|
||||
|
||||
// initiate UIA
|
||||
login, errRes := userInteractiveAuth.Verify(ctx, bodyBytes, device)
|
||||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
|
||||
defer req.Body.Close() // nolint: errcheck
|
||||
if login.Username() != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden("unable to delete devices for other user"),
|
||||
}
|
||||
}
|
||||
|
||||
payload := devicesDeleteJSON{}
|
||||
if err = json.Unmarshal(bodyBytes, &payload); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("unable to unmarshal device deletion request")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
var res api.PerformDeviceDeletionResponse
|
||||
if err := userAPI.PerformDeviceDeletion(ctx, &api.PerformDeviceDeletionRequest{
|
||||
|
|
@ -259,7 +293,10 @@ func DeleteDevices(
|
|||
DeviceIDs: payload.Devices,
|
||||
}, &res); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.PerformDeviceDeletion failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
|
|
@ -34,7 +35,7 @@ type roomDirectoryResponse struct {
|
|||
Servers []string `json:"servers"`
|
||||
}
|
||||
|
||||
func (r *roomDirectoryResponse) fillServers(servers []gomatrixserverlib.ServerName) {
|
||||
func (r *roomDirectoryResponse) fillServers(servers []spec.ServerName) {
|
||||
r.Servers = make([]string, len(servers))
|
||||
for i, s := range servers {
|
||||
r.Servers[i] = string(s)
|
||||
|
|
@ -45,7 +46,7 @@ func (r *roomDirectoryResponse) fillServers(servers []gomatrixserverlib.ServerNa
|
|||
func DirectoryRoom(
|
||||
req *http.Request,
|
||||
roomAlias string,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
cfg *config.ClientAPI,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
fedSenderAPI federationAPI.ClientFederationAPI,
|
||||
|
|
@ -54,7 +55,7 @@ func DirectoryRoom(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Room alias must be in the form '#localpart:domain'"),
|
||||
JSON: spec.BadJSON("Room alias must be in the form '#localpart:domain'"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +69,10 @@ func DirectoryRoom(
|
|||
queryRes := &roomserverAPI.GetRoomIDForAliasResponse{}
|
||||
if err = rsAPI.GetRoomIDForAlias(req.Context(), queryReq, queryRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.GetRoomIDForAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
res.RoomID = queryRes.RoomID
|
||||
|
|
@ -82,7 +86,10 @@ func DirectoryRoom(
|
|||
// TODO: Return 502 if the remote server errored.
|
||||
// TODO: Return 504 if the remote server timed out.
|
||||
util.GetLogger(req.Context()).WithError(fedErr).Error("federation.LookupRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
res.RoomID = fedRes.RoomID
|
||||
res.fillServers(fedRes.Servers)
|
||||
|
|
@ -91,7 +98,7 @@ func DirectoryRoom(
|
|||
if res.RoomID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound(
|
||||
JSON: spec.NotFound(
|
||||
fmt.Sprintf("Room alias %s not found", roomAlias),
|
||||
),
|
||||
}
|
||||
|
|
@ -101,7 +108,10 @@ func DirectoryRoom(
|
|||
var joinedHostsRes federationAPI.QueryJoinedHostServerNamesInRoomResponse
|
||||
if err = fedSenderAPI.QueryJoinedHostServerNamesInRoom(req.Context(), &joinedHostsReq, &joinedHostsRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("fedSenderAPI.QueryJoinedHostServerNamesInRoom failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
res.fillServers(joinedHostsRes.ServerNames)
|
||||
}
|
||||
|
|
@ -124,14 +134,14 @@ func SetLocalAlias(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Room alias must be in the form '#localpart:domain'"),
|
||||
JSON: spec.BadJSON("Room alias must be in the form '#localpart:domain'"),
|
||||
}
|
||||
}
|
||||
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Alias must be on local homeserver"),
|
||||
JSON: spec.Forbidden("Alias must be on local homeserver"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +154,7 @@ func SetLocalAlias(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("User ID must be in the form '@localpart:domain'"),
|
||||
JSON: spec.BadJSON("User ID must be in the form '@localpart:domain'"),
|
||||
}
|
||||
}
|
||||
for _, appservice := range cfg.Derived.ApplicationServices {
|
||||
|
|
@ -156,7 +166,7 @@ func SetLocalAlias(
|
|||
if namespace.Exclusive && namespace.RegexpObject.MatchString(alias) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.ASExclusive("Alias is reserved by an application service"),
|
||||
JSON: spec.ASExclusive("Alias is reserved by an application service"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -179,13 +189,16 @@ func SetLocalAlias(
|
|||
var queryRes roomserverAPI.SetRoomAliasResponse
|
||||
if err := rsAPI.SetRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if queryRes.AliasExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusConflict,
|
||||
JSON: jsonerror.Unknown("The alias " + alias + " already exists."),
|
||||
JSON: spec.Unknown("The alias " + alias + " already exists."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,20 +222,23 @@ func RemoveLocalAlias(
|
|||
var queryRes roomserverAPI.RemoveRoomAliasResponse
|
||||
if err := rsAPI.RemoveRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if !queryRes.Found {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("The alias does not exist."),
|
||||
JSON: spec.NotFound("The alias does not exist."),
|
||||
}
|
||||
}
|
||||
|
||||
if !queryRes.Removed {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("You do not have permission to remove this alias."),
|
||||
JSON: spec.Forbidden("You do not have permission to remove this alias."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,12 +263,15 @@ func GetVisibility(
|
|||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryPublishedRooms failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
var v roomVisibility
|
||||
if len(res.RoomIDs) == 1 {
|
||||
v.Visibility = gomatrixserverlib.Public
|
||||
v.Visibility = spec.Public
|
||||
} else {
|
||||
v.Visibility = "private"
|
||||
}
|
||||
|
|
@ -277,7 +296,7 @@ func SetVisibility(
|
|||
queryEventsReq := roomserverAPI.QueryLatestEventsAndStateRequest{
|
||||
RoomID: roomID,
|
||||
StateToFetch: []gomatrixserverlib.StateKeyTuple{{
|
||||
EventType: gomatrixserverlib.MRoomPowerLevels,
|
||||
EventType: spec.MRoomPowerLevels,
|
||||
StateKey: "",
|
||||
}},
|
||||
}
|
||||
|
|
@ -285,15 +304,18 @@ func SetVisibility(
|
|||
err := rsAPI.QueryLatestEventsAndState(req.Context(), &queryEventsReq, &queryEventsRes)
|
||||
if err != nil || len(queryEventsRes.StateEvents) == 0 {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("could not query events from room")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// 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].Event)
|
||||
if power.UserLevel(dev.UserID) < power.EventLevel(gomatrixserverlib.MRoomCanonicalAlias, true) {
|
||||
power, _ := gomatrixserverlib.NewPowerLevelContentFromEvent(queryEventsRes.StateEvents[0].PDU)
|
||||
if power.UserLevel(dev.UserID) < power.EventLevel(spec.MRoomCanonicalAlias, true) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID doesn't have power level to change visibility"),
|
||||
JSON: spec.Forbidden("userID doesn't have power level to change visibility"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,16 +324,15 @@ func SetVisibility(
|
|||
return *reqErr
|
||||
}
|
||||
|
||||
var publishRes roomserverAPI.PerformPublishResponse
|
||||
if err := rsAPI.PerformPublish(req.Context(), &roomserverAPI.PerformPublishRequest{
|
||||
if err = rsAPI.PerformPublish(req.Context(), &roomserverAPI.PerformPublishRequest{
|
||||
RoomID: roomID,
|
||||
Visibility: v.Visibility,
|
||||
}, &publishRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if publishRes.Error != nil {
|
||||
util.GetLogger(req.Context()).WithError(publishRes.Error).Error("PerformPublish failed")
|
||||
return publishRes.Error.JSONResponse()
|
||||
}); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("failed to publish room")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -327,7 +348,7 @@ func SetVisibilityAS(
|
|||
if dev.AccountType != userapi.AccountTypeAppService {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Only appservice may use this endpoint"),
|
||||
JSON: spec.Forbidden("Only appservice may use this endpoint"),
|
||||
}
|
||||
}
|
||||
var v roomVisibility
|
||||
|
|
@ -340,18 +361,17 @@ func SetVisibilityAS(
|
|||
return *reqErr
|
||||
}
|
||||
}
|
||||
var publishRes roomserverAPI.PerformPublishResponse
|
||||
if err := rsAPI.PerformPublish(req.Context(), &roomserverAPI.PerformPublishRequest{
|
||||
RoomID: roomID,
|
||||
Visibility: v.Visibility,
|
||||
NetworkID: networkID,
|
||||
AppserviceID: dev.AppserviceID,
|
||||
}, &publishRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if publishRes.Error != nil {
|
||||
util.GetLogger(req.Context()).WithError(publishRes.Error).Error("PerformPublish failed")
|
||||
return publishRes.Error.JSONResponse()
|
||||
}); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("failed to publish room")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -23,19 +23,19 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
)
|
||||
|
||||
var (
|
||||
cacheMu sync.Mutex
|
||||
publicRoomsCache []gomatrixserverlib.PublicRoom
|
||||
publicRoomsCache []fclient.PublicRoom
|
||||
)
|
||||
|
||||
type PublicRoomReq struct {
|
||||
|
|
@ -56,7 +56,7 @@ type filter struct {
|
|||
func GetPostPublicRooms(
|
||||
req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
cfg *config.ClientAPI,
|
||||
) util.JSONResponse {
|
||||
var request PublicRoomReq
|
||||
|
|
@ -67,11 +67,11 @@ func GetPostPublicRooms(
|
|||
if request.IncludeAllNetworks && request.NetworkID != "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam("include_all_networks and third_party_instance_id can not be used together"),
|
||||
JSON: spec.InvalidParam("include_all_networks and third_party_instance_id can not be used together"),
|
||||
}
|
||||
}
|
||||
|
||||
serverName := gomatrixserverlib.ServerName(request.Server)
|
||||
serverName := spec.ServerName(request.Server)
|
||||
if serverName != "" && !cfg.Matrix.IsLocalServerName(serverName) {
|
||||
res, err := federation.GetPublicRoomsFiltered(
|
||||
req.Context(), cfg.Matrix.ServerName, serverName,
|
||||
|
|
@ -81,7 +81,10 @@ func GetPostPublicRooms(
|
|||
)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("failed to get public rooms")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -92,7 +95,10 @@ func GetPostPublicRooms(
|
|||
response, err := publicRooms(req.Context(), request, rsAPI, extRoomsProvider)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Errorf("failed to work out public rooms")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -102,10 +108,10 @@ func GetPostPublicRooms(
|
|||
|
||||
func publicRooms(
|
||||
ctx context.Context, request PublicRoomReq, rsAPI roomserverAPI.ClientRoomserverAPI, extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||
) (*gomatrixserverlib.RespPublicRooms, error) {
|
||||
) (*fclient.RespPublicRooms, error) {
|
||||
|
||||
response := gomatrixserverlib.RespPublicRooms{
|
||||
Chunk: []gomatrixserverlib.PublicRoom{},
|
||||
response := fclient.RespPublicRooms{
|
||||
Chunk: []fclient.PublicRoom{},
|
||||
}
|
||||
var limit int64
|
||||
var offset int64
|
||||
|
|
@ -122,7 +128,7 @@ func publicRooms(
|
|||
}
|
||||
err = nil
|
||||
|
||||
var rooms []gomatrixserverlib.PublicRoom
|
||||
var rooms []fclient.PublicRoom
|
||||
if request.Since == "" {
|
||||
rooms = refreshPublicRoomCache(ctx, rsAPI, extRoomsProvider, request)
|
||||
} else {
|
||||
|
|
@ -146,14 +152,14 @@ func publicRooms(
|
|||
return &response, err
|
||||
}
|
||||
|
||||
func filterRooms(rooms []gomatrixserverlib.PublicRoom, searchTerm string) []gomatrixserverlib.PublicRoom {
|
||||
func filterRooms(rooms []fclient.PublicRoom, searchTerm string) []fclient.PublicRoom {
|
||||
if searchTerm == "" {
|
||||
return rooms
|
||||
}
|
||||
|
||||
normalizedTerm := strings.ToLower(searchTerm)
|
||||
|
||||
result := make([]gomatrixserverlib.PublicRoom, 0)
|
||||
result := make([]fclient.PublicRoom, 0)
|
||||
for _, room := range rooms {
|
||||
if strings.Contains(strings.ToLower(room.Name), normalizedTerm) ||
|
||||
strings.Contains(strings.ToLower(room.Topic), normalizedTerm) ||
|
||||
|
|
@ -172,7 +178,7 @@ func fillPublicRoomsReq(httpReq *http.Request, request *PublicRoomReq) *util.JSO
|
|||
if httpReq.Method != "GET" && httpReq.Method != "POST" {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusMethodNotAllowed,
|
||||
JSON: jsonerror.NotFound("Bad method"),
|
||||
JSON: spec.NotFound("Bad method"),
|
||||
}
|
||||
}
|
||||
if httpReq.Method == "GET" {
|
||||
|
|
@ -183,7 +189,7 @@ func fillPublicRoomsReq(httpReq *http.Request, request *PublicRoomReq) *util.JSO
|
|||
util.GetLogger(httpReq.Context()).WithError(err).Error("strconv.Atoi failed")
|
||||
return &util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON("limit param is not a number"),
|
||||
JSON: spec.BadJSON("limit param is not a number"),
|
||||
}
|
||||
}
|
||||
request.Limit = int64(limit)
|
||||
|
|
@ -214,7 +220,7 @@ func fillPublicRoomsReq(httpReq *http.Request, request *PublicRoomReq) *util.JSO
|
|||
// limit=3&since=6 => G (prev='3', next='')
|
||||
//
|
||||
// A value of '-1' for prev/next indicates no position.
|
||||
func sliceInto(slice []gomatrixserverlib.PublicRoom, since int64, limit int64) (subset []gomatrixserverlib.PublicRoom, prev, next int) {
|
||||
func sliceInto(slice []fclient.PublicRoom, since int64, limit int64) (subset []fclient.PublicRoom, prev, next int) {
|
||||
prev = -1
|
||||
next = -1
|
||||
|
||||
|
|
@ -241,10 +247,10 @@ func sliceInto(slice []gomatrixserverlib.PublicRoom, since int64, limit int64) (
|
|||
func refreshPublicRoomCache(
|
||||
ctx context.Context, rsAPI roomserverAPI.ClientRoomserverAPI, extRoomsProvider api.ExtraPublicRoomsProvider,
|
||||
request PublicRoomReq,
|
||||
) []gomatrixserverlib.PublicRoom {
|
||||
) []fclient.PublicRoom {
|
||||
cacheMu.Lock()
|
||||
defer cacheMu.Unlock()
|
||||
var extraRooms []gomatrixserverlib.PublicRoom
|
||||
var extraRooms []fclient.PublicRoom
|
||||
if extRoomsProvider != nil {
|
||||
extraRooms = extRoomsProvider.Rooms()
|
||||
}
|
||||
|
|
@ -269,7 +275,7 @@ func refreshPublicRoomCache(
|
|||
util.GetLogger(ctx).WithError(err).Error("PopulatePublicRooms failed")
|
||||
return publicRoomsCache
|
||||
}
|
||||
publicRoomsCache = []gomatrixserverlib.PublicRoom{}
|
||||
publicRoomsCache = []fclient.PublicRoom{}
|
||||
publicRoomsCache = append(publicRoomsCache, pubRooms...)
|
||||
publicRoomsCache = append(publicRoomsCache, extraRooms...)
|
||||
publicRoomsCache = dedupeAndShuffle(publicRoomsCache)
|
||||
|
|
@ -281,16 +287,16 @@ func refreshPublicRoomCache(
|
|||
return publicRoomsCache
|
||||
}
|
||||
|
||||
func getPublicRoomsFromCache() []gomatrixserverlib.PublicRoom {
|
||||
func getPublicRoomsFromCache() []fclient.PublicRoom {
|
||||
cacheMu.Lock()
|
||||
defer cacheMu.Unlock()
|
||||
return publicRoomsCache
|
||||
}
|
||||
|
||||
func dedupeAndShuffle(in []gomatrixserverlib.PublicRoom) []gomatrixserverlib.PublicRoom {
|
||||
func dedupeAndShuffle(in []fclient.PublicRoom) []fclient.PublicRoom {
|
||||
// de-duplicate rooms with the same room ID. We can join the room via any of these aliases as we know these servers
|
||||
// are alive and well, so we arbitrarily pick one (purposefully shuffling them to spread the load a bit)
|
||||
var publicRooms []gomatrixserverlib.PublicRoom
|
||||
var publicRooms []fclient.PublicRoom
|
||||
haveRoomIDs := make(map[string]bool)
|
||||
rand.Shuffle(len(in), func(i, j int) {
|
||||
in[i], in[j] = in[j], in[i]
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
)
|
||||
|
||||
func pubRoom(name string) gomatrixserverlib.PublicRoom {
|
||||
return gomatrixserverlib.PublicRoom{
|
||||
func pubRoom(name string) fclient.PublicRoom {
|
||||
return fclient.PublicRoom{
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceInto(t *testing.T) {
|
||||
slice := []gomatrixserverlib.PublicRoom{
|
||||
slice := []fclient.PublicRoom{
|
||||
pubRoom("a"), pubRoom("b"), pubRoom("c"), pubRoom("d"), pubRoom("e"), pubRoom("f"), pubRoom("g"),
|
||||
}
|
||||
limit := int64(3)
|
||||
|
|
@ -22,7 +22,7 @@ func TestSliceInto(t *testing.T) {
|
|||
since int64
|
||||
wantPrev int
|
||||
wantNext int
|
||||
wantSubset []gomatrixserverlib.PublicRoom
|
||||
wantSubset []fclient.PublicRoom
|
||||
}{
|
||||
{
|
||||
since: 0,
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ import (
|
|||
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
type getJoinedRoomsResponse struct {
|
||||
|
|
@ -40,7 +40,10 @@ func GetJoinedRooms(
|
|||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryRoomsForUser failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if res.RoomIDs == nil {
|
||||
res.RoomIDs = []string{}
|
||||
|
|
|
|||
|
|
@ -15,14 +15,17 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -40,7 +43,6 @@ func JoinRoomByIDOrAlias(
|
|||
IsGuest: device.AccountType == api.AccountTypeGuest,
|
||||
Content: map[string]interface{}{},
|
||||
}
|
||||
joinRes := roomserverAPI.PerformJoinResponse{}
|
||||
|
||||
// Check to see if any ?server_name= query parameters were
|
||||
// given in the request.
|
||||
|
|
@ -48,7 +50,7 @@ func JoinRoomByIDOrAlias(
|
|||
for _, serverName := range serverNames {
|
||||
joinReq.ServerNames = append(
|
||||
joinReq.ServerNames,
|
||||
gomatrixserverlib.ServerName(serverName),
|
||||
spec.ServerName(serverName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -61,58 +63,84 @@ func JoinRoomByIDOrAlias(
|
|||
// Work out our localpart for the client profile request.
|
||||
|
||||
// Request our profile content to populate the request content with.
|
||||
res := &api.QueryProfileResponse{}
|
||||
err := profileAPI.QueryProfile(req.Context(), &api.QueryProfileRequest{UserID: device.UserID}, res)
|
||||
if err != nil || !res.UserExists {
|
||||
if !res.UserExists {
|
||||
util.GetLogger(req.Context()).Error("Unable to query user profile, no profile found.")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("Unable to query user profile, no profile found."),
|
||||
}
|
||||
}
|
||||
profile, err := profileAPI.QueryProfile(req.Context(), device.UserID)
|
||||
|
||||
util.GetLogger(req.Context()).WithError(err).Error("UserProfileAPI.QueryProfile failed")
|
||||
} else {
|
||||
joinReq.Content["displayname"] = res.DisplayName
|
||||
joinReq.Content["avatar_url"] = res.AvatarURL
|
||||
switch err {
|
||||
case nil:
|
||||
joinReq.Content["displayname"] = profile.DisplayName
|
||||
joinReq.Content["avatar_url"] = profile.AvatarURL
|
||||
case appserviceAPI.ErrProfileNotExists:
|
||||
util.GetLogger(req.Context()).Error("Unable to query user profile, no profile found.")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.Unknown("Unable to query user profile, no profile found."),
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
// Ask the roomserver to perform the join.
|
||||
done := make(chan util.JSONResponse, 1)
|
||||
go func() {
|
||||
defer close(done)
|
||||
if err := rsAPI.PerformJoin(req.Context(), &joinReq, &joinRes); err != nil {
|
||||
done <- jsonerror.InternalAPIError(req.Context(), err)
|
||||
} else if joinRes.Error != nil {
|
||||
if joinRes.Error.Code == roomserverAPI.PerformErrorNotAllowed && device.AccountType == api.AccountTypeGuest {
|
||||
done <- util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.GuestAccessForbidden(joinRes.Error.Msg),
|
||||
}
|
||||
} else {
|
||||
done <- joinRes.Error.JSONResponse()
|
||||
}
|
||||
} else {
|
||||
done <- util.JSONResponse{
|
||||
roomID, _, err := rsAPI.PerformJoin(req.Context(), &joinReq)
|
||||
var response util.JSONResponse
|
||||
|
||||
switch e := err.(type) {
|
||||
case nil: // success case
|
||||
response = util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
// TODO: Put the response struct somewhere internal.
|
||||
JSON: struct {
|
||||
RoomID string `json:"room_id"`
|
||||
}{joinRes.RoomID},
|
||||
}{roomID},
|
||||
}
|
||||
case roomserverAPI.ErrInvalidID:
|
||||
response = util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.Unknown(e.Error()),
|
||||
}
|
||||
case roomserverAPI.ErrNotAllowed:
|
||||
jsonErr := spec.Forbidden(e.Error())
|
||||
if device.AccountType == api.AccountTypeGuest {
|
||||
jsonErr = spec.GuestAccessForbidden(e.Error())
|
||||
}
|
||||
response = util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonErr,
|
||||
}
|
||||
case *gomatrix.HTTPError: // this ensures we proxy responses over federation to the client
|
||||
response = util.JSONResponse{
|
||||
Code: e.Code,
|
||||
JSON: json.RawMessage(e.Message),
|
||||
}
|
||||
case eventutil.ErrRoomNoExists:
|
||||
response = util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: spec.NotFound(e.Error()),
|
||||
}
|
||||
default:
|
||||
response = util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
done <- response
|
||||
}()
|
||||
|
||||
// Wait either for the join to finish, or for us to hit a reasonable
|
||||
// timeout, at which point we'll just return a 200 to placate clients.
|
||||
timer := time.NewTimer(time.Second * 20)
|
||||
select {
|
||||
case <-time.After(time.Second * 20):
|
||||
case <-timer.C:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusAccepted,
|
||||
JSON: jsonerror.Unknown("The room join will continue in the background."),
|
||||
JSON: spec.Unknown("The room join will continue in the background."),
|
||||
}
|
||||
case result := <-done:
|
||||
// Stop and drain the timer
|
||||
if !timer.Stop() {
|
||||
<-timer.C
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ func TestJoinRoomByIDOrAlias(t *testing.T) {
|
|||
Preset: presetPublicChat,
|
||||
RoomAliasName: "alias",
|
||||
Invite: []string{bob.ID},
|
||||
GuestCanJoin: false,
|
||||
}, aliceDev, &cfg.ClientAPI, userAPI, rsAPI, asAPI, time.Now())
|
||||
crResp, ok := resp.JSON.(createRoomResponse)
|
||||
if !ok {
|
||||
|
|
@ -75,13 +74,12 @@ func TestJoinRoomByIDOrAlias(t *testing.T) {
|
|||
|
||||
// create a room with guest access enabled and invite Charlie
|
||||
resp = createRoom(ctx, createRoomRequest{
|
||||
Name: "testing",
|
||||
IsDirect: true,
|
||||
Topic: "testing",
|
||||
Visibility: "public",
|
||||
Preset: presetPublicChat,
|
||||
Invite: []string{charlie.ID},
|
||||
GuestCanJoin: true,
|
||||
Name: "testing",
|
||||
IsDirect: true,
|
||||
Topic: "testing",
|
||||
Visibility: "public",
|
||||
Preset: presetPublicChat,
|
||||
Invite: []string{charlie.ID},
|
||||
}, aliceDev, &cfg.ClientAPI, userAPI, rsAPI, asAPI, time.Now())
|
||||
crRespWithGuestAccess, ok := resp.JSON.(createRoomResponse)
|
||||
if !ok {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -61,28 +61,26 @@ func CreateKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, de
|
|||
if resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
var performKeyBackupResp userapi.PerformKeyBackupResponse
|
||||
if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
if len(kb.AuthData) == 0 {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("missing auth_data"),
|
||||
}
|
||||
}
|
||||
version, err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
UserID: device.UserID,
|
||||
Version: "",
|
||||
AuthData: kb.AuthData,
|
||||
Algorithm: kb.Algorithm,
|
||||
}, &performKeyBackupResp); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if performKeyBackupResp.Error != "" {
|
||||
if performKeyBackupResp.BadInput {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
|
||||
}
|
||||
}
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
|
||||
})
|
||||
if err != nil {
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %w", err))
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: keyBackupVersionCreateResponse{
|
||||
Version: performKeyBackupResp.Version,
|
||||
Version: version,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -90,20 +88,17 @@ func CreateKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, de
|
|||
// KeyBackupVersion returns the key backup version specified. If `version` is empty, the latest `keyBackupVersionResponse` is returned.
|
||||
// Implements GET /_matrix/client/r0/room_keys/version and GET /_matrix/client/r0/room_keys/version/{version}
|
||||
func KeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version string) util.JSONResponse {
|
||||
var queryResp userapi.QueryKeyBackupResponse
|
||||
if err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
|
||||
queryResp, err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
|
||||
UserID: device.UserID,
|
||||
Version: version,
|
||||
}, &queryResp); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if queryResp.Error != "" {
|
||||
return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", queryResp.Error))
|
||||
})
|
||||
if err != nil {
|
||||
return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", err))
|
||||
}
|
||||
if !queryResp.Exists {
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("version not found"),
|
||||
JSON: spec.NotFound("version not found"),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -126,31 +121,29 @@ func ModifyKeyBackupVersionAuthData(req *http.Request, userAPI userapi.ClientUse
|
|||
if resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
var performKeyBackupResp userapi.PerformKeyBackupResponse
|
||||
if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
performKeyBackupResp, err := userAPI.UpdateBackupKeyAuthData(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
UserID: device.UserID,
|
||||
Version: version,
|
||||
AuthData: kb.AuthData,
|
||||
Algorithm: kb.Algorithm,
|
||||
}, &performKeyBackupResp); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if performKeyBackupResp.Error != "" {
|
||||
if performKeyBackupResp.BadInput {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
|
||||
}
|
||||
})
|
||||
switch e := err.(type) {
|
||||
case spec.ErrRoomKeysVersion:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: e,
|
||||
}
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
|
||||
case nil:
|
||||
default:
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %w", e))
|
||||
}
|
||||
|
||||
if !performKeyBackupResp.Exists {
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("backup version not found"),
|
||||
JSON: spec.NotFound("backup version not found"),
|
||||
}
|
||||
}
|
||||
// Unclear what the 200 body should be
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: keyBackupVersionCreateResponse{
|
||||
|
|
@ -162,35 +155,19 @@ func ModifyKeyBackupVersionAuthData(req *http.Request, userAPI userapi.ClientUse
|
|||
// Delete a version of key backup. Version must not be empty. If the key backup was previously deleted, will return 200 OK.
|
||||
// Implements DELETE /_matrix/client/r0/room_keys/version/{version}
|
||||
func DeleteKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version string) util.JSONResponse {
|
||||
var performKeyBackupResp userapi.PerformKeyBackupResponse
|
||||
if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
UserID: device.UserID,
|
||||
Version: version,
|
||||
DeleteBackup: true,
|
||||
}, &performKeyBackupResp); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
exists, err := userAPI.DeleteKeyBackup(req.Context(), device.UserID, version)
|
||||
if err != nil {
|
||||
return util.ErrorResponse(fmt.Errorf("DeleteKeyBackup: %s", err))
|
||||
}
|
||||
if performKeyBackupResp.Error != "" {
|
||||
if performKeyBackupResp.BadInput {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
|
||||
}
|
||||
}
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
|
||||
}
|
||||
if !performKeyBackupResp.Exists {
|
||||
if !exists {
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("backup version not found"),
|
||||
JSON: spec.NotFound("backup version not found"),
|
||||
}
|
||||
}
|
||||
// Unclear what the 200 body should be
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: keyBackupVersionCreateResponse{
|
||||
Version: performKeyBackupResp.Version,
|
||||
},
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,27 +175,26 @@ func DeleteKeyBackupVersion(req *http.Request, userAPI userapi.ClientUserAPI, de
|
|||
func UploadBackupKeys(
|
||||
req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version string, keys *keyBackupSessionRequest,
|
||||
) util.JSONResponse {
|
||||
var performKeyBackupResp userapi.PerformKeyBackupResponse
|
||||
if err := userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
performKeyBackupResp, err := userAPI.UpdateBackupKeyAuthData(req.Context(), &userapi.PerformKeyBackupRequest{
|
||||
UserID: device.UserID,
|
||||
Version: version,
|
||||
Keys: *keys,
|
||||
}, &performKeyBackupResp); err != nil && performKeyBackupResp.Error == "" {
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
if performKeyBackupResp.Error != "" {
|
||||
if performKeyBackupResp.BadInput {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
|
||||
}
|
||||
})
|
||||
|
||||
switch e := err.(type) {
|
||||
case spec.ErrRoomKeysVersion:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: e,
|
||||
}
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
|
||||
case nil:
|
||||
default:
|
||||
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %w", e))
|
||||
}
|
||||
if !performKeyBackupResp.Exists {
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("backup version not found"),
|
||||
JSON: spec.NotFound("backup version not found"),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -234,23 +210,20 @@ func UploadBackupKeys(
|
|||
func GetBackupKeys(
|
||||
req *http.Request, userAPI userapi.ClientUserAPI, device *userapi.Device, version, roomID, sessionID string,
|
||||
) util.JSONResponse {
|
||||
var queryResp userapi.QueryKeyBackupResponse
|
||||
if err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
|
||||
queryResp, err := userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
|
||||
UserID: device.UserID,
|
||||
Version: version,
|
||||
ReturnKeys: true,
|
||||
KeysForRoomID: roomID,
|
||||
KeysForSessionID: sessionID,
|
||||
}, &queryResp); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if queryResp.Error != "" {
|
||||
return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", queryResp.Error))
|
||||
})
|
||||
if err != nil {
|
||||
return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %w", err))
|
||||
}
|
||||
if !queryResp.Exists {
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("version not found"),
|
||||
JSON: spec.NotFound("version not found"),
|
||||
}
|
||||
}
|
||||
if sessionID != "" {
|
||||
|
|
@ -267,17 +240,20 @@ func GetBackupKeys(
|
|||
}
|
||||
} else if roomID != "" {
|
||||
roomData, ok := queryResp.Keys[roomID]
|
||||
if ok {
|
||||
// wrap response in "sessions"
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: struct {
|
||||
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
|
||||
}{
|
||||
Sessions: roomData,
|
||||
},
|
||||
}
|
||||
if !ok {
|
||||
// If no keys are found, then an object with an empty sessions property will be returned
|
||||
roomData = make(map[string]userapi.KeyBackupSession)
|
||||
}
|
||||
// wrap response in "sessions"
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: struct {
|
||||
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
|
||||
}{
|
||||
Sessions: roomData,
|
||||
},
|
||||
}
|
||||
|
||||
} else {
|
||||
// response is the same as the upload request
|
||||
var resp keyBackupSessionRequest
|
||||
|
|
@ -298,6 +274,6 @@ func GetBackupKeys(
|
|||
}
|
||||
return util.JSONResponse{
|
||||
Code: 404,
|
||||
JSON: jsonerror.NotFound("keys not found"),
|
||||
JSON: spec.NotFound("keys not found"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -71,31 +71,29 @@ func UploadCrossSigningDeviceKeys(
|
|||
sessions.addCompletedSessionStage(sessionID, authtypes.LoginTypePassword)
|
||||
|
||||
uploadReq.UserID = device.UserID
|
||||
if err := keyserverAPI.PerformUploadDeviceKeys(req.Context(), &uploadReq.PerformUploadDeviceKeysRequest, uploadRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
keyserverAPI.PerformUploadDeviceKeys(req.Context(), &uploadReq.PerformUploadDeviceKeysRequest, uploadRes)
|
||||
|
||||
if err := uploadRes.Error; err != nil {
|
||||
switch {
|
||||
case err.IsInvalidSignature:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidSignature(err.Error()),
|
||||
JSON: spec.InvalidSignature(err.Error()),
|
||||
}
|
||||
case err.IsMissingParam:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingParam(err.Error()),
|
||||
JSON: spec.MissingParam(err.Error()),
|
||||
}
|
||||
case err.IsInvalidParam:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
default:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown(err.Error()),
|
||||
JSON: spec.Unknown(err.Error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -115,31 +113,29 @@ func UploadCrossSigningDeviceSignatures(req *http.Request, keyserverAPI api.Clie
|
|||
}
|
||||
|
||||
uploadReq.UserID = device.UserID
|
||||
if err := keyserverAPI.PerformUploadDeviceSignatures(req.Context(), uploadReq, uploadRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
keyserverAPI.PerformUploadDeviceSignatures(req.Context(), uploadReq, uploadRes)
|
||||
|
||||
if err := uploadRes.Error; err != nil {
|
||||
switch {
|
||||
case err.IsInvalidSignature:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidSignature(err.Error()),
|
||||
JSON: spec.InvalidSignature(err.Error()),
|
||||
}
|
||||
case err.IsMissingParam:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingParam(err.Error()),
|
||||
JSON: spec.MissingParam(err.Error()),
|
||||
}
|
||||
case err.IsInvalidParam:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
default:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown(err.Error()),
|
||||
JSON: spec.Unknown(err.Error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ import (
|
|||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
type uploadKeysRequest struct {
|
||||
|
|
@ -67,7 +67,10 @@ func UploadKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *api.Device)
|
|||
}
|
||||
if uploadRes.Error != nil {
|
||||
util.GetLogger(req.Context()).WithError(uploadRes.Error).Error("Failed to PerformUploadKeys")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if len(uploadRes.KeyErrors) > 0 {
|
||||
util.GetLogger(req.Context()).WithField("key_errors", uploadRes.KeyErrors).Error("Failed to upload one or more keys")
|
||||
|
|
@ -112,14 +115,12 @@ func QueryKeys(req *http.Request, keyAPI api.ClientKeyAPI, device *api.Device) u
|
|||
return *resErr
|
||||
}
|
||||
queryRes := api.QueryKeysResponse{}
|
||||
if err := keyAPI.QueryKeys(req.Context(), &api.QueryKeysRequest{
|
||||
keyAPI.QueryKeys(req.Context(), &api.QueryKeysRequest{
|
||||
UserID: device.UserID,
|
||||
UserToDevices: r.DeviceKeys,
|
||||
Timeout: r.GetTimeout(),
|
||||
// TODO: Token?
|
||||
}, &queryRes); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
}, &queryRes)
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: map[string]interface{}{
|
||||
|
|
@ -152,15 +153,16 @@ func ClaimKeys(req *http.Request, keyAPI api.ClientKeyAPI) util.JSONResponse {
|
|||
return *resErr
|
||||
}
|
||||
claimRes := api.PerformClaimKeysResponse{}
|
||||
if err := keyAPI.PerformClaimKeys(req.Context(), &api.PerformClaimKeysRequest{
|
||||
keyAPI.PerformClaimKeys(req.Context(), &api.PerformClaimKeysRequest{
|
||||
OneTimeKeys: r.OneTimeKeys,
|
||||
Timeout: r.GetTimeout(),
|
||||
}, &claimRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
}, &claimRes)
|
||||
if claimRes.Error != nil {
|
||||
util.GetLogger(req.Context()).WithError(claimRes.Error).Error("failed to PerformClaimKeys")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -41,12 +41,12 @@ func LeaveRoomByID(
|
|||
if leaveRes.Code != 0 {
|
||||
return util.JSONResponse{
|
||||
Code: leaveRes.Code,
|
||||
JSON: jsonerror.LeaveServerNoticeError(),
|
||||
JSON: spec.LeaveServerNoticeError(),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown(err.Error()),
|
||||
JSON: spec.Unknown(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ func Login(
|
|||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusMethodNotAllowed,
|
||||
JSON: jsonerror.NotFound("Bad method"),
|
||||
JSON: spec.NotFound("Bad method"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,13 +83,19 @@ func completeAuth(
|
|||
token, err := auth.GenerateAccessToken()
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("auth.GenerateAccessToken failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
localpart, serverName, err := userutil.ParseUsernameParam(login.Username(), cfg)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("auth.ParseUsernameParam failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
var performRes userapi.PerformDeviceCreationResponse
|
||||
|
|
@ -105,7 +111,7 @@ func completeAuth(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to create device: " + err.Error()),
|
||||
JSON: spec.Unknown("failed to create device: " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/test"
|
||||
|
|
@ -39,7 +40,7 @@ func TestLogin(t *testing.T) {
|
|||
natsInstance := jetstream.NATSInstance{}
|
||||
// add a vhost
|
||||
cfg.Global.VirtualHosts = append(cfg.Global.VirtualHosts, &config.VirtualHost{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{ServerName: "vh1"},
|
||||
SigningIdentity: fclient.SigningIdentity{ServerName: "vh1"},
|
||||
})
|
||||
|
||||
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -33,7 +33,10 @@ func Logout(
|
|||
}, &performRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformDeviceDeletion failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -53,7 +56,10 @@ func LogoutAll(
|
|||
}, &performRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformDeviceDeletion failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -16,100 +16,86 @@ package routing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/threepid"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
var errMissingUserID = errors.New("'user_id' must be supplied")
|
||||
|
||||
func SendBan(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI, device *userapi.Device,
|
||||
roomID string, cfg *config.ClientAPI,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI)
|
||||
body, evTime, reqErr := extractRequestData(req)
|
||||
if reqErr != nil {
|
||||
return *reqErr
|
||||
}
|
||||
|
||||
if body.UserID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("missing user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
errRes := checkMemberInRoom(req.Context(), rsAPI, device.UserID, roomID)
|
||||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
|
||||
plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: gomatrixserverlib.MRoomPowerLevels,
|
||||
StateKey: "",
|
||||
})
|
||||
if plEvent == nil {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You don't have permission to ban this user, no power_levels event in this room."),
|
||||
}
|
||||
}
|
||||
pl, err := plEvent.PowerLevels()
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You don't have permission to ban this user, the power_levels event for this room is malformed so auth checks cannot be performed."),
|
||||
}
|
||||
pl, errRes := getPowerlevels(req, rsAPI, roomID)
|
||||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
allowedToBan := pl.UserLevel(device.UserID) >= pl.Ban
|
||||
if !allowedToBan {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You don't have permission to ban this user, power level too low."),
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden("You don't have permission to ban this user, power level too low."),
|
||||
}
|
||||
}
|
||||
|
||||
return sendMembership(req.Context(), profileAPI, device, roomID, "ban", body.Reason, cfg, body.UserID, evTime, roomVer, rsAPI, asAPI)
|
||||
return sendMembership(req.Context(), profileAPI, device, roomID, spec.Ban, body.Reason, cfg, body.UserID, evTime, rsAPI, asAPI)
|
||||
}
|
||||
|
||||
func sendMembership(ctx context.Context, profileAPI userapi.ClientUserAPI, device *userapi.Device,
|
||||
roomID, membership, reason string, cfg *config.ClientAPI, targetUserID string, evTime time.Time,
|
||||
roomVer gomatrixserverlib.RoomVersion,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI) util.JSONResponse {
|
||||
|
||||
event, err := buildMembershipEvent(
|
||||
ctx, targetUserID, reason, profileAPI, device, membership,
|
||||
roomID, false, cfg, evTime, rsAPI, asAPI,
|
||||
)
|
||||
if err == errMissingUserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(err.Error()),
|
||||
}
|
||||
} else if err == eventutil.ErrRoomNoExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound(err.Error()),
|
||||
}
|
||||
} else if err != nil {
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
serverName := device.UserDomain()
|
||||
if err = roomserverAPI.SendEvents(
|
||||
ctx, rsAPI,
|
||||
roomserverAPI.KindNew,
|
||||
[]*gomatrixserverlib.HeaderedEvent{event.Event.Headered(roomVer)},
|
||||
[]*types.HeaderedEvent{event},
|
||||
device.UserDomain(),
|
||||
serverName,
|
||||
serverName,
|
||||
|
|
@ -117,7 +103,10 @@ func sendMembership(ctx context.Context, profileAPI userapi.ClientUserAPI, devic
|
|||
false,
|
||||
); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -131,14 +120,66 @@ func SendKick(
|
|||
roomID string, cfg *config.ClientAPI,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI)
|
||||
body, evTime, reqErr := extractRequestData(req)
|
||||
if reqErr != nil {
|
||||
return *reqErr
|
||||
}
|
||||
if body.UserID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON("missing user_id"),
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("missing user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
errRes := checkMemberInRoom(req.Context(), rsAPI, device.UserID, roomID)
|
||||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
|
||||
pl, errRes := getPowerlevels(req, rsAPI, roomID)
|
||||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
allowedToKick := pl.UserLevel(device.UserID) >= 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."),
|
||||
}
|
||||
}
|
||||
|
||||
var queryRes roomserverAPI.QueryMembershipForUserResponse
|
||||
err := rsAPI.QueryMembershipForUser(req.Context(), &roomserverAPI.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: body.UserID,
|
||||
}, &queryRes)
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
// kick is only valid if the user is not currently banned or left (that is, they are joined or invited)
|
||||
if queryRes.Membership != spec.Join && queryRes.Membership != spec.Invite {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Unknown("cannot /kick banned or left users"),
|
||||
}
|
||||
}
|
||||
// TODO: should we be using SendLeave instead?
|
||||
return sendMembership(req.Context(), profileAPI, device, roomID, spec.Leave, body.Reason, cfg, body.UserID, evTime, rsAPI, asAPI)
|
||||
}
|
||||
|
||||
func SendUnban(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI, device *userapi.Device,
|
||||
roomID string, cfg *config.ClientAPI,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
body, evTime, reqErr := extractRequestData(req)
|
||||
if reqErr != nil {
|
||||
return *reqErr
|
||||
}
|
||||
if body.UserID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("missing user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,56 +196,16 @@ func SendKick(
|
|||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
// kick is only valid if the user is not currently banned or left (that is, they are joined or invited)
|
||||
if queryRes.Membership != "join" && queryRes.Membership != "invite" {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Unknown("cannot /kick banned or left users"),
|
||||
}
|
||||
}
|
||||
// TODO: should we be using SendLeave instead?
|
||||
return sendMembership(req.Context(), profileAPI, device, roomID, "leave", body.Reason, cfg, body.UserID, evTime, roomVer, rsAPI, asAPI)
|
||||
}
|
||||
|
||||
func SendUnban(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI, device *userapi.Device,
|
||||
roomID string, cfg *config.ClientAPI,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
body, evTime, roomVer, reqErr := extractRequestData(req, roomID, rsAPI)
|
||||
if reqErr != nil {
|
||||
return *reqErr
|
||||
}
|
||||
if body.UserID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON("missing user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
var queryRes roomserverAPI.QueryMembershipForUserResponse
|
||||
err := rsAPI.QueryMembershipForUser(req.Context(), &roomserverAPI.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: body.UserID,
|
||||
}, &queryRes)
|
||||
if err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
if !queryRes.RoomExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("room does not exist"),
|
||||
}
|
||||
}
|
||||
// unban is only valid if the user is currently banned
|
||||
if queryRes.Membership != "ban" {
|
||||
if queryRes.Membership != spec.Ban {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.Unknown("can only /unban users that are banned"),
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.Unknown("can only /unban users that are banned"),
|
||||
}
|
||||
}
|
||||
// TODO: should we be using SendLeave instead?
|
||||
return sendMembership(req.Context(), profileAPI, device, roomID, "leave", body.Reason, cfg, body.UserID, evTime, roomVer, rsAPI, asAPI)
|
||||
return sendMembership(req.Context(), profileAPI, device, roomID, spec.Leave, body.Reason, cfg, body.UserID, evTime, rsAPI, asAPI)
|
||||
}
|
||||
|
||||
func SendInvite(
|
||||
|
|
@ -212,7 +213,7 @@ func SendInvite(
|
|||
roomID string, cfg *config.ClientAPI,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
body, evTime, _, reqErr := extractRequestData(req, roomID, rsAPI)
|
||||
body, evTime, reqErr := extractRequestData(req)
|
||||
if reqErr != nil {
|
||||
return *reqErr
|
||||
}
|
||||
|
|
@ -234,6 +235,18 @@ func SendInvite(
|
|||
}
|
||||
}
|
||||
|
||||
if body.UserID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON("missing user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
errRes := checkMemberInRoom(req.Context(), rsAPI, device.UserID, roomID)
|
||||
if errRes != nil {
|
||||
return *errRes
|
||||
}
|
||||
|
||||
// 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)
|
||||
return response
|
||||
|
|
@ -250,39 +263,43 @@ func sendInvite(
|
|||
asAPI appserviceAPI.AppServiceInternalAPI, evTime time.Time,
|
||||
) (util.JSONResponse, error) {
|
||||
event, err := buildMembershipEvent(
|
||||
ctx, userID, reason, profileAPI, device, "invite",
|
||||
ctx, userID, reason, profileAPI, device, spec.Invite,
|
||||
roomID, false, cfg, evTime, rsAPI, asAPI,
|
||||
)
|
||||
if err == errMissingUserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(err.Error()),
|
||||
}, err
|
||||
} else if err == eventutil.ErrRoomNoExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound(err.Error()),
|
||||
}, err
|
||||
} else if err != nil {
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildMembershipEvent failed")
|
||||
return jsonerror.InternalServerError(), err
|
||||
}
|
||||
|
||||
var inviteRes api.PerformInviteResponse
|
||||
if err := rsAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
||||
Event: event,
|
||||
InviteRoomState: nil, // ask the roomserver to draw up invite room state for us
|
||||
RoomVersion: event.RoomVersion,
|
||||
SendAsServer: string(device.UserDomain()),
|
||||
}, &inviteRes); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
JSON: spec.InternalServerError{},
|
||||
}, err
|
||||
}
|
||||
if inviteRes.Error != nil {
|
||||
return inviteRes.Error.JSONResponse(), inviteRes.Error
|
||||
|
||||
err = rsAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
||||
Event: event,
|
||||
InviteRoomState: nil, // ask the roomserver to draw up invite room state for us
|
||||
RoomVersion: event.Version(),
|
||||
SendAsServer: string(device.UserDomain()),
|
||||
})
|
||||
|
||||
switch e := err.(type) {
|
||||
case roomserverAPI.ErrInvalidID:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.Unknown(e.Error()),
|
||||
}, e
|
||||
case roomserverAPI.ErrNotAllowed:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden(e.Error()),
|
||||
}, e
|
||||
case nil:
|
||||
default:
|
||||
util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
|
||||
sentry.CaptureException(err)
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}, err
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -298,13 +315,13 @@ func buildMembershipEvent(
|
|||
membership, roomID string, isDirect bool,
|
||||
cfg *config.ClientAPI, evTime time.Time,
|
||||
rsAPI roomserverAPI.ClientRoomserverAPI, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) (*gomatrixserverlib.HeaderedEvent, error) {
|
||||
) (*types.HeaderedEvent, error) {
|
||||
profile, err := loadProfile(ctx, targetUserID, cfg, profileAPI, asAPI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builder := gomatrixserverlib.EventBuilder{
|
||||
proto := gomatrixserverlib.ProtoEvent{
|
||||
Sender: device.UserID,
|
||||
RoomID: roomID,
|
||||
Type: "m.room.member",
|
||||
|
|
@ -319,7 +336,7 @@ func buildMembershipEvent(
|
|||
IsDirect: isDirect,
|
||||
}
|
||||
|
||||
if err = builder.SetContent(content); err != nil {
|
||||
if err = proto.SetContent(content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -328,7 +345,7 @@ func buildMembershipEvent(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return eventutil.QueryAndBuildEvent(ctx, &builder, cfg.Matrix, identity, evTime, rsAPI, nil)
|
||||
return eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, nil)
|
||||
}
|
||||
|
||||
// loadProfile lookups the profile of a given user from the database and returns
|
||||
|
|
@ -357,19 +374,7 @@ func loadProfile(
|
|||
return profile, err
|
||||
}
|
||||
|
||||
func extractRequestData(req *http.Request, roomID string, rsAPI roomserverAPI.ClientRoomserverAPI) (
|
||||
body *threepid.MembershipRequest, evTime time.Time, roomVer gomatrixserverlib.RoomVersion, resErr *util.JSONResponse,
|
||||
) {
|
||||
verReq := roomserverAPI.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := roomserverAPI.QueryRoomVersionForRoomResponse{}
|
||||
if err := rsAPI.QueryRoomVersionForRoom(req.Context(), &verReq, &verRes); err != nil {
|
||||
resErr = &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
return
|
||||
}
|
||||
roomVer = verRes.RoomVersion
|
||||
func extractRequestData(req *http.Request) (body *threepid.MembershipRequest, evTime time.Time, resErr *util.JSONResponse) {
|
||||
|
||||
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {
|
||||
resErr = reqErr
|
||||
|
|
@ -380,7 +385,7 @@ func extractRequestData(req *http.Request, roomID string, rsAPI roomserverAPI.Cl
|
|||
if err != nil {
|
||||
resErr = &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -402,67 +407,59 @@ func checkAndProcessThreepid(
|
|||
req.Context(), device, body, cfg, rsAPI, profileAPI,
|
||||
roomID, evTime,
|
||||
)
|
||||
if err == threepid.ErrMissingParameter {
|
||||
switch e := err.(type) {
|
||||
case nil:
|
||||
case threepid.ErrMissingParameter:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
|
||||
return inviteStored, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(err.Error()),
|
||||
JSON: spec.BadJSON(err.Error()),
|
||||
}
|
||||
} else if err == threepid.ErrNotTrusted {
|
||||
case threepid.ErrNotTrusted:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
|
||||
return inviteStored, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotTrusted(body.IDServer),
|
||||
JSON: spec.NotTrusted(body.IDServer),
|
||||
}
|
||||
} else if err == eventutil.ErrRoomNoExists {
|
||||
case eventutil.ErrRoomNoExists:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
|
||||
return inviteStored, &util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound(err.Error()),
|
||||
JSON: spec.NotFound(err.Error()),
|
||||
}
|
||||
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok {
|
||||
case gomatrixserverlib.BadJSONError:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
|
||||
return inviteStored, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(e.Error()),
|
||||
JSON: spec.BadJSON(e.Error()),
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
default:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAndProcessInvite failed")
|
||||
er := jsonerror.InternalServerError()
|
||||
return inviteStored, &er
|
||||
return inviteStored, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkMemberInRoom(ctx context.Context, rsAPI roomserverAPI.ClientRoomserverAPI, userID, roomID string) *util.JSONResponse {
|
||||
tuple := gomatrixserverlib.StateKeyTuple{
|
||||
EventType: gomatrixserverlib.MRoomMember,
|
||||
StateKey: userID,
|
||||
}
|
||||
var membershipRes roomserverAPI.QueryCurrentStateResponse
|
||||
err := rsAPI.QueryCurrentState(ctx, &roomserverAPI.QueryCurrentStateRequest{
|
||||
RoomID: roomID,
|
||||
StateTuples: []gomatrixserverlib.StateKeyTuple{tuple},
|
||||
var membershipRes roomserverAPI.QueryMembershipForUserResponse
|
||||
err := rsAPI.QueryMembershipForUser(ctx, &roomserverAPI.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: userID,
|
||||
}, &membershipRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("QueryCurrentState: could not query membership for user")
|
||||
e := jsonerror.InternalServerError()
|
||||
return &e
|
||||
}
|
||||
ev := membershipRes.StateEvents[tuple]
|
||||
if ev == nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("QueryMembershipForUser: could not query membership for user")
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("user does not belong to room"),
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
membership, err := ev.Membership()
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Member event isn't valid")
|
||||
e := jsonerror.InternalServerError()
|
||||
return &e
|
||||
}
|
||||
if membership != gomatrixserverlib.Join {
|
||||
if !membershipRes.IsInRoom {
|
||||
return &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("user does not belong to room"),
|
||||
JSON: spec.Forbidden("user does not belong to room"),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -482,18 +479,21 @@ func SendForget(
|
|||
err := rsAPI.QueryMembershipForUser(ctx, &membershipReq, &membershipRes)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("QueryMembershipForUser: could not query membership for user")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !membershipRes.RoomExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("room does not exist"),
|
||||
JSON: spec.Forbidden("room does not exist"),
|
||||
}
|
||||
}
|
||||
if membershipRes.IsInRoom {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown(fmt.Sprintf("User %s is in room %s", device.UserID, roomID)),
|
||||
JSON: spec.Unknown(fmt.Sprintf("User %s is in room %s", device.UserID, roomID)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -504,10 +504,34 @@ func SendForget(
|
|||
response := roomserverAPI.PerformForgetResponse{}
|
||||
if err := rsAPI.PerformForget(ctx, &request, &response); err != nil {
|
||||
logger.WithError(err).Error("PerformForget: unable to forget room")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func getPowerlevels(req *http.Request, rsAPI roomserverAPI.ClientRoomserverAPI, roomID string) (*gomatrixserverlib.PowerLevelContent, *util.JSONResponse) {
|
||||
plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: spec.MRoomPowerLevels,
|
||||
StateKey: "",
|
||||
})
|
||||
if plEvent == nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden("You don't have permission to perform this action, no power_levels event in this room."),
|
||||
}
|
||||
}
|
||||
pl, err := plEvent.PowerLevels()
|
||||
if err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden("You don't have permission to perform this action, the power_levels event for this room is malformed so auth checks cannot be performed."),
|
||||
}
|
||||
}
|
||||
return pl, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -35,7 +35,10 @@ func GetNotifications(
|
|||
limit, err = strconv.ParseInt(limitStr, 10, 64)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("ParseInt(limit) failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +46,10 @@ func GetNotifications(
|
|||
localpart, domain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
err = userAPI.QueryNotifications(req.Context(), &userapi.QueryNotificationsRequest{
|
||||
Localpart: localpart,
|
||||
|
|
@ -54,7 +60,10 @@ func GetNotifications(
|
|||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryNotifications failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
util.GetLogger(req.Context()).WithField("from", req.URL.Query().Get("from")).WithField("limit", limit).WithField("only", req.URL.Query().Get("only")).WithField("next", queryRes.NextToken).Infof("QueryNotifications: len %d", len(queryRes.Notifications))
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ func CreateOpenIDToken(
|
|||
if userID != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Cannot request tokens for other users"),
|
||||
JSON: spec.Forbidden("Cannot request tokens for other users"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +55,10 @@ func CreateOpenIDToken(
|
|||
err := userAPI.PerformOpenIDTokenCreation(req.Context(), &request, &response)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("userAPI.CreateOpenIDToken failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
|
@ -90,7 +90,10 @@ func Password(
|
|||
localpart, domain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the user API to perform the password change.
|
||||
|
|
@ -102,11 +105,17 @@ func Password(
|
|||
passwordRes := &api.PerformPasswordUpdateResponse{}
|
||||
if err := userAPI.PerformPasswordUpdate(req.Context(), passwordReq, passwordRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformPasswordUpdate failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !passwordRes.PasswordUpdated {
|
||||
util.GetLogger(req.Context()).Error("Expected password to have been updated but wasn't")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// If the request asks us to log out all other devices then
|
||||
|
|
@ -120,7 +129,10 @@ func Password(
|
|||
logoutRes := &api.PerformDeviceDeletionResponse{}
|
||||
if err := userAPI.PerformDeviceDeletion(req.Context(), logoutReq, logoutRes); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformDeviceDeletion failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
pushersReq := &api.PerformPusherDeletionRequest{
|
||||
|
|
@ -130,7 +142,10 @@ func Password(
|
|||
}
|
||||
if err := userAPI.PerformPusherDeletion(req.Context(), pushersReq, &struct{}{}); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformPusherDeletion failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,15 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func PeekRoomByIDOrAlias(
|
||||
|
|
@ -41,25 +43,42 @@ func PeekRoomByIDOrAlias(
|
|||
UserID: device.UserID,
|
||||
DeviceID: device.ID,
|
||||
}
|
||||
peekRes := roomserverAPI.PerformPeekResponse{}
|
||||
|
||||
// Check to see if any ?server_name= query parameters were
|
||||
// given in the request.
|
||||
if serverNames, ok := req.URL.Query()["server_name"]; ok {
|
||||
for _, serverName := range serverNames {
|
||||
peekReq.ServerNames = append(
|
||||
peekReq.ServerNames,
|
||||
gomatrixserverlib.ServerName(serverName),
|
||||
spec.ServerName(serverName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the roomserver to perform the peek.
|
||||
if err := rsAPI.PerformPeek(req.Context(), &peekReq, &peekRes); err != nil {
|
||||
return util.ErrorResponse(err)
|
||||
}
|
||||
if peekRes.Error != nil {
|
||||
return peekRes.Error.JSONResponse()
|
||||
roomID, err := rsAPI.PerformPeek(req.Context(), &peekReq)
|
||||
switch e := err.(type) {
|
||||
case roomserverAPI.ErrInvalidID:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.Unknown(e.Error()),
|
||||
}
|
||||
case roomserverAPI.ErrNotAllowed:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden(e.Error()),
|
||||
}
|
||||
case *gomatrix.HTTPError:
|
||||
return util.JSONResponse{
|
||||
Code: e.Code,
|
||||
JSON: json.RawMessage(e.Message),
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
logrus.WithError(err).WithField("roomID", roomIDOrAlias).Errorf("Failed to peek room")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// if this user is already joined to the room, we let them peek anyway
|
||||
|
|
@ -75,7 +94,7 @@ func PeekRoomByIDOrAlias(
|
|||
// TODO: Put the response struct somewhere internal.
|
||||
JSON: struct {
|
||||
RoomID string `json:"room_id"`
|
||||
}{peekRes.RoomID},
|
||||
}{roomID},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,18 +104,20 @@ func UnpeekRoomByID(
|
|||
rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
roomID string,
|
||||
) util.JSONResponse {
|
||||
unpeekReq := roomserverAPI.PerformUnpeekRequest{
|
||||
RoomID: roomID,
|
||||
UserID: device.UserID,
|
||||
DeviceID: device.ID,
|
||||
}
|
||||
unpeekRes := roomserverAPI.PerformUnpeekResponse{}
|
||||
|
||||
if err := rsAPI.PerformUnpeek(req.Context(), &unpeekReq, &unpeekRes); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
if unpeekRes.Error != nil {
|
||||
return unpeekRes.Error.JSONResponse()
|
||||
err := rsAPI.PerformUnpeek(req.Context(), roomID, device.UserID, device.ID)
|
||||
switch e := err.(type) {
|
||||
case roomserverAPI.ErrInvalidID:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.Unknown(e.Error()),
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
logrus.WithError(err).WithField("roomID", roomID).Errorf("Failed to un-peek room")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -21,13 +21,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/syncapi/types"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/nats-io/nats.go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
|
@ -54,7 +53,7 @@ func SetPresence(
|
|||
if device.UserID != userID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Unable to set presence for other user."),
|
||||
JSON: spec.Forbidden("Unable to set presence for other user."),
|
||||
}
|
||||
}
|
||||
var presence presenceReq
|
||||
|
|
@ -67,7 +66,7 @@ func SetPresence(
|
|||
if !ok {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.Unknown(fmt.Sprintf("Unknown presence '%s'.", presence.Presence)),
|
||||
JSON: spec.Unknown(fmt.Sprintf("Unknown presence '%s'.", presence.Presence)),
|
||||
}
|
||||
}
|
||||
err := producer.SendPresence(req.Context(), userID, presenceStatus, presence.StatusMsg)
|
||||
|
|
@ -75,7 +74,7 @@ func SetPresence(
|
|||
log.WithError(err).Errorf("failed to update presence")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +99,7 @@ func GetPresence(
|
|||
log.WithError(err).Errorf("unable to get presence")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,11 +118,11 @@ func GetPresence(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.InternalServerError(),
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
p := types.PresenceInternal{LastActiveTS: gomatrixserverlib.Timestamp(lastActive)}
|
||||
p := types.PresenceInternal{LastActiveTS: spec.Timestamp(lastActive)}
|
||||
currentlyActive := p.CurrentlyActive()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
|
|||
|
|
@ -20,43 +20,47 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
// GetProfile implements GET /profile/{userID}
|
||||
func GetProfile(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI, cfg *config.ClientAPI,
|
||||
req *http.Request, profileAPI userapi.ProfileAPI, cfg *config.ClientAPI,
|
||||
userID string,
|
||||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
) util.JSONResponse {
|
||||
profile, err := getProfile(req.Context(), profileAPI, cfg, userID, asAPI, federation)
|
||||
if err != nil {
|
||||
if err == eventutil.ErrProfileNoExists {
|
||||
if err == appserviceAPI.ErrProfileNotExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("The user does not exist or does not have a profile"),
|
||||
JSON: spec.NotFound("The user does not exist or does not have a profile"),
|
||||
}
|
||||
}
|
||||
|
||||
util.GetLogger(req.Context()).WithError(err).Error("getProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: eventutil.ProfileResponse{
|
||||
JSON: eventutil.UserProfile{
|
||||
AvatarURL: profile.AvatarURL,
|
||||
DisplayName: profile.DisplayName,
|
||||
},
|
||||
|
|
@ -65,64 +69,61 @@ func GetProfile(
|
|||
|
||||
// GetAvatarURL implements GET /profile/{userID}/avatar_url
|
||||
func GetAvatarURL(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI, cfg *config.ClientAPI,
|
||||
req *http.Request, profileAPI userapi.ProfileAPI, cfg *config.ClientAPI,
|
||||
userID string, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
) util.JSONResponse {
|
||||
profile, err := getProfile(req.Context(), profileAPI, cfg, userID, asAPI, federation)
|
||||
if err != nil {
|
||||
if err == eventutil.ErrProfileNoExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("The user does not exist or does not have a profile"),
|
||||
}
|
||||
}
|
||||
|
||||
util.GetLogger(req.Context()).WithError(err).Error("getProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
profile := GetProfile(req, profileAPI, cfg, userID, asAPI, federation)
|
||||
p, ok := profile.JSON.(eventutil.UserProfile)
|
||||
// not a profile response, so most likely an error, return that
|
||||
if !ok {
|
||||
return profile
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: eventutil.AvatarURL{
|
||||
AvatarURL: profile.AvatarURL,
|
||||
JSON: eventutil.UserProfile{
|
||||
AvatarURL: p.AvatarURL,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SetAvatarURL implements PUT /profile/{userID}/avatar_url
|
||||
func SetAvatarURL(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI,
|
||||
req *http.Request, profileAPI userapi.ProfileAPI,
|
||||
device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.ClientRoomserverAPI,
|
||||
) util.JSONResponse {
|
||||
if userID != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not match the current user"),
|
||||
JSON: spec.Forbidden("userID does not match the current user"),
|
||||
}
|
||||
}
|
||||
|
||||
var r eventutil.AvatarURL
|
||||
var r eventutil.UserProfile
|
||||
if resErr := httputil.UnmarshalJSONRequest(req, &r); resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
if r.AvatarURL == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("'avatar_url' must be supplied."),
|
||||
JSON: spec.BadJSON("'avatar_url' must be supplied."),
|
||||
}
|
||||
}
|
||||
|
||||
localpart, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not belong to a locally configured domain"),
|
||||
JSON: spec.Forbidden("userID does not belong to a locally configured domain"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,28 +131,27 @@ func SetAvatarURL(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
setRes := &userapi.PerformSetAvatarURLResponse{}
|
||||
if err = profileAPI.SetAvatarURL(req.Context(), &userapi.PerformSetAvatarURLRequest{
|
||||
Localpart: localpart,
|
||||
ServerName: domain,
|
||||
AvatarURL: r.AvatarURL,
|
||||
}, setRes); err != nil {
|
||||
profile, changed, err := profileAPI.SetAvatarURL(req.Context(), localpart, domain, r.AvatarURL)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("profileAPI.SetAvatarURL failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
// No need to build new membership events, since nothing changed
|
||||
if !setRes.Changed {
|
||||
if !changed {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
response, err := updateProfile(req.Context(), rsAPI, device, setRes.Profile, userID, cfg, evTime)
|
||||
response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, cfg, evTime)
|
||||
if err != nil {
|
||||
return response
|
||||
}
|
||||
|
|
@ -164,64 +164,61 @@ func SetAvatarURL(
|
|||
|
||||
// GetDisplayName implements GET /profile/{userID}/displayname
|
||||
func GetDisplayName(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI, cfg *config.ClientAPI,
|
||||
req *http.Request, profileAPI userapi.ProfileAPI, cfg *config.ClientAPI,
|
||||
userID string, asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
) util.JSONResponse {
|
||||
profile, err := getProfile(req.Context(), profileAPI, cfg, userID, asAPI, federation)
|
||||
if err != nil {
|
||||
if err == eventutil.ErrProfileNoExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("The user does not exist or does not have a profile"),
|
||||
}
|
||||
}
|
||||
|
||||
util.GetLogger(req.Context()).WithError(err).Error("getProfile failed")
|
||||
return jsonerror.InternalServerError()
|
||||
profile := GetProfile(req, profileAPI, cfg, userID, asAPI, federation)
|
||||
p, ok := profile.JSON.(eventutil.UserProfile)
|
||||
// not a profile response, so most likely an error, return that
|
||||
if !ok {
|
||||
return profile
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: eventutil.DisplayName{
|
||||
DisplayName: profile.DisplayName,
|
||||
JSON: eventutil.UserProfile{
|
||||
DisplayName: p.DisplayName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// SetDisplayName implements PUT /profile/{userID}/displayname
|
||||
func SetDisplayName(
|
||||
req *http.Request, profileAPI userapi.ClientUserAPI,
|
||||
req *http.Request, profileAPI userapi.ProfileAPI,
|
||||
device *userapi.Device, userID string, cfg *config.ClientAPI, rsAPI api.ClientRoomserverAPI,
|
||||
) util.JSONResponse {
|
||||
if userID != device.UserID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not match the current user"),
|
||||
JSON: spec.Forbidden("userID does not match the current user"),
|
||||
}
|
||||
}
|
||||
|
||||
var r eventutil.DisplayName
|
||||
var r eventutil.UserProfile
|
||||
if resErr := httputil.UnmarshalJSONRequest(req, &r); resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
if r.DisplayName == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("'displayname' must be supplied."),
|
||||
JSON: spec.BadJSON("'displayname' must be supplied."),
|
||||
}
|
||||
}
|
||||
|
||||
localpart, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if !cfg.Matrix.IsLocalServerName(domain) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("userID does not belong to a locally configured domain"),
|
||||
JSON: spec.Forbidden("userID does not belong to a locally configured domain"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,29 +226,27 @@ func SetDisplayName(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
profileRes := &userapi.PerformUpdateDisplayNameResponse{}
|
||||
err = profileAPI.SetDisplayName(req.Context(), &userapi.PerformUpdateDisplayNameRequest{
|
||||
Localpart: localpart,
|
||||
ServerName: domain,
|
||||
DisplayName: r.DisplayName,
|
||||
}, profileRes)
|
||||
profile, changed, err := profileAPI.SetDisplayName(req.Context(), localpart, domain, r.DisplayName)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("profileAPI.SetDisplayName failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
// No need to build new membership events, since nothing changed
|
||||
if !profileRes.Changed {
|
||||
if !changed {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
response, err := updateProfile(req.Context(), rsAPI, device, profileRes.Profile, userID, cfg, evTime)
|
||||
response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, cfg, evTime)
|
||||
if err != nil {
|
||||
return response
|
||||
}
|
||||
|
|
@ -274,13 +269,19 @@ func updateProfile(
|
|||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("QueryRoomsForUser failed")
|
||||
return jsonerror.InternalServerError(), err
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}, err
|
||||
}
|
||||
|
||||
_, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError(), err
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}, err
|
||||
}
|
||||
|
||||
events, err := buildMembershipEvents(
|
||||
|
|
@ -291,16 +292,22 @@ func updateProfile(
|
|||
case gomatrixserverlib.BadJSONError:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(e.Error()),
|
||||
JSON: spec.BadJSON(e.Error()),
|
||||
}, e
|
||||
default:
|
||||
util.GetLogger(ctx).WithError(err).Error("buildMembershipEvents failed")
|
||||
return jsonerror.InternalServerError(), e
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}, e
|
||||
}
|
||||
|
||||
if err := api.SendEvents(ctx, rsAPI, api.KindNew, events, device.UserDomain(), domain, domain, nil, true); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("SendEvents failed")
|
||||
return jsonerror.InternalServerError(), err
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}, err
|
||||
}
|
||||
return util.JSONResponse{}, nil
|
||||
}
|
||||
|
|
@ -308,12 +315,12 @@ func updateProfile(
|
|||
// getProfile gets the full profile of a user by querying the database or a
|
||||
// remote homeserver.
|
||||
// Returns an error when something goes wrong or specifically
|
||||
// eventutil.ErrProfileNoExists when the profile doesn't exist.
|
||||
// eventutil.ErrProfileNotExists when the profile doesn't exist.
|
||||
func getProfile(
|
||||
ctx context.Context, profileAPI userapi.ClientUserAPI, cfg *config.ClientAPI,
|
||||
ctx context.Context, profileAPI userapi.ProfileAPI, cfg *config.ClientAPI,
|
||||
userID string,
|
||||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
) (*authtypes.Profile, error) {
|
||||
localpart, domain, err := gomatrixserverlib.SplitID('@', userID)
|
||||
if err != nil {
|
||||
|
|
@ -325,7 +332,7 @@ func getProfile(
|
|||
if fedErr != nil {
|
||||
if x, ok := fedErr.(gomatrix.HTTPError); ok {
|
||||
if x.Code == http.StatusNotFound {
|
||||
return nil, eventutil.ErrProfileNoExists
|
||||
return nil, appserviceAPI.ErrProfileNotExists
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -353,17 +360,11 @@ func buildMembershipEvents(
|
|||
roomIDs []string,
|
||||
newProfile authtypes.Profile, userID string, cfg *config.ClientAPI,
|
||||
evTime time.Time, rsAPI api.ClientRoomserverAPI,
|
||||
) ([]*gomatrixserverlib.HeaderedEvent, error) {
|
||||
evs := []*gomatrixserverlib.HeaderedEvent{}
|
||||
) ([]*types.HeaderedEvent, error) {
|
||||
evs := []*types.HeaderedEvent{}
|
||||
|
||||
for _, roomID := range roomIDs {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := rsAPI.QueryRoomVersionForRoom(ctx, &verReq, &verRes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builder := gomatrixserverlib.EventBuilder{
|
||||
proto := gomatrixserverlib.ProtoEvent{
|
||||
Sender: userID,
|
||||
RoomID: roomID,
|
||||
Type: "m.room.member",
|
||||
|
|
@ -371,13 +372,13 @@ func buildMembershipEvents(
|
|||
}
|
||||
|
||||
content := gomatrixserverlib.MemberContent{
|
||||
Membership: gomatrixserverlib.Join,
|
||||
Membership: spec.Join,
|
||||
}
|
||||
|
||||
content.DisplayName = newProfile.DisplayName
|
||||
content.AvatarURL = newProfile.AvatarURL
|
||||
|
||||
if err := builder.SetContent(content); err != nil {
|
||||
if err := proto.SetContent(content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -386,12 +387,12 @@ func buildMembershipEvents(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
event, err := eventutil.QueryAndBuildEvent(ctx, &builder, cfg.Matrix, identity, evTime, rsAPI, nil)
|
||||
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
evs = append(evs, event.Headered(verRes.RoomVersion))
|
||||
evs = append(evs, event)
|
||||
}
|
||||
|
||||
return evs, nil
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ import (
|
|||
"net/url"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -34,7 +34,10 @@ func GetPushers(
|
|||
localpart, domain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
err = userAPI.QueryPushers(req.Context(), &userapi.QueryPushersRequest{
|
||||
Localpart: localpart,
|
||||
|
|
@ -42,7 +45,10 @@ func GetPushers(
|
|||
}, &queryRes)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("QueryPushers failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
for i := range queryRes.Pushers {
|
||||
queryRes.Pushers[i].SessionID = 0
|
||||
|
|
@ -63,7 +69,10 @@ func SetPusher(
|
|||
localpart, domain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
body := userapi.PerformPusherSetRequest{}
|
||||
if resErr := httputil.UnmarshalJSONRequest(req, &body); resErr != nil {
|
||||
|
|
@ -99,7 +108,10 @@ func SetPusher(
|
|||
err = userAPI.PerformPusherSet(req.Context(), &body, &struct{}{})
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("PerformPusherSet failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -111,6 +123,6 @@ func SetPusher(
|
|||
func invalidParam(msg string) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam(msg),
|
||||
JSON: spec.InvalidParam(msg),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,31 +7,34 @@ import (
|
|||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/pushrules"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
func errorResponse(ctx context.Context, err error, msg string, args ...interface{}) util.JSONResponse {
|
||||
if eerr, ok := err.(*jsonerror.MatrixError); ok {
|
||||
if eerr, ok := err.(spec.MatrixError); ok {
|
||||
var status int
|
||||
switch eerr.ErrCode {
|
||||
case "M_INVALID_ARGUMENT_VALUE":
|
||||
case spec.ErrorInvalidParam:
|
||||
status = http.StatusBadRequest
|
||||
case "M_NOT_FOUND":
|
||||
case spec.ErrorNotFound:
|
||||
status = http.StatusNotFound
|
||||
default:
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
return util.MatrixErrorResponse(status, eerr.ErrCode, eerr.Err)
|
||||
return util.MatrixErrorResponse(status, string(eerr.ErrCode), eerr.Err)
|
||||
}
|
||||
util.GetLogger(ctx).WithError(err).Errorf(msg, args...)
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
func GetAllPushRules(ctx context.Context, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRulesJSON failed")
|
||||
}
|
||||
|
|
@ -42,13 +45,13 @@ func GetAllPushRules(ctx context.Context, device *userapi.Device, userAPI userap
|
|||
}
|
||||
|
||||
func GetPushRulesByScope(ctx context.Context, scope string, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRulesJSON failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -57,17 +60,18 @@ func GetPushRulesByScope(ctx context.Context, scope string, device *userapi.Devi
|
|||
}
|
||||
|
||||
func GetPushRulesByKind(ctx context.Context, scope, kind string, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRules failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
|
||||
if rulesPtr == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
// Even if rulesPtr is not nil, there may not be any rules for this kind
|
||||
if rulesPtr == nil || (rulesPtr != nil && len(*rulesPtr) == 0) {
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -76,21 +80,21 @@ func GetPushRulesByKind(ctx context.Context, scope, kind string, device *userapi
|
|||
}
|
||||
|
||||
func GetPushRuleByRuleID(ctx context.Context, scope, kind, ruleID string, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRules failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
|
||||
if rulesPtr == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
}
|
||||
i := pushRuleIndexByID(*rulesPtr, ruleID)
|
||||
if i < 0 {
|
||||
return errorResponse(ctx, jsonerror.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
return errorResponse(ctx, spec.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -101,26 +105,30 @@ func GetPushRuleByRuleID(ctx context.Context, scope, kind, ruleID string, device
|
|||
func PutPushRuleByRuleID(ctx context.Context, scope, kind, ruleID, afterRuleID, beforeRuleID string, body io.Reader, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
||||
var newRule pushrules.Rule
|
||||
if err := json.NewDecoder(body).Decode(&newRule); err != nil {
|
||||
return errorResponse(ctx, err, "JSON Decode failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.BadJSON(err.Error()),
|
||||
}
|
||||
}
|
||||
newRule.RuleID = ruleID
|
||||
|
||||
errs := pushrules.ValidateRule(pushrules.Kind(kind), &newRule)
|
||||
if len(errs) > 0 {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue(errs[0].Error()), "rule sanity check failed: %v", errs)
|
||||
return errorResponse(ctx, spec.InvalidParam(errs[0].Error()), "rule sanity check failed: %v", errs)
|
||||
}
|
||||
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRules failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
|
||||
if rulesPtr == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
// while this should be impossible (ValidateRule would already return an error), better keep it around
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
}
|
||||
i := pushRuleIndexByID(*rulesPtr, ruleID)
|
||||
if i >= 0 && afterRuleID == "" && beforeRuleID == "" {
|
||||
|
|
@ -144,7 +152,7 @@ func PutPushRuleByRuleID(ctx context.Context, scope, kind, ruleID, afterRuleID,
|
|||
}
|
||||
|
||||
// Add new rule.
|
||||
i, err := findPushRuleInsertionIndex(*rulesPtr, afterRuleID, beforeRuleID)
|
||||
i, err = findPushRuleInsertionIndex(*rulesPtr, afterRuleID, beforeRuleID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "findPushRuleInsertionIndex failed")
|
||||
}
|
||||
|
|
@ -153,7 +161,7 @@ func PutPushRuleByRuleID(ctx context.Context, scope, kind, ruleID, afterRuleID,
|
|||
util.GetLogger(ctx).WithField("after", afterRuleID).WithField("before", beforeRuleID).Infof("Added new push rule at %d", i)
|
||||
}
|
||||
|
||||
if err := putPushRules(ctx, device.UserID, ruleSets, userAPI); err != nil {
|
||||
if err = userAPI.PerformPushRulesPut(ctx, device.UserID, ruleSets); err != nil {
|
||||
return errorResponse(ctx, err, "putPushRules failed")
|
||||
}
|
||||
|
||||
|
|
@ -161,26 +169,26 @@ func PutPushRuleByRuleID(ctx context.Context, scope, kind, ruleID, afterRuleID,
|
|||
}
|
||||
|
||||
func DeletePushRuleByRuleID(ctx context.Context, scope, kind, ruleID string, device *userapi.Device, userAPI userapi.ClientUserAPI) util.JSONResponse {
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRules failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
|
||||
if rulesPtr == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
}
|
||||
i := pushRuleIndexByID(*rulesPtr, ruleID)
|
||||
if i < 0 {
|
||||
return errorResponse(ctx, jsonerror.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
return errorResponse(ctx, spec.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
}
|
||||
|
||||
*rulesPtr = append((*rulesPtr)[:i], (*rulesPtr)[i+1:]...)
|
||||
|
||||
if err := putPushRules(ctx, device.UserID, ruleSets, userAPI); err != nil {
|
||||
if err = userAPI.PerformPushRulesPut(ctx, device.UserID, ruleSets); err != nil {
|
||||
return errorResponse(ctx, err, "putPushRules failed")
|
||||
}
|
||||
|
||||
|
|
@ -192,21 +200,21 @@ func GetPushRuleAttrByRuleID(ctx context.Context, scope, kind, ruleID, attr stri
|
|||
if err != nil {
|
||||
return errorResponse(ctx, err, "pushRuleAttrGetter failed")
|
||||
}
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRules failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
|
||||
if rulesPtr == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
}
|
||||
i := pushRuleIndexByID(*rulesPtr, ruleID)
|
||||
if i < 0 {
|
||||
return errorResponse(ctx, jsonerror.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
return errorResponse(ctx, spec.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
|
|
@ -221,7 +229,7 @@ func PutPushRuleAttrByRuleID(ctx context.Context, scope, kind, ruleID, attr stri
|
|||
if err := json.NewDecoder(body).Decode(&newPartialRule); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(err.Error()),
|
||||
JSON: spec.BadJSON(err.Error()),
|
||||
}
|
||||
}
|
||||
if newPartialRule.Actions == nil {
|
||||
|
|
@ -238,27 +246,27 @@ func PutPushRuleAttrByRuleID(ctx context.Context, scope, kind, ruleID, attr stri
|
|||
return errorResponse(ctx, err, "pushRuleAttrSetter failed")
|
||||
}
|
||||
|
||||
ruleSets, err := queryPushRules(ctx, device.UserID, userAPI)
|
||||
ruleSets, err := userAPI.QueryPushRules(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return errorResponse(ctx, err, "queryPushRules failed")
|
||||
}
|
||||
ruleSet := pushRuleSetByScope(ruleSets, pushrules.Scope(scope))
|
||||
if ruleSet == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rule set"), "pushRuleSetByScope failed")
|
||||
}
|
||||
rulesPtr := pushRuleSetKindPointer(ruleSet, pushrules.Kind(kind))
|
||||
if rulesPtr == nil {
|
||||
return errorResponse(ctx, jsonerror.InvalidArgumentValue("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
return errorResponse(ctx, spec.InvalidParam("invalid push rules kind"), "pushRuleSetKindPointer failed")
|
||||
}
|
||||
i := pushRuleIndexByID(*rulesPtr, ruleID)
|
||||
if i < 0 {
|
||||
return errorResponse(ctx, jsonerror.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
return errorResponse(ctx, spec.NotFound("push rule ID not found"), "pushRuleIndexByID failed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(attrGet((*rulesPtr)[i]), attrGet(&newPartialRule)) {
|
||||
attrSet((*rulesPtr)[i], &newPartialRule)
|
||||
|
||||
if err := putPushRules(ctx, device.UserID, ruleSets, userAPI); err != nil {
|
||||
if err = userAPI.PerformPushRulesPut(ctx, device.UserID, ruleSets); err != nil {
|
||||
return errorResponse(ctx, err, "putPushRules failed")
|
||||
}
|
||||
}
|
||||
|
|
@ -266,28 +274,6 @@ func PutPushRuleAttrByRuleID(ctx context.Context, scope, kind, ruleID, attr stri
|
|||
return util.JSONResponse{Code: http.StatusOK, JSON: struct{}{}}
|
||||
}
|
||||
|
||||
func queryPushRules(ctx context.Context, userID string, userAPI userapi.ClientUserAPI) (*pushrules.AccountRuleSets, error) {
|
||||
var res userapi.QueryPushRulesResponse
|
||||
if err := userAPI.QueryPushRules(ctx, &userapi.QueryPushRulesRequest{UserID: userID}, &res); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.QueryPushRules failed")
|
||||
return nil, err
|
||||
}
|
||||
return res.RuleSets, nil
|
||||
}
|
||||
|
||||
func putPushRules(ctx context.Context, userID string, ruleSets *pushrules.AccountRuleSets, userAPI userapi.ClientUserAPI) error {
|
||||
req := userapi.PerformPushRulesPutRequest{
|
||||
UserID: userID,
|
||||
RuleSets: ruleSets,
|
||||
}
|
||||
var res struct{}
|
||||
if err := userAPI.PerformPushRulesPut(ctx, &req, &res); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.PerformPushRulesPut failed")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pushRuleSetByScope(ruleSets *pushrules.AccountRuleSets, scope pushrules.Scope) *pushrules.RuleSet {
|
||||
switch scope {
|
||||
case pushrules.GlobalScope:
|
||||
|
|
@ -330,7 +316,7 @@ func pushRuleAttrGetter(attr string) (func(*pushrules.Rule) interface{}, error)
|
|||
case "enabled":
|
||||
return func(rule *pushrules.Rule) interface{} { return rule.Enabled }, nil
|
||||
default:
|
||||
return nil, jsonerror.InvalidArgumentValue("invalid push rule attribute")
|
||||
return nil, spec.InvalidParam("invalid push rule attribute")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -341,7 +327,7 @@ func pushRuleAttrSetter(attr string) (func(dest, src *pushrules.Rule), error) {
|
|||
case "enabled":
|
||||
return func(dest, src *pushrules.Rule) { dest.Enabled = src.Enabled }, nil
|
||||
default:
|
||||
return nil, jsonerror.InvalidArgumentValue("invalid push rule attribute")
|
||||
return nil, spec.InvalidParam("invalid push rule attribute")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,10 +341,10 @@ func findPushRuleInsertionIndex(rules []*pushrules.Rule, afterID, beforeID strin
|
|||
}
|
||||
}
|
||||
if i == len(rules) {
|
||||
return 0, jsonerror.NotFound("after: rule ID not found")
|
||||
return 0, spec.NotFound("after: rule ID not found")
|
||||
}
|
||||
if rules[i].Default {
|
||||
return 0, jsonerror.NotFound("after: rule ID must not be a default rule")
|
||||
return 0, spec.NotFound("after: rule ID must not be a default rule")
|
||||
}
|
||||
// We stopped on the "after" match to differentiate
|
||||
// not-found from is-last-entry. Now we move to the earliest
|
||||
|
|
@ -373,10 +359,10 @@ func findPushRuleInsertionIndex(rules []*pushrules.Rule, afterID, beforeID strin
|
|||
}
|
||||
}
|
||||
if i == len(rules) {
|
||||
return 0, jsonerror.NotFound("before: rule ID not found")
|
||||
return 0, spec.NotFound("before: rule ID not found")
|
||||
}
|
||||
if rules[i].Default {
|
||||
return 0, jsonerror.NotFound("before: rule ID must not be a default rule")
|
||||
return 0, spec.NotFound("before: rule ID must not be a default rule")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,8 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
|
|
@ -31,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func SetReceipt(req *http.Request, userAPI api.ClientUserAPI, syncProducer *producers.SyncAPIProducer, device *userapi.Device, roomID, receiptType, eventID string) util.JSONResponse {
|
||||
timestamp := gomatrixserverlib.AsTimestamp(time.Now())
|
||||
timestamp := spec.AsTimestamp(time.Now())
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"roomID": roomID,
|
||||
"receiptType": receiptType,
|
||||
|
|
@ -49,7 +48,10 @@ func SetReceipt(req *http.Request, userAPI api.ClientUserAPI, syncProducer *prod
|
|||
case "m.fully_read":
|
||||
data, err := json.Marshal(fullyReadEvent{EventID: eventID})
|
||||
if err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
dataReq := api.InputAccountDataRequest{
|
||||
|
|
|
|||
|
|
@ -16,17 +16,19 @@ package routing
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/internal/transactions"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
)
|
||||
|
|
@ -61,13 +63,13 @@ func SendRedaction(
|
|||
if ev == nil {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.NotFound("unknown event ID"), // TODO: is it ok to leak existence?
|
||||
JSON: spec.NotFound("unknown event ID"), // TODO: is it ok to leak existence?
|
||||
}
|
||||
}
|
||||
if ev.RoomID() != roomID {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.NotFound("cannot redact event in another room"),
|
||||
JSON: spec.NotFound("cannot redact event in another room"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,20 +79,20 @@ func SendRedaction(
|
|||
allowedToRedact := ev.Sender() == device.UserID
|
||||
if !allowedToRedact {
|
||||
plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: gomatrixserverlib.MRoomPowerLevels,
|
||||
EventType: spec.MRoomPowerLevels,
|
||||
StateKey: "",
|
||||
})
|
||||
if plEvent == nil {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You don't have permission to redact this event, no power_levels event in this room."),
|
||||
JSON: spec.Forbidden("You don't have permission to redact this event, no power_levels event in this room."),
|
||||
}
|
||||
}
|
||||
pl, err := plEvent.PowerLevels()
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden(
|
||||
JSON: spec.Forbidden(
|
||||
"You don't have permission to redact this event, the power_levels event for this room is malformed so auth checks cannot be performed.",
|
||||
),
|
||||
}
|
||||
|
|
@ -100,7 +102,7 @@ func SendRedaction(
|
|||
if !allowedToRedact {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("You don't have permission to redact this event, power level too low."),
|
||||
JSON: spec.Forbidden("You don't have permission to redact this event, power level too low."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,35 +113,44 @@ func SendRedaction(
|
|||
}
|
||||
|
||||
// create the new event and set all the fields we can
|
||||
builder := gomatrixserverlib.EventBuilder{
|
||||
proto := gomatrixserverlib.ProtoEvent{
|
||||
Sender: device.UserID,
|
||||
RoomID: roomID,
|
||||
Type: gomatrixserverlib.MRoomRedaction,
|
||||
Type: spec.MRoomRedaction,
|
||||
Redacts: eventID,
|
||||
}
|
||||
err := builder.SetContent(r)
|
||||
err := proto.SetContent(r)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("builder.SetContent failed")
|
||||
return jsonerror.InternalServerError()
|
||||
util.GetLogger(req.Context()).WithError(err).Error("proto.SetContent failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
|
||||
if err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
|
||||
e, err := eventutil.QueryAndBuildEvent(req.Context(), &builder, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
|
||||
if err == eventutil.ErrRoomNoExists {
|
||||
e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, cfg.Matrix, identity, time.Now(), rsAPI, &queryRes)
|
||||
if errors.Is(err, eventutil.ErrRoomNoExists{}) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
JSON: spec.NotFound("Room does not exist"),
|
||||
}
|
||||
}
|
||||
domain := device.UserDomain()
|
||||
if err = roomserverAPI.SendEvents(context.Background(), rsAPI, roomserverAPI.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, device.UserDomain(), domain, domain, nil, false); err != nil {
|
||||
if err = roomserverAPI.SendEvents(context.Background(), rsAPI, roomserverAPI.KindNew, []*types.HeaderedEvent{e}, device.UserDomain(), domain, domain, nil, false); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Errorf("failed to SendEvents")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
res := util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/config"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/gomatrixserverlib/tokens"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
|
@ -45,7 +46,6 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
)
|
||||
|
|
@ -164,7 +164,7 @@ func (d *sessionsDict) addCompletedSessionStage(sessionID string, stage authtype
|
|||
return
|
||||
}
|
||||
}
|
||||
d.sessions[sessionID] = append(sessions.sessions[sessionID], stage)
|
||||
d.sessions[sessionID] = append(d.sessions[sessionID], stage)
|
||||
}
|
||||
|
||||
func (d *sessionsDict) addDeviceToDelete(sessionID, deviceID string) {
|
||||
|
|
@ -206,10 +206,10 @@ var (
|
|||
// previous parameters with the ones supplied. This mean you cannot "build up" request params.
|
||||
type registerRequest struct {
|
||||
// registration parameters
|
||||
Password string `json:"password"`
|
||||
Username string `json:"username"`
|
||||
ServerName gomatrixserverlib.ServerName `json:"-"`
|
||||
Admin bool `json:"admin"`
|
||||
Password string `json:"password"`
|
||||
Username string `json:"username"`
|
||||
ServerName spec.ServerName `json:"-"`
|
||||
Admin bool `json:"admin"`
|
||||
// user-interactive auth params
|
||||
Auth authDict `json:"auth"`
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ func validateApplicationService(
|
|||
if matchedApplicationService == nil {
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.UnknownToken("Supplied access_token does not match any known application service"),
|
||||
JSON: spec.UnknownToken("Supplied access_token does not match any known application service"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ func validateApplicationService(
|
|||
// If we didn't find any matches, return M_EXCLUSIVE
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.ASExclusive(fmt.Sprintf(
|
||||
JSON: spec.ASExclusive(fmt.Sprintf(
|
||||
"Supplied username %s did not match any namespaces for application service ID: %s", username, matchedApplicationService.ID)),
|
||||
}
|
||||
}
|
||||
|
|
@ -447,7 +447,7 @@ func validateApplicationService(
|
|||
if UsernameMatchesMultipleExclusiveNamespaces(cfg, userID) {
|
||||
return "", &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.ASExclusive(fmt.Sprintf(
|
||||
JSON: spec.ASExclusive(fmt.Sprintf(
|
||||
"Supplied username %s matches multiple exclusive application service namespaces. Only 1 match allowed", username)),
|
||||
}
|
||||
}
|
||||
|
|
@ -473,12 +473,12 @@ func Register(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotJSON("Unable to read request body"),
|
||||
JSON: spec.NotJSON("Unable to read request body"),
|
||||
}
|
||||
}
|
||||
|
||||
var r registerRequest
|
||||
host := gomatrixserverlib.ServerName(req.Host)
|
||||
host := spec.ServerName(req.Host)
|
||||
if v := cfg.Matrix.VirtualHostForHTTPHost(host); v != nil {
|
||||
r.ServerName = v.ServerName
|
||||
} else {
|
||||
|
|
@ -517,7 +517,7 @@ func Register(
|
|||
if _, err = strconv.ParseInt(r.Username, 10, 64); err == nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidUsername("Numeric user IDs are reserved"),
|
||||
JSON: spec.InvalidUsername("Numeric user IDs are reserved"),
|
||||
}
|
||||
}
|
||||
// Auto generate a numeric username if r.Username is empty
|
||||
|
|
@ -528,7 +528,10 @@ func Register(
|
|||
nres := &userapi.QueryNumericLocalpartResponse{}
|
||||
if err = userAPI.QueryNumericLocalpart(req.Context(), nreq, nres); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("userAPI.QueryNumericLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
r.Username = strconv.FormatInt(nres.ID, 10)
|
||||
}
|
||||
|
|
@ -551,7 +554,7 @@ func Register(
|
|||
// type is not known or specified)
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("A known registration type (e.g. m.login.application_service) must be specified if an access_token is provided"),
|
||||
JSON: spec.MissingParam("A known registration type (e.g. m.login.application_service) must be specified if an access_token is provided"),
|
||||
}
|
||||
default:
|
||||
// Spec-compliant case (neither the access_token nor the login type are
|
||||
|
|
@ -589,7 +592,7 @@ func handleGuestRegistration(
|
|||
if !registrationEnabled || !guestsEnabled {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(
|
||||
JSON: spec.Forbidden(
|
||||
fmt.Sprintf("Guest registration is disabled on %q", r.ServerName),
|
||||
),
|
||||
}
|
||||
|
|
@ -603,7 +606,7 @@ func handleGuestRegistration(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to create account: " + err.Error()),
|
||||
JSON: spec.Unknown("failed to create account: " + err.Error()),
|
||||
}
|
||||
}
|
||||
token, err := tokens.GenerateLoginToken(tokens.TokenOptions{
|
||||
|
|
@ -615,7 +618,7 @@ func handleGuestRegistration(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("Failed to generate access token"),
|
||||
JSON: spec.Unknown("Failed to generate access token"),
|
||||
}
|
||||
}
|
||||
//we don't allow guests to specify their own device_id
|
||||
|
|
@ -631,7 +634,7 @@ func handleGuestRegistration(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to create device: " + err.Error()),
|
||||
JSON: spec.Unknown("failed to create device: " + err.Error()),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -681,7 +684,7 @@ func handleRegistrationFlow(
|
|||
if !registrationEnabled && r.Auth.Type != authtypes.LoginTypeSharedSecret {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(
|
||||
JSON: spec.Forbidden(
|
||||
fmt.Sprintf("Registration is disabled on %q", r.ServerName),
|
||||
),
|
||||
}
|
||||
|
|
@ -695,7 +698,7 @@ func handleRegistrationFlow(
|
|||
UsernameMatchesExclusiveNamespaces(cfg, r.Username) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.ASExclusive("This username is reserved by an application service."),
|
||||
JSON: spec.ASExclusive("This username is reserved by an application service."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -705,15 +708,15 @@ func handleRegistrationFlow(
|
|||
err := validateRecaptcha(cfg, r.Auth.Response, req.RemoteAddr)
|
||||
switch err {
|
||||
case ErrCaptchaDisabled:
|
||||
return util.JSONResponse{Code: http.StatusForbidden, JSON: jsonerror.Unknown(err.Error())}
|
||||
return util.JSONResponse{Code: http.StatusForbidden, JSON: spec.Unknown(err.Error())}
|
||||
case ErrMissingResponse:
|
||||
return util.JSONResponse{Code: http.StatusBadRequest, JSON: jsonerror.BadJSON(err.Error())}
|
||||
return util.JSONResponse{Code: http.StatusBadRequest, JSON: spec.BadJSON(err.Error())}
|
||||
case ErrInvalidCaptcha:
|
||||
return util.JSONResponse{Code: http.StatusUnauthorized, JSON: jsonerror.BadJSON(err.Error())}
|
||||
return util.JSONResponse{Code: http.StatusUnauthorized, JSON: spec.BadJSON(err.Error())}
|
||||
case nil:
|
||||
default:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("failed to validate recaptcha")
|
||||
return util.JSONResponse{Code: http.StatusInternalServerError, JSON: jsonerror.InternalServerError()}
|
||||
return util.JSONResponse{Code: http.StatusInternalServerError, JSON: spec.InternalServerError{}}
|
||||
}
|
||||
|
||||
// Add Recaptcha to the list of completed registration stages
|
||||
|
|
@ -731,7 +734,7 @@ func handleRegistrationFlow(
|
|||
default:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotImplemented,
|
||||
JSON: jsonerror.Unknown("unknown/unimplemented auth type"),
|
||||
JSON: spec.Unknown("unknown/unimplemented auth type"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -763,7 +766,7 @@ func handleApplicationServiceRegistration(
|
|||
if tokenErr != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.MissingToken(tokenErr.Error()),
|
||||
JSON: spec.MissingToken(tokenErr.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -824,7 +827,7 @@ func checkAndCompleteFlow(
|
|||
func completeRegistration(
|
||||
ctx context.Context,
|
||||
userAPI userapi.ClientUserAPI,
|
||||
username string, serverName gomatrixserverlib.ServerName, displayName string,
|
||||
username string, serverName spec.ServerName, displayName string,
|
||||
password, appserviceID, ipAddr, userAgent, sessionID string,
|
||||
inhibitLogin eventutil.WeakBoolean,
|
||||
deviceDisplayName, deviceID *string,
|
||||
|
|
@ -833,14 +836,14 @@ func completeRegistration(
|
|||
if username == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Missing username"),
|
||||
JSON: spec.MissingParam("Missing username"),
|
||||
}
|
||||
}
|
||||
// Blank passwords are only allowed by registered application services
|
||||
if password == "" && appserviceID == "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MissingArgument("Missing password"),
|
||||
JSON: spec.MissingParam("Missing password"),
|
||||
}
|
||||
}
|
||||
var accRes userapi.PerformAccountCreationResponse
|
||||
|
|
@ -856,12 +859,12 @@ func completeRegistration(
|
|||
if _, ok := err.(*userapi.ErrorConflict); ok { // user already exists
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UserInUse("Desired user ID is already taken."),
|
||||
JSON: spec.UserInUse("Desired user ID is already taken."),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to create account: " + err.Error()),
|
||||
JSON: spec.Unknown("failed to create account: " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -883,22 +886,16 @@ func completeRegistration(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("Failed to generate access token"),
|
||||
JSON: spec.Unknown("Failed to generate access token"),
|
||||
}
|
||||
}
|
||||
|
||||
if displayName != "" {
|
||||
nameReq := userapi.PerformUpdateDisplayNameRequest{
|
||||
Localpart: username,
|
||||
ServerName: serverName,
|
||||
DisplayName: displayName,
|
||||
}
|
||||
var nameRes userapi.PerformUpdateDisplayNameResponse
|
||||
err = userAPI.SetDisplayName(ctx, &nameReq, &nameRes)
|
||||
_, _, err = userAPI.SetDisplayName(ctx, username, serverName, displayName)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to set display name: " + err.Error()),
|
||||
JSON: spec.Unknown("failed to set display name: " + err.Error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -916,7 +913,7 @@ func completeRegistration(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to create device: " + err.Error()),
|
||||
JSON: spec.Unknown("failed to create device: " + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1000,7 +997,7 @@ func RegisterAvailable(
|
|||
// Squash username to all lowercase letters
|
||||
username = strings.ToLower(username)
|
||||
domain := cfg.Matrix.ServerName
|
||||
host := gomatrixserverlib.ServerName(req.Host)
|
||||
host := spec.ServerName(req.Host)
|
||||
if v := cfg.Matrix.VirtualHostForHTTPHost(host); v != nil {
|
||||
domain = v.ServerName
|
||||
}
|
||||
|
|
@ -1011,7 +1008,7 @@ func RegisterAvailable(
|
|||
if v.ServerName == domain && !v.AllowRegistration {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(
|
||||
JSON: spec.Forbidden(
|
||||
fmt.Sprintf("Registration is not allowed on %q", string(v.ServerName)),
|
||||
),
|
||||
}
|
||||
|
|
@ -1028,7 +1025,7 @@ func RegisterAvailable(
|
|||
if appservice.OwnsNamespaceCoveringUserId(userID) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UserInUse("Desired user ID is reserved by an application service."),
|
||||
JSON: spec.UserInUse("Desired user ID is reserved by an application service."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1041,14 +1038,14 @@ func RegisterAvailable(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: jsonerror.Unknown("failed to check availability:" + err.Error()),
|
||||
JSON: spec.Unknown("failed to check availability:" + err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
if !res.Available {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UserInUse("Desired User ID is already taken."),
|
||||
JSON: spec.UserInUse("Desired User ID is already taken."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1065,7 +1062,7 @@ func handleSharedSecretRegistration(cfg *config.ClientAPI, userAPI userapi.Clien
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.BadJSON(fmt.Sprintf("malformed json: %s", err)),
|
||||
JSON: spec.BadJSON(fmt.Sprintf("malformed json: %s", err)),
|
||||
}
|
||||
}
|
||||
valid, err := sr.IsValidMacLogin(ssrr.Nonce, ssrr.User, ssrr.Password, ssrr.Admin, ssrr.MacBytes)
|
||||
|
|
@ -1075,7 +1072,7 @@ func handleSharedSecretRegistration(cfg *config.ClientAPI, userAPI userapi.Clien
|
|||
if !valid {
|
||||
return util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("bad mac"),
|
||||
JSON: spec.Forbidden("bad mac"),
|
||||
}
|
||||
}
|
||||
// downcase capitals
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/caching"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
|
|
@ -39,6 +38,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/test/testrig"
|
||||
"github.com/matrix-org/dendrite/userapi"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -306,7 +306,7 @@ func Test_register(t *testing.T) {
|
|||
guestsDisabled: true,
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(`Guest registration is disabled on "test"`),
|
||||
JSON: spec.Forbidden(`Guest registration is disabled on "test"`),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -318,7 +318,7 @@ func Test_register(t *testing.T) {
|
|||
loginType: "im.not.known",
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusNotImplemented,
|
||||
JSON: jsonerror.Unknown("unknown/unimplemented auth type"),
|
||||
JSON: spec.Unknown("unknown/unimplemented auth type"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -326,7 +326,7 @@ func Test_register(t *testing.T) {
|
|||
registrationDisabled: true,
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(`Registration is disabled on "test"`),
|
||||
JSON: spec.Forbidden(`Registration is disabled on "test"`),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -344,7 +344,7 @@ func Test_register(t *testing.T) {
|
|||
username: "success",
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UserInUse("Desired user ID is already taken."),
|
||||
JSON: spec.UserInUse("Desired user ID is already taken."),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -361,7 +361,7 @@ func Test_register(t *testing.T) {
|
|||
username: "1337",
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidUsername("Numeric user IDs are reserved"),
|
||||
JSON: spec.InvalidUsername("Numeric user IDs are reserved"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -369,7 +369,7 @@ func Test_register(t *testing.T) {
|
|||
loginType: authtypes.LoginTypeRecaptcha,
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Unknown(ErrCaptchaDisabled.Error()),
|
||||
JSON: spec.Unknown(ErrCaptchaDisabled.Error()),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -378,7 +378,7 @@ func Test_register(t *testing.T) {
|
|||
loginType: authtypes.LoginTypeRecaptcha,
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(ErrMissingResponse.Error()),
|
||||
JSON: spec.BadJSON(ErrMissingResponse.Error()),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -388,7 +388,7 @@ func Test_register(t *testing.T) {
|
|||
captchaBody: `notvalid`,
|
||||
wantResponse: util.JSONResponse{
|
||||
Code: http.StatusUnauthorized,
|
||||
JSON: jsonerror.BadJSON(ErrInvalidCaptcha.Error()),
|
||||
JSON: spec.BadJSON(ErrInvalidCaptcha.Error()),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -402,7 +402,7 @@ func Test_register(t *testing.T) {
|
|||
enableRecaptcha: true,
|
||||
loginType: authtypes.LoginTypeRecaptcha,
|
||||
captchaBody: `i should fail for other reasons`,
|
||||
wantResponse: util.JSONResponse{Code: http.StatusInternalServerError, JSON: jsonerror.InternalServerError()},
|
||||
wantResponse: util.JSONResponse{Code: http.StatusInternalServerError, JSON: spec.InternalServerError{}},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +484,7 @@ func Test_register(t *testing.T) {
|
|||
if !reflect.DeepEqual(r.Flows, cfg.Derived.Registration.Flows) {
|
||||
t.Fatalf("unexpected registration flows: %+v, want %+v", r.Flows, cfg.Derived.Registration.Flows)
|
||||
}
|
||||
case *jsonerror.MatrixError:
|
||||
case spec.MatrixError:
|
||||
if !reflect.DeepEqual(tc.wantResponse, resp) {
|
||||
t.Fatalf("(%s), unexpected response: %+v, want: %+v", tc.name, resp, tc.wantResponse)
|
||||
}
|
||||
|
|
@ -541,7 +541,12 @@ func Test_register(t *testing.T) {
|
|||
resp = Register(req, userAPI, &cfg.ClientAPI)
|
||||
|
||||
switch resp.JSON.(type) {
|
||||
case *jsonerror.MatrixError:
|
||||
case spec.InternalServerError:
|
||||
if !reflect.DeepEqual(tc.wantResponse, resp) {
|
||||
t.Fatalf("unexpected response: %+v, want: %+v", resp, tc.wantResponse)
|
||||
}
|
||||
return
|
||||
case spec.MatrixError:
|
||||
if !reflect.DeepEqual(tc.wantResponse, resp) {
|
||||
t.Fatalf("unexpected response: %+v, want: %+v", resp, tc.wantResponse)
|
||||
}
|
||||
|
|
@ -611,11 +616,9 @@ func TestRegisterUserWithDisplayName(t *testing.T) {
|
|||
|
||||
assert.Equal(t, http.StatusOK, response.Code)
|
||||
|
||||
req := api.QueryProfileRequest{UserID: "@user:server"}
|
||||
var res api.QueryProfileResponse
|
||||
err := userAPI.QueryProfile(processCtx.Context(), &req, &res)
|
||||
profile, err := userAPI.QueryProfile(processCtx.Context(), "@user:server")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedDisplayName, res.DisplayName)
|
||||
assert.Equal(t, expectedDisplayName, profile.DisplayName)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -662,10 +665,8 @@ func TestRegisterAdminUsingSharedSecret(t *testing.T) {
|
|||
)
|
||||
assert.Equal(t, http.StatusOK, response.Code)
|
||||
|
||||
profilReq := api.QueryProfileRequest{UserID: "@alice:server"}
|
||||
var profileRes api.QueryProfileResponse
|
||||
err = userAPI.QueryProfile(processCtx.Context(), &profilReq, &profileRes)
|
||||
profile, err := userAPI.QueryProfile(processCtx.Context(), "@alice:server")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedDisplayName, profileRes.DisplayName)
|
||||
assert.Equal(t, expectedDisplayName, profile.DisplayName)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -39,14 +39,17 @@ func GetTags(
|
|||
if device.UserID != userID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Cannot retrieve another user's tags"),
|
||||
JSON: spec.Forbidden("Cannot retrieve another user's tags"),
|
||||
}
|
||||
}
|
||||
|
||||
tagContent, err := obtainSavedTags(req, userID, roomID, userAPI)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("obtainSavedTags failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -71,7 +74,7 @@ func PutTag(
|
|||
if device.UserID != userID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Cannot modify another user's tags"),
|
||||
JSON: spec.Forbidden("Cannot modify another user's tags"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +86,10 @@ func PutTag(
|
|||
tagContent, err := obtainSavedTags(req, userID, roomID, userAPI)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("obtainSavedTags failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if tagContent.Tags == nil {
|
||||
|
|
@ -93,7 +99,10 @@ func PutTag(
|
|||
|
||||
if err = saveTagData(req, userID, roomID, userAPI, tagContent); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("saveTagData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -118,14 +127,17 @@ func DeleteTag(
|
|||
if device.UserID != userID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Cannot modify another user's tags"),
|
||||
JSON: spec.Forbidden("Cannot modify another user's tags"),
|
||||
}
|
||||
}
|
||||
|
||||
tagContent, err := obtainSavedTags(req, userID, roomID, userAPI)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("obtainSavedTags failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the tag to be deleted exists
|
||||
|
|
@ -141,7 +153,10 @@ func DeleteTag(
|
|||
|
||||
if err = saveTagData(req, userID, roomID, userAPI, tagContent); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("saveTagData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ import (
|
|||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/matrix-org/dendrite/setup/base"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
|
@ -33,7 +34,6 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/auth"
|
||||
clientutil "github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||
"github.com/matrix-org/dendrite/internal/httputil"
|
||||
|
|
@ -56,7 +56,7 @@ func Setup(
|
|||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
userAPI userapi.ClientUserAPI,
|
||||
userDirectoryProvider userapi.QuerySearchProfilesAPI,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
federation fclient.FederationClient,
|
||||
syncProducer *producers.SyncAPIProducer,
|
||||
transactionsCache *transactions.Cache,
|
||||
federationSender federationAPI.ClientFederationAPI,
|
||||
|
|
@ -150,7 +150,7 @@ func Setup(
|
|||
}
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusMethodNotAllowed,
|
||||
JSON: jsonerror.NotFound("unknown method"),
|
||||
JSON: spec.NotFound("unknown method"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
|
||||
|
|
@ -164,13 +164,13 @@ func Setup(
|
|||
|
||||
dendriteAdminRouter.Handle("/admin/evacuateUser/{userID}",
|
||||
httputil.MakeAdminAPI("admin_evacuate_user", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return AdminEvacuateUser(req, cfg, rsAPI)
|
||||
return AdminEvacuateUser(req, rsAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
dendriteAdminRouter.Handle("/admin/purgeRoom/{roomID}",
|
||||
httputil.MakeAdminAPI("admin_purge_room", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return AdminPurgeRoom(req, cfg, device, rsAPI)
|
||||
return AdminPurgeRoom(req, rsAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ func Setup(
|
|||
|
||||
dendriteAdminRouter.Handle("/admin/downloadState/{serverName}/{roomID}",
|
||||
httputil.MakeAdminAPI("admin_download_state", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return AdminDownloadState(req, cfg, device, rsAPI)
|
||||
return AdminDownloadState(req, device, rsAPI)
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
|
|
@ -201,18 +201,13 @@ func Setup(
|
|||
// server notifications
|
||||
if cfg.Matrix.ServerNotices.Enabled {
|
||||
logrus.Info("Enabling server notices at /_synapse/admin/v1/send_server_notice")
|
||||
var serverNotificationSender *userapi.Device
|
||||
var err error
|
||||
notificationSenderOnce := &sync.Once{}
|
||||
serverNotificationSender, err := getSenderDevice(context.Background(), rsAPI, userAPI, cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("unable to get account for sending sending server notices")
|
||||
}
|
||||
|
||||
synapseAdminRouter.Handle("/admin/v1/send_server_notice/{txnID}",
|
||||
httputil.MakeAuthAPI("send_server_notice", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
notificationSenderOnce.Do(func() {
|
||||
serverNotificationSender, err = getSenderDevice(context.Background(), rsAPI, userAPI, cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("unable to get account for sending sending server notices")
|
||||
}
|
||||
})
|
||||
// not specced, but ensure we're rate limiting requests to this endpoint
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
|
|
@ -234,12 +229,6 @@ func Setup(
|
|||
|
||||
synapseAdminRouter.Handle("/admin/v1/send_server_notice",
|
||||
httputil.MakeAuthAPI("send_server_notice", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
notificationSenderOnce.Do(func() {
|
||||
serverNotificationSender, err = getSenderDevice(context.Background(), rsAPI, userAPI, cfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("unable to get account for sending sending server notices")
|
||||
}
|
||||
})
|
||||
// not specced, but ensure we're rate limiting requests to this endpoint
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
|
|
@ -270,7 +259,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
v3mux.Handle("/join/{roomIDOrAlias}",
|
||||
httputil.MakeAuthAPI(gomatrixserverlib.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
httputil.MakeAuthAPI(spec.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
}
|
||||
|
|
@ -290,7 +279,7 @@ func Setup(
|
|||
|
||||
if mscCfg.Enabled("msc2753") {
|
||||
v3mux.Handle("/peek/{roomIDOrAlias}",
|
||||
httputil.MakeAuthAPI(gomatrixserverlib.Peek, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
httputil.MakeAuthAPI(spec.Peek, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
}
|
||||
|
|
@ -310,7 +299,7 @@ func Setup(
|
|||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
v3mux.Handle("/rooms/{roomID}/join",
|
||||
httputil.MakeAuthAPI(gomatrixserverlib.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
httputil.MakeAuthAPI(spec.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
}
|
||||
|
|
@ -680,7 +669,7 @@ func Setup(
|
|||
httputil.MakeAuthAPI("push_rules", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("missing trailing slash"),
|
||||
JSON: spec.InvalidParam("missing trailing slash"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
|
@ -695,7 +684,7 @@ func Setup(
|
|||
httputil.MakeAuthAPI("push_rules", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("scope, kind and rule ID must be specified"),
|
||||
JSON: spec.InvalidParam("scope, kind and rule ID must be specified"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodPut)
|
||||
|
|
@ -714,7 +703,7 @@ func Setup(
|
|||
httputil.MakeAuthAPI("push_rules", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("missing trailing slash after scope"),
|
||||
JSON: spec.InvalidParam("missing trailing slash after scope"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
|
@ -723,7 +712,7 @@ func Setup(
|
|||
httputil.MakeAuthAPI("push_rules", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("kind and rule ID must be specified"),
|
||||
JSON: spec.InvalidParam("kind and rule ID must be specified"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodPut)
|
||||
|
|
@ -742,7 +731,7 @@ func Setup(
|
|||
httputil.MakeAuthAPI("push_rules", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("missing trailing slash after kind"),
|
||||
JSON: spec.InvalidParam("missing trailing slash after kind"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
|
@ -751,7 +740,7 @@ func Setup(
|
|||
httputil.MakeAuthAPI("push_rules", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue("rule ID must be specified"),
|
||||
JSON: spec.InvalidParam("rule ID must be specified"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodPut)
|
||||
|
|
@ -872,6 +861,8 @@ func Setup(
|
|||
// Browsers use the OPTIONS HTTP method to check if the CORS policy allows
|
||||
// PUT requests, so we need to allow this method
|
||||
|
||||
threePIDClient := base.CreateClient(dendriteCfg, nil) // TODO: Move this somewhere else, e.g. pass in as parameter
|
||||
|
||||
v3mux.Handle("/account/3pid",
|
||||
httputil.MakeAuthAPI("account_3pid", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return GetAssociated3PIDs(req, userAPI, device)
|
||||
|
|
@ -880,11 +871,11 @@ func Setup(
|
|||
|
||||
v3mux.Handle("/account/3pid",
|
||||
httputil.MakeAuthAPI("account_3pid", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return CheckAndSave3PIDAssociation(req, userAPI, device, cfg)
|
||||
return CheckAndSave3PIDAssociation(req, userAPI, device, cfg, threePIDClient)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
unstableMux.Handle("/account/3pid/delete",
|
||||
v3mux.Handle("/account/3pid/delete",
|
||||
httputil.MakeAuthAPI("account_3pid", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return Forget3PID(req, userAPI)
|
||||
}),
|
||||
|
|
@ -892,7 +883,7 @@ func Setup(
|
|||
|
||||
v3mux.Handle("/{path:(?:account/3pid|register)}/email/requestToken",
|
||||
httputil.MakeExternalAPI("account_3pid_request_token", func(req *http.Request) util.JSONResponse {
|
||||
return RequestEmailToken(req, userAPI, cfg)
|
||||
return RequestEmailToken(req, userAPI, cfg, threePIDClient)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
|
|
@ -958,7 +949,7 @@ func Setup(
|
|||
// TODO: Allow people to peek into rooms.
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.GuestAccessForbidden("Guest access not implemented"),
|
||||
JSON: spec.GuestAccessForbidden("Guest access not implemented"),
|
||||
}
|
||||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
|
@ -1126,7 +1117,7 @@ func Setup(
|
|||
|
||||
v3mux.Handle("/delete_devices",
|
||||
httputil.MakeAuthAPI("delete_devices", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
return DeleteDevices(req, userAPI, device)
|
||||
return DeleteDevices(req, userInteractiveAuth, userAPI, device)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
|
|
@ -1205,7 +1196,7 @@ func Setup(
|
|||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
}
|
||||
return GetCapabilities(req, rsAPI)
|
||||
return GetCapabilities()
|
||||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
|
|
@ -1263,7 +1254,7 @@ func Setup(
|
|||
if version == "" {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue("version must be specified"),
|
||||
JSON: spec.InvalidParam("version must be specified"),
|
||||
}
|
||||
}
|
||||
var reqBody keyBackupSessionRequest
|
||||
|
|
@ -1284,7 +1275,7 @@ func Setup(
|
|||
if version == "" {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue("version must be specified"),
|
||||
JSON: spec.InvalidParam("version must be specified"),
|
||||
}
|
||||
}
|
||||
roomID := vars["roomID"]
|
||||
|
|
@ -1316,7 +1307,7 @@ func Setup(
|
|||
if version == "" {
|
||||
return util.JSONResponse{
|
||||
Code: 400,
|
||||
JSON: jsonerror.InvalidArgumentValue("version must be specified"),
|
||||
JSON: spec.InvalidParam("version must be specified"),
|
||||
}
|
||||
}
|
||||
var reqBody userapi.KeyBackupSession
|
||||
|
|
@ -1417,7 +1408,7 @@ func Setup(
|
|||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
v3mux.Handle("/rooms/{roomId}/receipt/{receiptType}/{eventId}",
|
||||
httputil.MakeAuthAPI(gomatrixserverlib.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
httputil.MakeAuthAPI(spec.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,16 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/internal/transactions"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
)
|
||||
|
|
@ -75,12 +76,11 @@ func SendEvent(
|
|||
rsAPI api.ClientRoomserverAPI,
|
||||
txnCache *transactions.Cache,
|
||||
) util.JSONResponse {
|
||||
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
|
||||
verRes := api.QueryRoomVersionForRoomResponse{}
|
||||
if err := rsAPI.QueryRoomVersionForRoom(req.Context(), &verReq, &verRes); err != nil {
|
||||
roomVersion, err := rsAPI.QueryRoomVersionForRoom(req.Context(), roomID)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion(err.Error()),
|
||||
JSON: spec.UnsupportedRoomVersion(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ func SendEvent(
|
|||
// If we're sending a membership update, make sure to strip the authorised
|
||||
// via key if it is present, otherwise other servers won't be able to auth
|
||||
// the event if the room is set to the "restricted" join rule.
|
||||
if eventType == gomatrixserverlib.MRoomMember {
|
||||
if eventType == spec.MRoomMember {
|
||||
delete(r, "join_authorised_via_users_server")
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ func SendEvent(
|
|||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidArgumentValue(err.Error()),
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ func SendEvent(
|
|||
timeToGenerateEvent := time.Since(startedGeneratingEvent)
|
||||
|
||||
// validate that the aliases exists
|
||||
if eventType == gomatrixserverlib.MRoomCanonicalAlias && stateKey != nil && *stateKey == "" {
|
||||
if eventType == spec.MRoomCanonicalAlias && stateKey != nil && *stateKey == "" {
|
||||
aliasReq := api.AliasEvent{}
|
||||
if err = json.Unmarshal(e.Content(), &aliasReq); err != nil {
|
||||
return util.ErrorResponse(fmt.Errorf("unable to parse alias event: %w", err))
|
||||
|
|
@ -144,12 +144,15 @@ func SendEvent(
|
|||
if !aliasReq.Valid() {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam("Request contains invalid aliases."),
|
||||
JSON: spec.InvalidParam("Request contains invalid aliases."),
|
||||
}
|
||||
}
|
||||
aliasRes := &api.GetAliasesForRoomIDResponse{}
|
||||
if err = rsAPI.GetAliasesForRoomID(req.Context(), &api.GetAliasesForRoomIDRequest{RoomID: roomID}, aliasRes); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
var found int
|
||||
requestAliases := append(aliasReq.AltAliases, aliasReq.Alias)
|
||||
|
|
@ -164,7 +167,7 @@ func SendEvent(
|
|||
if aliasReq.Alias != "" && found < len(requestAliases) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadAlias("No matching alias found."),
|
||||
JSON: spec.BadAlias("No matching alias found."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -183,8 +186,8 @@ func SendEvent(
|
|||
if err := api.SendEvents(
|
||||
req.Context(), rsAPI,
|
||||
api.KindNew,
|
||||
[]*gomatrixserverlib.HeaderedEvent{
|
||||
e.Headered(verRes.RoomVersion),
|
||||
[]*types.HeaderedEvent{
|
||||
&types.HeaderedEvent{PDU: e},
|
||||
},
|
||||
device.UserDomain(),
|
||||
domain,
|
||||
|
|
@ -193,13 +196,16 @@ func SendEvent(
|
|||
false,
|
||||
); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
timeToSubmitEvent := time.Since(startedSubmittingEvent)
|
||||
util.GetLogger(req.Context()).WithFields(logrus.Fields{
|
||||
"event_id": e.EventID(),
|
||||
"room_id": roomID,
|
||||
"room_version": verRes.RoomVersion,
|
||||
"room_version": roomVersion,
|
||||
}).Info("Sent event to roomserver")
|
||||
|
||||
res := util.JSONResponse{
|
||||
|
|
@ -258,69 +264,77 @@ func generateSendEvent(
|
|||
cfg *config.ClientAPI,
|
||||
rsAPI api.ClientRoomserverAPI,
|
||||
evTime time.Time,
|
||||
) (*gomatrixserverlib.Event, *util.JSONResponse) {
|
||||
) (gomatrixserverlib.PDU, *util.JSONResponse) {
|
||||
// parse the incoming http request
|
||||
userID := device.UserID
|
||||
|
||||
// create the new event and set all the fields we can
|
||||
builder := gomatrixserverlib.EventBuilder{
|
||||
proto := gomatrixserverlib.ProtoEvent{
|
||||
Sender: userID,
|
||||
RoomID: roomID,
|
||||
Type: eventType,
|
||||
StateKey: stateKey,
|
||||
}
|
||||
err := builder.SetContent(r)
|
||||
err := proto.SetContent(r)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
|
||||
resErr := jsonerror.InternalServerError()
|
||||
return nil, &resErr
|
||||
util.GetLogger(ctx).WithError(err).Error("proto.SetContent failed")
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
|
||||
if err != nil {
|
||||
resErr := jsonerror.InternalServerError()
|
||||
return nil, &resErr
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
var queryRes api.QueryLatestEventsAndStateResponse
|
||||
e, err := eventutil.QueryAndBuildEvent(ctx, &builder, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
|
||||
if err == eventutil.ErrRoomNoExists {
|
||||
e, err := eventutil.QueryAndBuildEvent(ctx, &proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
|
||||
switch specificErr := err.(type) {
|
||||
case nil:
|
||||
case eventutil.ErrRoomNoExists:
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
JSON: spec.NotFound("Room does not exist"),
|
||||
}
|
||||
} else if e, ok := err.(gomatrixserverlib.BadJSONError); ok {
|
||||
case gomatrixserverlib.BadJSONError:
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(e.Error()),
|
||||
JSON: spec.BadJSON(specificErr.Error()),
|
||||
}
|
||||
} else if e, ok := err.(gomatrixserverlib.EventValidationError); ok {
|
||||
if e.Code == gomatrixserverlib.EventValidationTooLarge {
|
||||
case gomatrixserverlib.EventValidationError:
|
||||
if specificErr.Code == gomatrixserverlib.EventValidationTooLarge {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusRequestEntityTooLarge,
|
||||
JSON: jsonerror.BadJSON(e.Error()),
|
||||
JSON: spec.BadJSON(specificErr.Error()),
|
||||
}
|
||||
}
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON(e.Error()),
|
||||
JSON: spec.BadJSON(specificErr.Error()),
|
||||
}
|
||||
} else if err != nil {
|
||||
default:
|
||||
util.GetLogger(ctx).WithError(err).Error("eventutil.BuildEvent failed")
|
||||
resErr := jsonerror.InternalServerError()
|
||||
return nil, &resErr
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// check to see if this user can perform this operation
|
||||
stateEvents := make([]*gomatrixserverlib.Event, len(queryRes.StateEvents))
|
||||
stateEvents := make([]gomatrixserverlib.PDU, len(queryRes.StateEvents))
|
||||
for i := range queryRes.StateEvents {
|
||||
stateEvents[i] = queryRes.StateEvents[i].Event
|
||||
stateEvents[i] = queryRes.StateEvents[i].PDU
|
||||
}
|
||||
provider := gomatrixserverlib.NewAuthEvents(stateEvents)
|
||||
if err = gomatrixserverlib.Allowed(e.Event, &provider); err != nil {
|
||||
provider := gomatrixserverlib.NewAuthEvents(gomatrixserverlib.ToPDUs(stateEvents))
|
||||
if err = gomatrixserverlib.Allowed(e.PDU, &provider); err != nil {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(err.Error()), // TODO: Is this error string comprehensible to the client?
|
||||
JSON: spec.Forbidden(err.Error()), // TODO: Is this error string comprehensible to the client?
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,16 +345,16 @@ func generateSendEvent(
|
|||
util.GetLogger(ctx).WithError(err).Error("Cannot unmarshal the event content.")
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Cannot unmarshal the event content."),
|
||||
JSON: spec.BadJSON("Cannot unmarshal the event content."),
|
||||
}
|
||||
}
|
||||
if content["replacement_room"] == e.RoomID() {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.InvalidParam("Cannot send tombstone event that points to the same room."),
|
||||
JSON: spec.InvalidParam("Cannot send tombstone event that points to the same room."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return e.Event, nil
|
||||
return e.PDU, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ import (
|
|||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
"github.com/matrix-org/dendrite/internal/transactions"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// SendToDevice handles PUT /_matrix/client/r0/sendToDevice/{eventType}/{txnId}
|
||||
|
|
@ -53,7 +53,10 @@ func SendToDevice(
|
|||
req.Context(), device.UserID, userID, deviceID, eventType, message,
|
||||
); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("eduProducer.SendToDevice failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,12 +15,13 @@ package routing
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
type typingContentJSON struct {
|
||||
|
|
@ -38,7 +39,7 @@ func SendTyping(
|
|||
if device.UserID != userID {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("Cannot set another user's typing state"),
|
||||
JSON: spec.Forbidden("Cannot set another user's typing state"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +58,10 @@ func SendTyping(
|
|||
|
||||
if err := syncProducer.SendTyping(req.Context(), userID, roomID, r.Typing, r.Timeout); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("eduProducer.Send failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -22,22 +22,22 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/tokens"
|
||||
"github.com/matrix-org/util"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"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"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/internal/transactions"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// Unspecced server notice request
|
||||
|
|
@ -68,7 +68,7 @@ func SendServerNotice(
|
|||
if device.AccountType != userapi.AccountTypeAdmin {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("This API can only be used by admin users."),
|
||||
JSON: spec.Forbidden("This API can only be used by admin users."),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ func SendServerNotice(
|
|||
if !r.valid() {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.BadJSON("Invalid request"),
|
||||
JSON: spec.BadJSON("Invalid request"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +157,6 @@ func SendServerNotice(
|
|||
Visibility: "private",
|
||||
Preset: presetPrivateChat,
|
||||
CreationContent: cc,
|
||||
GuestCanJoin: false,
|
||||
RoomVersion: roomVersion,
|
||||
PowerLevelContentOverride: pl,
|
||||
}
|
||||
|
|
@ -176,7 +175,10 @@ func SendServerNotice(
|
|||
}}
|
||||
if err = saveTagData(req, r.UserID, roomID, userAPI, serverAlertTag); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("saveTagData failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -190,7 +192,10 @@ func SendServerNotice(
|
|||
err := rsAPI.QueryMembershipForUser(ctx, &api.QueryMembershipForUserRequest{UserID: r.UserID, RoomID: roomID}, &membershipRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("unable to query membership for user")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !membershipRes.IsInRoom {
|
||||
// re-invite the user
|
||||
|
|
@ -228,8 +233,8 @@ func SendServerNotice(
|
|||
if err := api.SendEvents(
|
||||
ctx, rsAPI,
|
||||
api.KindNew,
|
||||
[]*gomatrixserverlib.HeaderedEvent{
|
||||
e.Headered(roomVersion),
|
||||
[]*types.HeaderedEvent{
|
||||
&types.HeaderedEvent{PDU: e},
|
||||
},
|
||||
device.UserDomain(),
|
||||
cfgClient.Matrix.ServerName,
|
||||
|
|
@ -238,7 +243,10 @@ func SendServerNotice(
|
|||
false,
|
||||
); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("SendEvents failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
util.GetLogger(ctx).WithFields(logrus.Fields{
|
||||
"event_id": e.EventID(),
|
||||
|
|
@ -295,30 +303,28 @@ func getSenderDevice(
|
|||
}
|
||||
|
||||
// Set the avatarurl for the user
|
||||
avatarRes := &userapi.PerformSetAvatarURLResponse{}
|
||||
if err = userAPI.SetAvatarURL(ctx, &userapi.PerformSetAvatarURLRequest{
|
||||
Localpart: cfg.Matrix.ServerNotices.LocalPart,
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
AvatarURL: cfg.Matrix.ServerNotices.AvatarURL,
|
||||
}, avatarRes); err != nil {
|
||||
profile, avatarChanged, err := userAPI.SetAvatarURL(ctx,
|
||||
cfg.Matrix.ServerNotices.LocalPart,
|
||||
cfg.Matrix.ServerName,
|
||||
cfg.Matrix.ServerNotices.AvatarURL,
|
||||
)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.SetAvatarURL failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
profile := avatarRes.Profile
|
||||
|
||||
// Set the displayname for the user
|
||||
displayNameRes := &userapi.PerformUpdateDisplayNameResponse{}
|
||||
if err = userAPI.SetDisplayName(ctx, &userapi.PerformUpdateDisplayNameRequest{
|
||||
Localpart: cfg.Matrix.ServerNotices.LocalPart,
|
||||
ServerName: cfg.Matrix.ServerName,
|
||||
DisplayName: cfg.Matrix.ServerNotices.DisplayName,
|
||||
}, displayNameRes); err != nil {
|
||||
_, displayNameChanged, err := userAPI.SetDisplayName(ctx,
|
||||
cfg.Matrix.ServerNotices.LocalPart,
|
||||
cfg.Matrix.ServerName,
|
||||
cfg.Matrix.ServerNotices.DisplayName,
|
||||
)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("userAPI.SetDisplayName failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if displayNameRes.Changed {
|
||||
if displayNameChanged {
|
||||
profile.DisplayName = cfg.Matrix.ServerNotices.DisplayName
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +340,7 @@ func getSenderDevice(
|
|||
// We've got an existing account, return the first device of it
|
||||
if len(deviceRes.Devices) > 0 {
|
||||
// If there were changes to the profile, create a new membership event
|
||||
if displayNameRes.Changed || avatarRes.Changed {
|
||||
if displayNameChanged || avatarChanged {
|
||||
_, err = updateProfile(ctx, rsAPI, &deviceRes.Devices[0], profile, accRes.Account.UserID, cfg, time.Now())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -20,16 +20,18 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"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"
|
||||
"github.com/matrix-org/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type stateEventInStateResp struct {
|
||||
gomatrixserverlib.ClientEvent
|
||||
synctypes.ClientEvent
|
||||
PrevContent json.RawMessage `json:"prev_content,omitempty"`
|
||||
ReplacesState string `json:"replaces_state,omitempty"`
|
||||
}
|
||||
|
|
@ -54,12 +56,15 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
|||
StateToFetch: []gomatrixserverlib.StateKeyTuple{},
|
||||
}, &stateRes); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("queryAPI.QueryLatestEventsAndState failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !stateRes.RoomExists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden("room does not exist"),
|
||||
JSON: spec.Forbidden("room does not exist"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,11 +72,14 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
|||
// that marks the room as world-readable. If we don't then we assume that
|
||||
// the room is not world-readable.
|
||||
for _, ev := range stateRes.StateEvents {
|
||||
if ev.Type() == gomatrixserverlib.MRoomHistoryVisibility {
|
||||
if ev.Type() == spec.MRoomHistoryVisibility {
|
||||
content := map[string]string{}
|
||||
if err := json.Unmarshal(ev.Content(), &content); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for history visibility failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if visibility, ok := content["history_visibility"]; ok {
|
||||
worldReadable = visibility == "world_readable"
|
||||
|
|
@ -97,14 +105,17 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
|||
}, &membershipRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to QueryMembershipForUser")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
// If the user has never been in the room then stop at this point.
|
||||
// We won't tell the user about a room they have never joined.
|
||||
if !membershipRes.HasBeenInRoom {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(fmt.Sprintf("Unknown room %q or user %q has never joined this room", roomID, device.UserID)),
|
||||
JSON: spec.Forbidden(fmt.Sprintf("Unknown room %q or user %q has never joined this room", roomID, device.UserID)),
|
||||
}
|
||||
}
|
||||
// Otherwise, if the user has been in the room, whether or not we
|
||||
|
|
@ -122,7 +133,7 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
|||
"state_at_event": !wantLatestState,
|
||||
}).Info("Fetching all state")
|
||||
|
||||
stateEvents := []gomatrixserverlib.ClientEvent{}
|
||||
stateEvents := []synctypes.ClientEvent{}
|
||||
if wantLatestState {
|
||||
// If we are happy to use the latest state, either because the user is
|
||||
// still in the room, or because the room is world-readable, then just
|
||||
|
|
@ -131,7 +142,7 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
|||
for _, ev := range stateRes.StateEvents {
|
||||
stateEvents = append(
|
||||
stateEvents,
|
||||
gomatrixserverlib.HeaderedToClientEvent(ev, gomatrixserverlib.FormatAll),
|
||||
synctypes.ToClientEvent(ev, synctypes.FormatAll),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -145,12 +156,15 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a
|
|||
}, &stateAfterRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to QueryMembershipForUser")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
for _, ev := range stateAfterRes.StateEvents {
|
||||
stateEvents = append(
|
||||
stateEvents,
|
||||
gomatrixserverlib.HeaderedToClientEvent(ev, gomatrixserverlib.FormatAll),
|
||||
synctypes.ToClientEvent(ev, synctypes.FormatAll),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -184,9 +198,9 @@ func OnIncomingStateTypeRequest(
|
|||
StateKey: stateKey,
|
||||
},
|
||||
}
|
||||
if evType != gomatrixserverlib.MRoomHistoryVisibility && stateKey != "" {
|
||||
if evType != spec.MRoomHistoryVisibility && stateKey != "" {
|
||||
stateToFetch = append(stateToFetch, gomatrixserverlib.StateKeyTuple{
|
||||
EventType: gomatrixserverlib.MRoomHistoryVisibility,
|
||||
EventType: spec.MRoomHistoryVisibility,
|
||||
StateKey: "",
|
||||
})
|
||||
}
|
||||
|
|
@ -200,18 +214,24 @@ func OnIncomingStateTypeRequest(
|
|||
StateToFetch: stateToFetch,
|
||||
}, &stateRes); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("queryAPI.QueryLatestEventsAndState failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// Look at the room state and see if we have a history visibility event
|
||||
// that marks the room as world-readable. If we don't then we assume that
|
||||
// the room is not world-readable.
|
||||
for _, ev := range stateRes.StateEvents {
|
||||
if ev.Type() == gomatrixserverlib.MRoomHistoryVisibility {
|
||||
if ev.Type() == spec.MRoomHistoryVisibility {
|
||||
content := map[string]string{}
|
||||
if err := json.Unmarshal(ev.Content(), &content); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for history visibility failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if visibility, ok := content["history_visibility"]; ok {
|
||||
worldReadable = visibility == "world_readable"
|
||||
|
|
@ -237,14 +257,17 @@ func OnIncomingStateTypeRequest(
|
|||
}, &membershipRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to QueryMembershipForUser")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
// If the user has never been in the room then stop at this point.
|
||||
// We won't tell the user about a room they have never joined.
|
||||
if !membershipRes.HasBeenInRoom || membershipRes.Membership == gomatrixserverlib.Ban {
|
||||
if !membershipRes.HasBeenInRoom || membershipRes.Membership == spec.Ban {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(fmt.Sprintf("Unknown room %q or user %q has never joined this room", roomID, device.UserID)),
|
||||
JSON: spec.Forbidden(fmt.Sprintf("Unknown room %q or user %q has never joined this room", roomID, device.UserID)),
|
||||
}
|
||||
}
|
||||
// Otherwise, if the user has been in the room, whether or not we
|
||||
|
|
@ -264,7 +287,7 @@ func OnIncomingStateTypeRequest(
|
|||
"state_at_event": !wantLatestState,
|
||||
}).Info("Fetching state")
|
||||
|
||||
var event *gomatrixserverlib.HeaderedEvent
|
||||
var event *types.HeaderedEvent
|
||||
if wantLatestState {
|
||||
// If we are happy to use the latest state, either because the user is
|
||||
// still in the room, or because the room is world-readable, then just
|
||||
|
|
@ -292,7 +315,10 @@ func OnIncomingStateTypeRequest(
|
|||
}, &stateAfterRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("Failed to QueryMembershipForUser")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if len(stateAfterRes.StateEvents) > 0 {
|
||||
event = stateAfterRes.StateEvents[0]
|
||||
|
|
@ -304,12 +330,12 @@ func OnIncomingStateTypeRequest(
|
|||
if event == nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound(fmt.Sprintf("Cannot find state event for %q", evType)),
|
||||
JSON: spec.NotFound(fmt.Sprintf("Cannot find state event for %q", evType)),
|
||||
}
|
||||
}
|
||||
|
||||
stateEvent := stateEventInStateResp{
|
||||
ClientEvent: gomatrixserverlib.HeaderedToClientEvent(event, gomatrixserverlib.FormatAll),
|
||||
ClientEvent: synctypes.ToClientEvent(event, synctypes.FormatAll),
|
||||
}
|
||||
|
||||
var res interface{}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ import (
|
|||
"github.com/matrix-org/util"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// Protocols implements
|
||||
|
|
@ -33,13 +33,16 @@ func Protocols(req *http.Request, asAPI appserviceAPI.AppServiceInternalAPI, dev
|
|||
resp := &appserviceAPI.ProtocolResponse{}
|
||||
|
||||
if err := asAPI.Protocols(req.Context(), &appserviceAPI.ProtocolRequest{Protocol: protocol}, resp); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !resp.Exists {
|
||||
if protocol != "" {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("The protocol is unknown."),
|
||||
JSON: spec.NotFound("The protocol is unknown."),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -71,12 +74,15 @@ func User(req *http.Request, asAPI appserviceAPI.AppServiceInternalAPI, device *
|
|||
Protocol: protocol,
|
||||
Params: params.Encode(),
|
||||
}, resp); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !resp.Exists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("The Matrix User ID was not found"),
|
||||
JSON: spec.NotFound("The Matrix User ID was not found"),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
@ -97,12 +103,15 @@ func Location(req *http.Request, asAPI appserviceAPI.AppServiceInternalAPI, devi
|
|||
Protocol: protocol,
|
||||
Params: params.Encode(),
|
||||
}, resp); err != nil {
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !resp.Exists {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("No portal rooms were found."),
|
||||
JSON: spec.NotFound("No portal rooms were found."),
|
||||
}
|
||||
}
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/clientapi/threepid"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
userdb "github.com/matrix-org/dendrite/userapi/storage"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/util"
|
||||
|
|
@ -33,7 +34,7 @@ type reqTokenResponse struct {
|
|||
SID string `json:"sid"`
|
||||
}
|
||||
|
||||
type threePIDsResponse struct {
|
||||
type ThreePIDsResponse struct {
|
||||
ThreePIDs []authtypes.ThreePID `json:"threepids"`
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ type threePIDsResponse struct {
|
|||
//
|
||||
// POST /account/3pid/email/requestToken
|
||||
// POST /register/email/requestToken
|
||||
func RequestEmailToken(req *http.Request, threePIDAPI api.ClientUserAPI, cfg *config.ClientAPI) util.JSONResponse {
|
||||
func RequestEmailToken(req *http.Request, threePIDAPI api.ClientUserAPI, cfg *config.ClientAPI, client *fclient.Client) util.JSONResponse {
|
||||
var body threepid.EmailAssociationRequest
|
||||
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {
|
||||
return *reqErr
|
||||
|
|
@ -59,28 +60,37 @@ func RequestEmailToken(req *http.Request, threePIDAPI api.ClientUserAPI, cfg *co
|
|||
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threePIDAPI.QueryLocalpartForThreePID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if len(res.Localpart) > 0 {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MatrixError{
|
||||
ErrCode: "M_THREEPID_IN_USE",
|
||||
JSON: spec.MatrixError{
|
||||
ErrCode: spec.ErrorThreePIDInUse,
|
||||
Err: userdb.Err3PIDInUse.Error(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
resp.SID, err = threepid.CreateSession(req.Context(), body, cfg)
|
||||
if err == threepid.ErrNotTrusted {
|
||||
resp.SID, err = threepid.CreateSession(req.Context(), body, cfg, client)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
case threepid.ErrNotTrusted:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CreateSession failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotTrusted(body.IDServer),
|
||||
JSON: spec.NotTrusted(body.IDServer),
|
||||
}
|
||||
} else if err != nil {
|
||||
default:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CreateSession failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -92,7 +102,7 @@ func RequestEmailToken(req *http.Request, threePIDAPI api.ClientUserAPI, cfg *co
|
|||
// CheckAndSave3PIDAssociation implements POST /account/3pid
|
||||
func CheckAndSave3PIDAssociation(
|
||||
req *http.Request, threePIDAPI api.ClientUserAPI, device *api.Device,
|
||||
cfg *config.ClientAPI,
|
||||
cfg *config.ClientAPI, client *fclient.Client,
|
||||
) util.JSONResponse {
|
||||
var body threepid.EmailAssociationCheckRequest
|
||||
if reqErr := httputil.UnmarshalJSONRequest(req, &body); reqErr != nil {
|
||||
|
|
@ -100,22 +110,28 @@ func CheckAndSave3PIDAssociation(
|
|||
}
|
||||
|
||||
// Check if the association has been validated
|
||||
verified, address, medium, err := threepid.CheckAssociation(req.Context(), body.Creds, cfg)
|
||||
if err == threepid.ErrNotTrusted {
|
||||
verified, address, medium, err := threepid.CheckAssociation(req.Context(), body.Creds, cfg, client)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
case threepid.ErrNotTrusted:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAssociation failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotTrusted(body.Creds.IDServer),
|
||||
JSON: spec.NotTrusted(body.Creds.IDServer),
|
||||
}
|
||||
} else if err != nil {
|
||||
default:
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.CheckAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if !verified {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.MatrixError{
|
||||
ErrCode: "M_THREEPID_AUTH_FAILED",
|
||||
JSON: spec.MatrixError{
|
||||
ErrCode: spec.ErrorThreePIDAuthFailed,
|
||||
Err: "Failed to auth 3pid",
|
||||
},
|
||||
}
|
||||
|
|
@ -123,15 +139,13 @@ func CheckAndSave3PIDAssociation(
|
|||
|
||||
if body.Bind {
|
||||
// Publish the association on the identity server if requested
|
||||
err = threepid.PublishAssociation(body.Creds, device.UserID, cfg)
|
||||
if err == threepid.ErrNotTrusted {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.NotTrusted(body.Creds.IDServer),
|
||||
}
|
||||
} else if err != nil {
|
||||
err = threepid.PublishAssociation(req.Context(), body.Creds, device.UserID, cfg, client)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepid.PublishAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +153,10 @@ func CheckAndSave3PIDAssociation(
|
|||
localpart, domain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
if err = threePIDAPI.PerformSaveThreePIDAssociation(req.Context(), &api.PerformSaveThreePIDAssociationRequest{
|
||||
|
|
@ -149,7 +166,10 @@ func CheckAndSave3PIDAssociation(
|
|||
Medium: medium,
|
||||
}, &struct{}{}); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threePIDAPI.PerformSaveThreePIDAssociation failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
@ -165,7 +185,10 @@ func GetAssociated3PIDs(
|
|||
localpart, domain, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
res := &api.QueryThreePIDsForLocalpartResponse{}
|
||||
|
|
@ -175,12 +198,15 @@ func GetAssociated3PIDs(
|
|||
}, res)
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepidAPI.QueryThreePIDsForLocalpart failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: threePIDsResponse{res.ThreePIDs},
|
||||
JSON: ThreePIDsResponse{res.ThreePIDs},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,9 +217,15 @@ func Forget3PID(req *http.Request, threepidAPI api.ClientUserAPI) util.JSONRespo
|
|||
return *reqErr
|
||||
}
|
||||
|
||||
if err := threepidAPI.PerformForgetThreePID(req.Context(), &api.PerformForgetThreePIDRequest{}, &struct{}{}); err != nil {
|
||||
if err := threepidAPI.PerformForgetThreePID(req.Context(), &api.PerformForgetThreePIDRequest{
|
||||
ThreePID: body.Address,
|
||||
Medium: body.Medium,
|
||||
}, &struct{}{}); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("threepidAPI.PerformForgetThreePID failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
|
|
|
|||
|
|
@ -15,16 +15,18 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/version"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -53,42 +55,35 @@ func UpgradeRoom(
|
|||
if _, err := version.SupportedRoomVersion(gomatrixserverlib.RoomVersion(r.NewVersion)); err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: jsonerror.UnsupportedRoomVersion("This server does not support that room version"),
|
||||
JSON: spec.UnsupportedRoomVersion("This server does not support that room version"),
|
||||
}
|
||||
}
|
||||
|
||||
upgradeReq := roomserverAPI.PerformRoomUpgradeRequest{
|
||||
UserID: device.UserID,
|
||||
RoomID: roomID,
|
||||
RoomVersion: gomatrixserverlib.RoomVersion(r.NewVersion),
|
||||
}
|
||||
upgradeResp := roomserverAPI.PerformRoomUpgradeResponse{}
|
||||
|
||||
if err := rsAPI.PerformRoomUpgrade(req.Context(), &upgradeReq, &upgradeResp); err != nil {
|
||||
return jsonerror.InternalAPIError(req.Context(), err)
|
||||
}
|
||||
|
||||
if upgradeResp.Error != nil {
|
||||
if upgradeResp.Error.Code == roomserverAPI.PerformErrorNoRoom {
|
||||
newRoomID, err := rsAPI.PerformRoomUpgrade(req.Context(), roomID, device.UserID, gomatrixserverlib.RoomVersion(r.NewVersion))
|
||||
switch e := err.(type) {
|
||||
case nil:
|
||||
case roomserverAPI.ErrNotAllowed:
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden(e.Error()),
|
||||
}
|
||||
default:
|
||||
if errors.Is(err, eventutil.ErrRoomNoExists{}) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusNotFound,
|
||||
JSON: jsonerror.NotFound("Room does not exist"),
|
||||
JSON: spec.NotFound("Room does not exist"),
|
||||
}
|
||||
} else if upgradeResp.Error.Code == roomserverAPI.PerformErrorNotAllowed {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: jsonerror.Forbidden(upgradeResp.Error.Msg),
|
||||
}
|
||||
} else {
|
||||
return jsonerror.InternalServerError()
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
JSON: upgradeRoomResponse{
|
||||
ReplacementRoom: upgradeResp.NewRoomID,
|
||||
ReplacementRoom: newRoomID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import (
|
|||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
|
|
@ -41,8 +43,8 @@ func SearchUserDirectory(
|
|||
provider userapi.QuerySearchProfilesAPI,
|
||||
searchString string,
|
||||
limit int,
|
||||
federation *gomatrixserverlib.FederationClient,
|
||||
localServerName gomatrixserverlib.ServerName,
|
||||
federation fclient.FederationClient,
|
||||
localServerName spec.ServerName,
|
||||
) util.JSONResponse {
|
||||
if limit < 10 {
|
||||
limit = 10
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ import (
|
|||
"github.com/matrix-org/gomatrix"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// RequestTurnServer implements:
|
||||
|
|
@ -60,7 +60,10 @@ func RequestTurnServer(req *http.Request, device *api.Device, cfg *config.Client
|
|||
|
||||
if err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("mac.Write failed")
|
||||
return jsonerror.InternalServerError()
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
resp.Password = base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ import (
|
|||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// MembershipRequest represents the body of an incoming POST request
|
||||
|
|
@ -62,14 +64,34 @@ type idServerStoreInviteResponse struct {
|
|||
}
|
||||
|
||||
var (
|
||||
// ErrMissingParameter is the error raised if a request for 3PID invite has
|
||||
// an incomplete body
|
||||
ErrMissingParameter = errors.New("'address', 'id_server' and 'medium' must all be supplied")
|
||||
// ErrNotTrusted is the error raised if an identity server isn't in the list
|
||||
// of trusted servers in the configuration file.
|
||||
ErrNotTrusted = errors.New("untrusted server")
|
||||
errMissingParameter = fmt.Errorf("'address', 'id_server' and 'medium' must all be supplied")
|
||||
errNotTrusted = fmt.Errorf("untrusted server")
|
||||
)
|
||||
|
||||
// ErrMissingParameter is the error raised if a request for 3PID invite has
|
||||
// an incomplete body
|
||||
type ErrMissingParameter struct{}
|
||||
|
||||
func (e ErrMissingParameter) Error() string {
|
||||
return errMissingParameter.Error()
|
||||
}
|
||||
|
||||
func (e ErrMissingParameter) Unwrap() error {
|
||||
return errMissingParameter
|
||||
}
|
||||
|
||||
// ErrNotTrusted is the error raised if an identity server isn't in the list
|
||||
// of trusted servers in the configuration file.
|
||||
type ErrNotTrusted struct{}
|
||||
|
||||
func (e ErrNotTrusted) Error() string {
|
||||
return errNotTrusted.Error()
|
||||
}
|
||||
|
||||
func (e ErrNotTrusted) Unwrap() error {
|
||||
return errNotTrusted
|
||||
}
|
||||
|
||||
// CheckAndProcessInvite analyses the body of an incoming membership request.
|
||||
// If the fields relative to a third-party-invite are all supplied, lookups the
|
||||
// matching Matrix ID from the given identity server. If no Matrix ID is
|
||||
|
|
@ -97,7 +119,7 @@ func CheckAndProcessInvite(
|
|||
} else if body.Address == "" || body.IDServer == "" || body.Medium == "" {
|
||||
// If at least one of the 3PID-specific fields is supplied but not all
|
||||
// of them, return an error
|
||||
err = ErrMissingParameter
|
||||
err = ErrMissingParameter{}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -209,24 +231,17 @@ func queryIDServerStoreInvite(
|
|||
body *MembershipRequest, roomID string,
|
||||
) (*idServerStoreInviteResponse, error) {
|
||||
// Retrieve the sender's profile to get their display name
|
||||
localpart, serverName, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
_, serverName, err := gomatrixserverlib.SplitID('@', device.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var profile *authtypes.Profile
|
||||
if cfg.Matrix.IsLocalServerName(serverName) {
|
||||
res := &userapi.QueryProfileResponse{}
|
||||
err = userAPI.QueryProfile(ctx, &userapi.QueryProfileRequest{UserID: device.UserID}, res)
|
||||
profile, err = userAPI.QueryProfile(ctx, device.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
profile = &authtypes.Profile{
|
||||
Localpart: localpart,
|
||||
DisplayName: res.DisplayName,
|
||||
AvatarURL: res.AvatarURL,
|
||||
}
|
||||
|
||||
} else {
|
||||
profile = &authtypes.Profile{}
|
||||
}
|
||||
|
|
@ -285,7 +300,7 @@ func queryIDServerPubKey(ctx context.Context, idServerName string, keyID string)
|
|||
}
|
||||
|
||||
var pubKeyRes struct {
|
||||
PublicKey gomatrixserverlib.Base64Bytes `json:"public_key"`
|
||||
PublicKey spec.Base64Bytes `json:"public_key"`
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
|
|
@ -340,7 +355,7 @@ func emit3PIDInviteEvent(
|
|||
rsAPI api.ClientRoomserverAPI,
|
||||
evTime time.Time,
|
||||
) error {
|
||||
builder := &gomatrixserverlib.EventBuilder{
|
||||
proto := &gomatrixserverlib.ProtoEvent{
|
||||
Sender: device.UserID,
|
||||
RoomID: roomID,
|
||||
Type: "m.room.third_party_invite",
|
||||
|
|
@ -355,7 +370,7 @@ func emit3PIDInviteEvent(
|
|||
PublicKeys: res.PublicKeys,
|
||||
}
|
||||
|
||||
if err := builder.SetContent(content); err != nil {
|
||||
if err := proto.SetContent(content); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +380,7 @@ func emit3PIDInviteEvent(
|
|||
}
|
||||
|
||||
queryRes := api.QueryLatestEventsAndStateResponse{}
|
||||
event, err := eventutil.QueryAndBuildEvent(ctx, builder, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
|
||||
event, err := eventutil.QueryAndBuildEvent(ctx, proto, cfg.Matrix, identity, evTime, rsAPI, &queryRes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -373,8 +388,8 @@ func emit3PIDInviteEvent(
|
|||
return api.SendEvents(
|
||||
ctx, rsAPI,
|
||||
api.KindNew,
|
||||
[]*gomatrixserverlib.HeaderedEvent{
|
||||
event.Headered(queryRes.RoomVersion),
|
||||
[]*types.HeaderedEvent{
|
||||
event,
|
||||
},
|
||||
device.UserDomain(),
|
||||
cfg.Matrix.ServerName,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// EmailAssociationRequest represents the request defined at https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-register-email-requesttoken
|
||||
|
|
@ -37,7 +39,7 @@ type EmailAssociationRequest struct {
|
|||
|
||||
// EmailAssociationCheckRequest represents the request defined at https://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-account-3pid
|
||||
type EmailAssociationCheckRequest struct {
|
||||
Creds Credentials `json:"threePidCreds"`
|
||||
Creds Credentials `json:"three_pid_creds"`
|
||||
Bind bool `json:"bind"`
|
||||
}
|
||||
|
||||
|
|
@ -48,12 +50,16 @@ type Credentials struct {
|
|||
Secret string `json:"client_secret"`
|
||||
}
|
||||
|
||||
type SID struct {
|
||||
SID string `json:"sid"`
|
||||
}
|
||||
|
||||
// CreateSession creates a session on an identity server.
|
||||
// Returns the session's ID.
|
||||
// Returns an error if there was a problem sending the request or decoding the
|
||||
// response, or if the identity server responded with a non-OK status.
|
||||
func CreateSession(
|
||||
ctx context.Context, req EmailAssociationRequest, cfg *config.ClientAPI,
|
||||
ctx context.Context, req EmailAssociationRequest, cfg *config.ClientAPI, client *fclient.Client,
|
||||
) (string, error) {
|
||||
if err := isTrusted(req.IDServer, cfg); err != nil {
|
||||
return "", err
|
||||
|
|
@ -73,8 +79,7 @@ func CreateSession(
|
|||
}
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
client := http.Client{}
|
||||
resp, err := client.Do(request.WithContext(ctx))
|
||||
resp, err := client.DoHTTPRequest(ctx, request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -85,14 +90,20 @@ func CreateSession(
|
|||
}
|
||||
|
||||
// Extract the SID from the response and return it
|
||||
var sid struct {
|
||||
SID string `json:"sid"`
|
||||
}
|
||||
var sid SID
|
||||
err = json.NewDecoder(resp.Body).Decode(&sid)
|
||||
|
||||
return sid.SID, err
|
||||
}
|
||||
|
||||
type GetValidatedResponse struct {
|
||||
Medium string `json:"medium"`
|
||||
ValidatedAt int64 `json:"validated_at"`
|
||||
Address string `json:"address"`
|
||||
ErrCode string `json:"errcode"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// CheckAssociation checks the status of an ongoing association validation on an
|
||||
// identity server.
|
||||
// Returns a boolean set to true if the association has been validated, false if not.
|
||||
|
|
@ -102,6 +113,7 @@ func CreateSession(
|
|||
// response, or if the identity server responded with a non-OK status.
|
||||
func CheckAssociation(
|
||||
ctx context.Context, creds Credentials, cfg *config.ClientAPI,
|
||||
client *fclient.Client,
|
||||
) (bool, string, string, error) {
|
||||
if err := isTrusted(creds.IDServer, cfg); err != nil {
|
||||
return false, "", "", err
|
||||
|
|
@ -112,24 +124,17 @@ func CheckAssociation(
|
|||
if err != nil {
|
||||
return false, "", "", err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
|
||||
resp, err := client.DoHTTPRequest(ctx, req)
|
||||
if err != nil {
|
||||
return false, "", "", err
|
||||
}
|
||||
|
||||
var respBody struct {
|
||||
Medium string `json:"medium"`
|
||||
ValidatedAt int64 `json:"validated_at"`
|
||||
Address string `json:"address"`
|
||||
ErrCode string `json:"errcode"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
var respBody GetValidatedResponse
|
||||
if err = json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
|
||||
return false, "", "", err
|
||||
}
|
||||
|
||||
if respBody.ErrCode == "M_SESSION_NOT_VALIDATED" {
|
||||
if respBody.ErrCode == string(spec.ErrorSessionNotValidated) {
|
||||
return false, "", "", nil
|
||||
} else if len(respBody.ErrCode) > 0 {
|
||||
return false, "", "", errors.New(respBody.Error)
|
||||
|
|
@ -142,7 +147,7 @@ func CheckAssociation(
|
|||
// identifier and a Matrix ID.
|
||||
// Returns an error if there was a problem sending the request or decoding the
|
||||
// response, or if the identity server responded with a non-OK status.
|
||||
func PublishAssociation(creds Credentials, userID string, cfg *config.ClientAPI) error {
|
||||
func PublishAssociation(ctx context.Context, creds Credentials, userID string, cfg *config.ClientAPI, client *fclient.Client) error {
|
||||
if err := isTrusted(creds.IDServer, cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -160,8 +165,7 @@ func PublishAssociation(creds Credentials, userID string, cfg *config.ClientAPI)
|
|||
}
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
client := http.Client{}
|
||||
resp, err := client.Do(request)
|
||||
resp, err := client.DoHTTPRequest(ctx, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -183,5 +187,5 @@ func isTrusted(idServer string, cfg *config.ClientAPI) error {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
return ErrNotTrusted
|
||||
return ErrNotTrusted{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
// ParseUsernameParam extracts localpart from usernameParam.
|
||||
// usernameParam can either be a user ID or just the localpart/username.
|
||||
// If serverName is passed, it is verified against the domain obtained from usernameParam (if present)
|
||||
// Returns error in case of invalid usernameParam.
|
||||
func ParseUsernameParam(usernameParam string, cfg *config.Global) (string, gomatrixserverlib.ServerName, error) {
|
||||
func ParseUsernameParam(usernameParam string, cfg *config.Global) (string, spec.ServerName, error) {
|
||||
localpart := usernameParam
|
||||
|
||||
if strings.HasPrefix(usernameParam, "@") {
|
||||
|
|
@ -45,6 +46,6 @@ func ParseUsernameParam(usernameParam string, cfg *config.Global) (string, gomat
|
|||
}
|
||||
|
||||
// MakeUserID generates user ID from localpart & server name
|
||||
func MakeUserID(localpart string, server gomatrixserverlib.ServerName) string {
|
||||
func MakeUserID(localpart string, server spec.ServerName) string {
|
||||
return fmt.Sprintf("@%s:%s", localpart, string(server))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,21 +16,22 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
var (
|
||||
localpart = "somelocalpart"
|
||||
serverName gomatrixserverlib.ServerName = "someservername"
|
||||
invalidServerName gomatrixserverlib.ServerName = "invalidservername"
|
||||
goodUserID = "@" + localpart + ":" + string(serverName)
|
||||
badUserID = "@bad:user:name@noservername:"
|
||||
localpart = "somelocalpart"
|
||||
serverName spec.ServerName = "someservername"
|
||||
invalidServerName spec.ServerName = "invalidservername"
|
||||
goodUserID = "@" + localpart + ":" + string(serverName)
|
||||
badUserID = "@bad:user:name@noservername:"
|
||||
)
|
||||
|
||||
// TestGoodUserID checks that correct localpart is returned for a valid user ID.
|
||||
func TestGoodUserID(t *testing.T) {
|
||||
cfg := &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: serverName,
|
||||
},
|
||||
}
|
||||
|
|
@ -49,7 +50,7 @@ func TestGoodUserID(t *testing.T) {
|
|||
// TestWithLocalpartOnly checks that localpart is returned when usernameParam contains only localpart.
|
||||
func TestWithLocalpartOnly(t *testing.T) {
|
||||
cfg := &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: serverName,
|
||||
},
|
||||
}
|
||||
|
|
@ -68,7 +69,7 @@ func TestWithLocalpartOnly(t *testing.T) {
|
|||
// TestIncorrectDomain checks for error when there's server name mismatch.
|
||||
func TestIncorrectDomain(t *testing.T) {
|
||||
cfg := &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: invalidServerName,
|
||||
},
|
||||
}
|
||||
|
|
@ -83,7 +84,7 @@ func TestIncorrectDomain(t *testing.T) {
|
|||
// TestBadUserID checks that ParseUsernameParam fails for invalid user ID
|
||||
func TestBadUserID(t *testing.T) {
|
||||
cfg := &config.Global{
|
||||
SigningIdentity: gomatrixserverlib.SigningIdentity{
|
||||
SigningIdentity: fclient.SigningIdentity{
|
||||
ServerName: serverName,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"nhooyr.io/websocket"
|
||||
|
||||
pineconeRouter "github.com/matrix-org/pinecone/router"
|
||||
|
|
@ -91,17 +91,17 @@ func createTransport(s *pineconeSessions.Sessions) *http.Transport {
|
|||
|
||||
func CreateClient(
|
||||
s *pineconeSessions.Sessions,
|
||||
) *gomatrixserverlib.Client {
|
||||
return gomatrixserverlib.NewClient(
|
||||
gomatrixserverlib.WithTransport(createTransport(s)),
|
||||
) *fclient.Client {
|
||||
return fclient.NewClient(
|
||||
fclient.WithTransport(createTransport(s)),
|
||||
)
|
||||
}
|
||||
|
||||
func CreateFederationClient(
|
||||
cfg *config.Dendrite, s *pineconeSessions.Sessions,
|
||||
) *gomatrixserverlib.FederationClient {
|
||||
return gomatrixserverlib.NewFederationClient(
|
||||
) fclient.FederationClient {
|
||||
return fclient.NewFederationClient(
|
||||
cfg.Global.SigningIdentities(),
|
||||
gomatrixserverlib.WithTransport(createTransport(s)),
|
||||
fclient.WithTransport(createTransport(s)),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
package defaults
|
||||
|
||||
import "github.com/matrix-org/gomatrixserverlib"
|
||||
import "github.com/matrix-org/gomatrixserverlib/spec"
|
||||
|
||||
var DefaultServerNames = map[gomatrixserverlib.ServerName]struct{}{
|
||||
var DefaultServerNames = map[spec.ServerName]struct{}{
|
||||
"3bf0258d23c60952639cc4c69c71d1508a7d43a0475d9000ff900a1848411ec7": {},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/process"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
pineconeRouter "github.com/matrix-org/pinecone/router"
|
||||
|
|
@ -77,7 +78,7 @@ func main() {
|
|||
cfg = monolith.GenerateDefaultConfig(sk, *instanceDir, *instanceDir, *instanceName)
|
||||
}
|
||||
|
||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.ServerName = spec.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||
|
||||
p2pMonolith := monolith.P2PMonolith{}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import (
|
|||
"github.com/matrix-org/dendrite/setup/process"
|
||||
"github.com/matrix-org/dendrite/userapi"
|
||||
userAPI "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
pineconeConnections "github.com/matrix-org/pinecone/connections"
|
||||
|
|
@ -347,7 +347,7 @@ func (p *P2PMonolith) startEventHandler() {
|
|||
eLog := logrus.WithField("pinecone", "events")
|
||||
p.RelayRetriever = relay.NewRelayServerRetriever(
|
||||
context.Background(),
|
||||
gomatrixserverlib.ServerName(p.Router.PublicKey().String()),
|
||||
spec.ServerName(p.Router.PublicKey().String()),
|
||||
p.dendrite.FederationAPI,
|
||||
p.dendrite.RelayAPI,
|
||||
stopRelayServerSync,
|
||||
|
|
@ -373,7 +373,7 @@ func (p *P2PMonolith) startEventHandler() {
|
|||
// eLog.Info("Broadcast received from: ", e.PeerID)
|
||||
|
||||
req := &federationAPI.PerformWakeupServersRequest{
|
||||
ServerNames: []gomatrixserverlib.ServerName{gomatrixserverlib.ServerName(e.PeerID)},
|
||||
ServerNames: []spec.ServerName{spec.ServerName(e.PeerID)},
|
||||
}
|
||||
res := &federationAPI.PerformWakeupServersResponse{}
|
||||
if err := p.dendrite.FederationAPI.PerformWakeupServers(p.ProcessCtx.Context(), req, res); err != nil {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||
relayServerAPI "github.com/matrix-org/dendrite/relayapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.uber.org/atomic"
|
||||
)
|
||||
|
|
@ -32,10 +32,10 @@ const (
|
|||
|
||||
type RelayServerRetriever struct {
|
||||
ctx context.Context
|
||||
serverName gomatrixserverlib.ServerName
|
||||
serverName spec.ServerName
|
||||
federationAPI federationAPI.FederationInternalAPI
|
||||
relayAPI relayServerAPI.RelayInternalAPI
|
||||
relayServersQueried map[gomatrixserverlib.ServerName]bool
|
||||
relayServersQueried map[spec.ServerName]bool
|
||||
queriedServersMutex sync.Mutex
|
||||
running atomic.Bool
|
||||
quit chan bool
|
||||
|
|
@ -43,7 +43,7 @@ type RelayServerRetriever struct {
|
|||
|
||||
func NewRelayServerRetriever(
|
||||
ctx context.Context,
|
||||
serverName gomatrixserverlib.ServerName,
|
||||
serverName spec.ServerName,
|
||||
federationAPI federationAPI.FederationInternalAPI,
|
||||
relayAPI relayServerAPI.RelayInternalAPI,
|
||||
quit chan bool,
|
||||
|
|
@ -53,14 +53,14 @@ func NewRelayServerRetriever(
|
|||
serverName: serverName,
|
||||
federationAPI: federationAPI,
|
||||
relayAPI: relayAPI,
|
||||
relayServersQueried: make(map[gomatrixserverlib.ServerName]bool),
|
||||
relayServersQueried: make(map[spec.ServerName]bool),
|
||||
running: *atomic.NewBool(false),
|
||||
quit: quit,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RelayServerRetriever) InitializeRelayServers(eLog *logrus.Entry) {
|
||||
request := federationAPI.P2PQueryRelayServersRequest{Server: gomatrixserverlib.ServerName(r.serverName)}
|
||||
request := federationAPI.P2PQueryRelayServersRequest{Server: spec.ServerName(r.serverName)}
|
||||
response := federationAPI.P2PQueryRelayServersResponse{}
|
||||
err := r.federationAPI.P2PQueryRelayServers(r.ctx, &request, &response)
|
||||
if err != nil {
|
||||
|
|
@ -76,13 +76,13 @@ func (r *RelayServerRetriever) InitializeRelayServers(eLog *logrus.Entry) {
|
|||
eLog.Infof("Registered relay servers: %v", response.RelayServers)
|
||||
}
|
||||
|
||||
func (r *RelayServerRetriever) SetRelayServers(servers []gomatrixserverlib.ServerName) {
|
||||
func (r *RelayServerRetriever) SetRelayServers(servers []spec.ServerName) {
|
||||
UpdateNodeRelayServers(r.serverName, servers, r.ctx, r.federationAPI)
|
||||
|
||||
// Replace list of servers to sync with and mark them all as unsynced.
|
||||
r.queriedServersMutex.Lock()
|
||||
defer r.queriedServersMutex.Unlock()
|
||||
r.relayServersQueried = make(map[gomatrixserverlib.ServerName]bool)
|
||||
r.relayServersQueried = make(map[spec.ServerName]bool)
|
||||
for _, server := range servers {
|
||||
r.relayServersQueried[server] = false
|
||||
}
|
||||
|
|
@ -90,10 +90,10 @@ func (r *RelayServerRetriever) SetRelayServers(servers []gomatrixserverlib.Serve
|
|||
r.StartSync()
|
||||
}
|
||||
|
||||
func (r *RelayServerRetriever) GetRelayServers() []gomatrixserverlib.ServerName {
|
||||
func (r *RelayServerRetriever) GetRelayServers() []spec.ServerName {
|
||||
r.queriedServersMutex.Lock()
|
||||
defer r.queriedServersMutex.Unlock()
|
||||
relayServers := []gomatrixserverlib.ServerName{}
|
||||
relayServers := []spec.ServerName{}
|
||||
for server := range r.relayServersQueried {
|
||||
relayServers = append(relayServers, server)
|
||||
}
|
||||
|
|
@ -101,11 +101,11 @@ func (r *RelayServerRetriever) GetRelayServers() []gomatrixserverlib.ServerName
|
|||
return relayServers
|
||||
}
|
||||
|
||||
func (r *RelayServerRetriever) GetQueriedServerStatus() map[gomatrixserverlib.ServerName]bool {
|
||||
func (r *RelayServerRetriever) GetQueriedServerStatus() map[spec.ServerName]bool {
|
||||
r.queriedServersMutex.Lock()
|
||||
defer r.queriedServersMutex.Unlock()
|
||||
|
||||
result := map[gomatrixserverlib.ServerName]bool{}
|
||||
result := map[spec.ServerName]bool{}
|
||||
for server, queried := range r.relayServersQueried {
|
||||
result[server] = queried
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ func (r *RelayServerRetriever) SyncRelayServers(stop <-chan bool) {
|
|||
|
||||
t := time.NewTimer(relayServerRetryInterval)
|
||||
for {
|
||||
relayServersToQuery := []gomatrixserverlib.ServerName{}
|
||||
relayServersToQuery := []spec.ServerName{}
|
||||
func() {
|
||||
r.queriedServersMutex.Lock()
|
||||
defer r.queriedServersMutex.Unlock()
|
||||
|
|
@ -158,10 +158,10 @@ func (r *RelayServerRetriever) SyncRelayServers(stop <-chan bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *RelayServerRetriever) queryRelayServers(relayServers []gomatrixserverlib.ServerName) {
|
||||
func (r *RelayServerRetriever) queryRelayServers(relayServers []spec.ServerName) {
|
||||
logrus.Info("Querying relay servers for any available transactions")
|
||||
for _, server := range relayServers {
|
||||
userID, err := gomatrixserverlib.NewUserID("@user:"+string(r.serverName), false)
|
||||
userID, err := spec.NewUserID("@user:"+string(r.serverName), false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -187,8 +187,8 @@ func (r *RelayServerRetriever) queryRelayServers(relayServers []gomatrixserverli
|
|||
}
|
||||
|
||||
func UpdateNodeRelayServers(
|
||||
node gomatrixserverlib.ServerName,
|
||||
relays []gomatrixserverlib.ServerName,
|
||||
node spec.ServerName,
|
||||
relays []spec.ServerName,
|
||||
ctx context.Context,
|
||||
fedAPI federationAPI.FederationInternalAPI,
|
||||
) {
|
||||
|
|
@ -201,7 +201,7 @@ func UpdateNodeRelayServers(
|
|||
}
|
||||
|
||||
// Remove old, non-matching relays
|
||||
var serversToRemove []gomatrixserverlib.ServerName
|
||||
var serversToRemove []spec.ServerName
|
||||
for _, existingServer := range response.RelayServers {
|
||||
shouldRemove := true
|
||||
for _, newServer := range relays {
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ import (
|
|||
|
||||
federationAPI "github.com/matrix-org/dendrite/federationapi/api"
|
||||
relayServerAPI "github.com/matrix-org/dendrite/relayapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gotest.tools/v3/poll"
|
||||
)
|
||||
|
||||
var testRelayServers = []gomatrixserverlib.ServerName{"relay1", "relay2"}
|
||||
var testRelayServers = []spec.ServerName{"relay1", "relay2"}
|
||||
|
||||
type FakeFedAPI struct {
|
||||
federationAPI.FederationInternalAPI
|
||||
|
|
@ -48,8 +48,8 @@ type FakeRelayAPI struct {
|
|||
|
||||
func (r *FakeRelayAPI) PerformRelayServerSync(
|
||||
ctx context.Context,
|
||||
userID gomatrixserverlib.UserID,
|
||||
relayServer gomatrixserverlib.ServerName,
|
||||
userID spec.UserID,
|
||||
relayServer spec.ServerName,
|
||||
) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/defaults"
|
||||
"github.com/matrix-org/dendrite/federationapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
pineconeRouter "github.com/matrix-org/pinecone/router"
|
||||
|
|
@ -32,14 +33,14 @@ type PineconeRoomProvider struct {
|
|||
r *pineconeRouter.Router
|
||||
s *pineconeSessions.Sessions
|
||||
fedSender api.FederationInternalAPI
|
||||
fedClient *gomatrixserverlib.FederationClient
|
||||
fedClient fclient.FederationClient
|
||||
}
|
||||
|
||||
func NewPineconeRoomProvider(
|
||||
r *pineconeRouter.Router,
|
||||
s *pineconeSessions.Sessions,
|
||||
fedSender api.FederationInternalAPI,
|
||||
fedClient *gomatrixserverlib.FederationClient,
|
||||
fedClient fclient.FederationClient,
|
||||
) *PineconeRoomProvider {
|
||||
p := &PineconeRoomProvider{
|
||||
r: r,
|
||||
|
|
@ -50,31 +51,31 @@ func NewPineconeRoomProvider(
|
|||
return p
|
||||
}
|
||||
|
||||
func (p *PineconeRoomProvider) Rooms() []gomatrixserverlib.PublicRoom {
|
||||
list := map[gomatrixserverlib.ServerName]struct{}{}
|
||||
func (p *PineconeRoomProvider) Rooms() []fclient.PublicRoom {
|
||||
list := map[spec.ServerName]struct{}{}
|
||||
for k := range defaults.DefaultServerNames {
|
||||
list[k] = struct{}{}
|
||||
}
|
||||
for _, k := range p.r.Peers() {
|
||||
list[gomatrixserverlib.ServerName(k.PublicKey)] = struct{}{}
|
||||
list[spec.ServerName(k.PublicKey)] = struct{}{}
|
||||
}
|
||||
return bulkFetchPublicRoomsFromServers(
|
||||
context.Background(), p.fedClient,
|
||||
gomatrixserverlib.ServerName(p.r.PublicKey().String()), list,
|
||||
spec.ServerName(p.r.PublicKey().String()), list,
|
||||
)
|
||||
}
|
||||
|
||||
// bulkFetchPublicRoomsFromServers fetches public rooms from the list of homeservers.
|
||||
// Returns a list of public rooms.
|
||||
func bulkFetchPublicRoomsFromServers(
|
||||
ctx context.Context, fedClient *gomatrixserverlib.FederationClient,
|
||||
origin gomatrixserverlib.ServerName,
|
||||
homeservers map[gomatrixserverlib.ServerName]struct{},
|
||||
) (publicRooms []gomatrixserverlib.PublicRoom) {
|
||||
ctx context.Context, fedClient fclient.FederationClient,
|
||||
origin spec.ServerName,
|
||||
homeservers map[spec.ServerName]struct{},
|
||||
) (publicRooms []fclient.PublicRoom) {
|
||||
limit := 200
|
||||
// follow pipeline semantics, see https://blog.golang.org/pipelines for more info.
|
||||
// goroutines send rooms to this channel
|
||||
roomCh := make(chan gomatrixserverlib.PublicRoom, int(limit))
|
||||
roomCh := make(chan fclient.PublicRoom, int(limit))
|
||||
// signalling channel to tell goroutines to stop sending rooms and quit
|
||||
done := make(chan bool)
|
||||
// signalling to say when we can close the room channel
|
||||
|
|
@ -83,7 +84,7 @@ func bulkFetchPublicRoomsFromServers(
|
|||
// concurrently query for public rooms
|
||||
reqctx, reqcancel := context.WithTimeout(ctx, time.Second*5)
|
||||
for hs := range homeservers {
|
||||
go func(homeserverDomain gomatrixserverlib.ServerName) {
|
||||
go func(homeserverDomain spec.ServerName) {
|
||||
defer wg.Done()
|
||||
util.GetLogger(reqctx).WithField("hs", homeserverDomain).Info("Querying HS for public rooms")
|
||||
fres, err := fedClient.GetPublicRooms(reqctx, origin, homeserverDomain, int(limit), "", false, "")
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ import (
|
|||
clienthttputil "github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
"github.com/matrix-org/dendrite/cmd/dendrite-demo-pinecone/defaults"
|
||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
|
||||
pineconeRouter "github.com/matrix-org/pinecone/router"
|
||||
|
|
@ -38,7 +39,7 @@ type PineconeUserProvider struct {
|
|||
r *pineconeRouter.Router
|
||||
s *pineconeSessions.Sessions
|
||||
userAPI userapi.QuerySearchProfilesAPI
|
||||
fedClient *gomatrixserverlib.FederationClient
|
||||
fedClient fclient.FederationClient
|
||||
}
|
||||
|
||||
const PublicURL = "/_matrix/p2p/profiles"
|
||||
|
|
@ -47,7 +48,7 @@ func NewPineconeUserProvider(
|
|||
r *pineconeRouter.Router,
|
||||
s *pineconeSessions.Sessions,
|
||||
userAPI userapi.QuerySearchProfilesAPI,
|
||||
fedClient *gomatrixserverlib.FederationClient,
|
||||
fedClient fclient.FederationClient,
|
||||
) *PineconeUserProvider {
|
||||
p := &PineconeUserProvider{
|
||||
r: r,
|
||||
|
|
@ -79,12 +80,12 @@ func (p *PineconeUserProvider) FederatedUserProfiles(w http.ResponseWriter, r *h
|
|||
}
|
||||
|
||||
func (p *PineconeUserProvider) QuerySearchProfiles(ctx context.Context, req *userapi.QuerySearchProfilesRequest, res *userapi.QuerySearchProfilesResponse) error {
|
||||
list := map[gomatrixserverlib.ServerName]struct{}{}
|
||||
list := map[spec.ServerName]struct{}{}
|
||||
for k := range defaults.DefaultServerNames {
|
||||
list[k] = struct{}{}
|
||||
}
|
||||
for _, k := range p.r.Peers() {
|
||||
list[gomatrixserverlib.ServerName(k.PublicKey)] = struct{}{}
|
||||
list[spec.ServerName(k.PublicKey)] = struct{}{}
|
||||
}
|
||||
res.Profiles = bulkFetchUserDirectoriesFromServers(context.Background(), req, p.fedClient, list)
|
||||
return nil
|
||||
|
|
@ -94,8 +95,8 @@ func (p *PineconeUserProvider) QuerySearchProfiles(ctx context.Context, req *use
|
|||
// Returns a list of user profiles.
|
||||
func bulkFetchUserDirectoriesFromServers(
|
||||
ctx context.Context, req *userapi.QuerySearchProfilesRequest,
|
||||
fedClient *gomatrixserverlib.FederationClient,
|
||||
homeservers map[gomatrixserverlib.ServerName]struct{},
|
||||
fedClient fclient.FederationClient,
|
||||
homeservers map[spec.ServerName]struct{},
|
||||
) (profiles []authtypes.Profile) {
|
||||
jsonBody, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
|
|
@ -114,7 +115,7 @@ func bulkFetchUserDirectoriesFromServers(
|
|||
// concurrently query for public rooms
|
||||
reqctx, reqcancel := context.WithTimeout(ctx, time.Second*5)
|
||||
for hs := range homeservers {
|
||||
go func(homeserverDomain gomatrixserverlib.ServerName) {
|
||||
go func(homeserverDomain spec.ServerName) {
|
||||
defer wg.Done()
|
||||
util.GetLogger(reqctx).WithField("hs", homeserverDomain).Info("Querying HS for users")
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"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"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/matrix-org/dendrite/appservice"
|
||||
|
|
@ -145,7 +146,7 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
cfg.Global.ServerName = gomatrixserverlib.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.ServerName = spec.ServerName(hex.EncodeToString(pk))
|
||||
cfg.Global.KeyID = gomatrixserverlib.KeyID(signing.KeyID)
|
||||
|
||||
configErrors := &config.ConfigErrors{}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
)
|
||||
|
||||
const KeyID = "ed25519:dendrite-demo-yggdrasil"
|
||||
|
|
@ -36,7 +37,7 @@ func (f *YggdrasilKeys) KeyRing() *gomatrixserverlib.KeyRing {
|
|||
|
||||
func (f *YggdrasilKeys) FetchKeys(
|
||||
ctx context.Context,
|
||||
requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp,
|
||||
requests map[gomatrixserverlib.PublicKeyLookupRequest]spec.Timestamp,
|
||||
) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) {
|
||||
res := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult)
|
||||
for req := range requests {
|
||||
|
|
@ -54,7 +55,7 @@ func (f *YggdrasilKeys) FetchKeys(
|
|||
Key: hexkey,
|
||||
},
|
||||
ExpiredTS: gomatrixserverlib.PublicKeyNotExpired,
|
||||
ValidUntilTS: gomatrixserverlib.AsTimestamp(time.Now().Add(24 * time.Hour * 365)),
|
||||
ValidUntilTS: spec.AsTimestamp(time.Now().Add(24 * time.Hour * 365)),
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
)
|
||||
|
||||
type yggroundtripper struct {
|
||||
|
|
@ -17,7 +17,7 @@ func (y *yggroundtripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
return y.inner.RoundTrip(req)
|
||||
}
|
||||
|
||||
func (n *Node) CreateClient() *gomatrixserverlib.Client {
|
||||
func (n *Node) CreateClient() *fclient.Client {
|
||||
tr := &http.Transport{}
|
||||
tr.RegisterProtocol(
|
||||
"matrix", &yggroundtripper{
|
||||
|
|
@ -31,14 +31,14 @@ func (n *Node) CreateClient() *gomatrixserverlib.Client {
|
|||
},
|
||||
},
|
||||
)
|
||||
return gomatrixserverlib.NewClient(
|
||||
gomatrixserverlib.WithTransport(tr),
|
||||
return fclient.NewClient(
|
||||
fclient.WithTransport(tr),
|
||||
)
|
||||
}
|
||||
|
||||
func (n *Node) CreateFederationClient(
|
||||
cfg *config.Dendrite,
|
||||
) *gomatrixserverlib.FederationClient {
|
||||
) fclient.FederationClient {
|
||||
tr := &http.Transport{}
|
||||
tr.RegisterProtocol(
|
||||
"matrix", &yggroundtripper{
|
||||
|
|
@ -52,8 +52,8 @@ func (n *Node) CreateFederationClient(
|
|||
},
|
||||
},
|
||||
)
|
||||
return gomatrixserverlib.NewFederationClient(
|
||||
return fclient.NewFederationClient(
|
||||
cfg.Global.SigningIdentities(),
|
||||
gomatrixserverlib.WithTransport(tr),
|
||||
fclient.WithTransport(tr),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/neilalexander/utp"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
|
|
@ -134,14 +134,14 @@ func (n *Node) PeerCount() int {
|
|||
return len(n.core.GetPeers())
|
||||
}
|
||||
|
||||
func (n *Node) KnownNodes() []gomatrixserverlib.ServerName {
|
||||
func (n *Node) KnownNodes() []spec.ServerName {
|
||||
nodemap := map[string]struct{}{}
|
||||
for _, peer := range n.core.GetPeers() {
|
||||
nodemap[hex.EncodeToString(peer.Key)] = struct{}{}
|
||||
}
|
||||
var nodes []gomatrixserverlib.ServerName
|
||||
var nodes []spec.ServerName
|
||||
for node := range nodemap {
|
||||
nodes = append(nodes, gomatrixserverlib.ServerName(node))
|
||||
nodes = append(nodes, spec.ServerName(node))
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,18 +21,19 @@ import (
|
|||
|
||||
"github.com/matrix-org/dendrite/cmd/dendrite-demo-yggdrasil/yggconn"
|
||||
"github.com/matrix-org/dendrite/federationapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/fclient"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
type YggdrasilRoomProvider struct {
|
||||
node *yggconn.Node
|
||||
fedSender api.FederationInternalAPI
|
||||
fedClient *gomatrixserverlib.FederationClient
|
||||
fedClient fclient.FederationClient
|
||||
}
|
||||
|
||||
func NewYggdrasilRoomProvider(
|
||||
node *yggconn.Node, fedSender api.FederationInternalAPI, fedClient *gomatrixserverlib.FederationClient,
|
||||
node *yggconn.Node, fedSender api.FederationInternalAPI, fedClient fclient.FederationClient,
|
||||
) *YggdrasilRoomProvider {
|
||||
p := &YggdrasilRoomProvider{
|
||||
node: node,
|
||||
|
|
@ -42,10 +43,10 @@ func NewYggdrasilRoomProvider(
|
|||
return p
|
||||
}
|
||||
|
||||
func (p *YggdrasilRoomProvider) Rooms() []gomatrixserverlib.PublicRoom {
|
||||
func (p *YggdrasilRoomProvider) Rooms() []fclient.PublicRoom {
|
||||
return bulkFetchPublicRoomsFromServers(
|
||||
context.Background(), p.fedClient,
|
||||
gomatrixserverlib.ServerName(p.node.DerivedServerName()),
|
||||
spec.ServerName(p.node.DerivedServerName()),
|
||||
p.node.KnownNodes(),
|
||||
)
|
||||
}
|
||||
|
|
@ -53,14 +54,14 @@ func (p *YggdrasilRoomProvider) Rooms() []gomatrixserverlib.PublicRoom {
|
|||
// bulkFetchPublicRoomsFromServers fetches public rooms from the list of homeservers.
|
||||
// Returns a list of public rooms.
|
||||
func bulkFetchPublicRoomsFromServers(
|
||||
ctx context.Context, fedClient *gomatrixserverlib.FederationClient,
|
||||
origin gomatrixserverlib.ServerName,
|
||||
homeservers []gomatrixserverlib.ServerName,
|
||||
) (publicRooms []gomatrixserverlib.PublicRoom) {
|
||||
ctx context.Context, fedClient fclient.FederationClient,
|
||||
origin spec.ServerName,
|
||||
homeservers []spec.ServerName,
|
||||
) (publicRooms []fclient.PublicRoom) {
|
||||
limit := 200
|
||||
// follow pipeline semantics, see https://blog.golang.org/pipelines for more info.
|
||||
// goroutines send rooms to this channel
|
||||
roomCh := make(chan gomatrixserverlib.PublicRoom, int(limit))
|
||||
roomCh := make(chan fclient.PublicRoom, int(limit))
|
||||
// signalling channel to tell goroutines to stop sending rooms and quit
|
||||
done := make(chan bool)
|
||||
// signalling to say when we can close the room channel
|
||||
|
|
@ -68,7 +69,7 @@ func bulkFetchPublicRoomsFromServers(
|
|||
wg.Add(len(homeservers))
|
||||
// concurrently query for public rooms
|
||||
for _, hs := range homeservers {
|
||||
go func(homeserverDomain gomatrixserverlib.ServerName) {
|
||||
go func(homeserverDomain spec.ServerName) {
|
||||
defer wg.Done()
|
||||
util.GetLogger(ctx).WithField("hs", homeserverDomain).Info("Querying HS for public rooms")
|
||||
fres, err := fedClient.GetPublicRooms(ctx, origin, homeserverDomain, int(limit), "", false, "")
|
||||
|
|
|
|||
|
|
@ -55,7 +55,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-stretch as build
|
||||
const DockerfilePostgreSQL = `FROM golang:1.18-buster as build
|
||||
RUN apt-get update && apt-get install -y postgresql
|
||||
WORKDIR /build
|
||||
ARG BINARY
|
||||
|
|
@ -72,18 +72,18 @@ RUN ./generate-config --ci > 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
|
||||
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/9.6/main/pg_hba.conf
|
||||
RUN sed -i "s%127.0.0.1/32 md5%127.0.0.1/32 trust%g" /etc/postgresql/11/main/pg_hba.conf
|
||||
# Bump up max conns for moar concurrency
|
||||
RUN sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/9.6/main/postgresql.conf
|
||||
RUN sed -i 's/max_connections = 100/max_connections = 2000/g' /etc/postgresql/11/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 9.6 main start \n\
|
||||
pg_ctlcluster 11 main start \n\
|
||||
\n\
|
||||
until pg_isready \n\
|
||||
do \n\
|
||||
|
|
@ -101,7 +101,7 @@ ENV BINARY=dendrite
|
|||
EXPOSE 8008 8448
|
||||
CMD /build/run_dendrite.sh`
|
||||
|
||||
const DockerfileSQLite = `FROM golang:1.18-stretch as build
|
||||
const DockerfileSQLite = `FROM golang:1.18-buster as build
|
||||
RUN apt-get update && apt-get install -y postgresql
|
||||
WORKDIR /build
|
||||
ARG BINARY
|
||||
|
|
@ -119,7 +119,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\/9.6\/main\/%g" dendrite.yaml
|
||||
RUN sed -i "s%connection_string:.file:%connection_string: file:\/var\/lib\/postgresql\/11\/main\/%g" dendrite.yaml
|
||||
|
||||
# This entry script starts postgres, waits for it to be up then starts dendrite
|
||||
RUN echo '\
|
||||
|
|
@ -402,7 +402,7 @@ func runImage(dockerClient *client.Client, volumeName string, branchNameToImageI
|
|||
{
|
||||
Type: mount.TypeVolume,
|
||||
Source: volumeName,
|
||||
Target: "/var/lib/postgresql/9.6/main",
|
||||
Target: "/var/lib/postgresql/11/main",
|
||||
},
|
||||
},
|
||||
}, nil, nil, "dendrite_upgrade_test_"+branchName)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue