diff --git a/api/system/spec.json b/api/system/spec.json index cbe4a2301..0236e83d6 100644 --- a/api/system/spec.json +++ b/api/system/spec.json @@ -86,7 +86,7 @@ } }, { - "name": "edit", + "name": "update", "method": "PUT", "title": "Update organisation details", "path": "/{id}", @@ -208,7 +208,7 @@ } }, { - "name": "edit", + "name": "update", "method": "PUT", "title": "Update team details", "path": "/{teamID}", @@ -391,13 +391,6 @@ "Client ID", "Session ID" ], - "struct": [ - { - "imports": [ - "sqlxTypes github.com/jmoiron/sqlx/types" - ] - } - ], "apis": [ { "name": "list", @@ -440,28 +433,16 @@ "required": true, "title": "Email" }, - { - "name": "username", - "type": "string", - "required": true, - "title": "Username" - }, - { - "name": "password", - "type": "string", - "required": true, - "title": "Password" - }, { "name": "name", "type": "string", - "required": true, + "required": false, "title": "Name" }, { "name": "handle", "type": "string", - "required": true, + "required": false, "title": "Handle" }, { @@ -469,30 +450,12 @@ "type": "string", "required": false, "title": "Kind (normal, bot)" - }, - { - "name": "meta", - "type": "sqlxTypes.JSONText", - "required": false, - "title": "Meta data" - }, - { - "name": "satosaID", - "type": "string", - "required": false, - "title": "Satosa ID" - }, - { - "name": "organisationID", - "type": "uint64", - "required": false, - "title": "Organisation ID" } ] } }, { - "name": "edit", + "name": "update", "method": "PUT", "title": "Update user details", "path": "/{userID}", @@ -512,18 +475,6 @@ "required": true, "title": "Email" }, - { - "name": "username", - "type": "string", - "required": true, - "title": "Username" - }, - { - "name": "password", - "type": "string", - "required": true, - "title": "Password" - }, { "name": "name", "type": "string", @@ -533,7 +484,7 @@ { "name": "handle", "type": "string", - "required": true, + "required": false, "title": "Handle" }, { @@ -541,24 +492,6 @@ "type": "string", "required": false, "title": "Kind (normal, bot)" - }, - { - "name": "meta", - "type": "sqlxTypes.JSONText", - "required": false, - "title": "Meta data" - }, - { - "name": "satosaID", - "type": "string", - "required": false, - "title": "Satosa ID" - }, - { - "name": "organisationID", - "type": "uint64", - "required": false, - "title": "Organisation ID" } ] } diff --git a/api/system/spec/organisation.json b/api/system/spec/organisation.json index 399ee27e3..3b5477f26 100644 --- a/api/system/spec/organisation.json +++ b/api/system/spec/organisation.json @@ -44,7 +44,7 @@ } }, { - "Name": "edit", + "Name": "update", "Method": "PUT", "Title": "Update organisation details", "Path": "/{id}", diff --git a/api/system/spec/team.json b/api/system/spec/team.json index 5cbb4b330..2d1ed34e3 100644 --- a/api/system/spec/team.json +++ b/api/system/spec/team.json @@ -50,7 +50,7 @@ } }, { - "Name": "edit", + "Name": "update", "Method": "PUT", "Title": "Update team details", "Path": "/{teamID}", diff --git a/api/system/spec/user.json b/api/system/spec/user.json index 196fc7e2c..e7c82b6d2 100644 --- a/api/system/spec/user.json +++ b/api/system/spec/user.json @@ -1,13 +1,7 @@ { "Title": "Users", "Interface": "User", - "Struct": [ - { - "imports": [ - "sqlxTypes github.com/jmoiron/sqlx/types" - ] - } - ], + "Struct": null, "Parameters": null, "Protocol": "", "Authentication": [ @@ -57,27 +51,15 @@ "title": "Email", "type": "string" }, - { - "name": "username", - "required": true, - "title": "Username", - "type": "string" - }, - { - "name": "password", - "required": true, - "title": "Password", - "type": "string" - }, { "name": "name", - "required": true, + "required": false, "title": "Name", "type": "string" }, { "name": "handle", - "required": true, + "required": false, "title": "Handle", "type": "string" }, @@ -86,30 +68,12 @@ "required": false, "title": "Kind (normal, bot)", "type": "string" - }, - { - "name": "meta", - "required": false, - "title": "Meta data", - "type": "sqlxTypes.JSONText" - }, - { - "name": "satosaID", - "required": false, - "title": "Satosa ID", - "type": "string" - }, - { - "name": "organisationID", - "required": false, - "title": "Organisation ID", - "type": "uint64" } ] } }, { - "Name": "edit", + "Name": "update", "Method": "PUT", "Title": "Update user details", "Path": "/{userID}", @@ -129,18 +93,6 @@ "title": "Email", "type": "string" }, - { - "name": "username", - "required": true, - "title": "Username", - "type": "string" - }, - { - "name": "password", - "required": true, - "title": "Password", - "type": "string" - }, { "name": "name", "required": true, @@ -149,7 +101,7 @@ }, { "name": "handle", - "required": true, + "required": false, "title": "Handle", "type": "string" }, @@ -158,24 +110,6 @@ "required": false, "title": "Kind (normal, bot)", "type": "string" - }, - { - "name": "meta", - "required": false, - "title": "Meta data", - "type": "sqlxTypes.JSONText" - }, - { - "name": "satosaID", - "required": false, - "title": "Satosa ID", - "type": "string" - }, - { - "name": "organisationID", - "required": false, - "title": "Organisation ID", - "type": "uint64" } ] } diff --git a/docs/system/README.md b/docs/system/README.md index 8406210cb..28f0d16e4 100644 --- a/docs/system/README.md +++ b/docs/system/README.md @@ -321,14 +321,9 @@ An organisation may have many teams. Teams may have many channels available. Acc | Parameter | Type | Method | Description | Default | Required? | | --------- | ---- | ------ | ----------- | ------- | --------- | | email | string | POST | Email | N/A | YES | -| username | string | POST | Username | N/A | YES | -| password | string | POST | Password | N/A | YES | -| name | string | POST | Name | N/A | YES | -| handle | string | POST | Handle | N/A | YES | +| name | string | POST | Name | N/A | NO | +| handle | string | POST | Handle | N/A | NO | | kind | string | POST | Kind (normal, bot) | N/A | NO | -| meta | sqlxTypes.JSONText | POST | Meta data | N/A | NO | -| satosaID | string | POST | Satosa ID | N/A | NO | -| organisationID | uint64 | POST | Organisation ID | N/A | NO | ## Update user details @@ -344,14 +339,9 @@ An organisation may have many teams. Teams may have many channels available. Acc | --------- | ---- | ------ | ----------- | ------- | --------- | | userID | uint64 | PATH | User ID | N/A | YES | | email | string | POST | Email | N/A | YES | -| username | string | POST | Username | N/A | YES | -| password | string | POST | Password | N/A | YES | | name | string | POST | Name | N/A | YES | -| handle | string | POST | Handle | N/A | YES | +| handle | string | POST | Handle | N/A | NO | | kind | string | POST | Kind (normal, bot) | N/A | NO | -| meta | sqlxTypes.JSONText | POST | Meta data | N/A | NO | -| satosaID | string | POST | Satosa ID | N/A | NO | -| organisationID | uint64 | POST | Organisation ID | N/A | NO | ## Read user details and memberships diff --git a/system/rest/handlers/organisation.go b/system/rest/handlers/organisation.go index 7452bcbac..005071fa9 100644 --- a/system/rest/handlers/organisation.go +++ b/system/rest/handlers/organisation.go @@ -29,7 +29,7 @@ import ( type OrganisationAPI interface { List(context.Context, *request.OrganisationList) (interface{}, error) Create(context.Context, *request.OrganisationCreate) (interface{}, error) - Edit(context.Context, *request.OrganisationEdit) (interface{}, error) + Update(context.Context, *request.OrganisationUpdate) (interface{}, error) Remove(context.Context, *request.OrganisationRemove) (interface{}, error) Read(context.Context, *request.OrganisationRead) (interface{}, error) Archive(context.Context, *request.OrganisationArchive) (interface{}, error) @@ -39,7 +39,7 @@ type OrganisationAPI interface { type Organisation struct { List func(http.ResponseWriter, *http.Request) Create func(http.ResponseWriter, *http.Request) - Edit func(http.ResponseWriter, *http.Request) + Update func(http.ResponseWriter, *http.Request) Remove func(http.ResponseWriter, *http.Request) Read func(http.ResponseWriter, *http.Request) Archive func(http.ResponseWriter, *http.Request) @@ -61,11 +61,11 @@ func NewOrganisation(oh OrganisationAPI) *Organisation { return oh.Create(r.Context(), params) }) }, - Edit: func(w http.ResponseWriter, r *http.Request) { + Update: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() - params := request.NewOrganisationEdit() + params := request.NewOrganisationUpdate() resputil.JSON(w, params.Fill(r), func() (interface{}, error) { - return oh.Edit(r.Context(), params) + return oh.Update(r.Context(), params) }) }, Remove: func(w http.ResponseWriter, r *http.Request) { @@ -98,7 +98,7 @@ func (oh *Organisation) MountRoutes(r chi.Router, middlewares ...func(http.Handl r.Route("/organisations", func(r chi.Router) { r.Get("/", oh.List) r.Post("/", oh.Create) - r.Put("/{id}", oh.Edit) + r.Put("/{id}", oh.Update) r.Delete("/{id}", oh.Remove) r.Get("/{id}", oh.Read) r.Post("/{id}/archive", oh.Archive) diff --git a/system/rest/handlers/team.go b/system/rest/handlers/team.go index 1afc0751b..31acdfa0c 100644 --- a/system/rest/handlers/team.go +++ b/system/rest/handlers/team.go @@ -29,7 +29,7 @@ import ( type TeamAPI interface { List(context.Context, *request.TeamList) (interface{}, error) Create(context.Context, *request.TeamCreate) (interface{}, error) - Edit(context.Context, *request.TeamEdit) (interface{}, error) + Update(context.Context, *request.TeamUpdate) (interface{}, error) Read(context.Context, *request.TeamRead) (interface{}, error) Remove(context.Context, *request.TeamRemove) (interface{}, error) Archive(context.Context, *request.TeamArchive) (interface{}, error) @@ -43,7 +43,7 @@ type TeamAPI interface { type Team struct { List func(http.ResponseWriter, *http.Request) Create func(http.ResponseWriter, *http.Request) - Edit func(http.ResponseWriter, *http.Request) + Update func(http.ResponseWriter, *http.Request) Read func(http.ResponseWriter, *http.Request) Remove func(http.ResponseWriter, *http.Request) Archive func(http.ResponseWriter, *http.Request) @@ -69,11 +69,11 @@ func NewTeam(th TeamAPI) *Team { return th.Create(r.Context(), params) }) }, - Edit: func(w http.ResponseWriter, r *http.Request) { + Update: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() - params := request.NewTeamEdit() + params := request.NewTeamUpdate() resputil.JSON(w, params.Fill(r), func() (interface{}, error) { - return th.Edit(r.Context(), params) + return th.Update(r.Context(), params) }) }, Read: func(w http.ResponseWriter, r *http.Request) { @@ -134,7 +134,7 @@ func (th *Team) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http r.Route("/teams", func(r chi.Router) { r.Get("/", th.List) r.Post("/", th.Create) - r.Put("/{teamID}", th.Edit) + r.Put("/{teamID}", th.Update) r.Get("/{teamID}", th.Read) r.Delete("/{teamID}", th.Remove) r.Post("/{teamID}/archive", th.Archive) diff --git a/system/rest/handlers/user.go b/system/rest/handlers/user.go index c95862a14..498f22733 100644 --- a/system/rest/handlers/user.go +++ b/system/rest/handlers/user.go @@ -29,7 +29,7 @@ import ( type UserAPI interface { List(context.Context, *request.UserList) (interface{}, error) Create(context.Context, *request.UserCreate) (interface{}, error) - Edit(context.Context, *request.UserEdit) (interface{}, error) + Update(context.Context, *request.UserUpdate) (interface{}, error) Read(context.Context, *request.UserRead) (interface{}, error) Remove(context.Context, *request.UserRemove) (interface{}, error) Suspend(context.Context, *request.UserSuspend) (interface{}, error) @@ -40,7 +40,7 @@ type UserAPI interface { type User struct { List func(http.ResponseWriter, *http.Request) Create func(http.ResponseWriter, *http.Request) - Edit func(http.ResponseWriter, *http.Request) + Update func(http.ResponseWriter, *http.Request) Read func(http.ResponseWriter, *http.Request) Remove func(http.ResponseWriter, *http.Request) Suspend func(http.ResponseWriter, *http.Request) @@ -63,11 +63,11 @@ func NewUser(uh UserAPI) *User { return uh.Create(r.Context(), params) }) }, - Edit: func(w http.ResponseWriter, r *http.Request) { + Update: func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() - params := request.NewUserEdit() + params := request.NewUserUpdate() resputil.JSON(w, params.Fill(r), func() (interface{}, error) { - return uh.Edit(r.Context(), params) + return uh.Update(r.Context(), params) }) }, Read: func(w http.ResponseWriter, r *http.Request) { @@ -107,7 +107,7 @@ func (uh *User) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http r.Route("/users", func(r chi.Router) { r.Get("/", uh.List) r.Post("/", uh.Create) - r.Put("/{userID}", uh.Edit) + r.Put("/{userID}", uh.Update) r.Get("/{userID}", uh.Read) r.Delete("/{userID}", uh.Remove) r.Post("/{userID}/suspend", uh.Suspend) diff --git a/system/rest/organisation.go b/system/rest/organisation.go index 9eb88eb2f..9d4060845 100644 --- a/system/rest/organisation.go +++ b/system/rest/organisation.go @@ -42,7 +42,7 @@ func (ctrl *Organisation) Create(ctx context.Context, r *request.OrganisationCre return ctrl.svc.org.With(ctx).Create(org) } -func (ctrl *Organisation) Edit(ctx context.Context, r *request.OrganisationEdit) (interface{}, error) { +func (ctrl *Organisation) Update(ctx context.Context, r *request.OrganisationUpdate) (interface{}, error) { org := &types.Organisation{ ID: r.ID, Name: r.Name, diff --git a/system/rest/request/organisation.go b/system/rest/request/organisation.go index 88cb4243e..2d9c09f39 100644 --- a/system/rest/request/organisation.go +++ b/system/rest/request/organisation.go @@ -121,17 +121,17 @@ func (o *OrganisationCreate) Fill(r *http.Request) (err error) { var _ RequestFiller = NewOrganisationCreate() -// Organisation edit request parameters -type OrganisationEdit struct { +// Organisation update request parameters +type OrganisationUpdate struct { ID uint64 `json:",string"` Name string } -func NewOrganisationEdit() *OrganisationEdit { - return &OrganisationEdit{} +func NewOrganisationUpdate() *OrganisationUpdate { + return &OrganisationUpdate{} } -func (o *OrganisationEdit) Fill(r *http.Request) (err error) { +func (o *OrganisationUpdate) Fill(r *http.Request) (err error) { if strings.ToLower(r.Header.Get("content-type")) == "application/json" { err = json.NewDecoder(r.Body).Decode(o) @@ -167,7 +167,7 @@ func (o *OrganisationEdit) Fill(r *http.Request) (err error) { return err } -var _ RequestFiller = NewOrganisationEdit() +var _ RequestFiller = NewOrganisationUpdate() // Organisation remove request parameters type OrganisationRemove struct { diff --git a/system/rest/request/team.go b/system/rest/request/team.go index 90753a873..53527959b 100644 --- a/system/rest/request/team.go +++ b/system/rest/request/team.go @@ -123,18 +123,18 @@ func (t *TeamCreate) Fill(r *http.Request) (err error) { var _ RequestFiller = NewTeamCreate() -// Team edit request parameters -type TeamEdit struct { +// Team update request parameters +type TeamUpdate struct { TeamID uint64 `json:",string"` Name string Members []uint64 `json:",string"` } -func NewTeamEdit() *TeamEdit { - return &TeamEdit{} +func NewTeamUpdate() *TeamUpdate { + return &TeamUpdate{} } -func (t *TeamEdit) Fill(r *http.Request) (err error) { +func (t *TeamUpdate) Fill(r *http.Request) (err error) { if strings.ToLower(r.Header.Get("content-type")) == "application/json" { err = json.NewDecoder(r.Body).Decode(t) @@ -171,7 +171,7 @@ func (t *TeamEdit) Fill(r *http.Request) (err error) { return err } -var _ RequestFiller = NewTeamEdit() +var _ RequestFiller = NewTeamUpdate() // Team read request parameters type TeamRead struct { diff --git a/system/rest/request/user.go b/system/rest/request/user.go index 946ba9ca7..c9215f2ea 100644 --- a/system/rest/request/user.go +++ b/system/rest/request/user.go @@ -24,8 +24,6 @@ import ( "github.com/go-chi/chi" "github.com/pkg/errors" - - sqlxTypes "github.com/jmoiron/sqlx/types" ) var _ = chi.URLParam @@ -89,15 +87,10 @@ var _ RequestFiller = NewUserList() // User create request parameters type UserCreate struct { - Email string - Username string - Password string - Name string - Handle string - Kind string - Meta sqlxTypes.JSONText - SatosaID string - OrganisationID uint64 `json:",string"` + Email string + Name string + Handle string + Kind string } func NewUserCreate() *UserCreate { @@ -135,14 +128,6 @@ func (u *UserCreate) Fill(r *http.Request) (err error) { u.Email = val } - if val, ok := post["username"]; ok { - - u.Username = val - } - if val, ok := post["password"]; ok { - - u.Password = val - } if val, ok := post["name"]; ok { u.Name = val @@ -155,45 +140,26 @@ func (u *UserCreate) Fill(r *http.Request) (err error) { u.Kind = val } - if val, ok := post["meta"]; ok { - - if u.Meta, err = parseJSONTextWithErr(val); err != nil { - return err - } - } - if val, ok := post["satosaID"]; ok { - - u.SatosaID = val - } - if val, ok := post["organisationID"]; ok { - - u.OrganisationID = parseUInt64(val) - } return err } var _ RequestFiller = NewUserCreate() -// User edit request parameters -type UserEdit struct { - UserID uint64 `json:",string"` - Email string - Username string - Password string - Name string - Handle string - Kind string - Meta sqlxTypes.JSONText - SatosaID string - OrganisationID uint64 `json:",string"` +// User update request parameters +type UserUpdate struct { + UserID uint64 `json:",string"` + Email string + Name string + Handle string + Kind string } -func NewUserEdit() *UserEdit { - return &UserEdit{} +func NewUserUpdate() *UserUpdate { + return &UserUpdate{} } -func (u *UserEdit) Fill(r *http.Request) (err error) { +func (u *UserUpdate) Fill(r *http.Request) (err error) { if strings.ToLower(r.Header.Get("content-type")) == "application/json" { err = json.NewDecoder(r.Body).Decode(u) @@ -225,14 +191,6 @@ func (u *UserEdit) Fill(r *http.Request) (err error) { u.Email = val } - if val, ok := post["username"]; ok { - - u.Username = val - } - if val, ok := post["password"]; ok { - - u.Password = val - } if val, ok := post["name"]; ok { u.Name = val @@ -245,25 +203,11 @@ func (u *UserEdit) Fill(r *http.Request) (err error) { u.Kind = val } - if val, ok := post["meta"]; ok { - - if u.Meta, err = parseJSONTextWithErr(val); err != nil { - return err - } - } - if val, ok := post["satosaID"]; ok { - - u.SatosaID = val - } - if val, ok := post["organisationID"]; ok { - - u.OrganisationID = parseUInt64(val) - } return err } -var _ RequestFiller = NewUserEdit() +var _ RequestFiller = NewUserUpdate() // User read request parameters type UserRead struct { diff --git a/system/rest/team.go b/system/rest/team.go index 23fa488ac..68ae35a8b 100644 --- a/system/rest/team.go +++ b/system/rest/team.go @@ -42,7 +42,7 @@ func (ctrl *Team) Create(ctx context.Context, r *request.TeamCreate) (interface{ return ctrl.svc.team.With(ctx).Create(org) } -func (ctrl *Team) Edit(ctx context.Context, r *request.TeamEdit) (interface{}, error) { +func (ctrl *Team) Update(ctx context.Context, r *request.TeamUpdate) (interface{}, error) { org := &types.Team{ ID: r.TeamID, Name: r.Name, diff --git a/system/rest/user.go b/system/rest/user.go index 525b148ac..8f3575f10 100644 --- a/system/rest/user.go +++ b/system/rest/user.go @@ -35,36 +35,24 @@ func (ctrl *User) List(ctx context.Context, r *request.UserList) (interface{}, e func (ctrl *User) Create(ctx context.Context, r *request.UserCreate) (interface{}, error) { user := &types.User{ - Email: r.Email, - Username: r.Username, - Name: r.Name, - Handle: r.Handle, - Kind: r.Kind, - Meta: r.Meta, - SatosaID: r.SatosaID, - OrganisationID: r.OrganisationID, - } - if err := user.GeneratePassword(r.Password); err != nil { - return nil, err + Email: r.Email, + Name: r.Name, + Handle: r.Handle, + Kind: r.Kind, } + return ctrl.user.With(ctx).Create(user) } -func (ctrl *User) Edit(ctx context.Context, r *request.UserEdit) (interface{}, error) { +func (ctrl *User) Update(ctx context.Context, r *request.UserUpdate) (interface{}, error) { user := &types.User{ - ID: r.UserID, - Email: r.Email, - Username: r.Username, - Name: r.Name, - Handle: r.Handle, - Kind: r.Kind, - Meta: r.Meta, - SatosaID: r.SatosaID, - OrganisationID: r.OrganisationID, - } - if err := user.GeneratePassword(r.Password); err != nil { - return nil, err + ID: r.UserID, + Email: r.Email, + Name: r.Name, + Handle: r.Handle, + Kind: r.Kind, } + return ctrl.user.With(ctx).Update(user) } diff --git a/system/service/team.go b/system/service/team.go index b5671b422..c2d166b4d 100644 --- a/system/service/team.go +++ b/system/service/team.go @@ -66,11 +66,25 @@ func (svc *team) Create(mod *types.Team) (*types.Team, error) { return svc.team.Create(mod) } -func (svc *team) Update(mod *types.Team) (*types.Team, error) { +func (svc *team) Update(mod *types.Team) (t *types.Team, err error) { // @todo: permission check if current user can add/edit team // @todo: make sure archived & deleted entries can not be edited - return svc.team.Update(mod) + return t, svc.db.Transaction(func() (err error) { + if t, err = svc.team.FindByID(mod.ID); err != nil { + return + } + + // Assign changed values + t.Name = mod.Name + t.Handle = mod.Handle + + if t, err = svc.team.Update(t); err != nil { + return err + } + + return nil + }) } func (svc *team) Delete(id uint64) error { diff --git a/system/service/user.go b/system/service/user.go index 7a0bd8568..9cb0c110e 100644 --- a/system/service/user.go +++ b/system/service/user.go @@ -150,8 +150,25 @@ func (svc *user) Create(input *types.User) (out *types.User, err error) { }) } -func (svc *user) Update(mod *types.User) (*types.User, error) { - return svc.user.Update(mod) +func (svc *user) Update(mod *types.User) (u *types.User, err error) { + return u, svc.db.Transaction(func() (err error) { + if u, err = svc.user.FindByID(mod.ID); err != nil { + return + } + + // Assign changed values + u.Email = mod.Email + u.Username = mod.Username + u.Name = mod.Name + u.Handle = mod.Handle + u.Kind = mod.Kind + + if u, err = svc.user.Update(u); err != nil { + return err + } + + return nil + }) } func (svc *user) canLogin(u *types.User) bool {