mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-29 01:33:10 -06:00
Merge branch 'master' of https://github.com/matrix-org/dendrite into add-presence
This commit is contained in:
commit
139817a0b3
49
.github/workflows/wasm.yml
vendored
Normal file
49
.github/workflows/wasm.yml
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
name: WebAssembly
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.16.5
|
||||||
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/go-build
|
||||||
|
~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
|
- name: Install Node
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: 14
|
||||||
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
|
- name: Reconfigure Git to use HTTPS auth for repo packages
|
||||||
|
run: >
|
||||||
|
git config --global url."https://github.com/".insteadOf
|
||||||
|
ssh://git@github.com/
|
||||||
|
|
||||||
|
- name: Install test dependencies
|
||||||
|
working-directory: ./test/wasm
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: ./test-dendritejs.sh
|
||||||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -3,6 +3,9 @@
|
||||||
# Hidden files
|
# Hidden files
|
||||||
.*
|
.*
|
||||||
|
|
||||||
|
# Allow GitHub config
|
||||||
|
!.github
|
||||||
|
|
||||||
# Downloads
|
# Downloads
|
||||||
/.downloads
|
/.downloads
|
||||||
|
|
||||||
|
|
@ -36,6 +39,7 @@ _testmain.go
|
||||||
*.exe
|
*.exe
|
||||||
*.test
|
*.test
|
||||||
*.prof
|
*.prof
|
||||||
|
*.wasm
|
||||||
|
|
||||||
# Generated keys
|
# Generated keys
|
||||||
*.pem
|
*.pem
|
||||||
|
|
@ -53,3 +57,6 @@ dendrite.yaml
|
||||||
|
|
||||||
# Generated code
|
# Generated code
|
||||||
cmd/dendrite-demo-yggdrasil/embed/fs*.go
|
cmd/dendrite-demo-yggdrasil/embed/fs*.go
|
||||||
|
|
||||||
|
# Test dependencies
|
||||||
|
test/wasm/node_modules
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Database stores events intended to be later sent to application services
|
// Database stores events intended to be later sent to application services
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/sh -eu
|
#!/bin/sh -eu
|
||||||
|
|
||||||
export GIT_COMMIT=$(git rev-list -1 HEAD) && \
|
export GIT_COMMIT=$(git rev-list -1 HEAD) && \
|
||||||
GOOS=js GOARCH=wasm go build -ldflags "-X main.GitCommit=$GIT_COMMIT" -o main.wasm ./cmd/dendritejs
|
GOOS=js GOARCH=wasm go build -ldflags "-X main.GitCommit=$GIT_COMMIT" -o bin/main.wasm ./cmd/dendritejs-pinecone
|
||||||
|
|
|
||||||
2
build.sh
2
build.sh
|
|
@ -21,4 +21,4 @@ mkdir -p bin
|
||||||
|
|
||||||
CGO_ENABLED=1 go build -trimpath -ldflags "$FLAGS" -v -o "bin/" ./cmd/...
|
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
|
CGO_ENABLED=0 GOOS=js GOARCH=wasm go build -trimpath -ldflags "$FLAGS" -o bin/main.wasm ./cmd/dendritejs-pinecone
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ func (r *Login) Username() string {
|
||||||
if r.Identifier.Type == "m.id.user" {
|
if r.Identifier.Type == "m.id.user" {
|
||||||
return r.Identifier.User
|
return r.Identifier.User
|
||||||
}
|
}
|
||||||
// deprecated but without it Riot iOS won't log in
|
// deprecated but without it Element iOS won't log in
|
||||||
return r.User
|
return r.User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
96
clientapi/routing/aliases.go
Normal file
96
clientapi/routing/aliases.go
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package routing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"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/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetAliases implements GET /_matrix/client/r0/rooms/{roomId}/aliases
|
||||||
|
func GetAliases(
|
||||||
|
req *http.Request, rsAPI api.RoomserverInternalAPI, device *userapi.Device, roomID string,
|
||||||
|
) util.JSONResponse {
|
||||||
|
stateTuple := gomatrixserverlib.StateKeyTuple{
|
||||||
|
EventType: gomatrixserverlib.MRoomHistoryVisibility,
|
||||||
|
StateKey: "",
|
||||||
|
}
|
||||||
|
stateReq := &api.QueryCurrentStateRequest{
|
||||||
|
RoomID: roomID,
|
||||||
|
StateTuples: []gomatrixserverlib.StateKeyTuple{stateTuple},
|
||||||
|
}
|
||||||
|
stateRes := &api.QueryCurrentStateResponse{}
|
||||||
|
if err := rsAPI.QueryCurrentState(req.Context(), stateReq, stateRes); err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.QueryCurrentState failed")
|
||||||
|
return util.ErrorResponse(fmt.Errorf("rsAPI.QueryCurrentState: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
visibility := "invite"
|
||||||
|
if historyVisEvent, ok := stateRes.StateEvents[stateTuple]; ok {
|
||||||
|
var err error
|
||||||
|
visibility, err = historyVisEvent.HistoryVisibility()
|
||||||
|
if err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Error("historyVisEvent.HistoryVisibility failed")
|
||||||
|
return util.ErrorResponse(fmt.Errorf("historyVisEvent.HistoryVisibility: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if visibility != gomatrixserverlib.WorldReadable {
|
||||||
|
queryReq := api.QueryMembershipForUserRequest{
|
||||||
|
RoomID: roomID,
|
||||||
|
UserID: device.UserID,
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
if !queryRes.IsInRoom {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
|
JSON: jsonerror.Forbidden("You aren't a member of this room."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aliasesReq := api.GetAliasesForRoomIDRequest{
|
||||||
|
RoomID: roomID,
|
||||||
|
}
|
||||||
|
aliasesRes := api.GetAliasesForRoomIDResponse{}
|
||||||
|
if err := rsAPI.GetAliasesForRoomID(req.Context(), &aliasesReq, &aliasesRes); err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Error("rsAPI.GetAliasesForRoomID failed")
|
||||||
|
return util.ErrorResponse(fmt.Errorf("rsAPI.GetAliasesForRoomID: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
response := struct {
|
||||||
|
Aliases []string `json:"aliases"`
|
||||||
|
}{
|
||||||
|
Aliases: aliasesRes.Aliases,
|
||||||
|
}
|
||||||
|
if response.Aliases == nil {
|
||||||
|
response.Aliases = []string{} // pleases sytest
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 200,
|
||||||
|
JSON: response,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,7 +43,7 @@ type createRoomRequest struct {
|
||||||
Visibility string `json:"visibility"`
|
Visibility string `json:"visibility"`
|
||||||
Topic string `json:"topic"`
|
Topic string `json:"topic"`
|
||||||
Preset string `json:"preset"`
|
Preset string `json:"preset"`
|
||||||
CreationContent map[string]interface{} `json:"creation_content"`
|
CreationContent json.RawMessage `json:"creation_content"`
|
||||||
InitialState []fledglingEvent `json:"initial_state"`
|
InitialState []fledglingEvent `json:"initial_state"`
|
||||||
RoomAliasName string `json:"room_alias_name"`
|
RoomAliasName string `json:"room_alias_name"`
|
||||||
GuestCanJoin bool `json:"guest_can_join"`
|
GuestCanJoin bool `json:"guest_can_join"`
|
||||||
|
|
@ -177,11 +177,6 @@ func createRoom(
|
||||||
|
|
||||||
// Clobber keys: creator, room_version
|
// Clobber keys: creator, room_version
|
||||||
|
|
||||||
if r.CreationContent == nil {
|
|
||||||
r.CreationContent = make(map[string]interface{}, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.CreationContent["creator"] = userID
|
|
||||||
roomVersion := roomserverVersion.DefaultRoomVersion()
|
roomVersion := roomserverVersion.DefaultRoomVersion()
|
||||||
if r.RoomVersion != "" {
|
if r.RoomVersion != "" {
|
||||||
candidateVersion := gomatrixserverlib.RoomVersion(r.RoomVersion)
|
candidateVersion := gomatrixserverlib.RoomVersion(r.RoomVersion)
|
||||||
|
|
@ -194,7 +189,6 @@ func createRoom(
|
||||||
}
|
}
|
||||||
roomVersion = candidateVersion
|
roomVersion = candidateVersion
|
||||||
}
|
}
|
||||||
r.CreationContent["room_version"] = roomVersion
|
|
||||||
|
|
||||||
// TODO: visibility/presets/raw initial state
|
// TODO: visibility/presets/raw initial state
|
||||||
// TODO: Create room alias association
|
// TODO: Create room alias association
|
||||||
|
|
@ -203,7 +197,7 @@ func createRoom(
|
||||||
logger.WithFields(log.Fields{
|
logger.WithFields(log.Fields{
|
||||||
"userID": userID,
|
"userID": userID,
|
||||||
"roomID": roomID,
|
"roomID": roomID,
|
||||||
"roomVersion": r.CreationContent["room_version"],
|
"roomVersion": roomVersion,
|
||||||
}).Info("Creating new room")
|
}).Info("Creating new room")
|
||||||
|
|
||||||
profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB)
|
profile, err := appserviceAPI.RetrieveUserProfile(req.Context(), userID, asAPI, accountDB)
|
||||||
|
|
@ -212,6 +206,109 @@ func createRoom(
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createContent := map[string]interface{}{}
|
||||||
|
if len(r.CreationContent) > 0 {
|
||||||
|
if err = json.Unmarshal(r.CreationContent, &createContent); err != nil {
|
||||||
|
util.GetLogger(req.Context()).WithError(err).Error("json.Unmarshal for creation_content failed")
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.BadJSON("invalid create content"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createContent["creator"] = userID
|
||||||
|
createContent["room_version"] = roomVersion
|
||||||
|
powerLevelContent := eventutil.InitialPowerLevelsContent(userID)
|
||||||
|
joinRuleContent := gomatrixserverlib.JoinRuleContent{
|
||||||
|
JoinRule: gomatrixserverlib.Invite,
|
||||||
|
}
|
||||||
|
historyVisibilityContent := gomatrixserverlib.HistoryVisibilityContent{
|
||||||
|
HistoryVisibility: historyVisibilityShared,
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.PowerLevelContentOverride != nil {
|
||||||
|
// Merge powerLevelContentOverride fields by unmarshalling it atop the defaults
|
||||||
|
err = json.Unmarshal(r.PowerLevelContentOverride, &powerLevelContent)
|
||||||
|
if err != nil {
|
||||||
|
util.GetLogger(req.Context()).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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.Preset {
|
||||||
|
case presetPrivateChat:
|
||||||
|
joinRuleContent.JoinRule = gomatrixserverlib.Invite
|
||||||
|
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||||
|
case presetTrustedPrivateChat:
|
||||||
|
joinRuleContent.JoinRule = gomatrixserverlib.Invite
|
||||||
|
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||||
|
// TODO If trusted_private_chat, all invitees are given the same power level as the room creator.
|
||||||
|
case presetPublicChat:
|
||||||
|
joinRuleContent.JoinRule = gomatrixserverlib.Public
|
||||||
|
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||||
|
}
|
||||||
|
|
||||||
|
createEvent := fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomCreate,
|
||||||
|
Content: createContent,
|
||||||
|
}
|
||||||
|
powerLevelEvent := fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomPowerLevels,
|
||||||
|
Content: powerLevelContent,
|
||||||
|
}
|
||||||
|
joinRuleEvent := fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomJoinRules,
|
||||||
|
Content: joinRuleContent,
|
||||||
|
}
|
||||||
|
historyVisibilityEvent := fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomHistoryVisibility,
|
||||||
|
Content: historyVisibilityContent,
|
||||||
|
}
|
||||||
|
membershipEvent := fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomMember,
|
||||||
|
StateKey: userID,
|
||||||
|
Content: gomatrixserverlib.MemberContent{
|
||||||
|
Membership: gomatrixserverlib.Join,
|
||||||
|
DisplayName: profile.DisplayName,
|
||||||
|
AvatarURL: profile.AvatarURL,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameEvent *fledglingEvent
|
||||||
|
var topicEvent *fledglingEvent
|
||||||
|
var guestAccessEvent *fledglingEvent
|
||||||
|
var aliasEvent *fledglingEvent
|
||||||
|
|
||||||
|
if r.Name != "" {
|
||||||
|
nameEvent = &fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomName,
|
||||||
|
Content: eventutil.NameContent{
|
||||||
|
Name: r.Name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Topic != "" {
|
||||||
|
topicEvent = &fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomTopic,
|
||||||
|
Content: eventutil.TopicContent{
|
||||||
|
Topic: r.Topic,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.GuestCanJoin {
|
||||||
|
guestAccessEvent = &fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomGuestAccess,
|
||||||
|
Content: eventutil.GuestAccessContent{
|
||||||
|
GuestAccess: "can_join",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var roomAlias string
|
var roomAlias string
|
||||||
if r.RoomAliasName != "" {
|
if r.RoomAliasName != "" {
|
||||||
roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, cfg.Matrix.ServerName)
|
roomAlias = fmt.Sprintf("#%s:%s", r.RoomAliasName, cfg.Matrix.ServerName)
|
||||||
|
|
@ -230,44 +327,46 @@ func createRoom(
|
||||||
if aliasResp.RoomID != "" {
|
if aliasResp.RoomID != "" {
|
||||||
return util.MessageResponse(400, "Alias already exists")
|
return util.MessageResponse(400, "Alias already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aliasEvent = &fledglingEvent{
|
||||||
|
Type: gomatrixserverlib.MRoomCanonicalAlias,
|
||||||
|
Content: eventutil.CanonicalAlias{
|
||||||
|
Alias: roomAlias,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
membershipContent := gomatrixserverlib.MemberContent{
|
var initialStateEvents []fledglingEvent
|
||||||
Membership: gomatrixserverlib.Join,
|
for i := range r.InitialState {
|
||||||
DisplayName: profile.DisplayName,
|
if r.InitialState[i].StateKey != "" {
|
||||||
AvatarURL: profile.AvatarURL,
|
initialStateEvents = append(initialStateEvents, r.InitialState[i])
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var joinRules, historyVisibility string
|
switch r.InitialState[i].Type {
|
||||||
switch r.Preset {
|
case gomatrixserverlib.MRoomCreate:
|
||||||
case presetPrivateChat:
|
continue
|
||||||
joinRules = gomatrixserverlib.Invite
|
|
||||||
historyVisibility = historyVisibilityShared
|
|
||||||
case presetTrustedPrivateChat:
|
|
||||||
joinRules = gomatrixserverlib.Invite
|
|
||||||
historyVisibility = historyVisibilityShared
|
|
||||||
// TODO If trusted_private_chat, all invitees are given the same power level as the room creator.
|
|
||||||
case presetPublicChat:
|
|
||||||
joinRules = gomatrixserverlib.Public
|
|
||||||
historyVisibility = historyVisibilityShared
|
|
||||||
default:
|
|
||||||
// Default room rules, r.Preset was previously checked for valid values so
|
|
||||||
// only a request with no preset should end up here.
|
|
||||||
joinRules = gomatrixserverlib.Invite
|
|
||||||
historyVisibility = historyVisibilityShared
|
|
||||||
}
|
|
||||||
|
|
||||||
var builtEvents []*gomatrixserverlib.HeaderedEvent
|
case gomatrixserverlib.MRoomPowerLevels:
|
||||||
|
powerLevelEvent = r.InitialState[i]
|
||||||
|
|
||||||
powerLevelContent := eventutil.InitialPowerLevelsContent(userID)
|
case gomatrixserverlib.MRoomJoinRules:
|
||||||
if r.PowerLevelContentOverride != nil {
|
joinRuleEvent = r.InitialState[i]
|
||||||
// Merge powerLevelContentOverride fields by unmarshalling it atop the defaults
|
|
||||||
err = json.Unmarshal(r.PowerLevelContentOverride, &powerLevelContent)
|
case gomatrixserverlib.MRoomHistoryVisibility:
|
||||||
if err != nil {
|
historyVisibilityEvent = r.InitialState[i]
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
case gomatrixserverlib.MRoomGuestAccess:
|
||||||
JSON: jsonerror.BadJSON("malformed power_level_content_override"),
|
guestAccessEvent = &r.InitialState[i]
|
||||||
}
|
|
||||||
|
case gomatrixserverlib.MRoomName:
|
||||||
|
nameEvent = &r.InitialState[i]
|
||||||
|
|
||||||
|
case gomatrixserverlib.MRoomTopic:
|
||||||
|
topicEvent = &r.InitialState[i]
|
||||||
|
|
||||||
|
default:
|
||||||
|
initialStateEvents = append(initialStateEvents, r.InitialState[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,37 +383,33 @@ func createRoom(
|
||||||
// 10- m.room.topic (opt)
|
// 10- m.room.topic (opt)
|
||||||
// 11- invite events (opt) - with is_direct flag if applicable TODO
|
// 11- invite events (opt) - with is_direct flag if applicable TODO
|
||||||
// 12- 3pid invite events (opt) TODO
|
// 12- 3pid invite events (opt) TODO
|
||||||
// 13- m.room.aliases event for HS (if alias specified) TODO
|
|
||||||
// This differs from Synapse slightly. Synapse would vary the ordering of 3-7
|
// This differs from Synapse slightly. Synapse would vary the ordering of 3-7
|
||||||
// depending on if those events were in "initial_state" or not. This made it
|
// depending on if those events were in "initial_state" or not. This made it
|
||||||
// harder to reason about, hence sticking to a strict static ordering.
|
// harder to reason about, hence sticking to a strict static ordering.
|
||||||
// TODO: Synapse has txn/token ID on each event. Do we need to do this here?
|
// TODO: Synapse has txn/token ID on each event. Do we need to do this here?
|
||||||
eventsToMake := []fledglingEvent{
|
eventsToMake := []fledglingEvent{
|
||||||
{"m.room.create", "", r.CreationContent},
|
createEvent, membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent,
|
||||||
{"m.room.member", userID, membershipContent},
|
|
||||||
{"m.room.power_levels", "", powerLevelContent},
|
|
||||||
{"m.room.join_rules", "", gomatrixserverlib.JoinRuleContent{JoinRule: joinRules}},
|
|
||||||
{"m.room.history_visibility", "", eventutil.HistoryVisibilityContent{HistoryVisibility: historyVisibility}},
|
|
||||||
}
|
}
|
||||||
if roomAlias != "" {
|
if guestAccessEvent != nil {
|
||||||
|
eventsToMake = append(eventsToMake, *guestAccessEvent)
|
||||||
|
}
|
||||||
|
eventsToMake = append(eventsToMake, initialStateEvents...)
|
||||||
|
if nameEvent != nil {
|
||||||
|
eventsToMake = append(eventsToMake, *nameEvent)
|
||||||
|
}
|
||||||
|
if topicEvent != nil {
|
||||||
|
eventsToMake = append(eventsToMake, *topicEvent)
|
||||||
|
}
|
||||||
|
if aliasEvent != nil {
|
||||||
// TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room.
|
// TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room.
|
||||||
// This means we might fail creating the alias but say the canonical alias is something that doesn't exist.
|
// This means we might fail creating the alias but say the canonical alias is something that doesn't exist.
|
||||||
// m.room.aliases is handled when we call roomserver.SetRoomAlias
|
eventsToMake = append(eventsToMake, *aliasEvent)
|
||||||
eventsToMake = append(eventsToMake, fledglingEvent{"m.room.canonical_alias", "", eventutil.CanonicalAlias{Alias: roomAlias}})
|
|
||||||
}
|
|
||||||
if r.GuestCanJoin {
|
|
||||||
eventsToMake = append(eventsToMake, fledglingEvent{"m.room.guest_access", "", eventutil.GuestAccessContent{GuestAccess: "can_join"}})
|
|
||||||
}
|
|
||||||
eventsToMake = append(eventsToMake, r.InitialState...)
|
|
||||||
if r.Name != "" {
|
|
||||||
eventsToMake = append(eventsToMake, fledglingEvent{"m.room.name", "", eventutil.NameContent{Name: r.Name}})
|
|
||||||
}
|
|
||||||
if r.Topic != "" {
|
|
||||||
eventsToMake = append(eventsToMake, fledglingEvent{"m.room.topic", "", eventutil.TopicContent{Topic: r.Topic}})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: invite events
|
// TODO: invite events
|
||||||
// TODO: 3pid invite events
|
// TODO: 3pid invite events
|
||||||
|
|
||||||
|
var builtEvents []*gomatrixserverlib.HeaderedEvent
|
||||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
||||||
for i, e := range eventsToMake {
|
for i, e := range eventsToMake {
|
||||||
depth := i + 1 // depth starts at 1
|
depth := i + 1 // depth starts at 1
|
||||||
|
|
@ -403,7 +498,7 @@ func createRoom(
|
||||||
fallthrough
|
fallthrough
|
||||||
case gomatrixserverlib.MRoomCanonicalAlias:
|
case gomatrixserverlib.MRoomCanonicalAlias:
|
||||||
fallthrough
|
fallthrough
|
||||||
case "m.room.encryption": // TODO: move this to gmsl
|
case gomatrixserverlib.MRoomEncryption:
|
||||||
fallthrough
|
fallthrough
|
||||||
case gomatrixserverlib.MRoomMember:
|
case gomatrixserverlib.MRoomMember:
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
|
||||||
|
|
@ -113,13 +113,12 @@ func DirectoryRoom(
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLocalAlias implements PUT /directory/room/{roomAlias}
|
// SetLocalAlias implements PUT /directory/room/{roomAlias}
|
||||||
// TODO: Check if the user has the power level to set an alias
|
|
||||||
func SetLocalAlias(
|
func SetLocalAlias(
|
||||||
req *http.Request,
|
req *http.Request,
|
||||||
device *api.Device,
|
device *api.Device,
|
||||||
alias string,
|
alias string,
|
||||||
cfg *config.ClientAPI,
|
cfg *config.ClientAPI,
|
||||||
aliasAPI roomserverAPI.RoomserverInternalAPI,
|
rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
_, domain, err := gomatrixserverlib.SplitID('#', alias)
|
_, domain, err := gomatrixserverlib.SplitID('#', alias)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -172,7 +171,7 @@ func SetLocalAlias(
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
}
|
}
|
||||||
var queryRes roomserverAPI.SetRoomAliasResponse
|
var queryRes roomserverAPI.SetRoomAliasResponse
|
||||||
if err := aliasAPI.SetRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
if err := rsAPI.SetRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed")
|
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
@ -195,43 +194,32 @@ func RemoveLocalAlias(
|
||||||
req *http.Request,
|
req *http.Request,
|
||||||
device *api.Device,
|
device *api.Device,
|
||||||
alias string,
|
alias string,
|
||||||
aliasAPI roomserverAPI.RoomserverInternalAPI,
|
rsAPI roomserverAPI.RoomserverInternalAPI,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
|
|
||||||
creatorQueryReq := roomserverAPI.GetCreatorIDForAliasRequest{
|
|
||||||
Alias: alias,
|
|
||||||
}
|
|
||||||
var creatorQueryRes roomserverAPI.GetCreatorIDForAliasResponse
|
|
||||||
if err := aliasAPI.GetCreatorIDForAlias(req.Context(), &creatorQueryReq, &creatorQueryRes); err != nil {
|
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.GetCreatorIDForAlias failed")
|
|
||||||
return jsonerror.InternalServerError()
|
|
||||||
}
|
|
||||||
|
|
||||||
if creatorQueryRes.UserID == "" {
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusNotFound,
|
|
||||||
JSON: jsonerror.NotFound("Alias does not exist"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if creatorQueryRes.UserID != device.UserID {
|
|
||||||
// TODO: Still allow deletion if user is admin
|
|
||||||
return util.JSONResponse{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: jsonerror.Forbidden("You do not have permission to delete this alias"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
queryReq := roomserverAPI.RemoveRoomAliasRequest{
|
queryReq := roomserverAPI.RemoveRoomAliasRequest{
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
UserID: device.UserID,
|
UserID: device.UserID,
|
||||||
}
|
}
|
||||||
var queryRes roomserverAPI.RemoveRoomAliasResponse
|
var queryRes roomserverAPI.RemoveRoomAliasResponse
|
||||||
if err := aliasAPI.RemoveRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
if err := rsAPI.RemoveRoomAlias(req.Context(), &queryReq, &queryRes); err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed")
|
util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !queryRes.Found {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusNotFound,
|
||||||
|
JSON: jsonerror.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."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
JSON: struct{}{},
|
JSON: struct{}{},
|
||||||
|
|
@ -294,9 +282,9 @@ func SetVisibility(
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTSPEC: Check if the user's power is greater than power required to change m.room.aliases event
|
// 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)
|
power, _ := gomatrixserverlib.NewPowerLevelContentFromEvent(queryEventsRes.StateEvents[0].Event)
|
||||||
if power.UserLevel(dev.UserID) < power.EventLevel(gomatrixserverlib.MRoomAliases, true) {
|
if power.UserLevel(dev.UserID) < power.EventLevel(gomatrixserverlib.MRoomCanonicalAlias, true) {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
Code: http.StatusForbidden,
|
Code: http.StatusForbidden,
|
||||||
JSON: jsonerror.Forbidden("userID doesn't have power level to change visibility"),
|
JSON: jsonerror.Forbidden("userID doesn't have power level to change visibility"),
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,37 @@ func SendBan(
|
||||||
if reqErr != nil {
|
if reqErr != nil {
|
||||||
return *reqErr
|
return *reqErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return sendMembership(req.Context(), accountDB, device, roomID, "ban", body.Reason, cfg, body.UserID, evTime, roomVer, rsAPI, asAPI)
|
return sendMembership(req.Context(), accountDB, device, roomID, "ban", body.Reason, cfg, body.UserID, evTime, roomVer, rsAPI, asAPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,14 @@ func Setup(
|
||||||
return OnIncomingStateRequest(req.Context(), device, rsAPI, vars["roomID"])
|
return OnIncomingStateRequest(req.Context(), device, rsAPI, vars["roomID"])
|
||||||
})).Methods(http.MethodGet, http.MethodOptions)
|
})).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/aliases", httputil.MakeAuthAPI("aliases", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
|
if err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return GetAliases(req, rsAPI, device, vars["roomID"])
|
||||||
|
})).Methods(http.MethodGet, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/rooms/{roomID}/state/{type:[^/]+/?}", httputil.MakeAuthAPI("room_state", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
r0mux.Handle("/rooms/{roomID}/state/{type:[^/]+/?}", httputil.MakeAuthAPI("room_state", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ import (
|
||||||
"github.com/matrix-org/dendrite/eduserver/cache"
|
"github.com/matrix-org/dendrite/eduserver/cache"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createKeyDB(
|
func createKeyDB(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build riotweb
|
// +build elementweb
|
||||||
|
|
||||||
package embed
|
package embed
|
||||||
|
|
||||||
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// From within the Riot Web directory:
|
// From within the Element Web directory:
|
||||||
// go run github.com/mjibson/esc -o /path/to/dendrite/internal/embed/fs_riotweb.go -private -pkg embed .
|
// go run github.com/mjibson/esc -o /path/to/dendrite/internal/embed/fs_elementweb.go -private -pkg embed .
|
||||||
|
|
||||||
var cssFile = regexp.MustCompile("\\.css$")
|
var cssFile = regexp.MustCompile("\\.css$")
|
||||||
var jsFile = regexp.MustCompile("\\.js$")
|
var jsFile = regexp.MustCompile("\\.js$")
|
||||||
|
|
@ -68,7 +68,7 @@ func Embed(rootMux *mux.Router, listenPort int, serverName string) {
|
||||||
}
|
}
|
||||||
js, _ := sjson.SetBytes(buf, "default_server_config.m\\.homeserver.base_url", url)
|
js, _ := sjson.SetBytes(buf, "default_server_config.m\\.homeserver.base_url", url)
|
||||||
js, _ = sjson.SetBytes(js, "default_server_config.m\\.homeserver.server_name", serverName)
|
js, _ = sjson.SetBytes(js, "default_server_config.m\\.homeserver.server_name", serverName)
|
||||||
js, _ = sjson.SetBytes(js, "brand", fmt.Sprintf("Riot %s", serverName))
|
js, _ = sjson.SetBytes(js, "brand", fmt.Sprintf("Element %s", serverName))
|
||||||
js, _ = sjson.SetBytes(js, "disable_guests", true)
|
js, _ = sjson.SetBytes(js, "disable_guests", true)
|
||||||
js, _ = sjson.SetBytes(js, "disable_3pid_login", true)
|
js, _ = sjson.SetBytes(js, "disable_3pid_login", true)
|
||||||
js, _ = sjson.DeleteBytes(js, "welcomeUserId")
|
js, _ = sjson.DeleteBytes(js, "welcomeUserId")
|
||||||
|
|
@ -76,7 +76,7 @@ func Embed(rootMux *mux.Router, listenPort int, serverName string) {
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println("*-------------------------------*")
|
fmt.Println("*-------------------------------*")
|
||||||
fmt.Println("| This build includes Riot Web! |")
|
fmt.Println("| This build includes Element Web! |")
|
||||||
fmt.Println("*-------------------------------*")
|
fmt.Println("*-------------------------------*")
|
||||||
fmt.Println("Point your browser to:", url)
|
fmt.Println("Point your browser to:", url)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !riotweb
|
// +build !elementweb
|
||||||
|
|
||||||
package embed
|
package embed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ import (
|
||||||
pineconeSessions "github.com/matrix-org/pinecone/sessions"
|
pineconeSessions "github.com/matrix-org/pinecone/sessions"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build riotweb
|
// +build elementweb
|
||||||
|
|
||||||
package embed
|
package embed
|
||||||
|
|
||||||
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// From within the Riot Web directory:
|
// From within the Element Web directory:
|
||||||
// go run github.com/mjibson/esc -o /path/to/dendrite/internal/embed/fs_riotweb.go -private -pkg embed .
|
// go run github.com/mjibson/esc -o /path/to/dendrite/internal/embed/fs_elementweb.go -private -pkg embed .
|
||||||
|
|
||||||
var cssFile = regexp.MustCompile("\\.css$")
|
var cssFile = regexp.MustCompile("\\.css$")
|
||||||
var jsFile = regexp.MustCompile("\\.js$")
|
var jsFile = regexp.MustCompile("\\.js$")
|
||||||
|
|
@ -68,16 +68,16 @@ func Embed(rootMux *mux.Router, listenPort int, serverName string) {
|
||||||
}
|
}
|
||||||
js, _ := sjson.SetBytes(buf, "default_server_config.m\\.homeserver.base_url", url)
|
js, _ := sjson.SetBytes(buf, "default_server_config.m\\.homeserver.base_url", url)
|
||||||
js, _ = sjson.SetBytes(js, "default_server_config.m\\.homeserver.server_name", serverName)
|
js, _ = sjson.SetBytes(js, "default_server_config.m\\.homeserver.server_name", serverName)
|
||||||
js, _ = sjson.SetBytes(js, "brand", fmt.Sprintf("Riot %s", serverName))
|
js, _ = sjson.SetBytes(js, "brand", fmt.Sprintf("Element %s", serverName))
|
||||||
js, _ = sjson.SetBytes(js, "disable_guests", true)
|
js, _ = sjson.SetBytes(js, "disable_guests", true)
|
||||||
js, _ = sjson.SetBytes(js, "disable_3pid_login", true)
|
js, _ = sjson.SetBytes(js, "disable_3pid_login", true)
|
||||||
js, _ = sjson.DeleteBytes(js, "welcomeUserId")
|
js, _ = sjson.DeleteBytes(js, "welcomeUserId")
|
||||||
_, _ = w.Write(js)
|
_, _ = w.Write(js)
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println("*-------------------------------*")
|
fmt.Println("*----------------------------------*")
|
||||||
fmt.Println("| This build includes Riot Web! |")
|
fmt.Println("| This build includes Element Web! |")
|
||||||
fmt.Println("*-------------------------------*")
|
fmt.Println("*----------------------------------*")
|
||||||
fmt.Println("Point your browser to:", url)
|
fmt.Println("Point your browser to:", url)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !riotweb
|
// +build !elementweb
|
||||||
|
|
||||||
package embed
|
package embed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ import (
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ import (
|
||||||
"github.com/matrix-org/dendrite/signingkeyserver"
|
"github.com/matrix-org/dendrite/signingkeyserver"
|
||||||
"github.com/matrix-org/dendrite/userapi"
|
"github.com/matrix-org/dendrite/userapi"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"github.com/matrix-org/dendrite/setup"
|
"github.com/matrix-org/dendrite/setup"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type entrypoint func(base *setup.BaseDendrite, cfg *config.Dendrite)
|
type entrypoint func(base *setup.BaseDendrite, cfg *config.Dendrite)
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,13 @@ func generateKey() ed25519.PrivateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
startup()
|
||||||
|
|
||||||
|
// We want to block forever to let the fetch and libp2p handler serve the APIs
|
||||||
|
select {}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startup() {
|
||||||
sk := generateKey()
|
sk := generateKey()
|
||||||
pk := sk.Public().(ed25519.PublicKey)
|
pk := sk.Public().(ed25519.PublicKey)
|
||||||
|
|
||||||
|
|
@ -251,7 +258,4 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// We want to block forever to let the fetch and libp2p handler serve the APIs
|
|
||||||
select {}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
cmd/dendritejs-pinecone/main_test.go
Normal file
25
cmd/dendritejs-pinecone/main_test.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build wasm
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStartup(t *testing.T) {
|
||||||
|
startup()
|
||||||
|
}
|
||||||
15
docs/p2p.md
15
docs/p2p.md
|
|
@ -2,14 +2,23 @@
|
||||||
|
|
||||||
These are the instructions for setting up P2P Dendrite, current as of May 2020. There's both Go stuff and JS stuff to do to set this up.
|
These are the instructions for setting up P2P Dendrite, current as of May 2020. There's both Go stuff and JS stuff to do to set this up.
|
||||||
|
|
||||||
|
|
||||||
### Dendrite
|
### Dendrite
|
||||||
|
|
||||||
|
#### Build
|
||||||
|
|
||||||
- The `master` branch has a WASM-only binary for dendrite: `./cmd/dendritejs`.
|
- The `master` branch has a WASM-only binary for dendrite: `./cmd/dendritejs`.
|
||||||
- Build it and copy assets to riot-web.
|
- Build it and copy assets to riot-web.
|
||||||
```
|
```
|
||||||
$ GOOS=js GOARCH=wasm go build -o main.wasm ./cmd/dendritejs
|
$ ./build-dendritejs.sh
|
||||||
$ cp main.wasm ../riot-web/src/vector/dendrite.wasm
|
$ cp bin/main.wasm ../riot-web/src/vector/dendrite.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Test
|
||||||
|
|
||||||
|
To check that the Dendrite side is working well as Wasm, you can run the
|
||||||
|
Wasm-specific tests:
|
||||||
|
```
|
||||||
|
$ ./test-dendritejs.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Rendezvous
|
### Rendezvous
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeJoin implements the /make_join API
|
// MakeJoin implements the /make_join API
|
||||||
|
|
@ -228,6 +229,21 @@ func SendJoin(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that this is in fact a join event
|
||||||
|
membership, err := event.Membership()
|
||||||
|
if err != nil {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.BadJSON("missing content.membership key"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if membership != gomatrixserverlib.Join {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.BadJSON("membership must be 'join'"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the event is signed by the server sending the request.
|
// Check that the event is signed by the server sending the request.
|
||||||
redacted := event.Redact()
|
redacted := event.Redact()
|
||||||
verifyRequests := []gomatrixserverlib.VerifyJSONRequest{{
|
verifyRequests := []gomatrixserverlib.VerifyJSONRequest{{
|
||||||
|
|
@ -296,16 +312,26 @@ func SendJoin(
|
||||||
// We are responsible for notifying other servers that the user has joined
|
// We are responsible for notifying other servers that the user has joined
|
||||||
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
||||||
if !alreadyJoined {
|
if !alreadyJoined {
|
||||||
if err = api.SendEvents(
|
var response api.InputRoomEventsResponse
|
||||||
httpReq.Context(), rsAPI,
|
rsAPI.InputRoomEvents(httpReq.Context(), &api.InputRoomEventsRequest{
|
||||||
api.KindNew,
|
InputRoomEvents: []api.InputRoomEvent{
|
||||||
[]*gomatrixserverlib.HeaderedEvent{
|
{
|
||||||
event.Headered(stateAndAuthChainResponse.RoomVersion),
|
Kind: api.KindNew,
|
||||||
|
Event: event.Headered(stateAndAuthChainResponse.RoomVersion),
|
||||||
|
AuthEventIDs: event.AuthEventIDs(),
|
||||||
|
SendAsServer: string(cfg.Matrix.ServerName),
|
||||||
|
TransactionID: nil,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
cfg.Matrix.ServerName,
|
}, &response)
|
||||||
nil,
|
if response.ErrMsg != "" {
|
||||||
); err != nil {
|
util.GetLogger(httpReq.Context()).WithField(logrus.ErrorKey, response.ErrMsg).Error("SendEvents failed")
|
||||||
util.GetLogger(httpReq.Context()).WithError(err).Error("SendEvents failed")
|
if response.NotAllowed {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.Forbidden(response.ErrMsg),
|
||||||
|
}
|
||||||
|
}
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeLeave implements the /make_leave API
|
// MakeLeave implements the /make_leave API
|
||||||
|
|
@ -174,6 +175,13 @@ func SendLeave(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if event.StateKey() == nil {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.InvalidArgumentValue("missing state_key"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the user has already left. If so, no-op!
|
// Check if the user has already left. If so, no-op!
|
||||||
queryReq := &api.QueryLatestEventsAndStateRequest{
|
queryReq := &api.QueryLatestEventsAndStateRequest{
|
||||||
RoomID: roomID,
|
RoomID: roomID,
|
||||||
|
|
@ -240,7 +248,10 @@ func SendLeave(
|
||||||
mem, err := event.Membership()
|
mem, err := event.Membership()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.GetLogger(httpReq.Context()).WithError(err).Error("event.Membership failed")
|
util.GetLogger(httpReq.Context()).WithError(err).Error("event.Membership failed")
|
||||||
return jsonerror.InternalServerError()
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.BadJSON("missing content.membership key"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if mem != gomatrixserverlib.Leave {
|
if mem != gomatrixserverlib.Leave {
|
||||||
return util.JSONResponse{
|
return util.JSONResponse{
|
||||||
|
|
@ -252,16 +263,27 @@ func SendLeave(
|
||||||
// Send the events to the room server.
|
// Send the events to the room server.
|
||||||
// We are responsible for notifying other servers that the user has left
|
// We are responsible for notifying other servers that the user has left
|
||||||
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
// the room, so set SendAsServer to cfg.Matrix.ServerName
|
||||||
if err = api.SendEvents(
|
var response api.InputRoomEventsResponse
|
||||||
httpReq.Context(), rsAPI,
|
rsAPI.InputRoomEvents(httpReq.Context(), &api.InputRoomEventsRequest{
|
||||||
api.KindNew,
|
InputRoomEvents: []api.InputRoomEvent{
|
||||||
[]*gomatrixserverlib.HeaderedEvent{
|
{
|
||||||
event.Headered(verRes.RoomVersion),
|
Kind: api.KindNew,
|
||||||
|
Event: event.Headered(verRes.RoomVersion),
|
||||||
|
AuthEventIDs: event.AuthEventIDs(),
|
||||||
|
SendAsServer: string(cfg.Matrix.ServerName),
|
||||||
|
TransactionID: nil,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
cfg.Matrix.ServerName,
|
}, &response)
|
||||||
nil,
|
|
||||||
); err != nil {
|
if response.ErrMsg != "" {
|
||||||
util.GetLogger(httpReq.Context()).WithError(err).Error("producer.SendEvents failed")
|
util.GetLogger(httpReq.Context()).WithField(logrus.ErrorKey, response.ErrMsg).WithField("not_allowed", response.NotAllowed).Error("producer.SendEvents failed")
|
||||||
|
if response.NotAllowed {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: http.StatusBadRequest,
|
||||||
|
JSON: jsonerror.Forbidden(response.ErrMsg),
|
||||||
|
}
|
||||||
|
}
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ package sqlite3
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/federationsender/storage/shared"
|
"github.com/matrix-org/dendrite/federationsender/storage/shared"
|
||||||
"github.com/matrix-org/dendrite/federationsender/storage/sqlite3/deltas"
|
"github.com/matrix-org/dendrite/federationsender/storage/sqlite3/deltas"
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
"github.com/matrix-org/dendrite/internal/caching"
|
||||||
|
|
|
||||||
8
go.mod
8
go.mod
|
|
@ -1,7 +1,7 @@
|
||||||
module github.com/matrix-org/dendrite
|
module github.com/matrix-org/dendrite
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Arceliar/ironwood v0.0.0-20210619124114-6ad55cae5031 // indirect
|
github.com/Arceliar/ironwood v0.0.0-20210619124114-6ad55cae5031
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.0
|
github.com/DATA-DOG/go-sqlmock v1.5.0
|
||||||
github.com/HdrHistogram/hdrhistogram-go v1.0.1 // indirect
|
github.com/HdrHistogram/hdrhistogram-go v1.0.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.1.1
|
github.com/Masterminds/semver/v3 v3.1.1
|
||||||
|
|
@ -29,15 +29,15 @@ require (
|
||||||
github.com/lucas-clemente/quic-go v0.19.3
|
github.com/lucas-clemente/quic-go v0.19.3
|
||||||
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b
|
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b
|
||||||
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4
|
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20210625141222-bd2b7124cee8
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20210714141824-52d282133140
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20210722110442-5061d6986876
|
||||||
github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0
|
github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0
|
||||||
github.com/matrix-org/pinecone v0.0.0-20210623102758-74f885644c1b
|
github.com/matrix-org/pinecone v0.0.0-20210623102758-74f885644c1b
|
||||||
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
|
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
|
||||||
github.com/mattn/go-sqlite3 v1.14.7-0.20210414154423-1157a4212dcb
|
github.com/mattn/go-sqlite3 v1.14.7-0.20210414154423-1157a4212dcb
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/neilalexander/utp v0.1.1-0.20210705212447-691f29ad692b
|
github.com/neilalexander/utp v0.1.1-0.20210720104546-52626cdf31b2
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6
|
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6
|
||||||
github.com/opentracing/opentracing-go v1.2.0
|
github.com/opentracing/opentracing-go v1.2.0
|
||||||
|
|
|
||||||
15
go.sum
15
go.sum
|
|
@ -118,9 +118,7 @@ github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgw
|
||||||
github.com/anacrolix/missinggo v1.1.2-0.20190815015349-b888af804467/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
|
github.com/anacrolix/missinggo v1.1.2-0.20190815015349-b888af804467/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
|
||||||
github.com/anacrolix/missinggo v1.2.1 h1:0IE3TqX5y5D0IxeMwTyIgqdDew4QrzcXaaEnJQyjHvw=
|
github.com/anacrolix/missinggo v1.2.1 h1:0IE3TqX5y5D0IxeMwTyIgqdDew4QrzcXaaEnJQyjHvw=
|
||||||
github.com/anacrolix/missinggo v1.2.1/go.mod h1:J5cMhif8jPmFoC3+Uvob3OXXNIhOUikzMt+uUjeM21Y=
|
github.com/anacrolix/missinggo v1.2.1/go.mod h1:J5cMhif8jPmFoC3+Uvob3OXXNIhOUikzMt+uUjeM21Y=
|
||||||
github.com/anacrolix/missinggo/perf v1.0.0 h1:7ZOGYziGEBytW49+KmYGTaNfnwUqP1HBsy6BqESAJVw=
|
|
||||||
github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ=
|
github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ=
|
||||||
github.com/anacrolix/sync v0.2.0 h1:oRe22/ZB+v7v/5Mbc4d2zE0AXEZy0trKyKLjqYOt6tY=
|
|
||||||
github.com/anacrolix/sync v0.2.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g=
|
github.com/anacrolix/sync v0.2.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g=
|
||||||
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
||||||
github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk=
|
github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk=
|
||||||
|
|
@ -1024,13 +1022,13 @@ github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b h1:xpcmnpfUImRC4
|
||||||
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b/go.mod h1:NgPCr+UavRGH6n5jmdX8DuqFZ4JiCWIJoZiuhTRLSUg=
|
github.com/matrix-org/dugong v0.0.0-20180820122854-51a565b5666b/go.mod h1:NgPCr+UavRGH6n5jmdX8DuqFZ4JiCWIJoZiuhTRLSUg=
|
||||||
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 h1:eqE5OnGx9ZMWmrRbD3KF/3KtTunw0iQulI7YxOIdxo4=
|
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 h1:eqE5OnGx9ZMWmrRbD3KF/3KtTunw0iQulI7YxOIdxo4=
|
||||||
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4/go.mod h1:3WluEZ9QXSwU30tWYqktnpC1x9mwZKx1r8uAv8Iq+a4=
|
github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4/go.mod h1:3WluEZ9QXSwU30tWYqktnpC1x9mwZKx1r8uAv8Iq+a4=
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20210625141222-bd2b7124cee8 h1:/FKUeUlCATr1gXxYqlaJgH8FW/sw0Jz8t7s8BIlECfg=
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d h1:mGhPVaTht5NViFN/UpdrIlRApmH2FWcVaKUH5MdBKiY=
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20210625141222-bd2b7124cee8/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0=
|
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4=
|
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20210714141824-52d282133140 h1:EWOcw9M3zoXz45aLgaOCay31Xa2QzzMX6vRLh0xNbzY=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20210722110442-5061d6986876 h1:6ypwCtgRLK0v/hGWvnd847+KTo9BSkP9N0A4qSniP4E=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20210714141824-52d282133140/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20210722110442-5061d6986876/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU=
|
||||||
github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0 h1:HZCzy4oVzz55e+cOMiX/JtSF2UOY1evBl2raaE7ACcU=
|
github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0 h1:HZCzy4oVzz55e+cOMiX/JtSF2UOY1evBl2raaE7ACcU=
|
||||||
github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0/go.mod h1:sjyPyRxKM5uw1nD2cJ6O2OxI6GOqyVBfNXqKjBZTBZE=
|
github.com/matrix-org/naffka v0.0.0-20210623111924-14ff508b58e0/go.mod h1:sjyPyRxKM5uw1nD2cJ6O2OxI6GOqyVBfNXqKjBZTBZE=
|
||||||
github.com/matrix-org/pinecone v0.0.0-20210623102758-74f885644c1b h1:5X5vdWQ13xrNkJVqaJHPsrt7rKkMJH5iac0EtfOuxSg=
|
github.com/matrix-org/pinecone v0.0.0-20210623102758-74f885644c1b h1:5X5vdWQ13xrNkJVqaJHPsrt7rKkMJH5iac0EtfOuxSg=
|
||||||
|
|
@ -1185,10 +1183,9 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uY
|
||||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||||
github.com/neilalexander/utp v0.1.1-0.20210622132614-ee9a34a30488 h1:xZk82i6JK2d0SqRIXwaxj7J/NQB6ngq0PuMx3wXBaRQ=
|
|
||||||
github.com/neilalexander/utp v0.1.1-0.20210622132614-ee9a34a30488/go.mod h1:NPHGhPc0/wudcaCqL/H5AOddkRf8GPRhzOujuUKGQu8=
|
github.com/neilalexander/utp v0.1.1-0.20210622132614-ee9a34a30488/go.mod h1:NPHGhPc0/wudcaCqL/H5AOddkRf8GPRhzOujuUKGQu8=
|
||||||
github.com/neilalexander/utp v0.1.1-0.20210705212447-691f29ad692b h1:XNm+Ks3bVziRJxcMaIbzumWEw7l52z9Rek6cMHgln1g=
|
github.com/neilalexander/utp v0.1.1-0.20210720104546-52626cdf31b2 h1:txJOiDxsypF8RbzbcyOD3ovip+uUWNZE/Zo7qLdARZQ=
|
||||||
github.com/neilalexander/utp v0.1.1-0.20210705212447-691f29ad692b/go.mod h1:ylsx0342RjGHjOoVKhR/wz/7Lhiusonihfj4QLxEMcU=
|
github.com/neilalexander/utp v0.1.1-0.20210720104546-52626cdf31b2/go.mod h1:NPHGhPc0/wudcaCqL/H5AOddkRf8GPRhzOujuUKGQu8=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6 h1:evlcQnJY+v8XRRchV3hXzpHDl6GcEZeLXAhlH9Csdww=
|
github.com/ngrok/sqlmw v0.0.0-20200129213757-d5c93a81bec6 h1:evlcQnJY+v8XRRchV3hXzpHDl6GcEZeLXAhlH9Csdww=
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ func InitialPowerLevelsContent(roomCreator string) (c gomatrixserverlib.PowerLev
|
||||||
"m.room.history_visibility": 100,
|
"m.room.history_visibility": 100,
|
||||||
"m.room.canonical_alias": 50,
|
"m.room.canonical_alias": 50,
|
||||||
"m.room.avatar": 50,
|
"m.room.avatar": 50,
|
||||||
"m.room.aliases": 0, // anyone can publish aliases by default. Has to be 0 else state_default is used.
|
|
||||||
}
|
}
|
||||||
c.Users = map[string]int64{roomCreator: 100}
|
c.Users = map[string]int64{roomCreator: 100}
|
||||||
return c
|
return c
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/matrix-org/util"
|
"github.com/matrix-org/util"
|
||||||
|
|
@ -113,13 +112,6 @@ func QueryVariadicOffset(count, offset int) string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func SQLiteDriverName() string {
|
|
||||||
if runtime.GOOS == "js" {
|
|
||||||
return "sqlite3_js"
|
|
||||||
}
|
|
||||||
return "sqlite3"
|
|
||||||
}
|
|
||||||
|
|
||||||
func minOfInts(a, b int) int {
|
func minOfInts(a, b int) int {
|
||||||
if a <= b {
|
if a <= b {
|
||||||
return a
|
return a
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ func Open(dbProperties *config.DatabaseOptions) (*sql.DB, error) {
|
||||||
var driverName, dsn string
|
var driverName, dsn string
|
||||||
switch {
|
switch {
|
||||||
case dbProperties.ConnectionString.IsSQLite():
|
case dbProperties.ConnectionString.IsSQLite():
|
||||||
driverName = SQLiteDriverName()
|
driverName = "sqlite3"
|
||||||
dsn, err = ParseFileURI(dbProperties.ConnectionString)
|
dsn, err = ParseFileURI(dbProperties.ConnectionString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("ParseFileURI: %w", err)
|
return nil, fmt.Errorf("ParseFileURI: %w", err)
|
||||||
|
|
@ -123,11 +123,11 @@ func Open(dbProperties *config.DatabaseOptions) (*sql.DB, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if driverName != SQLiteDriverName() {
|
if driverName != "sqlite3" {
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"MaxOpenConns": dbProperties.MaxOpenConns,
|
"MaxOpenConns": dbProperties.MaxOpenConns(),
|
||||||
"MaxIdleConns": dbProperties.MaxIdleConns,
|
"MaxIdleConns": dbProperties.MaxIdleConns(),
|
||||||
"ConnMaxLifetime": dbProperties.ConnMaxLifetime,
|
"ConnMaxLifetime": dbProperties.ConnMaxLifetime(),
|
||||||
"dataSourceName": regexp.MustCompile(`://[^@]*@`).ReplaceAllLiteralString(dsn, "://"),
|
"dataSourceName": regexp.MustCompile(`://[^@]*@`).ReplaceAllLiteralString(dsn, "://"),
|
||||||
}).Debug("Setting DB connection limits")
|
}).Debug("Setting DB connection limits")
|
||||||
db.SetMaxOpenConns(dbProperties.MaxOpenConns())
|
db.SetMaxOpenConns(dbProperties.MaxOpenConns())
|
||||||
|
|
|
||||||
|
|
@ -147,20 +147,17 @@ func (r *uploadRequest) doUpload(
|
||||||
// r.storeFileAndMetadata(ctx, tmpDir, ...)
|
// r.storeFileAndMetadata(ctx, tmpDir, ...)
|
||||||
// before you return from doUpload else we will leak a temp file. We could make this nicer with a `WithTransaction` style of
|
// before you return from doUpload else we will leak a temp file. We could make this nicer with a `WithTransaction` style of
|
||||||
// nested function to guarantee either storage or cleanup.
|
// nested function to guarantee either storage or cleanup.
|
||||||
|
if *cfg.MaxFileSizeBytes > 0 {
|
||||||
// should not happen, but prevents any int overflows
|
if *cfg.MaxFileSizeBytes+1 <= 0 {
|
||||||
if cfg.MaxFileSizeBytes != nil && *cfg.MaxFileSizeBytes+1 <= 0 {
|
r.Logger.WithFields(log.Fields{
|
||||||
r.Logger.WithFields(log.Fields{
|
"MaxFileSizeBytes": *cfg.MaxFileSizeBytes,
|
||||||
"MaxFileSizeBytes": *cfg.MaxFileSizeBytes + 1,
|
}).Warnf("Configured MaxFileSizeBytes overflows int64, defaulting to %d bytes", config.DefaultMaxFileSizeBytes)
|
||||||
}).Error("Error while transferring file, configured max_file_size_bytes overflows int64")
|
cfg.MaxFileSizeBytes = &config.DefaultMaxFileSizeBytes
|
||||||
return &util.JSONResponse{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
JSON: jsonerror.Unknown("Failed to upload"),
|
|
||||||
}
|
}
|
||||||
|
reqReader = io.LimitReader(reqReader, int64(*cfg.MaxFileSizeBytes)+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
lr := io.LimitReader(reqReader, int64(*cfg.MaxFileSizeBytes)+1)
|
hash, bytesWritten, tmpDir, err := fileutils.WriteTempFile(ctx, reqReader, cfg.AbsBasePath)
|
||||||
hash, bytesWritten, tmpDir, err := fileutils.WriteTempFile(ctx, lr, cfg.AbsBasePath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Logger.WithError(err).WithFields(log.Fields{
|
r.Logger.WithError(err).WithFields(log.Fields{
|
||||||
"MaxFileSizeBytes": *cfg.MaxFileSizeBytes,
|
"MaxFileSizeBytes": *cfg.MaxFileSizeBytes,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/mediaapi/types"
|
"github.com/matrix-org/dendrite/mediaapi/types"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Database is used to store metadata about a repository of media files.
|
// Database is used to store metadata about a repository of media files.
|
||||||
|
|
|
||||||
|
|
@ -78,4 +78,9 @@ type RemoveRoomAliasRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveRoomAliasResponse is a response to RemoveRoomAlias
|
// RemoveRoomAliasResponse is a response to RemoveRoomAlias
|
||||||
type RemoveRoomAliasResponse struct{}
|
type RemoveRoomAliasResponse struct {
|
||||||
|
// Did the alias exist before?
|
||||||
|
Found bool `json:"found"`
|
||||||
|
// Did we remove it?
|
||||||
|
Removed bool `json:"removed"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,11 +181,8 @@ type QueryServerJoinedToRoomRequest struct {
|
||||||
type QueryServerJoinedToRoomResponse struct {
|
type QueryServerJoinedToRoomResponse struct {
|
||||||
// True if the room exists on the server
|
// True if the room exists on the server
|
||||||
RoomExists bool `json:"room_exists"`
|
RoomExists bool `json:"room_exists"`
|
||||||
// True if we still believe that we are participating in the room
|
// True if we still believe that the server is participating in the room
|
||||||
IsInRoom bool `json:"is_in_room"`
|
IsInRoom bool `json:"is_in_room"`
|
||||||
// List of servers that are also in the room. This will not be populated
|
|
||||||
// if the queried ServerName is the local server name.
|
|
||||||
ServerNames []gomatrixserverlib.ServerName `json:"server_names"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent
|
// QueryServerAllowedToSeeEventRequest is a request to QueryServerAllowedToSeeEvent
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,7 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
@ -73,11 +70,7 @@ func (r *RoomserverInternalAPI) SetRoomAlias(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a m.room.aliases event with the updated list of aliases for this room
|
return nil
|
||||||
// At this point we've already committed the alias to the database so we
|
|
||||||
// shouldn't cancel this request.
|
|
||||||
// TODO: Ensure that we send unsent events when if server restarts.
|
|
||||||
return r.sendUpdatedAliasesEvent(context.TODO(), request.UserID, request.RoomID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRoomIDForAlias implements alias.RoomserverInternalAPI
|
// GetRoomIDForAlias implements alias.RoomserverInternalAPI
|
||||||
|
|
@ -157,122 +150,44 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
|
||||||
request *api.RemoveRoomAliasRequest,
|
request *api.RemoveRoomAliasRequest,
|
||||||
response *api.RemoveRoomAliasResponse,
|
response *api.RemoveRoomAliasResponse,
|
||||||
) error {
|
) error {
|
||||||
// Look up the room ID in the database
|
|
||||||
roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
|
roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("r.DB.GetRoomIDForAlias: %w", err)
|
||||||
|
}
|
||||||
|
if roomID == "" {
|
||||||
|
response.Found = false
|
||||||
|
response.Removed = false
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the dalias from the database
|
response.Found = true
|
||||||
|
creatorID, err := r.DB.GetCreatorIDForAlias(ctx, request.Alias)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("r.DB.GetCreatorIDForAlias: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if creatorID != request.UserID {
|
||||||
|
plEvent, err := r.DB.GetStateEvent(ctx, roomID, gomatrixserverlib.MRoomPowerLevels, "")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("r.DB.GetStateEvent: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pls, err := plEvent.PowerLevels()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("plEvent.PowerLevels: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pls.UserLevel(request.UserID) < pls.EventLevel(gomatrixserverlib.MRoomCanonicalAlias, true) {
|
||||||
|
response.Removed = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the alias from the database
|
||||||
if err := r.DB.RemoveRoomAlias(ctx, request.Alias); err != nil {
|
if err := r.DB.RemoveRoomAlias(ctx, request.Alias); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send an updated m.room.aliases event
|
response.Removed = true
|
||||||
// At this point we've already committed the alias to the database so we
|
return nil
|
||||||
// shouldn't cancel this request.
|
|
||||||
// TODO: Ensure that we send unsent events when if server restarts.
|
|
||||||
return r.sendUpdatedAliasesEvent(context.TODO(), request.UserID, roomID)
|
|
||||||
}
|
|
||||||
|
|
||||||
type roomAliasesContent struct {
|
|
||||||
Aliases []string `json:"aliases"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the updated m.room.aliases event to send to the room after addition or
|
|
||||||
// removal of an alias
|
|
||||||
func (r *RoomserverInternalAPI) sendUpdatedAliasesEvent(
|
|
||||||
ctx context.Context, userID string, roomID string,
|
|
||||||
) error {
|
|
||||||
serverName := string(r.Cfg.Matrix.ServerName)
|
|
||||||
|
|
||||||
builder := gomatrixserverlib.EventBuilder{
|
|
||||||
Sender: userID,
|
|
||||||
RoomID: roomID,
|
|
||||||
Type: "m.room.aliases",
|
|
||||||
StateKey: &serverName,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the updated list of aliases, marhal it and set it as the
|
|
||||||
// event's content
|
|
||||||
aliases, err := r.DB.GetAliasesForRoomID(ctx, roomID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
content := roomAliasesContent{Aliases: aliases}
|
|
||||||
rawContent, err := json.Marshal(content)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = builder.SetContent(json.RawMessage(rawContent))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get needed state events and depth
|
|
||||||
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(&builder)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(eventsNeeded.Tuples()) == 0 {
|
|
||||||
return errors.New("expecting state tuples for event builder, got none")
|
|
||||||
}
|
|
||||||
req := api.QueryLatestEventsAndStateRequest{
|
|
||||||
RoomID: roomID,
|
|
||||||
StateToFetch: eventsNeeded.Tuples(),
|
|
||||||
}
|
|
||||||
var res api.QueryLatestEventsAndStateResponse
|
|
||||||
if err = r.QueryLatestEventsAndState(ctx, &req, &res); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
builder.Depth = res.Depth
|
|
||||||
builder.PrevEvents = res.LatestEvents
|
|
||||||
|
|
||||||
// Add auth events
|
|
||||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
|
||||||
for i := range res.StateEvents {
|
|
||||||
err = authEvents.AddEvent(res.StateEvents[i].Event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refs, err := eventsNeeded.AuthEventReferences(&authEvents)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
builder.AuthEvents = refs
|
|
||||||
|
|
||||||
roomInfo, err := r.DB.RoomInfo(ctx, roomID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if roomInfo == nil {
|
|
||||||
return fmt.Errorf("room %s does not exist", roomID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the event
|
|
||||||
now := time.Now()
|
|
||||||
event, err := builder.Build(
|
|
||||||
now, r.Cfg.Matrix.ServerName, r.Cfg.Matrix.KeyID,
|
|
||||||
r.Cfg.Matrix.PrivateKey, roomInfo.RoomVersion,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the request
|
|
||||||
ire := api.InputRoomEvent{
|
|
||||||
Kind: api.KindNew,
|
|
||||||
Event: event.Headered(roomInfo.RoomVersion),
|
|
||||||
AuthEventIDs: event.AuthEventIDs(),
|
|
||||||
SendAsServer: serverName,
|
|
||||||
}
|
|
||||||
inputReq := api.InputRoomEventsRequest{
|
|
||||||
InputRoomEvents: []api.InputRoomEvent{ire},
|
|
||||||
}
|
|
||||||
var inputRes api.InputRoomEventsResponse
|
|
||||||
|
|
||||||
// Send the request
|
|
||||||
r.InputRoomEvents(ctx, &inputReq, &inputRes)
|
|
||||||
return inputRes.Err()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@ func (r *Inputer) updateMembership(
|
||||||
return updateToJoinMembership(mu, add, updates)
|
return updateToJoinMembership(mu, add, updates)
|
||||||
case gomatrixserverlib.Leave, gomatrixserverlib.Ban:
|
case gomatrixserverlib.Leave, gomatrixserverlib.Ban:
|
||||||
return updateToLeaveMembership(mu, add, newMembership, updates)
|
return updateToLeaveMembership(mu, add, newMembership, updates)
|
||||||
|
case gomatrixserverlib.Knock:
|
||||||
|
return updateToKnockMembership(mu, add, updates)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
"input: membership %q is not one of the allowed values", newMembership,
|
"input: membership %q is not one of the allowed values", newMembership,
|
||||||
|
|
@ -220,6 +222,18 @@ func updateToLeaveMembership(
|
||||||
return updates, nil
|
return updates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateToKnockMembership(
|
||||||
|
mu *shared.MembershipUpdater, add *gomatrixserverlib.Event, updates []api.OutputEvent,
|
||||||
|
) ([]api.OutputEvent, error) {
|
||||||
|
if mu.IsLeave() {
|
||||||
|
_, err := mu.SetToKnock(add)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updates, nil
|
||||||
|
}
|
||||||
|
|
||||||
// membershipChanges pairs up the membership state changes.
|
// membershipChanges pairs up the membership state changes.
|
||||||
func membershipChanges(removed, added []types.StateEntry) []stateChange {
|
func membershipChanges(removed, added []types.StateEntry) []stateChange {
|
||||||
changes := pairUpChanges(removed, added)
|
changes := pairUpChanges(removed, added)
|
||||||
|
|
|
||||||
|
|
@ -223,8 +223,8 @@ func buildInviteStrippedState(
|
||||||
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-member
|
// https://matrix.org/docs/spec/client_server/r0.6.0#m-room-member
|
||||||
for _, t := range []string{
|
for _, t := range []string{
|
||||||
gomatrixserverlib.MRoomName, gomatrixserverlib.MRoomCanonicalAlias,
|
gomatrixserverlib.MRoomName, gomatrixserverlib.MRoomCanonicalAlias,
|
||||||
gomatrixserverlib.MRoomAliases, gomatrixserverlib.MRoomJoinRules,
|
gomatrixserverlib.MRoomJoinRules, gomatrixserverlib.MRoomAvatar,
|
||||||
"m.room.avatar", "m.room.encryption", gomatrixserverlib.MRoomCreate,
|
gomatrixserverlib.MRoomEncryption, gomatrixserverlib.MRoomCreate,
|
||||||
} {
|
} {
|
||||||
stateWanted = append(stateWanted, gomatrixserverlib.StateKeyTuple{
|
stateWanted = append(stateWanted, gomatrixserverlib.StateKeyTuple{
|
||||||
EventType: t,
|
EventType: t,
|
||||||
|
|
|
||||||
|
|
@ -330,46 +330,17 @@ func (r *Queryer) QueryServerJoinedToRoom(
|
||||||
response.RoomExists = true
|
response.RoomExists = true
|
||||||
|
|
||||||
if request.ServerName == r.ServerName || request.ServerName == "" {
|
if request.ServerName == r.ServerName || request.ServerName == "" {
|
||||||
var joined bool
|
response.IsInRoom, err = r.DB.GetLocalServerInRoom(ctx, info.RoomNID)
|
||||||
joined, err = r.DB.GetLocalServerInRoom(ctx, info.RoomNID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("r.DB.GetLocalServerInRoom: %w", err)
|
return fmt.Errorf("r.DB.GetLocalServerInRoom: %w", err)
|
||||||
}
|
}
|
||||||
response.IsInRoom = joined
|
} else {
|
||||||
return nil
|
response.IsInRoom, err = r.DB.GetServerInRoom(ctx, info.RoomNID, request.ServerName)
|
||||||
}
|
if err != nil {
|
||||||
|
return fmt.Errorf("r.DB.GetServerInRoom: %w", err)
|
||||||
eventNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, true, false)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err)
|
|
||||||
}
|
|
||||||
if len(eventNIDs) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
events, err := r.DB.Events(ctx, eventNIDs)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("r.DB.Events: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
servers := map[gomatrixserverlib.ServerName]struct{}{}
|
|
||||||
for _, e := range events {
|
|
||||||
if e.Type() == gomatrixserverlib.MRoomMember && e.StateKey() != nil {
|
|
||||||
_, serverName, err := gomatrixserverlib.SplitID('@', *e.StateKey())
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
servers[serverName] = struct{}{}
|
|
||||||
if serverName == request.ServerName {
|
|
||||||
response.IsInRoom = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for server := range servers {
|
|
||||||
response.ServerNames = append(response.ServerNames, server)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -424,12 +424,17 @@ func (v *StateResolution) loadStateAfterEventsForNumericTuples(
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var calculateStateDurations = prometheus.NewSummaryVec(
|
var calculateStateDurations = prometheus.NewHistogramVec(
|
||||||
prometheus.SummaryOpts{
|
prometheus.HistogramOpts{
|
||||||
Namespace: "dendrite",
|
Namespace: "dendrite",
|
||||||
Subsystem: "roomserver",
|
Subsystem: "roomserver",
|
||||||
Name: "calculate_state_duration_microseconds",
|
Name: "calculate_state_duration_milliseconds",
|
||||||
Help: "How long it takes to calculate the state after a list of events",
|
Help: "How long it takes to calculate the state after a list of events",
|
||||||
|
Buckets: []float64{ // milliseconds
|
||||||
|
5, 10, 25, 50, 75, 100, 200, 300, 400, 500,
|
||||||
|
1000, 2000, 3000, 4000, 5000, 6000,
|
||||||
|
7000, 8000, 9000, 10000, 15000, 20000, 30000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// Takes two labels:
|
// Takes two labels:
|
||||||
// algorithm:
|
// algorithm:
|
||||||
|
|
@ -496,9 +501,8 @@ func (c *calculateStateMetrics) stop(stateNID types.StateSnapshotNID, err error)
|
||||||
} else {
|
} else {
|
||||||
outcome = "failure"
|
outcome = "failure"
|
||||||
}
|
}
|
||||||
endTime := time.Now()
|
|
||||||
calculateStateDurations.WithLabelValues(c.algorithm, outcome).Observe(
|
calculateStateDurations.WithLabelValues(c.algorithm, outcome).Observe(
|
||||||
float64(endTime.Sub(c.startTime).Nanoseconds()) / 1000.,
|
float64(time.Since(c.startTime).Milliseconds()),
|
||||||
)
|
)
|
||||||
calculateStatePrevEventLength.WithLabelValues(c.algorithm, outcome).Observe(
|
calculateStatePrevEventLength.WithLabelValues(c.algorithm, outcome).Observe(
|
||||||
float64(c.prevEventLength),
|
float64(c.prevEventLength),
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,8 @@ type Database interface {
|
||||||
JoinedUsersSetInRooms(ctx context.Context, roomIDs []string) (map[string]int, error)
|
JoinedUsersSetInRooms(ctx context.Context, roomIDs []string) (map[string]int, error)
|
||||||
// GetLocalServerInRoom returns true if we think we're in a given room or false otherwise.
|
// GetLocalServerInRoom returns true if we think we're in a given room or false otherwise.
|
||||||
GetLocalServerInRoom(ctx context.Context, roomNID types.RoomNID) (bool, error)
|
GetLocalServerInRoom(ctx context.Context, roomNID types.RoomNID) (bool, error)
|
||||||
|
// GetServerInRoom returns true if we think a server is in a given room or false otherwise.
|
||||||
|
GetServerInRoom(ctx context.Context, roomNID types.RoomNID, serverName gomatrixserverlib.ServerName) (bool, error)
|
||||||
// GetKnownUsers searches all users that userID knows about.
|
// GetKnownUsers searches all users that userID knows about.
|
||||||
GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error)
|
GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error)
|
||||||
// GetKnownRooms returns a list of all rooms we know about.
|
// GetKnownRooms returns a list of all rooms we know about.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const membershipSchema = `
|
const membershipSchema = `
|
||||||
|
|
@ -132,6 +133,16 @@ var selectKnownUsersSQL = "" +
|
||||||
const selectLocalServerInRoomSQL = "" +
|
const selectLocalServerInRoomSQL = "" +
|
||||||
"SELECT room_nid FROM roomserver_membership WHERE target_local = true AND membership_nid = $1 AND room_nid = $2 LIMIT 1"
|
"SELECT room_nid FROM roomserver_membership WHERE target_local = true AND membership_nid = $1 AND room_nid = $2 LIMIT 1"
|
||||||
|
|
||||||
|
// selectServerMembersInRoomSQL is an optimised case for checking for server members in a room.
|
||||||
|
// The JOIN is significantly leaner than the previous case of looking up event NIDs and reading the
|
||||||
|
// membership events from the database, as the JOIN query amounts to little more than two index
|
||||||
|
// scans which are very fast. The presence of a single row from this query suggests the server is
|
||||||
|
// in the room, no rows returned suggests they aren't.
|
||||||
|
const selectServerInRoomSQL = "" +
|
||||||
|
"SELECT room_nid FROM roomserver_membership" +
|
||||||
|
" JOIN roomserver_event_state_keys ON roomserver_membership.target_nid = roomserver_event_state_keys.event_state_key_nid" +
|
||||||
|
" WHERE membership_nid = $1 AND room_nid = $2 AND event_state_key LIKE '%:' || $3 LIMIT 1"
|
||||||
|
|
||||||
type membershipStatements struct {
|
type membershipStatements struct {
|
||||||
insertMembershipStmt *sql.Stmt
|
insertMembershipStmt *sql.Stmt
|
||||||
selectMembershipForUpdateStmt *sql.Stmt
|
selectMembershipForUpdateStmt *sql.Stmt
|
||||||
|
|
@ -146,6 +157,7 @@ type membershipStatements struct {
|
||||||
selectKnownUsersStmt *sql.Stmt
|
selectKnownUsersStmt *sql.Stmt
|
||||||
updateMembershipForgetRoomStmt *sql.Stmt
|
updateMembershipForgetRoomStmt *sql.Stmt
|
||||||
selectLocalServerInRoomStmt *sql.Stmt
|
selectLocalServerInRoomStmt *sql.Stmt
|
||||||
|
selectServerInRoomStmt *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMembershipTable(db *sql.DB) error {
|
func createMembershipTable(db *sql.DB) error {
|
||||||
|
|
@ -170,6 +182,7 @@ func prepareMembershipTable(db *sql.DB) (tables.Membership, error) {
|
||||||
{&s.selectKnownUsersStmt, selectKnownUsersSQL},
|
{&s.selectKnownUsersStmt, selectKnownUsersSQL},
|
||||||
{&s.updateMembershipForgetRoomStmt, updateMembershipForgetRoom},
|
{&s.updateMembershipForgetRoomStmt, updateMembershipForgetRoom},
|
||||||
{&s.selectLocalServerInRoomStmt, selectLocalServerInRoomSQL},
|
{&s.selectLocalServerInRoomStmt, selectLocalServerInRoomSQL},
|
||||||
|
{&s.selectServerInRoomStmt, selectServerInRoomSQL},
|
||||||
}.Prepare(db)
|
}.Prepare(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,3 +360,15 @@ func (s *membershipStatements) SelectLocalServerInRoom(ctx context.Context, room
|
||||||
found := nid > 0
|
found := nid > 0
|
||||||
return found, nil
|
return found, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *membershipStatements) SelectServerInRoom(ctx context.Context, roomNID types.RoomNID, serverName gomatrixserverlib.ServerName) (bool, error) {
|
||||||
|
var nid types.RoomNID
|
||||||
|
err := s.selectServerInRoomStmt.QueryRowContext(ctx, tables.MembershipStateJoin, roomNID, serverName).Scan(&nid)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return roomNID == nid, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,11 @@ func (u *MembershipUpdater) IsLeave() bool {
|
||||||
return u.membership == tables.MembershipStateLeaveOrBan
|
return u.membership == tables.MembershipStateLeaveOrBan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsKnock implements types.MembershipUpdater
|
||||||
|
func (u *MembershipUpdater) IsKnock() bool {
|
||||||
|
return u.membership == tables.MembershipStateKnock
|
||||||
|
}
|
||||||
|
|
||||||
// SetToInvite implements types.MembershipUpdater
|
// SetToInvite implements types.MembershipUpdater
|
||||||
func (u *MembershipUpdater) SetToInvite(event gomatrixserverlib.Event) (bool, error) {
|
func (u *MembershipUpdater) SetToInvite(event gomatrixserverlib.Event) (bool, error) {
|
||||||
var inserted bool
|
var inserted bool
|
||||||
|
|
@ -180,3 +185,27 @@ func (u *MembershipUpdater) SetToLeave(senderUserID string, eventID string) ([]s
|
||||||
})
|
})
|
||||||
return inviteEventIDs, err
|
return inviteEventIDs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetToKnock implements types.MembershipUpdater
|
||||||
|
func (u *MembershipUpdater) SetToKnock(event *gomatrixserverlib.Event) (bool, error) {
|
||||||
|
var inserted bool
|
||||||
|
err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error {
|
||||||
|
senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, event.Sender())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("u.d.AssignStateKeyNID: %w", err)
|
||||||
|
}
|
||||||
|
if u.membership != tables.MembershipStateKnock {
|
||||||
|
// Look up the NID of the new knock event
|
||||||
|
nIDs, err := u.d.EventNIDs(u.ctx, []string{event.EventID()})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("u.d.EventNIDs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = u.d.MembershipTable.UpdateMembership(u.ctx, u.txn, u.roomNID, u.targetUserNID, senderUserNID, tables.MembershipStateKnock, nIDs[event.EventID()], false); err != nil {
|
||||||
|
return fmt.Errorf("u.d.MembershipTable.UpdateMembership: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return inserted, err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -857,6 +857,9 @@ func (d *Database) GetStateEvent(ctx context.Context, roomID, evType, stateKey s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if roomInfo == nil || roomInfo.IsStub {
|
||||||
|
return nil, fmt.Errorf("room %s doesn't exist", roomID)
|
||||||
|
}
|
||||||
eventTypeNID, err := d.EventTypesTable.SelectEventTypeNID(ctx, nil, evType)
|
eventTypeNID, err := d.EventTypesTable.SelectEventTypeNID(ctx, nil, evType)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
// No rooms have an event of this type, otherwise we'd have an event type NID
|
// No rooms have an event of this type, otherwise we'd have an event type NID
|
||||||
|
|
@ -866,6 +869,10 @@ func (d *Database) GetStateEvent(ctx context.Context, roomID, evType, stateKey s
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
stateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, stateKey)
|
stateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, stateKey)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
// No rooms have a state event with this state key, otherwise we'd have an state key NID
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1064,6 +1071,11 @@ func (d *Database) GetLocalServerInRoom(ctx context.Context, roomNID types.RoomN
|
||||||
return d.MembershipTable.SelectLocalServerInRoom(ctx, roomNID)
|
return d.MembershipTable.SelectLocalServerInRoom(ctx, roomNID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetServerInRoom returns true if we think a server is in a given room or false otherwise.
|
||||||
|
func (d *Database) GetServerInRoom(ctx context.Context, roomNID types.RoomNID, serverName gomatrixserverlib.ServerName) (bool, error) {
|
||||||
|
return d.MembershipTable.SelectServerInRoom(ctx, roomNID, serverName)
|
||||||
|
}
|
||||||
|
|
||||||
// GetKnownUsers searches all users that userID knows about.
|
// GetKnownUsers searches all users that userID knows about.
|
||||||
func (d *Database) GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) {
|
func (d *Database) GetKnownUsers(ctx context.Context, userID, searchString string, limit int) ([]string, error) {
|
||||||
stateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, userID)
|
stateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, userID)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const membershipSchema = `
|
const membershipSchema = `
|
||||||
|
|
@ -108,6 +109,16 @@ var selectKnownUsersSQL = "" +
|
||||||
const selectLocalServerInRoomSQL = "" +
|
const selectLocalServerInRoomSQL = "" +
|
||||||
"SELECT room_nid FROM roomserver_membership WHERE target_local = 1 AND membership_nid = $1 AND room_nid = $2 LIMIT 1"
|
"SELECT room_nid FROM roomserver_membership WHERE target_local = 1 AND membership_nid = $1 AND room_nid = $2 LIMIT 1"
|
||||||
|
|
||||||
|
// selectServerMembersInRoomSQL is an optimised case for checking for server members in a room.
|
||||||
|
// The JOIN is significantly leaner than the previous case of looking up event NIDs and reading the
|
||||||
|
// membership events from the database, as the JOIN query amounts to little more than two index
|
||||||
|
// scans which are very fast. The presence of a single row from this query suggests the server is
|
||||||
|
// in the room, no rows returned suggests they aren't.
|
||||||
|
const selectServerInRoomSQL = "" +
|
||||||
|
"SELECT room_nid FROM roomserver_membership" +
|
||||||
|
" JOIN roomserver_event_state_keys ON roomserver_membership.target_nid = roomserver_event_state_keys.event_state_key_nid" +
|
||||||
|
" WHERE membership_nid = $1 AND room_nid = $2 AND event_state_key LIKE '%:' || $3 LIMIT 1"
|
||||||
|
|
||||||
type membershipStatements struct {
|
type membershipStatements struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
insertMembershipStmt *sql.Stmt
|
insertMembershipStmt *sql.Stmt
|
||||||
|
|
@ -122,6 +133,7 @@ type membershipStatements struct {
|
||||||
selectKnownUsersStmt *sql.Stmt
|
selectKnownUsersStmt *sql.Stmt
|
||||||
updateMembershipForgetRoomStmt *sql.Stmt
|
updateMembershipForgetRoomStmt *sql.Stmt
|
||||||
selectLocalServerInRoomStmt *sql.Stmt
|
selectLocalServerInRoomStmt *sql.Stmt
|
||||||
|
selectServerInRoomStmt *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMembershipTable(db *sql.DB) error {
|
func createMembershipTable(db *sql.DB) error {
|
||||||
|
|
@ -147,6 +159,7 @@ func prepareMembershipTable(db *sql.DB) (tables.Membership, error) {
|
||||||
{&s.selectKnownUsersStmt, selectKnownUsersSQL},
|
{&s.selectKnownUsersStmt, selectKnownUsersSQL},
|
||||||
{&s.updateMembershipForgetRoomStmt, updateMembershipForgetRoom},
|
{&s.updateMembershipForgetRoomStmt, updateMembershipForgetRoom},
|
||||||
{&s.selectLocalServerInRoomStmt, selectLocalServerInRoomSQL},
|
{&s.selectLocalServerInRoomStmt, selectLocalServerInRoomSQL},
|
||||||
|
{&s.selectServerInRoomStmt, selectServerInRoomSQL},
|
||||||
}.Prepare(db)
|
}.Prepare(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,3 +340,15 @@ func (s *membershipStatements) SelectLocalServerInRoom(ctx context.Context, room
|
||||||
found := nid > 0
|
found := nid > 0
|
||||||
return found, nil
|
return found, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *membershipStatements) SelectServerInRoom(ctx context.Context, roomNID types.RoomNID, serverName gomatrixserverlib.ServerName) (bool, error) {
|
||||||
|
var nid types.RoomNID
|
||||||
|
err := s.selectServerInRoomStmt.QueryRowContext(ctx, tables.MembershipStateJoin, roomNID, serverName).Scan(&nid)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return roomNID == nid, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
"github.com/matrix-org/dendrite/internal/caching"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ const (
|
||||||
MembershipStateLeaveOrBan MembershipState = 1
|
MembershipStateLeaveOrBan MembershipState = 1
|
||||||
MembershipStateInvite MembershipState = 2
|
MembershipStateInvite MembershipState = 2
|
||||||
MembershipStateJoin MembershipState = 3
|
MembershipStateJoin MembershipState = 3
|
||||||
|
MembershipStateKnock MembershipState = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
type Membership interface {
|
type Membership interface {
|
||||||
|
|
@ -136,6 +137,7 @@ type Membership interface {
|
||||||
SelectKnownUsers(ctx context.Context, userID types.EventStateKeyNID, searchString string, limit int) ([]string, error)
|
SelectKnownUsers(ctx context.Context, userID types.EventStateKeyNID, searchString string, limit int) ([]string, error)
|
||||||
UpdateForgetMembership(ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, forget bool) error
|
UpdateForgetMembership(ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, forget bool) error
|
||||||
SelectLocalServerInRoom(ctx context.Context, roomNID types.RoomNID) (bool, error)
|
SelectLocalServerInRoom(ctx context.Context, roomNID types.RoomNID) (bool, error)
|
||||||
|
SelectServerInRoom(ctx context.Context, roomNID types.RoomNID, serverName gomatrixserverlib.ServerName) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Published interface {
|
type Published interface {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MediaAPI struct {
|
type MediaAPI struct {
|
||||||
|
|
@ -36,6 +35,9 @@ type MediaAPI struct {
|
||||||
ThumbnailSizes []ThumbnailSize `yaml:"thumbnail_sizes"`
|
ThumbnailSizes []ThumbnailSize `yaml:"thumbnail_sizes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultMaxFileSizeBytes defines the default file size allowed in transfers
|
||||||
|
var DefaultMaxFileSizeBytes = FileSizeBytes(10485760)
|
||||||
|
|
||||||
func (c *MediaAPI) Defaults() {
|
func (c *MediaAPI) Defaults() {
|
||||||
c.InternalAPI.Listen = "http://localhost:7774"
|
c.InternalAPI.Listen = "http://localhost:7774"
|
||||||
c.InternalAPI.Connect = "http://localhost:7774"
|
c.InternalAPI.Connect = "http://localhost:7774"
|
||||||
|
|
@ -43,8 +45,7 @@ func (c *MediaAPI) Defaults() {
|
||||||
c.Database.Defaults(5)
|
c.Database.Defaults(5)
|
||||||
c.Database.ConnectionString = "file:mediaapi.db"
|
c.Database.ConnectionString = "file:mediaapi.db"
|
||||||
|
|
||||||
defaultMaxFileSizeBytes := FileSizeBytes(10485760)
|
c.MaxFileSizeBytes = &DefaultMaxFileSizeBytes
|
||||||
c.MaxFileSizeBytes = &defaultMaxFileSizeBytes
|
|
||||||
c.MaxThumbnailGenerators = 10
|
c.MaxThumbnailGenerators = 10
|
||||||
c.BasePath = "./media_store"
|
c.BasePath = "./media_store"
|
||||||
}
|
}
|
||||||
|
|
@ -58,11 +59,6 @@ func (c *MediaAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
|
||||||
checkNotEmpty(configErrs, "media_api.database.connection_string", string(c.Database.ConnectionString))
|
checkNotEmpty(configErrs, "media_api.database.connection_string", string(c.Database.ConnectionString))
|
||||||
|
|
||||||
checkNotEmpty(configErrs, "media_api.base_path", string(c.BasePath))
|
checkNotEmpty(configErrs, "media_api.base_path", string(c.BasePath))
|
||||||
// allow "unlimited" file size
|
|
||||||
if c.MaxFileSizeBytes != nil && *c.MaxFileSizeBytes <= 0 {
|
|
||||||
unlimitedSize := FileSizeBytes(math.MaxInt64 - 1)
|
|
||||||
c.MaxFileSizeBytes = &unlimitedSize
|
|
||||||
}
|
|
||||||
checkPositive(configErrs, "media_api.max_file_size_bytes", int64(*c.MaxFileSizeBytes))
|
checkPositive(configErrs, "media_api.max_file_size_bytes", int64(*c.MaxFileSizeBytes))
|
||||||
checkPositive(configErrs, "media_api.max_thumbnail_generators", int64(c.MaxThumbnailGenerators))
|
checkPositive(configErrs, "media_api.max_thumbnail_generators", int64(c.MaxThumbnailGenerators))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Database implements gomatrixserverlib.KeyDatabase and is used to store
|
// A Database implements gomatrixserverlib.KeyDatabase and is used to store
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ func (s *OutputRoomEventConsumer) updateStateEvent(event *gomatrixserverlib.Head
|
||||||
return event, err
|
return event, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevEvent == nil {
|
if prevEvent == nil || prevEvent.EventID() == event.EventID() {
|
||||||
return event, nil
|
return event, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ func (r *messagesReq) getStartEnd(events []*gomatrixserverlib.HeaderedEvent) (st
|
||||||
start = *r.from
|
start = *r.from
|
||||||
if events[len(events)-1].Type() == gomatrixserverlib.MRoomCreate {
|
if events[len(events)-1].Type() == gomatrixserverlib.MRoomCreate {
|
||||||
// NOTSPEC: We've hit the beginning of the room so there's really nowhere
|
// NOTSPEC: We've hit the beginning of the room so there's really nowhere
|
||||||
// else to go. This seems to fix Riot iOS from looping on /messages endlessly.
|
// else to go. This seems to fix Element iOS from looping on /messages endlessly.
|
||||||
end = types.TopologyToken{}
|
end = types.TopologyToken{}
|
||||||
} else {
|
} else {
|
||||||
end, err = r.db.EventPositionInTopology(
|
end, err = r.db.EventPositionInTopology(
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,6 @@ package sqlite3
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
// Import the sqlite3 package
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/syncapi/storage/shared"
|
"github.com/matrix-org/dendrite/syncapi/storage/shared"
|
||||||
|
|
|
||||||
|
|
@ -520,6 +520,8 @@ Inviting an AS-hosted user asks the AS server
|
||||||
Can generate a openid access_token that can be exchanged for information about a user
|
Can generate a openid access_token that can be exchanged for information about a user
|
||||||
Invalid openid access tokens are rejected
|
Invalid openid access tokens are rejected
|
||||||
Requests to userinfo without access tokens are rejected
|
Requests to userinfo without access tokens are rejected
|
||||||
|
'ban' event respects room powerlevel
|
||||||
|
Non-present room members cannot ban others
|
||||||
POST /_synapse/admin/v1/register with shared secret
|
POST /_synapse/admin/v1/register with shared secret
|
||||||
POST /_synapse/admin/v1/register admin with shared secret
|
POST /_synapse/admin/v1/register admin with shared secret
|
||||||
POST /_synapse/admin/v1/register with shared secret downcases capitals
|
POST /_synapse/admin/v1/register with shared secret downcases capitals
|
||||||
|
|
@ -535,3 +537,6 @@ Remote servers should reject attempts by non-creators to set the power levels
|
||||||
Federation handles empty auth_events in state_ids sanely
|
Federation handles empty auth_events in state_ids sanely
|
||||||
Key notary server should return an expired key if it can't find any others
|
Key notary server should return an expired key if it can't find any others
|
||||||
Key notary server must not overwrite a valid key with a spurious result from the origin server
|
Key notary server must not overwrite a valid key with a spurious result from the origin server
|
||||||
|
GET /rooms/:room_id/aliases lists aliases
|
||||||
|
Only room members can list aliases of a room
|
||||||
|
Users with sufficient power-level can delete other's aliases
|
||||||
|
|
|
||||||
3
test-dendritejs.sh
Executable file
3
test-dendritejs.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh -eu
|
||||||
|
|
||||||
|
GOOS=js GOARCH=wasm go test -v -exec "$(pwd)/test/wasm/index.js" ./cmd/dendritejs-pinecone
|
||||||
52
test/wasm/index.js
Executable file
52
test/wasm/index.js
Executable file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const childProcess = require('child_process');
|
||||||
|
|
||||||
|
(async function() {
|
||||||
|
// sql.js
|
||||||
|
const initSqlJs = require('sql.js');
|
||||||
|
await initSqlJs().then(SQL => {
|
||||||
|
global._go_sqlite = SQL;
|
||||||
|
console.log("Loaded sqlite")
|
||||||
|
});
|
||||||
|
// dendritejs expects to write to `/idb` so we create that here
|
||||||
|
// Since this is testing only, we use the default in-memory FS
|
||||||
|
global._go_sqlite.FS.mkdir("/idb");
|
||||||
|
|
||||||
|
// WebSocket
|
||||||
|
const WebSocket = require('isomorphic-ws');
|
||||||
|
global.WebSocket = WebSocket;
|
||||||
|
|
||||||
|
// Load the generic Go Wasm exec helper inline to trigger built-in run call
|
||||||
|
// This approach avoids copying `wasm_exec.js` into the repo, which is nice
|
||||||
|
// to aim for since it can differ between Go versions.
|
||||||
|
const goRoot = await new Promise((resolve, reject) => {
|
||||||
|
childProcess.execFile('go', ['env', 'GOROOT'], (err, out) => {
|
||||||
|
if (err) {
|
||||||
|
reject("Can't find go");
|
||||||
|
}
|
||||||
|
resolve(out.trim());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const execPath = path.join(goRoot, 'misc/wasm/wasm_exec.js');
|
||||||
|
const execCode = fs.readFileSync(execPath, 'utf8');
|
||||||
|
eval(execCode);
|
||||||
|
})();
|
||||||
67
test/wasm/package-lock.json
generated
Normal file
67
test/wasm/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"name": "wasm",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"isomorphic-ws": "^4.0.1",
|
||||||
|
"sql.js": "github:neilalexander/sql.js#252a72bf57b0538cbd49bbd6f70af71e516966ae",
|
||||||
|
"ws": "^7.5.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isomorphic-ws": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"ws": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sql.js": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "git+ssh://git@github.com/neilalexander/sql.js.git#252a72bf57b0538cbd49bbd6f70af71e516966ae",
|
||||||
|
"integrity": "sha512-EFYI/yMoQ1U08nZxQOZ7+4S0nOpKF45EVoWGef8L1kvSCMP3B3xSzwZeOmoF2tBVpbMssAgHEz43cf0ZulRDSQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "7.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.2.tgz",
|
||||||
|
"integrity": "sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"isomorphic-ws": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"sql.js": {
|
||||||
|
"version": "git+ssh://git@github.com/neilalexander/sql.js.git#252a72bf57b0538cbd49bbd6f70af71e516966ae",
|
||||||
|
"integrity": "sha512-EFYI/yMoQ1U08nZxQOZ7+4S0nOpKF45EVoWGef8L1kvSCMP3B3xSzwZeOmoF2tBVpbMssAgHEz43cf0ZulRDSQ==",
|
||||||
|
"from": "sql.js@github:neilalexander/sql.js#252a72bf57b0538cbd49bbd6f70af71e516966ae"
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "7.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.2.tgz",
|
||||||
|
"integrity": "sha512-lkF7AWRicoB9mAgjeKbGqVUekLnSNO4VjKVnuPHpQeOxZOErX6BPXwJk70nFslRCEEA8EVW7ZjKwXaP9N+1sKQ==",
|
||||||
|
"requires": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
test/wasm/package.json
Normal file
7
test/wasm/package.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"isomorphic-ws": "^4.0.1",
|
||||||
|
"sql.js": "github:neilalexander/sql.js#252a72bf57b0538cbd49bbd6f70af71e516966ae",
|
||||||
|
"ws": "^7.5.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,8 +25,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/storage/devices/sqlite3/deltas"
|
"github.com/matrix-org/dendrite/userapi/storage/devices/sqlite3/deltas"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// The length of generated device IDs
|
// The length of generated device IDs
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue