...

Source file src/github.com/google/go-github/v47/test/integration/authorizations_test.go

Documentation: github.com/google/go-github/v47/test/integration

     1  // Copyright 2016 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  
     6  //go:build integration
     7  // +build integration
     8  
     9  package integration
    10  
    11  import (
    12  	"context"
    13  	"math/rand"
    14  	"os"
    15  	"strconv"
    16  	"strings"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/google/go-github/v47/github"
    21  )
    22  
    23  const msgEnvMissing = "Skipping test because the required environment variable (%v) is not present."
    24  const envKeyGitHubUsername = "GITHUB_USERNAME"
    25  const envKeyGitHubPassword = "GITHUB_PASSWORD"
    26  const envKeyClientID = "GITHUB_CLIENT_ID"
    27  const envKeyClientSecret = "GITHUB_CLIENT_SECRET"
    28  const envKeyAccessToken = "GITHUB_ACCESS_TOKEN"
    29  const InvalidTokenValue = "iamnotacroken"
    30  
    31  // TestAuthorizationsAppOperations tests the application/token related operations, such
    32  // as creating, testing, resetting and revoking application OAuth tokens.
    33  func TestAuthorizationsAppOperations(t *testing.T) {
    34  
    35  	appAuthenticatedClient := getOAuthAppClient(t)
    36  
    37  	// We know these vars are set because getOAuthAppClient would have
    38  	// skipped the test by now
    39  	clientID := os.Getenv(envKeyClientID)
    40  	accessToken := os.Getenv(envKeyAccessToken)
    41  
    42  	// Verify the token
    43  	appAuth, resp, err := appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, accessToken)
    44  	failOnError(t, err)
    45  	failIfNotStatusCode(t, resp, 200)
    46  
    47  	// Quick sanity check
    48  	if *appAuth.Token != accessToken {
    49  		t.Fatal("The returned auth/token does not match.")
    50  	}
    51  
    52  	// Let's verify that we get a 404 for a non-existent token
    53  	_, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, InvalidTokenValue)
    54  	if err == nil {
    55  		t.Fatal("An error should have been returned because of the invalid token.")
    56  	}
    57  	failIfNotStatusCode(t, resp, 404)
    58  
    59  	// Let's reset the token
    60  	resetAuth, resp, err := appAuthenticatedClient.Authorizations.Reset(context.Background(), clientID, accessToken)
    61  	failOnError(t, err)
    62  	failIfNotStatusCode(t, resp, 200)
    63  
    64  	// Let's verify that we get a 404 for a non-existent token
    65  	_, resp, err = appAuthenticatedClient.Authorizations.Reset(context.Background(), clientID, InvalidTokenValue)
    66  	if err == nil {
    67  		t.Fatal("An error should have been returned because of the invalid token.")
    68  	}
    69  	failIfNotStatusCode(t, resp, 404)
    70  
    71  	// Verify that the token has changed
    72  	if *resetAuth.Token == accessToken {
    73  		t.Fatal("The reset token should be different from the original.")
    74  	}
    75  
    76  	// Verify that we do have a token value
    77  	if *resetAuth.Token == "" {
    78  		t.Fatal("A token value should have been returned.")
    79  	}
    80  
    81  	// Verify that the original token is now invalid
    82  	_, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, accessToken)
    83  	if err == nil {
    84  		t.Fatal("The original token should be invalid.")
    85  	}
    86  	failIfNotStatusCode(t, resp, 404)
    87  
    88  	// Check that the reset token is valid
    89  	_, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *resetAuth.Token)
    90  	failOnError(t, err)
    91  	failIfNotStatusCode(t, resp, 200)
    92  
    93  	// Let's revoke the token
    94  	resp, err = appAuthenticatedClient.Authorizations.Revoke(context.Background(), clientID, *resetAuth.Token)
    95  	failOnError(t, err)
    96  	failIfNotStatusCode(t, resp, 204)
    97  
    98  	// Sleep for two seconds... I've seen cases where the revocation appears not
    99  	// to have take place immediately.
   100  	time.Sleep(time.Second * 2)
   101  
   102  	// Now, the reset token should also be invalid
   103  	_, resp, err = appAuthenticatedClient.Authorizations.Check(context.Background(), clientID, *resetAuth.Token)
   104  	if err == nil {
   105  		t.Fatal("The reset token should be invalid.")
   106  	}
   107  	failIfNotStatusCode(t, resp, 404)
   108  }
   109  
   110  // generatePersonalAuthTokenRequest is a helper function that generates an
   111  // AuthorizationRequest for a Personal Access Token (no client id).
   112  func generatePersonalAuthTokenRequest() *github.AuthorizationRequest {
   113  
   114  	rand := randString()
   115  	auth := github.AuthorizationRequest{
   116  		Note:        github.String("Personal token: Note generated by test: " + rand),
   117  		Scopes:      []github.Scope{github.ScopePublicRepo},
   118  		Fingerprint: github.String("Personal token: Fingerprint generated by test: " + rand),
   119  	}
   120  
   121  	return &auth
   122  }
   123  
   124  // generatePersonalAuthTokenRequest is a helper function that generates an
   125  // AuthorizationRequest for an OAuth application Token (uses client id).
   126  func generateAppAuthTokenRequest(clientID string, clientSecret string) *github.AuthorizationRequest {
   127  
   128  	rand := randString()
   129  	auth := github.AuthorizationRequest{
   130  		Note:         github.String("App token: Note generated by test: " + rand),
   131  		Scopes:       []github.Scope{github.ScopePublicRepo},
   132  		Fingerprint:  github.String("App token: Fingerprint generated by test: " + rand),
   133  		ClientID:     github.String(clientID),
   134  		ClientSecret: github.String(clientSecret),
   135  	}
   136  
   137  	return &auth
   138  }
   139  
   140  // randString returns a (kinda) random string for uniqueness purposes.
   141  func randString() string {
   142  	return strconv.FormatInt(rand.NewSource(time.Now().UnixNano()).Int63(), 10)
   143  }
   144  
   145  // failOnError invokes t.Fatal() if err is present.
   146  func failOnError(t *testing.T, err error) {
   147  
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  }
   152  
   153  // failIfNotStatusCode invokes t.Fatal() if the response's status code doesn't match the expected code.
   154  func failIfNotStatusCode(t *testing.T, resp *github.Response, expectedCode int) {
   155  
   156  	if resp.StatusCode != expectedCode {
   157  		t.Fatalf("Expected HTTP status code [%v] but received [%v]", expectedCode, resp.StatusCode)
   158  	}
   159  
   160  }
   161  
   162  // getUserPassClient returns a GitHub client for authorization testing. The client
   163  // uses BasicAuth via GH username and password passed in environment variables
   164  // (and will skip the calling test if those vars are not present).
   165  func getUserPassClient(t *testing.T) *github.Client {
   166  	username, ok := os.LookupEnv(envKeyGitHubUsername)
   167  	if !ok {
   168  		t.Skipf(msgEnvMissing, envKeyGitHubUsername)
   169  	}
   170  
   171  	password, ok := os.LookupEnv(envKeyGitHubPassword)
   172  	if !ok {
   173  		t.Skipf(msgEnvMissing, envKeyGitHubPassword)
   174  	}
   175  
   176  	tp := github.BasicAuthTransport{
   177  		Username: strings.TrimSpace(username),
   178  		Password: strings.TrimSpace(password),
   179  	}
   180  
   181  	return github.NewClient(tp.Client())
   182  }
   183  
   184  // getOAuthAppClient returns a GitHub client for authorization testing. The client
   185  // uses BasicAuth, but instead of username and password, it uses the client id
   186  // and client secret passed in via environment variables
   187  // (and will skip the calling test if those vars are not present). Certain API operations (check
   188  // an authorization; reset an authorization; revoke an authorization for an app)
   189  // require this authentication mechanism.
   190  //
   191  // See GitHub API docs: https://developer.com/v3/oauth_authorizations/#check-an-authorization
   192  func getOAuthAppClient(t *testing.T) *github.Client {
   193  
   194  	username, ok := os.LookupEnv(envKeyClientID)
   195  	if !ok {
   196  		t.Skipf(msgEnvMissing, envKeyClientID)
   197  	}
   198  
   199  	password, ok := os.LookupEnv(envKeyClientSecret)
   200  	if !ok {
   201  		t.Skipf(msgEnvMissing, envKeyClientSecret)
   202  	}
   203  
   204  	tp := github.BasicAuthTransport{
   205  		Username: strings.TrimSpace(username),
   206  		Password: strings.TrimSpace(password),
   207  	}
   208  
   209  	return github.NewClient(tp.Client())
   210  }
   211  

View as plain text