Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions api/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ func (h IdentityHandler) Get(ctx *gin.Context) {
// @description filters:
// @description - kind
// @description - name
// @description - isDefault
// @description - application.id
// @tags dependencies
// @tags identities
Expand All @@ -95,7 +94,6 @@ func (h IdentityHandler) List(ctx *gin.Context) {
_ = ctx.Error(err)
return
}
filter = filter.Renamed("default", "`default`")
// Find
var list []model.Identity
db := h.DB(ctx)
Expand Down Expand Up @@ -233,6 +231,20 @@ func (h IdentityHandler) Create(ctx *gin.Context) {
}
r.With(m)

rtx := RichContext(ctx)
tr := trigger.Identity{
Trigger: trigger.Trigger{
TaskManager: rtx.TaskManager,
Client: rtx.Client,
DB: h.DB(ctx),
},
}
err = tr.Created(m)
if err != nil {
_ = ctx.Error(err)
return
}

h.Respond(ctx, http.StatusCreated, r)
}

Expand Down
5 changes: 4 additions & 1 deletion hack/add/identity.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ host="${HOST:-localhost:8080}"

id="${1:-0}" # 0=system-assigned.
name="${2:-Test}"
kind="${3:-source}"
def="${4:-0}"

# create identity.
curl -X POST ${host}/identities \
Expand All @@ -13,7 +15,8 @@ curl -X POST ${host}/identities \
"
id: ${id}
name: ${name}
kind: source
kind: ${kind}
default: ${def}
description: ${name} Description
user: userA
password: passwordA
Expand Down
30 changes: 20 additions & 10 deletions hack/update/identity.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

host="${HOST:-localhost:8080}"

curl -X PUT ${host}/identities/1 -d \
'{
"kind": "git",
"name":"test-git",
"description": "Forklift",
"user": "userB",
"password": "passwordB",
"key": "keyA",
"settings": "settingsB"
}' | jq -M .
id="${1:-0}" # 0=system-assigned.
name="${2:-Test}"
kind="${3:-source}"
def="${4:-0}"

# update an identity.
curl -X PUT ${host}/identities/${id} \
-H 'Content-Type:application/x-yaml' \
-H 'Accept:application/x-yaml' \
-d \
"
id: ${id}
name: ${name}
kind: ${kind}
default: ${def}
description: ${name} Description
user: userA
password: passwordA
key: keyA
settings: settingsA
"
30 changes: 30 additions & 0 deletions test/api/identity/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,33 @@ func TestIdentityNotCreateDupDefault(t *testing.T) {
}()
}
}

func TestIdentityNotUpdateDupDefault(t *testing.T) {
def := &api.Identity{
Name: "Test",
Kind: "Test",
Default: true,
}
err := Identity.Create(def)
assert.Must(t, err)
defer func() {
_ = Identity.Delete(def.ID)
}()
other := &api.Identity{
Name: "Test2",
Kind: "Test",
}
err = Identity.Create(other)
assert.Must(t, err)
defer func() {
_ = Identity.Delete(other.ID)
}()
other.Default = true
err = Identity.Update(other)
if err == nil {
t.Errorf("Created duplicate (default) identity: %v", other)
defer func() {
_ = Identity.Delete(other.ID)
}()
}
}
114 changes: 106 additions & 8 deletions trigger/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ package trigger

import (
"github.com/konveyor/tackle2-hub/model"
"gorm.io/gorm/clause"
)

// Identity trigger.
type Identity struct {
Trigger
}

// Updated model created trigger.
// Created model created trigger.
func (r *Identity) Created(m *model.Identity) (err error) {
if m.Default {
err = r.Updated(m)
}
return
}

// Updated model updated trigger.
func (r *Identity) Updated(m *model.Identity) (err error) {
tr := Application{
Trigger: Trigger{
Expand All @@ -19,18 +26,109 @@ func (r *Identity) Updated(m *model.Identity) (err error) {
DB: r.DB,
},
}
id := m.ID
m = &model.Identity{}
db := r.DB.Preload(clause.Associations)
err = db.First(m, id).Error
affected, err := r.affected(m)
if err != nil {
return
}
for _, batch := range affected {
var appList []model.Application
err = r.DB.Find(&appList, batch).Error
if err != nil {
return
}
for i := range appList {
err = tr.Updated(&appList[i])
if err != nil {
return
}
}
}
return
}

// affected returns the affected application ids.
// An application is affected when:
//- the changed identity is directly associated
//- the changed identity is the default (for the kind) and an
// application does not have an identity of the same kind
// directly associated.
func (r *Identity) affected(changed *model.Identity) (appIds [][]uint, err error) {
type M struct {
AppId uint
Id uint
Kind string
Default bool
}
db := r.DB.Select(
"a.ID AppId",
"i.ID Id",
"i.Kind Kind",
"i.`Default` `Default`")
db = db.Table("Application a")
db = db.Joins("LEFT JOIN ApplicationIdentity j ON j.ApplicationID = a.ID")
db = db.Joins("LEFT JOIN Identity i ON i.ID = j.IdentityID AND i.Kind = ?", changed.Kind)
cursor, err := db.Rows()
if err != nil {
return
}
for i := range m.Applications {
err = tr.Updated(&m.Applications[i])
defer func() {
_ = cursor.Close()
}()
m := M{}
var records []M
for cursor.Next() {
err = db.ScanRows(cursor, &m)
if err != nil {
return
}
records = append(records, m)
}
// direct association.
// map[application.ID]map[Identity.ID]struct{}
direct := make(map[uint]map[uint]struct{})
for _, m2 := range records {
if m2.Id > 0 {
ids, found := direct[m2.Id]
if !found {
ids = make(map[uint]struct{})
direct[m2.AppId] = ids
}
ids[m2.Id] = struct{}{}
}
}
// indirect association.
// map[application.ID]struct{}
indirect := make(map[uint]struct{})
if changed.Default {
for _, m2 := range records {
_, hasDirect := direct[m2.AppId]
if !hasDirect {
indirect[m2.AppId] = struct{}{}
}
}
}
// batch
batch := make([]uint, 0, 100)
add := func(id uint) {
if len(batch) == cap(batch) {
appIds = append(appIds, batch)
batch = make([]uint, 0, cap(batch))
}
batch = append(batch, id)
}
defer func() {
if len(batch) > 0 {
appIds = append(appIds, batch)
}
}()
for appId, ids := range direct {
_, found := ids[changed.ID]
if found {
add(appId)
}
}
for appId, _ := range indirect {
add(appId)
}
return
}
Loading