feat: option to disallow public org registration (#6917)

* feat: return 404 or 409 if org reg disallowed

* fix: system limit permissions

* feat: add iam limits api

* feat: disallow public org registrations on default instance

* add integration test

* test: integration

* fix test

* docs: describe public org registrations

* avoid updating docs deps

* fix system limits integration test

* silence integration tests

* fix linting

* ignore strange linter complaints

* review

* improve reset properties naming

* redefine the api

* use restrictions aggregate

* test query

* simplify and test projection

* test commands

* fix unit tests

* move integration test

* support restrictions on default instance

* also test GetRestrictions

* self review

* lint

* abstract away resource owner

* fix tests

* lint
This commit is contained in:
Elio Bischof
2023-11-22 10:29:38 +01:00
committed by GitHub
parent 5fa596a871
commit 76fe032b5f
45 changed files with 1280 additions and 123 deletions

View File

@@ -119,7 +119,7 @@ func NewUpsertStatement(event eventstore.Event, conflictCols []Column, values []
config.err = ErrNoValues
}
updateCols, updateVals := getUpdateCols(cols, conflictTarget)
updateCols, updateVals := getUpdateCols(values, conflictTarget)
if len(updateCols) == 0 || len(updateVals) == 0 {
config.err = ErrNoValues
}
@@ -141,17 +141,38 @@ func NewUpsertStatement(event eventstore.Event, conflictCols []Column, values []
return NewStatement(event, exec(config, q, opts))
}
func getUpdateCols(cols, conflictTarget []string) (updateCols, updateVals []string) {
var _ ValueContainer = (*onlySetValueOnInsert)(nil)
type onlySetValueOnInsert struct {
Table string
Value interface{}
}
func (c *onlySetValueOnInsert) GetValue() interface{} {
return c.Value
}
func OnlySetValueOnInsert(table string, value interface{}) *onlySetValueOnInsert {
return &onlySetValueOnInsert{
Table: table,
Value: value,
}
}
func getUpdateCols(cols []Column, conflictTarget []string) (updateCols, updateVals []string) {
updateCols = make([]string, len(cols))
updateVals = make([]string, len(cols))
copy(updateCols, cols)
for i := len(updateCols) - 1; i >= 0; i-- {
updateVals[i] = "EXCLUDED." + updateCols[i]
for i := len(cols) - 1; i >= 0; i-- {
col := cols[i]
table := "EXCLUDED"
if onlyOnInsert, ok := col.Value.(*onlySetValueOnInsert); ok {
table = onlyOnInsert.Table
}
updateCols[i] = col.Name
updateVals[i] = table + "." + col.Name
for _, conflict := range conflictTarget {
if conflict == updateCols[i] {
if conflict == col.Name {
copy(updateCols[i:], updateCols[i+1:])
updateCols[len(updateCols)-1] = ""
updateCols = updateCols[:len(updateCols)-1]
@@ -383,6 +404,10 @@ func NewCopyStatement(event eventstore.Event, conflictCols, from, to []Column, n
return NewStatement(event, exec(config, q, opts))
}
type ValueContainer interface {
GetValue() interface{}
}
func columnsToQuery(cols []Column) (names []string, parameters []string, values []interface{}) {
names = make([]string, len(cols))
values = make([]interface{}, len(cols))
@@ -390,10 +415,13 @@ func columnsToQuery(cols []Column) (names []string, parameters []string, values
var parameterIndex int
for i, col := range cols {
names[i] = col.Name
if c, ok := col.Value.(Column); ok {
switch c := col.Value.(type) {
case Column:
parameters[i] = c.Name
continue
} else {
case ValueContainer:
values[parameterIndex] = c.GetValue()
default:
values[parameterIndex] = col.Value
}
parameters[i] = "$" + strconv.Itoa(parameterIndex+1)

View File

@@ -358,7 +358,7 @@ func TestNewUpsertStatement(t *testing.T) {
},
},
{
name: "correct UPDATE single col",
name: "correct *onlySetValueOnInsert",
args: args{
table: "my_table",
event: &testEvent{
@@ -372,11 +372,18 @@ func TestNewUpsertStatement(t *testing.T) {
values: []Column{
{
Name: "col1",
Value: "val",
Value: "val1",
},
{
Name: "col2",
Value: "val",
Value: "val2",
},
{
Name: "col3",
Value: &onlySetValueOnInsert{
Table: "some.table",
Value: "val3",
},
},
},
},
@@ -388,8 +395,53 @@ func TestNewUpsertStatement(t *testing.T) {
executer: &wantExecuter{
params: []params{
{
query: "INSERT INTO my_table (col1, col2) VALUES ($1, $2) ON CONFLICT (col1) DO UPDATE SET col2 = EXCLUDED.col2",
args: []interface{}{"val", "val"},
query: "INSERT INTO my_table (col1, col2, col3) VALUES ($1, $2, $3) ON CONFLICT (col1) DO UPDATE SET (col2, col3) = (EXCLUDED.col2, some.table.col3)",
args: []interface{}{"val1", "val2", "val3"},
},
},
shouldExecute: true,
},
isErr: func(err error) bool {
return err == nil
},
},
},
{
name: "correct all *onlySetValueOnInsert",
args: args{
table: "my_table",
event: &testEvent{
aggregateType: "agg",
sequence: 1,
previousSequence: 0,
},
conflictCols: []Column{
NewCol("col1", nil),
},
values: []Column{
{
Name: "col1",
Value: "val1",
},
{
Name: "col2",
Value: &onlySetValueOnInsert{
Table: "some.table",
Value: "val2",
},
},
},
},
want: want{
table: "my_table",
aggregateType: "agg",
sequence: 1,
previousSequence: 1,
executer: &wantExecuter{
params: []params{
{
query: "INSERT INTO my_table (col1, col2) VALUES ($1, $2) ON CONFLICT (col1) DO UPDATE SET col2 = some.table.col2",
args: []interface{}{"val1", "val2"},
},
},
shouldExecute: true,