Browse Source

Support OAuth Authrization API.

Fixes #119
Fixes #241
sona-tar 10 years ago
committed by Will Norris
parent
commit
68828ce43f
3 changed files with 516 additions and 12 deletions
  1. +250
    -0
      github/authorizations.go
  2. +251
    -0
      github/authorizations_test.go
  3. +15
    -12
      github/github.go

+ 250
- 0
github/authorizations.go View File

@ -0,0 +1,250 @@
// Copyright 2015 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import "fmt"
// AuthorizationsService handles communication with the OAuth related
// methods of the GitHub API.
//
// This service requires HTTP Basic Authentication; it cannot be accessed using
// an OAuth token.
//
// GitHub API docs: http://developer.github.com/v3/oauth_authorizations/
type AuthorizationsService struct {
client *Client
}
// Authorization represents a GitHub authorized infomaration.
type Authorization struct {
ID *int `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Token *string `json:"token,omitempty"`
TokenLastEight *string `json:"token_last_eight,omitempty"`
HashedToken *string `json:"hashed_token,omitempty"`
App *AuthorizationApp `json:"app,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
UpdateAt *Timestamp `json:"updated_at,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
// AuthorizationApp represents application name that github allows app to use api
type AuthorizationApp struct {
URL *string `json:"url,omitempty"`
Name *string `json:"name,omitempty"`
ClientID *string `json:"client_id,omitempty"`
}
// AuthorizationRequest represents a request to create an authorization.
type AuthorizationRequest struct {
Scopes []string `json:"scopes,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
ClientID *string `json:"client_id,omitempty"`
ClientSecret *string `json:"client_secret,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
// AuthorizationUpdateRequest represents a request to update an authorization.
type AuthorizationUpdateRequest struct {
Scopes []string `json:"scopes,omitempty"`
AddScopes []string `json:"add_scopes,omitempty"`
RemoveScopes []string `json:"remove_scopes,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
// List the authorizations info the specified OAuth application.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations
func (s *AuthorizationsService) List(opt *ListOptions) ([]Authorization, *Response, error) {
u := "authorizations"
u, err := addOptions(u, opt)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
auths := new([]Authorization)
resp, err := s.client.Do(req, auths)
if err != nil {
return nil, resp, err
}
return *auths, resp, err
}
// Get a single authorization.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization
func (s *AuthorizationsService) Get(id int) (*Authorization, *Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(req, a)
if err != nil {
return nil, resp, err
}
return a, resp, err
}
// Create a new authorization for the specified OAuth application.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization
func (s *AuthorizationsService) Create(auth *AuthorizationRequest) (*Authorization, *Response, error) {
u := "authorizations"
req, err := s.client.NewRequest("POST", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(req, a)
if err != nil {
return nil, resp, err
}
return a, resp, err
}
// GetOrCreateForApp creates a new authorization for the specified OAuth
// application, only if an authorization for that application doesn’t already
// exist for the user.
//
// clientID is the OAuth Client ID with which to create the token.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app
func (s *AuthorizationsService) GetOrCreateForApp(clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) {
var u string
if auth.Fingerprint == nil || *auth.Fingerprint == "" {
u = fmt.Sprintf("authorizations/clients/%v", clientID)
} else {
u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint)
}
req, err := s.client.NewRequest("PUT", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(req, a)
if err != nil {
return nil, resp, err
}
return a, resp, err
}
// Edit a single authorization.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
func (s *AuthorizationsService) Edit(id int, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("PATCH", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(req, a)
if err != nil {
return nil, resp, err
}
return a, resp, err
}
// Delete a single authorization.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization
func (s *AuthorizationsService) Delete(id int) (*Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}
// Check a single authorization.
//
// OAuth applications can use this API method for checking OAuth token validity
// without running afoul of normal rate limits for failed login attempts.
// Authentication works differently with this particular endpoint. You must
// use Basic Authentication when accessing it, where the username is the OAuth
// application clientID and the password is its client_secret.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization
func (s *AuthorizationsService) Check(clientID string, token string) (*Authorization, *Response, error) {
u := fmt.Sprintf("applications/%s/tokens/%s", clientID, token)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(req, a)
if err != nil {
return nil, resp, err
}
return a, resp, err
}
// Reset a single authorization.
//
// OAuth applications can use this API method to reset a valid OAuth token
// without end user involvement. Applications must save the "token" property
// in the response, because changes take effect immediately.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization
func (s *AuthorizationsService) Reset(clientID string, token string) (*Authorization, *Response, error) {
u := fmt.Sprintf("applications/%s/tokens/%s", clientID, token)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(req, a)
if err != nil {
return nil, resp, err
}
return a, resp, err
}
// Revoke an authorization for an application.
//
// GitHub API Docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application
func (s *AuthorizationsService) Revoke(clientID string, token string) (*Response, error) {
u := fmt.Sprintf("applications/%s/tokens/%s", clientID, token)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(req, nil)
}

+ 251
- 0
github/authorizations_test.go View File

@ -0,0 +1,251 @@
// Copyright 2015 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
)
func TestAuthorizationsService_List(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/authorizations", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{"page": "1", "per_page": "2"})
fmt.Fprint(w, `[{"id":1}]`)
})
opt := &ListOptions{Page: 1, PerPage: 2}
got, _, err := client.Authorizations.List(opt)
if err != nil {
t.Errorf("Authorizations.List returned error: %v", err)
}
want := []Authorization{{ID: Int(1)}}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorizations.List returned %+v, want %+v", *got[0].ID, *want[0].ID)
}
}
func TestAuthorizationsService_Get(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{"id":1}`)
})
got, _, err := client.Authorizations.Get(1)
if err != nil {
t.Errorf("Authorizations.Get returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorizations.Get returned auth %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_Create(t *testing.T) {
setup()
defer teardown()
input := &AuthorizationRequest{
Note: String("test"),
}
mux.HandleFunc("/authorizations", func(w http.ResponseWriter, r *http.Request) {
v := new(AuthorizationRequest)
json.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "POST")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
fmt.Fprint(w, `{"ID":1}`)
})
got, _, err := client.Authorizations.Create(input)
if err != nil {
t.Errorf("Authorizations.Create returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorization.Create returned %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_GetOrCreateForApp(t *testing.T) {
setup()
defer teardown()
input := &AuthorizationRequest{
Note: String("test"),
}
mux.HandleFunc("/authorizations/clients/id", func(w http.ResponseWriter, r *http.Request) {
v := new(AuthorizationRequest)
json.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "PUT")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
fmt.Fprint(w, `{"ID":1}`)
})
got, _, err := client.Authorizations.GetOrCreateForApp("id", input)
if err != nil {
t.Errorf("Authorizations.GetOrCreateForApp returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorization.GetOrCreateForApp returned %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_GetOrCreateForApp_Fingerprint(t *testing.T) {
setup()
defer teardown()
input := &AuthorizationRequest{
Note: String("test"),
Fingerprint: String("fp"),
}
mux.HandleFunc("/authorizations/clients/id/fp", func(w http.ResponseWriter, r *http.Request) {
v := new(AuthorizationRequest)
json.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "PUT")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
fmt.Fprint(w, `{"ID":1}`)
})
got, _, err := client.Authorizations.GetOrCreateForApp("id", input)
if err != nil {
t.Errorf("Authorizations.GetOrCreateForApp returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorization.GetOrCreateForApp returned %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_Edit(t *testing.T) {
setup()
defer teardown()
input := &AuthorizationUpdateRequest{
Note: String("test"),
}
mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) {
v := new(AuthorizationUpdateRequest)
json.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "PATCH")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
fmt.Fprint(w, `{"ID":1}`)
})
got, _, err := client.Authorizations.Edit(1, input)
if err != nil {
t.Errorf("Authorizations.Edit returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorization.Update returned %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_Delete(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/authorizations/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
w.WriteHeader(http.StatusNoContent)
})
_, err := client.Authorizations.Delete(1)
if err != nil {
t.Errorf("Authorizations.Delete returned error: %v", err)
}
}
func TestAuthorizationsService_Check(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{"id":1}`)
})
got, _, err := client.Authorizations.Check("id", "t")
if err != nil {
t.Errorf("Authorizations.Check returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorizations.Check returned auth %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_Reset(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
fmt.Fprint(w, `{"ID":1}`)
})
got, _, err := client.Authorizations.Reset("id", "t")
if err != nil {
t.Errorf("Authorizations.Reset returned error: %v", err)
}
want := &Authorization{ID: Int(1)}
if !reflect.DeepEqual(got, want) {
t.Errorf("Authorizations.Reset returned auth %+v, want %+v", got, want)
}
}
func TestAuthorizationsService_Revoke(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/applications/id/tokens/t", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
w.WriteHeader(http.StatusNoContent)
})
_, err := client.Authorizations.Revoke("id", "t")
if err != nil {
t.Errorf("Authorizations.Revoke returned error: %v", err)
}
}

