Implement support for labels on system resources
This commit is contained in:
@@ -12,6 +12,10 @@ func (s Store) convertApplicationFilter(f types.ApplicationFilter) (query squirr
|
||||
|
||||
query = filter.StateCondition(query, "app.deleted_at", f.Deleted)
|
||||
|
||||
if len(f.LabeledIDs) > 0 {
|
||||
query = query.Where(squirrel.Eq{"app.id": f.LabeledIDs})
|
||||
}
|
||||
|
||||
if f.Query != "" {
|
||||
qs := f.Query + "%"
|
||||
query = query.Where(squirrel.Or{
|
||||
|
||||
@@ -17,6 +17,10 @@ func (s Store) convertRoleFilter(f types.RoleFilter) (query squirrel.SelectBuild
|
||||
query = query.Where(squirrel.Eq{"rl.ID": f.RoleID})
|
||||
}
|
||||
|
||||
if len(f.LabeledIDs) > 0 {
|
||||
query = query.Where(squirrel.Eq{"rl.id": f.LabeledIDs})
|
||||
}
|
||||
|
||||
if f.MemberID > 0 {
|
||||
query = query.Where(squirrel.Expr("rl.ID IN (SELECT rel_role FROM role_members AS m WHERE m.rel_user = ?)", f.MemberID))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ func (s Store) convertUserFilter(f types.UserFilter) (query squirrel.SelectBuild
|
||||
query = query.Where(squirrel.Eq{"usr.ID": f.UserID})
|
||||
}
|
||||
|
||||
if len(f.LabeledIDs) > 0 {
|
||||
query = query.Where(squirrel.Eq{"usr.id": f.LabeledIDs})
|
||||
}
|
||||
|
||||
if len(f.RoleID) > 0 {
|
||||
or := squirrel.Or{}
|
||||
// Due to lack of support for more exotic expressions (slice of values inside subquery)
|
||||
|
||||
@@ -234,6 +234,8 @@ endpoints:
|
||||
authentication:
|
||||
- Client ID
|
||||
- Session ID
|
||||
imports:
|
||||
- github.com/cortezaproject/corteza-server/pkg/label
|
||||
apis:
|
||||
- name: list
|
||||
method: GET
|
||||
@@ -253,6 +255,10 @@ endpoints:
|
||||
required: false
|
||||
title: Exclude (0, default), include (1) or return only (2) achived roles
|
||||
type: uint
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- type: uint
|
||||
name: limit
|
||||
title: Limit
|
||||
@@ -280,6 +286,10 @@ endpoints:
|
||||
name: members
|
||||
required: false
|
||||
title: Role member IDs
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- name: update
|
||||
method: PUT
|
||||
title: Update role details
|
||||
@@ -303,6 +313,10 @@ endpoints:
|
||||
name: members
|
||||
required: false
|
||||
title: Role member IDs
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- name: read
|
||||
method: GET
|
||||
title: Read role details and memberships
|
||||
@@ -443,6 +457,7 @@ endpoints:
|
||||
- Client ID
|
||||
- Session ID
|
||||
imports:
|
||||
- github.com/cortezaproject/corteza-server/pkg/label
|
||||
- github.com/cortezaproject/corteza-server/system/types
|
||||
apis:
|
||||
- name: list
|
||||
@@ -495,6 +510,10 @@ endpoints:
|
||||
required: false
|
||||
title: Exclude (0, default), include (1) or return only (2) suspended users
|
||||
type: uint
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- type: uint
|
||||
name: limit
|
||||
title: Limit
|
||||
@@ -526,6 +545,10 @@ endpoints:
|
||||
type: types.UserKind
|
||||
required: false
|
||||
title: Kind (normal, bot)
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- name: update
|
||||
method: PUT
|
||||
title: Update user details
|
||||
@@ -553,6 +576,10 @@ endpoints:
|
||||
type: types.UserKind
|
||||
required: false
|
||||
title: Kind (normal, bot)
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- name: read
|
||||
method: GET
|
||||
title: Read user details
|
||||
@@ -677,6 +704,7 @@ endpoints:
|
||||
entrypoint: application
|
||||
authentication: []
|
||||
imports:
|
||||
- github.com/cortezaproject/corteza-server/pkg/label
|
||||
- sqlxTypes github.com/jmoiron/sqlx/types
|
||||
apis:
|
||||
- name: list
|
||||
@@ -697,6 +725,10 @@ endpoints:
|
||||
required: false
|
||||
title: Exclude (0, default), include (1) or return only (2) deleted roles
|
||||
type: uint
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- type: uint
|
||||
name: limit
|
||||
title: Limit
|
||||
@@ -728,6 +760,10 @@ endpoints:
|
||||
type: sqlxTypes.JSONText
|
||||
required: false
|
||||
title: Arbitrary JSON holding application configuration
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- name: update
|
||||
method: PUT
|
||||
title: Update user details
|
||||
@@ -755,6 +791,10 @@ endpoints:
|
||||
type: sqlxTypes.JSONText
|
||||
required: false
|
||||
title: Arbitrary JSON holding application configuration
|
||||
- type: map[string]string
|
||||
name: labels
|
||||
title: Labels
|
||||
parser: label.ParseStrings
|
||||
- name: read
|
||||
method: GET
|
||||
title: Read application details
|
||||
|
||||
@@ -61,8 +61,9 @@ func (ctrl *Application) List(ctx context.Context, r *request.ApplicationList) (
|
||||
var (
|
||||
err error
|
||||
f = types.ApplicationFilter{
|
||||
Name: r.Name,
|
||||
Query: r.Query,
|
||||
Name: r.Name,
|
||||
Query: r.Query,
|
||||
Labels: r.Labels,
|
||||
|
||||
Deleted: filter.State(r.Deleted),
|
||||
}
|
||||
@@ -86,6 +87,7 @@ func (ctrl *Application) Create(ctx context.Context, r *request.ApplicationCreat
|
||||
app = &types.Application{
|
||||
Name: r.Name,
|
||||
Enabled: r.Enabled,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -107,6 +109,7 @@ func (ctrl *Application) Update(ctx context.Context, r *request.ApplicationUpdat
|
||||
ID: r.ApplicationID,
|
||||
Name: r.Name,
|
||||
Enabled: r.Enabled,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ package request
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/pkg/payload"
|
||||
"github.com/go-chi/chi"
|
||||
sqlxTypes "github.com/jmoiron/sqlx/types"
|
||||
@@ -46,6 +47,11 @@ type (
|
||||
// Exclude (0, default), include (1) or return only (2) deleted roles
|
||||
Deleted uint
|
||||
|
||||
// Labels GET parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
|
||||
// Limit GET parameter
|
||||
//
|
||||
// Limit
|
||||
@@ -82,6 +88,11 @@ type (
|
||||
//
|
||||
// Arbitrary JSON holding application configuration
|
||||
Config sqlxTypes.JSONText
|
||||
|
||||
// Labels POST parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
ApplicationUpdate struct {
|
||||
@@ -109,6 +120,11 @@ type (
|
||||
//
|
||||
// Arbitrary JSON holding application configuration
|
||||
Config sqlxTypes.JSONText
|
||||
|
||||
// Labels POST parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
ApplicationRead struct {
|
||||
@@ -156,6 +172,7 @@ func (r ApplicationList) Auditable() map[string]interface{} {
|
||||
"name": r.Name,
|
||||
"query": r.Query,
|
||||
"deleted": r.Deleted,
|
||||
"labels": r.Labels,
|
||||
"limit": r.Limit,
|
||||
"pageCursor": r.PageCursor,
|
||||
"sort": r.Sort,
|
||||
@@ -177,6 +194,11 @@ func (r ApplicationList) GetDeleted() uint {
|
||||
return r.Deleted
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationList) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationList) GetLimit() uint {
|
||||
return r.Limit
|
||||
@@ -227,6 +249,17 @@ func (r *ApplicationList) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := tmp["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := tmp["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := tmp["limit"]; ok && len(val) > 0 {
|
||||
r.Limit, err = payload.ParseUint(val[0]), nil
|
||||
if err != nil {
|
||||
@@ -262,6 +295,7 @@ func (r ApplicationCreate) Auditable() map[string]interface{} {
|
||||
"enabled": r.Enabled,
|
||||
"unify": r.Unify,
|
||||
"config": r.Config,
|
||||
"labels": r.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +319,11 @@ func (r ApplicationCreate) GetConfig() sqlxTypes.JSONText {
|
||||
return r.Config
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationCreate) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *ApplicationCreate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
@@ -332,6 +371,18 @@ func (r *ApplicationCreate) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := req.Form["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -350,6 +401,7 @@ func (r ApplicationUpdate) Auditable() map[string]interface{} {
|
||||
"enabled": r.Enabled,
|
||||
"unify": r.Unify,
|
||||
"config": r.Config,
|
||||
"labels": r.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,6 +430,11 @@ func (r ApplicationUpdate) GetConfig() sqlxTypes.JSONText {
|
||||
return r.Config
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationUpdate) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *ApplicationUpdate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
@@ -425,6 +482,18 @@ func (r *ApplicationUpdate) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := req.Form["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ package request
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/pkg/payload"
|
||||
"github.com/go-chi/chi"
|
||||
"io"
|
||||
@@ -45,6 +46,11 @@ type (
|
||||
// Exclude (0, default), include (1) or return only (2) achived roles
|
||||
Archived uint
|
||||
|
||||
// Labels GET parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
|
||||
// Limit GET parameter
|
||||
//
|
||||
// Limit
|
||||
@@ -76,6 +82,11 @@ type (
|
||||
//
|
||||
// Role member IDs
|
||||
Members []string
|
||||
|
||||
// Labels POST parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
RoleUpdate struct {
|
||||
@@ -98,6 +109,11 @@ type (
|
||||
//
|
||||
// Role member IDs
|
||||
Members []string
|
||||
|
||||
// Labels POST parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
RoleRead struct {
|
||||
@@ -214,6 +230,7 @@ func (r RoleList) Auditable() map[string]interface{} {
|
||||
"query": r.Query,
|
||||
"deleted": r.Deleted,
|
||||
"archived": r.Archived,
|
||||
"labels": r.Labels,
|
||||
"limit": r.Limit,
|
||||
"pageCursor": r.PageCursor,
|
||||
"sort": r.Sort,
|
||||
@@ -235,6 +252,11 @@ func (r RoleList) GetArchived() uint {
|
||||
return r.Archived
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r RoleList) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r RoleList) GetLimit() uint {
|
||||
return r.Limit
|
||||
@@ -285,6 +307,17 @@ func (r *RoleList) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := tmp["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := tmp["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := tmp["limit"]; ok && len(val) > 0 {
|
||||
r.Limit, err = payload.ParseUint(val[0]), nil
|
||||
if err != nil {
|
||||
@@ -319,6 +352,7 @@ func (r RoleCreate) Auditable() map[string]interface{} {
|
||||
"name": r.Name,
|
||||
"handle": r.Handle,
|
||||
"members": r.Members,
|
||||
"labels": r.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +371,11 @@ func (r RoleCreate) GetMembers() []string {
|
||||
return r.Members
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r RoleCreate) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *RoleCreate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
@@ -377,6 +416,18 @@ func (r *RoleCreate) Fill(req *http.Request) (err error) {
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
|
||||
if val, ok := req.Form["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := req.Form["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -394,6 +445,7 @@ func (r RoleUpdate) Auditable() map[string]interface{} {
|
||||
"name": r.Name,
|
||||
"handle": r.Handle,
|
||||
"members": r.Members,
|
||||
"labels": r.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,6 +469,11 @@ func (r RoleUpdate) GetMembers() []string {
|
||||
return r.Members
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r RoleUpdate) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *RoleUpdate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
@@ -457,6 +514,18 @@ func (r *RoleUpdate) Fill(req *http.Request) (err error) {
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
|
||||
if val, ok := req.Form["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := req.Form["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ package request
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/pkg/payload"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/go-chi/chi"
|
||||
@@ -86,6 +87,11 @@ type (
|
||||
// Exclude (0, default), include (1) or return only (2) suspended users
|
||||
Suspended uint
|
||||
|
||||
// Labels GET parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
|
||||
// Limit GET parameter
|
||||
//
|
||||
// Limit
|
||||
@@ -122,6 +128,11 @@ type (
|
||||
//
|
||||
// Kind (normal, bot)
|
||||
Kind types.UserKind
|
||||
|
||||
// Labels POST parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
UserUpdate struct {
|
||||
@@ -149,6 +160,11 @@ type (
|
||||
//
|
||||
// Kind (normal, bot)
|
||||
Kind types.UserKind
|
||||
|
||||
// Labels POST parameter
|
||||
//
|
||||
// Labels
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
UserRead struct {
|
||||
@@ -261,6 +277,7 @@ func (r UserList) Auditable() map[string]interface{} {
|
||||
"incSuspended": r.IncSuspended,
|
||||
"deleted": r.Deleted,
|
||||
"suspended": r.Suspended,
|
||||
"labels": r.Labels,
|
||||
"limit": r.Limit,
|
||||
"pageCursor": r.PageCursor,
|
||||
"sort": r.Sort,
|
||||
@@ -322,6 +339,11 @@ func (r UserList) GetSuspended() uint {
|
||||
return r.Suspended
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r UserList) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r UserList) GetLimit() uint {
|
||||
return r.Limit
|
||||
@@ -430,6 +452,17 @@ func (r *UserList) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := tmp["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := tmp["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := tmp["limit"]; ok && len(val) > 0 {
|
||||
r.Limit, err = payload.ParseUint(val[0]), nil
|
||||
if err != nil {
|
||||
@@ -465,6 +498,7 @@ func (r UserCreate) Auditable() map[string]interface{} {
|
||||
"name": r.Name,
|
||||
"handle": r.Handle,
|
||||
"kind": r.Kind,
|
||||
"labels": r.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,6 +522,11 @@ func (r UserCreate) GetKind() types.UserKind {
|
||||
return r.Kind
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r UserCreate) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *UserCreate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
@@ -535,6 +574,18 @@ func (r *UserCreate) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := req.Form["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -553,6 +604,7 @@ func (r UserUpdate) Auditable() map[string]interface{} {
|
||||
"name": r.Name,
|
||||
"handle": r.Handle,
|
||||
"kind": r.Kind,
|
||||
"labels": r.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,6 +633,11 @@ func (r UserUpdate) GetKind() types.UserKind {
|
||||
return r.Kind
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r UserUpdate) GetLabels() map[string]string {
|
||||
return r.Labels
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *UserUpdate) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
@@ -628,6 +685,18 @@ func (r *UserUpdate) Fill(req *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["labels[]"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if val, ok := req.Form["labels"]; ok {
|
||||
r.Labels, err = label.ParseStrings(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
+4
-1
@@ -58,7 +58,8 @@ func (ctrl Role) List(ctx context.Context, r *request.RoleList) (interface{}, er
|
||||
var (
|
||||
err error
|
||||
f = types.RoleFilter{
|
||||
Query: r.Query,
|
||||
Query: r.Query,
|
||||
Labels: r.Labels,
|
||||
|
||||
Archived: filter.State(r.Archived),
|
||||
Deleted: filter.State(r.Deleted),
|
||||
@@ -83,6 +84,7 @@ func (ctrl Role) Create(ctx context.Context, r *request.RoleCreate) (interface{}
|
||||
role = &types.Role{
|
||||
Name: r.Name,
|
||||
Handle: r.Handle,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -107,6 +109,7 @@ func (ctrl Role) Update(ctx context.Context, r *request.RoleUpdate) (interface{}
|
||||
ID: r.RoleID,
|
||||
Name: r.Name,
|
||||
Handle: r.Handle,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ func (ctrl User) List(ctx context.Context, r *request.UserList) (interface{}, er
|
||||
Username: r.Username,
|
||||
Handle: r.Handle,
|
||||
Kind: r.Kind,
|
||||
Labels: r.Labels,
|
||||
Suspended: filter.State(r.Suspended),
|
||||
Deleted: filter.State(r.Deleted),
|
||||
}
|
||||
@@ -76,6 +77,7 @@ func (ctrl User) Create(ctx context.Context, r *request.UserCreate) (interface{}
|
||||
Name: r.Name,
|
||||
Handle: r.Handle,
|
||||
Kind: r.Kind,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
|
||||
return ctrl.user.With(ctx).Create(user)
|
||||
@@ -88,6 +90,7 @@ func (ctrl User) Update(ctx context.Context, r *request.UserUpdate) (interface{}
|
||||
Name: r.Name,
|
||||
Handle: r.Handle,
|
||||
Kind: r.Kind,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
|
||||
return ctrl.user.With(ctx).Update(user)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/system/service/event"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
@@ -14,7 +15,7 @@ type (
|
||||
ac applicationAccessController
|
||||
eventbus eventDispatcher
|
||||
actionlog actionlog.Recorder
|
||||
store store.Applications
|
||||
store store.Storer
|
||||
}
|
||||
|
||||
applicationAccessController interface {
|
||||
@@ -27,7 +28,7 @@ type (
|
||||
)
|
||||
|
||||
// Application is a default application service initializer
|
||||
func Application(s store.Applications, ac applicationAccessController, al actionlog.Recorder, eb eventDispatcher) *application {
|
||||
func Application(s store.Storer, ac applicationAccessController, al actionlog.Recorder, eb eventDispatcher) *application {
|
||||
return &application{store: s, ac: ac, actionlog: al, eventbus: eb}
|
||||
}
|
||||
|
||||
@@ -83,8 +84,29 @@ func (svc *application) Search(ctx context.Context, af types.ApplicationFilter)
|
||||
}
|
||||
}
|
||||
|
||||
aa, f, err = store.SearchApplications(ctx, svc.store, af)
|
||||
return err
|
||||
if len(af.Labels) > 0 {
|
||||
af.LabeledIDs, err = label.Search(
|
||||
ctx,
|
||||
svc.store,
|
||||
types.Application{}.LabelResourceKind(),
|
||||
af.Labels,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if aa, f, err = store.SearchApplications(ctx, svc.store, af); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = label.Load(ctx, svc.store, toLabeledApplications(aa)...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}()
|
||||
|
||||
return aa, f, svc.recordAction(ctx, aaProps, ApplicationActionSearch, err)
|
||||
@@ -116,7 +138,11 @@ func (svc *application) Create(ctx context.Context, new *types.Application) (app
|
||||
return
|
||||
}
|
||||
|
||||
aaProps.setApplication(app)
|
||||
if err = label.Create(ctx, svc.store, new); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
app = new
|
||||
|
||||
_ = svc.eventbus.WaitFor(ctx, event.ApplicationAfterCreate(new, nil))
|
||||
return nil
|
||||
@@ -162,6 +188,13 @@ func (svc *application) Update(ctx context.Context, upd *types.Application) (app
|
||||
return err
|
||||
}
|
||||
|
||||
if label.Changed(app.Labels, upd.Labels) {
|
||||
if err = label.Update(ctx, svc.store, upd); err != nil {
|
||||
return
|
||||
}
|
||||
app.Labels = upd.Labels
|
||||
}
|
||||
|
||||
_ = svc.eventbus.WaitFor(ctx, event.ApplicationAfterUpdate(upd, app))
|
||||
return nil
|
||||
}()
|
||||
@@ -244,3 +277,19 @@ func (svc *application) Undelete(ctx context.Context, ID uint64) (err error) {
|
||||
|
||||
return svc.recordAction(ctx, aaProps, ApplicationActionUndelete, err)
|
||||
}
|
||||
|
||||
// toLabeledApplications converts to []label.LabeledResource
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func toLabeledApplications(set []*types.Application) []label.LabeledResource {
|
||||
if len(set) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ll := make([]label.LabeledResource, len(set))
|
||||
for i := range set {
|
||||
ll[i] = set[i]
|
||||
}
|
||||
|
||||
return ll
|
||||
}
|
||||
|
||||
+87
-9
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza-server/pkg/eventbus"
|
||||
"github.com/cortezaproject/corteza-server/pkg/handle"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/system/service/event"
|
||||
@@ -112,8 +113,33 @@ func (svc role) Find(filter types.RoleFilter) (rr types.RoleSet, f types.RoleFil
|
||||
}
|
||||
}
|
||||
|
||||
rr, f, err = store.SearchRoles(svc.ctx, svc.store, filter)
|
||||
return err
|
||||
if len(filter.Labels) > 0 {
|
||||
filter.LabeledIDs, err = label.Search(
|
||||
svc.ctx,
|
||||
svc.store,
|
||||
types.Role{}.LabelResourceKind(),
|
||||
filter.Labels,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// labels specified but no labeled resources found
|
||||
if len(filter.LabeledIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if rr, f, err = store.SearchRoles(svc.ctx, svc.store, filter); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, toLabeledRoles(rr)...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return rr, f, svc.recordAction(svc.ctx, raProps, RoleActionSearch, err)
|
||||
@@ -125,9 +151,17 @@ func (svc role) FindByID(roleID uint64) (r *types.Role, err error) {
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
r, err = svc.findByID(roleID)
|
||||
if r, err = svc.findByID(roleID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
raProps.setRole(r)
|
||||
return err
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return r, svc.recordAction(svc.ctx, raProps, RoleActionLookup, err)
|
||||
@@ -147,9 +181,17 @@ func (svc role) FindByName(name string) (r *types.Role, err error) {
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
r, err = store.LookupRoleByName(svc.ctx, svc.store, name)
|
||||
if r, err = store.LookupRoleByName(svc.ctx, svc.store, name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
raProps.setRole(r)
|
||||
return err
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return r, svc.recordAction(svc.ctx, raProps, RoleActionLookup, err)
|
||||
@@ -161,9 +203,17 @@ func (svc role) FindByHandle(h string) (r *types.Role, err error) {
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
r, err = store.LookupRoleByName(svc.ctx, svc.store, h)
|
||||
if r, err = store.LookupRoleByHandle(svc.ctx, svc.store, h); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
raProps.setRole(r)
|
||||
return err
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return r, svc.recordAction(svc.ctx, raProps, RoleActionLookup, err)
|
||||
@@ -218,7 +268,11 @@ func (svc role) Create(new *types.Role) (r *types.Role, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
raProps.setRole(r)
|
||||
if err = label.Create(svc.ctx, svc.store, new); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r = new
|
||||
|
||||
_ = svc.eventbus.WaitFor(svc.ctx, event.RoleAfterCreate(new, r))
|
||||
return
|
||||
@@ -269,6 +323,14 @@ func (svc role) Update(upd *types.Role) (r *types.Role, err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if label.Changed(r.Labels, upd.Labels) {
|
||||
if err = label.Update(svc.ctx, svc.store, upd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r.Labels = upd.Labels
|
||||
}
|
||||
|
||||
_ = svc.eventbus.WaitFor(svc.ctx, event.RoleAfterUpdate(upd, r))
|
||||
|
||||
return nil
|
||||
@@ -547,3 +609,19 @@ func (svc role) MemberRemove(roleID, memberID uint64) (err error) {
|
||||
|
||||
return svc.recordAction(svc.ctx, raProps, RoleActionMemberRemove, err)
|
||||
}
|
||||
|
||||
// toLabeledRoles converts to []label.LabeledResource
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func toLabeledRoles(set []*types.Role) []label.LabeledResource {
|
||||
if len(set) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ll := make([]label.LabeledResource, len(set))
|
||||
for i := range set {
|
||||
ll[i] = set[i]
|
||||
}
|
||||
|
||||
return ll
|
||||
}
|
||||
|
||||
+95
-8
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/pkg/eventbus"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza-server/pkg/handle"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/system/service/event"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
@@ -142,8 +143,17 @@ func (svc user) FindByID(userID uint64) (u *types.User, err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
u, err = svc.proc(store.LookupUserByID(svc.ctx, svc.store, userID))
|
||||
return err
|
||||
if u, err = svc.proc(store.LookupUserByID(svc.ctx, svc.store, userID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uaProps.setUser(u)
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return u, svc.recordAction(svc.ctx, uaProps, UserActionLookup, err)
|
||||
@@ -155,8 +165,17 @@ func (svc user) FindByEmail(email string) (u *types.User, err error) {
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
u, err = svc.proc(store.LookupUserByEmail(svc.ctx, svc.store, email))
|
||||
return err
|
||||
if u, err = svc.proc(store.LookupUserByEmail(svc.ctx, svc.store, email)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uaProps.setUser(u)
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return u, svc.recordAction(svc.ctx, uaProps, UserActionLookup, err)
|
||||
@@ -168,8 +187,17 @@ func (svc user) FindByUsername(username string) (u *types.User, err error) {
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
u, err = svc.proc(store.LookupUserByUsername(svc.ctx, svc.store, username))
|
||||
return err
|
||||
if u, err = svc.proc(store.LookupUserByUsername(svc.ctx, svc.store, username)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uaProps.setUser(u)
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return u, svc.recordAction(svc.ctx, uaProps, UserActionLookup, err)
|
||||
@@ -181,8 +209,17 @@ func (svc user) FindByHandle(handle string) (u *types.User, err error) {
|
||||
)
|
||||
|
||||
err = func() error {
|
||||
u, err = svc.proc(store.LookupUserByHandle(svc.ctx, svc.store, handle))
|
||||
return err
|
||||
if u, err = svc.proc(store.LookupUserByHandle(svc.ctx, svc.store, handle)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uaProps.setUser(u)
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return u, svc.recordAction(svc.ctx, uaProps, UserActionLookup, err)
|
||||
@@ -273,11 +310,33 @@ func (svc user) Find(filter types.UserFilter) (uu types.UserSet, f types.UserFil
|
||||
}
|
||||
}
|
||||
|
||||
if len(filter.Labels) > 0 {
|
||||
filter.LabeledIDs, err = label.Search(
|
||||
svc.ctx,
|
||||
svc.store,
|
||||
types.User{}.LabelResourceKind(),
|
||||
filter.Labels,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// labels specified but no labeled resources found
|
||||
if len(filter.LabeledIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
uu, f, err = store.SearchUsers(svc.ctx, svc.store, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = label.Load(svc.ctx, svc.store, toLabeledUsers(uu)...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return uu.Walk(func(u *types.User) error {
|
||||
svc.handlePrivateData(u)
|
||||
return nil
|
||||
@@ -343,6 +402,10 @@ func (svc user) Create(new *types.User) (u *types.User, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = label.Create(svc.ctx, svc.store, new); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_ = svc.eventbus.WaitFor(svc.ctx, event.UserAfterCreate(new, u))
|
||||
return
|
||||
}()
|
||||
@@ -405,6 +468,14 @@ func (svc user) Update(upd *types.User) (u *types.User, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if label.Changed(u.Labels, upd.Labels) {
|
||||
if err = label.Update(svc.ctx, svc.store, upd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
u.Labels = upd.Labels
|
||||
}
|
||||
|
||||
_ = svc.eventbus.WaitFor(svc.ctx, event.UserAfterUpdate(upd, u))
|
||||
return
|
||||
}()
|
||||
@@ -726,3 +797,19 @@ func createHandle(ctx context.Context, s store.Users, u *types.User) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// toLabeledUsers converts to []label.LabeledResource
|
||||
//
|
||||
// This function is auto-generated.
|
||||
func toLabeledUsers(set []*types.User) []label.LabeledResource {
|
||||
if len(set) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ll := make([]label.LabeledResource, len(set))
|
||||
for i := range set {
|
||||
ll[i] = set[i]
|
||||
}
|
||||
|
||||
return ll
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ type (
|
||||
|
||||
Unify *ApplicationUnify `json:"unify,omitempty"`
|
||||
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||
DeletedAt *time.Time `json:"deletedAt,omitempty"`
|
||||
@@ -39,6 +41,9 @@ type (
|
||||
Name string `json:"name"`
|
||||
Query string `json:"query"`
|
||||
|
||||
LabeledIDs []uint64 `json:"-"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
Deleted filter.State `json:"deleted"`
|
||||
|
||||
// Check fn is called by store backend for each resource found function can
|
||||
|
||||
@@ -10,9 +10,12 @@ import (
|
||||
type (
|
||||
// Role - An organisation may have many roles. Roles may have many channels available. Access to channels may be shared between roles.
|
||||
Role struct {
|
||||
ID uint64 `json:"roleID,string"`
|
||||
Name string `json:"name"`
|
||||
Handle string `json:"handle"`
|
||||
ID uint64 `json:"roleID,string"`
|
||||
Name string `json:"name"`
|
||||
Handle string `json:"handle"`
|
||||
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||
ArchivedAt *time.Time `json:"archivedAt,omitempty"`
|
||||
@@ -31,6 +34,9 @@ type (
|
||||
Deleted filter.State `json:"deleted"`
|
||||
Archived filter.State `json:"archived"`
|
||||
|
||||
LabeledIDs []uint64 `json:"-"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
// Check fn is called by store backend for each resource found function can
|
||||
// modify the resource and return false if store should not return it
|
||||
//
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package types
|
||||
|
||||
// This file is auto-generated.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
//
|
||||
// Definitions file that controls how this file is generated:
|
||||
// system/types/types.yaml
|
||||
|
||||
// SetLabel adds new label to label map
|
||||
func (m *Application) SetLabel(key string, value string) {
|
||||
if m.Labels == nil {
|
||||
m.Labels = make(map[string]string)
|
||||
}
|
||||
|
||||
m.Labels[key] = value
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (m Application) GetLabels() map[string]string {
|
||||
return m.Labels
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (Application) LabelResourceKind() string {
|
||||
return "application"
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (m Application) LabelResourceID() uint64 {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
// SetLabel adds new label to label map
|
||||
func (m *Role) SetLabel(key string, value string) {
|
||||
if m.Labels == nil {
|
||||
m.Labels = make(map[string]string)
|
||||
}
|
||||
|
||||
m.Labels[key] = value
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (m Role) GetLabels() map[string]string {
|
||||
return m.Labels
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (Role) LabelResourceKind() string {
|
||||
return "role"
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (m Role) LabelResourceID() uint64 {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
// SetLabel adds new label to label map
|
||||
func (m *User) SetLabel(key string, value string) {
|
||||
if m.Labels == nil {
|
||||
m.Labels = make(map[string]string)
|
||||
}
|
||||
|
||||
m.Labels[key] = value
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (m User) GetLabels() map[string]string {
|
||||
return m.Labels
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (User) LabelResourceKind() string {
|
||||
return "user"
|
||||
}
|
||||
|
||||
// GetLabels adds new label to label map
|
||||
func (m User) LabelResourceID() uint64 {
|
||||
return m.ID
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
types:
|
||||
User:
|
||||
labelResourceType: user
|
||||
Application:
|
||||
labelResourceType: application
|
||||
Role:
|
||||
labelResourceType: role
|
||||
RoleMember:
|
||||
noIdField: true
|
||||
Credentials:
|
||||
|
||||
@@ -25,6 +25,8 @@ type (
|
||||
|
||||
EmailConfirmed bool `json:"-"`
|
||||
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||
SuspendedAt *time.Time `json:"suspendedAt,omitempty"`
|
||||
@@ -49,6 +51,9 @@ type (
|
||||
Handle string `json:"handle"`
|
||||
Kind UserKind `json:"kind"`
|
||||
|
||||
LabeledIDs []uint64 `json:"-"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
|
||||
Deleted filter.State `json:"deleted"`
|
||||
Suspended filter.State `json:"suspended"`
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/cortezaproject/corteza-server/tests/helpers"
|
||||
"github.com/steinfletcher/apitest-jsonpath"
|
||||
"github.com/stretchr/testify/require"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -188,3 +190,84 @@ func TestApplicationDelete(t *testing.T) {
|
||||
h.a.NotNil(res)
|
||||
h.a.NotNil(res.DeletedAt)
|
||||
}
|
||||
|
||||
func TestApplicationLabels(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.clearApplications()
|
||||
|
||||
h.allow(types.SystemRBACResource, "application.create")
|
||||
h.allow(types.ApplicationRBACResource.AppendWildcard(), "read")
|
||||
h.allow(types.ApplicationRBACResource.AppendWildcard(), "update")
|
||||
h.allow(types.ApplicationRBACResource.AppendWildcard(), "delete")
|
||||
|
||||
var (
|
||||
ID uint64
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
payload = &types.Application{}
|
||||
)
|
||||
|
||||
helpers.SetLabelsViaAPI(h.apiInit(), t,
|
||||
"/application/",
|
||||
types.Application{Labels: map[string]string{"foo": "bar", "bar": "42"}},
|
||||
payload,
|
||||
)
|
||||
req.NotZero(payload.ID)
|
||||
|
||||
h.a.Equal(payload.Labels["foo"], "bar",
|
||||
"labels must contain foo with value bar")
|
||||
h.a.Equal(payload.Labels["bar"], "42",
|
||||
"labels must contain bar with value 42")
|
||||
req.Equal(payload.Labels, helpers.LoadLabelsFromStore(t, service.DefaultStore, payload.LabelResourceKind(), payload.ID),
|
||||
"response must match stored labels")
|
||||
|
||||
ID = payload.ID
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
if ID == 0 {
|
||||
t.Skip("label/create test not ran")
|
||||
}
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
payload = &types.Application{}
|
||||
)
|
||||
|
||||
helpers.SetLabelsViaAPI(h.apiInit(), t,
|
||||
fmt.Sprintf("PUT /application/%d", ID),
|
||||
&types.Application{Labels: map[string]string{"foo": "baz", "baz": "123"}},
|
||||
payload,
|
||||
)
|
||||
req.NotZero(payload.ID)
|
||||
//req.Nil(payload.UpdatedAt, "updatedAt must not change after changing labels")
|
||||
|
||||
req.Equal(payload.Labels["foo"], "baz",
|
||||
"labels must contain foo with value baz")
|
||||
req.NotContains(payload.Labels, "bar",
|
||||
"labels must not contain bar")
|
||||
req.Equal(payload.Labels["baz"], "123",
|
||||
"labels must contain baz with value 123")
|
||||
req.Equal(payload.Labels, helpers.LoadLabelsFromStore(t, service.DefaultStore, payload.LabelResourceKind(), payload.ID),
|
||||
"response must match stored labels")
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
if ID == 0 {
|
||||
t.Skip("label/create test not ran")
|
||||
}
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
set = types.ApplicationSet{}
|
||||
)
|
||||
|
||||
helpers.SearchWithLabelsViaAPI(h.apiInit(), t, "/application/", &set, url.Values{"labels": []string{"baz=123"}})
|
||||
req.NotEmpty(set)
|
||||
req.NotNil(set.FindByID(ID))
|
||||
req.NotNil(set.FindByID(ID).Labels)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/cortezaproject/corteza-server/tests/helpers"
|
||||
"github.com/steinfletcher/apitest-jsonpath"
|
||||
"github.com/stretchr/testify/require"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -219,3 +221,84 @@ func TestRoleDelete(t *testing.T) {
|
||||
h.a.NotNil(res)
|
||||
h.a.NotNil(res.DeletedAt)
|
||||
}
|
||||
|
||||
func TestRoleLabels(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.clearRoles()
|
||||
|
||||
h.allow(types.SystemRBACResource, "role.create")
|
||||
h.allow(types.RoleRBACResource.AppendWildcard(), "read")
|
||||
h.allow(types.RoleRBACResource.AppendWildcard(), "update")
|
||||
h.allow(types.RoleRBACResource.AppendWildcard(), "delete")
|
||||
|
||||
var (
|
||||
ID uint64
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
payload = &types.Role{}
|
||||
)
|
||||
|
||||
helpers.SetLabelsViaAPI(h.apiInit(), t,
|
||||
"/roles/",
|
||||
types.Role{Labels: map[string]string{"foo": "bar", "bar": "42"}},
|
||||
payload,
|
||||
)
|
||||
req.NotZero(payload.ID)
|
||||
|
||||
h.a.Equal(payload.Labels["foo"], "bar",
|
||||
"labels must contain foo with value bar")
|
||||
h.a.Equal(payload.Labels["bar"], "42",
|
||||
"labels must contain bar with value 42")
|
||||
req.Equal(payload.Labels, helpers.LoadLabelsFromStore(t, service.DefaultStore, payload.LabelResourceKind(), payload.ID),
|
||||
"response must match stored labels")
|
||||
|
||||
ID = payload.ID
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
if ID == 0 {
|
||||
t.Skip("label/create test not ran")
|
||||
}
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
payload = &types.Role{}
|
||||
)
|
||||
|
||||
helpers.SetLabelsViaAPI(h.apiInit(), t,
|
||||
fmt.Sprintf("PUT /roles/%d", ID),
|
||||
&types.Role{Labels: map[string]string{"foo": "baz", "baz": "123"}},
|
||||
payload,
|
||||
)
|
||||
req.NotZero(payload.ID)
|
||||
//req.Nil(payload.UpdatedAt, "updatedAt must not change after changing labels")
|
||||
|
||||
req.Equal(payload.Labels["foo"], "baz",
|
||||
"labels must contain foo with value baz")
|
||||
req.NotContains(payload.Labels, "bar",
|
||||
"labels must not contain bar")
|
||||
req.Equal(payload.Labels["baz"], "123",
|
||||
"labels must contain baz with value 123")
|
||||
req.Equal(payload.Labels, helpers.LoadLabelsFromStore(t, service.DefaultStore, payload.LabelResourceKind(), payload.ID),
|
||||
"response must match stored labels")
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
if ID == 0 {
|
||||
t.Skip("label/create test not ran")
|
||||
}
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
set = types.RoleSet{}
|
||||
)
|
||||
|
||||
helpers.SearchWithLabelsViaAPI(h.apiInit(), t, "/roles/", &set, url.Values{"labels": []string{"baz=123"}})
|
||||
req.NotEmpty(set)
|
||||
req.NotNil(set.FindByID(ID))
|
||||
req.NotNil(set.FindByID(ID).Labels)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/cortezaproject/corteza-server/tests/helpers"
|
||||
"github.com/steinfletcher/apitest-jsonpath"
|
||||
"github.com/stretchr/testify/require"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -380,3 +382,84 @@ func TestUserDelete(t *testing.T) {
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
}
|
||||
|
||||
func TestUserLabels(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.clearUsers()
|
||||
|
||||
h.allow(types.SystemRBACResource, "user.create")
|
||||
h.allow(types.UserRBACResource.AppendWildcard(), "read")
|
||||
h.allow(types.UserRBACResource.AppendWildcard(), "update")
|
||||
h.allow(types.UserRBACResource.AppendWildcard(), "delete")
|
||||
|
||||
var (
|
||||
ID uint64
|
||||
)
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
var (
|
||||
req = require.New(t)
|
||||
payload = &types.User{}
|
||||
)
|
||||
|
||||
helpers.SetLabelsViaAPI(h.apiInit(), t,
|
||||
"/users/",
|
||||
types.User{Email: h.randEmail(), Labels: map[string]string{"foo": "bar", "bar": "42"}},
|
||||
payload,
|
||||
)
|
||||
req.NotZero(payload.ID)
|
||||
|
||||
h.a.Equal(payload.Labels["foo"], "bar",
|
||||
"labels must contain foo with value bar")
|
||||
h.a.Equal(payload.Labels["bar"], "42",
|
||||
"labels must contain bar with value 42")
|
||||
req.Equal(payload.Labels, helpers.LoadLabelsFromStore(t, service.DefaultStore, payload.LabelResourceKind(), payload.ID),
|
||||
"response must match stored labels")
|
||||
|
||||
ID = payload.ID
|
||||
})
|
||||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
if ID == 0 {
|
||||
t.Skip("label/create test not ran")
|
||||
}
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
payload = &types.User{}
|
||||
)
|
||||
|
||||
helpers.SetLabelsViaAPI(h.apiInit(), t,
|
||||
fmt.Sprintf("PUT /users/%d", ID),
|
||||
&types.User{ID: ID, Email: h.randEmail(), Labels: map[string]string{"foo": "baz", "baz": "123"}},
|
||||
payload,
|
||||
)
|
||||
req.NotZero(payload.ID)
|
||||
//req.Nil(payload.UpdatedAt, "updatedAt must not change after changing labels")
|
||||
|
||||
req.Equal(payload.Labels["foo"], "baz",
|
||||
"labels must contain foo with value baz")
|
||||
req.NotContains(payload.Labels, "bar",
|
||||
"labels must not contain bar")
|
||||
req.Equal(payload.Labels["baz"], "123",
|
||||
"labels must contain baz with value 123")
|
||||
req.Equal(payload.Labels, helpers.LoadLabelsFromStore(t, service.DefaultStore, payload.LabelResourceKind(), payload.ID),
|
||||
"response must match stored labels")
|
||||
})
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
if ID == 0 {
|
||||
t.Skip("label/create test not ran")
|
||||
}
|
||||
|
||||
var (
|
||||
req = require.New(t)
|
||||
set = types.UserSet{}
|
||||
)
|
||||
|
||||
helpers.SearchWithLabelsViaAPI(h.apiInit(), t, "/users/", &set, url.Values{"labels": []string{"baz=123"}})
|
||||
req.NotEmpty(set)
|
||||
req.NotNil(set.FindByID(ID))
|
||||
req.NotNil(set.FindByID(ID).Labels)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user