mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-27 07:28:27 +00:00
Revert "Handle cases when AS is not masquerading"
This reverts commit 911deb88f4
.
This commit is contained in:
parent
1401a102fc
commit
cc9cae60cb
6 changed files with 91 additions and 33 deletions
|
@ -15,6 +15,7 @@
|
||||||
package appservice
|
package appservice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -27,7 +28,9 @@ import (
|
||||||
"github.com/matrix-org/dendrite/appservice/types"
|
"github.com/matrix-org/dendrite/appservice/types"
|
||||||
"github.com/matrix-org/dendrite/appservice/workers"
|
"github.com/matrix-org/dendrite/appservice/workers"
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
|
||||||
"github.com/matrix-org/dendrite/common/basecomponent"
|
"github.com/matrix-org/dendrite/common/basecomponent"
|
||||||
|
"github.com/matrix-org/dendrite/common/config"
|
||||||
"github.com/matrix-org/dendrite/common/transactions"
|
"github.com/matrix-org/dendrite/common/transactions"
|
||||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
@ -39,6 +42,7 @@ import (
|
||||||
func SetupAppServiceAPIComponent(
|
func SetupAppServiceAPIComponent(
|
||||||
base *basecomponent.BaseDendrite,
|
base *basecomponent.BaseDendrite,
|
||||||
accountsDB *accounts.Database,
|
accountsDB *accounts.Database,
|
||||||
|
deviceDB *devices.Database,
|
||||||
federation *gomatrixserverlib.FederationClient,
|
federation *gomatrixserverlib.FederationClient,
|
||||||
roomserverAliasAPI roomserverAPI.RoomserverAliasAPI,
|
roomserverAliasAPI roomserverAPI.RoomserverAliasAPI,
|
||||||
roomserverQueryAPI roomserverAPI.RoomserverQueryAPI,
|
roomserverQueryAPI roomserverAPI.RoomserverQueryAPI,
|
||||||
|
@ -50,11 +54,11 @@ func SetupAppServiceAPIComponent(
|
||||||
logrus.WithError(err).Panicf("failed to connect to appservice db")
|
logrus.WithError(err).Panicf("failed to connect to appservice db")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap application services in a type that relates the application service and
|
|
||||||
// a sync.Cond object that can be used to notify workers when there are new
|
|
||||||
// events to be sent out.
|
|
||||||
workerStates := make([]types.ApplicationServiceWorkerState, len(base.Cfg.Derived.ApplicationServices))
|
workerStates := make([]types.ApplicationServiceWorkerState, len(base.Cfg.Derived.ApplicationServices))
|
||||||
for _, appservice := range base.Cfg.Derived.ApplicationServices {
|
for _, appservice := range base.Cfg.Derived.ApplicationServices {
|
||||||
|
// Wrap each application service in a type that relates the application
|
||||||
|
// service and a sync.Cond object that can be used to notify workers when
|
||||||
|
// there are new events to be sent out.
|
||||||
eventCount := 0
|
eventCount := 0
|
||||||
|
|
||||||
m := sync.Mutex{}
|
m := sync.Mutex{}
|
||||||
|
@ -64,6 +68,15 @@ func SetupAppServiceAPIComponent(
|
||||||
EventsReady: &eventCount,
|
EventsReady: &eventCount,
|
||||||
}
|
}
|
||||||
workerStates = append(workerStates, ws)
|
workerStates = append(workerStates, ws)
|
||||||
|
|
||||||
|
// Generate a dummy account using the `sender_localpart` field for each
|
||||||
|
// application service. An application service will masquerade as this user if
|
||||||
|
// they do not provide a `user_id` during a request.
|
||||||
|
err := generateAppServiceAccount(accountsDB, deviceDB, appservice)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Panicf("unable to register appservice %s",
|
||||||
|
appservice.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a HTTP client that this component will use for all outbound and
|
// Create a HTTP client that this component will use for all outbound and
|
||||||
|
@ -100,3 +113,31 @@ func SetupAppServiceAPIComponent(
|
||||||
|
|
||||||
return &appserviceQueryAPI
|
return &appserviceQueryAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generateAppServiceAccounts creates a dummy account based off the
|
||||||
|
// `sender_localpart` field of each application service if it doesn't
|
||||||
|
// exist already
|
||||||
|
func generateAppServiceAccount(
|
||||||
|
accountsDB *accounts.Database,
|
||||||
|
deviceDB *devices.Database,
|
||||||
|
as config.ApplicationService,
|
||||||
|
) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// Create an account for the application service
|
||||||
|
acc, err := accountsDB.CreateAccount(ctx, as.SenderLocalpart, "", as.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if acc == nil {
|
||||||
|
// This account already exists
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a dummy device with a dummy token for the application service
|
||||||
|
_, err = deviceDB.CreateDevice(ctx, as.SenderLocalpart, nil, as.ASToken, &as.SenderLocalpart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package storage
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -174,9 +175,18 @@ func retrieveEvents(eventRows *sql.Rows) (events []gomatrixserverlib.Application
|
||||||
maxID = id
|
maxID = id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get age of the event from original timestamp and current time
|
// unsigned portion of a application service event
|
||||||
// TODO: Consider removing age as not many app services use it
|
unsigned := gomatrixserverlib.ApplicationServiceUnsigned{
|
||||||
event.Age = nowMilli - event.OriginServerTimestamp
|
// Age of the event from original timestamp and current time TODO: Consider
|
||||||
|
// removing age as not many app services use it
|
||||||
|
Age: nowMilli - event.OriginServerTimestamp,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsignedJSON, err := json.Marshal(unsigned)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, 0, err
|
||||||
|
}
|
||||||
|
event.Unsigned = gomatrixserverlib.RawJSON(unsignedJSON)
|
||||||
|
|
||||||
// TODO: Synapse does this. It's unnecessary to send Sender and UserID as the
|
// TODO: Synapse does this. It's unnecessary to send Sender and UserID as the
|
||||||
// same value. Do app services really require this? :)
|
// same value. Do app services really require this? :)
|
||||||
|
|
|
@ -217,8 +217,14 @@ func send(
|
||||||
transaction []byte,
|
transaction []byte,
|
||||||
) error {
|
) error {
|
||||||
// POST a transaction to our AS
|
// POST a transaction to our AS
|
||||||
address := fmt.Sprintf("%s/transactions/%d", appservice.URL, txnID)
|
address := fmt.Sprintf("%s/transactions/%d?access_token=%s", appservice.URL, txnID, appservice.HSToken)
|
||||||
resp, err := client.Post(address, "application/json", bytes.NewBuffer(transaction))
|
req, err := http.NewRequest(http.MethodPut, address, bytes.NewBuffer(transaction))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,14 +90,6 @@ func VerifyUserFromRequest(
|
||||||
}
|
}
|
||||||
|
|
||||||
if appService != nil {
|
if appService != nil {
|
||||||
// Create a dummy device for AS user
|
|
||||||
dev := authtypes.Device{
|
|
||||||
// Use AS dummy device ID
|
|
||||||
ID: types.AppServiceDeviceID,
|
|
||||||
// AS dummy device has AS's token.
|
|
||||||
AccessToken: token,
|
|
||||||
}
|
|
||||||
|
|
||||||
userID := req.URL.Query().Get("user_id")
|
userID := req.URL.Query().Get("user_id")
|
||||||
localpart, err := userutil.ParseUsernameParam(userID, nil)
|
localpart, err := userutil.ParseUsernameParam(userID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -107,25 +99,28 @@ func VerifyUserFromRequest(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if localpart != "" { // AS is masquerading as another user
|
// Verify that the user is registered
|
||||||
// Verify that the user is registered
|
account, err := data.AccountDB.GetAccountByLocalpart(req.Context(), localpart)
|
||||||
account, err := data.AccountDB.GetAccountByLocalpart(req.Context(), localpart)
|
|
||||||
// Verify that account exists & appServiceID matches
|
// Verify that account exists & appServiceID matches
|
||||||
if err == nil && account.AppServiceID == appService.ID {
|
if err == nil && account.AppServiceID == appService.ID {
|
||||||
// Set the userID of dummy device
|
// Create a dummy device for AS user
|
||||||
dev.UserID = userID
|
dev := authtypes.Device{
|
||||||
return &dev, nil
|
// Use AS dummy device ID
|
||||||
|
ID: types.AppServiceDeviceID,
|
||||||
|
// User the AS is masquerading as.
|
||||||
|
UserID: userID,
|
||||||
|
// AS dummy device has AS's token.
|
||||||
|
AccessToken: token,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &util.JSONResponse{
|
return &dev, nil
|
||||||
Code: http.StatusForbidden,
|
|
||||||
JSON: jsonerror.Forbidden("Application service has not registered this user"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AS is not masquerading as any user, so use AS's sender_localpart
|
return nil, &util.JSONResponse{
|
||||||
dev.UserID = appService.SenderLocalpart
|
Code: http.StatusForbidden,
|
||||||
return &dev, nil
|
JSON: jsonerror.Forbidden("Application service has not registered this user"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, &util.JSONResponse{
|
return nil, &util.JSONResponse{
|
||||||
|
|
|
@ -56,7 +56,7 @@ func main() {
|
||||||
|
|
||||||
alias, input, query := roomserver.SetupRoomServerComponent(base)
|
alias, input, query := roomserver.SetupRoomServerComponent(base)
|
||||||
asQuery := appservice.SetupAppServiceAPIComponent(
|
asQuery := appservice.SetupAppServiceAPIComponent(
|
||||||
base, accountDB, federation, alias, query, transactions.New(),
|
base, accountDB, deviceDB, federation, alias, query, transactions.New(),
|
||||||
)
|
)
|
||||||
|
|
||||||
clientapi.SetupClientAPIComponent(
|
clientapi.SetupClientAPIComponent(
|
||||||
|
|
|
@ -15,10 +15,16 @@
|
||||||
|
|
||||||
package gomatrixserverlib
|
package gomatrixserverlib
|
||||||
|
|
||||||
|
// ApplicationServiceUnsigned is the contents of the unsigned field of an
|
||||||
|
// ApplicationServiceEvent
|
||||||
|
type ApplicationServiceUnsigned struct {
|
||||||
|
Age int64 `json:"age,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ApplicationServiceEvent is an event format that is sent off to an
|
// ApplicationServiceEvent is an event format that is sent off to an
|
||||||
// application service as part of a transaction.
|
// application service as part of a transaction.
|
||||||
type ApplicationServiceEvent struct {
|
type ApplicationServiceEvent struct {
|
||||||
Age int64 `json:"age,omitempty"`
|
Unsigned RawJSON `json:"unsigned,omitempty"`
|
||||||
Content RawJSON `json:"content,omitempty"`
|
Content RawJSON `json:"content,omitempty"`
|
||||||
EventID string `json:"event_id,omitempty"`
|
EventID string `json:"event_id,omitempty"`
|
||||||
OriginServerTimestamp int64 `json:"origin_server_ts,omitempty"`
|
OriginServerTimestamp int64 `json:"origin_server_ts,omitempty"`
|
||||||
|
|
Loading…
Reference in a new issue