satellite/console: delete project members endpoint
This commit adds a new endpoint on the console api to delete project members and invitations. issue: https://github.com/storj/storj/issues/6136 Change-Id: I980bb97afd1ed2ed8f0f27cc2e8dc1d80d7eef05
This commit is contained in:
parent
d7d196fe61
commit
969599b60b
@ -524,6 +524,39 @@ func (p *Projects) RespondToInvitation(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteMembersAndInvitations deletes members and invitations from a project.
|
||||
func (p *Projects) DeleteMembersAndInvitations(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
var ok bool
|
||||
var idParam string
|
||||
|
||||
if idParam, ok = mux.Vars(r)["id"]; !ok {
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing project id route param"))
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.FromString(idParam)
|
||||
if err != nil {
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
emailsStr := r.URL.Query().Get("emails")
|
||||
if emailsStr == "" {
|
||||
p.serveJSONError(ctx, w, http.StatusBadRequest, errs.New("missing emails parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
emails := strings.Split(emailsStr, ",")
|
||||
|
||||
err = p.service.DeleteProjectMembersAndInvitations(ctx, id, emails)
|
||||
if err != nil {
|
||||
p.serveJSONError(ctx, w, http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
||||
// serveJSONError writes JSON error to response output stream.
|
||||
func (p *Projects) serveJSONError(ctx context.Context, w http.ResponseWriter, status int, err error) {
|
||||
web.ServeJSONError(ctx, p.log, w, status, err)
|
||||
|
@ -41,9 +41,15 @@ func createTestMembers(ctx context.Context, t *testing.T, db console.DB, p uuid.
|
||||
PasswordHash: []byte("test"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
members[memberID] = *member
|
||||
|
||||
status := console.UserStatus(1)
|
||||
|
||||
err = db.Users().Update(ctx, memberID, console.UpdateUserRequest{
|
||||
Status: &status,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = db.ProjectMembers().Insert(ctx, member.ID, p)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -382,3 +388,95 @@ func TestGetProjectMembersAndInvitationsLimitAndPage(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDeleteProjectMembers(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
sat := planet.Satellites[0]
|
||||
p := planet.Uplinks[0].Projects[0].ID
|
||||
|
||||
user, err := sat.DB.Console().Users().GetByEmail(ctx, planet.Uplinks[0].User[sat.ID()].Email)
|
||||
require.NoError(t, err)
|
||||
|
||||
members, invitees := createTestMembers(ctx, t, sat.DB.Console(), p, &user.ID)
|
||||
|
||||
tokenInfo, err := sat.API.Console.Service.Token(ctx, console.AuthUser{Email: user.Email, Password: user.FullName})
|
||||
require.NoError(t, err)
|
||||
|
||||
expire := time.Now().AddDate(0, 0, 1)
|
||||
cookie := http.Cookie{
|
||||
Name: "_tokenKey",
|
||||
Path: "/",
|
||||
Value: tokenInfo.Token.String(),
|
||||
Expires: expire,
|
||||
}
|
||||
|
||||
addr := planet.Satellites[0].API.Console.Listener.Addr().String()
|
||||
|
||||
var emails string
|
||||
var firstAppendDone bool
|
||||
for _, m := range members {
|
||||
if firstAppendDone {
|
||||
emails += ","
|
||||
} else {
|
||||
firstAppendDone = true
|
||||
}
|
||||
emails += m.Email
|
||||
}
|
||||
for e := range invitees {
|
||||
if len(members) > 0 {
|
||||
emails += ","
|
||||
}
|
||||
emails += e
|
||||
}
|
||||
|
||||
endpoint := fmt.Sprintf("http://%s/api/v0/projects/%s/members?", addr, p.String())
|
||||
params := url.Values{}
|
||||
params.Add("emails", emails)
|
||||
endpoint += params.Encode()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "DELETE", endpoint, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
req.AddCookie(&cookie)
|
||||
|
||||
client := http.Client{}
|
||||
res, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, res.Body.Close())
|
||||
require.NotContains(t, string(body), "error")
|
||||
|
||||
require.Equal(t, http.StatusOK, res.StatusCode)
|
||||
|
||||
page, err := sat.DB.Console().ProjectMembers().GetPagedWithInvitationsByProjectID(ctx, p, console.ProjectMembersCursor{Limit: 1, Page: 1})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, page.ProjectMembers, 1)
|
||||
require.Equal(t, user.ID, page.ProjectMembers[0].MemberID)
|
||||
|
||||
// test error
|
||||
endpoint = fmt.Sprintf("http://%s/api/v0/projects/%s/members?", addr, p.String())
|
||||
params = url.Values{}
|
||||
params.Add("emails", "nonmember@storj.test")
|
||||
endpoint += params.Encode()
|
||||
|
||||
req, err = http.NewRequestWithContext(ctx, "DELETE", endpoint, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
req.AddCookie(&cookie)
|
||||
|
||||
client = http.Client{}
|
||||
res, err = client.Do(req)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
|
||||
body, err = io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, res.Body.Close())
|
||||
require.Contains(t, string(body), "error")
|
||||
})
|
||||
}
|
||||
|
@ -278,6 +278,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
|
||||
projectsRouter.Handle("", http.HandlerFunc(projectsController.GetUserProjects)).Methods(http.MethodGet, http.MethodOptions)
|
||||
projectsRouter.Handle("/paged", http.HandlerFunc(projectsController.GetPagedProjects)).Methods(http.MethodGet, http.MethodOptions)
|
||||
projectsRouter.Handle("/{id}", http.HandlerFunc(projectsController.UpdateProject)).Methods(http.MethodPatch, http.MethodOptions)
|
||||
projectsRouter.Handle("/{id}/members", http.HandlerFunc(projectsController.DeleteMembersAndInvitations)).Methods(http.MethodDelete, http.MethodOptions)
|
||||
projectsRouter.Handle("/{id}/salt", http.HandlerFunc(projectsController.GetSalt)).Methods(http.MethodGet, http.MethodOptions)
|
||||
projectsRouter.Handle("/{id}/members", http.HandlerFunc(projectsController.GetMembersAndInvitations)).Methods(http.MethodGet, http.MethodOptions)
|
||||
projectsRouter.Handle("/{id}/invite", http.HandlerFunc(projectsController.InviteUsers)).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
Loading…
Reference in New Issue
Block a user