satellite/admin: add API endpoint for adding projects

Change-Id: I7970aa8bec810ee36727446d632a950c836f0597
This commit is contained in:
Michal Niewrzal 2020-05-11 18:05:36 +02:00
parent c58dccb7a8
commit 0e263f0099
4 changed files with 128 additions and 3 deletions

View File

@ -52,4 +52,25 @@ Updates usage limit for a project.
## POST /api/project/{project-id}/limit?rate={value}
Updates rate limit for a project.
Updates rate limit for a project.
## POST /api/project
Adds a project for specific user.
A successful request:
```json
{
"ownerId": "ca7aa0fb-442a-4d4e-aa36-a49abddae837",
"projectName": "2af8dc53-cadf-4ced-9b5c-e554afdadb51",
}
```
A successful response:
```json
{
"projectId": "ca7aa0fb-442a-4d4e-aa36-a49abddae837",
}
```

View File

@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"github.com/gorilla/mux"
@ -15,6 +16,7 @@ import (
"storj.io/common/memory"
"storj.io/common/uuid"
"storj.io/storj/satellite/console"
)
func (server *Server) userInfo(w http.ResponseWriter, r *http.Request) {
@ -82,7 +84,7 @@ func (server *Server) userInfo(w http.ResponseWriter, r *http.Request) {
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(data) // nothing to do with the error response, probably the client requesting disapperaed
_, _ = w.Write(data) // nothing to do with the error response, probably the client requesting disappeared
}
func (server *Server) getProjectLimit(w http.ResponseWriter, r *http.Request) {
@ -147,7 +149,7 @@ func (server *Server) getProjectLimit(w http.ResponseWriter, r *http.Request) {
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(data) // nothing to do with the error response, probably the client requesting disapperaed
_, _ = w.Write(data) // nothing to do with the error response, probably the client requesting disappeared
}
func (server *Server) putProjectLimit(w http.ResponseWriter, r *http.Request) {
@ -223,3 +225,63 @@ func (server *Server) putProjectLimit(w http.ResponseWriter, r *http.Request) {
}
}
}
func (server *Server) addProject(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusInternalServerError)
return
}
var input struct {
OwnerID uuid.UUID `json:"ownerId"`
ProjectName string `json:"projectName"`
}
var output struct {
ProjectID uuid.UUID `json:"projectId"`
}
err = json.Unmarshal(body, &input)
if err != nil {
http.Error(w, fmt.Sprintf("failed to unmarshal request: %v", err), http.StatusBadRequest)
return
}
if input.OwnerID.IsZero() {
http.Error(w, "OwnerID is not set", http.StatusBadRequest)
return
}
if input.ProjectName == "" {
http.Error(w, "ProjectName is not set", http.StatusBadRequest)
return
}
project, err := server.db.Console().Projects().Insert(ctx, &console.Project{
Name: input.ProjectName,
OwnerID: input.OwnerID,
})
if err != nil {
http.Error(w, fmt.Sprintf("failed to insert project: %v", err), http.StatusInternalServerError)
return
}
_, err = server.db.Console().ProjectMembers().Insert(ctx, project.OwnerID, project.ID)
if err != nil {
http.Error(w, fmt.Sprintf("failed to insert project member: %v", err), http.StatusInternalServerError)
return
}
output.ProjectID = project.ID
data, err := json.Marshal(output)
if err != nil {
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(data) // nothing to do with the error response, probably the client requesting disappeared
}

View File

@ -4,6 +4,7 @@
package admin_test
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
@ -15,6 +16,7 @@ import (
"go.uber.org/zap"
"storj.io/common/testcontext"
"storj.io/common/uuid"
"storj.io/storj/private/testplanet"
"storj.io/storj/satellite"
)
@ -103,6 +105,45 @@ func TestAPI(t *testing.T) {
})
}
func TestAddProject(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1,
StorageNodeCount: 0,
UplinkCount: 1,
Reconfigure: testplanet.Reconfigure{
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
config.Admin.Address = "127.0.0.1:0"
},
},
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
address := planet.Satellites[0].Admin.Admin.Listener.Addr()
userID := planet.Uplinks[0].Projects[0].Owner
body := strings.NewReader(fmt.Sprintf(`{"ownerId":"%s","projectName":"Test Project"}`, userID.ID.String()))
req, err := http.NewRequest(http.MethodPost, "http://"+address.String()+"/api/project", body)
require.NoError(t, err)
req.Header.Set("Authorization", "very-secret-token")
response, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
responseBody, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.NoError(t, response.Body.Close())
var output struct {
ProjectID uuid.UUID `json:"projectId"`
}
err = json.Unmarshal(responseBody, &output)
require.NoError(t, err)
project, err := planet.Satellites[0].DB.Console().Projects().Get(ctx, output.ProjectID)
require.NoError(t, err)
require.Equal(t, "Test Project", project.Name)
})
}
func assertGet(t *testing.T, link string, expected string) {
t.Helper()

View File

@ -64,6 +64,7 @@ func NewServer(log *zap.Logger, listener net.Listener, db DB, config Config) *Se
server.mux.HandleFunc("/api/user/{useremail}", server.userInfo).Methods("GET")
server.mux.HandleFunc("/api/project/{project}/limit", server.getProjectLimit).Methods("GET")
server.mux.HandleFunc("/api/project/{project}/limit", server.putProjectLimit).Methods("PUT", "POST")
server.mux.HandleFunc("/api/project", server.addProject).Methods("POST")
return server
}