provider

package
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2021 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package provider provides the database.Model implementation for the Provider entity that represents an external provider a user has connected to (GitHub, GitLab, etc.).

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidSignature = errors.New("invalid signature")
	ErrStateMismatch    = errors.New("state mismatch")
	ErrLocalhost        = errors.New("cannot use localhost for webhook URL")

	StatusDescriptions = map[runner.Status]string{
		runner.Queued:             "Build is queued.",
		runner.Running:            "Build is running.",
		runner.Passed:             "Build has passed.",
		runner.PassedWithFailures: "Build has passed with failures.",
		runner.Failed:             "Build has failed.",
		runner.Killed:             "Build was killed.",
		runner.TimedOut:           "Build has timed out.",
	}
)

Functions

func GetNextAndPrev

func GetNextAndPrev(link string) (int64, int64)

GetNextAndPrev link returns the page numbers for the next and previous page based off the given link string. This string is expected to be the value of a Link header (RFC-5988, RFC-8288). By default this will return 1 for both values if the given header value cannot be parsed properly.

func Model

func Model(pp []*Provider) func(int) database.Model

Model is called along with database.ModelSlice to convert the given slice of Provider models to a slice of database.Model interfaces.

func RepoModel

func RepoModel(rr []*Repo) func(int) database.Model

RepoModel is called along with database.ModelSlice to convert the given slice of Repo models to a slice of database.Model interfaces.

func Select

func Select(col string, opts ...query.Option) query.Query

Select returns a query that selects the given column from the providers table, with each given query.Option applied to the returned query.

Types

type BaseClient

type BaseClient struct {
	oauth2.Config

	// Host is the host of the server acting as the OAuth client for the
	// provider's OAuth server.
	Host string

	// APIEndpoint is the full URL where the provider's REST API is located.
	APIEndpoint string

	// State is the string used for verifying the final token exchange in the
	// webflow.
	State string

	// Secret is the secret that is set on each webhook created to verify the
	// request body sent by the provider.
	Secret string
}

BaseClient provides a base implementation of a provider's Client. This is used for performing all of the HTTP requests to a provider's API.

func (BaseClient) Auth

func (c BaseClient) Auth(ctx context.Context, v url.Values) (string, string, User, error)

Auth implements the Client interface.

func (BaseClient) AuthURL

func (c BaseClient) AuthURL() string

AuthURL implements the Client interface.

func (BaseClient) Delete

func (c BaseClient) Delete(tok, endpoint string) (*http.Response, error)

Delete performs a DELETE request to the given endpoint using the given token string as the authentication token.

func (BaseClient) Get

func (c BaseClient) Get(tok, endpoint string) (*http.Response, error)

Get performs a GET request to the given endpoint using the given token string as the authentication token.

func (BaseClient) Post

func (c BaseClient) Post(tok, endpoint string, r io.Reader) (*http.Response, error)

Post performs a POST request to the given endpoint using the given token string as the authentication token, and using the given io.Reader as the request body.

type Client

type Client interface {
	// Auth performs the final token exchange in the webflow. Upon success this
	// will return the access token, refresh token, and the details of the
	// User who successfully authenticated.
	Auth(context.Context, url.Values) (string, string, User, error)

	// AuthURL returns the full URL for authenticating against a provider and
	// starting the token exchange webflow.
	AuthURL() string

	// Repos returns a list of repos from the provider the user either owns or
	// has access to (via a group). The given page delineates which page of
	// repositories to get if there are multiple pages. A database.Paginator is
	// returned if there are multiple pages. This should return the repositories
	// ordered by when they were last updated.
	Repos(string, int64) ([]*Repo, database.Paginator, error)

	// Groups returns the ID of groups that a user is a member of from the
	// provider (if any/supported). This will be used to create multiple
	// providers in the database for each group, allowing for easy lookup
	// during webhook execution, should any webhook contain a group ID in place
	// of a user ID.
	Groups(string) ([]int64, error)

	// ToggleRepo will toggle the webhook for the given Repo using the given
	// string as the authentication token. This will create a webhook if it
	// doesn't exist for the Repo, otherwise it will delete it.
	ToggleRepo(string, *Repo) error

	// SetCommitStatus will set the commit status for the given commit hash to
	// the given runner.Status. This should only be called on commits that
	// belong to a merge or pull request.
	SetCommitStatus(string, *Repo, runner.Status, string, string) error

	// VerifyRequest verifies the contents of the given io.Reader against the
	// given string secret. This is typically used for verifying the contents
	// of a webhook that has been sent from said provider. Upon success it will
	// return a byte slice read from the given io.Reader.
	VerifyRequest(io.Reader, string) ([]byte, error)
}

Client provides a simple interface for a provider's REST API.

type Factory

type Factory func(string, string, string, string, string) Client

Factory is the type for creating a new Client for a provider. This takes the host of the server acting as an OAuth client, the endpoint of the provider for accessing the API, the secret for verifying webhooks, and finally the client ID, and client secret for the app we'll be granting access to.

