feat: App Keys API v2 (#10140)

# Which Problems Are Solved

This PR *partially* addresses #9450 . Specifically, it implements the
resource based API for app keys.

This PR, together with https://github.com/zitadel/zitadel/pull/10077
completes #9450 .

# How the Problems Are Solved

- Implementation of the following endpoints: `CreateApplicationKey`,
`DeleteApplicationKey`, `GetApplicationKey`, `ListApplicationKeys`
- `ListApplicationKeys` can filter by project, app or organization ID.
Sorting is also possible according to some criteria.
  - All endpoints use permissions V2

# TODO

 - [x] Deprecate old endpoints

# Additional Context

Closes #9450
This commit is contained in:
Marco A.
2025-07-02 09:34:19 +02:00
committed by GitHub
parent 64a03fba28
commit fce9e770ac
19 changed files with 1350 additions and 69 deletions

View File

@@ -98,6 +98,7 @@ type AuthNKey struct {
ChangeDate time.Time
ResourceOwner string
Sequence uint64
ApplicationID string
Expiration time.Time
Type domain.AuthNKeyType
@@ -222,6 +223,19 @@ func (q *Queries) SearchAuthNKeysData(ctx context.Context, queries *AuthNKeySear
return authNKeys, err
}
func (q *Queries) GetAuthNKeyByIDWithPermission(ctx context.Context, shouldTriggerBulk bool, id string, permissionCheck domain.PermissionCheck, queries ...SearchQuery) (*AuthNKey, error) {
key, err := q.GetAuthNKeyByID(ctx, shouldTriggerBulk, id, queries...)
if err != nil {
return nil, err
}
if err := appCheckPermission(ctx, key.ResourceOwner, key.AggregateID, permissionCheck); err != nil {
return nil, err
}
return key, nil
}
func (q *Queries) GetAuthNKeyByID(ctx context.Context, shouldTriggerBulk bool, id string, queries ...SearchQuery) (key *AuthNKey, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
@@ -330,6 +344,7 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys
AuthNKeyColumnSequence.identifier(),
AuthNKeyColumnExpiration.identifier(),
AuthNKeyColumnType.identifier(),
AuthNKeyColumnObjectID.identifier(),
countColumn.identifier(),
).From(authNKeyTable.identifier()).
PlaceholderFormat(sq.Dollar)
@@ -348,6 +363,7 @@ func prepareAuthNKeysQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeys
&authNKey.Sequence,
&authNKey.Expiration,
&authNKey.Type,
&authNKey.ApplicationID,
&count,
)
if err != nil {

View File

@@ -26,6 +26,7 @@ var (
` projections.authn_keys2.sequence,` +
` projections.authn_keys2.expiration,` +
` projections.authn_keys2.type,` +
` projections.authn_keys2.object_id,` +
` COUNT(*) OVER ()` +
` FROM projections.authn_keys2`
prepareAuthNKeysCols = []string{
@@ -37,6 +38,7 @@ var (
"sequence",
"expiration",
"type",
"object_id",
"count",
}
@@ -129,6 +131,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
uint64(20211109),
testNow,
1,
"app1",
},
},
),
@@ -147,6 +150,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
Sequence: 20211109,
Expiration: testNow,
Type: domain.AuthNKeyTypeJSON,
ApplicationID: "app1",
},
},
},
@@ -168,6 +172,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
uint64(20211109),
testNow,
1,
"app1",
},
{
"id-2",
@@ -178,6 +183,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
uint64(20211109),
testNow,
1,
"app1",
},
},
),
@@ -196,6 +202,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
Sequence: 20211109,
Expiration: testNow,
Type: domain.AuthNKeyTypeJSON,
ApplicationID: "app1",
},
{
ID: "id-2",
@@ -206,6 +213,7 @@ func Test_AuthNKeyPrepares(t *testing.T) {
Sequence: 20211109,
Expiration: testNow,
Type: domain.AuthNKeyTypeJSON,
ApplicationID: "app1",
},
},
},