Compare commits

...

5 Commits

38 changed files with 660 additions and 317 deletions
+24 -11
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "fmt" import "fmt"
@@ -261,16 +262,18 @@ func (s *Store) GetAuthProviderWithGroupMappings(id string) (models.AuthProvider
} }
func (s *Store) CountAuthProviderUsers(id string) (int, error) { func (s *Store) CountAuthProviderUsers(id string) (int, error) {
var row *sql.Row return countAuthProviderUsers(s, id)
}
func countAuthProviderUsers(execer sqlExecutor, id string) (int, error) {
var count int var count int
var err error var err error
row = s.QueryRow(`SELECT COUNT(*) FROM users WHERE auth_provider_id = (SELECT id FROM auth_providers WHERE public_id = ?)`, strings.TrimSpace(id)) err = execer.QueryRow(`SELECT COUNT(*) FROM users WHERE auth_provider_id = (SELECT id FROM auth_providers WHERE public_id = ?)`, strings.TrimSpace(id)).Scan(&count)
err = row.Scan(&count)
return count, err return count, err
} }
func (s *Store) CreateAuthProvider(item models.AuthProvider) (models.AuthProvider, error) { func (s *Store) CreateAuthProvider(ctx context.Context, item models.AuthProvider) (models.AuthProvider, error) {
var tx txExecutor var tx txExecutor
var err error var err error
var owned bool var owned bool
@@ -293,7 +296,7 @@ func (s *Store) CreateAuthProvider(item models.AuthProvider) (models.AuthProvide
item.GroupSyncMode, err = normalizeAuthProviderGroupSyncMode(item.GroupSyncMode) item.GroupSyncMode, err = normalizeAuthProviderGroupSyncMode(item.GroupSyncMode)
if err != nil { return item, err } if err != nil { return item, err }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
_, err = tx.Exec(`INSERT INTO auth_providers ( _, err = tx.Exec(`INSERT INTO auth_providers (
@@ -331,7 +334,7 @@ func (s *Store) CreateAuthProvider(item models.AuthProvider) (models.AuthProvide
return s.GetAuthProviderWithGroupMappings(item.ID) return s.GetAuthProviderWithGroupMappings(item.ID)
} }
func (s *Store) UpdateAuthProvider(item models.AuthProvider) (models.AuthProvider, error) { func (s *Store) UpdateAuthProvider(ctx context.Context, item models.AuthProvider) (models.AuthProvider, error) {
var tx txExecutor var tx txExecutor
var err error var err error
var owned bool var owned bool
@@ -351,7 +354,7 @@ func (s *Store) UpdateAuthProvider(item models.AuthProvider) (models.AuthProvide
return item, err return item, err
} }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
_, err = tx.Exec(`UPDATE auth_providers SET _, err = tx.Exec(`UPDATE auth_providers SET
@@ -395,22 +398,32 @@ func (s *Store) UpdateAuthProvider(item models.AuthProvider) (models.AuthProvide
return s.GetAuthProviderWithGroupMappings(item.ID) return s.GetAuthProviderWithGroupMappings(item.ID)
} }
func (s *Store) DeleteAuthProvider(id string, force bool) error { func (s *Store) DeleteAuthProvider(ctx context.Context, id string, force bool) error {
var count int var count int
var err error var err error
var tx txExecutor
var owned bool
if strings.TrimSpace(id) == BuiltinDBProviderPublicID { if strings.TrimSpace(id) == BuiltinDBProviderPublicID {
return errors.New("builtin provider cannot be deleted") return errors.New("builtin provider cannot be deleted")
} }
tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return err }
if !force { if !force {
count, err = s.CountAuthProviderUsers(id) count, err = countAuthProviderUsers(tx, id)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
if count > 0 { if count > 0 {
rollbackIfOwned(tx, owned)
return errors.New("provider has associated users") return errors.New("provider has associated users")
} }
} }
_, err = s.Exec(`DELETE FROM auth_providers WHERE public_id = ?`, strings.TrimSpace(id)) _, err = tx.Exec(`DELETE FROM auth_providers WHERE public_id = ?`, strings.TrimSpace(id))
return err if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
+101 -25
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "strings" import "strings"
@@ -59,13 +60,15 @@ func (s *Store) ListBlockComments(boardID, blockID string) ([]models.BlockCommen
return comments, rows.Err() return comments, rows.Err()
} }
func (s *Store) CreateBlockComment(boardID, blockID, content, userID string) (models.BlockComment, error) { func (s *Store) CreateBlockComment(ctx context.Context, boardID, blockID, content, userID string) (models.BlockComment, error) {
var id string var id string
var err error var err error
var now int64 var now int64
var internalBlockID int64 var internalBlockID int64
var internalUserID int64 var internalUserID int64
var bc models.BlockComment var bc models.BlockComment
var tx txExecutor
var owned bool
id, err = util.NewID() id, err = util.NewID()
if err != nil { if err != nil {
@@ -73,37 +76,50 @@ func (s *Store) CreateBlockComment(boardID, blockID, content, userID string) (mo
} }
now = time.Now().Unix() now = time.Now().Unix()
err = s.QueryRow(` tx, owned, err = s.beginImmediateContext(ctx)
if err != nil {
return bc, err
}
err = tx.QueryRow(`
SELECT bl.id FROM blocks bl SELECT bl.id FROM blocks bl
JOIN boards brd ON brd.id = bl.board_id JOIN boards brd ON brd.id = bl.board_id
WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0`, WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0`,
boardID, blockID).Scan(&internalBlockID) boardID, blockID).Scan(&internalBlockID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return bc, sql.ErrNoRows return bc, sql.ErrNoRows
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return bc, err return bc, err
} }
err = s.QueryRow(`SELECT id FROM users WHERE public_id = ?`, userID).Scan(&internalUserID) err = tx.QueryRow(`SELECT id FROM users WHERE public_id = ?`, userID).Scan(&internalUserID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return bc, err return bc, err
} }
_, err = s.Exec(` _, err = tx.Exec(`
INSERT INTO block_comments (public_id, block_id, content, created_by, created_at, updated_at) INSERT INTO block_comments (public_id, block_id, content, created_by, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?)`, VALUES (?, ?, ?, ?, ?, ?)`,
id, internalBlockID, content, internalUserID, now, now) id, internalBlockID, content, internalUserID, now, now)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return bc, err return bc, err
} }
err = s.QueryRow( err = tx.QueryRow(
`SELECT`+blockCommentSelectCols+blockCommentSelectFrom+` `SELECT`+blockCommentSelectCols+blockCommentSelectFrom+`
WHERE c.public_id = ?`, id).Scan( WHERE c.public_id = ?`, id).Scan(
&bc.ID, &bc.BlockID, &bc.Content, &bc.ID, &bc.BlockID, &bc.Content,
&bc.CreatedBy, &bc.CreatedByName, &bc.CreatedBy, &bc.CreatedByName,
&bc.CreatedAt, &bc.UpdatedAt, &bc.DeleteAt) &bc.CreatedAt, &bc.UpdatedAt, &bc.DeleteAt)
if err != nil {
rollbackIfOwned(tx, owned)
return bc, err
}
err = commitIfOwned(tx, owned)
if err != nil { if err != nil {
return bc, err return bc, err
} }
@@ -189,7 +205,7 @@ func (s *Store) ListBlockChecklistItems(boardID, blockID string) ([]models.Block
return items, rows.Err() return items, rows.Err()
} }
func (s *Store) CreateBlockChecklistItem(boardID, blockID, title, userID string) (models.BlockChecklistItem, error) { func (s *Store) CreateBlockChecklistItem(ctx context.Context, boardID, blockID, title, userID string) (models.BlockChecklistItem, error) {
var id string var id string
var err error var err error
var now int64 var now int64
@@ -197,6 +213,8 @@ func (s *Store) CreateBlockChecklistItem(boardID, blockID, title, userID string)
var internalUserID int64 var internalUserID int64
var maxOrder int64 var maxOrder int64
var item models.BlockChecklistItem var item models.BlockChecklistItem
var tx txExecutor
var owned bool
id, err = util.NewID() id, err = util.NewID()
if err != nil { if err != nil {
@@ -204,40 +222,57 @@ func (s *Store) CreateBlockChecklistItem(boardID, blockID, title, userID string)
} }
now = time.Now().Unix() now = time.Now().Unix()
err = s.QueryRow(` tx, owned, err = s.beginImmediateContext(ctx)
if err != nil {
return item, err
}
err = tx.QueryRow(`
SELECT bl.id FROM blocks bl SELECT bl.id FROM blocks bl
JOIN boards brd ON brd.id = bl.board_id JOIN boards brd ON brd.id = bl.board_id
WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0`, WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0`,
boardID, blockID).Scan(&internalBlockID) boardID, blockID).Scan(&internalBlockID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return item, sql.ErrNoRows return item, sql.ErrNoRows
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = s.QueryRow(`SELECT id FROM users WHERE public_id = ?`, userID).Scan(&internalUserID) err = tx.QueryRow(`SELECT id FROM users WHERE public_id = ?`, userID).Scan(&internalUserID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = s.QueryRow(`SELECT COALESCE(MAX(display_order), -1) FROM block_checklist_items WHERE block_id = ? AND delete_at = 0`, internalBlockID).Scan(&maxOrder) err = tx.QueryRow(`SELECT COALESCE(MAX(display_order), -1) FROM block_checklist_items WHERE block_id = ? AND delete_at = 0`, internalBlockID).Scan(&maxOrder)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
_, err = s.Exec(` _, err = tx.Exec(`
INSERT INTO block_checklist_items (public_id, block_id, title, done, display_order, created_by, updated_by, created_at, updated_at) INSERT INTO block_checklist_items (public_id, block_id, title, done, display_order, created_by, updated_by, created_at, updated_at)
VALUES (?, ?, ?, 0, ?, ?, ?, ?, ?)`, VALUES (?, ?, ?, 0, ?, ?, ?, ?, ?)`,
id, internalBlockID, title, maxOrder+1, internalUserID, internalUserID, now, now) id, internalBlockID, title, maxOrder+1, internalUserID, internalUserID, now, now)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = scanBlockChecklistItem( err = scanBlockChecklistItem(
s.QueryRow(`SELECT`+blockChecklistItemSelectCols+blockChecklistItemSelectFrom+` WHERE ci.public_id = ?`, id), tx.QueryRow(`SELECT`+blockChecklistItemSelectCols+blockChecklistItemSelectFrom+` WHERE ci.public_id = ?`, id),
&item) &item)
return item, err if err != nil {
rollbackIfOwned(tx, owned)
return item, err
}
err = commitIfOwned(tx, owned)
if err != nil {
return item, err
}
return item, nil
} }
func (s *Store) UpdateBlockChecklistItem(boardID, blockID, itemID, title string, done bool, userID string) (models.BlockChecklistItem, error) { func (s *Store) UpdateBlockChecklistItem(boardID, blockID, itemID, title string, done bool, userID string) (models.BlockChecklistItem, error) {
@@ -303,7 +338,7 @@ func (s *Store) DeleteBlockChecklistItem(boardID, blockID, itemID string) error
return nil return nil
} }
func (s *Store) ReorderBlockChecklistItems(boardID, blockID string, ids []string) ([]models.BlockChecklistItem, error) { func (s *Store) ReorderBlockChecklistItems(ctx context.Context, boardID, blockID string, ids []string) ([]models.BlockChecklistItem, error) {
var internalBlockID int64 var internalBlockID int64
var err error var err error
var now int64 var now int64
@@ -315,7 +350,7 @@ func (s *Store) ReorderBlockChecklistItems(boardID, blockID string, ids []string
var n int64 var n int64
now = time.Now().Unix() now = time.Now().Unix()
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -411,44 +446,62 @@ func (s *Store) ListBlockAttachments(boardID, blockID string) ([]models.BlockAtt
return items, rows.Err() return items, rows.Err()
} }
func (s *Store) CreateBlockAttachment(boardID, blockID string, item models.BlockAttachment) (models.BlockAttachment, error) { func (s *Store) CreateBlockAttachment(ctx context.Context, boardID, blockID string, item models.BlockAttachment) (models.BlockAttachment, error) {
var err error var err error
var internalBlockID int64 var internalBlockID int64
var internalUserID int64 var internalUserID int64
var now int64 var now int64
var tx txExecutor
var owned bool
now = time.Now().Unix() now = time.Now().Unix()
err = s.QueryRow(` tx, owned, err = s.beginImmediateContext(ctx)
if err != nil {
return item, err
}
err = tx.QueryRow(`
SELECT bl.id FROM blocks bl SELECT bl.id FROM blocks bl
JOIN boards brd ON brd.id = bl.board_id JOIN boards brd ON brd.id = bl.board_id
WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0`, WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0`,
boardID, blockID).Scan(&internalBlockID) boardID, blockID).Scan(&internalBlockID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return item, sql.ErrNoRows return item, sql.ErrNoRows
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = s.QueryRow(`SELECT id FROM users WHERE public_id = ?`, item.CreatedBy).Scan(&internalUserID) err = tx.QueryRow(`SELECT id FROM users WHERE public_id = ?`, item.CreatedBy).Scan(&internalUserID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
item.BlockID = blockID item.BlockID = blockID
item.CreatedAt = now item.CreatedAt = now
_, err = s.Exec(` _, err = tx.Exec(`
INSERT INTO block_attachments (public_id, block_id, filename, content_type, size, storage_path, created_by, created_at) INSERT INTO block_attachments (public_id, block_id, filename, content_type, size, storage_path, created_by, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
item.ID, internalBlockID, item.Filename, item.ContentType, item.Size, item.StoragePath, internalUserID, now) item.ID, internalBlockID, item.Filename, item.ContentType, item.Size, item.StoragePath, internalUserID, now)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = scanBlockAttachment( err = scanBlockAttachment(
s.QueryRow(`SELECT`+blockAttachmentSelectCols+blockAttachmentSelectFrom+` WHERE ba.public_id = ?`, item.ID), tx.QueryRow(`SELECT`+blockAttachmentSelectCols+blockAttachmentSelectFrom+` WHERE ba.public_id = ?`, item.ID),
&item) &item)
return item, err if err != nil {
rollbackIfOwned(tx, owned)
return item, err
}
err = commitIfOwned(tx, owned)
if err != nil {
return item, err
}
return item, nil
} }
func (s *Store) GetBlockAttachment(boardID, blockID, attachmentID string) (models.BlockAttachment, error) { func (s *Store) GetBlockAttachment(boardID, blockID, attachmentID string) (models.BlockAttachment, error) {
@@ -467,20 +520,36 @@ func (s *Store) GetBlockAttachment(boardID, blockID, attachmentID string) (model
return item, err return item, err
} }
func (s *Store) DeleteBlockAttachment(boardID, blockID, attachmentID string) (models.BlockAttachment, error) { func (s *Store) DeleteBlockAttachment(ctx context.Context, boardID, blockID, attachmentID string) (models.BlockAttachment, error) {
var item models.BlockAttachment var item models.BlockAttachment
var now int64 var now int64
var result sql.Result var result sql.Result
var n int64 var n int64
var err error var err error
var tx txExecutor
var owned bool
item, err = s.GetBlockAttachment(boardID, blockID, attachmentID) tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { if err != nil {
return item, err return item, err
} }
err = scanBlockAttachment(
tx.QueryRow(`SELECT`+blockAttachmentSelectCols+blockAttachmentSelectFrom+`
JOIN boards brd ON brd.id = bl.board_id
WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0 AND ba.public_id = ? AND ba.delete_at = 0`,
boardID, blockID, attachmentID),
&item)
if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return item, ErrBlockAttachmentNotFound
}
if err != nil {
rollbackIfOwned(tx, owned)
return item, err
}
now = time.Now().Unix() now = time.Now().Unix()
result, err = s.Exec(` result, err = tx.Exec(`
UPDATE block_attachments SET delete_at = ? UPDATE block_attachments SET delete_at = ?
WHERE public_id = ? WHERE public_id = ?
AND delete_at = 0 AND delete_at = 0
@@ -490,16 +559,23 @@ func (s *Store) DeleteBlockAttachment(boardID, blockID, attachmentID string) (mo
WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0 WHERE brd.public_id = ? AND bl.public_id = ? AND bl.delete_at = 0
)`, now, attachmentID, boardID, blockID) )`, now, attachmentID, boardID, blockID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
n, err = result.RowsAffected() n, err = result.RowsAffected()
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
if n == 0 { if n == 0 {
rollbackIfOwned(tx, owned)
return item, ErrBlockAttachmentNotFound return item, ErrBlockAttachmentNotFound
} }
item.DeleteAt = now item.DeleteAt = now
err = commitIfOwned(tx, owned)
if err != nil {
return item, err
}
return item, nil return item, nil
} }
@@ -701,7 +777,7 @@ func (s *Store) listBlockAssigneesForBoard(boardID string) (map[string][]models.
return result, rows.Err() return result, rows.Err()
} }
func (s *Store) UpsertBlockProperties(boardID, blockID string, props models.BlockProperties) (models.BlockProperties, error) { func (s *Store) UpsertBlockProperties(ctx context.Context, boardID, blockID string, props models.BlockProperties) (models.BlockProperties, error) {
var internalBlockID int64 var internalBlockID int64
var err error var err error
var tx txExecutor var tx txExecutor
@@ -712,7 +788,7 @@ func (s *Store) UpsertBlockProperties(boardID, blockID string, props models.Bloc
var affected int64 var affected int64
assigneeIDs = normalizeBlockAssigneeIDs(props) assigneeIDs = normalizeBlockAssigneeIDs(props)
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return props, err return props, err
} }
+103 -26
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "fmt" import "fmt"
@@ -65,7 +66,7 @@ func (s *Store) SeedDefaultBoardFieldValues(boardID string) error {
Label: item.Label, Label: item.Label,
Color: item.Color, Color: item.Color,
} }
_, err = s.CreateBoardFieldValue(boardID, fv) _, err = s.CreateBoardFieldValue(context.Background(), boardID, fv)
if err != nil { if err != nil {
return err return err
} }
@@ -74,12 +75,16 @@ func (s *Store) SeedDefaultBoardFieldValues(boardID string) error {
} }
func (s *Store) ListBoardFieldValues(boardID, field string) ([]models.BoardFieldValue, error) { func (s *Store) ListBoardFieldValues(boardID, field string) ([]models.BoardFieldValue, error) {
return listBoardFieldValues(s, boardID, field)
}
func listBoardFieldValues(execer sqlExecutor, boardID string, field string) ([]models.BoardFieldValue, error) {
var rows *sql.Rows var rows *sql.Rows
var err error var err error
var result []models.BoardFieldValue var result []models.BoardFieldValue
var fv models.BoardFieldValue var fv models.BoardFieldValue
rows, err = s.Query( rows, err = execer.Query(
`SELECT`+fieldValueCols+fieldValueFrom+` `SELECT`+fieldValueCols+fieldValueFrom+`
WHERE brd.public_id = ? AND fv.field = ? WHERE brd.public_id = ? AND fv.field = ?
ORDER BY fv.display_order ASC, fv.created_at ASC`, boardID, field) ORDER BY fv.display_order ASC, fv.created_at ASC`, boardID, field)
@@ -98,13 +103,15 @@ func (s *Store) ListBoardFieldValues(boardID, field string) ([]models.BoardField
return result, rows.Err() return result, rows.Err()
} }
func (s *Store) CreateBoardFieldValue(boardID string, fv models.BoardFieldValue) (models.BoardFieldValue, error) { func (s *Store) CreateBoardFieldValue(ctx context.Context, boardID string, fv models.BoardFieldValue) (models.BoardFieldValue, error) {
var id string var id string
var err error var err error
var now int64 var now int64
var internalBoardID int64 var internalBoardID int64
var maxOrder int64 var maxOrder int64
var result models.BoardFieldValue var result models.BoardFieldValue
var tx txExecutor
var owned bool
id, err = util.NewID() id, err = util.NewID()
if err != nil { if err != nil {
@@ -112,35 +119,51 @@ func (s *Store) CreateBoardFieldValue(boardID string, fv models.BoardFieldValue)
} }
now = time.Now().Unix() now = time.Now().Unix()
err = s.QueryRow(`SELECT id FROM boards WHERE public_id = ? AND delete_at = 0`, boardID).Scan(&internalBoardID) tx, owned, err = s.beginImmediateContext(ctx)
if err != nil {
return result, err
}
err = tx.QueryRow(`SELECT id FROM boards WHERE public_id = ? AND delete_at = 0`, boardID).Scan(&internalBoardID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return result, ErrBoardNotFound return result, ErrBoardNotFound
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return result, err return result, err
} }
err = s.QueryRow( err = tx.QueryRow(
`SELECT COALESCE(MAX(display_order), -1) FROM board_field_values WHERE board_id = ? AND field = ?`, `SELECT COALESCE(MAX(display_order), -1) FROM board_field_values WHERE board_id = ? AND field = ?`,
internalBoardID, fv.Field).Scan(&maxOrder) internalBoardID, fv.Field).Scan(&maxOrder)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return result, err return result, err
} }
_, err = s.Exec(` _, err = tx.Exec(`
INSERT INTO board_field_values INSERT INTO board_field_values
(public_id, board_id, field, value, label, color, display_order, start_date, end_date, created_at, updated_at) (public_id, board_id, field, value, label, color, display_order, start_date, end_date, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
id, internalBoardID, fv.Field, fv.Value, fv.Label, fv.Color, id, internalBoardID, fv.Field, fv.Value, fv.Label, fv.Color,
maxOrder+1, fv.StartDate, fv.EndDate, now, now) maxOrder+1, fv.StartDate, fv.EndDate, now, now)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return result, err return result, err
} }
err = scanFieldValue( err = scanFieldValue(
s.QueryRow(`SELECT`+fieldValueCols+fieldValueFrom+` WHERE fv.public_id = ?`, id), tx.QueryRow(`SELECT`+fieldValueCols+fieldValueFrom+` WHERE fv.public_id = ?`, id),
&result) &result)
return result, err if err != nil {
rollbackIfOwned(tx, owned)
return result, err
}
err = commitIfOwned(tx, owned)
if err != nil {
return result, err
}
return result, nil
} }
func (s *Store) UpdateBoardFieldValue(boardID, valueID string, fv models.BoardFieldValue) (models.BoardFieldValue, error) { func (s *Store) UpdateBoardFieldValue(boardID, valueID string, fv models.BoardFieldValue) (models.BoardFieldValue, error) {
@@ -188,13 +211,17 @@ func blockPropsCol(field string) (string, bool) {
return col, ok return col, ok
} }
func (s *Store) CountBoardFieldValueRefs(boardID, field, value string) (int, error) { func countBoardFieldValueRefs(execer sqlExecutor, boardID string, field string, value string) (int, error) {
var col, ok = blockPropsCol(field) var col string
var ok bool
var count int
var err error
col, ok = blockPropsCol(field)
if !ok { if !ok {
return 0, nil return 0, nil
} }
var count int err = execer.QueryRow(
var err = s.QueryRow(
fmt.Sprintf(` fmt.Sprintf(`
SELECT COUNT(*) FROM block_properties bp SELECT COUNT(*) FROM block_properties bp
JOIN blocks bl ON bl.id = bp.block_id JOIN blocks bl ON bl.id = bp.block_id
@@ -204,74 +231,124 @@ func (s *Store) CountBoardFieldValueRefs(boardID, field, value string) (int, err
return count, err return count, err
} }
func (s *Store) ReorderBoardFieldValues(boardID, field string, ids []string) ([]models.BoardFieldValue, error) { func (s *Store) CountBoardFieldValueRefs(boardID, field, value string) (int, error) {
return countBoardFieldValueRefs(s, boardID, field, value)
}
func (s *Store) ReorderBoardFieldValues(ctx context.Context, boardID, field string, ids []string) ([]models.BoardFieldValue, error) {
var internalBoardID int64 var internalBoardID int64
var err error var err error
var now int64 var now int64
var tx txExecutor
var owned bool
var i int
var id string
var result []models.BoardFieldValue
var execResult sql.Result
var n int64
now = time.Now().Unix() now = time.Now().Unix()
err = s.QueryRow(`SELECT id FROM boards WHERE public_id = ? AND delete_at = 0`, boardID).Scan(&internalBoardID) tx, owned, err = s.beginImmediateContext(ctx)
if err == sql.ErrNoRows {
return nil, ErrBoardNotFound
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = tx.QueryRow(`SELECT id FROM boards WHERE public_id = ? AND delete_at = 0`, boardID).Scan(&internalBoardID)
if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return nil, ErrBoardNotFound
}
if err != nil {
rollbackIfOwned(tx, owned)
return nil, err
}
for i, id := range ids { for i = 0; i < len(ids); i++ {
_, err = s.Exec(` id = ids[i]
execResult, err = tx.Exec(`
UPDATE board_field_values SET display_order = ?, updated_at = ? UPDATE board_field_values SET display_order = ?, updated_at = ?
WHERE public_id = ? AND board_id = ? AND field = ?`, WHERE public_id = ? AND board_id = ? AND field = ?`,
i, now, id, internalBoardID, field) i, now, id, internalBoardID, field)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return nil, err return nil, err
} }
n, err = execResult.RowsAffected()
if err != nil {
rollbackIfOwned(tx, owned)
return nil, err
}
if n == 0 {
rollbackIfOwned(tx, owned)
return nil, ErrFieldValueNotFound
}
} }
return s.ListBoardFieldValues(boardID, field) result, err = listBoardFieldValues(tx, boardID, field)
if err != nil {
rollbackIfOwned(tx, owned)
return nil, err
}
err = commitIfOwned(tx, owned)
if err != nil {
return nil, err
}
return result, nil
} }
func (s *Store) DeleteBoardFieldValue(boardID, valueID string) error { func (s *Store) DeleteBoardFieldValue(ctx context.Context, boardID, valueID string) error {
var err error var err error
var res sql.Result var res sql.Result
var n int64 var n int64
var value string var value string
var field string var field string
var count int
var tx txExecutor
var owned bool
err = s.QueryRow(` tx, owned, err = s.beginImmediateContext(ctx)
if err != nil {
return err
}
err = tx.QueryRow(`
SELECT fv.value, fv.field FROM board_field_values fv SELECT fv.value, fv.field FROM board_field_values fv
JOIN boards brd ON brd.id = fv.board_id JOIN boards brd ON brd.id = fv.board_id
WHERE fv.public_id = ? AND brd.public_id = ?`, valueID, boardID).Scan(&value, &field) WHERE fv.public_id = ? AND brd.public_id = ?`, valueID, boardID).Scan(&value, &field)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return ErrFieldValueNotFound return ErrFieldValueNotFound
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
var count int count, err = countBoardFieldValueRefs(tx, boardID, field, value)
count, err = s.CountBoardFieldValueRefs(boardID, field, value)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
if count > 0 { if count > 0 {
rollbackIfOwned(tx, owned)
return fmt.Errorf("%w: %d card(s)", ErrFieldValueInUse, count) return fmt.Errorf("%w: %d card(s)", ErrFieldValueInUse, count)
} }
res, err = s.Exec(` res, err = tx.Exec(`
DELETE FROM board_field_values DELETE FROM board_field_values
WHERE public_id = ? WHERE public_id = ?
AND board_id = (SELECT id FROM boards WHERE public_id = ? AND delete_at = 0)`, AND board_id = (SELECT id FROM boards WHERE public_id = ? AND delete_at = 0)`,
valueID, boardID) valueID, boardID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
n, err = res.RowsAffected() n, err = res.RowsAffected()
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
if n == 0 { if n == 0 {
rollbackIfOwned(tx, owned)
return ErrFieldValueNotFound return ErrFieldValueNotFound
} }
return nil return commitIfOwned(tx, owned)
} }
+28 -18
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "time" import "time"
@@ -39,7 +40,7 @@ func scanBoard(row interface{ Scan(...any) error }, b *models.Board) error {
) )
} }
func (s *Store) CreateBoard(board models.Board) (models.Board, error) { func (s *Store) CreateBoard(ctx context.Context, board models.Board) (models.Board, error) {
var id string var id string
var err error var err error
var nowUnix int64 var nowUnix int64
@@ -60,7 +61,7 @@ func (s *Store) CreateBoard(board models.Board) (models.Board, error) {
board.CardProperties = "[]" board.CardProperties = "[]"
} }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return board, err return board, err
} }
@@ -377,7 +378,7 @@ func (s *Store) insertBlockHistory(tx txExecutor, blockID int64, insertAt int64)
return err return err
} }
func (s *Store) CreateBlock(block models.Block) (models.Block, error) { func (s *Store) CreateBlock(ctx context.Context, block models.Block) (models.Block, error) {
var id string var id string
var err error var err error
var nowUnix int64 var nowUnix int64
@@ -401,7 +402,7 @@ func (s *Store) CreateBlock(block models.Block) (models.Block, error) {
block.Fields = "{}" block.Fields = "{}"
} }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return block, err return block, err
} }
@@ -512,7 +513,7 @@ func (s *Store) ListBlocksByType(boardID string, blockType string) ([]models.Blo
return blocks, rows.Err() return blocks, rows.Err()
} }
func (s *Store) UpdateBlock(block models.Block) (models.Block, error) { func (s *Store) UpdateBlock(ctx context.Context, block models.Block) (models.Block, error) {
var err error var err error
var nowUnix int64 var nowUnix int64
var tx txExecutor var tx txExecutor
@@ -525,7 +526,7 @@ func (s *Store) UpdateBlock(block models.Block) (models.Block, error) {
nowUnix = time.Now().UTC().Unix() nowUnix = time.Now().UTC().Unix()
block.UpdatedAt = nowUnix block.UpdatedAt = nowUnix
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return block, err return block, err
} }
@@ -591,7 +592,7 @@ func (s *Store) UpdateBlock(block models.Block) (models.Block, error) {
return s.GetBlock(block.BoardID, block.ID) return s.GetBlock(block.BoardID, block.ID)
} }
func (s *Store) PatchBlocks(boardID string, patches []models.BlockPatch, updatedBy string) error { func (s *Store) PatchBlocks(ctx context.Context, boardID string, patches []models.BlockPatch, updatedBy string) error {
var err error var err error
var nowUnix int64 var nowUnix int64
var tx txExecutor var tx txExecutor
@@ -608,7 +609,7 @@ func (s *Store) PatchBlocks(boardID string, patches []models.BlockPatch, updated
} }
nowUnix = time.Now().UTC().Unix() nowUnix = time.Now().UTC().Unix()
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -701,7 +702,7 @@ func (s *Store) PatchBlocks(boardID string, patches []models.BlockPatch, updated
return commitIfOwned(tx, owned) return commitIfOwned(tx, owned)
} }
func (s *Store) DeleteBlock(boardID string, id string, updatedBy string) error { func (s *Store) DeleteBlock(ctx context.Context, boardID string, id string, updatedBy string) error {
var err error var err error
var nowUnix int64 var nowUnix int64
var tx txExecutor var tx txExecutor
@@ -713,7 +714,7 @@ func (s *Store) DeleteBlock(boardID string, id string, updatedBy string) error {
var dID int64 var dID int64
nowUnix = time.Now().UTC().Unix() nowUnix = time.Now().UTC().Unix()
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -886,39 +887,48 @@ func (s *Store) ListBoardAssignableUsers(boardID string) ([]models.BoardAssignab
return users, rows.Err() return users, rows.Err()
} }
func (s *Store) UpsertBoardMember(member models.BoardMember) error { func (s *Store) UpsertBoardMember(ctx context.Context, member models.BoardMember) error {
var err error var err error
var nowUnix int64 var nowUnix int64
var boardInternalID int64 var boardInternalID int64
var userInternalID int64 var userInternalID int64
var row *sql.Row var tx txExecutor
var owned bool
nowUnix = time.Now().UTC().Unix() nowUnix = time.Now().UTC().Unix()
if member.CreatedAt == 0 { if member.CreatedAt == 0 {
member.CreatedAt = nowUnix member.CreatedAt = nowUnix
} }
row = s.QueryRow(`SELECT id FROM boards WHERE public_id = ? AND delete_at = 0`, member.BoardID) tx, owned, err = s.beginImmediateContext(ctx)
err = row.Scan(&boardInternalID) if err != nil { return err }
err = tx.QueryRow(`SELECT id FROM boards WHERE public_id = ? AND delete_at = 0`, member.BoardID).Scan(&boardInternalID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return ErrBoardNotFound return ErrBoardNotFound
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
row = s.QueryRow(`SELECT id FROM users WHERE public_id = ?`, member.UserID) err = tx.QueryRow(`SELECT id FROM users WHERE public_id = ?`, member.UserID).Scan(&userInternalID)
err = row.Scan(&userInternalID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
rollbackIfOwned(tx, owned)
return ErrUserNotFound return ErrUserNotFound
} }
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
_, err = s.Exec(` _, err = tx.Exec(`
INSERT INTO board_members (board_id, user_id, role, created_at) INSERT INTO board_members (board_id, user_id, role, created_at)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
ON CONFLICT(board_id, user_id) DO UPDATE SET role = excluded.role`, ON CONFLICT(board_id, user_id) DO UPDATE SET role = excluded.role`,
boardInternalID, userInternalID, member.Role, member.CreatedAt) boardInternalID, userInternalID, member.Role, member.CreatedAt)
return err if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func (s *Store) DeleteBoardMember(boardID string, userID string) error { func (s *Store) DeleteBoardMember(boardID string, userID string) error {
+35 -3
View File
@@ -196,6 +196,11 @@ func (s *Store) QueryRow(query string, args ...any) *sql.Row {
return s.execer().QueryRow(query, args...) return s.execer().QueryRow(query, args...)
} }
func normalizeStoreContext(ctx context.Context) context.Context {
if ctx == nil { return context.Background() }
return ctx
}
func (s *Store) BeginStore(ctx context.Context) (*Store, error) { func (s *Store) BeginStore(ctx context.Context) (*Store, error) {
var tx *sql.Tx var tx *sql.Tx
var err error var err error
@@ -203,6 +208,7 @@ func (s *Store) BeginStore(ctx context.Context) (*Store, error) {
if s == nil { return nil, fmt.Errorf("nil store") } if s == nil { return nil, fmt.Errorf("nil store") }
if s.tx != nil { return s, nil } // more than one BeginStore calls, return the existing tx if s.tx != nil { return s, nil } // more than one BeginStore calls, return the existing tx
ctx = normalizeStoreContext(ctx)
tx, err = s.DB.BeginTx(ctx, nil) tx, err = s.DB.BeginTx(ctx, nil)
if err != nil { return nil, err } if err != nil { return nil, err }
@@ -215,6 +221,7 @@ func (s *Store) BeginImmediateStore(ctx context.Context) (*Store, error) {
var tx *manualTx var tx *manualTx
var err error var err error
ctx = normalizeStoreContext(ctx)
if s.tx != nil { return s, nil } if s.tx != nil { return s, nil }
if !s.imm { return s.BeginStore(ctx) } if !s.imm { return s.BeginStore(ctx) }
@@ -244,22 +251,47 @@ func (s *Store) Rollback() error {
return s.tx.Rollback() return s.tx.Rollback()
} }
func (s *Store) begin() (txExecutor, bool, error) { //func (s *Store) begin() (txExecutor, bool, error) {
// return s.beginContext(context.Background())
//}
func (s *Store) beginContext(ctx context.Context) (txExecutor, bool, error) {
var tx *sql.Tx var tx *sql.Tx
var err error var err error
ctx = normalizeStoreContext(ctx)
if s == nil { return nil, false, fmt.Errorf("nil store") }
// return an existing transaction object that's already started by // return an existing transaction object that's already started by
// BeginStore() and BeginImmediateStore(). // BeginStore() and BeginImmediateStore().
// the second return value is false because the transaction is not started here. // the second return value is false because the transaction is not started here.
if s != nil && s.tx != nil { return s.tx, false, nil } if s.tx != nil { return s.tx, false, nil }
tx, err = s.DB.Begin() tx, err = s.DB.BeginTx(ctx, nil)
if err != nil { return nil, false, err } if err != nil { return nil, false, err }
// the second return value is true to indicate that the transaction has been started here // the second return value is true to indicate that the transaction has been started here
return tx, true, nil return tx, true, nil
} }
//func (s *Store) beginImmediate() (txExecutor, bool, error) {
// return s.beginImmediateContext(context.Background())
//}
func (s *Store) beginImmediateContext(ctx context.Context) (txExecutor, bool, error) {
var child *Store
var err error
ctx = normalizeStoreContext(ctx)
if s == nil { return nil, false, fmt.Errorf("nil store") }
if s.tx != nil { return s.tx, false, nil }
child, err = s.BeginImmediateStore(ctx)
if err != nil { return nil, false, err }
return child.tx, true, nil
}
func rollbackIfOwned(tx txExecutor, owned bool) { func rollbackIfOwned(tx txExecutor, owned bool) {
if tx != nil && owned { _ = tx.Rollback() } if tx != nil && owned { _ = tx.Rollback() }
} }
+55 -19
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "strings" import "strings"
@@ -87,26 +88,33 @@ func (s *Store) CreateUserGroup(item models.UserGroup) (models.UserGroup, error)
return item, nil return item, nil
} }
func (s *Store) UpdateUserGroup(item models.UserGroup) (models.UserGroup, error) { func (s *Store) UpdateUserGroup(ctx context.Context, item models.UserGroup) (models.UserGroup, error) {
var now int64 var now int64
var err error var err error
var mappingCount int var mappingCount int
var tx txExecutor
var owned bool
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.UpdatedAt = now item.UpdatedAt = now
item.Scope = NormalizeUserGroupScope(item.Scope) item.Scope = NormalizeUserGroupScope(item.Scope)
tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return item, err }
if item.Scope != UserGroupScopeExplicit { if item.Scope != UserGroupScopeExplicit {
err = s.QueryRow(`SELECT COUNT(*) err = tx.QueryRow(`SELECT COUNT(*)
FROM auth_provider_group_mappings m FROM auth_provider_group_mappings m
JOIN user_groups g ON g.id = m.group_id JOIN user_groups g ON g.id = m.group_id
WHERE g.public_id = ?`, strings.TrimSpace(item.ID)).Scan(&mappingCount) WHERE g.public_id = ?`, strings.TrimSpace(item.ID)).Scan(&mappingCount)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
if mappingCount > 0 { if mappingCount > 0 {
rollbackIfOwned(tx, owned)
return item, errors.New("group is used by auth provider group mappings") return item, errors.New("group is used by auth provider group mappings")
} }
} }
_, err = s.Exec(`UPDATE user_groups _, err = tx.Exec(`UPDATE user_groups
SET name = ?, description = ?, disabled = ?, totp_required = ?, scope = ?, updated_at = ? SET name = ?, description = ?, disabled = ?, totp_required = ?, scope = ?, updated_at = ?
WHERE public_id = ?`, WHERE public_id = ?`,
strings.TrimSpace(item.Name), strings.TrimSpace(item.Name),
@@ -118,22 +126,27 @@ func (s *Store) UpdateUserGroup(item models.UserGroup) (models.UserGroup, error)
strings.TrimSpace(item.ID), strings.TrimSpace(item.ID),
) )
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
item, err = s.GetUserGroup(item.ID) err = tx.QueryRow(`SELECT public_id, name, description, disabled, totp_required, scope, created_at, updated_at
FROM user_groups WHERE public_id = ?`, strings.TrimSpace(item.ID)).Scan(&item.ID, &item.Name, &item.Description, &item.Disabled, &item.TOTPRequired, &item.Scope, &item.CreatedAt, &item.UpdatedAt)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = commitIfOwned(tx, owned)
if err != nil { return item, err }
return item, nil return item, nil
} }
func (s *Store) DeleteUserGroup(groupID string) error { func (s *Store) DeleteUserGroup(ctx context.Context, groupID string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
var scope string var scope string
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return err } if err != nil { return err }
err = tx.QueryRow(`SELECT scope FROM user_groups WHERE public_id = ?`, strings.TrimSpace(groupID)).Scan(&scope) err = tx.QueryRow(`SELECT scope FROM user_groups WHERE public_id = ?`, strings.TrimSpace(groupID)).Scan(&scope)
@@ -214,44 +227,67 @@ func (s *Store) ListUserGroupMembers(groupID string) ([]models.UserGroupMember,
return items, nil return items, nil
} }
func (s *Store) AddUserGroupMember(groupID string, userID string) error { func (s *Store) AddUserGroupMember(ctx context.Context, groupID string, userID string) error {
var now int64 var now int64
var err error var err error
var group models.UserGroup var tx txExecutor
var owned bool
var scope string
group, err = s.GetUserGroup(groupID) tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return err } if err != nil { return err }
if NormalizeUserGroupScope(group.Scope) != UserGroupScopeExplicit { err = tx.QueryRow(`SELECT scope FROM user_groups WHERE public_id = ?`, strings.TrimSpace(groupID)).Scan(&scope)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
if NormalizeUserGroupScope(scope) != UserGroupScopeExplicit {
rollbackIfOwned(tx, owned)
return errors.New("virtual groups do not accept explicit members") return errors.New("virtual groups do not accept explicit members")
} }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
_, err = s.Exec(`INSERT OR IGNORE INTO user_group_members (group_id, user_id, created_at) _, err = tx.Exec(`INSERT OR IGNORE INTO user_group_members (group_id, user_id, created_at)
VALUES ((SELECT id FROM user_groups WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?)`, VALUES ((SELECT id FROM user_groups WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?)`,
strings.TrimSpace(groupID), strings.TrimSpace(userID), now) strings.TrimSpace(groupID), strings.TrimSpace(userID), now)
if err != nil {
return err rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func (s *Store) RemoveUserGroupMember(groupID string, userID string) error { func (s *Store) RemoveUserGroupMember(ctx context.Context, groupID string, userID string) error {
var err error var err error
var group models.UserGroup var tx txExecutor
var owned bool
var scope string
group, err = s.GetUserGroup(groupID) tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return err } if err != nil { return err }
if NormalizeUserGroupScope(group.Scope) != UserGroupScopeExplicit { err = tx.QueryRow(`SELECT scope FROM user_groups WHERE public_id = ?`, strings.TrimSpace(groupID)).Scan(&scope)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
if NormalizeUserGroupScope(scope) != UserGroupScopeExplicit {
rollbackIfOwned(tx, owned)
return errors.New("virtual groups do not have explicit members") return errors.New("virtual groups do not have explicit members")
} }
_, err = s.Exec(`DELETE FROM user_group_members _, err = tx.Exec(`DELETE FROM user_group_members
WHERE group_id = (SELECT id FROM user_groups WHERE public_id = ?) WHERE group_id = (SELECT id FROM user_groups WHERE public_id = ?)
AND user_id = (SELECT id FROM users WHERE public_id = ?)`, AND user_id = (SELECT id FROM users WHERE public_id = ?)`,
strings.TrimSpace(groupID), strings.TrimSpace(groupID),
strings.TrimSpace(userID), strings.TrimSpace(userID),
) )
return err if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func (s *Store) ListProjectGroupRoles(projectID string) ([]models.ProjectGroupRole, error) { func (s *Store) ListProjectGroupRoles(projectID string) ([]models.ProjectGroupRole, error) {
+5 -4
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "strings" import "strings"
@@ -312,7 +313,7 @@ func (s *Store) GetActivePKIClientProfileForUser(profileID string, userID string
return item, nil return item, nil
} }
func (s *Store) CreatePKIClientProfile(item models.PKIClientProfile) (models.PKIClientProfile, error) { func (s *Store) CreatePKIClientProfile(ctx context.Context, item models.PKIClientProfile) (models.PKIClientProfile, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -338,7 +339,7 @@ func (s *Store) CreatePKIClientProfile(item models.PKIClientProfile) (models.PKI
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.CreatedAt = now item.CreatedAt = now
item.UpdatedAt = now item.UpdatedAt = now
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return item, err return item, err
} }
@@ -412,7 +413,7 @@ func (s *Store) CreatePKIClientProfile(item models.PKIClientProfile) (models.PKI
return item, nil return item, nil
} }
func (s *Store) UpdatePKIClientProfile(item models.PKIClientProfile) (models.PKIClientProfile, error) { func (s *Store) UpdatePKIClientProfile(ctx context.Context, item models.PKIClientProfile) (models.PKIClientProfile, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -434,7 +435,7 @@ func (s *Store) UpdatePKIClientProfile(item models.PKIClientProfile) (models.PKI
} }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.UpdatedAt = now item.UpdatedAt = now
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return item, err return item, err
} }
+5 -4
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "strings" import "strings"
import "time" import "time"
@@ -127,7 +128,7 @@ func (s *Store) DeletePKICA(id string) error {
return err return err
} }
func (s *Store) DeletePKICASubtree(id string) error { func (s *Store) DeletePKICASubtree(ctx context.Context, id string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var rows *sql.Rows var rows *sql.Rows
@@ -143,7 +144,7 @@ func (s *Store) DeletePKICASubtree(id string) error {
var toDelete []string var toDelete []string
var contains bool var contains bool
parentByID = map[string]string{} parentByID = map[string]string{}
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -204,13 +205,13 @@ func (s *Store) DeletePKICASubtree(id string) error {
return nil return nil
} }
func (s *Store) NextPKICASerial(caID string) (int64, error) { func (s *Store) NextPKICASerial(ctx context.Context, caID string) (int64, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
var row *sql.Row var row *sql.Row
var serial int64 var serial int64
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return 0, err return 0, err
} }
+3 -2
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "time" import "time"
@@ -74,7 +75,7 @@ func (s *Store) SetPrincipalAPIKeyDisabled(principalID string, id string, disabl
return err return err
} }
func (s *Store) GetPrincipalByAPIKeyHash(tokenHash string) (models.ServicePrincipal, error) { func (s *Store) GetPrincipalByAPIKeyHash(ctx context.Context, tokenHash string) (models.ServicePrincipal, error) {
var principal models.ServicePrincipal var principal models.ServicePrincipal
var tx txExecutor var tx txExecutor
var owned bool var owned bool
@@ -85,7 +86,7 @@ func (s *Store) GetPrincipalByAPIKeyHash(tokenHash string) (models.ServicePrinci
var currentUnix int64 var currentUnix int64
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return principal, err } if err != nil { return principal, err }
now = time.Now().UTC() now = time.Now().UTC()
+3 -2
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "strings" import "strings"
import "time" import "time"
@@ -72,12 +73,12 @@ func (s *Store) UpdateServicePrincipal(item models.ServicePrincipal) error {
return err return err
} }
func (s *Store) DeleteServicePrincipal(id string) error { func (s *Store) DeleteServicePrincipal(ctx context.Context, id string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return err } if err != nil { return err }
_, err = tx.Exec(`DELETE FROM project_role_bindings WHERE subject_type = 'principal' AND subject_id = (SELECT id FROM service_principals WHERE public_id = ?)`, id) _, err = tx.Exec(`DELETE FROM project_role_bindings WHERE subject_type = 'principal' AND subject_id = (SELECT id FROM service_principals WHERE public_id = ?)`, id)
+11 -10
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "strings" import "strings"
import "time" import "time"
@@ -140,7 +141,7 @@ func (s *Store) TryStartRPMMirrorTask(repoID string, path string, now int64) (bo
return rows > 0, nil return rows > 0, nil
} }
func (s *Store) TryStartRPMMirrorRun(repoID string, path string, startedAt int64) (string, bool, error) { func (s *Store) TryStartRPMMirrorRun(ctx context.Context, repoID string, path string, startedAt int64) (string, bool, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var res sql.Result var res sql.Result
@@ -148,7 +149,7 @@ func (s *Store) TryStartRPMMirrorRun(repoID string, path string, startedAt int64
var runID string var runID string
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return "", false, err return "", false, err
} }
@@ -191,7 +192,7 @@ func (s *Store) UpdateRPMMirrorTaskProgress(repoID string, path string, step str
return err return err
} }
func (s *Store) FinishRPMMirrorTask(repoID string, path string, success bool, revision string, errMsg string) error { func (s *Store) FinishRPMMirrorTask(ctx context.Context, repoID string, path string, success bool, revision string, errMsg string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var now int64 var now int64
@@ -200,7 +201,7 @@ func (s *Store) FinishRPMMirrorTask(repoID string, path string, success bool, re
var interval int64 var interval int64
var row *sql.Row var row *sql.Row
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -236,7 +237,7 @@ func (s *Store) FinishRPMMirrorTask(repoID string, path string, success bool, re
return commitIfOwned(tx, owned) return commitIfOwned(tx, owned)
} }
func (s *Store) FinishRPMMirrorTaskRun(repoID string, path string, runID string, success bool, finishedAt int64, step string, total int64, done int64, failed int64, deleted int64, revision string, errMsg string) error { func (s *Store) FinishRPMMirrorTaskRun(ctx context.Context, repoID string, path string, runID string, success bool, finishedAt int64, step string, total int64, done int64, failed int64, deleted int64, revision string, errMsg string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var interval int64 var interval int64
@@ -245,7 +246,7 @@ func (s *Store) FinishRPMMirrorTaskRun(repoID string, path string, runID string,
var row *sql.Row var row *sql.Row
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -309,13 +310,13 @@ func (s *Store) SetRPMMirrorSyncEnabled(repoID string, path string, enabled bool
return err return err
} }
func (s *Store) ResetRunningRPMMirrorTasks() error { func (s *Store) ResetRunningRPMMirrorTasks(ctx context.Context) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var now int64 var now int64
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -540,7 +541,7 @@ func (s *Store) DeleteRPMRepoDirSubtree(repoID string, path string) error {
return err return err
} }
func (s *Store) MoveRPMRepoDir(repoID string, oldPath string, newPath string) error { func (s *Store) MoveRPMRepoDir(ctx context.Context, repoID string, oldPath string, newPath string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var now int64 var now int64
@@ -548,7 +549,7 @@ func (s *Store) MoveRPMRepoDir(repoID string, oldPath string, newPath string) er
var newPrefix string var newPrefix string
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return err } if err != nil { return err }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
+51 -24
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "encoding/json" import "encoding/json"
import "errors" import "errors"
@@ -268,33 +269,50 @@ func (s *Store) UpdateSSHServer(item models.SSHServer) (models.SSHServer, error)
return s.GetSSHServer(item.ID) return s.GetSSHServer(item.ID)
} }
func (s *Store) DeleteSSHServer(id string) error { func (s *Store) DeleteSSHServer(ctx context.Context, id string) error {
var err error var err error
var row *sql.Row var tx txExecutor
var owned bool
var count int64 var count int64
var trimmedID string var trimmedID string
trimmedID = strings.TrimSpace(id) trimmedID = strings.TrimSpace(id)
row = s.QueryRow(`SELECT COUNT(*) FROM ssh_access_profiles WHERE server_id = (SELECT id FROM ssh_servers WHERE public_id = ?)`, trimmedID) tx, owned, err = s.beginImmediateContext(ctx)
err = row.Scan(&count)
if err != nil { return err } if err != nil { return err }
err = tx.QueryRow(`SELECT COUNT(*) FROM ssh_access_profiles WHERE server_id = (SELECT id FROM ssh_servers WHERE public_id = ?)`, trimmedID).Scan(&count)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
if count > 0 { if count > 0 {
rollbackIfOwned(tx, owned)
return &SSHServerDeleteReferenceError{Kind: "SSH access profile", Count: count} return &SSHServerDeleteReferenceError{Kind: "SSH access profile", Count: count}
} }
row = s.QueryRow(`SELECT COUNT(*) FROM ssh_server_group_members WHERE server_id = (SELECT id FROM ssh_servers WHERE public_id = ?)`, trimmedID) err = tx.QueryRow(`SELECT COUNT(*) FROM ssh_server_group_members WHERE server_id = (SELECT id FROM ssh_servers WHERE public_id = ?)`, trimmedID).Scan(&count)
err = row.Scan(&count) if err != nil {
if err != nil { return err } rollbackIfOwned(tx, owned)
return err
}
if count > 0 { if count > 0 {
rollbackIfOwned(tx, owned)
return &SSHServerDeleteReferenceError{Kind: "SSH server group membership", Count: count} return &SSHServerDeleteReferenceError{Kind: "SSH server group membership", Count: count}
} }
row = s.QueryRow(`SELECT COUNT(*) FROM ssh_sessions WHERE server_id = (SELECT id FROM ssh_servers WHERE public_id = ?)`, trimmedID) err = tx.QueryRow(`SELECT COUNT(*) FROM ssh_sessions WHERE server_id = (SELECT id FROM ssh_servers WHERE public_id = ?)`, trimmedID).Scan(&count)
err = row.Scan(&count) if err != nil {
if err != nil { return err } rollbackIfOwned(tx, owned)
return err
}
if count > 0 { if count > 0 {
rollbackIfOwned(tx, owned)
return &SSHServerDeleteReferenceError{Kind: "SSH session history record", Count: count} return &SSHServerDeleteReferenceError{Kind: "SSH session history record", Count: count}
} }
_, err = s.Exec(`DELETE FROM ssh_servers WHERE public_id = ?`, trimmedID) _, err = tx.Exec(`DELETE FROM ssh_servers WHERE public_id = ?`, trimmedID)
return err if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func (s *Store) ListSSHAccessProfiles() ([]models.SSHAccessProfile, error) { func (s *Store) ListSSHAccessProfiles() ([]models.SSHAccessProfile, error) {
@@ -614,7 +632,7 @@ func (s *Store) GetSSHAccessProfile(id string) (models.SSHAccessProfile, error)
return item, nil return item, nil
} }
func (s *Store) CreateSSHAccessProfile(item models.SSHAccessProfile) (models.SSHAccessProfile, error) { func (s *Store) CreateSSHAccessProfile(ctx context.Context, item models.SSHAccessProfile) (models.SSHAccessProfile, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -653,7 +671,7 @@ func (s *Store) CreateSSHAccessProfile(item models.SSHAccessProfile) (models.SSH
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.CreatedAt = now item.CreatedAt = now
item.UpdatedAt = now item.UpdatedAt = now
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
item.SecretPayload = strings.TrimSpace(item.SecretPayload) item.SecretPayload = strings.TrimSpace(item.SecretPayload)
@@ -776,7 +794,7 @@ func (s *Store) CreateSSHAccessProfile(item models.SSHAccessProfile) (models.SSH
return item, nil return item, nil
} }
func (s *Store) UpdateSSHAccessProfile(item models.SSHAccessProfile) (models.SSHAccessProfile, error) { func (s *Store) UpdateSSHAccessProfile(ctx context.Context, item models.SSHAccessProfile) (models.SSHAccessProfile, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -809,7 +827,7 @@ func (s *Store) UpdateSSHAccessProfile(item models.SSHAccessProfile) (models.SSH
if err != nil { return item, err } if err != nil { return item, err }
item.UpdatedAt = time.Now().UTC().Unix() item.UpdatedAt = time.Now().UTC().Unix()
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
item.SecretPayload = strings.TrimSpace(item.SecretPayload) item.SecretPayload = strings.TrimSpace(item.SecretPayload)
@@ -910,7 +928,7 @@ func (s *Store) UpdateSSHAccessProfile(item models.SSHAccessProfile) (models.SSH
return item, nil return item, nil
} }
func (s *Store) DeleteSSHAccessProfile(id string) error { func (s *Store) DeleteSSHAccessProfile(ctx context.Context, id string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var row *sql.Row var row *sql.Row
@@ -918,7 +936,7 @@ func (s *Store) DeleteSSHAccessProfile(id string) error {
var credentialID sql.NullString var credentialID sql.NullString
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -1900,25 +1918,30 @@ func (s *Store) CreateSSHFileTransfer(item models.SSHFileTransfer) (models.SSHFi
return item, err return item, err
} }
func (s *Store) FinishSSHFileTransfer(id string, status string, paths []string, bytesTransferred int64, errText string) error { func (s *Store) FinishSSHFileTransfer(ctx context.Context, id string, status string, paths []string, bytesTransferred int64, errText string) error {
var row *sql.Row
var startedAt int64 var startedAt int64
var finishedAt int64 var finishedAt int64
var durationMS int64 var durationMS int64
var pathsJSON string var pathsJSON string
var err error var err error
var tx txExecutor
var owned bool
pathsJSON, err = encodeStringList(paths) pathsJSON, err = encodeStringList(paths)
if err != nil { return err } if err != nil { return err }
finishedAt = time.Now().UTC().Unix() finishedAt = time.Now().UTC().Unix()
row = s.QueryRow(`SELECT started_at FROM ssh_file_transfers WHERE public_id = ?`, strings.TrimSpace(id)) tx, owned, err = s.beginImmediateContext(ctx)
err = row.Scan(&startedAt)
if err != nil { return err } if err != nil { return err }
err = tx.QueryRow(`SELECT started_at FROM ssh_file_transfers WHERE public_id = ?`, strings.TrimSpace(id)).Scan(&startedAt)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
durationMS = 0 durationMS = 0
if startedAt > 0 && finishedAt >= startedAt { if startedAt > 0 && finishedAt >= startedAt {
durationMS = (finishedAt - startedAt) * 1000 durationMS = (finishedAt - startedAt) * 1000
} }
_, err = s.Exec(`UPDATE ssh_file_transfers _, err = tx.Exec(`UPDATE ssh_file_transfers
SET status = ?, paths_json = ?, bytes_transferred = ?, error = ?, finished_at = ?, duration_ms = ? SET status = ?, paths_json = ?, bytes_transferred = ?, error = ?, finished_at = ?, duration_ms = ?
WHERE public_id = ?`, WHERE public_id = ?`,
strings.TrimSpace(status), strings.TrimSpace(status),
@@ -1929,7 +1952,11 @@ func (s *Store) FinishSSHFileTransfer(id string, status string, paths []string,
durationMS, durationMS,
strings.TrimSpace(id), strings.TrimSpace(id),
) )
return err if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func scanSSHFileTransferRows(rows *sql.Rows, limit int) ([]models.SSHFileTransfer, bool, error) { func scanSSHFileTransferRows(rows *sql.Rows, limit int) ([]models.SSHFileTransfer, bool, error) {
+41 -16
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "strings" import "strings"
@@ -109,7 +110,7 @@ func (s *Store) GetSSHCredentialForUser(userID string, id string) (models.SSHCre
return item, err return item, err
} }
func (s *Store) CreateSSHCredential(item models.SSHCredential, secret models.SSHSecret) (models.SSHCredential, error) { func (s *Store) CreateSSHCredential(ctx context.Context, item models.SSHCredential, secret models.SSHSecret) (models.SSHCredential, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -124,7 +125,7 @@ func (s *Store) CreateSSHCredential(item models.SSHCredential, secret models.SSH
item.ID, err = util.NewID() item.ID, err = util.NewID()
if err != nil { return item, err } if err != nil { return item, err }
} }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
secret.Kind = "private_key" secret.Kind = "private_key"
secret.CreatedByKind = item.CreatedByKind secret.CreatedByKind = item.CreatedByKind
@@ -184,24 +185,48 @@ func (s *Store) UpdateSSHCredential(item models.SSHCredential) (models.SSHCreden
return s.GetSSHCredential(item.ID) return s.GetSSHCredential(item.ID)
} }
func (s *Store) DeleteSSHCredential(id string) error { func (s *Store) DeleteSSHCredential(ctx context.Context, id string) error {
var row *sql.Row
var count int var count int
var item models.SSHCredential var tx txExecutor
var owned bool
var secretID string
var err error var err error
id = strings.TrimSpace(id) id = strings.TrimSpace(id)
row = s.QueryRow(`SELECT COUNT(*) tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return err }
err = tx.QueryRow(`SELECT COUNT(*)
FROM ssh_access_profiles p FROM ssh_access_profiles p
JOIN ssh_credentials c ON c.id = p.ssh_credential_id JOIN ssh_credentials c ON c.id = p.ssh_credential_id
WHERE c.public_id = ?`, id) WHERE c.public_id = ?`, id).Scan(&count)
err = row.Scan(&count) if err != nil {
if err != nil { return err } rollbackIfOwned(tx, owned)
if count > 0 { return errors.New("ssh credential is used by access profiles") } return err
item, err = s.GetSSHCredential(id) }
if err != nil { return err } if count > 0 {
_, err = s.Exec(`DELETE FROM ssh_credentials WHERE public_id = ?`, id) rollbackIfOwned(tx, owned)
if err != nil { return err } return errors.New("ssh credential is used by access profiles")
_, err = s.Exec(`DELETE FROM ssh_secrets WHERE public_id = ?`, strings.TrimSpace(item.SecretID)) }
return err err = tx.QueryRow(`SELECT COALESCE(sec.public_id, '')
FROM ssh_credentials c
LEFT JOIN ssh_secrets sec ON sec.id = c.secret_id
WHERE c.public_id = ?`, id).Scan(&secretID)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
_, err = tx.Exec(`DELETE FROM ssh_credentials WHERE public_id = ?`, id)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
if strings.TrimSpace(secretID) != "" {
_, err = tx.Exec(`DELETE FROM ssh_secrets WHERE public_id = ?`, strings.TrimSpace(secretID))
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
}
return commitIfOwned(tx, owned)
} }
+5 -4
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "encoding/json" import "encoding/json"
import "errors" import "errors"
@@ -239,7 +240,7 @@ func (s *Store) GetSSHPrincipalGrant(id string) (models.SSHPrincipalGrant, error
return item, nil return item, nil
} }
func (s *Store) CreateSSHPrincipalGrant(item models.SSHPrincipalGrant) (models.SSHPrincipalGrant, error) { func (s *Store) CreateSSHPrincipalGrant(ctx context.Context, item models.SSHPrincipalGrant) (models.SSHPrincipalGrant, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -276,7 +277,7 @@ func (s *Store) CreateSSHPrincipalGrant(item models.SSHPrincipalGrant) (models.S
if err != nil { if err != nil {
return item, err return item, err
} }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return item, err return item, err
} }
@@ -335,7 +336,7 @@ func (s *Store) CreateSSHPrincipalGrant(item models.SSHPrincipalGrant) (models.S
return item, nil return item, nil
} }
func (s *Store) UpdateSSHPrincipalGrant(item models.SSHPrincipalGrant) (models.SSHPrincipalGrant, error) { func (s *Store) UpdateSSHPrincipalGrant(ctx context.Context, item models.SSHPrincipalGrant) (models.SSHPrincipalGrant, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -367,7 +368,7 @@ func (s *Store) UpdateSSHPrincipalGrant(item models.SSHPrincipalGrant) (models.S
} }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.UpdatedAt = now item.UpdatedAt = now
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return item, err return item, err
} }
+27 -13
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "strings" import "strings"
@@ -113,7 +114,7 @@ func (s *Store) ListSSHServersForGroup(groupID string) ([]models.SSHServer, erro
return items, nil return items, nil
} }
func (s *Store) CreateSSHServerGroup(item models.SSHServerGroup) (models.SSHServerGroup, error) { func (s *Store) CreateSSHServerGroup(ctx context.Context, item models.SSHServerGroup) (models.SSHServerGroup, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -131,7 +132,7 @@ func (s *Store) CreateSSHServerGroup(item models.SSHServerGroup) (models.SSHServ
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.CreatedAt = now item.CreatedAt = now
item.UpdatedAt = now item.UpdatedAt = now
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
_, err = tx.Exec(`INSERT INTO ssh_server_groups (public_id, name, description, enabled, tags_json, created_by_kind, created_by_user_id, created_by_principal_id, created_by_subject_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ? AND ? = 'user'), (SELECT id FROM service_principals WHERE public_id = ? AND ? = 'service_principal'), ?, ?, ?)`, item.ID, strings.TrimSpace(item.Name), strings.TrimSpace(item.Description), item.Enabled, tagsJSON, strings.TrimSpace(item.CreatedByKind), strings.TrimSpace(item.CreatedBySubjectID), strings.TrimSpace(item.CreatedByKind), strings.TrimSpace(item.CreatedBySubjectID), strings.TrimSpace(item.CreatedByKind), strings.TrimSpace(item.CreatedBySubjectName), item.CreatedAt, item.UpdatedAt) _, err = tx.Exec(`INSERT INTO ssh_server_groups (public_id, name, description, enabled, tags_json, created_by_kind, created_by_user_id, created_by_principal_id, created_by_subject_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ? AND ? = 'user'), (SELECT id FROM service_principals WHERE public_id = ? AND ? = 'service_principal'), ?, ?, ?)`, item.ID, strings.TrimSpace(item.Name), strings.TrimSpace(item.Description), item.Enabled, tagsJSON, strings.TrimSpace(item.CreatedByKind), strings.TrimSpace(item.CreatedBySubjectID), strings.TrimSpace(item.CreatedByKind), strings.TrimSpace(item.CreatedBySubjectID), strings.TrimSpace(item.CreatedByKind), strings.TrimSpace(item.CreatedBySubjectName), item.CreatedAt, item.UpdatedAt)
if err != nil { rollbackIfOwned(tx, owned); return item, err } if err != nil { rollbackIfOwned(tx, owned); return item, err }
@@ -140,7 +141,7 @@ func (s *Store) CreateSSHServerGroup(item models.SSHServerGroup) (models.SSHServ
return s.GetSSHServerGroup(item.ID) return s.GetSSHServerGroup(item.ID)
} }
func (s *Store) UpdateSSHServerGroup(item models.SSHServerGroup) (models.SSHServerGroup, error) { func (s *Store) UpdateSSHServerGroup(ctx context.Context, item models.SSHServerGroup) (models.SSHServerGroup, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
@@ -152,7 +153,7 @@ func (s *Store) UpdateSSHServerGroup(item models.SSHServerGroup) (models.SSHServ
tagsJSON, err = encodeStringList(item.Tags) tagsJSON, err = encodeStringList(item.Tags)
if err != nil { return item, err } if err != nil { return item, err }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return item, err } if err != nil { return item, err }
_, err = tx.Exec(`UPDATE ssh_server_groups SET name = ?, description = ?, enabled = ?, tags_json = ?, updated_at = ? WHERE public_id = ?`, strings.TrimSpace(item.Name), strings.TrimSpace(item.Description), item.Enabled, tagsJSON, now, strings.TrimSpace(item.ID)) _, err = tx.Exec(`UPDATE ssh_server_groups SET name = ?, description = ?, enabled = ?, tags_json = ?, updated_at = ? WHERE public_id = ?`, strings.TrimSpace(item.Name), strings.TrimSpace(item.Description), item.Enabled, tagsJSON, now, strings.TrimSpace(item.ID))
if err != nil { rollbackIfOwned(tx, owned); return item, err } if err != nil { rollbackIfOwned(tx, owned); return item, err }
@@ -161,21 +162,34 @@ func (s *Store) UpdateSSHServerGroup(item models.SSHServerGroup) (models.SSHServ
return s.GetSSHServerGroup(item.ID) return s.GetSSHServerGroup(item.ID)
} }
func (s *Store) DeleteSSHServerGroup(id string) error { func (s *Store) DeleteSSHServerGroup(ctx context.Context, id string) error {
var row *sql.Row var tx txExecutor
var owned bool
var count int var count int
var err error var err error
id = strings.TrimSpace(id) id = strings.TrimSpace(id)
row = s.QueryRow(`SELECT COUNT(*) tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return err }
err = tx.QueryRow(`SELECT COUNT(*)
FROM ssh_access_profiles p FROM ssh_access_profiles p
JOIN ssh_server_groups g ON g.id = p.server_group_id JOIN ssh_server_groups g ON g.id = p.server_group_id
WHERE g.public_id = ?`, id) WHERE g.public_id = ?`, id).Scan(&count)
err = row.Scan(&count) if err != nil {
if err != nil { return err } rollbackIfOwned(tx, owned)
if count > 0 { return errors.New("ssh server group is used by access profiles") } return err
_, err = s.Exec(`DELETE FROM ssh_server_groups WHERE public_id = ?`, id) }
return err if count > 0 {
rollbackIfOwned(tx, owned)
return errors.New("ssh server group is used by access profiles")
}
_, err = tx.Exec(`DELETE FROM ssh_server_groups WHERE public_id = ?`, id)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func (s *Store) AddSSHServerGroupMember(groupID string, serverID string) error { func (s *Store) AddSSHServerGroupMember(groupID string, serverID string) error {
+3 -2
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "encoding/json" import "encoding/json"
import "errors" import "errors"
@@ -145,13 +146,13 @@ func (s *Store) GetSSHUserCAForUser(id string) (models.SSHUserCA, error) {
return item, nil return item, nil
} }
func (s *Store) NextSSHUserCASerial(id string) (uint64, error) { func (s *Store) NextSSHUserCASerial(ctx context.Context, id string) (uint64, error) {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var row *sql.Row var row *sql.Row
var serial int64 var serial int64
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return 0, err return 0, err
} }
+5 -4
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "errors" import "errors"
import "strings" import "strings"
@@ -70,14 +71,14 @@ func (s *Store) GetTLSSettings() (models.TLSSettings, error) {
return settings, nil return settings, nil
} }
func (s *Store) SetTLSSettings(settings models.TLSSettings) error { func (s *Store) SetTLSSettings(ctx context.Context, settings models.TLSSettings) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
var now int64 var now int64
var endpointPoliciesJSON string var endpointPoliciesJSON string
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return err } if err != nil { return err }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
@@ -473,7 +474,7 @@ func (s *Store) GetSessionUser(token string) (models.User, time.Time, bool, erro
return user, time.Unix(expiresUnix, 0).UTC(), totpVerified, nil return user, time.Unix(expiresUnix, 0).UTC(), totpVerified, nil
} }
func (s *Store) CreateProject(project models.Project) (models.Project, error) { func (s *Store) CreateProject(ctx context.Context, project models.Project) (models.Project, error) {
var id string var id string
var err error var err error
var nowUnix int64 var nowUnix int64
@@ -490,7 +491,7 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
project.UpdatedAt = nowUnix project.UpdatedAt = nowUnix
if project.UpdatedBy == "" { project.UpdatedBy = project.CreatedBy } if project.UpdatedBy == "" { project.UpdatedBy = project.CreatedBy }
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return project, err } if err != nil { return project, err }
if project.HomePage == "" { project.HomePage = "settings" } if project.HomePage == "" { project.HomePage = "settings" }
+36 -17
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "encoding/json" import "encoding/json"
import "fmt" import "fmt"
@@ -213,7 +214,7 @@ func (s *Store) GetTLSAuthPolicy(id string) (models.TLSAuthPolicy, error) {
return item, nil return item, nil
} }
func (s *Store) insertTLSAuthPolicyAllowedPKICerts(policyID int64, certPublicIDs []string) error { func insertTLSAuthPolicyAllowedPKICerts(execer sqlExecutor, policyID int64, certPublicIDs []string) error {
var seen map[string]bool var seen map[string]bool
var i int var i int
var certPublicID string var certPublicID string
@@ -231,7 +232,7 @@ func (s *Store) insertTLSAuthPolicyAllowedPKICerts(policyID int64, certPublicIDs
continue continue
} }
seen[certPublicID] = true seen[certPublicID] = true
result, err = s.Exec(`INSERT INTO tls_auth_policy_allowed_pki_certs (policy_id, cert_id) SELECT ?, id FROM pki_certs WHERE public_id = ?`, policyID, certPublicID) result, err = execer.Exec(`INSERT INTO tls_auth_policy_allowed_pki_certs (policy_id, cert_id) SELECT ?, id FROM pki_certs WHERE public_id = ?`, policyID, certPublicID)
if err != nil { if err != nil {
return err return err
} }
@@ -246,12 +247,14 @@ func (s *Store) insertTLSAuthPolicyAllowedPKICerts(policyID int64, certPublicIDs
return nil return nil
} }
func (s *Store) CreateTLSAuthPolicy(item models.TLSAuthPolicy) (models.TLSAuthPolicy, error) { func (s *Store) CreateTLSAuthPolicy(ctx context.Context, item models.TLSAuthPolicy) (models.TLSAuthPolicy, error) {
var id string var id string
var now int64 var now int64
var err error var err error
var result sql.Result var result sql.Result
var internalID int64 var internalID int64
var tx txExecutor
var owned bool
if item.ID == "" { if item.ID == "" {
id, err = util.NewID() id, err = util.NewID()
@@ -263,45 +266,61 @@ func (s *Store) CreateTLSAuthPolicy(item models.TLSAuthPolicy) (models.TLSAuthPo
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.CreatedAt = now item.CreatedAt = now
item.UpdatedAt = now item.UpdatedAt = now
result, err = s.Exec(`INSERT INTO tls_auth_policies (public_id, name, description, read_mode, write_mode, require_principal_for_write, allowed_cert_fingerprints, required_permissions, permission_match, required_scope, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, tx, owned, err = s.beginImmediateContext(ctx)
if err != nil { return item, err }
result, err = tx.Exec(`INSERT INTO tls_auth_policies (public_id, name, description, read_mode, write_mode, require_principal_for_write, allowed_cert_fingerprints, required_permissions, permission_match, required_scope, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
item.ID, item.Name, item.Description, item.ReadMode, item.WriteMode, item.RequirePrincipalForWrite, strings.Join(item.AllowedCertFingerprints, ","), strings.Join(item.RequiredPermissions, ","), item.PermissionMatch, item.RequiredScope, item.CreatedAt, item.UpdatedAt) item.ID, item.Name, item.Description, item.ReadMode, item.WriteMode, item.RequirePrincipalForWrite, strings.Join(item.AllowedCertFingerprints, ","), strings.Join(item.RequiredPermissions, ","), item.PermissionMatch, item.RequiredScope, item.CreatedAt, item.UpdatedAt)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
internalID, err = result.LastInsertId() internalID, err = result.LastInsertId()
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = s.insertTLSAuthPolicyAllowedPKICerts(internalID, item.AllowedPKIClientCertIDs) err = insertTLSAuthPolicyAllowedPKICerts(tx, internalID, item.AllowedPKIClientCertIDs)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return item, err return item, err
} }
err = commitIfOwned(tx, owned)
if err != nil { return item, err }
return item, nil return item, nil
} }
func (s *Store) UpdateTLSAuthPolicy(item models.TLSAuthPolicy) error { func (s *Store) UpdateTLSAuthPolicy(ctx context.Context, item models.TLSAuthPolicy) error {
var now int64 var now int64
var err error var err error
var row *sql.Row
var internalID int64 var internalID int64
var tx txExecutor
var owned bool
row = s.QueryRow(`SELECT id FROM tls_auth_policies WHERE public_id = ?`, item.ID) tx, owned, err = s.beginImmediateContext(ctx)
err = row.Scan(&internalID) if err != nil { return err }
if err != nil {
return err err = tx.QueryRow(`SELECT id FROM tls_auth_policies WHERE public_id = ?`, item.ID).Scan(&internalID)
} if err != nil { rollbackIfOwned(tx, owned); return err }
now = time.Now().UTC().Unix() now = time.Now().UTC().Unix()
item.UpdatedAt = now item.UpdatedAt = now
_, err = s.Exec(`UPDATE tls_auth_policies SET name = ?, description = ?, read_mode = ?, write_mode = ?, require_principal_for_write = ?, allowed_cert_fingerprints = ?, required_permissions = ?, permission_match = ?, required_scope = ?, updated_at = ? WHERE public_id = ?`, _, err = tx.Exec(`UPDATE tls_auth_policies SET name = ?, description = ?, read_mode = ?, write_mode = ?, require_principal_for_write = ?, allowed_cert_fingerprints = ?, required_permissions = ?, permission_match = ?, required_scope = ?, updated_at = ? WHERE public_id = ?`,
item.Name, item.Description, item.ReadMode, item.WriteMode, item.RequirePrincipalForWrite, strings.Join(item.AllowedCertFingerprints, ","), strings.Join(item.RequiredPermissions, ","), item.PermissionMatch, item.RequiredScope, item.UpdatedAt, item.ID) item.Name, item.Description, item.ReadMode, item.WriteMode, item.RequirePrincipalForWrite, strings.Join(item.AllowedCertFingerprints, ","), strings.Join(item.RequiredPermissions, ","), item.PermissionMatch, item.RequiredScope, item.UpdatedAt, item.ID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
_, err = s.Exec(`DELETE FROM tls_auth_policy_allowed_pki_certs WHERE policy_id = ?`, internalID) _, err = tx.Exec(`DELETE FROM tls_auth_policy_allowed_pki_certs WHERE policy_id = ?`, internalID)
if err != nil { if err != nil {
rollbackIfOwned(tx, owned)
return err return err
} }
return s.insertTLSAuthPolicyAllowedPKICerts(internalID, item.AllowedPKIClientCertIDs) err = insertTLSAuthPolicyAllowedPKICerts(tx, internalID, item.AllowedPKIClientCertIDs)
if err != nil {
rollbackIfOwned(tx, owned)
return err
}
return commitIfOwned(tx, owned)
} }
func (s *Store) DeleteTLSAuthPolicy(id string) error { func (s *Store) DeleteTLSAuthPolicy(id string) error {
@@ -362,7 +381,7 @@ func (s *Store) EnsureDefaultTLSAuthPolicies() error {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {
return err return err
} }
_, err = s.CreateTLSAuthPolicy(item) _, err = s.CreateTLSAuthPolicy(context.Background(), item)
if err != nil { if err != nil {
return err return err
} }
@@ -382,7 +401,7 @@ func (s *Store) EnsureTLSAuthPolicyBindings() error {
} }
if len(settings.EndpointPolicies) == 0 { if len(settings.EndpointPolicies) == 0 {
settings.EndpointPolicies = DefaultTLSEndpointPolicies() settings.EndpointPolicies = DefaultTLSEndpointPolicies()
err = s.SetTLSSettings(settings) err = s.SetTLSSettings(context.Background(), settings)
if err != nil { if err != nil {
return err return err
} }
+7 -6
View File
@@ -1,5 +1,6 @@
package db package db
import "context"
import "database/sql" import "database/sql"
import "strings" import "strings"
import "time" import "time"
@@ -38,7 +39,7 @@ func (s *Store) UpdateUser(user models.User) error {
return err return err
} }
func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) error { func (s *Store) UpdateUserWithPassword(ctx context.Context, user models.User, passwordHash string) error {
var err error var err error
var nowUnix int64 var nowUnix int64
var tx txExecutor var tx txExecutor
@@ -46,7 +47,7 @@ func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) er
nowUnix = time.Now().UTC().Unix() nowUnix = time.Now().UTC().Unix()
user.UpdatedAt = nowUnix user.UpdatedAt = nowUnix
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@@ -143,12 +144,12 @@ func (s *Store) ClearUserAvatar(id string) error {
return err return err
} }
func (s *Store) DeleteUser(id string) error { func (s *Store) DeleteUser(ctx context.Context, id string) error {
var tx txExecutor var tx txExecutor
var owned bool var owned bool
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return err } if err != nil { return err }
_, err = tx.Exec(`DELETE FROM project_role_bindings WHERE subject_type = 'user' AND subject_id = (SELECT id FROM users WHERE public_id = ?)`, id) _, err = tx.Exec(`DELETE FROM project_role_bindings WHERE subject_type = 'user' AND subject_id = (SELECT id FROM users WHERE public_id = ?)`, id)
@@ -202,7 +203,7 @@ func (s *Store) SetUserDisabled(id string, disabled bool) error {
return err return err
} }
func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) { func (s *Store) GetUserByAPIKeyHash(ctx context.Context, tokenHash string) (models.User, error) {
var user models.User var user models.User
var tx txExecutor var tx txExecutor
var owned bool var owned bool
@@ -211,7 +212,7 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
var nowUnix int64 var nowUnix int64
var err error var err error
tx, owned, err = s.begin() tx, owned, err = s.beginContext(ctx)
if err != nil { return user, err } if err != nil { return user, err }
nowUnix = time.Now().UTC().Unix() nowUnix = time.Now().UTC().Unix()
+14 -14
View File
@@ -524,7 +524,7 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ map[string]strin
if err == nil { if err == nil {
user = created user = created
if p.DefaultUserGroupID != "" { if p.DefaultUserGroupID != "" {
_ = api.store(r).AddUserGroupMember(p.DefaultUserGroupID, user.ID) _ = api.store(r).AddUserGroupMember(r.Context(), p.DefaultUserGroupID, user.ID)
} }
} else { } else {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
@@ -748,7 +748,7 @@ func (api *API) UpdateMe(w http.ResponseWriter, r *http.Request, _ map[string]st
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, "failed to hash password") WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, "failed to hash password")
return return
} }
err = api.store(r).UpdateUserWithPassword(user, hash) err = api.store(r).UpdateUserWithPassword(r.Context(), user, hash)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1044,7 +1044,7 @@ func (api *API) UpdateUser(w http.ResponseWriter, r *http.Request, params map[st
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, "failed to hash password") WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, "failed to hash password")
return return
} }
err = api.store(r).UpdateUserWithPassword(user, hash) err = api.store(r).UpdateUserWithPassword(r.Context(), user, hash)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1064,7 +1064,7 @@ func (api *API) DeleteUser(w http.ResponseWriter, r *http.Request, params map[st
if !api.requireAdmin(w, r) { if !api.requireAdmin(w, r) {
return return
} }
err = api.store(r).DeleteUser(params["id"]) err = api.store(r).DeleteUser(r.Context(), params["id"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1171,7 +1171,7 @@ func (api *API) UpdateUserGroup(w http.ResponseWriter, r *http.Request, params m
group.Disabled = req.Disabled group.Disabled = req.Disabled
group.TOTPRequired = req.TOTPRequired group.TOTPRequired = req.TOTPRequired
group.Scope = db.NormalizeUserGroupScope(req.Scope) group.Scope = db.NormalizeUserGroupScope(req.Scope)
group, err = api.store(r).UpdateUserGroup(group) group, err = api.store(r).UpdateUserGroup(r.Context(), group)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -1184,7 +1184,7 @@ func (api *API) DeleteUserGroup(w http.ResponseWriter, r *http.Request, params m
if !api.requireAdmin(w, r) { if !api.requireAdmin(w, r) {
return return
} }
err = api.store(r).DeleteUserGroup(params["id"]) err = api.store(r).DeleteUserGroup(r.Context(), params["id"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1222,7 +1222,7 @@ func (api *API) AddUserGroupMember(w http.ResponseWriter, r *http.Request, param
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "user_id required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "user_id required")
return return
} }
err = api.store(r).AddUserGroupMember(params["id"], req.UserID) err = api.store(r).AddUserGroupMember(r.Context(), params["id"], req.UserID)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -1235,7 +1235,7 @@ func (api *API) RemoveUserGroupMember(w http.ResponseWriter, r *http.Request, pa
if !api.requireAdmin(w, r) { if !api.requireAdmin(w, r) {
return return
} }
err = api.store(r).RemoveUserGroupMember(params["id"], params["userId"]) err = api.store(r).RemoveUserGroupMember(r.Context(), params["id"], params["userId"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1354,7 +1354,7 @@ func (api *API) UpdateTLSSettings(w http.ResponseWriter, r *http.Request, _ map[
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
err = api.store(r).SetTLSSettings(settings) err = api.store(r).SetTLSSettings(r.Context(), settings)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1396,7 +1396,7 @@ func (api *API) CreateTLSAuthPolicy(w http.ResponseWriter, r *http.Request, _ ma
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
created, err = api.store(r).CreateTLSAuthPolicy(item) created, err = api.store(r).CreateTLSAuthPolicy(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -1427,7 +1427,7 @@ func (api *API) UpdateTLSAuthPolicy(w http.ResponseWriter, r *http.Request, para
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
err = api.store(r).UpdateTLSAuthPolicy(item) err = api.store(r).UpdateTLSAuthPolicy(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -1700,7 +1700,7 @@ func (api *API) DeleteServicePrincipal(w http.ResponseWriter, r *http.Request, p
if !api.requireAdmin(w, r) { if !api.requireAdmin(w, r) {
return return
} }
err = api.store(r).DeleteServicePrincipal(params["id"]) err = api.store(r).DeleteServicePrincipal(r.Context(), params["id"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -2076,7 +2076,7 @@ func (api *API) CreateProject(w http.ResponseWriter, r *http.Request, _ map[stri
CreatedBy: user.ID, CreatedBy: user.ID,
UpdatedBy: user.ID, UpdatedBy: user.ID,
} }
created, err = api.store(r).CreateProject(project) created, err = api.store(r).CreateProject(r.Context(), project)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -4461,7 +4461,7 @@ func (api *API) RepoRPMRenameSubdir(w http.ResponseWriter, r *http.Request, para
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
} }
err = api.store(r).MoveRPMRepoDir(repo.ID, relPathClean, newRelPath) err = api.store(r).MoveRPMRepoDir(r.Context(), repo.ID, relPathClean, newRelPath)
if err != nil { if err != nil {
_ = os.Rename(newPath, fullPath) _ = os.Rename(newPath, fullPath)
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
+4 -4
View File
@@ -63,7 +63,7 @@ func (api *API) CreateAuthProvider(w http.ResponseWriter, r *http.Request, _ map
return return
} }
} }
created, err = api.store(r).CreateAuthProvider(req) created, err = api.store(r).CreateAuthProvider(r.Context(), req)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -103,13 +103,13 @@ func (api *API) UpdateAuthProvider(w http.ResponseWriter, r *http.Request, param
if strings.TrimSpace(req.Name) != "" { if strings.TrimSpace(req.Name) != "" {
existing.Name = strings.TrimSpace(req.Name) existing.Name = strings.TrimSpace(req.Name)
} }
updated, err = api.store(r).UpdateAuthProvider(existing) updated, err = api.store(r).UpdateAuthProvider(r.Context(), existing)
} else { } else {
if strings.TrimSpace(req.Name) == "" { if strings.TrimSpace(req.Name) == "" {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "name is required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "name is required")
return return
} }
updated, err = api.store(r).UpdateAuthProvider(req) updated, err = api.store(r).UpdateAuthProvider(r.Context(), req)
} }
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -144,7 +144,7 @@ func (api *API) DeleteAuthProvider(w http.ResponseWriter, r *http.Request, param
return return
} }
} }
err = api.store(r).DeleteAuthProvider(params["id"], force) err = api.store(r).DeleteAuthProvider(r.Context(), params["id"], force)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
+6 -6
View File
@@ -72,7 +72,7 @@ func (api *API) CreateBlockComment(w http.ResponseWriter, r *http.Request, param
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "content is required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "content is required")
return return
} }
comment, err = api.store(r).CreateBlockComment(params["boardId"], params["blockId"], req.Content, user.ID) comment, err = api.store(r).CreateBlockComment(r.Context(), params["boardId"], params["blockId"], req.Content, user.ID)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found")
@@ -184,7 +184,7 @@ func (api *API) CreateBlockChecklistItem(w http.ResponseWriter, r *http.Request,
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "title is required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "title is required")
return return
} }
item, err = api.store(r).CreateBlockChecklistItem(params["boardId"], params["blockId"], req.Title, user.ID) item, err = api.store(r).CreateBlockChecklistItem(r.Context(), params["boardId"], params["blockId"], req.Title, user.ID)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found")
@@ -266,7 +266,7 @@ func (api *API) ReorderBlockChecklistItems(w http.ResponseWriter, r *http.Reques
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "ids are required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "ids are required")
return return
} }
items, err = api.store(r).ReorderBlockChecklistItems(params["boardId"], params["blockId"], req.IDs) items, err = api.store(r).ReorderBlockChecklistItems(r.Context(), params["boardId"], params["blockId"], req.IDs)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found")
@@ -368,7 +368,7 @@ func (api *API) CreateBlockAttachment(w http.ResponseWriter, r *http.Request, pa
StoragePath: finalPath, StoragePath: finalPath,
CreatedBy: user.ID, CreatedBy: user.ID,
} }
created, err = api.store(r).CreateBlockAttachment(params["boardId"], params["blockId"], attachment) created, err = api.store(r).CreateBlockAttachment(r.Context(), params["boardId"], params["blockId"], attachment)
if err != nil { if err != nil {
_ = os.Remove(finalPath) _ = os.Remove(finalPath)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
@@ -423,7 +423,7 @@ func (api *API) DeleteBlockAttachment(w http.ResponseWriter, r *http.Request, pa
if !api.requireBoardRole(w, r, params["boardId"], "editor") { if !api.requireBoardRole(w, r, params["boardId"], "editor") {
return return
} }
item, err = api.store(r).DeleteBlockAttachment(params["boardId"], params["blockId"], params["attachmentId"]) item, err = api.store(r).DeleteBlockAttachment(r.Context(), params["boardId"], params["blockId"], params["attachmentId"])
if err != nil { if err != nil {
if errors.Is(err, db.ErrBlockAttachmentNotFound) { if errors.Is(err, db.ErrBlockAttachmentNotFound) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "attachment not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "attachment not found")
@@ -507,7 +507,7 @@ func (api *API) UpsertBlockProperties(w http.ResponseWriter, r *http.Request, pa
Sprint: req.Sprint, Sprint: req.Sprint,
Description: req.Description, Description: req.Description,
} }
bp, err = api.store(r).UpsertBlockProperties(params["boardId"], params["blockId"], bp) bp, err = api.store(r).UpsertBlockProperties(r.Context(), params["boardId"], params["blockId"], bp)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found")
@@ -55,7 +55,7 @@ func (api *API) CreateBoardFieldValue(w http.ResponseWriter, r *http.Request, pa
StartDate: req.StartDate, StartDate: req.StartDate,
EndDate: req.EndDate, EndDate: req.EndDate,
} }
created, err = api.store(r).CreateBoardFieldValue(params["boardId"], fv) created, err = api.store(r).CreateBoardFieldValue(r.Context(), params["boardId"], fv)
if err != nil { if err != nil {
if errors.Is(err, db.ErrBoardNotFound) { if errors.Is(err, db.ErrBoardNotFound) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "board not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "board not found")
@@ -114,7 +114,7 @@ func (api *API) ReorderBoardFieldValues(w http.ResponseWriter, r *http.Request,
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "ids are required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "ids are required")
return return
} }
values, err = api.store(r).ReorderBoardFieldValues(params["boardId"], params["field"], req.IDs) values, err = api.store(r).ReorderBoardFieldValues(r.Context(), params["boardId"], params["field"], req.IDs)
if err != nil { if err != nil {
if errors.Is(err, db.ErrBoardNotFound) { if errors.Is(err, db.ErrBoardNotFound) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "board not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "board not found")
@@ -135,7 +135,7 @@ func (api *API) DeleteBoardFieldValue(w http.ResponseWriter, r *http.Request, pa
if !api.requireBoardRole(w, r, params["boardId"], "admin") { if !api.requireBoardRole(w, r, params["boardId"], "admin") {
return return
} }
err = api.store(r).DeleteBoardFieldValue(params["boardId"], params["valueId"]) err = api.store(r).DeleteBoardFieldValue(r.Context(), params["boardId"], params["valueId"])
if err != nil { if err != nil {
if errors.Is(err, db.ErrFieldValueNotFound) { if errors.Is(err, db.ErrFieldValueNotFound) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "field value not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "field value not found")
+7 -7
View File
@@ -262,7 +262,7 @@ func (api *API) CreateBoard(w http.ResponseWriter, r *http.Request, params map[s
IsTemplate: req.IsTemplate, IsTemplate: req.IsTemplate,
CreatedBy: user.ID, CreatedBy: user.ID,
} }
created, err = api.store(r).CreateBoard(board) created, err = api.store(r).CreateBoard(r.Context(), board)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -443,7 +443,7 @@ func (api *API) CreateBlock(w http.ResponseWriter, r *http.Request, params map[s
CreatedBy: user.ID, CreatedBy: user.ID,
UpdatedBy: user.ID, UpdatedBy: user.ID,
} }
created, err = api.store(r).CreateBlock(block) created, err = api.store(r).CreateBlock(r.Context(), block)
if err != nil { if err != nil {
if errors.Is(err, db.ErrParentNotInBoard) { if errors.Is(err, db.ErrParentNotInBoard) {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -515,7 +515,7 @@ func (api *API) UpdateBlock(w http.ResponseWriter, r *http.Request, params map[s
} }
} }
block.UpdatedBy = user.ID block.UpdatedBy = user.ID
updated, err = api.store(r).UpdateBlock(block) updated, err = api.store(r).UpdateBlock(r.Context(), block)
if err != nil { if err != nil {
if errors.Is(err, db.ErrParentNotInBoard) || errors.Is(err, db.ErrParentCycle) { if errors.Is(err, db.ErrParentNotInBoard) || errors.Is(err, db.ErrParentCycle) {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -546,7 +546,7 @@ func (api *API) PatchBlocks(w http.ResponseWriter, r *http.Request, params map[s
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "invalid json") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "invalid json")
return return
} }
err = api.store(r).PatchBlocks(params["boardId"], patches, user.ID) err = api.store(r).PatchBlocks(r.Context(), params["boardId"], patches, user.ID)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found")
@@ -575,7 +575,7 @@ func (api *API) DeleteBlock(w http.ResponseWriter, r *http.Request, params map[s
if !api.requireBoardRole(w, r, params["boardId"], "editor") { if !api.requireBoardRole(w, r, params["boardId"], "editor") {
return return
} }
err = api.store(r).DeleteBlock(params["boardId"], params["blockId"], user.ID) err = api.store(r).DeleteBlock(r.Context(), params["boardId"], params["blockId"], user.ID)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "block not found")
@@ -661,7 +661,7 @@ func (api *API) AddBoardMember(w http.ResponseWriter, r *http.Request, params ma
UserID: req.UserID, UserID: req.UserID,
Role: role, Role: role,
} }
err = api.store(r).UpsertBoardMember(member) err = api.store(r).UpsertBoardMember(r.Context(), member)
if err != nil { if err != nil {
if errors.Is(err, db.ErrBoardNotFound) || errors.Is(err, db.ErrUserNotFound) { if errors.Is(err, db.ErrBoardNotFound) || errors.Is(err, db.ErrUserNotFound) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusNotFound, err.Error())
@@ -697,7 +697,7 @@ func (api *API) UpdateBoardMember(w http.ResponseWriter, r *http.Request, params
UserID: params["userId"], UserID: params["userId"],
Role: role, Role: role,
} }
err = api.store(r).UpsertBoardMember(member) err = api.store(r).UpsertBoardMember(r.Context(), member)
if err != nil { if err != nil {
if errors.Is(err, db.ErrBoardNotFound) || errors.Is(err, db.ErrUserNotFound) { if errors.Is(err, db.ErrBoardNotFound) || errors.Is(err, db.ErrUserNotFound) {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusNotFound, err.Error())
+4 -4
View File
@@ -435,7 +435,7 @@ func (api *API) oidcSyncUserGroups(ctx context.Context, provider models.AuthProv
mode = strings.TrimSpace(provider.GroupSyncMode) mode = strings.TrimSpace(provider.GroupSyncMode)
if mode == db.GroupSyncModeOff || mode == "" { if mode == db.GroupSyncModeOff || mode == "" {
if isNew && strings.TrimSpace(provider.DefaultUserGroupID) != "" { if isNew && strings.TrimSpace(provider.DefaultUserGroupID) != "" {
err = api.storeContext(ctx).AddUserGroupMember(provider.DefaultUserGroupID, user.ID) err = api.storeContext(ctx).AddUserGroupMember(ctx, provider.DefaultUserGroupID, user.ID)
if err != nil { return fmt.Errorf("oidc default user group assignment failed: %w", err) } if err != nil { return fmt.Errorf("oidc default user group assignment failed: %w", err) }
} }
return nil return nil
@@ -466,17 +466,17 @@ func (api *API) oidcSyncUserGroups(ctx context.Context, provider models.AuthProv
assignedAny = false assignedAny = false
for groupID, matched = range groupMatched { for groupID, matched = range groupMatched {
if matched { if matched {
err = api.storeContext(ctx).AddUserGroupMember(groupID, user.ID) err = api.storeContext(ctx).AddUserGroupMember(ctx, groupID, user.ID)
if err != nil { return fmt.Errorf("oidc sso group assignment failed: %w", err) } if err != nil { return fmt.Errorf("oidc sso group assignment failed: %w", err) }
assignedAny = true assignedAny = true
} else if mode == db.GroupSyncModeSync { } else if mode == db.GroupSyncModeSync {
err = api.storeContext(ctx).RemoveUserGroupMember(groupID, user.ID) err = api.storeContext(ctx).RemoveUserGroupMember(ctx, groupID, user.ID)
if err != nil { return fmt.Errorf("oidc sso group removal failed: %w", err) } if err != nil { return fmt.Errorf("oidc sso group removal failed: %w", err) }
} }
} }
if isNew && !assignedAny && strings.TrimSpace(provider.DefaultUserGroupID) != "" { if isNew && !assignedAny && strings.TrimSpace(provider.DefaultUserGroupID) != "" {
err = api.storeContext(ctx).AddUserGroupMember(provider.DefaultUserGroupID, user.ID) err = api.storeContext(ctx).AddUserGroupMember(ctx, provider.DefaultUserGroupID, user.ID)
if err != nil { return fmt.Errorf("oidc default user group assignment failed: %w", err) } if err != nil { return fmt.Errorf("oidc default user group assignment failed: %w", err) }
} }
@@ -213,7 +213,7 @@ func (api *API) CreatePKIClientProfile(w http.ResponseWriter, r *http.Request, _
if hasCurrentUser { if hasCurrentUser {
item.CreatedByUserID = currentUser.ID item.CreatedByUserID = currentUser.ID
} }
item, err = api.store(r).CreatePKIClientProfile(item) item, err = api.store(r).CreatePKIClientProfile(r.Context(), item)
if err != nil { if err != nil {
api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile create failed name=%s err=%v", item.Name, err) api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile create failed name=%s err=%v", item.Name, err)
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -296,7 +296,7 @@ func (api *API) UpdatePKIClientProfile(w http.ResponseWriter, r *http.Request, p
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "name is required") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "name is required")
return return
} }
existing, err = api.store(r).UpdatePKIClientProfile(existing) existing, err = api.store(r).UpdatePKIClientProfile(r.Context(), existing)
if err != nil { if err != nil {
api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile update failed id=%s err=%v", params["id"], err) api.Logger.Write(logIDPKI, codit_logger.LOG_WARN, "client profile update failed id=%s err=%v", params["id"], err)
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -448,7 +448,7 @@ func (api *API) IssuePKIClientCertForSelf(w http.ResponseWriter, r *http.Request
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "generated SAN URI is invalid") WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "generated SAN URI is invalid")
return return
} }
serial, err = api.store(r).NextPKICASerial(ca.ID) serial, err = api.store(r).NextPKICASerial(r.Context(), ca.ID)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
+2 -2
View File
@@ -531,7 +531,7 @@ func (api *API) IssuePKICert(w http.ResponseWriter, r *http.Request, _ map[strin
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "CA not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "CA not found")
return return
} }
serial, err = api.store(r).NextPKICASerial(ca.ID) serial, err = api.store(r).NextPKICASerial(r.Context(), ca.ID)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -884,7 +884,7 @@ func (api *API) DeletePKICA(w http.ResponseWriter, r *http.Request, params map[s
return return
} }
if force { if force {
err = api.store(r).DeletePKICASubtree(ca.ID) err = api.store(r).DeletePKICASubtree(r.Context(), ca.ID)
} else { } else {
err = api.store(r).DeletePKICA(ca.ID) err = api.store(r).DeletePKICA(ca.ID)
} }
@@ -165,7 +165,7 @@ func (api *API) finishSSHFileTransferAudit(audit *sshFileTransferAudit, status s
return return
} }
audit.Finished = true audit.Finished = true
err = audit.Store.FinishSSHFileTransfer(audit.Item.ID, status, audit.Paths, audit.Bytes, audit.ErrorText) err = audit.Store.FinishSSHFileTransfer(context.Background(), audit.Item.ID, status, audit.Paths, audit.Bytes, audit.ErrorText)
if err != nil { if err != nil {
api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN, "ssh file transfer audit finish failed id=%s op=%s err=%s", audit.Item.ID, audit.Item.Operation, err.Error()) api.Logger.Write(logIDSSHBroker, codit_logger.LOG_WARN, "ssh file transfer audit finish failed id=%s op=%s err=%s", audit.Item.ID, audit.Item.Operation, err.Error())
return return
@@ -308,7 +308,7 @@ func (api *API) UploadSSHSessionFilesForSelf(w http.ResponseWriter, r *http.Requ
if audit != nil { if audit != nil {
audit.Paths = append(audit.Paths, remotePath) audit.Paths = append(audit.Paths, remotePath)
} }
sshClient, err = api.openSSHSessionFileTransferClient(store, user, sessionItem, password, otpCode) sshClient, err = api.openSSHSessionFileTransferClient(r.Context(), store, user, sessionItem, password, otpCode)
if err != nil { if err != nil {
if audit != nil { if audit != nil {
audit.ErrorText = err.Error() audit.ErrorText = err.Error()
@@ -428,7 +428,7 @@ func (api *API) DownloadSSHSessionFilesForSelf(w http.ResponseWriter, r *http.Re
api.writeSSHSessionFileTransferError(w, r, err) api.writeSSHSessionFileTransferError(w, r, err)
return return
} }
sshClient, err = api.openSSHSessionFileTransferClient(store, user, sessionItem, req.Password, req.OTPCode) sshClient, err = api.openSSHSessionFileTransferClient(r.Context(), store, user, sessionItem, req.Password, req.OTPCode)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -601,7 +601,7 @@ func (api *API) CopySSHSessionFilesForSelf(w http.ResponseWriter, r *http.Reques
api.writeSSHSessionFileTransferError(w, r, err) api.writeSSHSessionFileTransferError(w, r, err)
return return
} }
sourceSSHClient, err = api.openSSHSessionFileTransferClient(store, user, sourceSession, req.SourcePassword, req.SourceOTPCode) sourceSSHClient, err = api.openSSHSessionFileTransferClient(r.Context(), store, user, sourceSession, req.SourcePassword, req.SourceOTPCode)
if err != nil { if err != nil {
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "source session: " + err.Error()}) WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "source session: " + err.Error()})
return return
@@ -609,7 +609,7 @@ func (api *API) CopySSHSessionFilesForSelf(w http.ResponseWriter, r *http.Reques
stopSourceClose = closeSSHClientOnContext(r.Context(), sourceSSHClient) stopSourceClose = closeSSHClientOnContext(r.Context(), sourceSSHClient)
defer stopSourceClose() defer stopSourceClose()
defer sourceSSHClient.Close() defer sourceSSHClient.Close()
targetSSHClient, err = api.openSSHSessionFileTransferClient(store, user, targetSession, req.TargetPassword, req.TargetOTPCode) targetSSHClient, err = api.openSSHSessionFileTransferClient(r.Context(), store, user, targetSession, req.TargetPassword, req.TargetOTPCode)
if err != nil { if err != nil {
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "target session: " + err.Error()}) WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "target session: " + err.Error()})
return return
@@ -775,7 +775,7 @@ func (api *API) writeSSHSessionFileTransferError(w http.ResponseWriter, r *http.
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
} }
func (api *API) openSSHSessionFileTransferClient(store *db.Store, user models.User, sessionItem models.SSHSession, promptedPassword string, otpCode string) (*ssh.Client, error) { func (api *API) openSSHSessionFileTransferClient(ctx context.Context, store *db.Store, user models.User, sessionItem models.SSHSession, promptedPassword string, otpCode string) (*ssh.Client, error) {
var prepared sshSessionPrepared var prepared sshSessionPrepared
var prepareStage string var prepareStage string
var sshConfig *ssh.ClientConfig var sshConfig *ssh.ClientConfig
@@ -784,7 +784,7 @@ func (api *API) openSSHSessionFileTransferClient(store *db.Store, user models.Us
var connectedHostKey ssh.PublicKey var connectedHostKey ssh.PublicKey
var err error var err error
prepared, prepareStage, err = api.prepareSSHSession(store, &user, &sessionItem, promptedPassword, otpCode) prepared, prepareStage, err = api.prepareSSHSession(ctx, store, &user, &sessionItem, promptedPassword, otpCode)
if err != nil { if err != nil {
if prepareStage == sshPrepareStageLoadProfile { if prepareStage == sshPrepareStageLoadProfile {
return nil, errors.New("ssh access profile not found") return nil, errors.New("ssh access profile not found")
+21 -21
View File
@@ -442,7 +442,7 @@ func (api *API) DeleteSSHServerAdmin(w http.ResponseWriter, r *http.Request, par
if !api.requireAdmin(w, r) { if !api.requireAdmin(w, r) {
return return
} }
err = api.store(r).DeleteSSHServer(params["id"]) err = api.store(r).DeleteSSHServer(r.Context(), params["id"])
if err != nil { if err != nil {
if errors.As(err, &referenceErr) { if errors.As(err, &referenceErr) {
WriteJSON(w, http.StatusConflict, map[string]string{"error": err.Error() + "; remove the references first or disable the server instead"}) WriteJSON(w, http.StatusConflict, map[string]string{"error": err.Error() + "; remove the references first or disable the server instead"})
@@ -491,7 +491,7 @@ func (api *API) CreateSSHServerGroupAdmin(w http.ResponseWriter, r *http.Request
} }
item = models.SSHServerGroup{Name: strings.TrimSpace(req.Name), Description: strings.TrimSpace(req.Description), Enabled: req.Enabled, Tags: req.Tags, CreatedByKind: "user", CreatedBySubjectID: user.ID, CreatedBySubjectName: user.Username} item = models.SSHServerGroup{Name: strings.TrimSpace(req.Name), Description: strings.TrimSpace(req.Description), Enabled: req.Enabled, Tags: req.Tags, CreatedByKind: "user", CreatedBySubjectID: user.ID, CreatedBySubjectName: user.Username}
item, err = api.store(r).CreateSSHServerGroup(item) item, err = api.store(r).CreateSSHServerGroup(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -518,7 +518,7 @@ func (api *API) UpdateSSHServerGroupAdmin(w http.ResponseWriter, r *http.Request
item.Description = strings.TrimSpace(req.Description) item.Description = strings.TrimSpace(req.Description)
item.Enabled = req.Enabled item.Enabled = req.Enabled
item.Tags = req.Tags item.Tags = req.Tags
item, err = api.store(r).UpdateSSHServerGroup(item) item, err = api.store(r).UpdateSSHServerGroup(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -529,7 +529,7 @@ func (api *API) UpdateSSHServerGroupAdmin(w http.ResponseWriter, r *http.Request
func (api *API) DeleteSSHServerGroupAdmin(w http.ResponseWriter, r *http.Request, params map[string]string) { func (api *API) DeleteSSHServerGroupAdmin(w http.ResponseWriter, r *http.Request, params map[string]string) {
var err error var err error
if !api.requireAdmin(w, r) { return } if !api.requireAdmin(w, r) { return }
err = api.store(r).DeleteSSHServerGroup(params["id"]) err = api.store(r).DeleteSSHServerGroup(r.Context(), params["id"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -658,7 +658,7 @@ func (api *API) CreateSSHCredentialAdmin(w http.ResponseWriter, r *http.Request,
CreatedBySubjectName: user.Username, CreatedBySubjectName: user.Username,
} }
secret = models.SSHSecret{Payload: encrypted} secret = models.SSHSecret{Payload: encrypted}
item, err = api.store(r).CreateSSHCredential(item, secret) item, err = api.store(r).CreateSSHCredential(r.Context(), item, secret)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -695,7 +695,7 @@ func (api *API) UpdateSSHCredentialAdmin(w http.ResponseWriter, r *http.Request,
func (api *API) DeleteSSHCredentialAdmin(w http.ResponseWriter, r *http.Request, params map[string]string) { func (api *API) DeleteSSHCredentialAdmin(w http.ResponseWriter, r *http.Request, params map[string]string) {
var err error var err error
if !api.requireAdmin(w, r) { return } if !api.requireAdmin(w, r) { return }
err = api.store(r).DeleteSSHCredential(params["id"]) err = api.store(r).DeleteSSHCredential(r.Context(), params["id"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -772,7 +772,7 @@ func (api *API) CreateSSHCredentialForSelf(w http.ResponseWriter, r *http.Reques
CreatedBySubjectName: user.Username, CreatedBySubjectName: user.Username,
} }
secret = models.SSHSecret{Payload: encrypted} secret = models.SSHSecret{Payload: encrypted}
item, err = api.store(r).CreateSSHCredential(item, secret) item, err = api.store(r).CreateSSHCredential(r.Context(), item, secret)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -828,7 +828,7 @@ func (api *API) DeleteSSHCredentialForSelf(w http.ResponseWriter, r *http.Reques
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "ssh credential not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "ssh credential not found")
return return
} }
err = api.store(r).DeleteSSHCredential(params["id"]) err = api.store(r).DeleteSSHCredential(r.Context(), params["id"])
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -900,7 +900,7 @@ func (api *API) CreateSSHAccessProfileAdmin(w http.ResponseWriter, r *http.Reque
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
item, err = api.store(r).CreateSSHAccessProfile(item) item, err = api.store(r).CreateSSHAccessProfile(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -948,7 +948,7 @@ func (api *API) UpdateSSHAccessProfileAdmin(w http.ResponseWriter, r *http.Reque
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
item, err = api.store(r).UpdateSSHAccessProfile(item) item, err = api.store(r).UpdateSSHAccessProfile(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -962,7 +962,7 @@ func (api *API) DeleteSSHAccessProfileAdmin(w http.ResponseWriter, r *http.Reque
if !api.requireAdmin(w, r) { if !api.requireAdmin(w, r) {
return return
} }
err = api.store(r).DeleteSSHAccessProfile(params["id"]) err = api.store(r).DeleteSSHAccessProfile(r.Context(), params["id"])
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
WriteJSONWithErrorReason(w, r, http.StatusNotFound, "ssh access profile not found") WriteJSONWithErrorReason(w, r, http.StatusNotFound, "ssh access profile not found")
@@ -1304,7 +1304,7 @@ func (api *API) DeleteSSHServerForSelf(w http.ResponseWriter, r *http.Request, p
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
} }
err = api.store(r).DeleteSSHServer(params["id"]) err = api.store(r).DeleteSSHServer(r.Context(), params["id"])
if err != nil { if err != nil {
if errors.As(err, &referenceErr) { if errors.As(err, &referenceErr) {
WriteJSON(w, http.StatusConflict, map[string]string{"error": err.Error() + "; remove the references first or disable the server instead"}) WriteJSON(w, http.StatusConflict, map[string]string{"error": err.Error() + "; remove the references first or disable the server instead"})
@@ -1478,7 +1478,7 @@ func (api *API) CreateSSHAccessProfileForSelf(w http.ResponseWriter, r *http.Req
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
item, err = api.store(r).CreateSSHAccessProfile(item) item, err = api.store(r).CreateSSHAccessProfile(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -1530,7 +1530,7 @@ func (api *API) UpdateSSHAccessProfileForSelf(w http.ResponseWriter, r *http.Req
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
} }
item, err = api.store(r).UpdateSSHAccessProfile(item) item, err = api.store(r).UpdateSSHAccessProfile(r.Context(), item)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -1562,7 +1562,7 @@ func (api *API) DeleteSSHAccessProfileForSelf(w http.ResponseWriter, r *http.Req
w.WriteHeader(http.StatusForbidden) w.WriteHeader(http.StatusForbidden)
return return
} }
err = api.store(r).DeleteSSHAccessProfile(item.ID) err = api.store(r).DeleteSSHAccessProfile(r.Context(), item.ID)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusInternalServerError, err.Error())
return return
@@ -1789,7 +1789,7 @@ func (api *API) CreateSSHSessionForSelf(w http.ResponseWriter, r *http.Request,
return return
} }
prepared, prepareStage, err = api.prepareSSHSession(api.store(r), &user, &item, req.Password, req.OTPCode) prepared, prepareStage, err = api.prepareSSHSession(r.Context(), api.store(r), &user, &item, req.Password, req.OTPCode)
if err != nil { if err != nil {
if prepareStage == sshPrepareStageHostKeyMissing || prepareStage == sshPrepareStageBuildAuth { if prepareStage == sshPrepareStageHostKeyMissing || prepareStage == sshPrepareStageBuildAuth {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -2564,7 +2564,7 @@ func discoverSSHServerHostKey(host string, port int, defaultUser string) (models
return item, nil return item, nil
} }
func (api *API) prepareSSHSession(store *db.Store, user *models.User, sessionItem *models.SSHSession, promptedPassword string, otpCode string) (sshSessionPrepared, string, error) { func (api *API) prepareSSHSession(ctx context.Context, store *db.Store, user *models.User, sessionItem *models.SSHSession, promptedPassword string, otpCode string) (sshSessionPrepared, string, error) {
var prepared sshSessionPrepared var prepared sshSessionPrepared
var err error var err error
@@ -2593,7 +2593,7 @@ func (api *API) prepareSSHSession(store *db.Store, user *models.User, sessionIte
prepared.PinHostKeyOnFirstUse = true prepared.PinHostKeyOnFirstUse = true
} }
prepared.AuthMethods, err = api.buildSSHSessionAuth(store, prepared.Profile, promptedPassword, otpCode) prepared.AuthMethods, err = api.buildSSHSessionAuth(ctx, store, prepared.Profile, promptedPassword, otpCode)
if err != nil { if err != nil {
return prepared, sshPrepareStageBuildAuth, err return prepared, sshPrepareStageBuildAuth, err
} }
@@ -3013,7 +3013,7 @@ func (api *API) runSSHSessionStream(store *db.Store, user *models.User, sessionI
api.logSSHSessionPreparedUse(sessionItem, user, &profile) api.logSSHSessionPreparedUse(sessionItem, user, &profile)
} else { } else {
prepared = &sshSessionPrepared{} prepared = &sshSessionPrepared{}
*prepared, prepareStage, err = api.prepareSSHSession(store, user, sessionItem, promptedPassword, promptedOTPCode) *prepared, prepareStage, err = api.prepareSSHSession(context.Background(), store, user, sessionItem, promptedPassword, promptedOTPCode)
if err != nil { if err != nil {
if prepareStage == sshPrepareStageLoadProfile { if prepareStage == sshPrepareStageLoadProfile {
api.logSSHSessionPrepareFailure(sessionItem, user, prepareStage, err) api.logSSHSessionPrepareFailure(sessionItem, user, prepareStage, err)
@@ -3622,7 +3622,7 @@ func appendSSHSecondFactorAuthMethods(methods []ssh.AuthMethod, profile models.S
return methods, nil return methods, nil
} }
func (api *API) buildSSHSessionAuth(store *db.Store, profile models.SSHAccessProfile, promptedPassword string, otpCode string) ([]ssh.AuthMethod, error) { func (api *API) buildSSHSessionAuth(ctx context.Context, store *db.Store, profile models.SSHAccessProfile, promptedPassword string, otpCode string) ([]ssh.AuthMethod, error) {
var methods []ssh.AuthMethod var methods []ssh.AuthMethod
var secret models.SSHSecret var secret models.SSHSecret
var credential models.SSHCredential var credential models.SSHCredential
@@ -3682,7 +3682,7 @@ func (api *API) buildSSHSessionAuth(store *db.Store, profile models.SSHAccessPro
principals, err = api.resolveSSHAccessProfilePrincipals(store, profile) principals, err = api.resolveSSHAccessProfilePrincipals(store, profile)
if err != nil { return nil, err } if err != nil { return nil, err }
signed, err = api.signSSHUserKeyWithCA(store, ca, profile.AuthPublicKey, "", principals, profile.DefaultCertValidSeconds, profile.MaxCertValidSeconds) signed, err = api.signSSHUserKeyWithCA(ctx, store, ca, profile.AuthPublicKey, "", principals, profile.DefaultCertValidSeconds, profile.MaxCertValidSeconds)
if err != nil { return nil, err } if err != nil { return nil, err }
certKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(strings.TrimSpace(signed.Certificate))) certKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(strings.TrimSpace(signed.Certificate)))
@@ -182,7 +182,7 @@ func (api *API) CreateSSHPrincipalGrant(w http.ResponseWriter, r *http.Request,
if hasCurrentUser { if hasCurrentUser {
item.CreatedByUserID = currentUser.ID item.CreatedByUserID = currentUser.ID
} }
item, err = api.store(r).CreateSSHPrincipalGrant(item) item, err = api.store(r).CreateSSHPrincipalGrant(r.Context(), item)
if err != nil { if err != nil {
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant create failed name=%s err=%v", name, err) api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant create failed name=%s err=%v", name, err)
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -254,7 +254,7 @@ func (api *API) UpdateSSHPrincipalGrant(w http.ResponseWriter, r *http.Request,
item.Disabled = req.Disabled item.Disabled = req.Disabled
item.Reason = strings.TrimSpace(req.Reason) item.Reason = strings.TrimSpace(req.Reason)
item.Targets = targets item.Targets = targets
item, err = api.store(r).UpdateSSHPrincipalGrant(item) item, err = api.store(r).UpdateSSHPrincipalGrant(r.Context(), item)
if err != nil { if err != nil {
api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant update failed id=%s err=%v", params["id"], err) api.Logger.Write(logIDSSHCA, codit_logger.LOG_WARN, "grant update failed id=%s err=%v", params["id"], err)
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
+6 -5
View File
@@ -1,5 +1,6 @@
package handlers package handlers
import "context"
import codit_logger "codit/logger" import codit_logger "codit/logger"
import "crypto/ed25519" import "crypto/ed25519"
import "crypto/ecdsa" import "crypto/ecdsa"
@@ -378,7 +379,7 @@ func (api *API) SignSSHUserKey(w http.ResponseWriter, r *http.Request, params ma
return return
} }
validSeconds = req.ValidSeconds validSeconds = req.ValidSeconds
response, err = api.signSSHUserKeyWithCA(api.store(r), item, sourcePublicKey, strings.TrimSpace(req.KeyID), principals, validSeconds, 604800) response, err = api.signSSHUserKeyWithCA(r.Context(), api.store(r), item, sourcePublicKey, strings.TrimSpace(req.KeyID), principals, validSeconds, 604800)
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
return return
@@ -708,9 +709,9 @@ func (api *API) SignSSHUserKeyForSelf(w http.ResponseWriter, r *http.Request, pa
} }
validSeconds = req.ValidSeconds validSeconds = req.ValidSeconds
if maxGrantValidSeconds > 0 && maxGrantValidSeconds < item.MaxUserValidSeconds { if maxGrantValidSeconds > 0 && maxGrantValidSeconds < item.MaxUserValidSeconds {
response, err = api.signSSHUserKeyWithCA(api.store(r), item, sourcePublicKey, strings.TrimSpace(req.KeyID), principals, validSeconds, maxGrantValidSeconds) response, err = api.signSSHUserKeyWithCA(r.Context(), api.store(r), item, sourcePublicKey, strings.TrimSpace(req.KeyID), principals, validSeconds, maxGrantValidSeconds)
} else { } else {
response, err = api.signSSHUserKeyWithCA(api.store(r), item, sourcePublicKey, strings.TrimSpace(req.KeyID), principals, validSeconds, item.MaxUserValidSeconds) response, err = api.signSSHUserKeyWithCA(r.Context(), api.store(r), item, sourcePublicKey, strings.TrimSpace(req.KeyID), principals, validSeconds, item.MaxUserValidSeconds)
} }
if err != nil { if err != nil {
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error()) WriteJSONWithErrorReason(w, r, http.StatusBadRequest, err.Error())
@@ -734,7 +735,7 @@ func (api *API) SignSSHUserKeyForSelf(w http.ResponseWriter, r *http.Request, pa
WriteJSON(w, http.StatusOK, response) WriteJSON(w, http.StatusOK, response)
} }
func (api *API) signSSHUserKeyWithCA(store *db.Store, item models.SSHUserCA, publicKey string, keyID string, principals []string, validSeconds int64, maxValidSeconds int64) (sshSignUserKeyResponse, error) { func (api *API) signSSHUserKeyWithCA(ctx context.Context, store *db.Store, item models.SSHUserCA, publicKey string, keyID string, principals []string, validSeconds int64, maxValidSeconds int64) (sshSignUserKeyResponse, error) {
var response sshSignUserKeyResponse var response sshSignUserKeyResponse
var signer ssh.Signer var signer ssh.Signer
var key ssh.PublicKey var key ssh.PublicKey
@@ -765,7 +766,7 @@ func (api *API) signSSHUserKeyWithCA(store *db.Store, item models.SSHUserCA, pub
if validSeconds < 60 || validSeconds > maxValidSeconds { if validSeconds < 60 || validSeconds > maxValidSeconds {
return response, fmt.Errorf("valid_seconds must be between 60 and %d", maxValidSeconds) return response, fmt.Errorf("valid_seconds must be between 60 and %d", maxValidSeconds)
} }
serial, err = store.NextSSHUserCASerial(item.ID) serial, err = store.NextSSHUserCASerial(ctx, item.ID)
if err != nil { if err != nil {
return response, err return response, err
} }
+4 -4
View File
@@ -57,14 +57,14 @@ func WithUserCookie(store *db.Store, sessionCookieName string, next http.Handler
return return
} }
hash = util.HashToken(token) hash = util.HashToken(token)
user, err = activeStore.GetUserByAPIKeyHash(hash) user, err = activeStore.GetUserByAPIKeyHash(r.Context(), hash)
if err == nil { if err == nil {
rememberUser(r.Context(), user) rememberUser(r.Context(), user)
ctx = context.WithValue(r.Context(), userKey, user) ctx = context.WithValue(r.Context(), userKey, user)
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
return return
} }
principal, err = activeStore.GetPrincipalByAPIKeyHash(hash) principal, err = activeStore.GetPrincipalByAPIKeyHash(r.Context(), hash)
if err != nil { if err != nil {
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
return return
@@ -82,14 +82,14 @@ func WithUserCookie(store *db.Store, sessionCookieName string, next http.Handler
return return
} }
hash = util.HashToken(token) hash = util.HashToken(token)
user, err = activeStore.GetUserByAPIKeyHash(hash) user, err = activeStore.GetUserByAPIKeyHash(r.Context(), hash)
if err == nil { if err == nil {
rememberUser(r.Context(), user) rememberUser(r.Context(), user)
ctx = context.WithValue(r.Context(), userKey, user) ctx = context.WithValue(r.Context(), userKey, user)
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
return return
} }
principal, err = activeStore.GetPrincipalByAPIKeyHash(hash) principal, err = activeStore.GetPrincipalByAPIKeyHash(r.Context(), hash)
if err != nil { if err != nil {
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
return return
+3 -3
View File
@@ -131,7 +131,7 @@ func (m *MirrorManager) Start() {
if m == nil { if m == nil {
return return
} }
err = m.store.ResetRunningRPMMirrorTasks() err = m.store.ResetRunningRPMMirrorTasks(context.Background())
if err != nil && m.logger != nil { if err != nil && m.logger != nil {
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "reset running tasks failed err=%v", err) m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "reset running tasks failed err=%v", err)
} }
@@ -199,7 +199,7 @@ func (m *MirrorManager) runDue() {
return return
} }
for i = 0; i < len(tasks); i++ { for i = 0; i < len(tasks); i++ {
runID, started, err = m.store.TryStartRPMMirrorRun(tasks[i].RepoID, tasks[i].MirrorPath, now) runID, started, err = m.store.TryStartRPMMirrorRun(context.Background(), tasks[i].RepoID, tasks[i].MirrorPath, now)
if err != nil { if err != nil {
if m.logger != nil { if m.logger != nil {
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "try start failed repo=%s path=%s err=%v", tasks[i].RepoID, tasks[i].MirrorPath, err) m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "try start failed repo=%s path=%s err=%v", tasks[i].RepoID, tasks[i].MirrorPath, err)
@@ -353,7 +353,7 @@ func (m *MirrorManager) finishTaskRun(task models.RPMMirrorTask, runID string, s
var err error var err error
finishedAt = time.Now().UTC().Unix() finishedAt = time.Now().UTC().Unix()
err = m.store.FinishRPMMirrorTaskRun(task.RepoID, task.MirrorPath, runID, success, finishedAt, step, total, done, failed, deleted, revision, errMsg) err = m.store.FinishRPMMirrorTaskRun(context.Background(), task.RepoID, task.MirrorPath, runID, success, finishedAt, step, total, done, failed, deleted, revision, errMsg)
if err != nil && m.logger != nil { if err != nil && m.logger != nil {
m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "finish sync state failed repo=%s path=%s run=%s err=%v", task.RepoID, task.MirrorPath, runID, err) m.logger.Write(logIDRPMMirror, codit_logger.LOG_ERROR, "finish sync state failed repo=%s path=%s run=%s err=%v", task.RepoID, task.MirrorPath, runID, err)
} }
+6 -6
View File
@@ -362,22 +362,22 @@ func auth_user(store *db.Store, username string, password string) (bool, error)
if err != nil || hash == "" { if err != nil || hash == "" {
if password != "" { if password != "" {
key = password key = password
user, err = store.GetUserByAPIKeyHash(util.HashToken(key)) user, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(key))
if err == nil { if err == nil {
return true, nil return true, nil
} }
principal, err = store.GetPrincipalByAPIKeyHash(util.HashToken(key)) principal, err = store.GetPrincipalByAPIKeyHash(context.Background(), util.HashToken(key))
if err == nil { if err == nil {
return !principal.Disabled, nil return !principal.Disabled, nil
} }
} }
if password == "" && username != "" { if password == "" && username != "" {
key = username key = username
user, err = store.GetUserByAPIKeyHash(util.HashToken(key)) user, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(key))
if err == nil { if err == nil {
return true, nil return true, nil
} }
principal, err = store.GetPrincipalByAPIKeyHash(util.HashToken(key)) principal, err = store.GetPrincipalByAPIKeyHash(context.Background(), util.HashToken(key))
if err == nil { if err == nil {
return !principal.Disabled, nil return !principal.Disabled, nil
} }
@@ -388,11 +388,11 @@ func auth_user(store *db.Store, username string, password string) (bool, error)
if err != nil { if err != nil {
if password != "" { if password != "" {
key = password key = password
user, err = store.GetUserByAPIKeyHash(util.HashToken(key)) user, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(key))
if err == nil { if err == nil {
return true, nil return true, nil
} }
principal, err = store.GetPrincipalByAPIKeyHash(util.HashToken(key)) principal, err = store.GetPrincipalByAPIKeyHash(context.Background(), util.HashToken(key))
if err == nil { if err == nil {
return !principal.Disabled, nil return !principal.Disabled, nil
} }
+8 -7
View File
@@ -1,5 +1,6 @@
package tests package tests
import "context"
import "database/sql" import "database/sql"
import "path/filepath" import "path/filepath"
import "testing" import "testing"
@@ -127,7 +128,7 @@ func TestAPIKeyAuthSuccess(t *testing.T) {
defer store.Close() defer store.Close()
user = createTestUser(t, store, "alice") user = createTestUser(t, store, "alice")
token = createAPIKey(t, store, user.ID, "default", 0) token = createAPIKey(t, store, user.ID, "default", 0)
got, err = store.GetUserByAPIKeyHash(util.HashToken(token)) got, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(token))
if err != nil { if err != nil {
t.Fatalf("lookup by api key: %v", err) t.Fatalf("lookup by api key: %v", err)
} }
@@ -145,7 +146,7 @@ func TestAPIKeyAuthExpiredKeyFails(t *testing.T) {
defer store.Close() defer store.Close()
user = createTestUser(t, store, "bob") user = createTestUser(t, store, "bob")
token = createAPIKey(t, store, user.ID, "expired", time.Now().UTC().Unix()-60) token = createAPIKey(t, store, user.ID, "expired", time.Now().UTC().Unix()-60)
_, err = store.GetUserByAPIKeyHash(util.HashToken(token)) _, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(token))
if err == nil { if err == nil {
t.Fatalf("expected error for expired key") t.Fatalf("expected error for expired key")
} }
@@ -177,7 +178,7 @@ func TestAPIKeyAuthDisabledKeyFails(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("disable key: %v", err) t.Fatalf("disable key: %v", err)
} }
_, err = store.GetUserByAPIKeyHash(util.HashToken(token)) _, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(token))
if err == nil { if err == nil {
t.Fatalf("expected error for disabled key") t.Fatalf("expected error for disabled key")
} }
@@ -199,7 +200,7 @@ func TestAPIKeyAuthDisabledUserFails(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("disable user: %v", err) t.Fatalf("disable user: %v", err)
} }
_, err = store.GetUserByAPIKeyHash(util.HashToken(token)) _, err = store.GetUserByAPIKeyHash(context.Background(), util.HashToken(token))
if err == nil { if err == nil {
t.Fatalf("expected error for disabled user") t.Fatalf("expected error for disabled user")
} }
@@ -225,7 +226,7 @@ func TestDeleteUserCascadesAPIKeys(t *testing.T) {
if len(keys) != 2 { if len(keys) != 2 {
t.Fatalf("expected two keys before delete, got %d", len(keys)) t.Fatalf("expected two keys before delete, got %d", len(keys))
} }
err = store.DeleteUser(user.ID) err = store.DeleteUser(context.Background(), user.ID)
if err != nil { if err != nil {
t.Fatalf("delete user: %v", err) t.Fatalf("delete user: %v", err)
} }
@@ -249,7 +250,7 @@ func TestPrincipalAPIKeyAuthSuccess(t *testing.T) {
defer store.Close() defer store.Close()
principal = createTestServicePrincipal(t, store, "robot") principal = createTestServicePrincipal(t, store, "robot")
token = createPrincipalAPIKey(t, store, principal.ID, "default", 0) token = createPrincipalAPIKey(t, store, principal.ID, "default", 0)
got, err = store.GetPrincipalByAPIKeyHash(util.HashToken(token)) got, err = store.GetPrincipalByAPIKeyHash(context.Background(), util.HashToken(token))
if err != nil { if err != nil {
t.Fatalf("lookup principal by api key: %v", err) t.Fatalf("lookup principal by api key: %v", err)
} }
@@ -273,7 +274,7 @@ func TestPrincipalAPIKeyAuthDisabledPrincipalFails(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("disable principal: %v", err) t.Fatalf("disable principal: %v", err)
} }
_, err = store.GetPrincipalByAPIKeyHash(util.HashToken(token)) _, err = store.GetPrincipalByAPIKeyHash(context.Background(), util.HashToken(token))
if err == nil { if err == nil {
t.Fatalf("expected error for disabled principal") t.Fatalf("expected error for disabled principal")
} }
+6 -5
View File
@@ -1,5 +1,6 @@
package tests package tests
import "context"
import "testing" import "testing"
import "codit/internal/db" import "codit/internal/db"
@@ -18,7 +19,7 @@ func createTestProject(t *testing.T, store *db.Store, user models.User, slug str
UpdatedBy: user.ID, UpdatedBy: user.ID,
HomePage: "info", HomePage: "info",
} }
project, err = store.CreateProject(project) project, err = store.CreateProject(context.Background(), project)
if err != nil { if err != nil {
t.Fatalf("create project: %v", err) t.Fatalf("create project: %v", err)
} }
@@ -85,14 +86,14 @@ func TestResetRunningRPMMirrorTasksMarksRunsFailed(t *testing.T) {
project = createTestProject(t, store, user, "mirror-reset") project = createTestProject(t, store, user, "mirror-reset")
repo = createTestRPMRepo(t, store, project, user, "repo") repo = createTestRPMRepo(t, store, project, user, "repo")
dir = createTestRPMMirrorDir(t, store, repo, "x86_64", 600) dir = createTestRPMMirrorDir(t, store, repo, "x86_64", 600)
runID, started, err = store.TryStartRPMMirrorRun(repo.ID, dir.Path, 1000) runID, started, err = store.TryStartRPMMirrorRun(context.Background(), repo.ID, dir.Path, 1000)
if err != nil { if err != nil {
t.Fatalf("try start mirror run: %v", err) t.Fatalf("try start mirror run: %v", err)
} }
if !started { if !started {
t.Fatalf("expected mirror run to start") t.Fatalf("expected mirror run to start")
} }
err = store.ResetRunningRPMMirrorTasks() err = store.ResetRunningRPMMirrorTasks(context.Background(), )
if err != nil { if err != nil {
t.Fatalf("reset running mirror tasks: %v", err) t.Fatalf("reset running mirror tasks: %v", err)
} }
@@ -147,14 +148,14 @@ func TestFinishRPMMirrorTaskRunUpdatesTaskAndRun(t *testing.T) {
project = createTestProject(t, store, user, "mirror-finish") project = createTestProject(t, store, user, "mirror-finish")
repo = createTestRPMRepo(t, store, project, user, "repo") repo = createTestRPMRepo(t, store, project, user, "repo")
dir = createTestRPMMirrorDir(t, store, repo, "x86_64", 600) dir = createTestRPMMirrorDir(t, store, repo, "x86_64", 600)
runID, started, err = store.TryStartRPMMirrorRun(repo.ID, dir.Path, 1000) runID, started, err = store.TryStartRPMMirrorRun(context.Background(), repo.ID, dir.Path, 1000)
if err != nil { if err != nil {
t.Fatalf("try start mirror run: %v", err) t.Fatalf("try start mirror run: %v", err)
} }
if !started { if !started {
t.Fatalf("expected mirror run to start") t.Fatalf("expected mirror run to start")
} }
err = store.FinishRPMMirrorTaskRun(repo.ID, dir.Path, runID, true, 1700, "done", 4, 4, 0, 0, "rev-1", "") err = store.FinishRPMMirrorTaskRun(context.Background(), repo.ID, dir.Path, runID, true, 1700, "done", 4, 4, 0, 0, "rev-1", "")
if err != nil { if err != nil {
t.Fatalf("finish mirror task run: %v", err) t.Fatalf("finish mirror task run: %v", err)
} }
+4 -3
View File
@@ -1,12 +1,13 @@
package tests package tests
import "context"
import "testing" import "testing"
import "codit/internal/models" import "codit/internal/models"
func createTestUserGroup(t *testing.T, store interface { func createTestUserGroup(t *testing.T, store interface {
CreateUserGroup(models.UserGroup) (models.UserGroup, error) CreateUserGroup(models.UserGroup) (models.UserGroup, error)
AddUserGroupMember(string, string) error AddUserGroupMember(context.Context, string, string) error
}, name string, userID string) models.UserGroup { }, name string, userID string) models.UserGroup {
var group models.UserGroup var group models.UserGroup
var err error var err error
@@ -20,7 +21,7 @@ func createTestUserGroup(t *testing.T, store interface {
if err != nil { if err != nil {
t.Fatalf("create user group: %v", err) t.Fatalf("create user group: %v", err)
} }
err = store.AddUserGroupMember(group.ID, userID) err = store.AddUserGroupMember(context.Background(), group.ID, userID)
if err != nil { if err != nil {
t.Fatalf("add user group member: %v", err) t.Fatalf("add user group member: %v", err)
} }
@@ -55,7 +56,7 @@ func TestSSHAccessProfileVisibilityForUserAndGroupTargets(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("create ssh server: %v", err) t.Fatalf("create ssh server: %v", err)
} }
created, err = store.CreateSSHAccessProfile(models.SSHAccessProfile{ created, err = store.CreateSSHAccessProfile(context.Background(), models.SSHAccessProfile{
ServerID: server.ID, ServerID: server.ID,
Name: "web deploy", Name: "web deploy",
Description: "deploy access", Description: "deploy access",
@@ -1,5 +1,6 @@
package tests package tests
import "context"
import "testing" import "testing"
import "time" import "time"
@@ -15,7 +16,7 @@ func TestSSHPrincipalGrantStoresMultiplePrincipals(t *testing.T) {
defer dbStore.Close() defer dbStore.Close()
user = createTestUser(t, dbStore, "ssh-grant-user") user = createTestUser(t, dbStore, "ssh-grant-user")
created, err = dbStore.CreateSSHPrincipalGrant(models.SSHPrincipalGrant{ created, err = dbStore.CreateSSHPrincipalGrant(context.Background(), models.SSHPrincipalGrant{
Name: "hyung-hwan-login", Name: "hyung-hwan-login",
Principals: []string{"hyung-hwan", "ops"}, Principals: []string{"hyung-hwan", "ops"},
Targets: []models.SSHPrincipalGrantTarget{ Targets: []models.SSHPrincipalGrantTarget{