feat(api): add delete speaker functionality and corresponding tests
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 26s
CI / web (push) Successful in 34s
CI / go (push) Failing after 36s
CI / bird2 (push) Has been skipped
CI / release (push) Has been skipped
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 26s
CI / web (push) Successful in 34s
CI / go (push) Failing after 36s
CI / bird2 (push) Has been skipped
CI / release (push) Has been skipped
- Implemented a DELETE endpoint for removing speakers, including necessary authorization checks and response handling. - Added a handler for the delete operation in the HTTP API. - Created unit tests to verify the delete functionality, ensuring proper deletion and response codes. - Updated OpenAPI documentation to reflect the new delete speaker endpoint.
This commit is contained in:
@@ -65,6 +65,7 @@ func (s *Server) registerCRUDRoutes(m *http.ServeMux) {
|
||||
m.HandleFunc("POST /speakers", s.handlePostSpeaker)
|
||||
m.HandleFunc("GET /speakers/{speaker_id}", s.handleGetSpeakerByID)
|
||||
m.HandleFunc("PATCH /speakers/{speaker_id}", s.handlePatchSpeaker)
|
||||
m.HandleFunc("DELETE /speakers/{speaker_id}", s.handleDeleteSpeaker)
|
||||
|
||||
m.HandleFunc("GET /revisions/{revision_id}/prefixes", s.handleRevisionPrefixes)
|
||||
|
||||
@@ -1021,6 +1022,18 @@ func (s *Server) handlePatchSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, speakerJSONFromStore(s.store, x))
|
||||
}
|
||||
|
||||
func (s *Server) handleDeleteSpeaker(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "editor") {
|
||||
return
|
||||
}
|
||||
if err := s.store.DeleteSpeaker(a.TenantID, r.PathValue("speaker_id")); err != nil {
|
||||
writeStoreErr(w, err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (s *Server) handleRevisionPrefixes(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok := authFromContext(r.Context())
|
||||
if !ok || !s.requireAtLeast(w, a, "viewer") {
|
||||
|
||||
@@ -41,6 +41,27 @@ func TestPostSpeaker_defaultsFromEndpointIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteSpeaker(t *testing.T) {
|
||||
srv, err := New(Options{InsecureDev: true, SeedDemo: true, BundleSeedHex: testBundleSeed})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer srv.Close()
|
||||
tenant, _, _, _, demoSpk := srv.Store().DemoIDs()
|
||||
mustSetTestAPIKeys(t, srv, "edkey|"+tenant+"|editor")
|
||||
|
||||
req := httptest.NewRequest(http.MethodDelete, "/v1/speakers/"+demoSpk, nil)
|
||||
req.Header.Set("Authorization", "Bearer edkey")
|
||||
rec := httptest.NewRecorder()
|
||||
srv.Handler().ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusNoContent {
|
||||
t.Fatalf("status %d body %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
if _, err := srv.Store().GetSpeaker(tenant, demoSpk); err == nil {
|
||||
t.Fatal("speaker should be deleted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBundleSigningPublicKey(t *testing.T) {
|
||||
srv, err := New(Options{InsecureDev: true, SeedDemo: true, BundleSeedHex: testBundleSeed})
|
||||
if err != nil {
|
||||
|
||||
@@ -646,6 +646,18 @@ func (p *Postgres) UpdateSpeaker(tenantID, id string, patch *store.SpeakerPatch)
|
||||
return p.GetSpeaker(tenantID, id)
|
||||
}
|
||||
|
||||
func (p *Postgres) DeleteSpeaker(tenantID, id string) error {
|
||||
ctx := context.Background()
|
||||
tag, err := p.pool.Exec(ctx, `DELETE FROM bgp_speaker WHERE id=$1 AND tenant_id=$2`, id, tenantID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag.RowsAffected() == 0 {
|
||||
return store.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Postgres) GetRevision(tenantID, revisionID string) (*store.Revision, error) {
|
||||
ctx := context.Background()
|
||||
var r store.Revision
|
||||
|
||||
@@ -73,6 +73,7 @@ type Backend interface {
|
||||
GetSpeakerAnyTenant(speakerID string) (*Speaker, error)
|
||||
CreateSpeaker(tenantID string, in *Speaker) (*Speaker, error)
|
||||
UpdateSpeaker(tenantID, id string, patch *SpeakerPatch) (*Speaker, error)
|
||||
DeleteSpeaker(tenantID, id string) error
|
||||
|
||||
GetRevision(tenantID, revisionID string) (*Revision, error)
|
||||
ListRevisions(tenantID, moduleID string, cursor string, limit int) (items []*Revision, nextCursor string, hasMore bool)
|
||||
|
||||
@@ -779,6 +779,18 @@ func (m *Memory) UpdateSpeaker(tenantID, id string, patch *SpeakerPatch) (*Speak
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
func (m *Memory) DeleteSpeaker(tenantID, id string) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
sp, ok := m.speakers[id]
|
||||
if !ok || sp.TenantID != tenantID {
|
||||
return ErrNotFound
|
||||
}
|
||||
delete(m.speakers, id)
|
||||
delete(m.publishedRevision, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Memory) ListRevisionPrefixes(tenantID, revisionID string, cursor string, limit int) ([]PrefixRow, string, bool) {
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
|
||||
Reference in New Issue
Block a user