Skip to content

Commit

Permalink
Return Empty Lists (#30)
Browse files Browse the repository at this point in the history
When an acestor doesn't exist, e.g. the organization hasn't been created
yet by project creation.  Makes UI handling far simpler.
  • Loading branch information
spjmurray authored Mar 20, 2024
1 parent 9310824 commit b10a4fa
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 10 deletions.
4 changes: 2 additions & 2 deletions charts/unikorn/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Helm chart for deploying Unikorn

type: application

version: v0.1.10
appVersion: v0.1.10
version: v0.1.11
appVersion: v0.1.11

icon: https://raw.githubusercontent.com/unikorn-cloud/unikorn/main/icons/default.png
6 changes: 5 additions & 1 deletion pkg/server/handler/cluster/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,17 @@ func NewClient(client client.Client, options *Options) *Client {
}

// List returns all clusters owned by the implicit control plane.
func (c *Client) List(ctx context.Context, organizationName string) ([]*generated.KubernetesCluster, error) {
func (c *Client) List(ctx context.Context, organizationName string) (generated.KubernetesClusters, error) {
selector := labels.NewSelector()

// TODO: a super-admin isn't scoped to a single organization!
// TODO: RBAC - filter projects based on user membership here.
organization, err := organization.NewClient(c.client).GetMetadata(ctx, organizationName)
if err != nil {
if errors.IsHTTPNotFound(err) {
return generated.KubernetesClusters{}, nil
}

return nil, err
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/server/handler/cluster/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,16 @@ func (c *Client) convert(in *unikornv1.KubernetesCluster) (*generated.Kubernetes
}

// uconvertList converts from a custom resource list into the API definition.
func (c *Client) convertList(in *unikornv1.KubernetesClusterList) ([]*generated.KubernetesCluster, error) {
out := make([]*generated.KubernetesCluster, len(in.Items))
func (c *Client) convertList(in *unikornv1.KubernetesClusterList) (generated.KubernetesClusters, error) {
out := make(generated.KubernetesClusters, len(in.Items))

for i := range in.Items {
item, err := c.convert(&in.Items[i])
if err != nil {
return nil, err
}

out[i] = item
out[i] = *item
}

return out, nil
Expand Down
12 changes: 8 additions & 4 deletions pkg/server/handler/clustermanager/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,29 +220,33 @@ func (c *Client) convert(in *unikornv1.ClusterManager) (*generated.ClusterManage
}

// convertList converts from Kubernetes into OpenAPI types.
func (c *Client) convertList(in *unikornv1.ClusterManagerList) ([]*generated.ClusterManager, error) {
out := make([]*generated.ClusterManager, len(in.Items))
func (c *Client) convertList(in *unikornv1.ClusterManagerList) (generated.ClusterManagers, error) {
out := make(generated.ClusterManagers, len(in.Items))

for i := range in.Items {
item, err := c.convert(&in.Items[i])
if err != nil {
return nil, err
}

out[i] = item
out[i] = *item
}

return out, nil
}

// List returns all control planes.
func (c *Client) List(ctx context.Context, organizationName string) ([]*generated.ClusterManager, error) {
func (c *Client) List(ctx context.Context, organizationName string) (generated.ClusterManagers, error) {
selector := labels.NewSelector()

// TODO: a super-admin isn't scoped to a single organization!
// TODO: RBAC - filter projects based on user membership here.
organization, err := organization.NewClient(c.client).GetMetadata(ctx, organizationName)
if err != nil {
if errors.IsHTTPNotFound(err) {
return generated.ClusterManagers{}, nil
}

return nil, err
}

Expand Down
48 changes: 48 additions & 0 deletions pkg/server/handler/project/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import (
goerrors "errors"
"slices"

"github.com/go-jose/go-jose/v3/jwt"

unikornv1core "github.com/unikorn-cloud/core/pkg/apis/unikorn/v1alpha1"
"github.com/unikorn-cloud/core/pkg/authorization/roles"
"github.com/unikorn-cloud/core/pkg/authorization/userinfo"
"github.com/unikorn-cloud/core/pkg/constants"
"github.com/unikorn-cloud/core/pkg/server/errors"
unikornv1 "github.com/unikorn-cloud/unikorn/pkg/apis/unikorn/v1alpha1"
Expand All @@ -33,6 +37,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
)

// Client wraps up project related management handling.
Expand Down Expand Up @@ -137,6 +142,37 @@ func convertList(in *unikornv1.ProjectList) generated.Projects {
return out
}

// GroupPermissions are privilege grants for a project.
type GroupPermissions struct {
// ID is the unique, immutable project identifier.
ID string `json:"id"`
// Roles are the privileges a user has for the group.
Roles []roles.Role `json:"roles"`
}

// OrganizationPermissions are privilege grants for an organization.
type OrganizationPermissions struct {
// IsAdmin allows the user to play with all resources in an organization.
IsAdmin bool `json:"isAdmin,omitempty"`
// Name is the name of the organization.
Name string `json:"name"`
// Groups are any groups the user belongs to in an organization.
Groups []GroupPermissions `json:"groups,omitempty"`
}

// Permissions are privilege grants for the entire system.
type Permissions struct {
// IsSuperAdmin HAS SUPER COW POWERS!!!
IsSuperAdmin bool `json:"isSuperAdmin,omitempty"`
// Organizations are any organizations the user has access to.
Organizations []OrganizationPermissions `json:"organizations,omitempty"`
}

type UserInfoType struct {
jwt.Claims
Permissions *Permissions `json:"permissions,omitempty"`
}

func (c *Client) List(ctx context.Context, organizationName string) (generated.Projects, error) {
organization, err := organization.NewClient(c.client).GetMetadata(ctx, organizationName)
if err != nil {
Expand All @@ -149,6 +185,18 @@ func (c *Client) List(ctx context.Context, organizationName string) (generated.P
return nil, err
}

ui := userinfo.FromContext(ctx)

userinfo := &UserInfoType{}

if err := ui.Claims(userinfo); err != nil {
return nil, errors.OAuth2ServerError("failed to extract claims").WithError(err)
}

log := log.FromContext(ctx)

log.Info("rbac", "userinfo", userinfo)

result := &unikornv1.ProjectList{}

if err := c.client.List(ctx, result, &client.ListOptions{Namespace: organization.Namespace}); err != nil {
Expand Down

0 comments on commit b10a4fa

Please sign in to comment.