diff --git a/go.mod b/go.mod index 14246a9..13323db 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/nxshock/signaller +module github.com/signaller-matrix/signaller go 1.12 diff --git a/internal/backend.go b/internal/backend.go index 86a5431..3861e7f 100644 --- a/internal/backend.go +++ b/internal/backend.go @@ -2,6 +2,7 @@ package internal import ( "github.com/signaller-matrix/signaller/internal/models" + "github.com/signaller-matrix/signaller/internal/models/common" "github.com/signaller-matrix/signaller/internal/models/createroom" "github.com/signaller-matrix/signaller/internal/models/devices" "github.com/signaller-matrix/signaller/internal/models/rooms" @@ -50,4 +51,6 @@ type User interface { LogoutAll() JoinRoom(Room) models.ApiError Invite(Room, User) models.ApiError + AddFilter(filterID string, filter common.Filter) + GetFilterByID(filterID string) *common.Filter } diff --git a/internal/backends/memory/backend.go b/internal/backends/memory/backend.go index 35c059c..913d41e 100644 --- a/internal/backends/memory/backend.go +++ b/internal/backends/memory/backend.go @@ -73,7 +73,7 @@ func (backend *Backend) Login(username, password, device string) (user internal. return nil, "", models.NewError(models.M_FORBIDDEN, "wrong password") } - token = newToken(defaultTokenSize) + token = internal.RandomString(defaultTokenSize) backend.data[username].(*User).Tokens[token] = Token{Device: device} diff --git a/internal/backends/memory/user.go b/internal/backends/memory/user.go index 4a2e90f..61860f8 100644 --- a/internal/backends/memory/user.go +++ b/internal/backends/memory/user.go @@ -6,6 +6,7 @@ import ( "github.com/signaller-matrix/signaller/internal" "github.com/signaller-matrix/signaller/internal/models" + "github.com/signaller-matrix/signaller/internal/models/common" "github.com/signaller-matrix/signaller/internal/models/createroom" "github.com/signaller-matrix/signaller/internal/models/devices" "github.com/signaller-matrix/signaller/internal/models/rooms" @@ -15,6 +16,7 @@ type User struct { name string password string Tokens map[string]Token + filters map[string]common.Filter backend *Backend @@ -48,7 +50,7 @@ func (user *User) CreateRoom(request createroom.Request) (internal.Room, models. events = append(events, RoomEvent{ Content: nil, Type: rooms.Create, - EventID: newToken(eventIDSize), + EventID: internal.RandomString(eventIDSize), Sender: user, OriginServerTS: t}) @@ -58,7 +60,7 @@ func (user *User) CreateRoom(request createroom.Request) (internal.Room, models. events = append(events, RoomEvent{ Content: []byte(request.Visibility), // TODO: check visibility vs join rules Type: rooms.JoinRules, - EventID: newToken(eventIDSize), + EventID: internal.RandomString(eventIDSize), Sender: user, OriginServerTS: t}) @@ -67,7 +69,7 @@ func (user *User) CreateRoom(request createroom.Request) (internal.Room, models. events = append(events, RoomEvent{ Content: nil, // TODO: add Type: rooms.Name, - EventID: newToken(eventIDSize), + EventID: internal.RandomString(eventIDSize), Sender: user, OriginServerTS: t}) } @@ -77,13 +79,13 @@ func (user *User) CreateRoom(request createroom.Request) (internal.Room, models. events = append(events, RoomEvent{ Content: nil, // TODO: add Type: rooms.CanonicalAlias, - EventID: newToken(eventIDSize), + EventID: internal.RandomString(eventIDSize), Sender: user, OriginServerTS: t}) } room := &Room{ - id: newToken(groupIDSize), + id: internal.RandomString(groupIDSize), aliasName: request.RoomAliasName, name: request.Name, topic: request.Topic, @@ -190,7 +192,7 @@ func (user *User) SendMessage(room internal.Room, text string) models.ApiError { room.(*Room).events = append(room.(*Room).events, RoomEvent{ Content: nil, Type: rooms.Message, - EventID: newToken(defaultTokenSize), + EventID: internal.RandomString(defaultTokenSize), Sender: user, OriginServerTS: time.Now(), Room: room}) @@ -275,3 +277,14 @@ func (user *User) JoinRoom(room internal.Room) models.ApiError { return nil } + +func (user *User) AddFilter(filterID string, filter common.Filter) { + user.filters[filterID] = filter +} + +func (user *User) GetFilterByID(filterID string) *common.Filter { + if val, ok := user.filters[filterID]; ok { + return &val + } + return nil +} diff --git a/internal/handlers.go b/internal/handlers.go index a5884ca..a79dc8a 100644 --- a/internal/handlers.go +++ b/internal/handlers.go @@ -323,6 +323,61 @@ func CapabilitiesHandler(w http.ResponseWriter, r *http.Request) { sendJsonResponse(w, http.StatusOK, response) } +func AddFilterHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + errorResponse(w, models.M_UNKNOWN, http.StatusBadRequest, "wrong method: "+r.Method) + return + } + + token := getTokenFromResponse(r) + if token == "" { + errorResponse(w, models.M_FORBIDDEN, http.StatusForbidden, "") + return + } + + user := currServer.Backend.GetUserByToken(token) + if user == nil { + errorResponse(w, models.M_UNKNOWN_TOKEN, http.StatusBadRequest, "") + return + } + + var request common.Filter + getRequest(r, &request) + + filterID := RandomString(12) + user.AddFilter(filterID, request) + + sendJsonResponse(w, http.StatusOK, map[string]interface{}{ + "filter_id": filterID, + }) +} + +func GetFilterHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + errorResponse(w, models.M_UNKNOWN, http.StatusBadRequest, "wrong method: "+r.Method) + return + } + + token := getTokenFromResponse(r) + if token == "" { + errorResponse(w, models.M_FORBIDDEN, http.StatusForbidden, "") + return + } + + user := currServer.Backend.GetUserByToken(token) + if user == nil { + errorResponse(w, models.M_UNKNOWN_TOKEN, http.StatusBadRequest, "") + return + } + + filter := user.GetFilterByID(mux.Vars(r)["filterID"]) + if filter == nil { + errorResponse(w, models.M_INVALID_PARAM, http.StatusNotFound, "") + } + + sendJsonResponse(w, http.StatusOK, filter) +} + // https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-devices func DevicesHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { diff --git a/internal/models/common/filter.go b/internal/models/common/filter.go new file mode 100644 index 0000000..029a292 --- /dev/null +++ b/internal/models/common/filter.go @@ -0,0 +1,27 @@ +package common + +type Filter struct { + Room struct { + State struct { + Types []string `json:"types"` + NotRooms []string `json:"not_rooms"` + } `json:"state"` + Timeline struct { + Limit int `json:"limit"` + Types []string `json:"types"` + NotRooms []string `json:"not_rooms"` + NotSenders []string `json:"not_senders"` + } `json:"timeline"` + Ephemeral struct { + Types []string `json:"types"` + NotRooms []string `json:"not_rooms"` + NotSenders []string `json:"not_senders"` + } `json:"ephemeral"` + } `json:"room"` + Presence struct { + Types []string `json:"types"` + NotSenders []string `json:"not_senders"` + } `json:"presence"` + EventFormat string `json:"event_format"` + EventFields []string `json:"event_fields"` +} diff --git a/internal/backends/memory/tokens.go b/internal/random_provider.go similarity index 54% rename from internal/backends/memory/tokens.go rename to internal/random_provider.go index 7714b35..284f006 100644 --- a/internal/backends/memory/tokens.go +++ b/internal/random_provider.go @@ -1,12 +1,12 @@ -package memory +package internal import ( "crypto/rand" "fmt" ) -// newToken returns new generated token with specified length -func newToken(size int) string { +// RandomString returns new generated token with specified length +func RandomString(size int) string { b := make([]byte, size) rand.Read(b) // TODO: check may be can be error diff --git a/internal/server.go b/internal/server.go index 2efbefa..4f04122 100644 --- a/internal/server.go +++ b/internal/server.go @@ -40,6 +40,9 @@ func NewServer(port int) (*Server, error) { router.HandleFunc("/_matrix/client/r0/rooms/{roomId}/leave", leaveRoomHandler) router.HandleFunc("/_matrix/client/r0/register/available", registerAvailableHandler) router.HandleFunc("/_matrix/client/r0/publicRooms", publicRoomsHandler) + router.HandleFunc("/_matrix/client/r0/user/{userId}/filter/{filterId}", GetFilterHandler).Methods("GET") + router.HandleFunc("/_matrix/client/r0/user/{userId}/filter", AddFilterHandler).Methods("POST") + router.HandleFunc("/", RootHandler) if port <= 0 || port > 65535 {