remove old certcache

This commit is contained in:
Cadey Ratio 2017-04-28 19:47:24 -07:00
parent 8fd83ff179
commit 6fc2e13e54
17 changed files with 816 additions and 147 deletions

View File

@ -1,12 +1,13 @@
package database
import (
"errors"
"time"
"github.com/Xe/ln"
"github.com/Xe/uuid"
"github.com/asdine/storm"
"github.com/brandur/simplebox"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@ -14,9 +15,13 @@ import (
var (
ErrNotImplemented = errors.New("database: not implemented")
ErrInvalidKind = errors.New("database: invalid route kind")
ErrRouteAlreadyExists = errors.New("database: route already exists")
ErrTokenAleradyExists = errors.New("database: token already exists")
ErrNoSuchRoute = errors.New("database: no such route")
ErrNoSuchToken = errors.New("database: no such token")
ErrCantDecryptCert = errors.New("database: can't decrypt cert")
ErrUnknownCryptMethod = errors.New("database: unknown encryption method")
ErrUnknown = errors.New("database: unknown error")
)
// BoltDBStorage is a backend that uses https://github.com/boltdb/bolt to store
@ -50,11 +55,24 @@ var (
func (b *BoltDBStorage) GetRoute(ctx context.Context, host string) (Route, error) {
r := Route{}
err := b.db.One("Hostname", host, &r)
return r, err
if err != nil {
ln.Error(err, ln.F{"err": err, "action": "route_get_route"})
switch err {
case storm.ErrNotFound:
return errors.Wrapf(err, "%v", ErrNoSuchRoute)
case storm.AlreadyExists:
return errors.Wrapf(err, "%v", ErrRouteAlreadyExists)
default:
return errors.Wrapf(err, "%v", ErrUnknown)
}
}
return r, nil
}
// GetAllRoutes gets all routes out of the database.
func (b *BoltDBStorage) GetAllRoutes(ctx context.Context) ([]Route, error) {
// GetAllRoutes gets all routes out of the database for a given user by username.
func (b *BoltDBStorage) GetAllRoutes(ctx context.Context, user string) ([]Route, error) {
rs := []Route{}
err := b.db.All(&rs)
return rs, err
@ -102,6 +120,22 @@ func (b *BoltDBStorage) GetToken(ctx context.Context, token string) (Token, erro
return t, err
}
// GetTokenID fetches a token by a given token ID.
func (b *BoltDBStorage) GetTokenID(ctx context.Context, id string) (Token, error) {
t := Token{}
err := b.db.One("ID", id, &t)
if err != nil {
switch err {
case storm.ErrNotFound:
return Token{}, ErrNoSuchToken
default:
return Token{}, err
}
}
return t, nil
}
// GetTokensForOwner fetches all of the tokens owned by a given owner.
func (b *BoltDBStorage) GetTokensForOwner(ctx context.Context, owner string) ([]Token, error) {
ts := []Token{}

View File

@ -1,105 +0,0 @@
package database
import (
"errors"
"log"
r "github.com/GoRethink/gorethink"
"github.com/brandur/simplebox"
"golang.org/x/crypto/acme/autocert"
"golang.org/x/net/context"
)
// CertCache extends DB to provide certificate management functions for
// https://godoc.org/golang.org/x/crypto/acme/autocert#Cache
type CertCache struct {
*DB
SimpleBox *simplebox.SimpleBox
}
// CryptoLevel indicates what form of cryptography the certificate is stored
// with.
type CryptoLevel int
// Crypto levels / strategies defined
const (
// NOTE: this is defined for debugging / testing usage only
CryptoLevelNone CryptoLevel = iota
// Use the global set of secretbox keys
CryptoLevelSecretbox
)
// CachedCert is an individual cached certificate in the database.
type CachedCert struct {
Key string `gorethink:"id" storm:"id"`
CryptoLevel CryptoLevel `gorethink:"cryptoLevel"`
// PEM-encoded bytes with the above crypto level as a filter.
Body []byte `gorethink:"body"`
}
// Get returns a certificate data for the specified key.
// If there's no such key, Get returns ErrCacheMiss.
func (c *CertCache) Get(ctx context.Context, key string) ([]byte, error) {
res, err := r.Table("certs").Get(key).Run(c.s)
if err != nil {
return nil, err
}
cert := &CachedCert{}
err = res.One(cert)
if err != nil {
log.Printf("decoding cached cert failed: %v", err)
return nil, autocert.ErrCacheMiss
}
var body []byte
switch cert.CryptoLevel {
case CryptoLevelNone:
body = cert.Body
case CryptoLevelSecretbox:
if c.SimpleBox == nil {
return nil, errors.New("can't read this cert, no key in memory")
}
body, err = c.SimpleBox.Decrypt(cert.Body)
if err != nil {
return nil, autocert.ErrCacheMiss
}
}
log.Printf("certcache: fetched: %s", key)
return body, nil
}
// Put stores the data in the cache under the specified key.
// Underlying implementations may use any data storage format,
// as long as the reverse operation, Get, results in the original data.
func (c *CertCache) Put(ctx context.Context, key string, data []byte) error {
cert := &CachedCert{
Key: key,
CryptoLevel: CryptoLevelNone,
Body: data,
}
if c.SimpleBox != nil {
cert.CryptoLevel = CryptoLevelSecretbox
cert.Body = c.SimpleBox.Encrypt(data)
}
log.Printf("certcache: added: %s", key)
_, err := r.Table("certs").Insert(cert).RunWrite(c.s)
return err
}
// Delete removes a certificate data from the cache under the specified key.
// If there's no such key in the cache, Delete returns nil.
func (c *CertCache) Delete(ctx context.Context, key string) error {
_, err := r.Table("certs").Get(key).Delete().Run(c.s)
log.Printf("certcache: deleted: %s", key)
return err
}

View File

@ -2,6 +2,7 @@ package database
import (
proto "git.xeserv.us/xena/route/proto"
"github.com/Xe/ln"
)
// Route is a single HTTP route.
@ -13,6 +14,15 @@ type Route struct {
Token string `gorethink:"token" storm:"-"` // deprecated
}
// F https://godoc.org/github.com/Xe/ln#F
func (r Route) F() ln.F {
return ln.F{
"route-id": r.ID,
"route-creator": r.Creator,
"route-hostname": r.Hostname,
}
}
// AsProto converts this into the protobuf.
func (r Route) AsProto() *proto.Route {
return &proto.Route{

View File

@ -15,6 +15,7 @@ type Storage interface {
// tokens
GetToken(ctx context.Context, token string) (Token, error)
GetTokenID(ctx context.Context, id string) (Token, error)
GetTokensForOwner(ctx context.Context, owner string) ([]Token, error)
PutToken(ctx context.Context, token, owner string, scopes []string) (Token, error)
DeleteToken(ctx context.Context, id string) error

View File

@ -1,6 +1,10 @@
package database
import "time"
import (
proto "git.xeserv.us/xena/route/proto"
"github.com/Xe/ln"
)
// Token is a single authorization token.
type Token struct {
@ -12,3 +16,22 @@ type Token struct {
CreatedAt time.Time `json:"created_at"`
Active bool `json:"active"`
}
// F https://godoc.org/github.com/Xe/ln#F
func (t Token) F() ln.F {
return ln.F{
"token-id": t.ID,
"token-owner": t.Owner,
"token-active": t.Active,
}
}
// AsProto ...
func (t Token) AsProto() *proto.Token {
return &proto.Token{
Id: t.ID,
Body: t.Body,
Scopes: t.Scopes,
Active: t.Active,
}
}

1
proto/client/.#client.go Symbolic link
View File

@ -0,0 +1 @@
xena@greedo.xeserv.us.17867:1486865539

2
proto/client/doc.go Normal file
View File

@ -0,0 +1,2 @@
// Package client is a higer level convenience wrapper around the RPC layer for route.
package client

View File

@ -396,7 +396,7 @@ var _Routes_serviceDesc = grpc.ServiceDesc{
type TokensClient interface {
Get(ctx context.Context, in *GetTokenRequest, opts ...grpc.CallOption) (*Token, error)
GetAll(ctx context.Context, in *Nil, opts ...grpc.CallOption) (*TokenSet, error)
Put(ctx context.Context, in *Token, opts ...grpc.CallOption) (*IDResponse, error)
Put(ctx context.Context, in *Token, opts ...grpc.CallOption) (*Token, error)
Delete(ctx context.Context, in *Token, opts ...grpc.CallOption) (*Nil, error)
Deactivate(ctx context.Context, in *Token, opts ...grpc.CallOption) (*Nil, error)
}
@ -427,8 +427,8 @@ func (c *tokensClient) GetAll(ctx context.Context, in *Nil, opts ...grpc.CallOpt
return out, nil
}
func (c *tokensClient) Put(ctx context.Context, in *Token, opts ...grpc.CallOption) (*IDResponse, error) {
out := new(IDResponse)
func (c *tokensClient) Put(ctx context.Context, in *Token, opts ...grpc.CallOption) (*Token, error) {
out := new(Token)
err := grpc.Invoke(ctx, "/route.Tokens/Put", in, out, c.cc, opts...)
if err != nil {
return nil, err
@ -459,7 +459,7 @@ func (c *tokensClient) Deactivate(ctx context.Context, in *Token, opts ...grpc.C
type TokensServer interface {
Get(context.Context, *GetTokenRequest) (*Token, error)
GetAll(context.Context, *Nil) (*TokenSet, error)
Put(context.Context, *Token) (*IDResponse, error)
Put(context.Context, *Token) (*Token, error)
Delete(context.Context, *Token) (*Nil, error)
Deactivate(context.Context, *Token) (*Nil, error)
}
@ -590,36 +590,36 @@ var _Tokens_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("route.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 484 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0x86, 0x15, 0x3b, 0x36, 0xed, 0xb4, 0x6a, 0xe9, 0x50, 0x82, 0x31, 0x45, 0x8a, 0x56, 0x20,
0x45, 0x3d, 0xd4, 0x10, 0x24, 0x10, 0x88, 0x0b, 0x22, 0x21, 0xe2, 0x52, 0x21, 0x97, 0x1b, 0x27,
0x37, 0x19, 0x15, 0x0b, 0xcb, 0x1b, 0xb2, 0x93, 0x4a, 0x08, 0x71, 0xe1, 0x15, 0x38, 0xf1, 0x3c,
0x3c, 0x02, 0xaf, 0xc0, 0x83, 0x20, 0xcf, 0x6e, 0x12, 0x27, 0x46, 0xe4, 0xb6, 0xb3, 0x3b, 0xff,
0xef, 0x7f, 0xbe, 0x89, 0x02, 0x7b, 0x33, 0x3d, 0x67, 0x3a, 0x9b, 0xce, 0x34, 0x6b, 0x0c, 0xa4,
0x88, 0x4f, 0xae, 0xb4, 0xbe, 0x2a, 0x28, 0xc9, 0xa6, 0x79, 0x92, 0x95, 0xa5, 0xe6, 0x8c, 0x73,
0x5d, 0x1a, 0xdb, 0xa4, 0x02, 0xf0, 0xcf, 0xf3, 0x42, 0x3d, 0x84, 0xc3, 0x11, 0x71, 0x5a, 0x09,
0x52, 0xfa, 0x3c, 0x27, 0xc3, 0x88, 0xd0, 0xfe, 0xa8, 0x0d, 0x47, 0xad, 0x6e, 0xab, 0xb7, 0x9b,
0xca, 0x59, 0x0d, 0x21, 0x90, 0x1e, 0x3c, 0x00, 0x2f, 0x9f, 0xb8, 0x27, 0x2f, 0x9f, 0x60, 0x04,
0x37, 0xc6, 0x33, 0xca, 0x58, 0xcf, 0x22, 0x4f, 0x2e, 0x17, 0xe5, 0xd2, 0xc6, 0xaf, 0xd9, 0xbc,
0x84, 0xe3, 0x11, 0xf1, 0xab, 0xa2, 0x10, 0x33, 0x93, 0x92, 0x99, 0xea, 0xd2, 0x10, 0x3e, 0x80,
0x50, 0x32, 0x9b, 0xa8, 0xd5, 0xf5, 0x7b, 0x7b, 0xfd, 0xfd, 0x33, 0x3b, 0x8f, 0xcd, 0xe5, 0xde,
0xd4, 0x09, 0xc0, 0xdb, 0xc1, 0x52, 0xb3, 0x91, 0x44, 0x7d, 0x80, 0xe0, 0xbd, 0xfe, 0x44, 0x65,
0x23, 0x22, 0x42, 0xfb, 0x52, 0x4f, 0xbe, 0xb8, 0x7c, 0x72, 0xc6, 0x0e, 0x84, 0x66, 0xac, 0xa7,
0x64, 0x22, 0xbf, 0xeb, 0xf7, 0x76, 0x53, 0x57, 0x55, 0xf7, 0xd9, 0x98, 0xf3, 0x6b, 0x8a, 0xda,
0xdd, 0x56, 0x6f, 0x27, 0x75, 0x95, 0x7a, 0x04, 0x3b, 0x62, 0x7e, 0x41, 0x5c, 0x85, 0xe5, 0xea,
0xbc, 0x19, 0x56, 0x1a, 0x52, 0xf7, 0xa6, 0x9e, 0x09, 0x58, 0x7b, 0xe7, 0xc0, 0x1e, 0x43, 0x20,
0x8f, 0x2e, 0x9b, 0x2d, 0x5c, 0x5c, 0x6f, 0x11, 0xb7, 0xff, 0xd3, 0x83, 0xd0, 0xe2, 0xc1, 0x37,
0xe0, 0x8f, 0x88, 0xb1, 0xe3, 0x3e, 0xb0, 0xb1, 0xa8, 0x78, 0x8d, 0x92, 0xba, 0xfb, 0xfd, 0xf7,
0x9f, 0x1f, 0xde, 0x2d, 0x3c, 0x4a, 0xae, 0x1f, 0x27, 0x96, 0x58, 0xf2, 0xb5, 0xa2, 0xfe, 0x0d,
0x87, 0x10, 0x5a, 0xec, 0x08, 0x4e, 0x72, 0x9e, 0x17, 0xf1, 0xbd, 0x95, 0x6d, 0x63, 0x23, 0x0a,
0xc5, 0x6d, 0x1f, 0x61, 0xe5, 0x86, 0x2f, 0xc0, 0x7f, 0x37, 0x67, 0x5c, 0xfb, 0x6c, 0x7c, 0xe4,
0xaa, 0xd5, 0x66, 0x16, 0x5a, 0x55, 0xd7, 0x0e, 0x20, 0x1c, 0x50, 0x41, 0x4c, 0xdb, 0xe5, 0x6e,
0x90, 0xd3, 0xe6, 0x20, 0xfd, 0x5f, 0x1e, 0x84, 0x82, 0xd4, 0xe0, 0xeb, 0x06, 0x9b, 0x3a, 0xeb,
0x78, 0x6d, 0x29, 0xaa, 0x23, 0x96, 0x37, 0xf1, 0xa0, 0xb2, 0xb4, 0x0b, 0x4a, 0x74, 0x49, 0xf8,
0xfc, 0x9f, 0x60, 0x0e, 0xeb, 0xda, 0x0b, 0xe2, 0x75, 0x18, 0x56, 0xbe, 0x09, 0x43, 0x7a, 0xb7,
0xc2, 0x70, 0xda, 0xa7, 0x0d, 0x18, 0x56, 0x5e, 0x0b, 0xb1, 0xd0, 0x9d, 0xd6, 0x75, 0x43, 0x80,
0x01, 0xc9, 0x2f, 0x32, 0xfb, 0xaf, 0xf6, 0xbe, 0x68, 0xef, 0xa8, 0xdb, 0xb5, 0x71, 0x27, 0x4b,
0xe1, 0x65, 0x28, 0xff, 0x00, 0x4f, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x47, 0x15, 0x47, 0xc2,
0x35, 0x04, 0x00, 0x00,
// 487 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x93, 0xcf, 0x6e, 0xd3, 0x40,
0x10, 0xc6, 0x15, 0x3b, 0x36, 0xed, 0xb4, 0x6a, 0xe9, 0x50, 0x82, 0x31, 0x45, 0x8a, 0x56, 0x20,
0x45, 0x3d, 0xd4, 0x10, 0x04, 0x08, 0xc4, 0x05, 0x91, 0x10, 0x71, 0xa9, 0x90, 0xcb, 0x8d, 0x93,
0x9b, 0x8c, 0x8a, 0x85, 0xe5, 0x0d, 0xde, 0x4d, 0x24, 0x84, 0xb8, 0xf0, 0x0a, 0x9c, 0x78, 0x19,
0x5e, 0x82, 0x57, 0xe0, 0x41, 0x90, 0x67, 0xd7, 0x89, 0xff, 0x20, 0xb8, 0xed, 0xec, 0xee, 0xf7,
0xed, 0x37, 0xbf, 0xb1, 0x61, 0xaf, 0x90, 0x2b, 0x4d, 0x67, 0xcb, 0x42, 0x6a, 0x89, 0x1e, 0x17,
0xe1, 0xc9, 0x95, 0x94, 0x57, 0x19, 0x45, 0xc9, 0x32, 0x8d, 0x92, 0x3c, 0x97, 0x3a, 0xd1, 0xa9,
0xcc, 0x95, 0xb9, 0x24, 0x3c, 0x70, 0xcf, 0xd3, 0x4c, 0xdc, 0x87, 0xc3, 0x19, 0xe9, 0xb8, 0x14,
0xc4, 0xf4, 0x69, 0x45, 0x4a, 0x23, 0x42, 0xff, 0x83, 0x54, 0x3a, 0xe8, 0x0d, 0x7b, 0xa3, 0xdd,
0x98, 0xd7, 0x62, 0x0a, 0x1e, 0xdf, 0xc1, 0x03, 0x70, 0xd2, 0x85, 0x3d, 0x72, 0xd2, 0x05, 0x06,
0x70, 0x6d, 0x5e, 0x50, 0xa2, 0x65, 0x11, 0x38, 0xbc, 0x59, 0x95, 0x1b, 0x1b, 0xb7, 0x66, 0xf3,
0x02, 0x8e, 0x67, 0xa4, 0x5f, 0x66, 0x19, 0x9b, 0xa9, 0x98, 0xd4, 0x52, 0xe6, 0x8a, 0xf0, 0x1e,
0xf8, 0x9c, 0x59, 0x05, 0xbd, 0xa1, 0x3b, 0xda, 0x1b, 0xef, 0x9f, 0x99, 0x7e, 0x4c, 0x2e, 0x7b,
0x26, 0x4e, 0x00, 0xde, 0x4c, 0x36, 0x9a, 0x56, 0x12, 0xf1, 0x1e, 0xbc, 0x77, 0xf2, 0x23, 0xe5,
0x9d, 0x88, 0x08, 0xfd, 0x4b, 0xb9, 0xf8, 0x6c, 0xf3, 0xf1, 0x1a, 0x07, 0xe0, 0xab, 0xb9, 0x5c,
0x92, 0x0a, 0xdc, 0xa1, 0x3b, 0xda, 0x8d, 0x6d, 0x55, 0xee, 0x27, 0x73, 0x9d, 0xae, 0x29, 0xe8,
0x0f, 0x7b, 0xa3, 0x9d, 0xd8, 0x56, 0xe2, 0x01, 0xec, 0xb0, 0xf9, 0x05, 0xe9, 0x32, 0xac, 0x2e,
0xd7, 0xed, 0xb0, 0x7c, 0x21, 0xb6, 0x67, 0xe2, 0x29, 0x83, 0x35, 0x7b, 0x16, 0xec, 0x31, 0x78,
0x7c, 0x68, 0xb3, 0x99, 0xc2, 0xc6, 0x75, 0xaa, 0xb8, 0xe3, 0x1f, 0x0e, 0xf8, 0x06, 0x0f, 0xbe,
0x06, 0x77, 0x46, 0x1a, 0x07, 0xf6, 0x81, 0xd6, 0xa0, 0xc2, 0x06, 0x25, 0x71, 0xfb, 0xdb, 0xaf,
0xdf, 0xdf, 0x9d, 0x1b, 0x78, 0x14, 0xad, 0x1f, 0x46, 0x86, 0x58, 0xf4, 0xa5, 0xa4, 0xfe, 0x15,
0xa7, 0xe0, 0x1b, 0xec, 0x08, 0x56, 0x72, 0x9e, 0x66, 0xe1, 0x9d, 0xad, 0x6d, 0x67, 0x22, 0x02,
0xd9, 0x6d, 0x1f, 0x61, 0xeb, 0x86, 0xcf, 0xc1, 0x7d, 0xbb, 0xd2, 0xd8, 0x78, 0x36, 0x3c, 0xb2,
0xd5, 0x76, 0x32, 0x95, 0x56, 0xd4, 0xb5, 0x13, 0xf0, 0x27, 0x94, 0x91, 0xa6, 0xff, 0xcb, 0x6d,
0x23, 0xa7, 0xdd, 0x46, 0xc6, 0x3f, 0x1d, 0xf0, 0x19, 0xa9, 0xc2, 0x57, 0x1d, 0x36, 0x75, 0xd6,
0x61, 0x63, 0x28, 0x62, 0xc0, 0x96, 0xd7, 0xf1, 0xa0, 0xb4, 0x34, 0x03, 0x8a, 0x64, 0x4e, 0xf8,
0xec, 0xaf, 0x60, 0x0e, 0xeb, 0xda, 0x0b, 0xd2, 0x4d, 0x18, 0x46, 0x8e, 0x8f, 0x9b, 0x30, 0xf8,
0x6e, 0xeb, 0xd5, 0x06, 0x07, 0x2b, 0x7b, 0xd2, 0xe1, 0x60, 0x94, 0xb5, 0xf7, 0x2b, 0xdd, 0x69,
0x5d, 0x37, 0x05, 0x98, 0x10, 0x7f, 0x8c, 0xc9, 0x3f, 0xb5, 0x77, 0x59, 0x7b, 0x4b, 0xdc, 0xac,
0x75, 0xba, 0xd8, 0x08, 0x2f, 0x7d, 0xfe, 0xf9, 0x1f, 0xfd, 0x09, 0x00, 0x00, 0xff, 0xff, 0xd3,
0x68, 0x6e, 0x4f, 0x30, 0x04, 0x00, 0x00,
}

View File

@ -65,7 +65,7 @@ service Tokens {
};
}
rpc Put(Token) returns (IDResponse) {
rpc Put(Token) returns (Token) {
option (google.api.http) = {
post: "/v1/tokens"
};

View File

@ -126,7 +126,7 @@
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/routeIDResponse"
"$ref": "#/definitions/routeToken"
}
}
},

55
server/common.go Normal file
View File

@ -0,0 +1,55 @@
package server
import (
"context"
"errors"
"git.xeserv.us/xena/route/database"
"github.com/Xe/ln"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
)
// errors
var (
ErrNotAuthorized = errors.New("server: not authorized")
)
func (s *Server) getAuth(ctx context.Context, scope string) (database.Token, error) {
var err error
md, ok := metadata.FromContext(ctx)
if !ok {
return "", grpc.Errorf(codes.Unauthenticated, "valid token required.")
}
jwtToken, ok := md["authorization"]
if !ok {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "valid token required.")
}
val := jwtToken[0]
t, err := s.db.GetToken(ctx, val)
if err != nil {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "valid token required.")
}
ok = false
for _, sc := range t.Scopes {
if sc == scope {
ok = true
}
}
if !ok {
return database.Token{}, grpc.Errorf(codes.Unauthenticated, "invalid scope.")
}
return t, nil
}
func handleError(ctx context.Context, clitok database.Token, err error, f ln.F) error {
ln.Error(err, f, clitok.F())
return err
}

91
server/route.go Normal file
View File

@ -0,0 +1,91 @@
package server
import (
proto "git.xeserv.us/xena/route/proto"
"github.com/Xe/ln"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
// Route implements rout.RoutesServer for gRPC
type Route struct {
*Server
}
// interface assertions
var (
_ proto.RoutesServer = &Route{}
)
// errors
var ()
// generic error message
const (
errorMsg = "internal service error, verify your parameters and try again later"
)
// Get fetches a route from the database.
func (r *Route) Get(ctx context.Context, req *proto.GetRouteRequest) (*proto.Route, error) {
val, err := r.db.GetRoute(ctx, req.Host)
if err != nil {
ln.Error(err, ln.F{"action": "Route.Get"})
return nil, err
}
return val.AsProto(), nil
}
// GetAll fetches all of the routes that you own.
func (r *Route) GetAll(ctx context.Context, req *proto.Nil) (*proto.GetAllRoutesResponse, error) {
routes, err := r.db.GetAllRoutes()
if err != nil {
ln.Error(err, ln.F{"action": "Route.GetAll"})
return nil, err
}
result := []*proto.Route{}
// let result = apply routeAsProto routes
for _, rt := range routes {
result = append(result, rt.AsProto())
}
return &proto.GetAllRoutesResponse{
Routes: result,
}, nil
}
func (r *Route) Put(ctx context.Context, rt *proto.Route) (*proto.IDResponse, error) {
drt, err := r.db.PutRoute(ctx, rt.Host, "http")
if err != nil {
ln.Error(err, ln.F{"action": "Route.Put"})
return nil, err
}
return &proto.IDResponse{
Id: drt.ID,
}
}
func (r *Route) Delete(ctx context.Context, rt *proto.Route) (*proto.IDResponse, error) {
drt, err := r.db.GetRoute(ctx, rt.Host)
if err != nil {
ln.Error(err, ln.F{"action": "Route.Delete_getRoute_verify"})
return nil, err
}
err := r.db.DeleteRoute(ctx, rt.Id)
f := drt.F()
f["action"] = "Route.Delete_db.DeleteRoute"
if err != nil {
ln.Error(err, f)
return nil, err
}
return &proto.IDResponse{Id: rt.Id}, nil
}

108
server/token.go Normal file
View File

@ -0,0 +1,108 @@
package server
import (
"context"
"github.com/Xe/ln"
"github.com/Xe/uuid"
proto "git.xeserv.us/xena/route/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// Token is the token server implementation for grpc use.
type Token struct {
*Server
}
// interface assertions
var (
_ proto.TokensServer = &Token{}
)
func (t *Token) Get(ctx context.Context, req *proto.GetTokenRequest) (*proto.Token, error) {
clitok, err := t.getAuth(ctx, "token:get")
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Get_getAuth"})
}
if req.Id == "" {
return nil, status.Errorf(codes.InvalidArgument, "must specify ID")
}
dbt, err := t.db.GetTokenID(ctx, req.Id)
if err != nil {
return nil, err
}
if dbt.Owner != clitok.Owner {
return nil, ErrNotAuthorized
}
return dbt.AsProto(), nil
}
func (t *Token) GetAll(ctx context.Context, req *proto.Nil) (*proto.TokenSet, error) {
clitok, err := t.getAuth(ctx, "token:getall")
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.GetAll_getAuth"})
}
toks, err := t.db.GetTokensForOwner(ctx, clitok.Owner)
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.GetAll_db.GetTokensForOwner"})
}
result := []*proto.Token{}
for _, tok := range toks {
result = append(result, tok.AsProto())
}
return &proto.TokenSet{
Tokens: result,
}, nil
}
func (t *Token) Put(ctx context.Context, tok *proto.Token) (*proto.Token, error) {
clitok, err := t.getAuth(ctx, "token:put")
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Put_getAuth"})
}
dbt, err := t.db.PutToken(ctx, uuid.New(), clitok.Owner, tok.Scopes)
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Put_db.PutToken"})
}
return dbt.AsProto(), nil
}
func (t *Token) Delete(ctx context.Context, tok *proto.Token) (*proto.Nil, error) {
clitok, err := t.getAuth(ctx, "token:delete")
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Delete_getAuth"})
}
err = t.db.DeleteToken(ctx, tok.Id)
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Delete_db.DeleteToken"})
}
return &proto.Nil{}, nil
}
func (t *Token) Deactivate(ctx context.Context, tok *proto.Token) (*proto.Nil, error) {
clitok, err := t.getAuth(ctx, "token:deactivate")
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Deactivate_getAuth"})
}
err = t.db.DeactivateToken(ctx, tok.Id)
if err != nil {
return nil, handleError(ctx, clitok, err, ln.F{"action": "Token.Deactivate_db.DeactivateToken"})
}
return &proto.Nil{}, nil
}

View File

@ -118,3 +118,8 @@ f6c17b524822278a87e3b3bd809fec33b51f5b46 github.com/emirpasic/gods/containers
f6c17b524822278a87e3b3bd809fec33b51f5b46 github.com/emirpasic/gods/trees
f6c17b524822278a87e3b3bd809fec33b51f5b46 github.com/emirpasic/gods/trees/redblacktree
f6c17b524822278a87e3b3bd809fec33b51f5b46 github.com/emirpasic/gods/utils
18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 github.com/golang/protobuf/proto
18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 github.com/golang/protobuf/ptypes/any
411e09b969b1170a9f0c467558eb4c4c110d9c77 google.golang.org/genproto/googleapis/rpc/status
0eb507a2ca07f13baf499f89d66cc566bf644643 (dirty) google.golang.org/grpc/codes
0eb507a2ca07f13baf499f89d66cc566bf644643 (dirty) google.golang.org/grpc/status

155
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go generated vendored Normal file
View File

@ -0,0 +1,155 @@
// Code generated by protoc-gen-go.
// source: github.com/golang/protobuf/ptypes/any/any.proto
// DO NOT EDIT!
/*
Package any is a generated protocol buffer package.
It is generated from these files:
github.com/golang/protobuf/ptypes/any/any.proto
It has these top-level messages:
Any
*/
package any
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// `Any` contains an arbitrary serialized protocol buffer message along with a
// URL that describes the type of the serialized message.
//
// Protobuf library provides support to pack/unpack Any values in the form
// of utility functions or additional generated methods of the Any type.
//
// Example 1: Pack and unpack a message in C++.
//
// Foo foo = ...;
// Any any;
// any.PackFrom(foo);
// ...
// if (any.UnpackTo(&foo)) {
// ...
// }
//
// Example 2: Pack and unpack a message in Java.
//
// Foo foo = ...;
// Any any = Any.pack(foo);
// ...
// if (any.is(Foo.class)) {
// foo = any.unpack(Foo.class);
// }
//
// Example 3: Pack and unpack a message in Python.
//
// foo = Foo(...)
// any = Any()
// any.Pack(foo)
// ...
// if any.Is(Foo.DESCRIPTOR):
// any.Unpack(foo)
// ...
//
// The pack methods provided by protobuf library will by default use
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
// methods only use the fully qualified type name after the last '/'
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
// name "y.z".
//
//
// JSON
// ====
// The JSON representation of an `Any` value uses the regular
// representation of the deserialized, embedded message, with an
// additional field `@type` which contains the type URL. Example:
//
// package google.profile;
// message Person {
// string first_name = 1;
// string last_name = 2;
// }
//
// {
// "@type": "type.googleapis.com/google.profile.Person",
// "firstName": <string>,
// "lastName": <string>
// }
//
// If the embedded message type is well-known and has a custom JSON
// representation, that representation will be embedded adding a field
// `value` which holds the custom JSON in addition to the `@type`
// field. Example (for message [google.protobuf.Duration][]):
//
// {
// "@type": "type.googleapis.com/google.protobuf.Duration",
// "value": "1.212s"
// }
//
type Any struct {
// A URL/resource name whose content describes the type of the
// serialized protocol buffer message.
//
// For URLs which use the scheme `http`, `https`, or no scheme, the
// following restrictions and interpretations apply:
//
// * If no scheme is provided, `https` is assumed.
// * The last segment of the URL's path must represent the fully
// qualified name of the type (as in `path/google.protobuf.Duration`).
// The name should be in a canonical form (e.g., leading "." is
// not accepted).
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the
// URL, or have them precompiled into a binary to avoid any
// lookup. Therefore, binary compatibility needs to be preserved
// on changes to types. (Use versioned type names to manage
// breaking changes.)
//
// Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics.
//
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
// Must be a valid serialized protocol buffer of the above specified type.
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (m *Any) Reset() { *m = Any{} }
func (m *Any) String() string { return proto.CompactTextString(m) }
func (*Any) ProtoMessage() {}
func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (*Any) XXX_WellKnownType() string { return "Any" }
func init() {
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
}
func init() { proto.RegisterFile("github.com/golang/protobuf/ptypes/any/any.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 187 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0xd7, 0x2f, 0x28,
0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x28, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xcc,
0xab, 0x04, 0x61, 0x3d, 0xb0, 0xb8, 0x10, 0x7f, 0x7a, 0x7e, 0x7e, 0x7a, 0x4e, 0xaa, 0x1e, 0x4c,
0x95, 0x92, 0x19, 0x17, 0xb3, 0x63, 0x5e, 0xa5, 0x90, 0x24, 0x17, 0x07, 0x48, 0x79, 0x7c, 0x69,
0x51, 0x8e, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x3b, 0x88, 0x1f, 0x5a, 0x94, 0x23, 0x24,
0xc2, 0xc5, 0x5a, 0x96, 0x98, 0x53, 0x9a, 0x2a, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x13, 0x04, 0xe1,
0x38, 0x15, 0x71, 0x09, 0x27, 0xe7, 0xe7, 0xea, 0xa1, 0x19, 0xe7, 0xc4, 0xe1, 0x98, 0x57, 0x19,
0x00, 0xe2, 0x04, 0x30, 0x46, 0xa9, 0x12, 0xe5, 0xb8, 0x05, 0x8c, 0x8c, 0x8b, 0x98, 0x98, 0xdd,
0x03, 0x9c, 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x4c, 0x0b, 0x80, 0xaa, 0xd2, 0x0b, 0x4f, 0xcd, 0xc9,
0xf1, 0xce, 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0xa9, 0x4e, 0x62, 0x03, 0x6b, 0x37, 0x06, 0x04, 0x00,
0x00, 0xff, 0xff, 0xc6, 0x4d, 0x03, 0x23, 0xf6, 0x00, 0x00, 0x00,
}

View File

@ -0,0 +1,144 @@
// Code generated by protoc-gen-go.
// source: google/rpc/status.proto
// DO NOT EDIT!
/*
Package status is a generated protocol buffer package.
It is generated from these files:
google/rpc/status.proto
It has these top-level messages:
Status
*/
package status
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/golang/protobuf/ptypes/any"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// The `Status` type defines a logical error model that is suitable for different
// programming environments, including REST APIs and RPC APIs. It is used by
// [gRPC](https://github.com/grpc). The error model is designed to be:
//
// - Simple to use and understand for most users
// - Flexible enough to meet unexpected needs
//
// # Overview
//
// The `Status` message contains three pieces of data: error code, error message,
// and error details. The error code should be an enum value of
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The
// error message should be a developer-facing English message that helps
// developers *understand* and *resolve* the error. If a localized user-facing
// error message is needed, put the localized message in the error details or
// localize it in the client. The optional error details may contain arbitrary
// information about the error. There is a predefined set of error detail types
// in the package `google.rpc` which can be used for common error conditions.
//
// # Language mapping
//
// The `Status` message is the logical representation of the error model, but it
// is not necessarily the actual wire format. When the `Status` message is
// exposed in different client libraries and different wire protocols, it can be
// mapped differently. For example, it will likely be mapped to some exceptions
// in Java, but more likely mapped to some error codes in C.
//
// # Other uses
//
// The error model and the `Status` message can be used in a variety of
// environments, either with or without APIs, to provide a
// consistent developer experience across different environments.
//
// Example uses of this error model include:
//
// - Partial errors. If a service needs to return partial errors to the client,
// it may embed the `Status` in the normal response to indicate the partial
// errors.
//
// - Workflow errors. A typical workflow has multiple steps. Each step may
// have a `Status` message for error reporting purpose.
//
// - Batch operations. If a client uses batch request and batch response, the
// `Status` message should be used directly inside batch response, one for
// each error sub-response.
//
// - Asynchronous operations. If an API call embeds asynchronous operation
// results in its response, the status of those operations should be
// represented directly using the `Status` message.
//
// - Logging. If some API errors are stored in logs, the message `Status` could
// be used directly after any stripping needed for security/privacy reasons.
type Status struct {
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
Code int32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"`
// A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
// A list of messages that carry the error details. There will be a
// common set of message types for APIs to use.
Details []*google_protobuf.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"`
}
func (m *Status) Reset() { *m = Status{} }
func (m *Status) String() string { return proto.CompactTextString(m) }
func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Status) GetCode() int32 {
if m != nil {
return m.Code
}
return 0
}
func (m *Status) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func (m *Status) GetDetails() []*google_protobuf.Any {
if m != nil {
return m.Details
}
return nil
}
func init() {
proto.RegisterType((*Status)(nil), "google.rpc.Status")
}
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0x38, 0x2e, 0xbe, 0xe4, 0xfc, 0x5c, 0x3d, 0x84, 0xa3, 0x9c,
0xb8, 0x21, 0xf6, 0x06, 0x80, 0x94, 0x07, 0x30, 0x46, 0x99, 0x43, 0xa5, 0xd2, 0xf3, 0x73, 0x12,
0xf3, 0xd2, 0xf5, 0xf2, 0x8b, 0xd2, 0xf5, 0xd3, 0x53, 0xf3, 0xc0, 0x86, 0xe9, 0x43, 0xa4, 0x12,
0x0b, 0x32, 0x8b, 0x91, 0xfc, 0x69, 0x0d, 0xa1, 0x16, 0x31, 0x31, 0x07, 0x05, 0x38, 0x27, 0xb1,
0x81, 0x55, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa4, 0x53, 0xf0, 0x7c, 0x10, 0x01, 0x00,
0x00,
}

145
vendor/google.golang.org/grpc/status/status.go generated vendored Normal file
View File

@ -0,0 +1,145 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Package status implements errors returned by gRPC. These errors are
// serialized and transmitted on the wire between server and client, and allow
// for additional data to be transmitted via the Details field in the status
// proto. gRPC service handlers should return an error created by this
// package, and gRPC clients should expect a corresponding error to be
// returned from the RPC call.
//
// This package upholds the invariants that a non-nil error may not
// contain an OK code, and an OK code must result in a nil error.
package status
import (
"fmt"
"github.com/golang/protobuf/proto"
spb "google.golang.org/genproto/googleapis/rpc/status"
"google.golang.org/grpc/codes"
)
// statusError is an alias of a status proto. It implements error and Status,
// and a nil statusError should never be returned by this package.
type statusError spb.Status
func (se *statusError) Error() string {
p := (*spb.Status)(se)
return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
}
func (se *statusError) status() *Status {
return &Status{s: (*spb.Status)(se)}
}
// Status represents an RPC status code, message, and details. It is immutable
// and should be created with New, Newf, or FromProto.
type Status struct {
s *spb.Status
}
// Code returns the status code contained in s.
func (s *Status) Code() codes.Code {
if s == nil || s.s == nil {
return codes.OK
}
return codes.Code(s.s.Code)
}
// Message returns the message contained in s.
func (s *Status) Message() string {
if s == nil || s.s == nil {
return ""
}
return s.s.Message
}
// Proto returns s's status as an spb.Status proto message.
func (s *Status) Proto() *spb.Status {
if s == nil {
return nil
}
return proto.Clone(s.s).(*spb.Status)
}
// Err returns an immutable error representing s; returns nil if s.Code() is
// OK.
func (s *Status) Err() error {
if s.Code() == codes.OK {
return nil
}
return (*statusError)(s.s)
}
// New returns a Status representing c and msg.
func New(c codes.Code, msg string) *Status {
return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
}
// Newf returns New(c, fmt.Sprintf(format, a...)).
func Newf(c codes.Code, format string, a ...interface{}) *Status {
return New(c, fmt.Sprintf(format, a...))
}
// Error returns an error representing c and msg. If c is OK, returns nil.
func Error(c codes.Code, msg string) error {
return New(c, msg).Err()
}
// Errorf returns Error(c, fmt.Sprintf(format, a...)).
func Errorf(c codes.Code, format string, a ...interface{}) error {
return Error(c, fmt.Sprintf(format, a...))
}
// ErrorProto returns an error representing s. If s.Code is OK, returns nil.
func ErrorProto(s *spb.Status) error {
return FromProto(s).Err()
}
// FromProto returns a Status representing s.
func FromProto(s *spb.Status) *Status {
return &Status{s: proto.Clone(s).(*spb.Status)}
}
// FromError returns a Status representing err if it was produced from this
// package, otherwise it returns nil, false.
func FromError(err error) (s *Status, ok bool) {
if err == nil {
return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true
}
if s, ok := err.(*statusError); ok {
return s.status(), true
}
return nil, false
}