Skip to content

Commit

Permalink
feat(daemon): identities API endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
benhoyt committed Jun 12, 2024
1 parent e1a5ee6 commit b90e8dd
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internals/daemon/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ var API = []*Command{{
Path: "/v1/notices/{id}",
ReadAccess: UserAccess{},
GET: v1GetNotice,
}, {
Path: "/v1/identities",
ReadAccess: UserAccess{},
WriteAccess: AdminAccess{},
GET: v1GetIdentities,
POST: v1PostIdentities,
}}

var (
Expand Down
72 changes: 72 additions & 0 deletions internals/daemon/api_identities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2024 Canonical Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package daemon

import (
"encoding/json"
"net/http"

"github.com/canonical/pebble/internals/overlord/state"
)

func v1GetIdentities(c *Command, r *http.Request, _ *UserState) Response {
st := c.d.overlord.State()
st.Lock()
defer st.Unlock()

identities := st.Identities()
return SyncResponse(identities)
}

func v1PostIdentities(c *Command, r *http.Request, _ *UserState) Response {
var payload struct {
Action string `json:"action"`
Identities map[string]*state.Identity `json:"identities"`
}
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&payload); err != nil {
return BadRequest("cannot decode request body: %v", err)
}

st := c.d.overlord.State()
st.Lock()
defer st.Unlock()

var err error
switch payload.Action {
case "add":
err = st.AddIdentities(payload.Identities)
case "update":
err = st.UpdateIdentities(payload.Identities)
case "replace":
err = st.ReplaceIdentities(payload.Identities)
case "remove":
identities := make(map[string]struct{})
for name, identity := range payload.Identities {
if identity != nil {
return BadRequest(`identity %q value must be null for "remove" action`, name)
}
identities[name] = struct{}{}
}
err = st.RemoveIdentities(identities)
default:
return BadRequest(`invalid action %q, must be "add", "update", "replace", or "remove"`, payload.Action)
}
if err != nil {
return BadRequest("%v", err)
}

return SyncResponse(nil)
}

0 comments on commit b90e8dd

Please sign in to comment.