mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add multi-scope support to API keys (#19917)
# Canonicalize API Key Scopes This PR introduces canonical API key scopes with a `coder:` namespace prefix to avoid collisions with low-level resource:action names. It: 1. Renames special API key scopes in the database: - `all` → `coder:all` - `application_connect` → `coder:application_connect` 2. Adds support for a new `scopes` field in the API key creation request, allowing multiple scopes to be specified while maintaining backward compatibility with the singular `scope` field. 3. Updates the API documentation to reflect these changes, including the new endpoint for listing public API key scopes. 4. Ensures backward compatibility by mapping between legacy and canonical scope names in relevant code paths.
This commit is contained in:
+14
-5
@@ -25,13 +25,12 @@ type CreateParams struct {
|
||||
// Optional.
|
||||
ExpiresAt time.Time
|
||||
LifetimeSeconds int64
|
||||
|
||||
// Scope is legacy single-scope input kept for backward compatibility.
|
||||
//
|
||||
// Deprecated: Prefer Scopes for new code.
|
||||
// Deprecated: use Scopes instead.
|
||||
Scope database.APIKeyScope
|
||||
// Scopes is the full list of scopes to attach to the key.
|
||||
// If empty and Scope is set, the generator will use [Scope].
|
||||
// If both are empty, the generator will default to [APIKeyScopeAll].
|
||||
Scopes database.APIKeyScopes
|
||||
TokenName string
|
||||
RemoteAddr string
|
||||
@@ -74,9 +73,19 @@ func Generate(params CreateParams) (database.InsertAPIKeyParams, string, error)
|
||||
case len(params.Scopes) > 0:
|
||||
scopes = params.Scopes
|
||||
case params.Scope != "":
|
||||
scopes = database.APIKeyScopes{params.Scope}
|
||||
var scope database.APIKeyScope
|
||||
switch params.Scope {
|
||||
case "all":
|
||||
scope = database.ApiKeyScopeCoderAll
|
||||
case "application_connect":
|
||||
scope = database.ApiKeyScopeCoderApplicationConnect
|
||||
default:
|
||||
scope = params.Scope
|
||||
}
|
||||
scopes = database.APIKeyScopes{scope}
|
||||
default:
|
||||
scopes = database.APIKeyScopes{database.APIKeyScopeAll}
|
||||
// Default to coder:all scope for backward compatibility.
|
||||
scopes = database.APIKeyScopes{database.ApiKeyScopeCoderAll}
|
||||
}
|
||||
|
||||
for _, s := range scopes {
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestGenerate(t *testing.T) {
|
||||
LifetimeSeconds: int64(time.Hour.Seconds()),
|
||||
TokenName: "hello",
|
||||
RemoteAddr: "1.2.3.4",
|
||||
Scope: database.APIKeyScopeApplicationConnect,
|
||||
Scope: database.ApiKeyScopeCoderApplicationConnect,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -62,7 +62,7 @@ func TestGenerate(t *testing.T) {
|
||||
ExpiresAt: time.Time{},
|
||||
TokenName: "hello",
|
||||
RemoteAddr: "1.2.3.4",
|
||||
Scope: database.APIKeyScopeApplicationConnect,
|
||||
Scope: database.ApiKeyScopeCoderApplicationConnect,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -75,7 +75,7 @@ func TestGenerate(t *testing.T) {
|
||||
ExpiresAt: time.Time{},
|
||||
TokenName: "hello",
|
||||
RemoteAddr: "1.2.3.4",
|
||||
Scope: database.APIKeyScopeApplicationConnect,
|
||||
Scope: database.ApiKeyScopeCoderApplicationConnect,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -88,7 +88,7 @@ func TestGenerate(t *testing.T) {
|
||||
LifetimeSeconds: int64(time.Hour.Seconds()),
|
||||
TokenName: "hello",
|
||||
RemoteAddr: "",
|
||||
Scope: database.APIKeyScopeApplicationConnect,
|
||||
Scope: database.ApiKeyScopeCoderApplicationConnect,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -161,7 +161,7 @@ func TestGenerate(t *testing.T) {
|
||||
if tc.params.Scope != "" {
|
||||
assert.True(t, key.Scopes.Has(tc.params.Scope))
|
||||
} else {
|
||||
assert.True(t, key.Scopes.Has(database.APIKeyScopeAll))
|
||||
assert.True(t, key.Scopes.Has(database.ApiKeyScopeCoderAll))
|
||||
}
|
||||
|
||||
if tc.params.TokenName != "" {
|
||||
|
||||
Reference in New Issue
Block a user