From fcd9b88bb7ee193542e277d48d21821db3cacb86 Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Sat, 10 Sep 2022 16:08:24 +0200 Subject: [PATCH] Fix required mismatch in update & create user This shouldn't break the api. --- api/user.go | 31 +++++++++----- docs/spec.json | 108 +++++++++++++++++++++++++++++-------------------- model/user.go | 48 +++++++++++++++++++--- 3 files changed, 128 insertions(+), 59 deletions(-) diff --git a/api/user.go b/api/user.go index 749c276..b27345b 100644 --- a/api/user.go +++ b/api/user.go @@ -147,7 +147,7 @@ func (a *UserAPI) GetCurrentUser(ctx *gin.Context) { // description: the user to add // required: true // schema: -// $ref: "#/definitions/UserWithPass" +// $ref: "#/definitions/CreateUserExternal" // responses: // 200: // description: Ok @@ -166,9 +166,13 @@ func (a *UserAPI) GetCurrentUser(ctx *gin.Context) { // schema: // $ref: "#/definitions/Error" func (a *UserAPI) CreateUser(ctx *gin.Context) { - user := model.UserExternalWithPass{} + user := model.CreateUserExternal{} if err := ctx.Bind(&user); err == nil { - internal := a.toInternalUser(&user, []byte{}) + internal := &model.User{ + Name: user.Name, + Admin: user.Admin, + Pass: password.CreatePassword(user.Pass, a.PasswordStrength), + } existingUser, err := a.DB.GetUserByName(internal.Name) if success := successOrAbort(ctx, 500, err); !success { return @@ -389,7 +393,7 @@ func (a *UserAPI) ChangePassword(ctx *gin.Context) { // description: the updated user // required: true // schema: -// $ref: "#/definitions/UserWithPass" +// $ref: "#/definitions/UpdateUserExternal" // responses: // 200: // description: Ok @@ -413,7 +417,7 @@ func (a *UserAPI) ChangePassword(ctx *gin.Context) { // $ref: "#/definitions/Error" func (a *UserAPI) UpdateUserByID(ctx *gin.Context) { withID(ctx, "id", func(id uint) { - var user *model.UserExternalWithPass + var user *model.UpdateUserExternal if err := ctx.Bind(&user); err == nil { oldUser, err := a.DB.GetUserByID(id) if success := successOrAbort(ctx, 500, err); !success { @@ -428,8 +432,15 @@ func (a *UserAPI) UpdateUserByID(ctx *gin.Context) { ctx.AbortWithError(400, errors.New("cannot delete last admin")) return } - internal := a.toInternalUser(user, oldUser.Pass) - internal.ID = id + internal := &model.User{ + ID: oldUser.ID, + Name: user.Name, + Admin: user.Admin, + Pass: oldUser.Pass, + } + if user.Pass != "" { + internal.Pass = password.CreatePassword(user.Pass, a.PasswordStrength) + } if success := successOrAbort(ctx, 500, a.DB.UpdateUser(internal)); !success { return } @@ -441,13 +452,13 @@ func (a *UserAPI) UpdateUserByID(ctx *gin.Context) { }) } -func (a *UserAPI) toInternalUser(response *model.UserExternalWithPass, pw []byte) *model.User { +func (a *UserAPI) toInternalUser(response *model.UserExternal, newPass string, pw []byte) *model.User { user := &model.User{ Name: response.Name, Admin: response.Admin, } - if response.Pass != "" { - user.Pass = password.CreatePassword(response.Pass, a.PasswordStrength) + if newPass != "" { + user.Pass = password.CreatePassword(newPass, a.PasswordStrength) } else { user.Pass = pw } diff --git a/docs/spec.json b/docs/spec.json index d51a3a7..5d83fd0 100644 --- a/docs/spec.json +++ b/docs/spec.json @@ -1634,7 +1634,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/UserWithPass" + "$ref": "#/definitions/CreateUserExternal" } } ], @@ -1771,7 +1771,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/UserWithPass" + "$ref": "#/definitions/UpdateUserExternal" } } ], @@ -2005,6 +2005,37 @@ }, "x-go-package": "github.com/gotify/server/v2/model" }, + "CreateUserExternal": { + "description": "Used for user creation.", + "type": "object", + "title": "CreateUserExternal Model", + "required": [ + "name", + "admin", + "pass" + ], + "properties": { + "admin": { + "description": "If the user is an administrator.", + "type": "boolean", + "x-go-name": "Admin", + "example": true + }, + "name": { + "description": "The user name. For login.", + "type": "string", + "x-go-name": "Name", + "example": "unicorn" + }, + "pass": { + "description": "The user password. For login.", + "type": "string", + "x-go-name": "Pass", + "example": "nrocinu" + } + }, + "x-go-package": "github.com/gotify/server/v2/model" + }, "Error": { "description": "The Error contains error relevant information.", "type": "object", @@ -2290,13 +2321,44 @@ "x-go-name": "PluginConfExternal", "x-go-package": "github.com/gotify/server/v2/model" }, + "UpdateUserExternal": { + "description": "Used for updating a user.", + "type": "object", + "title": "UpdateUserExternal Model", + "required": [ + "name", + "admin" + ], + "properties": { + "admin": { + "description": "If the user is an administrator.", + "type": "boolean", + "x-go-name": "Admin", + "example": true + }, + "name": { + "description": "The user name. For login.", + "type": "string", + "x-go-name": "Name", + "example": "unicorn" + }, + "pass": { + "description": "The user password. For login. Empty for using old password", + "type": "string", + "x-go-name": "Pass", + "example": "nrocinu" + } + }, + "x-go-package": "github.com/gotify/server/v2/model" + }, "User": { "description": "The User holds information about permission and other stuff.", "type": "object", "title": "UserExternal Model", "required": [ "id", - "name" + "name", + "admin" ], "properties": { "admin": { @@ -2341,46 +2403,6 @@ "x-go-name": "UserExternalPass", "x-go-package": "github.com/gotify/server/v2/model" }, - "UserWithPass": { - "description": "The UserWithPass holds information about the credentials and other stuff.", - "type": "object", - "title": "UserExternalWithPass Model", - "required": [ - "id", - "name", - "pass" - ], - "properties": { - "admin": { - "description": "If the user is an administrator.", - "type": "boolean", - "x-go-name": "Admin", - "example": true - }, - "id": { - "description": "The user id.", - "type": "integer", - "format": "int64", - "x-go-name": "ID", - "readOnly": true, - "example": 25 - }, - "name": { - "description": "The user name. For login.", - "type": "string", - "x-go-name": "Name", - "example": "unicorn" - }, - "pass": { - "description": "The user password. For login.", - "type": "string", - "x-go-name": "Pass", - "example": "nrocinu" - } - }, - "x-go-name": "UserExternalWithPass", - "x-go-package": "github.com/gotify/server/v2/model" - }, "VersionInfo": { "description": "VersionInfo Model", "type": "object", diff --git a/model/user.go b/model/user.go index 308dd05..bde1056 100644 --- a/model/user.go +++ b/model/user.go @@ -30,18 +30,54 @@ type UserExternal struct { Name string `binding:"required" json:"name" query:"name" form:"name"` // If the user is an administrator. // + // required: true // example: true Admin bool `json:"admin" form:"admin" query:"admin"` } -// UserExternalWithPass Model +// CreateUserExternal Model // -// The UserWithPass holds information about the credentials and other stuff. +// Used for user creation. // -// swagger:model UserWithPass -type UserExternalWithPass struct { - UserExternal - UserExternalPass +// swagger:model CreateUserExternal +type CreateUserExternal struct { + // The user name. For login. + // + // required: true + // example: unicorn + Name string `binding:"required" json:"name" query:"name" form:"name"` + // If the user is an administrator. + // + // required: true + // example: true + Admin bool `json:"admin" form:"admin" query:"admin"` + // The user password. For login. + // + // required: true + // example: nrocinu + Pass string `json:"pass,omitempty" form:"pass" query:"pass" binding:"required"` +} + +// UpdateUserExternal Model +// +// Used for updating a user. +// +// swagger:model UpdateUserExternal +type UpdateUserExternal struct { + // The user name. For login. + // + // required: true + // example: unicorn + Name string `binding:"required" json:"name" query:"name" form:"name"` + // If the user is an administrator. + // + // required: true + // example: true + Admin bool `json:"admin" form:"admin" query:"admin"` + // The user password. For login. Empty for using old password + // + // example: nrocinu + Pass string `json:"pass,omitempty" form:"pass" query:"pass"` } // UserExternalPass Model