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
import (
"context"
"net/http"
"sync"
"time"
@ -27,7 +28,9 @@ import (
"github.com/matrix-org/dendrite/appservice/types"
"github.com/matrix-org/dendrite/appservice/workers"
"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/config"
"github.com/matrix-org/dendrite/common/transactions"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib"
@ -39,6 +42,7 @@ import (
func SetupAppServiceAPIComponent(
base *basecomponent.BaseDendrite,
accountsDB *accounts.Database,
deviceDB *devices.Database,
federation *gomatrixserverlib.FederationClient,
roomserverAliasAPI roomserverAPI.RoomserverAliasAPI,
roomserverQueryAPI roomserverAPI.RoomserverQueryAPI,
@ -50,11 +54,11 @@ func SetupAppServiceAPIComponent(
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))
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
m := sync.Mutex{}
@ -64,6 +68,15 @@ func SetupAppServiceAPIComponent(
EventsReady: &eventCount,
}
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
@ -100,3 +113,31 @@ func SetupAppServiceAPIComponent(
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 (
"context"
"database/sql"
"encoding/json"
"fmt"
"time"
@ -174,9 +175,18 @@ func retrieveEvents(eventRows *sql.Rows) (events []gomatrixserverlib.Application
maxID = id
}
// Get age of the event from original timestamp and current time
// TODO: Consider removing age as not many app services use it
event.Age = nowMilli - event.OriginServerTimestamp
// unsigned portion of a application service event
unsigned := gomatrixserverlib.ApplicationServiceUnsigned{
// 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
// same value. Do app services really require this? :)

View file

@ -217,8 +217,14 @@ func send(
transaction []byte,
) error {
// POST a transaction to our AS
address := fmt.Sprintf("%s/transactions/%d", appservice.URL, txnID)
resp, err := client.Post(address, "application/json", bytes.NewBuffer(transaction))
address := fmt.Sprintf("%s/transactions/%d?access_token=%s", appservice.URL, txnID, appservice.HSToken)
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 {
return err
}

View file

@ -90,14 +90,6 @@ func VerifyUserFromRequest(
}
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")
localpart, err := userutil.ParseUsernameParam(userID, nil)
if err != nil {
@ -107,25 +99,28 @@ func VerifyUserFromRequest(
}
}
if localpart != "" { // AS is masquerading as another user
// Verify that the user is registered
account, err := data.AccountDB.GetAccountByLocalpart(req.Context(), localpart)
// Verify that account exists & appServiceID matches
if err == nil && account.AppServiceID == appService.ID {
// Set the userID of dummy device
dev.UserID = userID
return &dev, nil
// Verify that the user is registered
account, err := data.AccountDB.GetAccountByLocalpart(req.Context(), localpart)
// Verify that account exists & appServiceID matches
if err == nil && account.AppServiceID == appService.ID {
// Create a dummy device for AS user
dev := authtypes.Device{
// 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{
Code: http.StatusForbidden,
JSON: jsonerror.Forbidden("Application service has not registered this user"),
}
return &dev, nil
}
// AS is not masquerading as any user, so use AS's sender_localpart
dev.UserID = appService.SenderLocalpart
return &dev, nil
return nil, &util.JSONResponse{
Code: http.StatusForbidden,
JSON: jsonerror.Forbidden("Application service has not registered this user"),
}
}
return nil, &util.JSONResponse{

View file

@ -56,7 +56,7 @@ func main() {
alias, input, query := roomserver.SetupRoomServerComponent(base)
asQuery := appservice.SetupAppServiceAPIComponent(
base, accountDB, federation, alias, query, transactions.New(),
base, accountDB, deviceDB, federation, alias, query, transactions.New(),
)
clientapi.SetupClientAPIComponent(

View file

@ -15,10 +15,16 @@
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
// application service as part of a transaction.
type ApplicationServiceEvent struct {
Age int64 `json:"age,omitempty"`
Unsigned RawJSON `json:"unsigned,omitempty"`
Content RawJSON `json:"content,omitempty"`
EventID string `json:"event_id,omitempty"`
OriginServerTimestamp int64 `json:"origin_server_ts,omitempty"`