Notify clients when devices are deleted (#1233)
* Recheck device lists when join/leave events come in * Add PerformDeviceDeletion * Notify clients when devices are deleted * Unbreak things * Remove debug loggingmain
parent
292a9ddd82
commit
a7e67e65a8
|
@ -118,7 +118,9 @@ func (m *DendriteMonolith) Start() {
|
||||||
|
|
||||||
serverKeyAPI := &signing.YggdrasilKeys{}
|
serverKeyAPI := &signing.YggdrasilKeys{}
|
||||||
keyRing := serverKeyAPI.KeyRing()
|
keyRing := serverKeyAPI.KeyRing()
|
||||||
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices)
|
keyAPI := keyserver.NewInternalAPI(base.Cfg, federation, base.KafkaProducer)
|
||||||
|
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices, keyAPI)
|
||||||
|
keyAPI.SetUserAPI(userAPI)
|
||||||
|
|
||||||
rsAPI := roomserver.NewInternalAPI(
|
rsAPI := roomserver.NewInternalAPI(
|
||||||
base, keyRing, federation,
|
base, keyRing, federation,
|
||||||
|
@ -156,7 +158,7 @@ func (m *DendriteMonolith) Start() {
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
StateAPI: stateAPI,
|
StateAPI: stateAPI,
|
||||||
KeyAPI: keyserver.NewInternalAPI(base.Cfg, federation, userAPI, base.KafkaProducer),
|
KeyAPI: keyAPI,
|
||||||
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
||||||
ygg, fsAPI, federation,
|
ygg, fsAPI, federation,
|
||||||
),
|
),
|
||||||
|
|
|
@ -165,7 +165,7 @@ func UpdateDeviceByID(
|
||||||
|
|
||||||
// DeleteDeviceById handles DELETE requests to /devices/{deviceId}
|
// DeleteDeviceById handles DELETE requests to /devices/{deviceId}
|
||||||
func DeleteDeviceById(
|
func DeleteDeviceById(
|
||||||
req *http.Request, userInteractiveAuth *auth.UserInteractive, deviceDB devices.Database, device *api.Device,
|
req *http.Request, userInteractiveAuth *auth.UserInteractive, userAPI api.UserInternalAPI, device *api.Device,
|
||||||
deviceID string,
|
deviceID string,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
|
@ -197,8 +197,12 @@ func DeleteDeviceById(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := deviceDB.RemoveDevice(ctx, deviceID, localpart); err != nil {
|
var res api.PerformDeviceDeletionResponse
|
||||||
util.GetLogger(ctx).WithError(err).Error("deviceDB.RemoveDevice failed")
|
if err := userAPI.PerformDeviceDeletion(ctx, &api.PerformDeviceDeletionRequest{
|
||||||
|
UserID: device.UserID,
|
||||||
|
DeviceIDs: []string{deviceID},
|
||||||
|
}, &res); err != nil {
|
||||||
|
util.GetLogger(ctx).WithError(err).Error("userAPI.PerformDeviceDeletion failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,26 +214,24 @@ func DeleteDeviceById(
|
||||||
|
|
||||||
// DeleteDevices handles POST requests to /delete_devices
|
// DeleteDevices handles POST requests to /delete_devices
|
||||||
func DeleteDevices(
|
func DeleteDevices(
|
||||||
req *http.Request, deviceDB devices.Database, device *api.Device,
|
req *http.Request, userAPI api.UserInternalAPI, device *api.Device,
|
||||||
) util.JSONResponse {
|
) util.JSONResponse {
|
||||||
localpart, _, err := gomatrixserverlib.SplitID('@', device.UserID)
|
|
||||||
if err != nil {
|
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
|
|
||||||
return jsonerror.InternalServerError()
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
payload := devicesDeleteJSON{}
|
payload := devicesDeleteJSON{}
|
||||||
|
|
||||||
if err := json.NewDecoder(req.Body).Decode(&payload); err != nil {
|
if err := json.NewDecoder(req.Body).Decode(&payload); err != nil {
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("json.NewDecoder.Decode failed")
|
util.GetLogger(ctx).WithError(err).Error("json.NewDecoder.Decode failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
defer req.Body.Close() // nolint: errcheck
|
defer req.Body.Close() // nolint: errcheck
|
||||||
|
|
||||||
if err := deviceDB.RemoveDevices(ctx, localpart, payload.Devices); err != nil {
|
var res api.PerformDeviceDeletionResponse
|
||||||
util.GetLogger(req.Context()).WithError(err).Error("deviceDB.RemoveDevices failed")
|
if err := userAPI.PerformDeviceDeletion(ctx, &api.PerformDeviceDeletionRequest{
|
||||||
|
UserID: device.UserID,
|
||||||
|
DeviceIDs: payload.Devices,
|
||||||
|
}, &res); err != nil {
|
||||||
|
util.GetLogger(ctx).WithError(err).Error("userAPI.PerformDeviceDeletion failed")
|
||||||
return jsonerror.InternalServerError()
|
return jsonerror.InternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -654,13 +654,13 @@ func Setup(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return util.ErrorResponse(err)
|
return util.ErrorResponse(err)
|
||||||
}
|
}
|
||||||
return DeleteDeviceById(req, userInteractiveAuth, deviceDB, device, vars["deviceID"])
|
return DeleteDeviceById(req, userInteractiveAuth, userAPI, device, vars["deviceID"])
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodDelete, http.MethodOptions)
|
).Methods(http.MethodDelete, http.MethodOptions)
|
||||||
|
|
||||||
r0mux.Handle("/delete_devices",
|
r0mux.Handle("/delete_devices",
|
||||||
httputil.MakeAuthAPI("delete_devices", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
httputil.MakeAuthAPI("delete_devices", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||||
return DeleteDevices(req, deviceDB, device)
|
return DeleteDevices(req, userAPI, device)
|
||||||
}),
|
}),
|
||||||
).Methods(http.MethodPost, http.MethodOptions)
|
).Methods(http.MethodPost, http.MethodOptions)
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,9 @@ func main() {
|
||||||
accountDB := base.Base.CreateAccountsDB()
|
accountDB := base.Base.CreateAccountsDB()
|
||||||
deviceDB := base.Base.CreateDeviceDB()
|
deviceDB := base.Base.CreateDeviceDB()
|
||||||
federation := createFederationClient(base)
|
federation := createFederationClient(base)
|
||||||
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, nil)
|
keyAPI := keyserver.NewInternalAPI(base.Base.Cfg, federation, base.Base.KafkaProducer)
|
||||||
|
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, nil, keyAPI)
|
||||||
|
keyAPI.SetUserAPI(userAPI)
|
||||||
|
|
||||||
serverKeyAPI := serverkeyapi.NewInternalAPI(
|
serverKeyAPI := serverkeyapi.NewInternalAPI(
|
||||||
base.Base.Cfg, federation, base.Base.Caches,
|
base.Base.Cfg, federation, base.Base.Caches,
|
||||||
|
@ -186,7 +188,7 @@ func main() {
|
||||||
ServerKeyAPI: serverKeyAPI,
|
ServerKeyAPI: serverKeyAPI,
|
||||||
StateAPI: stateAPI,
|
StateAPI: stateAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
KeyAPI: keyserver.NewInternalAPI(base.Base.Cfg, federation, userAPI, base.Base.KafkaProducer),
|
KeyAPI: keyAPI,
|
||||||
ExtPublicRoomsProvider: provider,
|
ExtPublicRoomsProvider: provider,
|
||||||
}
|
}
|
||||||
monolith.AddAllPublicRoutes(base.Base.PublicAPIMux)
|
monolith.AddAllPublicRoutes(base.Base.PublicAPIMux)
|
||||||
|
|
|
@ -103,7 +103,9 @@ func main() {
|
||||||
serverKeyAPI := &signing.YggdrasilKeys{}
|
serverKeyAPI := &signing.YggdrasilKeys{}
|
||||||
keyRing := serverKeyAPI.KeyRing()
|
keyRing := serverKeyAPI.KeyRing()
|
||||||
|
|
||||||
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, nil)
|
keyAPI := keyserver.NewInternalAPI(base.Cfg, federation, base.KafkaProducer)
|
||||||
|
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, nil, keyAPI)
|
||||||
|
keyAPI.SetUserAPI(userAPI)
|
||||||
|
|
||||||
rsComponent := roomserver.NewInternalAPI(
|
rsComponent := roomserver.NewInternalAPI(
|
||||||
base, keyRing, federation,
|
base, keyRing, federation,
|
||||||
|
@ -142,7 +144,7 @@ func main() {
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
StateAPI: stateAPI,
|
StateAPI: stateAPI,
|
||||||
KeyAPI: keyserver.NewInternalAPI(base.Cfg, federation, userAPI, base.KafkaProducer),
|
KeyAPI: keyAPI,
|
||||||
//ServerKeyAPI: serverKeyAPI,
|
//ServerKeyAPI: serverKeyAPI,
|
||||||
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
ExtPublicRoomsProvider: yggrooms.NewYggdrasilRoomProvider(
|
||||||
ygg, fsAPI, federation,
|
ygg, fsAPI, federation,
|
||||||
|
|
|
@ -24,7 +24,8 @@ func main() {
|
||||||
base := setup.NewBaseDendrite(cfg, "KeyServer", true)
|
base := setup.NewBaseDendrite(cfg, "KeyServer", true)
|
||||||
defer base.Close() // nolint: errcheck
|
defer base.Close() // nolint: errcheck
|
||||||
|
|
||||||
intAPI := keyserver.NewInternalAPI(base.Cfg, base.CreateFederationClient(), base.UserAPIClient(), base.KafkaProducer)
|
intAPI := keyserver.NewInternalAPI(base.Cfg, base.CreateFederationClient(), base.KafkaProducer)
|
||||||
|
intAPI.SetUserAPI(base.UserAPIClient())
|
||||||
|
|
||||||
keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI)
|
keyserver.AddInternalRoutes(base.InternalAPIMux, intAPI)
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,9 @@ func main() {
|
||||||
serverKeyAPI = base.ServerKeyAPIClient()
|
serverKeyAPI = base.ServerKeyAPIClient()
|
||||||
}
|
}
|
||||||
keyRing := serverKeyAPI.KeyRing()
|
keyRing := serverKeyAPI.KeyRing()
|
||||||
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices)
|
keyAPI := keyserver.NewInternalAPI(base.Cfg, federation, base.KafkaProducer)
|
||||||
|
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices, keyAPI)
|
||||||
|
keyAPI.SetUserAPI(userAPI)
|
||||||
|
|
||||||
rsImpl := roomserver.NewInternalAPI(
|
rsImpl := roomserver.NewInternalAPI(
|
||||||
base, keyRing, federation,
|
base, keyRing, federation,
|
||||||
|
@ -119,7 +121,6 @@ func main() {
|
||||||
rsImpl.SetFederationSenderAPI(fsAPI)
|
rsImpl.SetFederationSenderAPI(fsAPI)
|
||||||
|
|
||||||
stateAPI := currentstateserver.NewInternalAPI(base.Cfg, base.KafkaConsumer)
|
stateAPI := currentstateserver.NewInternalAPI(base.Cfg, base.KafkaConsumer)
|
||||||
keyAPI := keyserver.NewInternalAPI(base.Cfg, federation, userAPI, base.KafkaProducer)
|
|
||||||
|
|
||||||
monolith := setup.Monolith{
|
monolith := setup.Monolith{
|
||||||
Config: base.Cfg,
|
Config: base.Cfg,
|
||||||
|
|
|
@ -27,7 +27,7 @@ func main() {
|
||||||
accountDB := base.CreateAccountsDB()
|
accountDB := base.CreateAccountsDB()
|
||||||
deviceDB := base.CreateDeviceDB()
|
deviceDB := base.CreateDeviceDB()
|
||||||
|
|
||||||
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices)
|
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, cfg.Derived.ApplicationServices, base.KeyServerHTTPClient())
|
||||||
|
|
||||||
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI)
|
userapi.AddInternalRoutes(base.InternalAPIMux, userAPI)
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,9 @@ func main() {
|
||||||
accountDB := base.CreateAccountsDB()
|
accountDB := base.CreateAccountsDB()
|
||||||
deviceDB := base.CreateDeviceDB()
|
deviceDB := base.CreateDeviceDB()
|
||||||
federation := createFederationClient(cfg, node)
|
federation := createFederationClient(cfg, node)
|
||||||
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, nil)
|
keyAPI := keyserver.NewInternalAPI(base.Cfg, federation, base.KafkaProducer)
|
||||||
|
userAPI := userapi.NewInternalAPI(accountDB, deviceDB, cfg.Matrix.ServerName, nil, keyAPI)
|
||||||
|
keyAPI.SetUserAPI(userAPI)
|
||||||
|
|
||||||
fetcher := &libp2pKeyFetcher{}
|
fetcher := &libp2pKeyFetcher{}
|
||||||
keyRing := gomatrixserverlib.KeyRing{
|
keyRing := gomatrixserverlib.KeyRing{
|
||||||
|
@ -233,7 +235,7 @@ func main() {
|
||||||
RoomserverAPI: rsAPI,
|
RoomserverAPI: rsAPI,
|
||||||
StateAPI: stateAPI,
|
StateAPI: stateAPI,
|
||||||
UserAPI: userAPI,
|
UserAPI: userAPI,
|
||||||
KeyAPI: keyserver.NewInternalAPI(base.Cfg, federation, userAPI, base.KafkaProducer),
|
KeyAPI: keyAPI,
|
||||||
//ServerKeyAPI: serverKeyAPI,
|
//ServerKeyAPI: serverKeyAPI,
|
||||||
ExtPublicRoomsProvider: p2pPublicRoomProvider,
|
ExtPublicRoomsProvider: p2pPublicRoomProvider,
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,13 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyInternalAPI interface {
|
type KeyInternalAPI interface {
|
||||||
|
// SetUserAPI assigns a user API to query when extracting device names.
|
||||||
|
SetUserAPI(i userapi.UserInternalAPI)
|
||||||
PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse)
|
PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse)
|
||||||
// PerformClaimKeys claims one-time keys for use in pre-key messages
|
// PerformClaimKeys claims one-time keys for use in pre-key messages
|
||||||
PerformClaimKeys(ctx context.Context, req *PerformClaimKeysRequest, res *PerformClaimKeysResponse)
|
PerformClaimKeys(ctx context.Context, req *PerformClaimKeysRequest, res *PerformClaimKeysResponse)
|
||||||
|
|
|
@ -40,6 +40,10 @@ type KeyInternalAPI struct {
|
||||||
Producer *producers.KeyChange
|
Producer *producers.KeyChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *KeyInternalAPI) SetUserAPI(i userapi.UserInternalAPI) {
|
||||||
|
a.UserAPI = i
|
||||||
|
}
|
||||||
|
|
||||||
func (a *KeyInternalAPI) QueryKeyChanges(ctx context.Context, req *api.QueryKeyChangesRequest, res *api.QueryKeyChangesResponse) {
|
func (a *KeyInternalAPI) QueryKeyChanges(ctx context.Context, req *api.QueryKeyChangesRequest, res *api.QueryKeyChangesResponse) {
|
||||||
if req.Partition < 0 {
|
if req.Partition < 0 {
|
||||||
req.Partition = a.Producer.DefaultPartition()
|
req.Partition = a.Producer.DefaultPartition()
|
||||||
|
@ -272,6 +276,10 @@ func (a *KeyInternalAPI) uploadDeviceKeys(ctx context.Context, req *api.PerformU
|
||||||
var keysToStore []api.DeviceKeys
|
var keysToStore []api.DeviceKeys
|
||||||
// assert that the user ID / device ID are not lying for each key
|
// assert that the user ID / device ID are not lying for each key
|
||||||
for _, key := range req.DeviceKeys {
|
for _, key := range req.DeviceKeys {
|
||||||
|
if len(key.KeyJSON) == 0 {
|
||||||
|
keysToStore = append(keysToStore, key)
|
||||||
|
continue // deleted keys don't need sanity checking
|
||||||
|
}
|
||||||
gotUserID := gjson.GetBytes(key.KeyJSON, "user_id").Str
|
gotUserID := gjson.GetBytes(key.KeyJSON, "user_id").Str
|
||||||
gotDeviceID := gjson.GetBytes(key.KeyJSON, "device_id").Str
|
gotDeviceID := gjson.GetBytes(key.KeyJSON, "device_id").Str
|
||||||
if gotUserID == key.UserID && gotDeviceID == key.DeviceID {
|
if gotUserID == key.UserID && gotDeviceID == key.DeviceID {
|
||||||
|
@ -286,6 +294,7 @@ func (a *KeyInternalAPI) uploadDeviceKeys(ctx context.Context, req *api.PerformU
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// get existing device keys so we can check for changes
|
// get existing device keys so we can check for changes
|
||||||
existingKeys := make([]api.DeviceKeys, len(keysToStore))
|
existingKeys := make([]api.DeviceKeys, len(keysToStore))
|
||||||
for i := range keysToStore {
|
for i := range keysToStore {
|
||||||
|
@ -358,7 +367,9 @@ func (a *KeyInternalAPI) emitDeviceKeyChanges(existing, new []api.DeviceKeys) er
|
||||||
for _, newKey := range new {
|
for _, newKey := range new {
|
||||||
exists := false
|
exists := false
|
||||||
for _, existingKey := range existing {
|
for _, existingKey := range existing {
|
||||||
if bytes.Equal(existingKey.KeyJSON, newKey.KeyJSON) {
|
// Do not treat the absence of keys as equal, or else we will not emit key changes
|
||||||
|
// when users delete devices which never had a key to begin with as both KeyJSONs are nil.
|
||||||
|
if bytes.Equal(existingKey.KeyJSON, newKey.KeyJSON) && len(existingKey.KeyJSON) > 0 {
|
||||||
exists = true
|
exists = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/httputil"
|
"github.com/matrix-org/dendrite/internal/httputil"
|
||||||
"github.com/matrix-org/dendrite/keyserver/api"
|
"github.com/matrix-org/dendrite/keyserver/api"
|
||||||
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,6 +53,10 @@ type httpKeyInternalAPI struct {
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *httpKeyInternalAPI) SetUserAPI(i userapi.UserInternalAPI) {
|
||||||
|
// no-op: doesn't need it
|
||||||
|
}
|
||||||
|
|
||||||
func (h *httpKeyInternalAPI) PerformClaimKeys(
|
func (h *httpKeyInternalAPI) PerformClaimKeys(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
request *api.PerformClaimKeysRequest,
|
request *api.PerformClaimKeysRequest,
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/keyserver/inthttp"
|
"github.com/matrix-org/dendrite/keyserver/inthttp"
|
||||||
"github.com/matrix-org/dendrite/keyserver/producers"
|
"github.com/matrix-org/dendrite/keyserver/producers"
|
||||||
"github.com/matrix-org/dendrite/keyserver/storage"
|
"github.com/matrix-org/dendrite/keyserver/storage"
|
||||||
userapi "github.com/matrix-org/dendrite/userapi/api"
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -37,7 +36,7 @@ func AddInternalRoutes(router *mux.Router, intAPI api.KeyInternalAPI) {
|
||||||
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
||||||
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
||||||
func NewInternalAPI(
|
func NewInternalAPI(
|
||||||
cfg *config.Dendrite, fedClient *gomatrixserverlib.FederationClient, userAPI userapi.UserInternalAPI, producer sarama.SyncProducer,
|
cfg *config.Dendrite, fedClient *gomatrixserverlib.FederationClient, producer sarama.SyncProducer,
|
||||||
) api.KeyInternalAPI {
|
) api.KeyInternalAPI {
|
||||||
db, err := storage.NewDatabase(
|
db, err := storage.NewDatabase(
|
||||||
string(cfg.Database.E2EKey),
|
string(cfg.Database.E2EKey),
|
||||||
|
@ -55,7 +54,6 @@ func NewInternalAPI(
|
||||||
DB: db,
|
DB: db,
|
||||||
ThisServer: cfg.Matrix.ServerName,
|
ThisServer: cfg.Matrix.ServerName,
|
||||||
FedClient: fedClient,
|
FedClient: fedClient,
|
||||||
UserAPI: userAPI,
|
|
||||||
Producer: keyChangeProducer,
|
Producer: keyChangeProducer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,11 @@ func (p *KeyChange) ProduceKeyChanges(keys []api.DeviceKeys) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"user_id": key.UserID,
|
"user_id": key.UserID,
|
||||||
"device_id": key.DeviceID,
|
"device_id": key.DeviceID,
|
||||||
"partition": partition,
|
"partition": partition,
|
||||||
"offset": offset,
|
"offset": offset,
|
||||||
|
"len_key_bytes": len(key.KeyJSON),
|
||||||
}).Infof("Produced to key change topic '%s'", p.Topic)
|
}).Infof("Produced to key change topic '%s'", p.Topic)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -32,7 +32,8 @@ type Database interface {
|
||||||
// DeviceKeysJSON populates the KeyJSON for the given keys. If any proided `keys` have a `KeyJSON` already then it will be replaced.
|
// DeviceKeysJSON populates the KeyJSON for the given keys. If any proided `keys` have a `KeyJSON` already then it will be replaced.
|
||||||
DeviceKeysJSON(ctx context.Context, keys []api.DeviceKeys) error
|
DeviceKeysJSON(ctx context.Context, keys []api.DeviceKeys) error
|
||||||
|
|
||||||
// StoreDeviceKeys persists the given keys. Keys with the same user ID and device ID will be replaced.
|
// StoreDeviceKeys persists the given keys. Keys with the same user ID and device ID will be replaced. An empty KeyJSON removes the key
|
||||||
|
// for this (user, device).
|
||||||
// Returns an error if there was a problem storing the keys.
|
// Returns an error if there was a problem storing the keys.
|
||||||
StoreDeviceKeys(ctx context.Context, keys []api.DeviceKeys) error
|
StoreDeviceKeys(ctx context.Context, keys []api.DeviceKeys) error
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ type OutputRoomEventConsumer struct {
|
||||||
rsConsumer *internal.ContinualConsumer
|
rsConsumer *internal.ContinualConsumer
|
||||||
db storage.Database
|
db storage.Database
|
||||||
notifier *sync.Notifier
|
notifier *sync.Notifier
|
||||||
|
keyChanges *OutputKeyChangeEventConsumer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOutputRoomEventConsumer creates a new OutputRoomEventConsumer. Call Start() to begin consuming from room servers.
|
// NewOutputRoomEventConsumer creates a new OutputRoomEventConsumer. Call Start() to begin consuming from room servers.
|
||||||
|
@ -44,6 +45,7 @@ func NewOutputRoomEventConsumer(
|
||||||
n *sync.Notifier,
|
n *sync.Notifier,
|
||||||
store storage.Database,
|
store storage.Database,
|
||||||
rsAPI api.RoomserverInternalAPI,
|
rsAPI api.RoomserverInternalAPI,
|
||||||
|
keyChanges *OutputKeyChangeEventConsumer,
|
||||||
) *OutputRoomEventConsumer {
|
) *OutputRoomEventConsumer {
|
||||||
|
|
||||||
consumer := internal.ContinualConsumer{
|
consumer := internal.ContinualConsumer{
|
||||||
|
@ -56,6 +58,7 @@ func NewOutputRoomEventConsumer(
|
||||||
db: store,
|
db: store,
|
||||||
notifier: n,
|
notifier: n,
|
||||||
rsAPI: rsAPI,
|
rsAPI: rsAPI,
|
||||||
|
keyChanges: keyChanges,
|
||||||
}
|
}
|
||||||
consumer.ProcessMessage = s.onMessage
|
consumer.ProcessMessage = s.onMessage
|
||||||
|
|
||||||
|
@ -160,9 +163,29 @@ func (s *OutputRoomEventConsumer) onNewRoomEvent(
|
||||||
}
|
}
|
||||||
s.notifier.OnNewEvent(&ev, "", nil, types.NewStreamToken(pduPos, 0, nil))
|
s.notifier.OnNewEvent(&ev, "", nil, types.NewStreamToken(pduPos, 0, nil))
|
||||||
|
|
||||||
|
s.notifyKeyChanges(&ev)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *OutputRoomEventConsumer) notifyKeyChanges(ev *gomatrixserverlib.HeaderedEvent) {
|
||||||
|
if ev.Type() != gomatrixserverlib.MRoomMember || ev.StateKey() == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
membership, err := ev.Membership()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch membership {
|
||||||
|
case gomatrixserverlib.Join:
|
||||||
|
s.keyChanges.OnJoinEvent(ev)
|
||||||
|
case gomatrixserverlib.Ban:
|
||||||
|
fallthrough
|
||||||
|
case gomatrixserverlib.Leave:
|
||||||
|
s.keyChanges.OnLeaveEvent(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *OutputRoomEventConsumer) onNewInviteEvent(
|
func (s *OutputRoomEventConsumer) onNewInviteEvent(
|
||||||
ctx context.Context, msg api.OutputNewInviteEvent,
|
ctx context.Context, msg api.OutputNewInviteEvent,
|
||||||
) error {
|
) error {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/currentstateserver/api"
|
"github.com/matrix-org/dendrite/currentstateserver/api"
|
||||||
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
||||||
"github.com/matrix-org/dendrite/syncapi/types"
|
"github.com/matrix-org/dendrite/syncapi/types"
|
||||||
|
userapi "github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ type mockKeyAPI struct{}
|
||||||
func (k *mockKeyAPI) PerformUploadKeys(ctx context.Context, req *keyapi.PerformUploadKeysRequest, res *keyapi.PerformUploadKeysResponse) {
|
func (k *mockKeyAPI) PerformUploadKeys(ctx context.Context, req *keyapi.PerformUploadKeysRequest, res *keyapi.PerformUploadKeysResponse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *mockKeyAPI) SetUserAPI(i userapi.UserInternalAPI) {}
|
||||||
|
|
||||||
// PerformClaimKeys claims one-time keys for use in pre-key messages
|
// PerformClaimKeys claims one-time keys for use in pre-key messages
|
||||||
func (k *mockKeyAPI) PerformClaimKeys(ctx context.Context, req *keyapi.PerformClaimKeysRequest, res *keyapi.PerformClaimKeysResponse) {
|
func (k *mockKeyAPI) PerformClaimKeys(ctx context.Context, req *keyapi.PerformClaimKeysRequest, res *keyapi.PerformClaimKeysResponse) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,16 @@ func AddPublicRoutes(
|
||||||
|
|
||||||
requestPool := sync.NewRequestPool(syncDB, notifier, userAPI, keyAPI, currentStateAPI)
|
requestPool := sync.NewRequestPool(syncDB, notifier, userAPI, keyAPI, currentStateAPI)
|
||||||
|
|
||||||
|
keyChangeConsumer := consumers.NewOutputKeyChangeEventConsumer(
|
||||||
|
cfg.Matrix.ServerName, string(cfg.Kafka.Topics.OutputKeyChangeEvent),
|
||||||
|
consumer, notifier, keyAPI, currentStateAPI, syncDB,
|
||||||
|
)
|
||||||
|
if err = keyChangeConsumer.Start(); err != nil {
|
||||||
|
logrus.WithError(err).Panicf("failed to start key change consumer")
|
||||||
|
}
|
||||||
|
|
||||||
roomConsumer := consumers.NewOutputRoomEventConsumer(
|
roomConsumer := consumers.NewOutputRoomEventConsumer(
|
||||||
cfg, consumer, notifier, syncDB, rsAPI,
|
cfg, consumer, notifier, syncDB, rsAPI, keyChangeConsumer,
|
||||||
)
|
)
|
||||||
if err = roomConsumer.Start(); err != nil {
|
if err = roomConsumer.Start(); err != nil {
|
||||||
logrus.WithError(err).Panicf("failed to start room server consumer")
|
logrus.WithError(err).Panicf("failed to start room server consumer")
|
||||||
|
@ -92,13 +100,5 @@ func AddPublicRoutes(
|
||||||
logrus.WithError(err).Panicf("failed to start send-to-device consumer")
|
logrus.WithError(err).Panicf("failed to start send-to-device consumer")
|
||||||
}
|
}
|
||||||
|
|
||||||
keyChangeConsumer := consumers.NewOutputKeyChangeEventConsumer(
|
|
||||||
cfg.Matrix.ServerName, string(cfg.Kafka.Topics.OutputKeyChangeEvent),
|
|
||||||
consumer, notifier, keyAPI, currentStateAPI, syncDB,
|
|
||||||
)
|
|
||||||
if err = keyChangeConsumer.Start(); err != nil {
|
|
||||||
logrus.WithError(err).Panicf("failed to start key change consumer")
|
|
||||||
}
|
|
||||||
|
|
||||||
routing.Setup(router, requestPool, syncDB, userAPI, federation, rsAPI, cfg)
|
routing.Setup(router, requestPool, syncDB, userAPI, federation, rsAPI, cfg)
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ Can claim one time key using POST
|
||||||
Can claim remote one time key using POST
|
Can claim remote one time key using POST
|
||||||
Local device key changes appear in v2 /sync
|
Local device key changes appear in v2 /sync
|
||||||
Local device key changes appear in /keys/changes
|
Local device key changes appear in /keys/changes
|
||||||
|
Local delete device changes appear in v2 /sync
|
||||||
Get left notifs for other users in sync and /keys/changes when user leaves
|
Get left notifs for other users in sync and /keys/changes when user leaves
|
||||||
Can add account data
|
Can add account data
|
||||||
Can add account data to room
|
Can add account data to room
|
||||||
|
|
|
@ -27,6 +27,7 @@ type UserInternalAPI interface {
|
||||||
InputAccountData(ctx context.Context, req *InputAccountDataRequest, res *InputAccountDataResponse) error
|
InputAccountData(ctx context.Context, req *InputAccountDataRequest, res *InputAccountDataResponse) error
|
||||||
PerformAccountCreation(ctx context.Context, req *PerformAccountCreationRequest, res *PerformAccountCreationResponse) error
|
PerformAccountCreation(ctx context.Context, req *PerformAccountCreationRequest, res *PerformAccountCreationResponse) error
|
||||||
PerformDeviceCreation(ctx context.Context, req *PerformDeviceCreationRequest, res *PerformDeviceCreationResponse) error
|
PerformDeviceCreation(ctx context.Context, req *PerformDeviceCreationRequest, res *PerformDeviceCreationResponse) error
|
||||||
|
PerformDeviceDeletion(ctx context.Context, req *PerformDeviceDeletionRequest, res *PerformDeviceDeletionResponse) error
|
||||||
QueryProfile(ctx context.Context, req *QueryProfileRequest, res *QueryProfileResponse) error
|
QueryProfile(ctx context.Context, req *QueryProfileRequest, res *QueryProfileResponse) error
|
||||||
QueryAccessToken(ctx context.Context, req *QueryAccessTokenRequest, res *QueryAccessTokenResponse) error
|
QueryAccessToken(ctx context.Context, req *QueryAccessTokenRequest, res *QueryAccessTokenResponse) error
|
||||||
QueryDevices(ctx context.Context, req *QueryDevicesRequest, res *QueryDevicesResponse) error
|
QueryDevices(ctx context.Context, req *QueryDevicesRequest, res *QueryDevicesResponse) error
|
||||||
|
@ -47,6 +48,15 @@ type InputAccountDataRequest struct {
|
||||||
type InputAccountDataResponse struct {
|
type InputAccountDataResponse struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PerformDeviceDeletionRequest struct {
|
||||||
|
UserID string
|
||||||
|
// The devices to delete
|
||||||
|
DeviceIDs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PerformDeviceDeletionResponse struct {
|
||||||
|
}
|
||||||
|
|
||||||
// QueryDeviceInfosRequest is the request to QueryDeviceInfos
|
// QueryDeviceInfosRequest is the request to QueryDeviceInfos
|
||||||
type QueryDeviceInfosRequest struct {
|
type QueryDeviceInfosRequest struct {
|
||||||
DeviceIDs []string
|
DeviceIDs []string
|
||||||
|
|
|
@ -25,10 +25,12 @@ import (
|
||||||
"github.com/matrix-org/dendrite/clientapi/userutil"
|
"github.com/matrix-org/dendrite/clientapi/userutil"
|
||||||
"github.com/matrix-org/dendrite/internal/config"
|
"github.com/matrix-org/dendrite/internal/config"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
"github.com/matrix-org/dendrite/userapi/storage/accounts"
|
||||||
"github.com/matrix-org/dendrite/userapi/storage/devices"
|
"github.com/matrix-org/dendrite/userapi/storage/devices"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
"github.com/matrix-org/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserInternalAPI struct {
|
type UserInternalAPI struct {
|
||||||
|
@ -37,6 +39,7 @@ type UserInternalAPI struct {
|
||||||
ServerName gomatrixserverlib.ServerName
|
ServerName gomatrixserverlib.ServerName
|
||||||
// AppServices is the list of all registered AS
|
// AppServices is the list of all registered AS
|
||||||
AppServices []config.ApplicationService
|
AppServices []config.ApplicationService
|
||||||
|
KeyAPI keyapi.KeyInternalAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *UserInternalAPI) InputAccountData(ctx context.Context, req *api.InputAccountDataRequest, res *api.InputAccountDataResponse) error {
|
func (a *UserInternalAPI) InputAccountData(ctx context.Context, req *api.InputAccountDataRequest, res *api.InputAccountDataResponse) error {
|
||||||
|
@ -104,6 +107,42 @@ func (a *UserInternalAPI) PerformDeviceCreation(ctx context.Context, req *api.Pe
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *UserInternalAPI) PerformDeviceDeletion(ctx context.Context, req *api.PerformDeviceDeletionRequest, res *api.PerformDeviceDeletionResponse) error {
|
||||||
|
util.GetLogger(ctx).WithField("user_id", req.UserID).WithField("devices", req.DeviceIDs).Info("PerformDeviceDeletion")
|
||||||
|
local, domain, err := gomatrixserverlib.SplitID('@', req.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if domain != a.ServerName {
|
||||||
|
return fmt.Errorf("cannot PerformDeviceDeletion of remote users: got %s want %s", domain, a.ServerName)
|
||||||
|
}
|
||||||
|
err = a.DeviceDB.RemoveDevices(ctx, local, req.DeviceIDs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// create empty device keys and upload them to delete what was once there and trigger device list changes
|
||||||
|
deviceKeys := make([]keyapi.DeviceKeys, len(req.DeviceIDs))
|
||||||
|
for i, did := range req.DeviceIDs {
|
||||||
|
deviceKeys[i] = keyapi.DeviceKeys{
|
||||||
|
UserID: req.UserID,
|
||||||
|
DeviceID: did,
|
||||||
|
KeyJSON: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var uploadRes keyapi.PerformUploadKeysResponse
|
||||||
|
a.KeyAPI.PerformUploadKeys(context.Background(), &keyapi.PerformUploadKeysRequest{
|
||||||
|
DeviceKeys: deviceKeys,
|
||||||
|
}, &uploadRes)
|
||||||
|
if uploadRes.Error != nil {
|
||||||
|
return fmt.Errorf("Failed to delete device keys: %v", uploadRes.Error)
|
||||||
|
}
|
||||||
|
if len(uploadRes.KeyErrors) > 0 {
|
||||||
|
return fmt.Errorf("Failed to delete device keys, key errors: %+v", uploadRes.KeyErrors)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *UserInternalAPI) QueryProfile(ctx context.Context, req *api.QueryProfileRequest, res *api.QueryProfileResponse) error {
|
func (a *UserInternalAPI) QueryProfile(ctx context.Context, req *api.QueryProfileRequest, res *api.QueryProfileResponse) error {
|
||||||
local, domain, err := gomatrixserverlib.SplitID('@', req.UserID)
|
local, domain, err := gomatrixserverlib.SplitID('@', req.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,6 +30,7 @@ const (
|
||||||
|
|
||||||
PerformDeviceCreationPath = "/userapi/performDeviceCreation"
|
PerformDeviceCreationPath = "/userapi/performDeviceCreation"
|
||||||
PerformAccountCreationPath = "/userapi/performAccountCreation"
|
PerformAccountCreationPath = "/userapi/performAccountCreation"
|
||||||
|
PerformDeviceDeletionPath = "/userapi/performDeviceDeletion"
|
||||||
|
|
||||||
QueryProfilePath = "/userapi/queryProfile"
|
QueryProfilePath = "/userapi/queryProfile"
|
||||||
QueryAccessTokenPath = "/userapi/queryAccessToken"
|
QueryAccessTokenPath = "/userapi/queryAccessToken"
|
||||||
|
@ -91,6 +92,18 @@ func (h *httpUserInternalAPI) PerformDeviceCreation(
|
||||||
return httputil.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
|
return httputil.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *httpUserInternalAPI) PerformDeviceDeletion(
|
||||||
|
ctx context.Context,
|
||||||
|
request *api.PerformDeviceDeletionRequest,
|
||||||
|
response *api.PerformDeviceDeletionResponse,
|
||||||
|
) error {
|
||||||
|
span, ctx := opentracing.StartSpanFromContext(ctx, "PerformDeviceDeletion")
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
|
apiURL := h.apiURL + PerformDeviceDeletionPath
|
||||||
|
return httputil.PostJSON(ctx, span, h.httpClient, apiURL, request, response)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *httpUserInternalAPI) QueryProfile(
|
func (h *httpUserInternalAPI) QueryProfile(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
request *api.QueryProfileRequest,
|
request *api.QueryProfileRequest,
|
||||||
|
|
|
@ -52,6 +52,19 @@ func AddRoutes(internalAPIMux *mux.Router, s api.UserInternalAPI) {
|
||||||
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
internalAPIMux.Handle(PerformDeviceDeletionPath,
|
||||||
|
httputil.MakeInternalAPI("performDeviceDeletion", func(req *http.Request) util.JSONResponse {
|
||||||
|
request := api.PerformDeviceDeletionRequest{}
|
||||||
|
response := api.PerformDeviceDeletionResponse{}
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
|
||||||
|
return util.MessageResponse(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
if err := s.PerformDeviceDeletion(req.Context(), &request, &response); err != nil {
|
||||||
|
return util.ErrorResponse(err)
|
||||||
|
}
|
||||||
|
return util.JSONResponse{Code: http.StatusOK, JSON: &response}
|
||||||
|
}),
|
||||||
|
)
|
||||||
internalAPIMux.Handle(QueryProfilePath,
|
internalAPIMux.Handle(QueryProfilePath,
|
||||||
httputil.MakeInternalAPI("queryProfile", func(req *http.Request) util.JSONResponse {
|
httputil.MakeInternalAPI("queryProfile", func(req *http.Request) util.JSONResponse {
|
||||||
request := api.QueryProfileRequest{}
|
request := api.QueryProfileRequest{}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package userapi
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/matrix-org/dendrite/internal/config"
|
"github.com/matrix-org/dendrite/internal/config"
|
||||||
|
keyapi "github.com/matrix-org/dendrite/keyserver/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/api"
|
"github.com/matrix-org/dendrite/userapi/api"
|
||||||
"github.com/matrix-org/dendrite/userapi/internal"
|
"github.com/matrix-org/dendrite/userapi/internal"
|
||||||
"github.com/matrix-org/dendrite/userapi/inthttp"
|
"github.com/matrix-org/dendrite/userapi/inthttp"
|
||||||
|
@ -34,12 +35,13 @@ func AddInternalRoutes(router *mux.Router, intAPI api.UserInternalAPI) {
|
||||||
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
// NewInternalAPI returns a concerete implementation of the internal API. Callers
|
||||||
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
// can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes.
|
||||||
func NewInternalAPI(accountDB accounts.Database, deviceDB devices.Database,
|
func NewInternalAPI(accountDB accounts.Database, deviceDB devices.Database,
|
||||||
serverName gomatrixserverlib.ServerName, appServices []config.ApplicationService) api.UserInternalAPI {
|
serverName gomatrixserverlib.ServerName, appServices []config.ApplicationService, keyAPI keyapi.KeyInternalAPI) api.UserInternalAPI {
|
||||||
|
|
||||||
return &internal.UserInternalAPI{
|
return &internal.UserInternalAPI{
|
||||||
AccountDB: accountDB,
|
AccountDB: accountDB,
|
||||||
DeviceDB: deviceDB,
|
DeviceDB: deviceDB,
|
||||||
ServerName: serverName,
|
ServerName: serverName,
|
||||||
AppServices: appServices,
|
AppServices: appServices,
|
||||||
|
KeyAPI: keyAPI,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func MustMakeInternalAPI(t *testing.T) (api.UserInternalAPI, accounts.Database,
|
||||||
t.Fatalf("failed to create device DB: %s", err)
|
t.Fatalf("failed to create device DB: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return userapi.NewInternalAPI(accountDB, deviceDB, serverName, nil), accountDB, deviceDB
|
return userapi.NewInternalAPI(accountDB, deviceDB, serverName, nil, nil), accountDB, deviceDB
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQueryProfile(t *testing.T) {
|
func TestQueryProfile(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue