implement AS timestamp massaging (#542)

main
Andrew Morgan 2018-07-17 08:45:30 -07:00 committed by GitHub
parent 99005d6a91
commit a56752f3f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 82 additions and 50 deletions

View File

@ -68,7 +68,7 @@ func VerifyUserFromRequest(
// Try to find local user from device database // Try to find local user from device database
dev, devErr := verifyAccessToken(req, data.DeviceDB) dev, devErr := verifyAccessToken(req, data.DeviceDB)
if devErr == nil { if devErr == nil {
return dev, nil return dev, verifyUserParameters(req)
} }
// Try to find the Application Service user // Try to find the Application Service user
@ -134,6 +134,18 @@ func VerifyUserFromRequest(
} }
} }
// verifyUserParameters ensures that a request coming from a regular user is not
// using any query parameters reserved for an application service
func verifyUserParameters(req *http.Request) *util.JSONResponse {
if req.URL.Query().Get("ts") != "" {
return &util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.Unknown("parameter 'ts' not allowed without valid parameter 'access_token'"),
}
}
return nil
}
// verifyAccessToken verifies that an access token was supplied in the given HTTP request // verifyAccessToken verifies that an access token was supplied in the given HTTP request
// and returns the device it corresponds to. Returns resErr (an error response which can be // and returns the device it corresponds to. Returns resErr (an error response which can be
// sent to the client) if the token is invalid or there was a problem querying the database. // sent to the client) if the token is invalid or there was a problem querying the database.

View File

@ -18,7 +18,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
"time"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
@ -113,7 +112,8 @@ type fledglingEvent struct {
} }
// CreateRoom implements /createRoom // CreateRoom implements /createRoom
func CreateRoom(req *http.Request, device *authtypes.Device, func CreateRoom(
req *http.Request, device *authtypes.Device,
cfg config.Dendrite, producer *producers.RoomserverProducer, cfg config.Dendrite, producer *producers.RoomserverProducer,
accountDB *accounts.Database, aliasAPI api.RoomserverAliasAPI, accountDB *accounts.Database, aliasAPI api.RoomserverAliasAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -125,7 +125,8 @@ func CreateRoom(req *http.Request, device *authtypes.Device,
// createRoom implements /createRoom // createRoom implements /createRoom
// nolint: gocyclo // nolint: gocyclo
func createRoom(req *http.Request, device *authtypes.Device, func createRoom(
req *http.Request, device *authtypes.Device,
cfg config.Dendrite, roomID string, producer *producers.RoomserverProducer, cfg config.Dendrite, roomID string, producer *producers.RoomserverProducer,
accountDB *accounts.Database, aliasAPI api.RoomserverAliasAPI, accountDB *accounts.Database, aliasAPI api.RoomserverAliasAPI,
) util.JSONResponse { ) util.JSONResponse {
@ -248,7 +249,7 @@ func createRoom(req *http.Request, device *authtypes.Device,
builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()} builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
} }
var ev *gomatrixserverlib.Event var ev *gomatrixserverlib.Event
ev, err = buildEvent(&builder, &authEvents, cfg) ev, err = buildEvent(req, &builder, &authEvents, cfg)
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }
@ -307,9 +308,12 @@ func createRoom(req *http.Request, device *authtypes.Device,
} }
// buildEvent fills out auth_events for the builder then builds the event // buildEvent fills out auth_events for the builder then builds the event
func buildEvent(builder *gomatrixserverlib.EventBuilder, func buildEvent(
req *http.Request,
builder *gomatrixserverlib.EventBuilder,
provider gomatrixserverlib.AuthEventProvider, provider gomatrixserverlib.AuthEventProvider,
cfg config.Dendrite) (*gomatrixserverlib.Event, error) { cfg config.Dendrite,
) (*gomatrixserverlib.Event, error) {
eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder) eventsNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(builder)
if err != nil { if err != nil {
@ -321,8 +325,8 @@ func buildEvent(builder *gomatrixserverlib.EventBuilder,
} }
builder.AuthEvents = refs builder.AuthEvents = refs
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName) eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
now := time.Now() eventTime := common.ParseTSParam(req)
event, err := builder.Build(eventID, now, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) event, err := builder.Build(eventID, eventTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot build event %s : Builder failed to build. %s", builder.Type, err) return nil, fmt.Errorf("cannot build event %s : Builder failed to build. %s", builder.Type, err)
} }

View File

@ -18,7 +18,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
"time"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
@ -215,7 +214,7 @@ func (r joinRoomReq) joinRoomUsingServers(
} }
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
event, err := common.BuildEvent(r.req.Context(), &eb, r.cfg, r.queryAPI, &queryRes) event, err := common.BuildEvent(r.req, &eb, r.cfg, r.queryAPI, &queryRes)
if err == nil { if err == nil {
if _, err = r.producer.SendEvents(r.req.Context(), []gomatrixserverlib.Event{*event}, r.cfg.Matrix.ServerName, nil); err != nil { if _, err = r.producer.SendEvents(r.req.Context(), []gomatrixserverlib.Event{*event}, r.cfg.Matrix.ServerName, nil); err != nil {
return httputil.LogThenError(r.req, err) return httputil.LogThenError(r.req, err)
@ -285,10 +284,10 @@ func (r joinRoomReq) joinRoomUsingServer(roomID string, server gomatrixserverlib
return nil, err return nil, err
} }
now := time.Now()
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), r.cfg.Matrix.ServerName) eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), r.cfg.Matrix.ServerName)
eventTime := common.ParseTSParam(r.req)
event, err := respMakeJoin.JoinEvent.Build( event, err := respMakeJoin.JoinEvent.Build(
eventID, now, r.cfg.Matrix.ServerName, r.cfg.Matrix.KeyID, r.cfg.Matrix.PrivateKey, eventID, eventTime, r.cfg.Matrix.ServerName, r.cfg.Matrix.KeyID, r.cfg.Matrix.PrivateKey,
) )
if err != nil { if err != nil {
res := httputil.LogThenError(r.req, err) res := httputil.LogThenError(r.req, err)

View File

@ -48,8 +48,7 @@ func SendMembership(
} }
inviteStored, err := threepid.CheckAndProcessInvite( inviteStored, err := threepid.CheckAndProcessInvite(
req.Context(), req, device, &body, cfg, queryAPI, accountDB, producer, membership, roomID,
device, &body, cfg, queryAPI, accountDB, producer, membership, roomID,
) )
if err == threepid.ErrMissingParameter { if err == threepid.ErrMissingParameter {
return util.JSONResponse{ return util.JSONResponse{
@ -81,7 +80,7 @@ func SendMembership(
} }
event, err := buildMembershipEvent( event, err := buildMembershipEvent(
req.Context(), body, accountDB, device, membership, roomID, cfg, queryAPI, req, body, accountDB, device, membership, roomID, cfg, queryAPI,
) )
if err == errMissingUserID { if err == errMissingUserID {
return util.JSONResponse{ return util.JSONResponse{
@ -110,7 +109,7 @@ func SendMembership(
} }
func buildMembershipEvent( func buildMembershipEvent(
ctx context.Context, req *http.Request,
body threepid.MembershipRequest, accountDB *accounts.Database, body threepid.MembershipRequest, accountDB *accounts.Database,
device *authtypes.Device, membership string, roomID string, cfg config.Dendrite, device *authtypes.Device, membership string, roomID string, cfg config.Dendrite,
queryAPI api.RoomserverQueryAPI, queryAPI api.RoomserverQueryAPI,
@ -120,7 +119,7 @@ func buildMembershipEvent(
return nil, err return nil, err
} }
profile, err := loadProfile(ctx, stateKey, cfg, accountDB) profile, err := loadProfile(req.Context(), stateKey, cfg, accountDB)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -148,7 +147,7 @@ func buildMembershipEvent(
return nil, err return nil, err
} }
return common.BuildEvent(ctx, &builder, cfg, queryAPI, nil) return common.BuildEvent(req, &builder, cfg, queryAPI, nil)
} }
// loadProfile lookups the profile of a given user from the database and returns // loadProfile lookups the profile of a given user from the database and returns

View File

@ -15,7 +15,6 @@
package routing package routing
import ( import (
"context"
"database/sql" "database/sql"
"net/http" "net/http"
@ -151,7 +150,7 @@ func SetAvatarURL(
AvatarURL: r.AvatarURL, AvatarURL: r.AvatarURL,
} }
events, err := buildMembershipEvents(req.Context(), memberships, newProfile, userID, cfg, queryAPI) events, err := buildMembershipEvents(req, memberships, newProfile, userID, cfg, queryAPI)
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }
@ -239,7 +238,7 @@ func SetDisplayName(
AvatarURL: oldProfile.AvatarURL, AvatarURL: oldProfile.AvatarURL,
} }
events, err := buildMembershipEvents(req.Context(), memberships, newProfile, userID, cfg, queryAPI) events, err := buildMembershipEvents(req, memberships, newProfile, userID, cfg, queryAPI)
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
} }
@ -259,7 +258,7 @@ func SetDisplayName(
} }
func buildMembershipEvents( func buildMembershipEvents(
ctx context.Context, req *http.Request,
memberships []authtypes.Membership, memberships []authtypes.Membership,
newProfile authtypes.Profile, userID string, cfg *config.Dendrite, newProfile authtypes.Profile, userID string, cfg *config.Dendrite,
queryAPI api.RoomserverQueryAPI, queryAPI api.RoomserverQueryAPI,
@ -285,7 +284,7 @@ func buildMembershipEvents(
return nil, err return nil, err
} }
event, err := common.BuildEvent(ctx, &builder, *cfg, queryAPI, nil) event, err := common.BuildEvent(req, &builder, *cfg, queryAPI, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -76,7 +76,7 @@ func SendEvent(
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
e, err := common.BuildEvent(req.Context(), &builder, cfg, queryAPI, &queryRes) e, err := common.BuildEvent(req, &builder, cfg, queryAPI, &queryRes)
if err == common.ErrRoomNoExists { if err == common.ErrRoomNoExists {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,

View File

@ -85,7 +85,7 @@ var (
// fills the Matrix ID in the request body so a normal invite membership event // fills the Matrix ID in the request body so a normal invite membership event
// can be emitted. // can be emitted.
func CheckAndProcessInvite( func CheckAndProcessInvite(
ctx context.Context, req *http.Request,
device *authtypes.Device, body *MembershipRequest, cfg config.Dendrite, device *authtypes.Device, body *MembershipRequest, cfg config.Dendrite,
queryAPI api.RoomserverQueryAPI, db *accounts.Database, queryAPI api.RoomserverQueryAPI, db *accounts.Database,
producer *producers.RoomserverProducer, membership string, roomID string, producer *producers.RoomserverProducer, membership string, roomID string,
@ -101,7 +101,7 @@ func CheckAndProcessInvite(
return return
} }
lookupRes, storeInviteRes, err := queryIDServer(ctx, db, cfg, device, body, roomID) lookupRes, storeInviteRes, err := queryIDServer(req.Context(), db, cfg, device, body, roomID)
if err != nil { if err != nil {
return return
} }
@ -110,7 +110,7 @@ func CheckAndProcessInvite(
// No Matrix ID could be found for this 3PID, meaning that a // No Matrix ID could be found for this 3PID, meaning that a
// "m.room.third_party_invite" have to be emitted from the data in // "m.room.third_party_invite" have to be emitted from the data in
// storeInviteRes. // storeInviteRes.
err = emit3PIDInviteEvent(ctx, body, storeInviteRes, device, roomID, cfg, queryAPI, producer) err = emit3PIDInviteEvent(req, body, storeInviteRes, device, roomID, cfg, queryAPI, producer)
inviteStoredOnIDServer = err == nil inviteStoredOnIDServer = err == nil
return return
@ -325,7 +325,7 @@ func checkIDServerSignatures(
// emit3PIDInviteEvent builds and sends a "m.room.third_party_invite" event. // emit3PIDInviteEvent builds and sends a "m.room.third_party_invite" event.
// Returns an error if something failed in the process. // Returns an error if something failed in the process.
func emit3PIDInviteEvent( func emit3PIDInviteEvent(
ctx context.Context, req *http.Request,
body *MembershipRequest, res *idServerStoreInviteResponse, body *MembershipRequest, res *idServerStoreInviteResponse,
device *authtypes.Device, roomID string, cfg config.Dendrite, device *authtypes.Device, roomID string, cfg config.Dendrite,
queryAPI api.RoomserverQueryAPI, producer *producers.RoomserverProducer, queryAPI api.RoomserverQueryAPI, producer *producers.RoomserverProducer,
@ -350,11 +350,11 @@ func emit3PIDInviteEvent(
} }
var queryRes *api.QueryLatestEventsAndStateResponse var queryRes *api.QueryLatestEventsAndStateResponse
event, err := common.BuildEvent(ctx, builder, cfg, queryAPI, queryRes) event, err := common.BuildEvent(req, builder, cfg, queryAPI, queryRes)
if err != nil { if err != nil {
return err return err
} }
_, err = producer.SendEvents(ctx, []gomatrixserverlib.Event{*event}, cfg.Matrix.ServerName, nil) _, err = producer.SendEvents(req.Context(), []gomatrixserverlib.Event{*event}, cfg.Matrix.ServerName, nil)
return err return err
} }

View File

@ -18,6 +18,8 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"net/http"
"strconv"
"time" "time"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
@ -38,18 +40,18 @@ var ErrRoomNoExists = errors.New("Room does not exist")
// the room doesn't exist // the room doesn't exist
// Returns an error if something else went wrong // Returns an error if something else went wrong
func BuildEvent( func BuildEvent(
ctx context.Context, req *http.Request,
builder *gomatrixserverlib.EventBuilder, cfg config.Dendrite, builder *gomatrixserverlib.EventBuilder, cfg config.Dendrite,
queryAPI api.RoomserverQueryAPI, queryRes *api.QueryLatestEventsAndStateResponse, queryAPI api.RoomserverQueryAPI, queryRes *api.QueryLatestEventsAndStateResponse,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {
err := AddPrevEventsToEvent(ctx, builder, queryAPI, queryRes) err := AddPrevEventsToEvent(req.Context(), builder, queryAPI, queryRes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName) eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
now := time.Now() eventTime := ParseTSParam(req)
event, err := builder.Build(eventID, now, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) event, err := builder.Build(eventID, eventTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -57,6 +59,25 @@ func BuildEvent(
return &event, nil return &event, nil
} }
// ParseTSParam takes a req from an application service and parses a Time object
// from the req if it exists in the query parameters. If it doesn't exist, the
// current time is returned.
func ParseTSParam(req *http.Request) time.Time {
// Use the ts parameter's value for event time if present
tsStr := req.URL.Query().Get("ts")
if tsStr == "" {
return time.Now()
}
// The parameter exists, parse into a Time object
ts, err := strconv.ParseInt(tsStr, 10, 64)
if err != nil {
return time.Unix(ts/1000, 0)
}
return time.Unix(ts/1000, 0)
}
// AddPrevEventsToEvent fills out the prev_events and auth_events fields in builder // AddPrevEventsToEvent fills out the prev_events and auth_events fields in builder
func AddPrevEventsToEvent( func AddPrevEventsToEvent(
ctx context.Context, ctx context.Context,

View File

@ -31,7 +31,6 @@ import (
// MakeJoin implements the /make_join API // MakeJoin implements the /make_join API
func MakeJoin( func MakeJoin(
ctx context.Context,
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
cfg config.Dendrite, cfg config.Dendrite,
@ -65,7 +64,7 @@ func MakeJoin(
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
event, err := common.BuildEvent(ctx, &builder, cfg, query, &queryRes) event, err := common.BuildEvent(httpReq, &builder, cfg, query, &queryRes)
if err == common.ErrRoomNoExists { if err == common.ErrRoomNoExists {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,

View File

@ -61,7 +61,7 @@ func MakeLeave(
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
event, err := common.BuildEvent(httpReq.Context(), &builder, cfg, query, &queryRes) event, err := common.BuildEvent(httpReq, &builder, cfg, query, &queryRes)
if err == common.ErrRoomNoExists { if err == common.ErrRoomNoExists {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,

View File

@ -165,7 +165,7 @@ func Setup(
roomID := vars["roomID"] roomID := vars["roomID"]
userID := vars["userID"] userID := vars["userID"]
return MakeJoin( return MakeJoin(
httpReq.Context(), httpReq, request, cfg, query, roomID, userID, httpReq, request, cfg, query, roomID, userID,
) )
}, },
)).Methods(http.MethodGet) )).Methods(http.MethodGet)

View File

@ -20,7 +20,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"time"
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
"github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/httputil"
@ -70,7 +69,7 @@ func CreateInvitesFrom3PIDInvites(
evs := []gomatrixserverlib.Event{} evs := []gomatrixserverlib.Event{}
for _, inv := range body.Invites { for _, inv := range body.Invites {
event, err := createInviteFrom3PIDInvite( event, err := createInviteFrom3PIDInvite(
req.Context(), queryAPI, cfg, inv, federation, accountDB, req, queryAPI, cfg, inv, federation, accountDB,
) )
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(req, err)
@ -135,7 +134,7 @@ func ExchangeThirdPartyInvite(
} }
// Auth and build the event from what the remote server sent us // Auth and build the event from what the remote server sent us
event, err := buildMembershipEvent(httpReq.Context(), &builder, queryAPI, cfg) event, err := buildMembershipEvent(httpReq, &builder, queryAPI, cfg)
if err == errNotInRoom { if err == errNotInRoom {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
@ -170,7 +169,7 @@ func ExchangeThirdPartyInvite(
// Returns an error if there was a problem building the event or fetching the // Returns an error if there was a problem building the event or fetching the
// necessary data to do so. // necessary data to do so.
func createInviteFrom3PIDInvite( func createInviteFrom3PIDInvite(
ctx context.Context, queryAPI api.RoomserverQueryAPI, cfg config.Dendrite, req *http.Request, queryAPI api.RoomserverQueryAPI, cfg config.Dendrite,
inv invite, federation *gomatrixserverlib.FederationClient, inv invite, federation *gomatrixserverlib.FederationClient,
accountDB *accounts.Database, accountDB *accounts.Database,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {
@ -191,7 +190,7 @@ func createInviteFrom3PIDInvite(
StateKey: &inv.MXID, StateKey: &inv.MXID,
} }
profile, err := accountDB.GetProfileByLocalpart(ctx, localpart) profile, err := accountDB.GetProfileByLocalpart(req.Context(), localpart)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -209,9 +208,9 @@ func createInviteFrom3PIDInvite(
return nil, err return nil, err
} }
event, err := buildMembershipEvent(ctx, builder, queryAPI, cfg) event, err := buildMembershipEvent(req, builder, queryAPI, cfg)
if err == errNotInRoom { if err == errNotInRoom {
return nil, sendToRemoteServer(ctx, inv, federation, cfg, *builder) return nil, sendToRemoteServer(req.Context(), inv, federation, cfg, *builder)
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -226,7 +225,7 @@ func createInviteFrom3PIDInvite(
// Returns errNotInRoom if the server is not in the room the invite is for. // Returns errNotInRoom if the server is not in the room the invite is for.
// Returns an error if something failed during the process. // Returns an error if something failed during the process.
func buildMembershipEvent( func buildMembershipEvent(
ctx context.Context, req *http.Request,
builder *gomatrixserverlib.EventBuilder, queryAPI api.RoomserverQueryAPI, builder *gomatrixserverlib.EventBuilder, queryAPI api.RoomserverQueryAPI,
cfg config.Dendrite, cfg config.Dendrite,
) (*gomatrixserverlib.Event, error) { ) (*gomatrixserverlib.Event, error) {
@ -241,7 +240,7 @@ func buildMembershipEvent(
StateToFetch: eventsNeeded.Tuples(), StateToFetch: eventsNeeded.Tuples(),
} }
var queryRes api.QueryLatestEventsAndStateResponse var queryRes api.QueryLatestEventsAndStateResponse
if err = queryAPI.QueryLatestEventsAndState(ctx, &queryReq, &queryRes); err != nil { if err = queryAPI.QueryLatestEventsAndState(req.Context(), &queryReq, &queryRes); err != nil {
return nil, err return nil, err
} }
@ -274,8 +273,8 @@ func buildMembershipEvent(
builder.AuthEvents = refs builder.AuthEvents = refs
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName) eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), cfg.Matrix.ServerName)
now := time.Now() eventTime := common.ParseTSParam(req)
event, err := builder.Build(eventID, now, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey) event, err := builder.Build(eventID, eventTime, cfg.Matrix.ServerName, cfg.Matrix.KeyID, cfg.Matrix.PrivateKey)
return &event, err return &event, err
} }