// This file was auto-generated by the veyron vdl tool.
// Source: identity.vdl

// Package identity defines services for identity providers in the veyron ecosystem.
package identity

import (
	// VDL system imports
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/ipc"

	// VDL user imports
	"v.io/v23/security"
)

// OAuthBlesserClientMethods is the client interface
// containing OAuthBlesser methods.
//
// OAuthBlesser exchanges OAuth access tokens for
// an email address from an OAuth-based identity provider and uses the email
// address obtained to bless the client.
//
// OAuth is described in RFC 6749 (http://tools.ietf.org/html/rfc6749),
// though the Google implementation also has informative documentation at
// https://developers.google.com/accounts/docs/OAuth2
//
// WARNING: There is no binding between the channel over which the access token
// was obtained (typically https) and the channel used to make the RPC (a
// veyron virtual circuit).
// Thus, if Mallory possesses the access token associated with Alice's account,
// she may be able to obtain a blessing with Alice's name on it.
type OAuthBlesserClientMethods interface {
	// BlessUsingAccessToken uses the provided access token to obtain the email
	// address and returns a blessing along with the email address.
	BlessUsingAccessToken(ctx *context.T, token string, opts ...ipc.CallOpt) (blessing security.WireBlessings, email string, err error)
}

// OAuthBlesserClientStub adds universal methods to OAuthBlesserClientMethods.
type OAuthBlesserClientStub interface {
	OAuthBlesserClientMethods
	ipc.UniversalServiceMethods
}

// OAuthBlesserClient returns a client stub for OAuthBlesser.
func OAuthBlesserClient(name string, opts ...ipc.BindOpt) OAuthBlesserClientStub {
	var client ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(ipc.Client); ok {
			client = clientOpt
		}
	}
	return implOAuthBlesserClientStub{name, client}
}

type implOAuthBlesserClientStub struct {
	name   string
	client ipc.Client
}

func (c implOAuthBlesserClientStub) c(ctx *context.T) ipc.Client {
	if c.client != nil {
		return c.client
	}
	return v23.GetClient(ctx)
}

func (c implOAuthBlesserClientStub) BlessUsingAccessToken(ctx *context.T, i0 string, opts ...ipc.CallOpt) (o0 security.WireBlessings, o1 string, err error) {
	var call ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessUsingAccessToken", []interface{}{i0}, opts...); err != nil {
		return
	}
	err = call.Finish(&o0, &o1)
	return
}

// OAuthBlesserServerMethods is the interface a server writer
// implements for OAuthBlesser.
//
// OAuthBlesser exchanges OAuth access tokens for
// an email address from an OAuth-based identity provider and uses the email
// address obtained to bless the client.
//
// OAuth is described in RFC 6749 (http://tools.ietf.org/html/rfc6749),
// though the Google implementation also has informative documentation at
// https://developers.google.com/accounts/docs/OAuth2
//
// WARNING: There is no binding between the channel over which the access token
// was obtained (typically https) and the channel used to make the RPC (a
// veyron virtual circuit).
// Thus, if Mallory possesses the access token associated with Alice's account,
// she may be able to obtain a blessing with Alice's name on it.
type OAuthBlesserServerMethods interface {
	// BlessUsingAccessToken uses the provided access token to obtain the email
	// address and returns a blessing along with the email address.
	BlessUsingAccessToken(ctx ipc.ServerContext, token string) (blessing security.WireBlessings, email string, err error)
}

// OAuthBlesserServerStubMethods is the server interface containing
// OAuthBlesser methods, as expected by ipc.Server.
// There is no difference between this interface and OAuthBlesserServerMethods
// since there are no streaming methods.
type OAuthBlesserServerStubMethods OAuthBlesserServerMethods

// OAuthBlesserServerStub adds universal methods to OAuthBlesserServerStubMethods.
type OAuthBlesserServerStub interface {
	OAuthBlesserServerStubMethods
	// Describe the OAuthBlesser interfaces.
	Describe__() []ipc.InterfaceDesc
}

