You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
9.7 KiB

  1. // Copyright 2015 The go-github AUTHORS. All rights reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package github
  6. import (
  7. "context"
  8. "fmt"
  9. )
  10. // Scope models a GitHub authorization scope.
  11. //
  12. // GitHub API docs: https://developer.github.com/v3/oauth/#scopes
  13. type Scope string
  14. // This is the set of scopes for GitHub API V3
  15. const (
  16. ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact?
  17. ScopeUser Scope = "user"
  18. ScopeUserEmail Scope = "user:email"
  19. ScopeUserFollow Scope = "user:follow"
  20. ScopePublicRepo Scope = "public_repo"
  21. ScopeRepo Scope = "repo"
  22. ScopeRepoDeployment Scope = "repo_deployment"
  23. ScopeRepoStatus Scope = "repo:status"
  24. ScopeDeleteRepo Scope = "delete_repo"
  25. ScopeNotifications Scope = "notifications"
  26. ScopeGist Scope = "gist"
  27. ScopeReadRepoHook Scope = "read:repo_hook"
  28. ScopeWriteRepoHook Scope = "write:repo_hook"
  29. ScopeAdminRepoHook Scope = "admin:repo_hook"
  30. ScopeAdminOrgHook Scope = "admin:org_hook"
  31. ScopeReadOrg Scope = "read:org"
  32. ScopeWriteOrg Scope = "write:org"
  33. ScopeAdminOrg Scope = "admin:org"
  34. ScopeReadPublicKey Scope = "read:public_key"
  35. ScopeWritePublicKey Scope = "write:public_key"
  36. ScopeAdminPublicKey Scope = "admin:public_key"
  37. ScopeReadGPGKey Scope = "read:gpg_key"
  38. ScopeWriteGPGKey Scope = "write:gpg_key"
  39. ScopeAdminGPGKey Scope = "admin:gpg_key"
  40. ScopeSecurityEvents Scope = "security_events"
  41. )
  42. // AuthorizationsService handles communication with the authorization related
  43. // methods of the GitHub API.
  44. //
  45. // This service requires HTTP Basic Authentication; it cannot be accessed using
  46. // an OAuth token.
  47. //
  48. // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/
  49. type AuthorizationsService service
  50. // Authorization represents an individual GitHub authorization.
  51. type Authorization struct {
  52. ID *int64 `json:"id,omitempty"`
  53. URL *string `json:"url,omitempty"`
  54. Scopes []Scope `json:"scopes,omitempty"`
  55. Token *string `json:"token,omitempty"`
  56. TokenLastEight *string `json:"token_last_eight,omitempty"`
  57. HashedToken *string `json:"hashed_token,omitempty"`
  58. App *AuthorizationApp `json:"app,omitempty"`
  59. Note *string `json:"note,omitempty"`
  60. NoteURL *string `json:"note_url,omitempty"`
  61. UpdatedAt *Timestamp `json:"updated_at,omitempty"`
  62. CreatedAt *Timestamp `json:"created_at,omitempty"`
  63. Fingerprint *string `json:"fingerprint,omitempty"`
  64. // User is only populated by the Check and Reset methods.
  65. User *User `json:"user,omitempty"`
  66. }
  67. func (a Authorization) String() string {
  68. return Stringify(a)
  69. }
  70. // AuthorizationApp represents an individual GitHub app (in the context of authorization).
  71. type AuthorizationApp struct {
  72. URL *string `json:"url,omitempty"`
  73. Name *string `json:"name,omitempty"`
  74. ClientID *string `json:"client_id,omitempty"`
  75. }
  76. func (a AuthorizationApp) String() string {
  77. return Stringify(a)
  78. }
  79. // Grant represents an OAuth application that has been granted access to an account.
  80. type Grant struct {
  81. ID *int64 `json:"id,omitempty"`
  82. URL *string `json:"url,omitempty"`
  83. App *AuthorizationApp `json:"app,omitempty"`
  84. CreatedAt *Timestamp `json:"created_at,omitempty"`
  85. UpdatedAt *Timestamp `json:"updated_at,omitempty"`
  86. Scopes []string `json:"scopes,omitempty"`
  87. }
  88. func (g Grant) String() string {
  89. return Stringify(g)
  90. }
  91. // AuthorizationRequest represents a request to create an authorization.
  92. type AuthorizationRequest struct {
  93. Scopes []Scope `json:"scopes,omitempty"`
  94. Note *string `json:"note,omitempty"`
  95. NoteURL *string `json:"note_url,omitempty"`
  96. ClientID *string `json:"client_id,omitempty"`
  97. ClientSecret *string `json:"client_secret,omitempty"`
  98. Fingerprint *string `json:"fingerprint,omitempty"`
  99. }
  100. func (a AuthorizationRequest) String() string {
  101. return Stringify(a)
  102. }
  103. // AuthorizationUpdateRequest represents a request to update an authorization.
  104. //
  105. // Note that for any one update, you must only provide one of the "scopes"
  106. // fields. That is, you may provide only one of "Scopes", or "AddScopes", or
  107. // "RemoveScopes".
  108. //
  109. // GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
  110. type AuthorizationUpdateRequest struct {
  111. Scopes []string `json:"scopes,omitempty"`
  112. AddScopes []string `json:"add_scopes,omitempty"`
  113. RemoveScopes []string `json:"remove_scopes,omitempty"`
  114. Note *string `json:"note,omitempty"`
  115. NoteURL *string `json:"note_url,omitempty"`
  116. Fingerprint *string `json:"fingerprint,omitempty"`
  117. }
  118. func (a AuthorizationUpdateRequest) String() string {
  119. return Stringify(a)
  120. }
  121. // Check if an OAuth token is valid for a specific app.
  122. //
  123. // Note that this operation requires the use of BasicAuth, but where the
  124. // username is the OAuth application clientID, and the password is its
  125. // clientSecret. Invalid tokens will return a 404 Not Found.
  126. //
  127. // The returned Authorization.User field will be populated.
  128. //
  129. // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#check-a-token
  130. func (s *AuthorizationsService) Check(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) {
  131. u := fmt.Sprintf("applications/%v/token", clientID)
  132. reqBody := &struct {
  133. AccessToken string `json:"access_token"`
  134. }{AccessToken: accessToken}
  135. req, err := s.client.NewRequest("POST", u, reqBody)
  136. if err != nil {
  137. return nil, nil, err
  138. }
  139. req.Header.Set("Accept", mediaTypeOAuthAppPreview)
  140. a := new(Authorization)
  141. resp, err := s.client.Do(ctx, req, a)
  142. if err != nil {
  143. return nil, resp, err
  144. }
  145. return a, resp, nil
  146. }
  147. // Reset is used to reset a valid OAuth token without end user involvement.
  148. // Applications must save the "token" property in the response, because changes
  149. // take effect immediately.
  150. //
  151. // Note that this operation requires the use of BasicAuth, but where the
  152. // username is the OAuth application clientID, and the password is its
  153. // clientSecret. Invalid tokens will return a 404 Not Found.
  154. //
  155. // The returned Authorization.User field will be populated.
  156. //
  157. // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#reset-a-token
  158. func (s *AuthorizationsService) Reset(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) {
  159. u := fmt.Sprintf("applications/%v/token", clientID)
  160. reqBody := &struct {
  161. AccessToken string `json:"access_token"`
  162. }{AccessToken: accessToken}
  163. req, err := s.client.NewRequest("PATCH", u, reqBody)
  164. if err != nil {
  165. return nil, nil, err
  166. }
  167. req.Header.Set("Accept", mediaTypeOAuthAppPreview)
  168. a := new(Authorization)
  169. resp, err := s.client.Do(ctx, req, a)
  170. if err != nil {
  171. return nil, resp, err
  172. }
  173. return a, resp, nil
  174. }
  175. // Revoke an authorization for an application.
  176. //
  177. // Note that this operation requires the use of BasicAuth, but where the
  178. // username is the OAuth application clientID, and the password is its
  179. // clientSecret. Invalid tokens will return a 404 Not Found.
  180. //
  181. // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#delete-an-app-token
  182. func (s *AuthorizationsService) Revoke(ctx context.Context, clientID, accessToken string) (*Response, error) {
  183. u := fmt.Sprintf("applications/%v/token", clientID)
  184. reqBody := &struct {
  185. AccessToken string `json:"access_token"`
  186. }{AccessToken: accessToken}
  187. req, err := s.client.NewRequest("DELETE", u, reqBody)
  188. if err != nil {
  189. return nil, err
  190. }
  191. req.Header.Set("Accept", mediaTypeOAuthAppPreview)
  192. return s.client.Do(ctx, req, nil)
  193. }
  194. // DeleteGrant deletes an OAuth application grant. Deleting an application's
  195. // grant will also delete all OAuth tokens associated with the application for
  196. // the user.
  197. //
  198. // GitHub API docs: https://developer.github.com/v3/apps/oauth_applications/#delete-an-app-authorization
  199. func (s *AuthorizationsService) DeleteGrant(ctx context.Context, clientID, accessToken string) (*Response, error) {
  200. u := fmt.Sprintf("applications/%v/grant", clientID)
  201. reqBody := &struct {
  202. AccessToken string `json:"access_token"`
  203. }{AccessToken: accessToken}
  204. req, err := s.client.NewRequest("DELETE", u, reqBody)
  205. if err != nil {
  206. return nil, err
  207. }
  208. req.Header.Set("Accept", mediaTypeOAuthAppPreview)
  209. return s.client.Do(ctx, req, nil)
  210. }
  211. // CreateImpersonation creates an impersonation OAuth token.
  212. //
  213. // This requires admin permissions. With the returned Authorization.Token
  214. // you can e.g. create or delete a user's public SSH key. NOTE: creating a
  215. // new token automatically revokes an existing one.
  216. //
  217. // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token
  218. func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) {
  219. u := fmt.Sprintf("admin/users/%v/authorizations", username)
  220. req, err := s.client.NewRequest("POST", u, authReq)
  221. if err != nil {
  222. return nil, nil, err
  223. }
  224. a := new(Authorization)
  225. resp, err := s.client.Do(ctx, req, a)
  226. if err != nil {
  227. return nil, resp, err
  228. }
  229. return a, resp, nil
  230. }
  231. // DeleteImpersonation deletes an impersonation OAuth token.
  232. //
  233. // NOTE: there can be only one at a time.
  234. //
  235. // GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token
  236. func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) {
  237. u := fmt.Sprintf("admin/users/%v/authorizations", username)
  238. req, err := s.client.NewRequest("DELETE", u, nil)
  239. if err != nil {
  240. return nil, err
  241. }
  242. return s.client.Do(ctx, req, nil)
  243. }