[GH-ISSUE #215] (u *User) Update function does not follow API spec, always fails #61

Closed
opened 2026-03-03 15:29:57 +03:00 by kerem · 0 comments
Owner

Originally created by @kernel-sanders on GitHub (Sep 11, 2025).
Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/215

The user update function sends the full user object (a client plus every value return from a GET request) however a PUT requires we send a subset of this, and fails when extra fields are sent (i.e. tokens). Without a new struct to send, the current user update function always results in a 400 error.

GET /access/users/{userid} API docs:

Image

User struct from types.go:

type User struct {
	client         *Client
	UserID         string           `json:"userid,omitempty"`
	Comment        string           `json:"comment,omitempty"`
	Email          string           `json:"email,omitempty"`
	Enable         IntOrBool        `json:"enable"`
	Expire         int              `json:"expire,omitempty"`
	Firstname      string           `json:"firstname,omitempty"`
	Lastname       string           `json:"lastname,omitempty"`
	Groups         []string         `json:"groups,omitempty"`
	Keys           string           `json:"keys,omitempty"`
	Tokens         map[string]Token `json:"tokens,omitempty"`
	RealmType      string           `json:"realm-type,omitempty"`
	TFALockedUntil string           `json:"tfa-locked-until,omitempty"`
	TOTPLocked     IntOrBool        `json:"totp-locked,omitempty"`
}

PUT /access/users/{userid} API docs:

Image

The current user update function from access.go simply PUTs the entire user struct

func (u *User) Update(ctx context.Context) error {
	return u.client.Put(ctx, fmt.Sprintf("/access/users/%s", u.UserID), u, nil)
}

UserOptions (would need to be created) struct to match the PUT API requirements:

// You only need to send the fields you want to update
type UserOptions struct {
	Append    IntOrBool `json:"append,omitempty"`
	Comment   string    `json:"comment,omitempty"`
	Email     string    `json:"email,omitempty"`
	Enable    IntOrBool `json:"enable"`
	Expire    int       `json:"expire,omitempty"`
	Firstname string    `json:"firstname,omitempty"`
	Groups    []string  `json:"groups,omitempty"`
	Keys      string    `json:"keys,omitempty"`
	Lastname  string    `json:"lastname,omitempty"`
}

The user update function would need to be updated to:

func (u *User) Update(ctx context.Context, options UserOptions) error {
	return u.client.Put(ctx, fmt.Sprintf("/access/users/%s", u.UserID), &options, nil)
}
Originally created by @kernel-sanders on GitHub (Sep 11, 2025). Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/215 The user update function sends the full user object (a client plus every value return from a GET request) however a PUT requires we send a subset of this, and fails when extra fields are sent (i.e. `tokens`). Without a new struct to send, the current user update function always results in a 400 error. GET /access/users/{userid} [API docs](https://pve.proxmox.com/pve-docs/api-viewer/#/access/users/{userid}): <img width="1072" height="842" alt="Image" src="https://github.com/user-attachments/assets/9ed6479f-b29e-4c83-8eee-8effcc86a9d7" /> User struct from types.go: ``` type User struct { client *Client UserID string `json:"userid,omitempty"` Comment string `json:"comment,omitempty"` Email string `json:"email,omitempty"` Enable IntOrBool `json:"enable"` Expire int `json:"expire,omitempty"` Firstname string `json:"firstname,omitempty"` Lastname string `json:"lastname,omitempty"` Groups []string `json:"groups,omitempty"` Keys string `json:"keys,omitempty"` Tokens map[string]Token `json:"tokens,omitempty"` RealmType string `json:"realm-type,omitempty"` TFALockedUntil string `json:"tfa-locked-until,omitempty"` TOTPLocked IntOrBool `json:"totp-locked,omitempty"` } ``` PUT /access/users/{userid} [API docs](https://pve.proxmox.com/pve-docs/api-viewer/#/access/users/{userid}): <img width="996" height="852" alt="Image" src="https://github.com/user-attachments/assets/d0f57383-92b9-4142-ad6b-74f34014fdf0" /> The current user update function from [access.go](https://github.com/luthermonson/go-proxmox/blob/main/access.go#L168C1-L170C2) simply PUTs the entire user struct ``` func (u *User) Update(ctx context.Context) error { return u.client.Put(ctx, fmt.Sprintf("/access/users/%s", u.UserID), u, nil) } ``` UserOptions (would need to be created) struct to match the PUT API requirements: ``` // You only need to send the fields you want to update type UserOptions struct { Append IntOrBool `json:"append,omitempty"` Comment string `json:"comment,omitempty"` Email string `json:"email,omitempty"` Enable IntOrBool `json:"enable"` Expire int `json:"expire,omitempty"` Firstname string `json:"firstname,omitempty"` Groups []string `json:"groups,omitempty"` Keys string `json:"keys,omitempty"` Lastname string `json:"lastname,omitempty"` } ``` The user update function would need to be updated to: ``` func (u *User) Update(ctx context.Context, options UserOptions) error { return u.client.Put(ctx, fmt.Sprintf("/access/users/%s", u.UserID), &options, nil) } ```
kerem closed this issue 2026-03-03 15:29:57 +03:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/go-proxmox#61
No description provided.