diff --git a/server/server.go b/server/server.go index be6c573..81daa6b 100644 --- a/server/server.go +++ b/server/server.go @@ -59,8 +59,6 @@ import ( Docs: - "expires" field in message - server.yml: enable-X flags - Refactor: - - rename /access -> /reservation */ // Server is the main server, providing the UI and API for ntfy @@ -105,8 +103,8 @@ var ( accountPasswordPath = "/v1/account/password" accountSettingsPath = "/v1/account/settings" accountSubscriptionPath = "/v1/account/subscription" - accountAccessPath = "/v1/account/access" - accountAccessSingleRegex = regexp.MustCompile(`/v1/account/access/([-_A-Za-z0-9]{1,64})$`) + accountReservationPath = "/v1/account/reservation" + accountReservationSingleRegex = regexp.MustCompile(`/v1/account/reservation/([-_A-Za-z0-9]{1,64})$`) accountSubscriptionSingleRegex = regexp.MustCompile(`^/v1/account/subscription/([-_A-Za-z0-9]{16})$`) matrixPushPath = "/_matrix/push/v1/notify" staticRegex = regexp.MustCompile(`^/static/.+`) @@ -364,10 +362,10 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit return s.ensureUser(s.handleAccountSubscriptionChange)(w, r, v) } else if r.Method == http.MethodDelete && accountSubscriptionSingleRegex.MatchString(r.URL.Path) { return s.ensureUser(s.handleAccountSubscriptionDelete)(w, r, v) - } else if r.Method == http.MethodPost && r.URL.Path == accountAccessPath { - return s.ensureUser(s.handleAccountAccessAdd)(w, r, v) - } else if r.Method == http.MethodDelete && accountAccessSingleRegex.MatchString(r.URL.Path) { - return s.ensureUser(s.handleAccountAccessDelete)(w, r, v) + } else if r.Method == http.MethodPost && r.URL.Path == accountReservationPath { + return s.ensureUser(s.handleAccountReservationAdd)(w, r, v) + } else if r.Method == http.MethodDelete && accountReservationSingleRegex.MatchString(r.URL.Path) { + return s.ensureUser(s.handleAccountReservationDelete)(w, r, v) } else if r.Method == http.MethodGet && r.URL.Path == matrixPushPath { return s.handleMatrixDiscovery(w) } else if r.Method == http.MethodGet && staticRegex.MatchString(r.URL.Path) { diff --git a/server/server_account.go b/server/server_account.go index 2f5d04f..5234993 100644 --- a/server/server_account.go +++ b/server/server_account.go @@ -316,7 +316,7 @@ func (s *Server) handleAccountSubscriptionDelete(w http.ResponseWriter, r *http. return nil } -func (s *Server) handleAccountAccessAdd(w http.ResponseWriter, r *http.Request, v *visitor) error { +func (s *Server) handleAccountReservationAdd(w http.ResponseWriter, r *http.Request, v *visitor) error { if v.user != nil && v.user.Role == user.RoleAdmin { return errHTTPBadRequestMakesNoSenseForAdmin } @@ -332,7 +332,7 @@ func (s *Server) handleAccountAccessAdd(w http.ResponseWriter, r *http.Request, return errHTTPBadRequestPermissionInvalid } if v.user.Tier == nil { - return errHTTPUnauthorized // FIXME there should always be a plan! + return errHTTPUnauthorized } if err := s.userManager.CheckAllowAccess(v.user.Name, req.Topic); err != nil { return errHTTPConflictTopicReserved @@ -361,8 +361,8 @@ func (s *Server) handleAccountAccessAdd(w http.ResponseWriter, r *http.Request, return nil } -func (s *Server) handleAccountAccessDelete(w http.ResponseWriter, r *http.Request, v *visitor) error { - matches := accountAccessSingleRegex.FindStringSubmatch(r.URL.Path) +func (s *Server) handleAccountReservationDelete(w http.ResponseWriter, r *http.Request, v *visitor) error { + matches := accountReservationSingleRegex.FindStringSubmatch(r.URL.Path) if len(matches) != 2 { return errHTTPInternalErrorInvalidPath } diff --git a/server/server_account_test.go b/server/server_account_test.go index d6c28c8..f1615eb 100644 --- a/server/server_account_test.go +++ b/server/server_account_test.go @@ -350,7 +350,7 @@ func TestAccount_Reservation_AddWithoutTierFails(t *testing.T) { rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil) require.Equal(t, 200, rr.Code) - rr = request(t, s, "POST", "/v1/account/access", `{"topic":"mytopic", "everyone":"deny-all"}`, map[string]string{ + rr = request(t, s, "POST", "/v1/account/reservation", `{"topic":"mytopic", "everyone":"deny-all"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 401, rr.Code) @@ -362,7 +362,7 @@ func TestAccount_Reservation_AddAdminSuccess(t *testing.T) { s := newTestServer(t, conf) require.Nil(t, s.userManager.AddUser("phil", "adminpass", user.RoleAdmin, "unit-test")) - rr := request(t, s, "POST", "/v1/account/access", `{"topic":"mytopic","everyone":"deny-all"}`, map[string]string{ + rr := request(t, s, "POST", "/v1/account/reservation", `{"topic":"mytopic","everyone":"deny-all"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "adminpass"), }) require.Equal(t, 400, rr.Code) @@ -393,24 +393,24 @@ func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) { require.Nil(t, s.userManager.ChangeTier("phil", "pro")) // Reserve two topics - rr = request(t, s, "POST", "/v1/account/access", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{ + rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 200, rr.Code) - rr = request(t, s, "POST", "/v1/account/access", `{"topic": "another", "everyone":"read-only"}`, map[string]string{ + rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "another", "everyone":"read-only"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 200, rr.Code) // Trying to reserve a third should fail - rr = request(t, s, "POST", "/v1/account/access", `{"topic": "yet-another", "everyone":"deny-all"}`, map[string]string{ + rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "yet-another", "everyone":"deny-all"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 429, rr.Code) // Modify existing should still work - rr = request(t, s, "POST", "/v1/account/access", `{"topic": "another", "everyone":"write-only"}`, map[string]string{ + rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "another", "everyone":"write-only"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 200, rr.Code) @@ -436,7 +436,7 @@ func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) { require.Equal(t, "deny-all", account.Reservations[1].Everyone) // Delete and re-check - rr = request(t, s, "DELETE", "/v1/account/access/another", "", map[string]string{ + rr = request(t, s, "DELETE", "/v1/account/reservation/another", "", map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 200, rr.Code) @@ -468,7 +468,7 @@ func TestAccount_Reservation_PublishByAnonymousFails(t *testing.T) { require.Nil(t, s.userManager.ChangeTier("phil", "pro")) // Reserve a topic - rr = request(t, s, "POST", "/v1/account/access", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{ + rr = request(t, s, "POST", "/v1/account/reservation", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{ "Authorization": util.BasicAuth("phil", "mypass"), }) require.Equal(t, 200, rr.Code) diff --git a/web/src/app/AccountApi.js b/web/src/app/AccountApi.js index 52aa836..1ce2766 100644 --- a/web/src/app/AccountApi.js +++ b/web/src/app/AccountApi.js @@ -1,6 +1,6 @@ import { - accountAccessSingleUrl, - accountAccessUrl, + accountReservationSingleUrl, + accountReservationUrl, accountPasswordUrl, accountSettingsUrl, accountSubscriptionSingleUrl, @@ -229,7 +229,7 @@ class AccountApi { } async upsertAccess(topic, everyone) { - const url = accountAccessUrl(config.base_url); + const url = accountReservationUrl(config.base_url); console.log(`[AccountApi] Upserting user access to topic ${topic}, everyone=${everyone}`); const response = await fetch(url, { method: "POST", @@ -250,7 +250,7 @@ class AccountApi { } async deleteAccess(topic) { - const url = accountAccessSingleUrl(config.base_url, topic); + const url = accountReservationSingleUrl(config.base_url, topic); console.log(`[AccountApi] Removing topic reservation ${url}`); const response = await fetch(url, { method: "DELETE", diff --git a/web/src/app/utils.js b/web/src/app/utils.js index bdfbf0c..4b06da7 100644 --- a/web/src/app/utils.js +++ b/web/src/app/utils.js @@ -24,8 +24,8 @@ export const accountTokenUrl = (baseUrl) => `${baseUrl}/v1/account/token`; export const accountSettingsUrl = (baseUrl) => `${baseUrl}/v1/account/settings`; export const accountSubscriptionUrl = (baseUrl) => `${baseUrl}/v1/account/subscription`; export const accountSubscriptionSingleUrl = (baseUrl, id) => `${baseUrl}/v1/account/subscription/${id}`; -export const accountAccessUrl = (baseUrl) => `${baseUrl}/v1/account/access`; -export const accountAccessSingleUrl = (baseUrl, topic) => `${baseUrl}/v1/account/access/${topic}`; +export const accountReservationUrl = (baseUrl) => `${baseUrl}/v1/account/reservation`; +export const accountReservationSingleUrl = (baseUrl, topic) => `${baseUrl}/v1/account/reservation/${topic}`; export const shortUrl = (url) => url.replaceAll(/https?:\/\//g, ""); export const expandUrl = (url) => [`https://${url}`, `http://${url}`]; export const expandSecureUrl = (url) => `https://${url}`;