Skip to content
Snippets Groups Projects
Commit d765b6e6 authored by Florent Gluck's avatar Florent Gluck
Browse files

- WIP: REST API documentation

- Updated code so that backend never returns user passwords (hashed)
- Bumped server version to 1.10.1
parent 3a5c91e0
No related branches found
No related tags found
No related merge requests found
...@@ -4,23 +4,22 @@ ...@@ -4,23 +4,22 @@
| Route | Description | Method | Input | Output | | Route | Description | Method | Input | Output |
|--- |--- |--- |--- |--- | |--- |--- |--- |--- |--- |
| `/login` | login (return access token) | POST | common.params.Login | common.params.Login | | `/login` | login (return access token) | POST | common.params.Login | common.params.Token |
| `/token/refresh` | obtain a new access token | GET | | common.params.Token | | `/token/refresh` | obtain a new access token | GET | - | common.params.Token |
| `/version` | obtain version number | GET | | common.params.Version | | `/version` | obtain version number | GET | - | common.params.Version |
### User management ### User management
| Route | Description | Method | Input | Req. user cap. | Output | | Route | Description | Method | Input | Req. user cap. | Output |
|--- |--- |--- |--- |--- |--- | |--- |--- |--- |--- |--- |--- |
| `/users` | create a user | POST | email,firstname,lastname,pwd,caps | `USER_CREATE` | | | `/users` | create a user | POST | common.params.UserWithPwd | `USER_CREATE` | - |
| `/users/{email}` | delete a user | DELETE | | `USER_DESTROY` | | | `/users/{email}` | delete a user | DELETE | - | `USER_DESTROY` | - |
| `/users/{email}/caps` | set caps for a user | PUT | caps | `USER_SET_CAPS` | | | `/users/{email}/caps` | set caps for a user | PUT | common.params.UserSetCaps | `USER_SET_CAPS` | - |
| `/users/{email}/unlock` | unlock a user | PUT | | `USER_UNLOCK` | | | `/users/{email}/unlock` | unlock a user | PUT | - | `USER_UNLOCK` | - |
| `/users/{email}/resetpwd` | reset a user's pwd | PUT | | `USER_RESETPWD` | new pwd | | `/users/{email}/resetpwd` | reset a user's pwd | PUT | - | `USER_RESETPWD` | common.params.UserSetPwd |
| `/users/pwd` | set current user's pwd | PUT | pwd | | | | `/users/pwd` | set current user's pwd | PUT | common.params.UserSetPwd | - | - |
| `/users` | list users | GET | | `USER_LIST` | | | `/users` | list users | GET | - | `USER_LIST` | []common.params.UserWithoutPwd |
| `/users/{email}` | list a user | GET | | `USER_LIST` | | | `/users/whoami` | list current user | GET | - | | common.params.UserWithoutPwd |
| `/users/whoami` | list current user | GET | | | |
- Open question: shall we forbid the deletion of a user if they still own templates or VMs? - Open question: shall we forbid the deletion of a user if they still own templates or VMs?
......
...@@ -55,7 +55,7 @@ List of user capabilities: ...@@ -55,7 +55,7 @@ List of user capabilities:
i = 0 i = 0
} }
} }
u.PrintErr(usage) u.PrintlnErr(usage)
} }
func (cmd *Add)Run(args []string) int { func (cmd *Add)Run(args []string) int {
...@@ -79,8 +79,10 @@ func (cmd *Add)Run(args []string) int { ...@@ -79,8 +79,10 @@ func (cmd *Add)Run(args []string) int {
} }
if err := cmd.runRequest(cargs); err != nil { if err := cmd.runRequest(cargs); err != nil {
u.PrintlnErr(err.Error()) u.PrintlnErr("FAILED creating user "+cargs.Email+": "+err.Error())
statusCode = 1 statusCode = 1
} else {
u.Println("Successfully created user "+cargs.Email)
} }
} else if argc == 1 { } else if argc == 1 {
// Detected syntax: file.csv // Detected syntax: file.csv
......
...@@ -10,11 +10,11 @@ const ( ...@@ -10,11 +10,11 @@ const (
msgInsufficientCaps = "Permission denied: insufficient capabilities" msgInsufficientCaps = "Permission denied: insufficient capabilities"
) )
func jsonMsg(msg string) map[string]interface{} { // func jsonMsg(msg string) map[string]interface{} {
// The following 2 lines are identical: // // The following 2 lines are identical:
//return map[string]interface{}{"message": msg} // //return map[string]interface{}{"message": msg}
return echo.Map{"message": msg} // return echo.Map{"message": msg}
} // }
// Decodes and validates a json object in the response's body. // Decodes and validates a json object in the response's body.
func decodeJson(c echo.Context, object any) error { func decodeJson(c echo.Context, object any) error {
......
...@@ -236,7 +236,7 @@ func (r *RouterTemplates)DeleteTemplate(c echo.Context) error { ...@@ -236,7 +236,7 @@ func (r *RouterTemplates)DeleteTemplate(c echo.Context) error {
if err := r.tpl.DeleteTemplate(tplID, r.vms); err != nil { if err := r.tpl.DeleteTemplate(tplID, r.vms); err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} else if user.HasCapability(caps.CAP_TPL_DESTROY) { } else if user.HasCapability(caps.CAP_TPL_DESTROY) {
template, err := r.tpl.GetTemplate(tplID) template, err := r.tpl.GetTemplate(tplID)
if err != nil { if err != nil {
...@@ -247,7 +247,7 @@ func (r *RouterTemplates)DeleteTemplate(c echo.Context) error { ...@@ -247,7 +247,7 @@ func (r *RouterTemplates)DeleteTemplate(c echo.Context) error {
if err := r.tpl.DeleteTemplate(tplID, r.vms); err != nil { if err := r.tpl.DeleteTemplate(tplID, r.vms); err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
} }
...@@ -284,7 +284,7 @@ func (r *RouterTemplates)EditTemplate(c echo.Context) error { ...@@ -284,7 +284,7 @@ func (r *RouterTemplates)EditTemplate(c echo.Context) error {
if err := r.tpl.EditTemplate(tplID, p.Name, p.Access); err != nil { if err := r.tpl.EditTemplate(tplID, p.Name, p.Access); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} else if user.HasCapability(caps.CAP_TPL_EDIT) { } else if user.HasCapability(caps.CAP_TPL_EDIT) {
template, err := r.tpl.GetTemplate(tplID) template, err := r.tpl.GetTemplate(tplID)
if err != nil { if err != nil {
...@@ -297,7 +297,7 @@ func (r *RouterTemplates)EditTemplate(c echo.Context) error { ...@@ -297,7 +297,7 @@ func (r *RouterTemplates)EditTemplate(c echo.Context) error {
if err := r.tpl.EditTemplate(tplID, p.Name, p.Access); err != nil { if err := r.tpl.EditTemplate(tplID, p.Name, p.Access); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
} }
......
...@@ -34,7 +34,7 @@ func (r *RouterUsers)GetUsers(c echo.Context) error { ...@@ -34,7 +34,7 @@ func (r *RouterUsers)GetUsers(c echo.Context) error {
list := []params.UserWithoutPwd{} list := []params.UserWithoutPwd{}
for _, u := range r.users.GetUsers() { for _, u := range r.users.GetUsers() {
user := params.UserWithoutPwd{u.Email, u.FirstName, u.LastName, u.Caps} user := params.UserWithoutPwd{Email: u.Email, FirstName: u.FirstName, LastName: u.LastName, Caps: u.Caps}
list = append(list, user) list = append(list, user)
} }
...@@ -49,7 +49,8 @@ func (r *RouterUsers)GetLoggedUser(c echo.Context) error { ...@@ -49,7 +49,8 @@ func (r *RouterUsers)GetLoggedUser(c echo.Context) error {
return echo.NewHTTPError(http.StatusUnauthorized, err.Error()) return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
} }
return c.JSONPretty(http.StatusOK, user, " ") userWithoutPwd := params.UserWithoutPwd{Email: user.Email, FirstName: user.FirstName, LastName: user.LastName, Caps: user.Caps}
return c.JSONPretty(http.StatusOK, userWithoutPwd, " ")
} }
// Deletes a user by its ID. // Deletes a user by its ID.
...@@ -75,7 +76,7 @@ func (r *RouterUsers)DeleteUserByEmail(c echo.Context) error { ...@@ -75,7 +76,7 @@ func (r *RouterUsers)DeleteUserByEmail(c echo.Context) error {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
// Creates a user. // Creates a user.
...@@ -112,7 +113,7 @@ func (r *RouterUsers)CreateUser(c echo.Context) error { ...@@ -112,7 +113,7 @@ func (r *RouterUsers)CreateUser(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusCreated, newUser, " ") return c.JSON(http.StatusCreated, "")
} }
// Update a user's capabilities. // Update a user's capabilities.
...@@ -154,7 +155,7 @@ func (r *RouterUsers)SetUserCaps(c echo.Context) error { ...@@ -154,7 +155,7 @@ func (r *RouterUsers)SetUserCaps(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
// Update the logged user's password. // Update the logged user's password.
...@@ -185,7 +186,7 @@ func (r *RouterUsers)SetUserPwd(c echo.Context) error { ...@@ -185,7 +186,7 @@ func (r *RouterUsers)SetUserPwd(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
// Unlock a user. // Unlock a user.
...@@ -211,7 +212,7 @@ func (r *RouterUsers)UnlockUser(c echo.Context) error { ...@@ -211,7 +212,7 @@ func (r *RouterUsers)UnlockUser(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
// Reset a user's password. // Reset a user's password.
......
...@@ -311,7 +311,7 @@ func (r *RouterVMs)DeleteVM(c echo.Context) error { ...@@ -311,7 +311,7 @@ func (r *RouterVMs)DeleteVM(c echo.Context) error {
if err := r.vms.DeleteVM(vm.GetID()); err != nil { if err := r.vms.DeleteVM(vm.GetID()); err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
}) })
} }
...@@ -326,7 +326,7 @@ func (r *RouterVMs)StartVM(c echo.Context) error { ...@@ -326,7 +326,7 @@ func (r *RouterVMs)StartVM(c echo.Context) error {
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
}) })
} }
...@@ -346,7 +346,7 @@ func (r *RouterVMs)StartVMWithCreds(c echo.Context) error { ...@@ -346,7 +346,7 @@ func (r *RouterVMs)StartVMWithCreds(c echo.Context) error {
if err := r.vms.StartVMWithCreds(vm.GetID(), p.Port, true, p.Pwd); err != nil { if err := r.vms.StartVMWithCreds(vm.GetID(), p.Port, true, p.Pwd); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
}) })
} }
...@@ -360,7 +360,7 @@ func (r *RouterVMs)KillVM(c echo.Context) error { ...@@ -360,7 +360,7 @@ func (r *RouterVMs)KillVM(c echo.Context) error {
if err := r.vms.KillVM(vm.GetID()); err != nil { if err := r.vms.KillVM(vm.GetID()); err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
}) })
} }
...@@ -374,7 +374,7 @@ func (r *RouterVMs)ShutdownVM(c echo.Context) error { ...@@ -374,7 +374,7 @@ func (r *RouterVMs)ShutdownVM(c echo.Context) error {
if err := r.vms.ShutdownVM(vm.GetID()); err != nil { if err := r.vms.ShutdownVM(vm.GetID()); err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
}) })
} }
...@@ -388,7 +388,7 @@ func (r *RouterVMs)RebootVM(c echo.Context) error { ...@@ -388,7 +388,7 @@ func (r *RouterVMs)RebootVM(c echo.Context) error {
if err := r.vms.RebootVM(vm.GetID()); err != nil { if err := r.vms.RebootVM(vm.GetID()); err != nil {
return echo.NewHTTPError(http.StatusNotFound, err.Error()) return echo.NewHTTPError(http.StatusNotFound, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
}) })
} }
...@@ -451,7 +451,7 @@ func (r *RouterVMs)SetVMAccessForUser(c echo.Context) error { ...@@ -451,7 +451,7 @@ func (r *RouterVMs)SetVMAccessForUser(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
// Delete a VM Access for a given user. // Delete a VM Access for a given user.
...@@ -480,7 +480,7 @@ func (r *RouterVMs)DeleteVMAccessForUser(c echo.Context) error { ...@@ -480,7 +480,7 @@ func (r *RouterVMs)DeleteVMAccessForUser(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusOK, jsonMsg("OK"), " ") return c.JSON(http.StatusOK, "")
} }
// Exports a VM's directory into a compressed archive. // Exports a VM's directory into a compressed archive.
...@@ -559,7 +559,7 @@ func (r *RouterVMs)ImportFilesToVM(c echo.Context) error { ...@@ -559,7 +559,7 @@ func (r *RouterVMs)ImportFilesToVM(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err.Error()) return echo.NewHTTPError(http.StatusBadRequest, err.Error())
} }
return c.JSONPretty(http.StatusCreated, jsonMsg("OK"), " ") return c.JSON(http.StatusCreated, "")
}) })
} }
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
const ( const (
major = 1 major = 1
minor = 10 minor = 10
bugfix = 0 bugfix = 1
) )
var version params.Version = params.NewVersion(major, minor, bugfix) var version params.Version = params.NewVersion(major, minor, bugfix)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment