dendrite/roomserver/inthttp/client.go
Neil 738686ae68
Add /_dendrite/admin/purgeRoom/{roomID} (#2662)
This adds a new admin endpoint `/_dendrite/admin/purgeRoom/{roomID}`. It
completely erases all database entries for a given room ID.

The roomserver will start by clearing all data for that room and then
will generate an output event to notify downstream components (i.e. the
sync API and federation API) to do the same.

It does not currently clear media and it is currently not implemented
for SQLite since it relies on SQL array operations right now.

Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
Co-authored-by: Till Faelligen <2353100+S7evinK@users.noreply.github.com>
2023-01-19 21:02:32 +01:00

575 lines
19 KiB
Go

package inthttp
import (
"context"
"errors"
"net/http"
"github.com/matrix-org/gomatrixserverlib"
asAPI "github.com/matrix-org/dendrite/appservice/api"
fsInputAPI "github.com/matrix-org/dendrite/federationapi/api"
"github.com/matrix-org/dendrite/internal/caching"
"github.com/matrix-org/dendrite/internal/httputil"
"github.com/matrix-org/dendrite/roomserver/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
)
const (
// Alias operations
RoomserverSetRoomAliasPath = "/roomserver/setRoomAlias"
RoomserverGetRoomIDForAliasPath = "/roomserver/GetRoomIDForAlias"
RoomserverGetAliasesForRoomIDPath = "/roomserver/GetAliasesForRoomID"
RoomserverGetCreatorIDForAliasPath = "/roomserver/GetCreatorIDForAlias"
RoomserverRemoveRoomAliasPath = "/roomserver/removeRoomAlias"
// Input operations
RoomserverInputRoomEventsPath = "/roomserver/inputRoomEvents"
// Perform operations
RoomserverPerformInvitePath = "/roomserver/performInvite"
RoomserverPerformPeekPath = "/roomserver/performPeek"
RoomserverPerformUnpeekPath = "/roomserver/performUnpeek"
RoomserverPerformRoomUpgradePath = "/roomserver/performRoomUpgrade"
RoomserverPerformJoinPath = "/roomserver/performJoin"
RoomserverPerformLeavePath = "/roomserver/performLeave"
RoomserverPerformBackfillPath = "/roomserver/performBackfill"
RoomserverPerformPublishPath = "/roomserver/performPublish"
RoomserverPerformInboundPeekPath = "/roomserver/performInboundPeek"
RoomserverPerformForgetPath = "/roomserver/performForget"
RoomserverPerformAdminEvacuateRoomPath = "/roomserver/performAdminEvacuateRoom"
RoomserverPerformAdminEvacuateUserPath = "/roomserver/performAdminEvacuateUser"
RoomserverPerformAdminDownloadStatePath = "/roomserver/performAdminDownloadState"
RoomserverPerformAdminPurgeRoomPath = "/roomserver/performAdminPurgeRoom"
// Query operations
RoomserverQueryLatestEventsAndStatePath = "/roomserver/queryLatestEventsAndState"
RoomserverQueryStateAfterEventsPath = "/roomserver/queryStateAfterEvents"
RoomserverQueryEventsByIDPath = "/roomserver/queryEventsByID"
RoomserverQueryMembershipForUserPath = "/roomserver/queryMembershipForUser"
RoomserverQueryMembershipsForRoomPath = "/roomserver/queryMembershipsForRoom"
RoomserverQueryServerJoinedToRoomPath = "/roomserver/queryServerJoinedToRoomPath"
RoomserverQueryServerAllowedToSeeEventPath = "/roomserver/queryServerAllowedToSeeEvent"
RoomserverQueryMissingEventsPath = "/roomserver/queryMissingEvents"
RoomserverQueryStateAndAuthChainPath = "/roomserver/queryStateAndAuthChain"
RoomserverQueryRoomVersionCapabilitiesPath = "/roomserver/queryRoomVersionCapabilities"
RoomserverQueryRoomVersionForRoomPath = "/roomserver/queryRoomVersionForRoom"
RoomserverQueryPublishedRoomsPath = "/roomserver/queryPublishedRooms"
RoomserverQueryCurrentStatePath = "/roomserver/queryCurrentState"
RoomserverQueryRoomsForUserPath = "/roomserver/queryRoomsForUser"
RoomserverQueryBulkStateContentPath = "/roomserver/queryBulkStateContent"
RoomserverQuerySharedUsersPath = "/roomserver/querySharedUsers"
RoomserverQueryKnownUsersPath = "/roomserver/queryKnownUsers"
RoomserverQueryServerBannedFromRoomPath = "/roomserver/queryServerBannedFromRoom"
RoomserverQueryAuthChainPath = "/roomserver/queryAuthChain"
RoomserverQueryRestrictedJoinAllowed = "/roomserver/queryRestrictedJoinAllowed"
RoomserverQueryMembershipAtEventPath = "/roomserver/queryMembershipAtEvent"
RoomserverQueryLeftMembersPath = "/roomserver/queryLeftMembers"
)
type httpRoomserverInternalAPI struct {
roomserverURL string
httpClient *http.Client
cache caching.RoomVersionCache
}
// NewRoomserverClient creates a RoomserverInputAPI implemented by talking to a HTTP POST API.
// If httpClient is nil an error is returned
func NewRoomserverClient(
roomserverURL string,
httpClient *http.Client,
cache caching.RoomVersionCache,
) (api.RoomserverInternalAPI, error) {
if httpClient == nil {
return nil, errors.New("NewRoomserverInternalAPIHTTP: httpClient is <nil>")
}
return &httpRoomserverInternalAPI{
roomserverURL: roomserverURL,
httpClient: httpClient,
cache: cache,
}, nil
}
// SetFederationInputAPI no-ops in HTTP client mode as there is no chicken/egg scenario
func (h *httpRoomserverInternalAPI) SetFederationAPI(fsAPI fsInputAPI.RoomserverFederationAPI, keyRing *gomatrixserverlib.KeyRing) {
}
// SetAppserviceAPI no-ops in HTTP client mode as there is no chicken/egg scenario
func (h *httpRoomserverInternalAPI) SetAppserviceAPI(asAPI asAPI.AppServiceInternalAPI) {
}
// SetUserAPI no-ops in HTTP client mode as there is no chicken/egg scenario
func (h *httpRoomserverInternalAPI) SetUserAPI(userAPI userapi.RoomserverUserAPI) {
}
// SetRoomAlias implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) SetRoomAlias(
ctx context.Context,
request *api.SetRoomAliasRequest,
response *api.SetRoomAliasResponse,
) error {
return httputil.CallInternalRPCAPI(
"SetRoomAlias", h.roomserverURL+RoomserverSetRoomAliasPath,
h.httpClient, ctx, request, response,
)
}
// GetRoomIDForAlias implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) GetRoomIDForAlias(
ctx context.Context,
request *api.GetRoomIDForAliasRequest,
response *api.GetRoomIDForAliasResponse,
) error {
return httputil.CallInternalRPCAPI(
"GetRoomIDForAlias", h.roomserverURL+RoomserverGetRoomIDForAliasPath,
h.httpClient, ctx, request, response,
)
}
// GetAliasesForRoomID implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) GetAliasesForRoomID(
ctx context.Context,
request *api.GetAliasesForRoomIDRequest,
response *api.GetAliasesForRoomIDResponse,
) error {
return httputil.CallInternalRPCAPI(
"GetAliasesForRoomID", h.roomserverURL+RoomserverGetAliasesForRoomIDPath,
h.httpClient, ctx, request, response,
)
}
// RemoveRoomAlias implements RoomserverAliasAPI
func (h *httpRoomserverInternalAPI) RemoveRoomAlias(
ctx context.Context,
request *api.RemoveRoomAliasRequest,
response *api.RemoveRoomAliasResponse,
) error {
return httputil.CallInternalRPCAPI(
"RemoveRoomAlias", h.roomserverURL+RoomserverRemoveRoomAliasPath,
h.httpClient, ctx, request, response,
)
}
// InputRoomEvents implements RoomserverInputAPI
func (h *httpRoomserverInternalAPI) InputRoomEvents(
ctx context.Context,
request *api.InputRoomEventsRequest,
response *api.InputRoomEventsResponse,
) error {
if err := httputil.CallInternalRPCAPI(
"InputRoomEvents", h.roomserverURL+RoomserverInputRoomEventsPath,
h.httpClient, ctx, request, response,
); err != nil {
response.ErrMsg = err.Error()
}
return nil
}
func (h *httpRoomserverInternalAPI) PerformInvite(
ctx context.Context,
request *api.PerformInviteRequest,
response *api.PerformInviteResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformInvite", h.roomserverURL+RoomserverPerformInvitePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformJoin(
ctx context.Context,
request *api.PerformJoinRequest,
response *api.PerformJoinResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformJoin", h.roomserverURL+RoomserverPerformJoinPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformPeek(
ctx context.Context,
request *api.PerformPeekRequest,
response *api.PerformPeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformPeek", h.roomserverURL+RoomserverPerformPeekPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformInboundPeek(
ctx context.Context,
request *api.PerformInboundPeekRequest,
response *api.PerformInboundPeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformInboundPeek", h.roomserverURL+RoomserverPerformInboundPeekPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformUnpeek(
ctx context.Context,
request *api.PerformUnpeekRequest,
response *api.PerformUnpeekResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformUnpeek", h.roomserverURL+RoomserverPerformUnpeekPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformRoomUpgrade(
ctx context.Context,
request *api.PerformRoomUpgradeRequest,
response *api.PerformRoomUpgradeResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformRoomUpgrade", h.roomserverURL+RoomserverPerformRoomUpgradePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformLeave(
ctx context.Context,
request *api.PerformLeaveRequest,
response *api.PerformLeaveResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformLeave", h.roomserverURL+RoomserverPerformLeavePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformPublish(
ctx context.Context,
request *api.PerformPublishRequest,
response *api.PerformPublishResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformPublish", h.roomserverURL+RoomserverPerformPublishPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminEvacuateRoom(
ctx context.Context,
request *api.PerformAdminEvacuateRoomRequest,
response *api.PerformAdminEvacuateRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminEvacuateRoom", h.roomserverURL+RoomserverPerformAdminEvacuateRoomPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminDownloadState(
ctx context.Context,
request *api.PerformAdminDownloadStateRequest,
response *api.PerformAdminDownloadStateResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminDownloadState", h.roomserverURL+RoomserverPerformAdminDownloadStatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminEvacuateUser(
ctx context.Context,
request *api.PerformAdminEvacuateUserRequest,
response *api.PerformAdminEvacuateUserResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminEvacuateUser", h.roomserverURL+RoomserverPerformAdminEvacuateUserPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformAdminPurgeRoom(
ctx context.Context,
request *api.PerformAdminPurgeRoomRequest,
response *api.PerformAdminPurgeRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformAdminPurgeRoom", h.roomserverURL+RoomserverPerformAdminPurgeRoomPath,
h.httpClient, ctx, request, response,
)
}
// QueryLatestEventsAndState implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryLatestEventsAndState(
ctx context.Context,
request *api.QueryLatestEventsAndStateRequest,
response *api.QueryLatestEventsAndStateResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryLatestEventsAndState", h.roomserverURL+RoomserverQueryLatestEventsAndStatePath,
h.httpClient, ctx, request, response,
)
}
// QueryStateAfterEvents implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryStateAfterEvents(
ctx context.Context,
request *api.QueryStateAfterEventsRequest,
response *api.QueryStateAfterEventsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryStateAfterEvents", h.roomserverURL+RoomserverQueryStateAfterEventsPath,
h.httpClient, ctx, request, response,
)
}
// QueryEventsByID implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryEventsByID(
ctx context.Context,
request *api.QueryEventsByIDRequest,
response *api.QueryEventsByIDResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryEventsByID", h.roomserverURL+RoomserverQueryEventsByIDPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryPublishedRooms(
ctx context.Context,
request *api.QueryPublishedRoomsRequest,
response *api.QueryPublishedRoomsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryPublishedRooms", h.roomserverURL+RoomserverQueryPublishedRoomsPath,
h.httpClient, ctx, request, response,
)
}
// QueryMembershipForUser implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryMembershipForUser(
ctx context.Context,
request *api.QueryMembershipForUserRequest,
response *api.QueryMembershipForUserResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryMembershipForUser", h.roomserverURL+RoomserverQueryMembershipForUserPath,
h.httpClient, ctx, request, response,
)
}
// QueryMembershipsForRoom implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryMembershipsForRoom(
ctx context.Context,
request *api.QueryMembershipsForRoomRequest,
response *api.QueryMembershipsForRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryMembershipsForRoom", h.roomserverURL+RoomserverQueryMembershipsForRoomPath,
h.httpClient, ctx, request, response,
)
}
// QueryMembershipsForRoom implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryServerJoinedToRoom(
ctx context.Context,
request *api.QueryServerJoinedToRoomRequest,
response *api.QueryServerJoinedToRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryServerJoinedToRoom", h.roomserverURL+RoomserverQueryServerJoinedToRoomPath,
h.httpClient, ctx, request, response,
)
}
// QueryServerAllowedToSeeEvent implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryServerAllowedToSeeEvent(
ctx context.Context,
request *api.QueryServerAllowedToSeeEventRequest,
response *api.QueryServerAllowedToSeeEventResponse,
) (err error) {
return httputil.CallInternalRPCAPI(
"QueryServerAllowedToSeeEvent", h.roomserverURL+RoomserverQueryServerAllowedToSeeEventPath,
h.httpClient, ctx, request, response,
)
}
// QueryMissingEvents implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) QueryMissingEvents(
ctx context.Context,
request *api.QueryMissingEventsRequest,
response *api.QueryMissingEventsResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryMissingEvents", h.roomserverURL+RoomserverQueryMissingEventsPath,
h.httpClient, ctx, request, response,
)
}
// QueryStateAndAuthChain implements RoomserverQueryAPI
func (h *httpRoomserverInternalAPI) QueryStateAndAuthChain(
ctx context.Context,
request *api.QueryStateAndAuthChainRequest,
response *api.QueryStateAndAuthChainResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryStateAndAuthChain", h.roomserverURL+RoomserverQueryStateAndAuthChainPath,
h.httpClient, ctx, request, response,
)
}
// PerformBackfill implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) PerformBackfill(
ctx context.Context,
request *api.PerformBackfillRequest,
response *api.PerformBackfillResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformBackfill", h.roomserverURL+RoomserverPerformBackfillPath,
h.httpClient, ctx, request, response,
)
}
// QueryRoomVersionCapabilities implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) QueryRoomVersionCapabilities(
ctx context.Context,
request *api.QueryRoomVersionCapabilitiesRequest,
response *api.QueryRoomVersionCapabilitiesResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRoomVersionCapabilities", h.roomserverURL+RoomserverQueryRoomVersionCapabilitiesPath,
h.httpClient, ctx, request, response,
)
}
// QueryRoomVersionForRoom implements RoomServerQueryAPI
func (h *httpRoomserverInternalAPI) QueryRoomVersionForRoom(
ctx context.Context,
request *api.QueryRoomVersionForRoomRequest,
response *api.QueryRoomVersionForRoomResponse,
) error {
if roomVersion, ok := h.cache.GetRoomVersion(request.RoomID); ok {
response.RoomVersion = roomVersion
return nil
}
err := httputil.CallInternalRPCAPI(
"QueryRoomVersionForRoom", h.roomserverURL+RoomserverQueryRoomVersionForRoomPath,
h.httpClient, ctx, request, response,
)
if err == nil {
h.cache.StoreRoomVersion(request.RoomID, response.RoomVersion)
}
return err
}
func (h *httpRoomserverInternalAPI) QueryCurrentState(
ctx context.Context,
request *api.QueryCurrentStateRequest,
response *api.QueryCurrentStateResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryCurrentState", h.roomserverURL+RoomserverQueryCurrentStatePath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryRoomsForUser(
ctx context.Context,
request *api.QueryRoomsForUserRequest,
response *api.QueryRoomsForUserResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRoomsForUser", h.roomserverURL+RoomserverQueryRoomsForUserPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryBulkStateContent(
ctx context.Context,
request *api.QueryBulkStateContentRequest,
response *api.QueryBulkStateContentResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryBulkStateContent", h.roomserverURL+RoomserverQueryBulkStateContentPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QuerySharedUsers(
ctx context.Context,
request *api.QuerySharedUsersRequest,
response *api.QuerySharedUsersResponse,
) error {
return httputil.CallInternalRPCAPI(
"QuerySharedUsers", h.roomserverURL+RoomserverQuerySharedUsersPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryKnownUsers(
ctx context.Context,
request *api.QueryKnownUsersRequest,
response *api.QueryKnownUsersResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryKnownUsers", h.roomserverURL+RoomserverQueryKnownUsersPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryAuthChain(
ctx context.Context,
request *api.QueryAuthChainRequest,
response *api.QueryAuthChainResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryAuthChain", h.roomserverURL+RoomserverQueryAuthChainPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryServerBannedFromRoom(
ctx context.Context,
request *api.QueryServerBannedFromRoomRequest,
response *api.QueryServerBannedFromRoomResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryServerBannedFromRoom", h.roomserverURL+RoomserverQueryServerBannedFromRoomPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryRestrictedJoinAllowed(
ctx context.Context,
request *api.QueryRestrictedJoinAllowedRequest,
response *api.QueryRestrictedJoinAllowedResponse,
) error {
return httputil.CallInternalRPCAPI(
"QueryRestrictedJoinAllowed", h.roomserverURL+RoomserverQueryRestrictedJoinAllowed,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) PerformForget(
ctx context.Context,
request *api.PerformForgetRequest,
response *api.PerformForgetResponse,
) error {
return httputil.CallInternalRPCAPI(
"PerformForget", h.roomserverURL+RoomserverPerformForgetPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryMembershipAtEvent(ctx context.Context, request *api.QueryMembershipAtEventRequest, response *api.QueryMembershipAtEventResponse) error {
return httputil.CallInternalRPCAPI(
"QueryMembershiptAtEvent", h.roomserverURL+RoomserverQueryMembershipAtEventPath,
h.httpClient, ctx, request, response,
)
}
func (h *httpRoomserverInternalAPI) QueryLeftUsers(ctx context.Context, request *api.QueryLeftUsersRequest, response *api.QueryLeftUsersResponse) error {
return httputil.CallInternalRPCAPI(
"RoomserverQueryLeftMembers", h.roomserverURL+RoomserverQueryLeftMembersPath,
h.httpClient, ctx, request, response,
)
}