2017-08-04 15:32:10 +00:00
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2017-10-11 17:16:53 +00:00
package routing
2017-08-04 15:32:10 +00:00
import (
2017-09-13 12:37:50 +00:00
"context"
2022-02-10 10:05:37 +00:00
"fmt"
2017-08-04 15:32:10 +00:00
"net/http"
2018-08-06 13:09:25 +00:00
"time"
2017-08-04 15:32:10 +00:00
2023-04-03 19:21:06 +00:00
"github.com/matrix-org/gomatrixserverlib"
2023-04-19 14:50:33 +00:00
"github.com/matrix-org/gomatrixserverlib/spec"
2023-04-03 19:21:06 +00:00
2018-08-20 09:45:17 +00:00
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
2017-08-04 15:32:10 +00:00
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
2017-09-01 09:13:10 +00:00
"github.com/matrix-org/dendrite/clientapi/threepid"
2020-06-12 13:55:57 +00:00
"github.com/matrix-org/dendrite/internal/eventutil"
2022-05-05 12:17:38 +00:00
"github.com/matrix-org/dendrite/roomserver/api"
2018-08-20 09:45:17 +00:00
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
2023-04-27 11:54:20 +00:00
"github.com/matrix-org/dendrite/roomserver/types"
2020-12-02 17:41:00 +00:00
"github.com/matrix-org/dendrite/setup/config"
2020-06-16 13:10:55 +00:00
userapi "github.com/matrix-org/dendrite/userapi/api"
2017-08-04 15:32:10 +00:00
"github.com/matrix-org/util"
)
2020-06-24 17:19:54 +00:00
func SendBan (
2022-05-05 12:17:38 +00:00
req * http . Request , profileAPI userapi . ClientUserAPI , device * userapi . Device ,
2020-08-10 13:18:04 +00:00
roomID string , cfg * config . ClientAPI ,
2022-05-06 11:39:26 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI , asAPI appserviceAPI . AppServiceInternalAPI ,
2017-08-04 15:32:10 +00:00
) util . JSONResponse {
2023-04-03 19:21:06 +00:00
body , evTime , reqErr := extractRequestData ( req )
2020-06-24 17:19:54 +00:00
if reqErr != nil {
return * reqErr
}
2021-07-19 17:33:05 +00:00
2023-04-03 19:21:06 +00:00
if body . UserID == "" {
return util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : jsonerror . BadJSON ( "missing user_id" ) ,
}
}
2021-07-19 17:33:05 +00:00
errRes := checkMemberInRoom ( req . Context ( ) , rsAPI , device . UserID , roomID )
if errRes != nil {
return * errRes
}
2023-04-03 19:21:06 +00:00
pl , errRes := getPowerlevels ( req , rsAPI , roomID )
if errRes != nil {
return * errRes
2021-07-19 17:33:05 +00:00
}
allowedToBan := pl . UserLevel ( device . UserID ) >= pl . Ban
if ! allowedToBan {
return util . JSONResponse {
2023-04-03 19:21:06 +00:00
Code : http . StatusForbidden ,
2021-07-19 17:33:05 +00:00
JSON : jsonerror . Forbidden ( "You don't have permission to ban this user, power level too low." ) ,
}
}
2023-04-19 14:50:33 +00:00
return sendMembership ( req . Context ( ) , profileAPI , device , roomID , spec . Ban , body . Reason , cfg , body . UserID , evTime , rsAPI , asAPI )
2020-06-24 17:19:54 +00:00
}
2022-05-05 12:17:38 +00:00
func sendMembership ( ctx context . Context , profileAPI userapi . ClientUserAPI , device * userapi . Device ,
2020-08-10 13:18:04 +00:00
roomID , membership , reason string , cfg * config . ClientAPI , targetUserID string , evTime time . Time ,
2022-05-06 11:39:26 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI , asAPI appserviceAPI . AppServiceInternalAPI ) util . JSONResponse {
2020-06-24 17:19:54 +00:00
event , err := buildMembershipEvent (
2022-03-24 21:45:44 +00:00
ctx , targetUserID , reason , profileAPI , device , membership ,
2020-06-24 17:19:54 +00:00
roomID , false , cfg , evTime , rsAPI , asAPI ,
)
2023-04-03 19:21:06 +00:00
if err != nil {
2020-06-24 17:19:54 +00:00
util . GetLogger ( ctx ) . WithError ( err ) . Error ( "buildMembershipEvent failed" )
return jsonerror . InternalServerError ( )
2020-03-27 16:28:22 +00:00
}
2022-10-26 11:59:19 +00:00
serverName := device . UserDomain ( )
2020-09-03 14:22:16 +00:00
if err = roomserverAPI . SendEvents (
2020-06-24 17:19:54 +00:00
ctx , rsAPI ,
2021-09-08 16:31:03 +00:00
roomserverAPI . KindNew ,
2023-04-27 11:54:20 +00:00
[ ] * types . HeaderedEvent { event } ,
2022-11-15 15:05:23 +00:00
device . UserDomain ( ) ,
2022-10-26 11:59:19 +00:00
serverName ,
serverName ,
2020-06-24 17:19:54 +00:00
nil ,
2022-01-05 17:44:49 +00:00
false ,
2020-09-03 14:22:16 +00:00
) ; err != nil {
2020-06-24 17:19:54 +00:00
util . GetLogger ( ctx ) . WithError ( err ) . Error ( "SendEvents failed" )
return jsonerror . InternalServerError ( )
}
return util . JSONResponse {
Code : http . StatusOK ,
JSON : struct { } { } ,
}
}
func SendKick (
2022-05-05 12:17:38 +00:00
req * http . Request , profileAPI userapi . ClientUserAPI , device * userapi . Device ,
2020-08-10 13:18:04 +00:00
roomID string , cfg * config . ClientAPI ,
2022-05-06 11:39:26 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI , asAPI appserviceAPI . AppServiceInternalAPI ,
2020-06-24 17:19:54 +00:00
) util . JSONResponse {
2023-04-03 19:21:06 +00:00
body , evTime , reqErr := extractRequestData ( req )
2020-06-24 17:19:54 +00:00
if reqErr != nil {
2017-08-29 14:17:26 +00:00
return * reqErr
}
2020-06-24 17:19:54 +00:00
if body . UserID == "" {
return util . JSONResponse {
2023-04-03 19:21:06 +00:00
Code : http . StatusBadRequest ,
2020-06-24 17:19:54 +00:00
JSON : jsonerror . BadJSON ( "missing user_id" ) ,
}
}
2017-08-29 14:17:26 +00:00
2020-09-04 11:30:56 +00:00
errRes := checkMemberInRoom ( req . Context ( ) , rsAPI , device . UserID , roomID )
2020-07-27 08:20:09 +00:00
if errRes != nil {
return * errRes
}
2023-04-03 19:21:06 +00:00
pl , errRes := getPowerlevels ( req , rsAPI , roomID )
if errRes != nil {
return * errRes
}
allowedToKick := pl . UserLevel ( device . UserID ) >= pl . Kick
if ! allowedToKick {
return util . JSONResponse {
Code : http . StatusForbidden ,
JSON : jsonerror . Forbidden ( "You don't have permission to kick this user, power level too low." ) ,
}
}
2020-06-24 17:19:54 +00:00
var queryRes roomserverAPI . QueryMembershipForUserResponse
err := rsAPI . QueryMembershipForUser ( req . Context ( ) , & roomserverAPI . QueryMembershipForUserRequest {
RoomID : roomID ,
UserID : body . UserID ,
} , & queryRes )
2018-08-22 12:40:25 +00:00
if err != nil {
2020-06-24 17:19:54 +00:00
return util . ErrorResponse ( err )
}
2020-07-27 08:20:09 +00:00
// kick is only valid if the user is not currently banned or left (that is, they are joined or invited)
2023-04-19 14:50:33 +00:00
if queryRes . Membership != spec . Join && queryRes . Membership != spec . Invite {
2018-08-22 12:40:25 +00:00
return util . JSONResponse {
2023-04-03 19:21:06 +00:00
Code : http . StatusForbidden ,
2020-07-27 08:20:09 +00:00
JSON : jsonerror . Unknown ( "cannot /kick banned or left users" ) ,
2018-08-22 12:40:25 +00:00
}
}
2020-06-24 17:19:54 +00:00
// TODO: should we be using SendLeave instead?
2023-04-19 14:50:33 +00:00
return sendMembership ( req . Context ( ) , profileAPI , device , roomID , spec . Leave , body . Reason , cfg , body . UserID , evTime , rsAPI , asAPI )
2020-06-24 17:19:54 +00:00
}
func SendUnban (
2022-05-05 12:17:38 +00:00
req * http . Request , profileAPI userapi . ClientUserAPI , device * userapi . Device ,
2020-08-10 13:18:04 +00:00
roomID string , cfg * config . ClientAPI ,
2022-05-06 11:39:26 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI , asAPI appserviceAPI . AppServiceInternalAPI ,
2020-06-24 17:19:54 +00:00
) util . JSONResponse {
2023-04-03 19:21:06 +00:00
body , evTime , reqErr := extractRequestData ( req )
2020-06-24 17:19:54 +00:00
if reqErr != nil {
return * reqErr
}
if body . UserID == "" {
return util . JSONResponse {
2023-04-03 19:21:06 +00:00
Code : http . StatusBadRequest ,
2020-06-24 17:19:54 +00:00
JSON : jsonerror . BadJSON ( "missing user_id" ) ,
}
}
2023-04-03 19:21:06 +00:00
errRes := checkMemberInRoom ( req . Context ( ) , rsAPI , device . UserID , roomID )
if errRes != nil {
return * errRes
}
2020-06-24 17:19:54 +00:00
var queryRes roomserverAPI . QueryMembershipForUserResponse
err := rsAPI . QueryMembershipForUser ( req . Context ( ) , & roomserverAPI . QueryMembershipForUserRequest {
RoomID : roomID ,
UserID : body . UserID ,
} , & queryRes )
if err != nil {
return util . ErrorResponse ( err )
}
2023-04-03 19:21:06 +00:00
2020-06-24 17:19:54 +00:00
// unban is only valid if the user is currently banned
2023-04-19 14:50:33 +00:00
if queryRes . Membership != spec . Ban {
2020-06-24 17:19:54 +00:00
return util . JSONResponse {
2023-04-03 19:21:06 +00:00
Code : http . StatusBadRequest ,
2020-06-24 17:19:54 +00:00
JSON : jsonerror . Unknown ( "can only /unban users that are banned" ) ,
}
}
// TODO: should we be using SendLeave instead?
2023-04-19 14:50:33 +00:00
return sendMembership ( req . Context ( ) , profileAPI , device , roomID , spec . Leave , body . Reason , cfg , body . UserID , evTime , rsAPI , asAPI )
2020-06-24 17:19:54 +00:00
}
func SendInvite (
2022-05-05 12:17:38 +00:00
req * http . Request , profileAPI userapi . ClientUserAPI , device * userapi . Device ,
2020-08-10 13:18:04 +00:00
roomID string , cfg * config . ClientAPI ,
2022-05-06 11:39:26 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI , asAPI appserviceAPI . AppServiceInternalAPI ,
2020-06-24 17:19:54 +00:00
) util . JSONResponse {
2023-04-03 19:21:06 +00:00
body , evTime , reqErr := extractRequestData ( req )
2020-06-24 17:19:54 +00:00
if reqErr != nil {
return * reqErr
}
2018-08-22 12:40:25 +00:00
2019-07-12 13:29:30 +00:00
inviteStored , jsonErrResp := checkAndProcessThreepid (
2022-03-24 21:45:44 +00:00
req , device , body , cfg , rsAPI , profileAPI , roomID , evTime ,
2017-09-11 18:18:19 +00:00
)
2019-07-12 13:29:30 +00:00
if jsonErrResp != nil {
return * jsonErrResp
2017-08-29 14:17:26 +00:00
}
2017-09-11 18:18:19 +00:00
// If an invite has been stored on an identity server, it means that a
// m.room.third_party_invite event has been emitted and that we shouldn't
// emit a m.room.member one.
if inviteStored {
return util . JSONResponse {
2018-03-13 15:55:45 +00:00
Code : http . StatusOK ,
2017-09-11 18:18:19 +00:00
JSON : struct { } { } ,
}
}
2023-04-03 19:21:06 +00:00
if body . UserID == "" {
return util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : jsonerror . BadJSON ( "missing user_id" ) ,
}
}
errRes := checkMemberInRoom ( req . Context ( ) , rsAPI , device . UserID , roomID )
if errRes != nil {
return * errRes
}
2022-02-18 15:05:03 +00:00
// We already received the return value, so no need to check for an error here.
2022-03-24 21:45:44 +00:00
response , _ := sendInvite ( req . Context ( ) , profileAPI , device , roomID , body . UserID , body . Reason , cfg , rsAPI , asAPI , evTime )
2022-02-18 15:05:03 +00:00
return response
}
// sendInvite sends an invitation to a user. Returns a JSONResponse and an error
func sendInvite (
ctx context . Context ,
2022-05-05 12:17:38 +00:00
profileAPI userapi . ClientUserAPI ,
2022-02-18 15:05:03 +00:00
device * userapi . Device ,
roomID , userID , reason string ,
cfg * config . ClientAPI ,
2022-05-05 12:17:38 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI ,
2022-05-06 11:39:26 +00:00
asAPI appserviceAPI . AppServiceInternalAPI , evTime time . Time ,
2022-02-18 15:05:03 +00:00
) ( util . JSONResponse , error ) {
2017-09-11 18:18:19 +00:00
event , err := buildMembershipEvent (
2023-04-19 14:50:33 +00:00
ctx , userID , reason , profileAPI , device , spec . Invite ,
2020-05-07 15:46:11 +00:00
roomID , false , cfg , evTime , rsAPI , asAPI ,
2017-09-11 18:18:19 +00:00
)
2023-04-03 19:21:06 +00:00
if err != nil {
2022-02-18 15:05:03 +00:00
util . GetLogger ( ctx ) . WithError ( err ) . Error ( "buildMembershipEvent failed" )
return jsonerror . InternalServerError ( ) , err
2017-09-11 18:18:19 +00:00
}
2022-05-05 12:17:38 +00:00
var inviteRes api . PerformInviteResponse
if err := rsAPI . PerformInvite ( ctx , & api . PerformInviteRequest {
Event : event ,
InviteRoomState : nil , // ask the roomserver to draw up invite room state for us
2023-04-27 11:54:20 +00:00
RoomVersion : event . Version ( ) ,
2022-10-26 11:59:19 +00:00
SendAsServer : string ( device . UserDomain ( ) ) ,
2022-05-05 12:17:38 +00:00
} , & inviteRes ) ; err != nil {
util . GetLogger ( ctx ) . WithError ( err ) . Error ( "PerformInvite failed" )
2020-08-17 10:40:49 +00:00
return util . JSONResponse {
Code : http . StatusInternalServerError ,
JSON : jsonerror . InternalServerError ( ) ,
2022-02-18 15:05:03 +00:00
} , err
2017-09-11 18:18:19 +00:00
}
2022-05-05 12:17:38 +00:00
if inviteRes . Error != nil {
return inviteRes . Error . JSONResponse ( ) , inviteRes . Error
}
return util . JSONResponse {
Code : http . StatusOK ,
JSON : struct { } { } ,
} , nil
2017-09-11 18:18:19 +00:00
}
func buildMembershipEvent (
2018-08-06 13:09:25 +00:00
ctx context . Context ,
2022-05-05 12:17:38 +00:00
targetUserID , reason string , profileAPI userapi . ClientUserAPI ,
2020-06-16 13:10:55 +00:00
device * userapi . Device ,
2020-05-07 15:46:11 +00:00
membership , roomID string , isDirect bool ,
2020-08-10 13:18:04 +00:00
cfg * config . ClientAPI , evTime time . Time ,
2022-05-06 11:39:26 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI , asAPI appserviceAPI . AppServiceInternalAPI ,
2023-04-27 11:54:20 +00:00
) ( * types . HeaderedEvent , error ) {
2022-03-24 21:45:44 +00:00
profile , err := loadProfile ( ctx , targetUserID , cfg , profileAPI , asAPI )
2017-08-04 15:32:10 +00:00
if err != nil {
2017-09-11 18:18:19 +00:00
return nil , err
2017-08-04 15:32:10 +00:00
}
builder := gomatrixserverlib . EventBuilder {
Sender : device . UserID ,
RoomID : roomID ,
Type : "m.room.member" ,
2020-06-24 17:19:54 +00:00
StateKey : & targetUserID ,
2017-08-04 15:32:10 +00:00
}
2019-08-15 17:45:11 +00:00
content := gomatrixserverlib . MemberContent {
2017-08-04 15:32:10 +00:00
Membership : membership ,
DisplayName : profile . DisplayName ,
AvatarURL : profile . AvatarURL ,
Reason : reason ,
2020-05-07 15:46:11 +00:00
IsDirect : isDirect ,
2017-08-04 15:32:10 +00:00
}
if err = builder . SetContent ( content ) ; err != nil {
2017-09-11 18:18:19 +00:00
return nil , err
2017-08-04 15:32:10 +00:00
}
2022-11-15 15:05:23 +00:00
identity , err := cfg . Matrix . SigningIdentityFor ( device . UserDomain ( ) )
if err != nil {
return nil , err
}
return eventutil . QueryAndBuildEvent ( ctx , & builder , cfg . Matrix , identity , evTime , rsAPI , nil )
2017-08-04 15:32:10 +00:00
}
2017-08-29 14:17:26 +00:00
// loadProfile lookups the profile of a given user from the database and returns
// it if the user is local to this server, or returns an empty profile if not.
// Returns an error if the retrieval failed or if the first parameter isn't a
// valid Matrix ID.
2017-09-18 13:15:27 +00:00
func loadProfile (
2018-08-20 09:45:17 +00:00
ctx context . Context ,
userID string ,
2020-08-10 13:18:04 +00:00
cfg * config . ClientAPI ,
2022-05-05 12:17:38 +00:00
profileAPI userapi . ClientUserAPI ,
2022-05-06 11:39:26 +00:00
asAPI appserviceAPI . AppServiceInternalAPI ,
2017-09-18 13:15:27 +00:00
) ( * authtypes . Profile , error ) {
2018-08-20 09:45:17 +00:00
_ , serverName , err := gomatrixserverlib . SplitID ( '@' , userID )
2017-08-29 14:17:26 +00:00
if err != nil {
return nil , err
}
var profile * authtypes . Profile
2022-10-26 11:59:19 +00:00
if cfg . Matrix . IsLocalServerName ( serverName ) {
2022-03-24 21:45:44 +00:00
profile , err = appserviceAPI . RetrieveUserProfile ( ctx , userID , asAPI , profileAPI )
2017-08-29 14:17:26 +00:00
} else {
profile = & authtypes . Profile { }
}
return profile , err
}
2023-04-03 19:21:06 +00:00
func extractRequestData ( req * http . Request ) ( body * threepid . MembershipRequest , evTime time . Time , resErr * util . JSONResponse ) {
2017-08-04 15:32:10 +00:00
2020-06-24 17:19:54 +00:00
if reqErr := httputil . UnmarshalJSONRequest ( req , & body ) ; reqErr != nil {
resErr = reqErr
return
2017-08-04 15:32:10 +00:00
}
2020-06-24 17:19:54 +00:00
evTime , err := httputil . ParseTSParam ( req )
if err != nil {
resErr = & util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : jsonerror . InvalidArgumentValue ( err . Error ( ) ) ,
}
return
}
2017-08-04 15:32:10 +00:00
return
}
2019-07-12 13:29:30 +00:00
func checkAndProcessThreepid (
req * http . Request ,
2020-06-16 13:10:55 +00:00
device * userapi . Device ,
2019-07-12 13:29:30 +00:00
body * threepid . MembershipRequest ,
2020-08-10 13:18:04 +00:00
cfg * config . ClientAPI ,
2022-05-05 12:17:38 +00:00
rsAPI roomserverAPI . ClientRoomserverAPI ,
profileAPI userapi . ClientUserAPI ,
2020-06-24 17:19:54 +00:00
roomID string ,
2019-07-12 13:29:30 +00:00
evTime time . Time ,
) ( inviteStored bool , errRes * util . JSONResponse ) {
inviteStored , err := threepid . CheckAndProcessInvite (
2022-03-24 21:45:44 +00:00
req . Context ( ) , device , body , cfg , rsAPI , profileAPI ,
2020-06-24 17:19:54 +00:00
roomID , evTime ,
2019-07-12 13:29:30 +00:00
)
if err == threepid . ErrMissingParameter {
return inviteStored , & util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : jsonerror . BadJSON ( err . Error ( ) ) ,
}
} else if err == threepid . ErrNotTrusted {
return inviteStored , & util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : jsonerror . NotTrusted ( body . IDServer ) ,
}
2020-06-12 13:55:57 +00:00
} else if err == eventutil . ErrRoomNoExists {
2019-07-12 13:29:30 +00:00
return inviteStored , & util . JSONResponse {
Code : http . StatusNotFound ,
JSON : jsonerror . NotFound ( err . Error ( ) ) ,
}
2020-06-04 09:53:39 +00:00
} else if e , ok := err . ( gomatrixserverlib . BadJSONError ) ; ok {
return inviteStored , & util . JSONResponse {
Code : http . StatusBadRequest ,
JSON : jsonerror . BadJSON ( e . Error ( ) ) ,
}
}
if err != nil {
2020-03-02 16:20:44 +00:00
util . GetLogger ( req . Context ( ) ) . WithError ( err ) . Error ( "threepid.CheckAndProcessInvite failed" )
er := jsonerror . InternalServerError ( )
2019-07-12 13:29:30 +00:00
return inviteStored , & er
}
return
}
2020-07-02 14:41:18 +00:00
2022-05-05 12:17:38 +00:00
func checkMemberInRoom ( ctx context . Context , rsAPI roomserverAPI . ClientRoomserverAPI , userID , roomID string ) * util . JSONResponse {
2023-04-03 19:21:06 +00:00
var membershipRes roomserverAPI . QueryMembershipForUserResponse
err := rsAPI . QueryMembershipForUser ( ctx , & roomserverAPI . QueryMembershipForUserRequest {
RoomID : roomID ,
UserID : userID ,
2020-07-02 14:41:18 +00:00
} , & membershipRes )
if err != nil {
2023-04-03 19:21:06 +00:00
util . GetLogger ( ctx ) . WithError ( err ) . Error ( "QueryMembershipForUser: could not query membership for user" )
2020-08-25 20:04:35 +00:00
e := jsonerror . InternalServerError ( )
return & e
}
2023-04-03 19:21:06 +00:00
if ! membershipRes . IsInRoom {
2020-07-02 14:41:18 +00:00
return & util . JSONResponse {
Code : http . StatusForbidden ,
JSON : jsonerror . Forbidden ( "user does not belong to room" ) ,
}
}
return nil
}
2020-11-05 10:19:23 +00:00
func SendForget (
req * http . Request , device * userapi . Device ,
2022-05-05 12:17:38 +00:00
roomID string , rsAPI roomserverAPI . ClientRoomserverAPI ,
2020-11-05 10:19:23 +00:00
) util . JSONResponse {
ctx := req . Context ( )
logger := util . GetLogger ( ctx ) . WithField ( "roomID" , roomID ) . WithField ( "userID" , device . UserID )
2021-09-08 16:31:03 +00:00
var membershipRes roomserverAPI . QueryMembershipForUserResponse
membershipReq := roomserverAPI . QueryMembershipForUserRequest {
2020-11-05 10:19:23 +00:00
RoomID : roomID ,
UserID : device . UserID ,
}
err := rsAPI . QueryMembershipForUser ( ctx , & membershipReq , & membershipRes )
if err != nil {
logger . WithError ( err ) . Error ( "QueryMembershipForUser: could not query membership for user" )
return jsonerror . InternalServerError ( )
}
2022-05-11 10:29:23 +00:00
if ! membershipRes . RoomExists {
return util . JSONResponse {
Code : http . StatusForbidden ,
JSON : jsonerror . Forbidden ( "room does not exist" ) ,
}
}
2020-11-05 10:19:23 +00:00
if membershipRes . IsInRoom {
return util . JSONResponse {
Code : http . StatusBadRequest ,
2022-02-10 10:05:37 +00:00
JSON : jsonerror . Unknown ( fmt . Sprintf ( "User %s is in room %s" , device . UserID , roomID ) ) ,
2020-11-05 10:19:23 +00:00
}
}
2021-09-08 16:31:03 +00:00
request := roomserverAPI . PerformForgetRequest {
2020-11-05 10:19:23 +00:00
RoomID : roomID ,
UserID : device . UserID ,
}
2021-09-08 16:31:03 +00:00
response := roomserverAPI . PerformForgetResponse { }
2020-11-05 10:19:23 +00:00
if err := rsAPI . PerformForget ( ctx , & request , & response ) ; err != nil {
logger . WithError ( err ) . Error ( "PerformForget: unable to forget room" )
return jsonerror . InternalServerError ( )
}
return util . JSONResponse {
Code : http . StatusOK ,
JSON : struct { } { } ,
}
}
2023-04-03 19:21:06 +00:00
func getPowerlevels ( req * http . Request , rsAPI roomserverAPI . ClientRoomserverAPI , roomID string ) ( * gomatrixserverlib . PowerLevelContent , * util . JSONResponse ) {
plEvent := roomserverAPI . GetStateEvent ( req . Context ( ) , rsAPI , roomID , gomatrixserverlib . StateKeyTuple {
2023-04-19 14:50:33 +00:00
EventType : spec . MRoomPowerLevels ,
2023-04-03 19:21:06 +00:00
StateKey : "" ,
} )
if plEvent == nil {
return nil , & util . JSONResponse {
Code : http . StatusForbidden ,
JSON : jsonerror . Forbidden ( "You don't have permission to perform this action, no power_levels event in this room." ) ,
}
}
pl , err := plEvent . PowerLevels ( )
if err != nil {
return nil , & util . JSONResponse {
Code : http . StatusForbidden ,
JSON : jsonerror . Forbidden ( "You don't have permission to perform this action, the power_levels event for this room is malformed so auth checks cannot be performed." ) ,
}
}
return pl , nil
}