diff --git a/STATUS.md b/STATUS.md index 1f1cf65..20ccb0d 100644 --- a/STATUS.md +++ b/STATUS.md @@ -6,8 +6,9 @@ Implemented from [Client-Server API](https://matrix.org/docs/spec/client_server/ - [x] [5.4.2 POST /_matrix/client/r0/login](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-login) - [x] [5.4.3 POST /_matrix/client/r0/logout](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-logout) - [x] [5.4.4 POST /_matrix/client/r0/logout/all](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-logout-all) +- [x] [5.5.1 POST /_matrix/client/r0/register](https://matrix.org/docs/spec/client_server/r0.5.0#post-matrix-client-r0-register) - [x] [5.5.4 POST /_matrix/client/r0/account/password](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-account-password) - [x] [5.7.1 GET /_matrix/client/r0/account/whoami](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-account-whoami) - [x] [6.1 GET /_matrix/client/r0/capabilities](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-capabilities) - [x] [10.4.1 GET /_matrix/client/r0/joined_rooms](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-joined-rooms) -- [x] [5.5.1 POST /_matrix/client/r0/register](https://matrix.org/docs/spec/client_server/r0.5.0#post-matrix-client-r0-register) \ No newline at end of file +- [x] [13.10.1.1 GET /_matrix/client/r0/devices](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-devices) diff --git a/internal/backend.go b/internal/backend.go index 49393ea..843c336 100644 --- a/internal/backend.go +++ b/internal/backend.go @@ -3,6 +3,7 @@ package internal import ( "github.com/nxshock/signaller/internal/models" "github.com/nxshock/signaller/internal/models/createroom" + "github.com/nxshock/signaller/internal/models/devices" "github.com/nxshock/signaller/internal/models/rooms" "github.com/nxshock/signaller/internal/models/sync" ) @@ -34,6 +35,7 @@ type User interface { SendMessage(room Room, text string) *models.ApiError JoinedRooms() []Room ChangePassword(newPassword string) + Devices() []devices.Device Logout(token string) LogoutAll() } diff --git a/internal/backends/memory/user.go b/internal/backends/memory/user.go index a8938c7..39932eb 100644 --- a/internal/backends/memory/user.go +++ b/internal/backends/memory/user.go @@ -7,6 +7,7 @@ import ( "github.com/nxshock/signaller/internal" "github.com/nxshock/signaller/internal/models" "github.com/nxshock/signaller/internal/models/createroom" + "github.com/nxshock/signaller/internal/models/devices" "github.com/nxshock/signaller/internal/models/rooms" ) @@ -176,6 +177,22 @@ func (user *User) JoinedRooms() []internal.Room { return result } +func (user *User) Devices() []devices.Device { + user.backend.mutex.Lock() + defer user.backend.mutex.Unlock() + + var result []devices.Device + + for _, token := range user.Tokens { + device := devices.Device{ + DeviceID: token.Device} + + result = append(result, device) + } + + return result +} + func (user *User) ChangePassword(newPassword string) { user.mutex.Lock() defer user.mutex.Unlock() diff --git a/internal/backends/memory/user_test.go b/internal/backends/memory/user_test.go index a25fb62..c5f8793 100644 --- a/internal/backends/memory/user_test.go +++ b/internal/backends/memory/user_test.go @@ -130,3 +130,16 @@ func TestNewPassword(t *testing.T) { user.ChangePassword(newPassword) assert.Equal(t, newPassword, user.Password()) } + +func TestDevices(t *testing.T) { + backend := NewBackend("localhost") + + var expectedDeviceID = "my device" + + user, _, err := backend.Register("user1", "", expectedDeviceID) + assert.Nil(t, err) + + devices := user.Devices() + assert.Len(t, devices, 1) + assert.Equal(t, expectedDeviceID, devices[0].DeviceID) +} diff --git a/internal/handlers.go b/internal/handlers.go index 855bc16..f0c40c5 100644 --- a/internal/handlers.go +++ b/internal/handlers.go @@ -276,6 +276,15 @@ func CapabilitiesHandler(w http.ResponseWriter, r *http.Request) { sendJsonResponse(w, http.StatusOK, response) } +// 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 { + errorResponse(w, models.M_UNKNOWN, http.StatusBadRequest, "wrong method: "+r.Method) + return + } + +} + func sendJsonResponse(w http.ResponseWriter, httpStatus int, data interface{}) error { b, err := json.Marshal(data) if err != nil { diff --git a/internal/models/devices/devices.go b/internal/models/devices/devices.go new file mode 100644 index 0000000..03475ee --- /dev/null +++ b/internal/models/devices/devices.go @@ -0,0 +1,12 @@ +package devices + +type Response struct { + Devices []Device `json:"devices"` // A list of all registered devices for this user. +} + +type Device struct { + DeviceID string `json:"device_id"` // Required. Identifier of this device. + DisplayName string `json:"display_name"` // Display name set by the user for this device. Absent if no name has been set. + LastSeenIP string `json:"last_seen_ip"` // The IP address where this device was last seen. (May be a few minutes out of date, for efficiency reasons). + LastSeenTS int `json:"last_seen_ts"` // The timestamp (in milliseconds since the unix epoch) when this devices was last seen. (May be a few minutes out of date, for efficiency reasons). +} diff --git a/internal/server.go b/internal/server.go index 4439a88..bb4a827 100644 --- a/internal/server.go +++ b/internal/server.go @@ -37,6 +37,7 @@ func NewServer(port int) (*Server, error) { router.HandleFunc("/_matrix/client/r0/account/password", PasswordHandler) router.HandleFunc("/_matrix/client/r0/sync", SyncHandler) router.HandleFunc("/_matrix/client/r0/capabilities", CapabilitiesHandler) + router.HandleFunc("/_matrix/client/r0/devices", DevicesHandler) router.HandleFunc("/", RootHandler) if port <= 0 || port > 65535 {