Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions github/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,17 @@ type App struct {

// InstallationToken represents an installation token.
type InstallationToken struct {
Token *string `json:"token,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Token *string `json:"token,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
}

// ScopedInstallationTokenRequest represents a request to create an
// installation token with limited repository and permission access.
type ScopedInstallationTokenRequest struct {
RepositoryIds *[]int64 `json:"repository_ids,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
}

// InstallationPermissions lists the permissions for metadata, contents, issues and single file for an installation.
Expand Down Expand Up @@ -190,6 +199,30 @@ func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*I
return t, resp, nil
}

// CreateScopedInstallationToken creates a new installation token
// with limited repository and permission access.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token
func (s *AppsService) CreateScopedInstallationToken(ctx context.Context, id int64, request *ScopedInstallationTokenRequest) (*InstallationToken, *Response, error) {
u := fmt.Sprintf("app/installations/%v/access_tokens", id)

req, err := s.client.NewRequest("POST", u, request)
if err != nil {
return nil, nil, err
}

// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)

t := new(InstallationToken)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}

return t, resp, nil
}

// Create a new attachment on user comment containing a url.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-a-content-attachment
Expand Down
83 changes: 83 additions & 0 deletions github/apps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package github

import (
"context"
"encoding/json"
"fmt"
"net/http"
"reflect"
Expand Down Expand Up @@ -185,6 +186,88 @@ func TestAppsService_CreateInstallationToken(t *testing.T) {
}
}

func TestAppsService_CreateRepositoryScopedInstallationToken(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

input := &ScopedInstallationTokenRequest{RepositoryIds: &[]int64{1}}

mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
v := new(ScopedInstallationTokenRequest)
json.NewDecoder(r.Body).Decode(v)

testMethod(t, r, "POST")
testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}

fmt.Fprint(w, `{"token":"t", "repositories": [{"id": 1}]}`)
})

token, _, err := client.Apps.CreateScopedInstallationToken(context.Background(), 1, input)
if err != nil {
t.Errorf("Apps.CreateScopedInstallationToken returned error: %v", err)
}

want := &InstallationToken{
Token: String("t"),
Repositories: []*Repository{
{ID: Int64(1)},
},
}

if !reflect.DeepEqual(token, want) {
t.Errorf("Apps.CreateScopedInstallationToken returned %+v, want %+v", token, want)
}
}

func TestAppsService_CreateRepositoryAndPermissionScopedInstallationToken(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

input := &ScopedInstallationTokenRequest{
RepositoryIds: &[]int64{1},
Permissions: &InstallationPermissions{
Metadata: String("read"),
Contents: String("read"),
},
}

mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
v := new(ScopedInstallationTokenRequest)
json.NewDecoder(r.Body).Decode(v)

testMethod(t, r, "POST")
testHeader(t, r, "Accept", mediaTypeIntegrationPreview)
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}

fmt.Fprint(w, `{"token":"t", "repositories": [{"id": 1}], "permissions": { "metadata": "read", "contents": "read" }}`)
})

token, _, err := client.Apps.CreateScopedInstallationToken(context.Background(), 1, input)
if err != nil {
t.Errorf("Apps.CreateScopedInstallationToken returned error: %v", err)
}

want := &InstallationToken{
Token: String("t"),
Repositories: []*Repository{
{ID: Int64(1)},
},
Permissions: &InstallationPermissions{
Metadata: String("read"),
Contents: String("read"),
},
}

if !reflect.DeepEqual(token, want) {
t.Errorf("Apps.CreateScopedInstallationToken returned %+v, want %+v", token, want)
}
}

func TestAppsService_CreateAttachement(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()
Expand Down
24 changes: 24 additions & 0 deletions github/github-accessors.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.