type Provider

type Provider struct {
	ID             int64         `db:"id"`
	UserID         int64         `db:"user_id"`
	ProviderUserID sql.NullInt64 `db:"provider_user_id"`
	Name           string        `db:"name"`
	AccessToken    []byte        `db:"access_token"`
	RefreshToken   []byte        `db:"refresh_token"`
	Connected      bool          `db:"connected"`
	MainAccount    bool          `db:"main_account"`
	ExpiresAt      time.Time     `db:"expires_at"`
	AuthURL        string        `db:"-"`

	User *user.User `db:"-"`
}

Provider is the type that represents an external Git hosting provider that has been connected to a user's account.

func (*Provider) Bind

func (p *Provider) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to a user.User model.

func (*Provider) Endpoint

func (*Provider) Endpoint(_ ...string) string

Endpoint implements the database.Model interface. This is a stub method and returns an empty string.

func (*Provider) IsZero

func (p *Provider) IsZero() bool

IsZero implements the database.Model interface.

func (*Provider) JSON

func (*Provider) JSON(_ string) map[string]interface{}

JSON implements the database.Model interface. This is a stub method and returns an empty map.

func (*Provider) Primary

func (p *Provider) Primary() (string, int64)

Primary implements the database.Model interface.

func (*Provider) Repos

func (p *Provider) Repos(crypto *crypto.AESGCM, reg *Registry, page int64) ([]*Repo, database.Paginator, error)

Repos get's the repositories from the current provider's API endpoint. The given crypto.AESGCM is used to decrypt the access token that is used to authenticate against the API. The given page is used to get the repositories on that given page.

func (*Provider) SetCommitStatus

func (p *Provider) SetCommitStatus(crypto *crypto.AESGCM, reg *Registry, r *Repo, status runner.Status, url, sha string) error

SetCommitStatus will set the given status for the given commit sha on the current provider. This assumes the given commit sha is part of a merge/pull request.

func (*Provider) SetPrimary

func (p *Provider) SetPrimary(id int64)

SetPrimary implements the database.Model interface.

func (*Provider) ToggleRepo

func (p *Provider) ToggleRepo(crypto *crypto.AESGCM, reg *Registry, r *Repo) error

ToggleRepo will with add or remove a hook for the given repository hosted on the current provider. This will either set/unset the HookID field on the given Repo struct, and will toggle the Enabled field depending on whether a hook was added or removed.

func (*Provider) Values

func (p *Provider) Values() map[string]interface{}

Values implements the database.Model interface. This will return a map with the following values, user_id, provider_user_id, name, access_token, refresh_token, connected, and expires_at.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry provides a thread-safe way of registering multiple Client implementations against a given name, and for retrieving them at a later point in time.

func NewRegistry

func NewRegistry() *Registry

func (*Registry) All

func (r *Registry) All() map[string]Client

All returns all Client implementations in the current Registry.

func (*Registry) Get

func (r *Registry) Get(name string) (Client, error)

Get returns a Client implementation for the given name. If no implementation is found then nil is returned along with an error.

func (*Registry) Register

func (r *Registry) Register(name string, imp Client)

Register the given Client implementation against the given name. If an implementation is already registered this will panic.

type Repo

type Repo struct {
	ID             int64         `db:"id"`
	UserID         int64         `db:"user_id"`
	ProviderID     int64         `db:"provider_id"`
	ProviderUserID int64         `db:"-"`
	HookID         sql.NullInt64 `db:"hook_id"`
	RepoID         int64         `db:"repo_id"`
	ProviderName   string        `db:"provider_name"`
	Enabled        bool          `db:"enabled"`
	Name           string        `db:"name"`
	Href           string        `db:"href"`

	User     *user.User `db:"-"`
	Provider *Provider  `db:"-"`
}

Repo is the type that represents a Repo from a remote Git hosting provider.

func RepoFromContext

func RepoFromContext(ctx context.Context) (*Repo, bool)

RepoFromContext returns the Repo model from the given context, if any.

func (*Repo) Bind

func (r *Repo) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to either a user.User model or Provider model.

func (*Repo) Endpoint

func (r *Repo) Endpoint(uri ...string) string

Endpoint returns the endpoint to the current Repo, and appends any of the given URI parts.

func (*Repo) IsZero

func (r *Repo) IsZero() bool

IsZero implements the database.Model interface.

func (*Repo) JSON

func (*Repo) JSON(_ string) map[string]interface{}

JSON implements the database.Model interface. This is a stub method and returns an empty map.

func (*Repo) Primary

func (r *Repo) Primary() (string, int64)

Primary implements the database.Model interface.

func (*Repo) SetPrimary

func (r *Repo) SetPrimary(id int64)

SetPrimary implements the database.Model interface.

func (*Repo) Values

func (r *Repo) Values() map[string]interface{}