+ 15
- 12
github/github.go View File

@ -89,18 +89,19 @@ type Client struct {
rate Rate // Rate limit for the client as determined by the most recent API call.
// Services used for talking to different parts of the GitHub API.
Activity *ActivityService
Gists *GistsService
Git *GitService
Gitignores *GitignoresService
Issues *IssuesService
Organizations *OrganizationsService
PullRequests *PullRequestsService
Repositories *RepositoriesService
Search *SearchService
Users *UsersService
Licenses *LicensesService
Migrations *MigrationService
Activity *ActivityService
Authorizations *AuthorizationsService
Gists *GistsService
Git *GitService
Gitignores *GitignoresService
Issues *IssuesService
Organizations *OrganizationsService
PullRequests *PullRequestsService
Repositories *RepositoriesService
Search *SearchService
Users *UsersService
Licenses *LicensesService
Migrations *MigrationService
}
// ListOptions specifies the optional parameters to various List methods that
@ -153,6 +154,7 @@ func NewClient(httpClient *http.Client) *Client {
c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL}
c.Activity = &ActivityService{client: c}
c.Authorizations = &AuthorizationsService{client: c}
c.Gists = &GistsService{client: c}
c.Git = &GitService{client: c}
c.Gitignores = &GitignoresService{client: c}
@ -365,6 +367,7 @@ func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
}
}
}
return response, err
}


Loading…
Cancel
Save