// OAuthBlesserServer returns a server stub for OAuthBlesser.
// It converts an implementation of OAuthBlesserServerMethods into
// an object that may be used by ipc.Server.
func OAuthBlesserServer(impl OAuthBlesserServerMethods) OAuthBlesserServerStub {
	stub := implOAuthBlesserServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := ipc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := ipc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implOAuthBlesserServerStub struct {
	impl OAuthBlesserServerMethods
	gs   *ipc.GlobState
}

func (s implOAuthBlesserServerStub) BlessUsingAccessToken(ctx ipc.ServerContext, i0 string) (security.WireBlessings, string, error) {
	return s.impl.BlessUsingAccessToken(ctx, i0)
}

func (s implOAuthBlesserServerStub) Globber() *ipc.GlobState {
	return s.gs
}

func (s implOAuthBlesserServerStub) Describe__() []ipc.InterfaceDesc {
	return []ipc.InterfaceDesc{OAuthBlesserDesc}
}

// OAuthBlesserDesc describes the OAuthBlesser interface.
var OAuthBlesserDesc ipc.InterfaceDesc = descOAuthBlesser

// descOAuthBlesser hides the desc to keep godoc clean.
var descOAuthBlesser = ipc.InterfaceDesc{
	Name:    "OAuthBlesser",
	PkgPath: "v.io/core/veyron/services/identity",
	Doc:     "// OAuthBlesser exchanges OAuth access tokens for\n// an email address from an OAuth-based identity provider and uses the email\n// address obtained to bless the client.\n//\n// OAuth is described in RFC 6749 (http://tools.ietf.org/html/rfc6749),\n// though the Google implementation also has informative documentation at\n// https://developers.google.com/accounts/docs/OAuth2\n//\n// WARNING: There is no binding between the channel over which the access token\n// was obtained (typically https) and the channel used to make the RPC (a\n// veyron virtual circuit).\n// Thus, if Mallory possesses the access token associated with Alice's account,\n// she may be able to obtain a blessing with Alice's name on it.",
	Methods: []ipc.MethodDesc{
		{
			Name: "BlessUsingAccessToken",
			Doc:  "// BlessUsingAccessToken uses the provided access token to obtain the email\n// address and returns a blessing along with the email address.",
			InArgs: []ipc.ArgDesc{
				{"token", ``}, // string
			},
			OutArgs: []ipc.ArgDesc{
				{"blessing", ``}, // security.WireBlessings
				{"email", ``},    // string
			},
		},
	},
}

// MacaroonBlesserClientMethods is the client interface
// containing MacaroonBlesser methods.
//
// MacaroonBlesser returns a blessing given the provided macaroon string.
type MacaroonBlesserClientMethods interface {
	// Bless uses the provided macaroon (which contains email and caveats)
	// to return a blessing for the client.
	Bless(ctx *context.T, macaroon string, opts ...ipc.CallOpt) (blessing security.WireBlessings, err error)
}

// MacaroonBlesserClientStub adds universal methods to MacaroonBlesserClientMethods.
type MacaroonBlesserClientStub interface {
	MacaroonBlesserClientMethods
	ipc.UniversalServiceMethods
}

// MacaroonBlesserClient returns a client stub for MacaroonBlesser.
func MacaroonBlesserClient(name string, opts ...ipc.BindOpt) MacaroonBlesserClientStub {
	var client ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(ipc.Client); ok {
			client = clientOpt
		}
	}
	return implMacaroonBlesserClientStub{name, client}
}

type implMacaroonBlesserClientStub struct {
	name   string
	client ipc.Client
}

func (c implMacaroonBlesserClientStub) c(ctx *context.T) ipc.Client {
	if c.client != nil {
		return c.client
	}
	return v23.GetClient(ctx)
}

func (c implMacaroonBlesserClientStub) Bless(ctx *context.T, i0 string, opts ...ipc.CallOpt) (o0 security.WireBlessings, err error) {
	var call ipc.Call
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Bless", []interface{}{i0}, opts...); err != nil {
		return
	}
	err = call.Finish(&o0)
	return
}

// MacaroonBlesserServerMethods is the interface a server writer
// implements for MacaroonBlesser.
//
// MacaroonBlesser returns a blessing given the provided macaroon string.
type MacaroonBlesserServerMethods interface {
	// Bless uses the provided macaroon (which contains email and caveats)
	// to return a blessing for the client.
	Bless(ctx ipc.ServerContext, macaroon string) (blessing security.WireBlessings, err error)
}

// MacaroonBlesserServerStubMethods is the server interface containing
// MacaroonBlesser methods, as expected by ipc.Server.
// There is no difference between this interface and MacaroonBlesserServerMethods
// since there are no streaming methods.
type MacaroonBlesserServerStubMethods MacaroonBlesserServerMethods

// MacaroonBlesserServerStub adds universal methods to MacaroonBlesserServerStubMethods.
type MacaroonBlesserServerStub interface {
	MacaroonBlesserServerStubMethods
	// Describe the MacaroonBlesser interfaces.
	Describe__() []ipc.InterfaceDesc
}

// MacaroonBlesserServer returns a server stub for MacaroonBlesser.
// It converts an implementation of MacaroonBlesserServerMethods into
// an object that may be used by ipc.Server.
func MacaroonBlesserServer(impl MacaroonBlesserServerMethods) MacaroonBlesserServerStub {
	stub := implMacaroonBlesserServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := ipc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := ipc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implMacaroonBlesserServerStub struct {
	impl MacaroonBlesserServerMethods
	gs   *ipc.GlobState
}

func (s implMacaroonBlesserServerStub) Bless(ctx ipc.ServerContext, i0 string) (security.WireBlessings, error) {
	return s.impl.Bless(ctx, i0)
}

func (s implMacaroonBlesserServerStub) Globber() *ipc.GlobState {
	return s.gs
}

func (s implMacaroonBlesserServerStub) Describe__() []ipc.InterfaceDesc {
	return []ipc.InterfaceDesc{MacaroonBlesserDesc}
}

// MacaroonBlesserDesc describes the MacaroonBlesser interface.
var MacaroonBlesserDesc ipc.InterfaceDesc = descMacaroonBlesser

// descMacaroonBlesser hides the desc to keep godoc clean.
var descMacaroonBlesser = ipc.InterfaceDesc{
	Name:    "MacaroonBlesser",
	PkgPath: "v.io/core/veyron/services/identity",
	Doc:     "// MacaroonBlesser returns a blessing given the provided macaroon string.",
	Methods: []ipc.MethodDesc{
		{
			Name: "Bless",
			Doc:  "// Bless uses the provided macaroon (which contains email and caveats)\n// to return a blessing for the client.",
			InArgs: []ipc.ArgDesc{
				{"macaroon", ``}, // string
			},
			OutArgs: []ipc.ArgDesc{
				{"blessing", ``}, // security.WireBlessings
			},
		},
	},
}
