diff --git a/internal/access/store.go b/internal/access/store.go index 685f63a..7e07bc4 100644 --- a/internal/access/store.go +++ b/internal/access/store.go @@ -103,8 +103,9 @@ func (s *Store) HasAccessControl(projectID string) bool { if len(s.members[projectID]) > 0 { return true } + now := time.Now().UTC() for _, token := range s.tokens { - if token.ProjectID == projectID { + if token.ProjectID == projectID && token.RevokedAt == nil && (token.ExpiresAt == nil || now.Before(*token.ExpiresAt)) { return true } } diff --git a/internal/access/store_test.go b/internal/access/store_test.go index 555e419..e967241 100644 --- a/internal/access/store_test.go +++ b/internal/access/store_test.go @@ -102,3 +102,35 @@ func TestStoreKeepsLastProjectAdmin(t *testing.T) { t.Fatal("demoting the last project admin should fail") } } + +func TestStoreIgnoresExpiredAndRevokedTokensForAccessControl(t *testing.T) { + store, err := New(filepath.Join(t.TempDir(), "access.json")) + if err != nil { + t.Fatal(err) + } + expired := time.Now().UTC().Add(-time.Minute) + _, _, err = store.CreateToken("ssl", "过期令牌", RoleViewer, &expired) + if err != nil { + t.Fatal(err) + } + if store.HasAccessControl("ssl") { + t.Fatal("过期项目令牌不应启用项目权限控制") + } + _, secret, err := store.CreateToken("ssl", "待吊销令牌", RoleViewer, nil) + if err != nil { + t.Fatal(err) + } + tokens := store.ListTokens("ssl") + if len(tokens) != 2 { + t.Fatalf("项目令牌数量错误:%d", len(tokens)) + } + if _, err := store.RevokeToken("ssl", tokens[1].ID); err != nil { + t.Fatal(err) + } + if store.HasAccessControl("ssl") { + t.Fatal("仅剩过期或吊销令牌时不应启用项目权限控制") + } + if _, ok := store.AuthenticateToken("ssl", secret); ok { + t.Fatal("已吊销项目令牌仍可认证") + } +}