Rework system/application sorting via weight
This commit is contained in:
parent
77c754b81b
commit
1e44e4299b
@ -62,6 +62,7 @@ func (c *application) MarshalYAML() (interface{}, error) {
|
||||
nn, err := makeMap(
|
||||
"name", c.res.Name,
|
||||
"enabled", c.res.Enabled,
|
||||
"weight", c.res.Weight,
|
||||
|
||||
"unify", c.res.Unify,
|
||||
|
||||
|
||||
@ -33,6 +33,9 @@ type (
|
||||
|
||||
// ApplicationMetrics (custom function)
|
||||
ApplicationMetrics(ctx context.Context) (*types.ApplicationMetrics, error)
|
||||
|
||||
// ReorderApplications (custom function)
|
||||
ReorderApplications(ctx context.Context, _order []uint64) error
|
||||
}
|
||||
)
|
||||
|
||||
@ -84,3 +87,7 @@ func TruncateApplications(ctx context.Context, s Applications) error {
|
||||
func ApplicationMetrics(ctx context.Context, s Applications) (*types.ApplicationMetrics, error) {
|
||||
return s.ApplicationMetrics(ctx)
|
||||
}
|
||||
|
||||
func ReorderApplications(ctx context.Context, s Applications, _order []uint64) error {
|
||||
return s.ReorderApplications(ctx, _order)
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ fields:
|
||||
- { field: Name, sortable: true }
|
||||
- { field: OwnerID }
|
||||
- { field: Enabled }
|
||||
- { field: Weight, sortable: true }
|
||||
- { field: Unify }
|
||||
- { field: CreatedAt, sortable: true }
|
||||
- { field: UpdatedAt, sortable: true }
|
||||
@ -22,6 +23,12 @@ functions:
|
||||
- name: ApplicationMetrics
|
||||
return: [ "*types.ApplicationMetrics", "error" ]
|
||||
|
||||
- name: ReorderApplications
|
||||
arguments:
|
||||
- { name: order, type: "[]uint64" }
|
||||
return: [ "error" ]
|
||||
|
||||
|
||||
rdbms:
|
||||
alias: app
|
||||
table: applications
|
||||
|
||||
@ -435,6 +435,7 @@ func (s Store) internalApplicationRowScanner(row rowScanner) (res *types.Applica
|
||||
&res.Name,
|
||||
&res.OwnerID,
|
||||
&res.Enabled,
|
||||
&res.Weight,
|
||||
&res.Unify,
|
||||
&res.CreatedAt,
|
||||
&res.UpdatedAt,
|
||||
@ -482,6 +483,7 @@ func (Store) applicationColumns(aa ...string) []string {
|
||||
alias + "name",
|
||||
alias + "rel_owner",
|
||||
alias + "enabled",
|
||||
alias + "weight",
|
||||
alias + "unify",
|
||||
alias + "created_at",
|
||||
alias + "updated_at",
|
||||
@ -496,7 +498,7 @@ func (Store) applicationColumns(aa ...string) []string {
|
||||
// With optional string arg, all columns are returned aliased
|
||||
func (Store) sortableApplicationColumns() map[string]string {
|
||||
return map[string]string{
|
||||
"id": "id", "name": "name", "created_at": "created_at",
|
||||
"id": "id", "name": "name", "weight": "weight", "created_at": "created_at",
|
||||
"createdat": "created_at",
|
||||
"updated_at": "updated_at",
|
||||
"updatedat": "updated_at",
|
||||
@ -515,6 +517,7 @@ func (s Store) internalApplicationEncoder(res *types.Application) store.Payload
|
||||
"name": res.Name,
|
||||
"rel_owner": res.OwnerID,
|
||||
"enabled": res.Enabled,
|
||||
"weight": res.Weight,
|
||||
"unify": res.Unify,
|
||||
"created_at": res.CreatedAt,
|
||||
"updated_at": res.UpdatedAt,
|
||||
@ -551,6 +554,9 @@ func (s Store) collectApplicationCursorValues(res *types.Application, cc ...*fil
|
||||
case "name":
|
||||
cursor.Set(c.Column, res.Name, c.Descending)
|
||||
|
||||
case "weight":
|
||||
cursor.Set(c.Column, res.Weight, c.Descending)
|
||||
|
||||
case "created_at":
|
||||
cursor.Set(c.Column, res.CreatedAt, c.Descending)
|
||||
|
||||
|
||||
@ -2,8 +2,10 @@ package rdbms
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
)
|
||||
|
||||
@ -56,3 +58,56 @@ func (s Store) ApplicationMetrics(ctx context.Context) (*types.ApplicationMetric
|
||||
|
||||
return rval, nil
|
||||
}
|
||||
|
||||
func (s Store) ReorderApplications(ctx context.Context, order []uint64) (err error) {
|
||||
var (
|
||||
apps types.ApplicationSet
|
||||
appMap = map[uint64]bool{}
|
||||
weight = 1
|
||||
|
||||
f = types.ApplicationFilter{}
|
||||
)
|
||||
|
||||
if apps, _, err = s.SearchApplications(ctx, f); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, app := range apps {
|
||||
appMap[app.ID] = true
|
||||
}
|
||||
|
||||
// honor parameter first
|
||||
for _, pageID := range order {
|
||||
if appMap[pageID] {
|
||||
appMap[pageID] = false
|
||||
err = s.execUpdateApplications(ctx,
|
||||
squirrel.Eq{"app.id": pageID},
|
||||
store.Payload{"weight": weight})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
weight++
|
||||
}
|
||||
}
|
||||
|
||||
for pageID, update := range appMap {
|
||||
if !update {
|
||||
continue
|
||||
}
|
||||
|
||||
err = s.execUpdateApplications(ctx,
|
||||
squirrel.Eq{"app.id": pageID},
|
||||
store.Payload{"weight": weight})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
weight++
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package rdbms
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/store/rdbms/ddl"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@ -59,6 +60,10 @@ func (g genericUpgrades) Upgrade(ctx context.Context, t *ddl.Table) error {
|
||||
return g.all(ctx,
|
||||
g.AlterActionlogAddID,
|
||||
)
|
||||
case "applications":
|
||||
return g.all(ctx,
|
||||
g.AddWeightField,
|
||||
)
|
||||
case "users":
|
||||
return g.all(ctx,
|
||||
g.AlterUsersDropOrganisation,
|
||||
@ -243,6 +248,17 @@ func (g genericUpgrades) AlterActionlogAddID(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g genericUpgrades) AddWeightField(ctx context.Context) error {
|
||||
_, err := g.u.AddColumn(ctx, "applications", &ddl.Column{
|
||||
Name: "weight",
|
||||
Type: ddl.ColumnType{Type: ddl.ColumnTypeInteger},
|
||||
IsNull: false,
|
||||
DefaultValue: "0",
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (g genericUpgrades) RenameReminders(ctx context.Context) error {
|
||||
return g.RenameTable(ctx, "sys_reminder", "reminders")
|
||||
}
|
||||
|
||||
@ -221,6 +221,7 @@ func (Schema) Applications() *Table {
|
||||
ID,
|
||||
ColumnDef("name", ColumnTypeText),
|
||||
ColumnDef("enabled", ColumnTypeBoolean, DefaultValue("true")),
|
||||
ColumnDef("weight", ColumnTypeInteger, DefaultValue("0")),
|
||||
ColumnDef("unify", ColumnTypeJson),
|
||||
ColumnDef("rel_owner", ColumnTypeIdentifier),
|
||||
CUDTimestamps,
|
||||
|
||||
@ -744,6 +744,10 @@ endpoints:
|
||||
type: bool
|
||||
required: false
|
||||
title: Enabled
|
||||
- name: weight
|
||||
type: int
|
||||
required: false
|
||||
title: Weight for sorting
|
||||
- name: unify
|
||||
type: sqlxTypes.JSONText
|
||||
required: false
|
||||
@ -775,6 +779,10 @@ endpoints:
|
||||
type: bool
|
||||
required: false
|
||||
title: Enabled
|
||||
- name: weight
|
||||
type: int
|
||||
required: false
|
||||
title: Weight for sorting
|
||||
- name: unify
|
||||
type: sqlxTypes.JSONText
|
||||
required: false
|
||||
@ -832,6 +840,17 @@ endpoints:
|
||||
type: string
|
||||
title: Script to execute
|
||||
required: true
|
||||
- name: reorder
|
||||
method: POST
|
||||
title: Reorder applications
|
||||
path: "/reorder"
|
||||
parameters:
|
||||
post:
|
||||
- name: applicationIDs
|
||||
type: "[]string"
|
||||
required: true
|
||||
title: Application order
|
||||
|
||||
- title: Permissions
|
||||
parameters: {}
|
||||
entrypoint: permissions
|
||||
|
||||
@ -2,6 +2,8 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/api"
|
||||
"github.com/cortezaproject/corteza-server/pkg/corredor"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
@ -27,6 +29,7 @@ type (
|
||||
Update(ctx context.Context, upd *types.Application) (app *types.Application, err error)
|
||||
Delete(ctx context.Context, ID uint64) (err error)
|
||||
Undelete(ctx context.Context, ID uint64) (err error)
|
||||
Reorder(ctx context.Context, order []uint64) (err error)
|
||||
}
|
||||
|
||||
applicationAccessController interface {
|
||||
@ -87,6 +90,7 @@ func (ctrl *Application) Create(ctx context.Context, r *request.ApplicationCreat
|
||||
app = &types.Application{
|
||||
Name: r.Name,
|
||||
Enabled: r.Enabled,
|
||||
Weight: r.Weight,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
)
|
||||
@ -109,6 +113,7 @@ func (ctrl *Application) Update(ctx context.Context, r *request.ApplicationUpdat
|
||||
ID: r.ApplicationID,
|
||||
Name: r.Name,
|
||||
Enabled: r.Enabled,
|
||||
Weight: r.Weight,
|
||||
Labels: r.Labels,
|
||||
}
|
||||
)
|
||||
@ -151,6 +156,21 @@ func (ctrl *Application) TriggerScript(ctx context.Context, r *request.Applicati
|
||||
return application, err
|
||||
}
|
||||
|
||||
func (ctrl *Application) Reorder(ctx context.Context, r *request.ApplicationReorder) (interface{}, error) {
|
||||
order := make([]uint64, len(r.ApplicationIDs))
|
||||
|
||||
for i, aid := range r.ApplicationIDs {
|
||||
parsed, err := strconv.ParseUint(aid, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
order[i] = parsed
|
||||
}
|
||||
|
||||
return api.OK(), ctrl.application.Reorder(ctx, order)
|
||||
}
|
||||
|
||||
func (ctrl Application) makePayload(ctx context.Context, m *types.Application, err error) (*applicationPayload, error) {
|
||||
if err != nil || m == nil {
|
||||
return nil, err
|
||||
|
||||
@ -26,6 +26,7 @@ type (
|
||||
Delete(context.Context, *request.ApplicationDelete) (interface{}, error)
|
||||
Undelete(context.Context, *request.ApplicationUndelete) (interface{}, error)
|
||||
TriggerScript(context.Context, *request.ApplicationTriggerScript) (interface{}, error)
|
||||
Reorder(context.Context, *request.ApplicationReorder) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
@ -37,6 +38,7 @@ type (
|
||||
Delete func(http.ResponseWriter, *http.Request)
|
||||
Undelete func(http.ResponseWriter, *http.Request)
|
||||
TriggerScript func(http.ResponseWriter, *http.Request)
|
||||
Reorder func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
)
|
||||
|
||||
@ -152,6 +154,22 @@ func NewApplication(h ApplicationAPI) *Application {
|
||||
return
|
||||
}
|
||||
|
||||
api.Send(w, r, value)
|
||||
},
|
||||
Reorder: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewApplicationReorder()
|
||||
if err := params.Fill(r); err != nil {
|
||||
api.Send(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
value, err := h.Reorder(r.Context(), params)
|
||||
if err != nil {
|
||||
api.Send(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
api.Send(w, r, value)
|
||||
},
|
||||
}
|
||||
@ -167,5 +185,6 @@ func (h Application) MountRoutes(r chi.Router, middlewares ...func(http.Handler)
|
||||
r.Delete("/application/{applicationID}", h.Delete)
|
||||
r.Post("/application/{applicationID}/undelete", h.Undelete)
|
||||
r.Post("/application/{applicationID}/trigger", h.TriggerScript)
|
||||
r.Post("/application/reorder", h.Reorder)
|
||||
})
|
||||
}
|
||||
|
||||
@ -79,6 +79,11 @@ type (
|
||||
// Enabled
|
||||
Enabled bool
|
||||
|
||||
// Weight POST parameter
|
||||
//
|
||||
// Weight for sorting
|
||||
Weight int
|
||||
|
||||
// Unify POST parameter
|
||||
//
|
||||
// Unify properties
|
||||
@ -111,6 +116,11 @@ type (
|
||||
// Enabled
|
||||
Enabled bool
|
||||
|
||||
// Weight POST parameter
|
||||
//
|
||||
// Weight for sorting
|
||||
Weight int
|
||||
|
||||
// Unify POST parameter
|
||||
//
|
||||
// Unify properties
|
||||
@ -159,6 +169,13 @@ type (
|
||||
// Script to execute
|
||||
Script string
|
||||
}
|
||||
|
||||
ApplicationReorder struct {
|
||||
// ApplicationIDs POST parameter
|
||||
//
|
||||
// Application order
|
||||
ApplicationIDs []string
|
||||
}
|
||||
)
|
||||
|
||||
// NewApplicationList request
|
||||
@ -293,6 +310,7 @@ func (r ApplicationCreate) Auditable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"name": r.Name,
|
||||
"enabled": r.Enabled,
|
||||
"weight": r.Weight,
|
||||
"unify": r.Unify,
|
||||
"config": r.Config,
|
||||
"labels": r.Labels,
|
||||
@ -309,6 +327,11 @@ func (r ApplicationCreate) GetEnabled() bool {
|
||||
return r.Enabled
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationCreate) GetWeight() int {
|
||||
return r.Weight
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationCreate) GetUnify() sqlxTypes.JSONText {
|
||||
return r.Unify
|
||||
@ -358,6 +381,13 @@ func (r *ApplicationCreate) Fill(req *http.Request) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["weight"]; ok && len(val) > 0 {
|
||||
r.Weight, err = payload.ParseInt(val[0]), nil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["unify"]; ok && len(val) > 0 {
|
||||
r.Unify, err = payload.ParseJSONTextWithErr(val[0])
|
||||
if err != nil {
|
||||
@ -399,6 +429,7 @@ func (r ApplicationUpdate) Auditable() map[string]interface{} {
|
||||
"applicationID": r.ApplicationID,
|
||||
"name": r.Name,
|
||||
"enabled": r.Enabled,
|
||||
"weight": r.Weight,
|
||||
"unify": r.Unify,
|
||||
"config": r.Config,
|
||||
"labels": r.Labels,
|
||||
@ -420,6 +451,11 @@ func (r ApplicationUpdate) GetEnabled() bool {
|
||||
return r.Enabled
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationUpdate) GetWeight() int {
|
||||
return r.Weight
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationUpdate) GetUnify() sqlxTypes.JSONText {
|
||||
return r.Unify
|
||||
@ -469,6 +505,13 @@ func (r *ApplicationUpdate) Fill(req *http.Request) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["weight"]; ok && len(val) > 0 {
|
||||
r.Weight, err = payload.ParseInt(val[0]), nil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := req.Form["unify"]; ok && len(val) > 0 {
|
||||
r.Unify, err = payload.ParseJSONTextWithErr(val[0])
|
||||
if err != nil {
|
||||
@ -711,3 +754,51 @@ func (r *ApplicationTriggerScript) Fill(req *http.Request) (err error) {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// NewApplicationReorder request
|
||||
func NewApplicationReorder() *ApplicationReorder {
|
||||
return &ApplicationReorder{}
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationReorder) Auditable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"applicationIDs": r.ApplicationIDs,
|
||||
}
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r ApplicationReorder) GetApplicationIDs() []string {
|
||||
return r.ApplicationIDs
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
func (r *ApplicationReorder) Fill(req *http.Request) (err error) {
|
||||
if strings.ToLower(req.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(req.Body).Decode(r)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return fmt.Errorf("error parsing http request body: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if err = req.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// POST params
|
||||
|
||||
//if val, ok := req.Form["applicationIDs[]"]; ok && len(val) > 0 {
|
||||
// r.ApplicationIDs, err = val, nil
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"github.com/cortezaproject/corteza-server/pkg/label"
|
||||
@ -182,6 +183,7 @@ func (svc *application) Update(ctx context.Context, upd *types.Application) (app
|
||||
// Assign changed values after afterUpdate events are emitted
|
||||
app.Name = upd.Name
|
||||
app.Enabled = upd.Enabled
|
||||
app.Weight = upd.Weight
|
||||
app.UpdatedAt = now()
|
||||
|
||||
if upd.Unify != nil {
|
||||
@ -282,6 +284,31 @@ func (svc *application) Undelete(ctx context.Context, ID uint64) (err error) {
|
||||
return svc.recordAction(ctx, aaProps, ApplicationActionUndelete, err)
|
||||
}
|
||||
|
||||
func (svc *application) Reorder(ctx context.Context, order []uint64) (err error) {
|
||||
var (
|
||||
aProps = &applicationActionProps{}
|
||||
)
|
||||
|
||||
err = store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) error {
|
||||
for _, id := range order {
|
||||
// This access control creates an aux application so we don't have to fetch them
|
||||
// from the store; the ID is the only thing that matters...
|
||||
auxApp := &types.Application{
|
||||
ID: id,
|
||||
}
|
||||
|
||||
if !svc.ac.CanUpdateApplication(ctx, auxApp) {
|
||||
aProps.application = auxApp
|
||||
return ApplicationErrNotAllowedToUpdate(aProps)
|
||||
}
|
||||
}
|
||||
|
||||
return store.ReorderApplications(ctx, s, order)
|
||||
})
|
||||
|
||||
return svc.recordAction(ctx, aProps, ApplicationActionReorder, err)
|
||||
}
|
||||
|
||||
// toLabeledApplications converts to []label.LabeledResource
|
||||
//
|
||||
// This function is auto-generated.
|
||||
|
||||
@ -265,6 +265,26 @@ func ApplicationActionSearch(props ...*applicationActionProps) *applicationActio
|
||||
return a
|
||||
}
|
||||
|
||||
// ApplicationActionReorder returns "system:application.reorder" action
|
||||
//
|
||||
// This function is auto-generated.
|
||||
//
|
||||
func ApplicationActionReorder(props ...*applicationActionProps) *applicationAction {
|
||||
a := &applicationAction{
|
||||
timestamp: time.Now(),
|
||||
resource: "system:application",
|
||||
action: "reorder",
|
||||
log: "reordered applications",
|
||||
severity: actionlog.Notice,
|
||||
}
|
||||
|
||||
if len(props) > 0 {
|
||||
a.props = props[0]
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// ApplicationActionLookup returns "system:application.lookup" action
|
||||
//
|
||||
// This function is auto-generated.
|
||||
|
||||
@ -31,6 +31,9 @@ actions:
|
||||
log: "searched for applications"
|
||||
severity: info
|
||||
|
||||
- action: reorder
|
||||
log: "reordered applications"
|
||||
|
||||
- action: lookup
|
||||
log: "looked-up for a {application}"
|
||||
severity: info
|
||||
|
||||
@ -3,9 +3,10 @@ package types
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/filter"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
@ -17,6 +18,7 @@ type (
|
||||
Name string `json:"name"`
|
||||
OwnerID uint64 `json:"ownerID"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Weight int `json:"weight"`
|
||||
|
||||
Unify *ApplicationUnify `json:"unify,omitempty"`
|
||||
|
||||
@ -34,7 +36,6 @@ type (
|
||||
Logo string `json:"logo"`
|
||||
Url string `json:"url"`
|
||||
Config string `json:"config"`
|
||||
Order uint `json:"order"`
|
||||
}
|
||||
|
||||
ApplicationFilter struct {
|
||||
|
||||
@ -514,7 +514,6 @@ func TestStoreYaml_base(t *testing.T) {
|
||||
req.Equal("logo", app.Unify.Logo)
|
||||
req.Equal("url", app.Unify.Url)
|
||||
req.Equal("{\"config\": \"config\"}", app.Unify.Config)
|
||||
req.Equal(uint(0), app.Unify.Order)
|
||||
req.Equal(createdAt.Format(time.RFC3339), app.CreatedAt.Format(time.RFC3339))
|
||||
req.Equal(updatedAt.Format(time.RFC3339), app.UpdatedAt.Format(time.RFC3339))
|
||||
},
|
||||
|
||||
@ -66,7 +66,6 @@ func sTestApplication(ctx context.Context, t *testing.T, s store.Storer, usrID u
|
||||
Logo: "logo",
|
||||
Url: "url",
|
||||
Config: "{\"config\": \"config\"}",
|
||||
Order: 0,
|
||||
},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: &updatedAt,
|
||||
|
||||
@ -3,17 +3,18 @@ package system
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/id"
|
||||
"github.com/cortezaproject/corteza-server/store"
|
||||
"github.com/cortezaproject/corteza-server/system/service"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/cortezaproject/corteza-server/tests/helpers"
|
||||
"github.com/steinfletcher/apitest-jsonpath"
|
||||
jsonpath "github.com/steinfletcher/apitest-jsonpath"
|
||||
"github.com/stretchr/testify/require"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (h helper) clearApplications() {
|
||||
@ -44,6 +45,17 @@ func (h helper) lookupApplicationByID(ID uint64) *types.Application {
|
||||
return res
|
||||
}
|
||||
|
||||
func (h helper) lookupApplicationByName(name string) *types.Application {
|
||||
res, _, err := store.SearchApplications(context.Background(), service.DefaultStore, types.ApplicationFilter{
|
||||
Name: name,
|
||||
})
|
||||
h.noError(err)
|
||||
if len(res) == 0 {
|
||||
return nil
|
||||
}
|
||||
return res[0]
|
||||
}
|
||||
|
||||
func TestApplicationRead(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
|
||||
@ -122,6 +134,25 @@ func TestApplicationCreate(t *testing.T) {
|
||||
End()
|
||||
}
|
||||
|
||||
func TestApplicationCreate_weight(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.allow(types.SystemRBACResource, "application.create")
|
||||
name := "name_weight_create_" + rs()
|
||||
|
||||
h.apiInit().
|
||||
Post("/application/").
|
||||
FormData("name", name).
|
||||
FormData("weight", "10").
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
res := h.lookupApplicationByName(name)
|
||||
h.a.NotNil(res)
|
||||
h.a.Equal(10, res.Weight)
|
||||
}
|
||||
|
||||
func TestApplicationUpdateForbidden(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
u := h.repoMakeApplication()
|
||||
@ -159,6 +190,75 @@ func TestApplicationUpdate(t *testing.T) {
|
||||
h.a.Equal(newName, res.Name)
|
||||
}
|
||||
|
||||
func TestApplicationUpdate_weight(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
res := h.repoMakeApplication()
|
||||
h.allow(types.ApplicationRBACResource.AppendWildcard(), "update")
|
||||
|
||||
newName := "updated-" + rs()
|
||||
newHandle := "updated-" + rs()
|
||||
|
||||
h.apiInit().
|
||||
Put(fmt.Sprintf("/application/%d", res.ID)).
|
||||
Header("Accept", "application/json").
|
||||
FormData("name", newName).
|
||||
FormData("handle", newHandle).
|
||||
FormData("weight", "20").
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
res = h.lookupApplicationByID(res.ID)
|
||||
h.a.NotNil(res)
|
||||
h.a.Equal(20, res.Weight)
|
||||
}
|
||||
|
||||
func TestApplicationReorder_forbiden(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.allow(types.ApplicationRBACResource.AppendWildcard(), "update")
|
||||
a := h.repoMakeApplication()
|
||||
b := h.repoMakeApplication()
|
||||
c := h.repoMakeApplication()
|
||||
h.deny(types.ApplicationRBACResource.AppendID(b.ID), "update")
|
||||
|
||||
h.apiInit().
|
||||
Post("/application/reorder").
|
||||
Header("Accept", "application/json").
|
||||
JSON(fmt.Sprintf(`{ "applicationIDs": ["%d", "%d", "%d"] }`, b.ID, a.ID, c.ID)).
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertError("not allowed to update this application")).
|
||||
End()
|
||||
}
|
||||
|
||||
func TestApplicationReorder(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
h.allow(types.ApplicationRBACResource.AppendWildcard(), "update")
|
||||
a := h.repoMakeApplication()
|
||||
b := h.repoMakeApplication()
|
||||
c := h.repoMakeApplication()
|
||||
|
||||
h.apiInit().
|
||||
Post("/application/reorder").
|
||||
Header("Accept", "application/json").
|
||||
JSON(fmt.Sprintf(`{ "applicationIDs": ["%d", "%d", "%d"] }`, b.ID, a.ID, c.ID)).
|
||||
Expect(t).
|
||||
Status(http.StatusOK).
|
||||
Assert(helpers.AssertNoErrors).
|
||||
End()
|
||||
|
||||
check := func(app uint64, w int) {
|
||||
res := h.lookupApplicationByID(app)
|
||||
h.a.NotNil(res)
|
||||
h.a.Equal(w, res.Weight)
|
||||
}
|
||||
|
||||
check(b.ID, 1)
|
||||
check(a.ID, 2)
|
||||
check(c.ID, 3)
|
||||
}
|
||||
|
||||
func TestApplicationDeleteForbidden(t *testing.T) {
|
||||
h := newHelper(t)
|
||||
u := h.repoMakeApplication()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user