Values implements the database.Model interface. This will return a map with the following values, user_id, provider_id, hook_id, repo_id, and enabled.

type RepoForm

type RepoForm struct {
	ProviderID int64  `schema:"provider_id"`
	RepoID     int64  `schema:"repo_id"`
	Name       string `schema:"name"`
	Href       string `schema:"href"`
}

Form is the type that represents the input data for enabling/disabling a repository on a Git hosting provider.

func (RepoForm) Fields

func (f RepoForm) Fields() map[string]string

Fields implements the form.Form interface. This will always return an empty map.

func (RepoForm) Validate

func (f RepoForm) Validate() error

Validate implements the form.Form interface. This will always return nil as the Form cannot accept user inputs, it is something that is pre-populated.

type RepoStore

type RepoStore struct {
	database.Store

	// User is the bound user.User model. If not nil this will bind the
	// user.User model to any Repo models that are created. If not nil this
	// will append a WHERE clause on the user_id column for all SELECT queries
	// performed.
	User *user.User

	// Provider is the bound Provider model. If not nil this will bind the
	// Provider model to any Repo models that are created. If not nil this will
	// append a WHERE clause on the provider_id column for all SELECT queries
	// performed.
	Provider *Provider
}

RepoStore is the type for creating and modifying Repo models in the database.

func NewRepoStore

func NewRepoStore(db *sqlx.DB, mm ...database.Model) *RepoStore

NewRepoStore returns a new RepoStore for querying the provider_repos table. Each database passed to this function will be bound to the returned RepoStore.

func (*RepoStore) All

func (s *RepoStore) All(opts ...query.Option) ([]*Repo, error)

All returns a slice Repo models, applying each query.Option that is given. The database.Where option is applied to the *user.User and *Provider bound models.

func (*RepoStore) Bind

func (s *RepoStore) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to either a user.User model or Provider model.

func (*RepoStore) Delete

func (s *RepoStore) Delete(ids ...int64) error

Delete deletes the repos from the database with the given ids.

func (*RepoStore) Get

func (s *RepoStore) Get(opts ...query.Option) (*Repo, error)

Get returns a single Repo database, applying each query.Option that is given. The database.Where option is applied to the *user.User and *Provider bound models.

func (*RepoStore) New

func (s *RepoStore) New() *Repo

New returns a new Repo binding any non-nil models to it from the current RepoStore.

func (*RepoStore) Touch

func (s *RepoStore) Touch(r *Repo) error

Touch will create the given Repo if it does not exist, otherwise it will update it.

func (*RepoStore) Update

func (s *RepoStore) Update(rr ...*Repo) error

Update updates the given Repo models in the providers table.

type Store

type Store struct {
	database.Store

	// User is the bound user.User model. If not nil this will bind the
	// user.User model to any Provider models that are created. If not nil this
	// will append a WHERE clause on the user_id column for all SELECT queries
	// performed.
	User *user.User
}

Store is the type for creating and modifying Provider models in the database.

func NewStore

func NewStore(db *sqlx.DB, mm ...database.Model) *Store

NewStore returns a new Store for querying the providers table. Each database passed to this function will be bound to the returned Store.

func (*Store) All

func (s *Store) All(opts ...query.Option) ([]*Provider, error)

All returns a slice of Provider models, applying each query.Option that is given. The database.Where option is applied to the *user.User bound database.

func (*Store) Bind

func (s *Store) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to a user.User model.

func (*Store) Create

func (s *Store) Create(userId int64, name string, access, refresh []byte, main, connected bool) (*Provider, error)

Create creates a new provider of the given name, and with the given access and refresh tokens. The given userId parameter should be the ID of the user's account from the provider we're connecting to.

func (*Store) Delete

func (s *Store) Delete(pp ...*Provider) error

Delete deletes the given Provider models from the providers table.

func (*Store) Get

func (s *Store) Get(opts ...query.Option) (*Provider, error)

Get returns a single Provider model, applying each query.Option that is given. The database.Where option is applied to the *user.User bound database.

func (*Store) New

func (s *Store) New() *Provider

New returns a new Provider binding any non-nil models to it from the current Store.

func (*Store) Update

func (s *Store) Update(id, userId int64, name string, access, refresh []byte, main, connected bool) error

Update updates the provider in the database for the given id. This will set the userId, name, tokens, and connected status to the given values.

type User

type User struct {
	ID       int64  // ID of the user from the provider.
	Email    string // Email of the user from the provider.
	Login    string // Login of the user from the provider, this is only used for GitHub.
	Username string // Username of the user from the provider.
}

Directories

Path Synopsis
Package github provides an implementation of the provider.Client interface for the GitHub REST API.
Package github provides an implementation of the provider.Client interface for the GitHub REST API.
Package gitlab provides an implementation of the provider.Client interface for the GitLab REST API.
Package gitlab provides an implementation of the provider.Client interface for the GitLab REST API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL