@@ -9,8 +9,106 @@ import (
9
9
"context"
10
10
"fmt"
11
11
"net/http"
12
+ "net/url"
13
+ "strings"
12
14
)
13
15
16
+ // PersonalAccessToken represents the minimal representation of an organization programmatic access grant.
17
+ //
18
+ // GitHub API docs: https://docs.github.com/en/rest/orgs/personal-access-tokens?apiVersion=2022-11-28
19
+ type PersonalAccessToken struct {
20
+ // "Unique identifier of the fine-grained personal access token.
21
+ // The `pat_id` used to get details about an approved fine-grained personal access token.
22
+ ID * int64 `json:"id"`
23
+
24
+ // Owner is the GitHub user associated with the token.
25
+ Owner * User `json:"owner"`
26
+
27
+ // RepositorySelection is the type of repository selection requested.
28
+ // Possible values are: "none", "all", "subset".
29
+ RepositorySelection * string `json:"repository_selection"`
30
+
31
+ // URL to the list of repositories the fine-grained personal access token can access.
32
+ // Only follow when `repository_selection` is `subset`.
33
+ RepositoriesURL * string `json:"repositories_url"`
34
+
35
+ // Permissions are the permissions requested, categorized by type.
36
+ Permissions * PersonalAccessTokenPermissions `json:"permissions"`
37
+
38
+ // Date and time when the fine-grained personal access token was approved to access the organization.
39
+ AccessGrantedAt * Timestamp `json:"access_granted_at"`
40
+
41
+ // Whether the associated fine-grained personal access token has expired.
42
+ TokenExpired * bool `json:"token_expired"`
43
+
44
+ // Date and time when the associated fine-grained personal access token expires.
45
+ TokenExpiresAt * Timestamp `json:"token_expires_at"`
46
+
47
+ // Date and time when the associated fine-grained personal access token was last used for authentication.
48
+ TokenLastUsedAt * Timestamp `json:"token_last_used_at"`
49
+ }
50
+
51
+ // ListFineGrainedPATOptions specifies optional parameters to ListFineGrainedPersonalAccessTokens.
52
+ type ListFineGrainedPATOptions struct {
53
+ // The property by which to sort the results.
54
+ // Default: created_at
55
+ // Value: created_at
56
+ Sort string `url:"sort,omitempty"`
57
+
58
+ // The direction to sort the results by.
59
+ // Default: desc
60
+ // Value: asc, desc
61
+ Direction string `url:"direction,omitempty"`
62
+
63
+ // A list of owner usernames to use to filter the results.
64
+ Owner []string `url:"-"`
65
+
66
+ // The name of the repository to use to filter the results.
67
+ Repository string `url:"repository,omitempty"`
68
+
69
+ // The permission to use to filter the results.
70
+ Permission string `url:"permission,omitempty"`
71
+
72
+ // Only show fine-grained personal access tokens used before the given time.
73
+ // This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
74
+ LastUsedBefore string `url:"last_used_before,omitempty"`
75
+
76
+ // Only show fine-grained personal access tokens used after the given time.
77
+ // This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
78
+ LastUsedAfter string `url:"last_used_after,omitempty"`
79
+
80
+ ListOptions
81
+ }
82
+
83
+ // ListFineGrainedPersonalAccessTokens lists approved fine-grained personal access tokens owned by organization members that can access organization resources.
84
+ // Only GitHub Apps can call this API, using the `Personal access tokens` organization permissions (read).
85
+ //
86
+ // GitHub API docs: https://docs.github.com/rest/orgs/personal-access-tokens#list-fine-grained-personal-access-tokens-with-access-to-organization-resources
87
+ //
88
+ //meta:operation GET /orgs/{org}/personal-access-tokens
89
+ func (s * OrganizationsService ) ListFineGrainedPersonalAccessTokens (ctx context.Context , org string , opts * ListFineGrainedPATOptions ) ([]* PersonalAccessToken , * Response , error ) {
90
+ u := fmt .Sprintf ("orgs/%v/personal-access-tokens" , org )
91
+ // The `owner` parameter is a special case that uses the `owner[]=...` format and needs a custom function to format it correctly.
92
+ u , err := addListFineGrainedPATOptions (u , opts )
93
+ if err != nil {
94
+ return nil , nil , err
95
+ }
96
+
97
+ req , err := s .client .NewRequest (http .MethodGet , u , opts )
98
+ if err != nil {
99
+ return nil , nil , err
100
+ }
101
+
102
+ var pats []* PersonalAccessToken
103
+
104
+ resp , err := s .client .Do (ctx , req , & pats )
105
+ if err != nil {
106
+ return nil , resp , err
107
+ }
108
+
109
+ return pats , resp , nil
110
+ }
111
+
14
112
// ReviewPersonalAccessTokenRequestOptions specifies the parameters to the ReviewPersonalAccessTokenRequest method.
15
113
type ReviewPersonalAccessTokenRequestOptions struct {
16
114
Action string `json:"action"`
@@ -34,3 +132,36 @@ func (s *OrganizationsService) ReviewPersonalAccessTokenRequest(ctx context.Cont
34
132
35
133
return s .client .Do (ctx , req , nil )
36
134
}
135
+
136
+ // addListFineGrainedPATOptions adds the owner parameter to the URL query string with the correct format if it is set.
137
+ //
138
+ // GitHub API expects the owner parameter to be a list of strings in the `owner[]=...` format.
139
+ // For multiple owner values, the owner parameter is repeated in the query string.
140
+ //
141
+ // Example:
142
+ // owner[]=user1&owner[]=user2
143
+ // This will filter the results to only include fine-grained personal access tokens owned by `user1` and `user2`.
144
+ //
145
+ // This function ensures the owner parameter is formatted correctly in the URL query string.
146
+ func addListFineGrainedPATOptions (s string , opts * ListFineGrainedPATOptions ) (string , error ) {
147
+ u , err := addOptions (s , opts )
148
+ if err != nil {
149
+ return s , err
150
+ }
151
+
152
+ if len (opts .Owner ) > 0 {
153
+ ownerVals := make ([]string , len (opts .Owner ))
154
+ for i , owner := range opts .Owner {
155
+ ownerVals [i ] = fmt .Sprintf ("owner[]=%s" , url .QueryEscape (owner ))
156
+ }
157
+ ownerQuery := strings .Join (ownerVals , "&" )
158
+
159
+ if strings .Contains (u , "?" ) {
160
+ u += "&" + ownerQuery
161
+ } else {
162
+ u += "?" + ownerQuery
163
+ }
164
+ }
165
+
166
+ return u , nil
167
+ }
0 commit comments