Revert "Handle cases when AS is not masquerading"

This reverts commit 911deb88f4.
This commit is contained in:
Andrew Morgan 2018-06-12 16:41:32 +01:00
parent 1401a102fc
commit cc9cae60cb
6 changed files with 91 additions and 33 deletions

View file

@ -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
}

View file

@ -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? :)

View file

@ -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
} }

View file

@ -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{

View file

@ -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(

View file

@ -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"`