Skip to content

Commit

Permalink
rework access to use options, added permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
luthermonson committed Aug 20, 2023
1 parent 205042b commit 29c54ea
Show file tree
Hide file tree
Showing 10 changed files with 579 additions and 51 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ around this library to make that easier.
## Usage
Create a client and use the public methods to access Proxmox resources.

### Basic usage with login credentials
### Basic usage with login with a username and password credential
```go
package main

Expand All @@ -37,15 +37,19 @@ import (
)

func main() {
client := proxmox.NewClient("https://localhost:8006/api2/json")
if err := client.Login("root@pam", "password"); err != nil {
panic(err)
credentials := proxmox.Credentials{
Username: "root@pam",
Password: "12345",
}
client := proxmox.NewClient("https://localhost:8006/api2/json",
proxmox.WithCredentials(&credentials),
)

version, err := client.Version()
if err != nil {
panic(err)
}
fmt.Println(version.Release) // 6.3
fmt.Println(version.Release) // 7.4
}
```

Expand All @@ -70,7 +74,7 @@ func main() {
secret := "somegeneratedapitokenguidefromtheproxmoxui"

client := proxmox.NewClient("https://localhost:8006/api2/json",
proxmox.WithClient(&insecureHTTPClient),
proxmox.WithHTTPClient(&insecureHTTPClient),
proxmox.WithAPIToken(tokenID, secret),
)

Expand Down
21 changes: 21 additions & 0 deletions access.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package proxmox

import (
"fmt"
"net/url"
)

// Deprecated: Use WithCredentials Option
func (c *Client) Login(username, password string) error {
_, err := c.Ticket(&Credentials{
Username: username,
Expand All @@ -13,10 +15,29 @@ func (c *Client) Login(username, password string) error {
return err
}

// Deprecated: Use the WithAPIToken Option
func (c *Client) APIToken(tokenID, secret string) {
c.token = fmt.Sprintf("%s=%s", tokenID, secret)
}

func (c *Client) Ticket(credentials *Credentials) (*Session, error) {
return c.session, c.Post("/access/ticket", credentials, &c.session)
}

// Permissions get permissions for the current user for the client which passes no params, use Permission
func (c *Client) Permissions(o *PermissionsOptions) (permissions Permissions, err error) {
u := url.URL{Path: "/access/permissions"}

if o != nil { // params are optional
params := url.Values{}
if o.UserID != "" {
params.Add("userid", o.UserID)
}
if o.Path != "" {
params.Add("path", o.Path)
}
u.RawQuery = params.Encode()
}

return permissions, c.Get(u.String(), &permissions)
}
59 changes: 59 additions & 0 deletions access_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package proxmox

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/luthermonson/go-proxmox/tests/mocks"
)

func TestTicket(t *testing.T) {
mocks.On(mockConfig)
defer mocks.Off()

// todo current mocks are hardcoded with test data, make configurable via mock config
client := mockClient(WithCredentials(
&Credentials{
Username: "root@pam",
Password: "1234",
}))

session, err := client.Ticket(client.credentials)
assert.Nil(t, err)
assert.Equal(t, "root@pam", session.Username)
assert.Equal(t, "pve-cluster", session.ClusterName)
}

func TestPermissions(t *testing.T) {
mocks.On(mockConfig)
defer mocks.Off()
client := mockClient()

perms, err := client.Permissions(nil)
assert.Nil(t, err)
assert.Equal(t, 8, len(perms))
assert.Equal(t, 1, perms["/"]["Datastore.Allocate"])

// test path option
perms, err = client.Permissions(&PermissionsOptions{
Path: "path",
})
assert.Nil(t, err)
assert.Equal(t, 1, perms["path"]["permission"])

// test userid
perms, err = client.Permissions(&PermissionsOptions{
UserID: "userid",
})
assert.Nil(t, err)
assert.Equal(t, 2, perms["path"]["permission"])

// test both path and userid
perms, err = client.Permissions(&PermissionsOptions{
UserID: "userid",
Path: "path",
})
assert.Nil(t, err)
assert.Equal(t, 3, perms["path"]["permission"])
}
22 changes: 16 additions & 6 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,28 @@ import (

type Option func(*Client)

// Deprecated: Use WithHTTPClient
func WithClient(client *http.Client) Option {
return WithHTTPClient(client)
}

func WithHTTPClient(client *http.Client) Option {
return func(c *Client) {
c.httpClient = client
}
}

// Deprecated: Use WithCredential
func WithLogins(username, password string) Option {
return WithCredentials(&Credentials{
Username: username,
Password: password,
})
}

func WithCredentials(credentials *Credentials) Option {
return func(c *Client) {
c.credentials = &Credentials{
Username: username,
Password: password,
}
c.credentials = credentials
}
}

Expand All @@ -29,11 +39,11 @@ func WithAPIToken(tokenID, secret string) Option {
}

// WithSession experimental
func WithSession(ticket, csrfPreventionToken string) Option {
func WithSession(ticket, CSRFPreventionToken string) Option {
return func(c *Client) {
c.session = &Session{
Ticket: ticket,
CsrfPreventionToken: csrfPreventionToken,
CSRFPreventionToken: CSRFPreventionToken,
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,22 @@ func TestWithLogins(t *testing.T) {
assert.Equal(t, client.credentials, &Credentials{Username: "root@pam", Password: "1234"})
}

func TestWithCredentials(t *testing.T) {
client := NewClient("", WithCredentials(&Credentials{
Username: "root@pam",
Password: "1234",
}))
assert.Equal(t, client.credentials, &Credentials{Username: "root@pam", Password: "1234"})
}

func TestWithAPIToken(t *testing.T) {
client := NewClient("", WithAPIToken("root@pam!test", "1234"))
assert.Equal(t, client.token, "root@pam!test=1234")
}

func TestWithSession(t *testing.T) {
client := NewClient("", WithSession("ticket", "csrf"))
assert.Equal(t, client.session, &Session{Ticket: "ticket", CsrfPreventionToken: "csrf"})
assert.Equal(t, client.session, &Session{Ticket: "ticket", CSRFPreventionToken: "csrf"})
}

func TestWithUserAgent(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion proxmox.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (c *Client) authHeaders(header *http.Header) {
header.Add("Authorization", "PVEAPIToken="+c.token)
} else if c.session != nil {
header.Add("Cookie", "PVEAuthCookie="+c.session.Ticket)
header.Add("CSRFPreventionToken", c.session.CsrfPreventionToken)
header.Add("CSRFPreventionToken", c.session.CSRFPreventionToken)
}
}

Expand Down
4 changes: 4 additions & 0 deletions proxmox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func mockClient(options ...Option) *Client {
return NewClient(mockConfig.URI, options...)
}

func TestMakeTag(t *testing.T) {
assert.Equal(t, "go-proxmox+tagname", MakeTag("tagname"))
}

// options tested in options_test.go
func TestNewClient(t *testing.T) {
v := NewClient(TestURI)
Expand Down
31 changes: 0 additions & 31 deletions tests/integration/access_test.go
Original file line number Diff line number Diff line change
@@ -1,32 +1 @@
package integration

import (
"testing"

"github.com/luthermonson/go-proxmox"
"github.com/stretchr/testify/assert"
)

func TestLogin(t *testing.T) {
client := ClientFromEnv()
_, err := client.Version()
assert.True(t, proxmox.IsNotAuthorized(err))

err = client.Login(td.username, td.password)
assert.Nil(t, err)

version, err := client.Version()
assert.Nil(t, err)
assert.NotEmpty(t, version.Version)
}

func TestAPIToken(t *testing.T) {
client := ClientFromEnv()
_, err := client.Version()
assert.True(t, proxmox.IsNotAuthorized(err))

client.APIToken(td.tokenID, td.secret)
version, err := client.Version()
assert.Nil(t, err)
assert.NotNil(t, version.Version)
}
Loading

0 comments on commit 29c54ea

Please sign in to comment.