import full test suite

This commit is contained in:
Tit Petric
2018-07-20 18:08:10 +02:00
parent 3ad1363277
commit 826c5ab7f9
11 changed files with 369 additions and 36 deletions
+20 -2
View File
@@ -13,6 +13,8 @@ import (
"time"
)
var _ = tls.Config{}
type (
Client struct {
Transport *http.Transport
@@ -21,9 +23,21 @@ type (
isDebug bool
config configuration
}
ClientInterface interface {
Users() *Users
Roles() *Roles
Resources() *Resources
Sessions() *Sessions
}
)
func (c *Client) Users() *Users { return &Users{c} }
func (c *Client) Users() *Users { return &Users{c} }
func (c *Client) Roles() *Roles { return &Roles{c} }
func (c *Client) Resources() *Resources { return &Resources{c} }
func (c *Client) Sessions() *Sessions { return &Sessions{c} }
var _ ClientInterface = &Client{}
func New() (*Client, error) {
if err := config.validate(); err != nil {
@@ -38,7 +52,7 @@ func New() (*Client, error) {
}).Dial,
TLSHandshakeTimeout: timeout,
// @todo: === remove this line ===
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
//TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{
@@ -70,6 +84,10 @@ func (c *Client) Post(url string, body interface{}) (*http.Response, error) {
return c.Request("POST", url, body)
}
func (c *Client) Patch(url string, body interface{}) (*http.Response, error) {
return c.Request("PATCH", url, body)
}
func (c *Client) Delete(url string) (*http.Response, error) {
return c.Request("DELETE", url, nil)
}
+17
View File
@@ -0,0 +1,17 @@
package rbac_test
import (
"github.com/crusttech/crust/rbac"
"github.com/namsral/flag"
)
var loaded bool
func getClient() (*rbac.Client, error) {
if !loaded {
rbac.Flags()
flag.Parse()
loaded = true
}
return rbac.New()
}
+56
View File
@@ -0,0 +1,56 @@
package rbac
import (
"fmt"
"github.com/pkg/errors"
)
type (
Resources struct {
*Client
}
ResourcesInterface interface {
Create(resourceID string, operations []string) error
Delete(resourceID string) error
}
)
const (
resourcesCreate = "/resources/%s"
resourcesDelete = "/resources/%s"
)
func (u *Resources) Create(resourceID string, operations []string) error {
body := struct {
Operations []string `json:"operations"`
}{operations}
resp, err := u.Client.Post(fmt.Sprintf(resourcesCreate, resourceID), body)
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
func (u *Resources) Delete(resourceID string) error {
resp, err := u.Client.Delete(fmt.Sprintf(resourcesCreate, resourceID))
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
var _ ResourcesInterface = &Resources{}
+28
View File
@@ -0,0 +1,28 @@
package rbac_test
import (
"testing"
)
func TestResources(t *testing.T) {
rbac, err := getClient()
if err != nil {
t.Errorf("Unexpected error when creating RBAC instance: %+v", err)
}
rbac.Debug(false)
resources := rbac.Resources()
resources.Delete("test-resource")
if err := resources.Create("test-resource", []string{"view", "edit", "delete"}); err != nil {
t.Errorf("Error when creating test-resource, %+v", err)
}
if err := resources.Delete("test-resource"); err != nil {
t.Errorf("Unexpected error deleting a resource, %+v", err)
}
if err := resources.Delete("test-resource"); err == nil {
t.Errorf("Expected error when deleting unexistant resource, got none")
}
}
+52
View File
@@ -0,0 +1,52 @@
package rbac
import (
"fmt"
"github.com/pkg/errors"
)
type (
Roles struct {
*Client
}
RolesInterface interface {
Create(role string) error
Delete(role string) error
}
)
const (
rolesCreate = "/roles/%s"
rolesDelete = "/roles/%s"
)
func (u *Roles) Create(role string) error {
resp, err := u.Client.Post(fmt.Sprintf(rolesCreate, role), nil)
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
func (u *Roles) Delete(role string) error {
resp, err := u.Client.Delete(fmt.Sprintf(rolesDelete, role))
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
var _ RolesInterface = &Roles{}
+28
View File
@@ -0,0 +1,28 @@
package rbac_test
import (
"testing"
)
func TestRoles(t *testing.T) {
rbac, err := getClient()
if err != nil {
t.Errorf("Unexpected error when creating RBAC instance: %+v", err)
}
rbac.Debug(false)
roles := rbac.Roles()
roles.Delete("test-role")
if err := roles.Create("test-role"); err != nil {
t.Errorf("Error when creating test-role: %+v", err)
}
if err := roles.Delete("test-role"); err != nil {
t.Errorf("Error when deleting test-role: %+v", err)
}
if err := roles.Delete("non-existant"); err == nil {
t.Errorf("Expected error on deleting a non-existant role")
}
}
+76
View File
@@ -0,0 +1,76 @@
package rbac
import (
"encoding/json"
"fmt"
"github.com/crusttech/crust/rbac/types"
"github.com/pkg/errors"
)
type (
Sessions struct {
*Client
}
SessionsInterface interface {
Create(sessionID string, username string, roles []string) error
Get(sessionID string) (*types.Session, error)
Delete(sessionID string) error
}
)
const (
sessionsCreate = "/sessions/%s"
sessionsGet = "/sessions/%s"
sessionsDelete = "/sessions/%s"
)
func (u *Sessions) Create(sessionID string, username string, roles []string) error {
body := struct {
Username string `json:"username"`
Roles []string `json:"roles,omitempty"`
}{username, roles}
resp, err := u.Client.Post(fmt.Sprintf(sessionsCreate, sessionID), body)
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
func (u *Sessions) Get(sessionID string) (*types.Session, error) {
resp, err := u.Client.Get(fmt.Sprintf(sessionsGet, sessionID))
if err != nil {
return nil, errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
session := &types.Session{}
return session, errors.Wrap(json.NewDecoder(resp.Body).Decode(session), "decoding json failed")
default:
return nil, toError(resp)
}
}
func (u *Sessions) Delete(sessionID string) error {
resp, err := u.Client.Delete(fmt.Sprintf(sessionsDelete, sessionID))
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
var _ SessionsInterface = &Sessions{}
+38
View File
@@ -0,0 +1,38 @@
package rbac_test
import (
"testing"
)
func TestSessions(t *testing.T) {
rbac, err := getClient()
if err != nil {
t.Errorf("Unexpected error when creating RBAC instance: %+v", err)
}
rbac.Debug(false)
sessions := rbac.Sessions()
users := rbac.Users()
// clean up data
users.Delete("test-user")
sessions.Delete("test-session")
if err := users.Create("test-user", "test-password"); err != nil {
t.Errorf("Unexpected error when creating test-user, %+v", err)
return
}
if err := sessions.Create("test-session", "test-user", []string{}); err != nil {
t.Errorf("Unexpected error when creating test-session, %+v", err)
}
if _, err := sessions.Get("test-session"); err != nil {
t.Errorf("Unexpected error when getting test-session, %+v", err)
}
if err := sessions.Delete("test-session"); err != nil {
t.Errorf("Unexpected error when deleting test-session, %+v", err)
}
// Write tests (need users, roles)
}
+6 -1
View File
@@ -2,6 +2,11 @@ package types
type (
User struct {
username string
Username string `json:"username"`
}
Session struct {
Username string `json:"username"`
Roles []string `json:"roles"`
}
)
+38
View File
@@ -15,6 +15,8 @@ type (
Create(username, password string) error
Get(username string) (*types.User, error)
Delete(username string) error
Assign(username string, roles []string) error
}
)
@@ -36,6 +38,42 @@ func (u *Users) Create(username, password string) error {
}
}
func (u *Users) Assign(username string, roles []string) error {
body := struct {
Roles []string `json:"roles"`
}{roles}
resp, err := u.Client.Patch("/users/"+username+"/assignRoles", body)
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
func (u *Users) Deassign(username string, roles []string) error {
body := struct {
Roles []string `json:"roles"`
}{roles}
resp, err := u.Client.Patch("/users/"+username+"/deassignRoles", body)
if err != nil {
return errors.Wrap(err, "request failed")
}
defer resp.Body.Close()
switch resp.StatusCode {
case 200:
return nil
default:
return toError(resp)
}
}
func (u *Users) Get(username string) (*types.User, error) {
resp, err := u.Client.Get("/users/" + username)
if err != nil {
+10 -33
View File
@@ -1,55 +1,32 @@
package rbac_test
import (
"os"
"testing"
"github.com/crusttech/crust/rbac"
"github.com/namsral/flag"
)
var _ = os.Setenv
func TestUsers(t *testing.T) {
rbac.Flags()
flag.Parse()
rbac, err := rbac.New()
rbac, err := getClient()
if err != nil {
t.Errorf("Unexpected error when creating RBAC instance: %+v", err)
}
rbac.Debug(false)
users := rbac.Users()
users.Delete("test-user")
// clean up env
{
// just making sure we don't have one
// and we're ignoring possible err's
users.Delete("test-user")
if err := users.Create("test-user", "test-password"); err != nil {
t.Errorf("Error when creating test-user: %+v", err)
}
// create a user
{
err := users.Create("test-user", "test-password")
if err != nil {
t.Errorf("Error when creating test-user: %+v", err)
}
if err := users.Delete("test-user"); err != nil {
t.Errorf("Error when deleting test-user: %+v", err)
}
// delete a user
{
err := users.Delete("test-user")
if err != nil {
t.Errorf("Error when deleting test-user: %+v", err)
}
if _, err := users.Get("non-existant"); err == nil {
t.Errorf("Expected error on retrieving a non-existant user")
}
// check getting a non-existant user fails
{
_, err := users.Get("non-existant")
if err == nil {
t.Errorf("Expected error on retrieving a non-existant user")
}
if err := users.Delete("non-existant"); err == nil {
t.Errorf("Expected error on deleting a non-existant user")
}
}