aboutsummaryrefslogtreecommitdiff
path: root/roomserver/internal
diff options
context:
space:
mode:
Diffstat (limited to 'roomserver/internal')
-rw-r--r--roomserver/internal/api.go1
-rw-r--r--roomserver/internal/perform/perform_join.go24
-rw-r--r--roomserver/internal/query/query.go164
3 files changed, 54 insertions, 135 deletions
diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go
index ee433f0d..35b7383a 100644
--- a/roomserver/internal/api.go
+++ b/roomserver/internal/api.go
@@ -94,6 +94,7 @@ func NewRoomserverAPI(
Cache: caches,
IsLocalServerName: dendriteCfg.Global.IsLocalServerName,
ServerACLs: serverACLs,
+ Cfg: dendriteCfg,
},
enableMetrics: enableMetrics,
// perform-er structs get initialised when we have a federation sender to use
diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go
index 34bea5b6..181a9349 100644
--- a/roomserver/internal/perform/perform_join.go
+++ b/roomserver/internal/perform/perform_join.go
@@ -372,22 +372,14 @@ func (r *Joiner) populateAuthorisedViaUserForRestrictedJoin(
ctx context.Context,
joinReq *rsAPI.PerformJoinRequest,
) (string, error) {
- req := &api.QueryRestrictedJoinAllowedRequest{
- UserID: joinReq.UserID,
- RoomID: joinReq.RoomIDOrAlias,
- }
- res := &api.QueryRestrictedJoinAllowedResponse{}
- if err := r.Queryer.QueryRestrictedJoinAllowed(ctx, req, res); err != nil {
- return "", fmt.Errorf("r.Queryer.QueryRestrictedJoinAllowed: %w", err)
- }
- if !res.Restricted {
- return "", nil
- }
- if !res.Resident {
- return "", nil
+ roomID, err := spec.NewRoomID(joinReq.RoomIDOrAlias)
+ if err != nil {
+ return "", err
}
- if !res.Allowed {
- return "", rsAPI.ErrNotAllowed{Err: fmt.Errorf("the join to room %s was not allowed", joinReq.RoomIDOrAlias)}
+ userID, err := spec.NewUserID(joinReq.UserID, true)
+ if err != nil {
+ return "", err
}
- return res.AuthorisedVia, nil
+
+ return r.Queryer.QueryRestrictedJoinAllowed(ctx, *roomID, *userID)
}
diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go
index effcc90d..6d898e8a 100644
--- a/roomserver/internal/query/query.go
+++ b/roomserver/internal/query/query.go
@@ -17,10 +17,11 @@ package query
import (
"context"
"database/sql"
- "encoding/json"
"errors"
"fmt"
+ //"github.com/matrix-org/dendrite/roomserver/internal"
+ "github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
@@ -44,6 +45,42 @@ type Queryer struct {
Cache caching.RoomServerCaches
IsLocalServerName func(spec.ServerName) bool
ServerACLs *acls.ServerACLs
+ Cfg *config.Dendrite
+}
+
+func (r *Queryer) RestrictedRoomJoinInfo(ctx context.Context, roomID spec.RoomID, userID spec.UserID, localServerName spec.ServerName) (*gomatrixserverlib.RestrictedRoomJoinInfo, error) {
+ roomInfo, err := r.QueryRoomInfo(ctx, roomID)
+ if err != nil || roomInfo == nil || roomInfo.IsStub() {
+ return nil, err
+ }
+
+ req := api.QueryServerJoinedToRoomRequest{
+ ServerName: localServerName,
+ RoomID: roomID.String(),
+ }
+ res := api.QueryServerJoinedToRoomResponse{}
+ if err = r.QueryServerJoinedToRoom(ctx, &req, &res); err != nil {
+ util.GetLogger(ctx).WithError(err).Error("rsAPI.QueryServerJoinedToRoom failed")
+ return nil, fmt.Errorf("InternalServerError: Failed to query room: %w", err)
+ }
+
+ userJoinedToRoom, err := r.UserJoinedToRoom(ctx, types.RoomNID(roomInfo.RoomNID), userID)
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("rsAPI.UserJoinedToRoom failed")
+ return nil, fmt.Errorf("InternalServerError: %w", err)
+ }
+
+ locallyJoinedUsers, err := r.LocallyJoinedUsers(ctx, roomInfo.RoomVersion, types.RoomNID(roomInfo.RoomNID))
+ if err != nil {
+ util.GetLogger(ctx).WithError(err).Error("rsAPI.GetLocallyJoinedUsers failed")
+ return nil, fmt.Errorf("InternalServerError: %w", err)
+ }
+
+ return &gomatrixserverlib.RestrictedRoomJoinInfo{
+ LocalServerInRoom: res.RoomExists && res.IsInRoom,
+ UserJoinedToRoom: userJoinedToRoom,
+ JoinedUsers: locallyJoinedUsers,
+ }, nil
}
// QueryLatestEventsAndState implements api.RoomserverInternalAPI
@@ -906,131 +943,20 @@ func (r *Queryer) LocallyJoinedUsers(ctx context.Context, roomVersion gomatrixse
}
// nolint:gocyclo
-func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, req *api.QueryRestrictedJoinAllowedRequest, res *api.QueryRestrictedJoinAllowedResponse) error {
+func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (string, error) {
// Look up if we know anything about the room. If it doesn't exist
// or is a stub entry then we can't do anything.
- roomInfo, err := r.DB.RoomInfo(ctx, req.RoomID)
+ roomInfo, err := r.DB.RoomInfo(ctx, roomID.String())
if err != nil {
- return fmt.Errorf("r.DB.RoomInfo: %w", err)
+ return "", fmt.Errorf("r.DB.RoomInfo: %w", err)
}
if roomInfo == nil || roomInfo.IsStub() {
- return nil // fmt.Errorf("room %q doesn't exist or is stub room", req.RoomID)
+ return "", nil // fmt.Errorf("room %q doesn't exist or is stub room", req.RoomID)
}
verImpl, err := gomatrixserverlib.GetRoomVersion(roomInfo.RoomVersion)
if err != nil {
- return err
- }
- // If the room version doesn't allow restricted joins then don't
- // try to process any further.
- allowRestrictedJoins := verImpl.MayAllowRestrictedJoinsInEventAuth()
- if !allowRestrictedJoins {
- return nil
- }
- // Start off by populating the "resident" flag in the response. If we
- // come across any rooms in the request that are missing, we will unset
- // the flag.
- res.Resident = true
- // Get the join rules to work out if the join rule is "restricted".
- joinRulesEvent, err := r.DB.GetStateEvent(ctx, req.RoomID, spec.MRoomJoinRules, "")
- if err != nil {
- return fmt.Errorf("r.DB.GetStateEvent: %w", err)
- }
- if joinRulesEvent == nil {
- return nil
- }
- var joinRules gomatrixserverlib.JoinRuleContent
- if err = json.Unmarshal(joinRulesEvent.Content(), &joinRules); err != nil {
- return fmt.Errorf("json.Unmarshal: %w", err)
- }
- // If the join rule isn't "restricted" or "knock_restricted" then there's nothing more to do.
- res.Restricted = joinRules.JoinRule == spec.Restricted || joinRules.JoinRule == spec.KnockRestricted
- if !res.Restricted {
- return nil
- }
- // If the user is already invited to the room then the join is allowed
- // but we don't specify an authorised via user, since the event auth
- // will allow the join anyway.
- var pending bool
- if pending, _, _, _, err = helpers.IsInvitePending(ctx, r.DB, req.RoomID, req.UserID); err != nil {
- return fmt.Errorf("helpers.IsInvitePending: %w", err)
- } else if pending {
- res.Allowed = true
- return nil
- }
- // We need to get the power levels content so that we can determine which
- // users in the room are entitled to issue invites. We need to use one of
- // these users as the authorising user.
- powerLevelsEvent, err := r.DB.GetStateEvent(ctx, req.RoomID, spec.MRoomPowerLevels, "")
- if err != nil {
- return fmt.Errorf("r.DB.GetStateEvent: %w", err)
- }
- powerLevels, err := powerLevelsEvent.PowerLevels()
- if err != nil {
- return fmt.Errorf("unable to get powerlevels: %w", err)
- }
- // Step through the join rules and see if the user matches any of them.
- for _, rule := range joinRules.Allow {
- // We only understand "m.room_membership" rules at this point in
- // time, so skip any rule that doesn't match those.
- if rule.Type != spec.MRoomMembership {
- continue
- }
- // See if the room exists. If it doesn't exist or if it's a stub
- // room entry then we can't check memberships.
- targetRoomInfo, err := r.DB.RoomInfo(ctx, rule.RoomID)
- if err != nil || targetRoomInfo == nil || targetRoomInfo.IsStub() {
- res.Resident = false
- continue
- }
- // First of all work out if *we* are still in the room, otherwise
- // it's possible that the memberships will be out of date.
- isIn, err := r.DB.GetLocalServerInRoom(ctx, targetRoomInfo.RoomNID)
- if err != nil || !isIn {
- // If we aren't in the room, we can no longer tell if the room
- // memberships are up-to-date.
- res.Resident = false
- continue
- }
- // At this point we're happy that we are in the room, so now let's
- // see if the target user is in the room.
- _, isIn, _, err = r.DB.GetMembership(ctx, targetRoomInfo.RoomNID, req.UserID)
- if err != nil {
- continue
- }
- // If the user is not in the room then we will skip them.
- if !isIn {
- continue
- }
- // The user is in the room, so now we will need to authorise the
- // join using the user ID of one of our own users in the room. Pick
- // one.
- joinNIDs, err := r.DB.GetMembershipEventNIDsForRoom(ctx, targetRoomInfo.RoomNID, true, true)
- if err != nil || len(joinNIDs) == 0 {
- // There should always be more than one join NID at this point
- // because we are gated behind GetLocalServerInRoom, but y'know,
- // sometimes strange things happen.
- continue
- }
- // For each of the joined users, let's see if we can get a valid
- // membership event.
- for _, joinNID := range joinNIDs {
- events, err := r.DB.Events(ctx, roomInfo.RoomVersion, []types.EventNID{joinNID})
- if err != nil || len(events) != 1 {
- continue
- }
- event := events[0]
- if event.Type() != spec.MRoomMember || event.StateKey() == nil {
- continue // shouldn't happen
- }
- // Only users that have the power to invite should be chosen.
- if powerLevels.UserLevel(*event.StateKey()) < powerLevels.Invite {
- continue
- }
- res.Resident = true
- res.Allowed = true
- res.AuthorisedVia = *event.StateKey()
- return nil
- }
+ return "", err
}
- return nil
+
+ return verImpl.CheckRestrictedJoin(ctx, r.Cfg.Global.ServerName, &api.JoinRoomQuerier{Roomserver: r}, roomID, userID)
}