remove old certcache
This commit is contained in:
parent
8fd83ff179
commit
6fc2e13e54
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllRoutes gets all routes out of the database.
|
||||
func (b *BoltDBStorage) GetAllRoutes(ctx context.Context) ([]Route, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// 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{}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
xena@greedo.xeserv.us.17867:1486865539
|
|
@ -0,0 +1,2 @@
|
|||
// Package client is a higer level convenience wrapper around the RPC layer for route.
|
||||
package client
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ service Tokens {
|
|||
};
|
||||
}
|
||||
|
||||
rpc Put(Token) returns (IDResponse) {
|
||||
rpc Put(Token) returns (Token) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/tokens"
|
||||
};
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/routeIDResponse"
|
||||
"$ref": "#/definitions/routeToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
144
vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
generated
vendored
Normal file
144
vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
generated
vendored
Normal 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,
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue