Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3e06647

Browse files
committed
feat: rename special API key scopes to coder:* namespace
This change unifies scope handling by migrating special scopes to thecoder:* namespace while maintaining backward compatibility:- Database: 'all' -> 'coder:all', 'application_connect' -> 'coder:application_connect'- API accepts both legacy and canonical forms in requests- Responses maintain legacy format for existing client compatibility- Scope catalog returns all public scopes including canonical specials- Validation enforces public scope requirements using unified logicThe migration preserves existing API key functionality while establishingconsistent scope naming conventions for future extensibility.
1 parente25866a commit3e06647

31 files changed

+341
-127
lines changed

‎coderd/apidoc/docs.go‎

Lines changed: 90 additions & 3 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json‎

Lines changed: 32 additions & 5 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apikey.go‎

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"net/http"
77
"strconv"
8+
"strings"
89
"time"
910

1011
"github.com/go-chi/chi/v5"
@@ -66,9 +67,37 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) {
6667
return
6768
}
6869

69-
scope:=database.APIKeyScopeAll
70-
ifscope!="" {
71-
scope=database.APIKeyScope(createToken.Scope)
70+
// Compatibility shim: accept singular "scope" or plural "scopes".
71+
// Convert to canonical coder:* specials where applicable.
72+
varrequested []string
73+
iflen(createToken.Scopes)>0 {
74+
for_,s:=rangecreateToken.Scopes {
75+
requested=append(requested,string(s))
76+
}
77+
}elseifs:=strings.TrimSpace(string(createToken.Scope));s!="" {
78+
requested=append(requested,s)
79+
}
80+
81+
fori,s:=rangerequested {
82+
switchs {
83+
case"all":
84+
requested[i]="coder:all"
85+
case"application_connect":
86+
requested[i]="coder:application_connect"
87+
}
88+
}
89+
90+
vardbScopes database.APIKeyScopes
91+
for_,s:=rangerequested {
92+
ifrbac.IsPublicScope(rbac.ScopeName(s)) {
93+
dbScopes=append(dbScopes,database.APIKeyScope(s))
94+
continue
95+
}
96+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
97+
Message:"Invalid API key scope.",
98+
Detail:fmt.Sprintf("scope %q is not public or not recognized",s),
99+
})
100+
return
72101
}
73102

74103
tokenName:=namesgenerator.GetRandomName(1)
@@ -81,7 +110,7 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) {
81110
UserID:user.ID,
82111
LoginType:database.LoginTypeToken,
83112
DefaultLifetime:api.DeploymentValues.Sessions.DefaultTokenDuration.Value(),
84-
Scope:scope,
113+
Scopes:dbScopes,
85114
TokenName:tokenName,
86115
}
87116

‎coderd/apikey/apikey.go‎

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ type CreateParams struct {
2525
// Optional.
2626
ExpiresAt time.Time
2727
LifetimeSecondsint64
28-
Scope database.APIKeyScope
29-
TokenNamestring
30-
RemoteAddrstring
28+
// Deprecated: use Scopes. If set and Scopes is empty, Generate will create
29+
// a single-element Scopes slice containing this value.
30+
Scope database.APIKeyScope
31+
// If empty and Scope is also empty, Scopes default to the `coder:all`.
32+
Scopes database.APIKeyScopes
33+
TokenNamestring
34+
RemoteAddrstring
3135
}
3236

3337
// Generate generates an API key, returning the key as a string as well as the
@@ -62,14 +66,17 @@ func Generate(params CreateParams) (database.InsertAPIKeyParams, string, error)
6266

6367
bitlen:=len(ip)*8
6468

65-
scope:=database.APIKeyScopeAll
66-
ifparams.Scope!="" {
67-
scope=params.Scope
68-
}
69-
switchscope {
70-
casedatabase.APIKeyScopeAll,database.APIKeyScopeApplicationConnect:
71-
default:
72-
return database.InsertAPIKeyParams{},"",xerrors.Errorf("invalid API key scope: %q",scope)
69+
// Decide scopes using compatibility rules:
70+
// 1) If Scopes provided, use as-is.
71+
// 2) Else if Scope provided, wrap it.
72+
// 3) Else default to canonical coder:all.
73+
scopes:=params.Scopes
74+
iflen(scopes)==0 {
75+
ifparams.Scope!="" {
76+
scopes= database.APIKeyScopes{params.Scope}
77+
}else {
78+
scopes= database.APIKeyScopes{database.APIKeyScope("coder:all")}
79+
}
7380
}
7481

7582
token:=fmt.Sprintf("%s-%s",keyID,keySecret)
@@ -92,7 +99,7 @@ func Generate(params CreateParams) (database.InsertAPIKeyParams, string, error)
9299
UpdatedAt:dbtime.Now(),
93100
HashedSecret:hashed[:],
94101
LoginType:params.LoginType,
95-
Scopes:database.APIKeyScopes{scope},
102+
Scopes:scopes,
96103
AllowList: database.AllowList{database.AllowListWildcard()},
97104
TokenName:params.TokenName,
98105
},token,nil

‎coderd/apikey/apikey_test.go‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestGenerate(t *testing.T) {
3535
LifetimeSeconds:int64(time.Hour.Seconds()),
3636
TokenName:"hello",
3737
RemoteAddr:"1.2.3.4",
38-
Scope:database.APIKeyScopeApplicationConnect,
38+
Scope:database.ApiKeyScopeCoderApplicationConnect,
3939
},
4040
},
4141
{
@@ -62,7 +62,7 @@ func TestGenerate(t *testing.T) {
6262
ExpiresAt: time.Time{},
6363
TokenName:"hello",
6464
RemoteAddr:"1.2.3.4",
65-
Scope:database.APIKeyScopeApplicationConnect,
65+
Scope:database.ApiKeyScopeCoderApplicationConnect,
6666
},
6767
},
6868
{
@@ -75,7 +75,7 @@ func TestGenerate(t *testing.T) {
7575
ExpiresAt: time.Time{},
7676
TokenName:"hello",
7777
RemoteAddr:"1.2.3.4",
78-
Scope:database.APIKeyScopeApplicationConnect,
78+
Scope:database.ApiKeyScopeCoderApplicationConnect,
7979
},
8080
},
8181
{
@@ -88,7 +88,7 @@ func TestGenerate(t *testing.T) {
8888
LifetimeSeconds:int64(time.Hour.Seconds()),
8989
TokenName:"hello",
9090
RemoteAddr:"",
91-
Scope:database.APIKeyScopeApplicationConnect,
91+
Scope:database.ApiKeyScopeCoderApplicationConnect,
9292
},
9393
},
9494
{
@@ -161,7 +161,7 @@ func TestGenerate(t *testing.T) {
161161
iftc.params.Scope!="" {
162162
assert.True(t,key.Scopes.Has(tc.params.Scope))
163163
}else {
164-
assert.True(t,key.Scopes.Has(database.APIKeyScopeAll))
164+
assert.True(t,key.Scopes.Has(database.ApiKeyScopeCoderAll))
165165
}
166166

167167
iftc.params.TokenName!="" {

‎coderd/apikey_scopes_validation_test.go‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,17 @@ func TestTokenCreation_AllowsLegacyScopes(t *testing.T) {
5454
require.NoError(t,err)
5555
require.NotEmpty(t,resp.Key)
5656
}
57+
58+
funcTestTokenCreation_AllowsCanonicalSpecialScope(t*testing.T) {
59+
client:=coderdtest.New(t,nil)
60+
_=coderdtest.CreateFirstUser(t,client)
61+
62+
ctx,cancel:=context.WithTimeout(t.Context(),10*time.Second)
63+
defercancel()
64+
65+
resp,err:=client.CreateToken(ctx,codersdk.Me, codersdk.CreateTokenRequest{
66+
Scope:codersdk.APIKeyScopeCoderApplicationConnect,
67+
})
68+
require.NoError(t,err)
69+
require.NotEmpty(t,resp.Key)
70+
}

‎coderd/database/dbauthz/dbauthz_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func (s *MethodTestSuite) TestAPIKey() {
251251
}))
252252
s.Run("InsertAPIKey",s.Mocked(func(dbm*dbmock.MockStore,faker*gofakeit.Faker,check*expects) {
253253
u:=testutil.Fake(s.T(),faker, database.User{})
254-
arg:= database.InsertAPIKeyParams{UserID:u.ID,LoginType:database.LoginTypePassword,Scopes: database.APIKeyScopes{database.APIKeyScopeAll},IPAddress:defaultIPAddress()}
254+
arg:= database.InsertAPIKeyParams{UserID:u.ID,LoginType:database.LoginTypePassword,Scopes: database.APIKeyScopes{database.ApiKeyScopeCoderAll},IPAddress:defaultIPAddress()}
255255
ret:=testutil.Fake(s.T(),faker, database.APIKey{UserID:u.ID,LoginType:database.LoginTypePassword})
256256
dbm.EXPECT().InsertAPIKey(gomock.Any(),arg).Return(ret,nil).AnyTimes()
257257
check.Args(arg).Asserts(rbac.ResourceApiKey.WithOwner(u.ID.String()),policy.ActionCreate)
@@ -265,7 +265,7 @@ func (s *MethodTestSuite) TestAPIKey() {
265265
check.Args(arg).Asserts(a,policy.ActionUpdate).Returns()
266266
}))
267267
s.Run("DeleteApplicationConnectAPIKeysByUserID",s.Mocked(func(dbm*dbmock.MockStore,faker*gofakeit.Faker,check*expects) {
268-
a:=testutil.Fake(s.T(),faker, database.APIKey{Scopes: database.APIKeyScopes{database.APIKeyScopeApplicationConnect}})
268+
a:=testutil.Fake(s.T(),faker, database.APIKey{Scopes: database.APIKeyScopes{database.ApiKeyScopeCoderApplicationConnect}})
269269
dbm.EXPECT().DeleteApplicationConnectAPIKeysByUserID(gomock.Any(),a.UserID).Return(nil).AnyTimes()
270270
check.Args(a.UserID).Asserts(rbac.ResourceApiKey.WithOwner(a.UserID.String()),policy.ActionDelete).Returns()
271271
}))

‎coderd/database/dbgen/dbgen.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func APIKey(t testing.TB, db database.Store, seed database.APIKey, munge ...func
185185
CreatedAt:takeFirst(seed.CreatedAt,dbtime.Now()),
186186
UpdatedAt:takeFirst(seed.UpdatedAt,dbtime.Now()),
187187
LoginType:takeFirst(seed.LoginType,database.LoginTypePassword),
188-
Scopes:takeFirstSlice([]database.APIKeyScope(seed.Scopes), []database.APIKeyScope{database.APIKeyScopeAll}),
188+
Scopes:takeFirstSlice([]database.APIKeyScope(seed.Scopes), []database.APIKeyScope{database.ApiKeyScopeCoderAll}),
189189
AllowList:takeFirstSlice(seed.AllowList, database.AllowList{database.AllowListWildcard()}),
190190
TokenName:takeFirst(seed.TokenName),
191191
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp