First iteration of selfpass gRPC backend, w/ credentials CRUD functional

This commit is contained in:
mitchell 2019-04-14 20:56:55 -07:00
commit 719a462048
15 changed files with 1610 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea
bin

21
Makefile Normal file
View File

@ -0,0 +1,21 @@
.PHONY: all build clean format test
build: clean format test
go build -o ./bin/server ./cmd/server/server.go
clean:
rm -rf ./bin
go mod tidy
dev: build
./bin/server --dev
format:
goimports -w -l .
gen-protoc:
protoc --go_out=plugins=grpc:. \
./credentials/protobuf/service.proto
test:
go test -cover ./...

90
cmd/server/server.go Normal file
View File

@ -0,0 +1,90 @@
package main
import (
"flag"
"io"
"net"
"os"
"os/signal"
"github.com/go-kit/kit/log"
"github.com/mitchell/selfpass/credentials/protobuf"
"github.com/mitchell/selfpass/credentials/repositories"
"github.com/mitchell/selfpass/credentials/service"
"github.com/mitchell/selfpass/credentials/transport"
"google.golang.org/grpc"
)
var logger log.Logger
func main() {
var (
stop = make(chan os.Signal)
dev = flag.Bool("dev", false, "enables dev mode logging")
port = flag.String("port", "8080", "specify the port to listen on")
tableName = flag.String(
"credential-table-name",
"selfpass-credential",
"specify the credential table name on AWS",
)
)
signal.Notify(stop, os.Interrupt)
flag.Parse()
logger = newLogger(os.Stdout, *dev)
var (
db = repositories.NewDynamoTable(*tableName)
svc = service.NewCredentials(db)
gsrv = transport.NewGRPCServer(svc, logger)
srv = grpc.NewServer()
)
protobuf.RegisterCredentialServiceServer(srv, gsrv)
addr := "0.0.0.0:" + *port
lis, err := net.Listen("tcp", addr)
check(err)
go func() {
logger.Log(
"message", "serving",
"address", addr,
"credentialTable", tableName,
"dev", dev,
)
check(srv.Serve(lis))
}()
<-stop
logger.Log("message", "gracefully stopping")
srv.GracefulStop()
}
func newLogger(writer io.Writer, dev bool) log.Logger {
var l log.Logger
writer = log.NewSyncWriter(writer)
if dev {
l = log.NewLogfmtLogger(writer)
} else {
l = log.NewJSONLogger(writer)
}
l = log.WithPrefix(l, "caller", log.DefaultCaller, "timestamp", log.DefaultTimestamp)
lfunc := log.LoggerFunc(func(in ...interface{}) error {
if err := l.Log(in...); err != nil {
panic(err.Error())
}
return nil
})
return lfunc
}
func check(err error) {
if err != nil {
logger.Log("error", err)
os.Exit(1)
}
}

View File

@ -0,0 +1,67 @@
package endpoints
import (
"context"
"github.com/go-kit/kit/endpoint"
"github.com/mitchell/selfpass/credentials/types"
)
// MakeGetAllMetadataEndpoint TODO
func MakeGetAllMetadataEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(GetAllMetadataRequest)
mdch, errch := svc.GetAllMetadata(ctx, r.SourceHost)
return MetadataStream{
Metadata: mdch,
Errors: errch,
}, nil
}
}
// MakeCreateEndpoint TODO
func MakeCreateEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(types.CredentialInput)
return svc.Create(ctx, r)
}
}
// MakeUpdateEndpoint TODO
func MakeUpdateEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(UpdateRequest)
return svc.Update(ctx, r.ID, r.Credential)
}
}
func MakeDeleteEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(IDRequest)
return nil, svc.Delete(ctx, r.ID)
}
}
// IDRequest TODO
type IDRequest struct {
ID string
}
// GetAllMetadataRequest TODO
type GetAllMetadataRequest struct {
SourceHost string
}
// MetadataStream TODO
type MetadataStream struct {
Metadata <-chan types.Metadata
Errors chan error
}
// UpdateRequest TODO
type UpdateRequest struct {
ID string
Credential types.CredentialInput
}

View File

@ -0,0 +1,751 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: credentials/protobuf/service.proto
package protobuf
import (
context "context"
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// 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.ProtoPackageIsVersion3 // please upgrade the proto package
type DeleteResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DeleteResponse) Reset() { *m = DeleteResponse{} }
func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
func (*DeleteResponse) ProtoMessage() {}
func (*DeleteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{0}
}
func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeleteResponse.Unmarshal(m, b)
}
func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic)
}
func (m *DeleteResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_DeleteResponse.Merge(m, src)
}
func (m *DeleteResponse) XXX_Size() int {
return xxx_messageInfo_DeleteResponse.Size(m)
}
func (m *DeleteResponse) XXX_DiscardUnknown() {
xxx_messageInfo_DeleteResponse.DiscardUnknown(m)
}
var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo
func (m *DeleteResponse) GetSuccess() bool {
if m != nil {
return m.Success
}
return false
}
type GetAllMetadataRequest struct {
SourceHost string `protobuf:"bytes,1,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetAllMetadataRequest) Reset() { *m = GetAllMetadataRequest{} }
func (m *GetAllMetadataRequest) String() string { return proto.CompactTextString(m) }
func (*GetAllMetadataRequest) ProtoMessage() {}
func (*GetAllMetadataRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{1}
}
func (m *GetAllMetadataRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetAllMetadataRequest.Unmarshal(m, b)
}
func (m *GetAllMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetAllMetadataRequest.Marshal(b, m, deterministic)
}
func (m *GetAllMetadataRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetAllMetadataRequest.Merge(m, src)
}
func (m *GetAllMetadataRequest) XXX_Size() int {
return xxx_messageInfo_GetAllMetadataRequest.Size(m)
}
func (m *GetAllMetadataRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetAllMetadataRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetAllMetadataRequest proto.InternalMessageInfo
func (m *GetAllMetadataRequest) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
type IdRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *IdRequest) Reset() { *m = IdRequest{} }
func (m *IdRequest) String() string { return proto.CompactTextString(m) }
func (*IdRequest) ProtoMessage() {}
func (*IdRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{2}
}
func (m *IdRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_IdRequest.Unmarshal(m, b)
}
func (m *IdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_IdRequest.Marshal(b, m, deterministic)
}
func (m *IdRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_IdRequest.Merge(m, src)
}
func (m *IdRequest) XXX_Size() int {
return xxx_messageInfo_IdRequest.Size(m)
}
func (m *IdRequest) XXX_DiscardUnknown() {
xxx_messageInfo_IdRequest.DiscardUnknown(m)
}
var xxx_messageInfo_IdRequest proto.InternalMessageInfo
func (m *IdRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
type UpdateRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Credential *CredentialRequest `protobuf:"bytes,2,opt,name=credential,proto3" json:"credential,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
func (m *UpdateRequest) String() string { return proto.CompactTextString(m) }
func (*UpdateRequest) ProtoMessage() {}
func (*UpdateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{3}
}
func (m *UpdateRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UpdateRequest.Unmarshal(m, b)
}
func (m *UpdateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UpdateRequest.Marshal(b, m, deterministic)
}
func (m *UpdateRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_UpdateRequest.Merge(m, src)
}
func (m *UpdateRequest) XXX_Size() int {
return xxx_messageInfo_UpdateRequest.Size(m)
}
func (m *UpdateRequest) XXX_DiscardUnknown() {
xxx_messageInfo_UpdateRequest.DiscardUnknown(m)
}
var xxx_messageInfo_UpdateRequest proto.InternalMessageInfo
func (m *UpdateRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *UpdateRequest) GetCredential() *CredentialRequest {
if m != nil {
return m.Credential
}
return nil
}
type Metadata struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
CreatedAt *timestamp.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt *timestamp.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
Primary string `protobuf:"bytes,4,opt,name=primary,proto3" json:"primary,omitempty"`
SourceHost string `protobuf:"bytes,5,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
LoginUrl string `protobuf:"bytes,6,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Metadata) Reset() { *m = Metadata{} }
func (m *Metadata) String() string { return proto.CompactTextString(m) }
func (*Metadata) ProtoMessage() {}
func (*Metadata) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{4}
}
func (m *Metadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Metadata.Unmarshal(m, b)
}
func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
}
func (m *Metadata) XXX_Merge(src proto.Message) {
xxx_messageInfo_Metadata.Merge(m, src)
}
func (m *Metadata) XXX_Size() int {
return xxx_messageInfo_Metadata.Size(m)
}
func (m *Metadata) XXX_DiscardUnknown() {
xxx_messageInfo_Metadata.DiscardUnknown(m)
}
var xxx_messageInfo_Metadata proto.InternalMessageInfo
func (m *Metadata) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Metadata) GetCreatedAt() *timestamp.Timestamp {
if m != nil {
return m.CreatedAt
}
return nil
}
func (m *Metadata) GetUpdatedAt() *timestamp.Timestamp {
if m != nil {
return m.UpdatedAt
}
return nil
}
func (m *Metadata) GetPrimary() string {
if m != nil {
return m.Primary
}
return ""
}
func (m *Metadata) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
func (m *Metadata) GetLoginUrl() string {
if m != nil {
return m.LoginUrl
}
return ""
}
type Credential struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
CreatedAt *timestamp.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt *timestamp.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
Primary string `protobuf:"bytes,4,opt,name=primary,proto3" json:"primary,omitempty"`
Username string `protobuf:"bytes,5,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,6,opt,name=email,proto3" json:"email,omitempty"`
Password string `protobuf:"bytes,7,opt,name=password,proto3" json:"password,omitempty"`
SourceHost string `protobuf:"bytes,8,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
LoginUrl string `protobuf:"bytes,9,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Credential) Reset() { *m = Credential{} }
func (m *Credential) String() string { return proto.CompactTextString(m) }
func (*Credential) ProtoMessage() {}
func (*Credential) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{5}
}
func (m *Credential) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Credential.Unmarshal(m, b)
}
func (m *Credential) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Credential.Marshal(b, m, deterministic)
}
func (m *Credential) XXX_Merge(src proto.Message) {
xxx_messageInfo_Credential.Merge(m, src)
}
func (m *Credential) XXX_Size() int {
return xxx_messageInfo_Credential.Size(m)
}
func (m *Credential) XXX_DiscardUnknown() {
xxx_messageInfo_Credential.DiscardUnknown(m)
}
var xxx_messageInfo_Credential proto.InternalMessageInfo
func (m *Credential) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Credential) GetCreatedAt() *timestamp.Timestamp {
if m != nil {
return m.CreatedAt
}
return nil
}
func (m *Credential) GetUpdatedAt() *timestamp.Timestamp {
if m != nil {
return m.UpdatedAt
}
return nil
}
func (m *Credential) GetPrimary() string {
if m != nil {
return m.Primary
}
return ""
}
func (m *Credential) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *Credential) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *Credential) GetPassword() string {
if m != nil {
return m.Password
}
return ""
}
func (m *Credential) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
func (m *Credential) GetLoginUrl() string {
if m != nil {
return m.LoginUrl
}
return ""
}
type CredentialRequest struct {
Primary string `protobuf:"bytes,1,opt,name=primary,proto3" json:"primary,omitempty"`
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
SourceHost string `protobuf:"bytes,5,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
LoginUrl string `protobuf:"bytes,6,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CredentialRequest) Reset() { *m = CredentialRequest{} }
func (m *CredentialRequest) String() string { return proto.CompactTextString(m) }
func (*CredentialRequest) ProtoMessage() {}
func (*CredentialRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{6}
}
func (m *CredentialRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CredentialRequest.Unmarshal(m, b)
}
func (m *CredentialRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CredentialRequest.Marshal(b, m, deterministic)
}
func (m *CredentialRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CredentialRequest.Merge(m, src)
}
func (m *CredentialRequest) XXX_Size() int {
return xxx_messageInfo_CredentialRequest.Size(m)
}
func (m *CredentialRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CredentialRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CredentialRequest proto.InternalMessageInfo
func (m *CredentialRequest) GetPrimary() string {
if m != nil {
return m.Primary
}
return ""
}
func (m *CredentialRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *CredentialRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *CredentialRequest) GetPassword() string {
if m != nil {
return m.Password
}
return ""
}
func (m *CredentialRequest) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
func (m *CredentialRequest) GetLoginUrl() string {
if m != nil {
return m.LoginUrl
}
return ""
}
func init() {
proto.RegisterType((*DeleteResponse)(nil), "selfpass.credentials.DeleteResponse")
proto.RegisterType((*GetAllMetadataRequest)(nil), "selfpass.credentials.GetAllMetadataRequest")
proto.RegisterType((*IdRequest)(nil), "selfpass.credentials.IdRequest")
proto.RegisterType((*UpdateRequest)(nil), "selfpass.credentials.UpdateRequest")
proto.RegisterType((*Metadata)(nil), "selfpass.credentials.Metadata")
proto.RegisterType((*Credential)(nil), "selfpass.credentials.Credential")
proto.RegisterType((*CredentialRequest)(nil), "selfpass.credentials.CredentialRequest")
}
func init() { proto.RegisterFile("credentials/protobuf/service.proto", fileDescriptor_ad34efc7bbd96e69) }
var fileDescriptor_ad34efc7bbd96e69 = []byte{
// 493 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0x5d, 0x6b, 0xd4, 0x40,
0x14, 0x25, 0xd9, 0x76, 0x9b, 0xdc, 0xe2, 0x82, 0x43, 0x85, 0x90, 0x82, 0xbb, 0x44, 0xc1, 0xa2,
0x90, 0x4a, 0x7d, 0xd1, 0xc7, 0xb5, 0xc2, 0xd6, 0x07, 0x11, 0x52, 0xfb, 0xe2, 0xcb, 0x32, 0x4d,
0x6e, 0xb7, 0x81, 0xc9, 0x4e, 0x9c, 0x99, 0x28, 0xfe, 0x30, 0x41, 0xff, 0x91, 0x3f, 0x43, 0x32,
0xc9, 0xec, 0x47, 0x3a, 0xdb, 0x5d, 0xdf, 0xfa, 0x96, 0x3b, 0x39, 0x67, 0xe6, 0xdc, 0x33, 0x73,
0x2e, 0x44, 0xa9, 0xc0, 0x0c, 0xe7, 0x2a, 0xa7, 0x4c, 0x9e, 0x96, 0x82, 0x2b, 0x7e, 0x5d, 0xdd,
0x9c, 0x4a, 0x14, 0xdf, 0xf3, 0x14, 0x63, 0xbd, 0x40, 0x8e, 0x24, 0xb2, 0x9b, 0x92, 0x4a, 0x19,
0xaf, 0x80, 0xc3, 0xe1, 0x8c, 0xf3, 0x19, 0xc3, 0x25, 0x49, 0xe5, 0x05, 0x4a, 0x45, 0x8b, 0xb2,
0xa1, 0x45, 0x2f, 0x61, 0xf0, 0x01, 0x19, 0x2a, 0x4c, 0x50, 0x96, 0x7c, 0x2e, 0x91, 0x04, 0x70,
0x20, 0xab, 0x34, 0x45, 0x29, 0x03, 0x67, 0xe4, 0x9c, 0x78, 0x89, 0x29, 0xa3, 0xb7, 0xf0, 0x64,
0x82, 0x6a, 0xcc, 0xd8, 0x27, 0x54, 0x34, 0xa3, 0x8a, 0x26, 0xf8, 0xad, 0x42, 0xa9, 0xc8, 0x10,
0x0e, 0x25, 0xaf, 0x44, 0x8a, 0xd3, 0x5b, 0x2e, 0x95, 0xa6, 0xf9, 0x09, 0x34, 0x4b, 0x17, 0x5c,
0xaa, 0xe8, 0x18, 0xfc, 0x8f, 0x99, 0x41, 0x0f, 0xc0, 0xcd, 0xb3, 0x16, 0xe4, 0xe6, 0x59, 0x74,
0x0b, 0x8f, 0xae, 0xca, 0x8c, 0xd6, 0x12, 0xac, 0x00, 0x32, 0x01, 0x58, 0xf6, 0x14, 0xb8, 0x23,
0xe7, 0xe4, 0xf0, 0xec, 0x45, 0x6c, 0xeb, 0x37, 0x3e, 0x5f, 0x7c, 0xb7, 0x9b, 0x25, 0x2b, 0xd4,
0xe8, 0xaf, 0x03, 0x9e, 0xd1, 0x7e, 0xe7, 0x94, 0x77, 0xfa, 0x14, 0xaa, 0x30, 0x9b, 0x52, 0xd5,
0x9e, 0x12, 0xc6, 0x8d, 0x7f, 0xb1, 0xf1, 0x2f, 0xfe, 0x62, 0xfc, 0x4b, 0xfc, 0x16, 0x3d, 0x56,
0x35, 0xb5, 0xd2, 0x1d, 0x68, 0x6a, 0x6f, 0x3b, 0xb5, 0x45, 0x8f, 0x55, 0xed, 0x76, 0x29, 0xf2,
0x82, 0x8a, 0x9f, 0xc1, 0x9e, 0x96, 0x62, 0xca, 0xae, 0xa9, 0xfb, 0x5d, 0x53, 0xc9, 0x31, 0xf8,
0x8c, 0xcf, 0xf2, 0xf9, 0xb4, 0x12, 0x2c, 0xe8, 0xeb, 0xdf, 0x9e, 0x5e, 0xb8, 0x12, 0x2c, 0xfa,
0xed, 0x02, 0x2c, 0xcd, 0x78, 0xf0, 0xcd, 0x86, 0xe0, 0x55, 0x12, 0xc5, 0x9c, 0x16, 0xd8, 0x76,
0xba, 0xa8, 0xc9, 0x11, 0xec, 0x63, 0x41, 0x73, 0xd3, 0x63, 0x53, 0xd4, 0x8c, 0xfa, 0xf6, 0x7f,
0x70, 0x91, 0x05, 0x07, 0x0d, 0xc3, 0xd4, 0x5d, 0xeb, 0xbc, 0xfb, 0xad, 0xf3, 0x3b, 0xd6, 0xfd,
0x71, 0xe0, 0xf1, 0x9d, 0x77, 0xb4, 0xaa, 0xdd, 0xd9, 0xac, 0xdd, 0xdd, 0xa4, 0xbd, 0xb7, 0x49,
0xfb, 0xde, 0xfd, 0xda, 0xff, 0xef, 0xda, 0xcf, 0x7e, 0xf5, 0x56, 0xb5, 0x5f, 0x36, 0x13, 0x82,
0x4c, 0x61, 0xb0, 0x1e, 0x5c, 0xf2, 0xca, 0x1e, 0x1f, 0x6b, 0xbc, 0xc3, 0xa7, 0x76, 0xb0, 0x81,
0xbd, 0x76, 0xc8, 0x05, 0xf4, 0x26, 0xa8, 0xc8, 0xd0, 0x0e, 0x5c, 0x44, 0x3f, 0x1c, 0x6d, 0x4b,
0x2d, 0xb9, 0x84, 0xfe, 0xb9, 0x7e, 0x6a, 0x64, 0xd7, 0x84, 0xef, 0xb0, 0xe9, 0x67, 0xe8, 0x37,
0x13, 0x86, 0x3c, 0xb3, 0x63, 0xd7, 0xe6, 0xcf, 0x6e, 0x1b, 0x36, 0x53, 0x73, 0x7b, 0xcb, 0xcf,
0xed, 0x80, 0xf5, 0xa1, 0xfb, 0x1e, 0xbe, 0x7a, 0x26, 0x3a, 0xd7, 0x7d, 0xfd, 0xf5, 0xe6, 0x5f,
0x00, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xb2, 0x15, 0xd8, 0xf6, 0x05, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// CredentialServiceClient is the client API for CredentialService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CredentialServiceClient interface {
GetAllMetadata(ctx context.Context, in *GetAllMetadataRequest, opts ...grpc.CallOption) (CredentialService_GetAllMetadataClient, error)
Get(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*Credential, error)
Create(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*Credential, error)
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Credential, error)
Delete(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
}
type credentialServiceClient struct {
cc *grpc.ClientConn
}
func NewCredentialServiceClient(cc *grpc.ClientConn) CredentialServiceClient {
return &credentialServiceClient{cc}
}
func (c *credentialServiceClient) GetAllMetadata(ctx context.Context, in *GetAllMetadataRequest, opts ...grpc.CallOption) (CredentialService_GetAllMetadataClient, error) {
stream, err := c.cc.NewStream(ctx, &_CredentialService_serviceDesc.Streams[0], "/selfpass.credentials.CredentialService/GetAllMetadata", opts...)
if err != nil {
return nil, err
}
x := &credentialServiceGetAllMetadataClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type CredentialService_GetAllMetadataClient interface {
Recv() (*Metadata, error)
grpc.ClientStream
}
type credentialServiceGetAllMetadataClient struct {
grpc.ClientStream
}
func (x *credentialServiceGetAllMetadataClient) Recv() (*Metadata, error) {
m := new(Metadata)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *credentialServiceClient) Get(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*Credential, error) {
out := new(Credential)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Get", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *credentialServiceClient) Create(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*Credential, error) {
out := new(Credential)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Create", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *credentialServiceClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Credential, error) {
out := new(Credential)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Update", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *credentialServiceClient) Delete(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
out := new(DeleteResponse)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Delete", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CredentialServiceServer is the server API for CredentialService service.
type CredentialServiceServer interface {
GetAllMetadata(*GetAllMetadataRequest, CredentialService_GetAllMetadataServer) error
Get(context.Context, *IdRequest) (*Credential, error)
Create(context.Context, *CredentialRequest) (*Credential, error)
Update(context.Context, *UpdateRequest) (*Credential, error)
Delete(context.Context, *IdRequest) (*DeleteResponse, error)
}
// UnimplementedCredentialServiceServer can be embedded to have forward compatible implementations.
type UnimplementedCredentialServiceServer struct {
}
func (*UnimplementedCredentialServiceServer) GetAllMetadata(req *GetAllMetadataRequest, srv CredentialService_GetAllMetadataServer) error {
return status.Errorf(codes.Unimplemented, "method GetAllMetadata not implemented")
}
func (*UnimplementedCredentialServiceServer) Get(ctx context.Context, req *IdRequest) (*Credential, error) {
return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
func (*UnimplementedCredentialServiceServer) Create(ctx context.Context, req *CredentialRequest) (*Credential, error) {
return nil, status.Errorf(codes.Unimplemented, "method Create not implemented")
}
func (*UnimplementedCredentialServiceServer) Update(ctx context.Context, req *UpdateRequest) (*Credential, error) {
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
}
func (*UnimplementedCredentialServiceServer) Delete(ctx context.Context, req *IdRequest) (*DeleteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
}
func RegisterCredentialServiceServer(s *grpc.Server, srv CredentialServiceServer) {
s.RegisterService(&_CredentialService_serviceDesc, srv)
}
func _CredentialService_GetAllMetadata_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetAllMetadataRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(CredentialServiceServer).GetAllMetadata(m, &credentialServiceGetAllMetadataServer{stream})
}
type CredentialService_GetAllMetadataServer interface {
Send(*Metadata) error
grpc.ServerStream
}
type credentialServiceGetAllMetadataServer struct {
grpc.ServerStream
}
func (x *credentialServiceGetAllMetadataServer) Send(m *Metadata) error {
return x.ServerStream.SendMsg(m)
}
func _CredentialService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Get(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Get",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Get(ctx, req.(*IdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CredentialRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Create(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Create",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Create(ctx, req.(*CredentialRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Update(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Update(ctx, req.(*UpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Delete(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Delete",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Delete(ctx, req.(*IdRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CredentialService_serviceDesc = grpc.ServiceDesc{
ServiceName: "selfpass.credentials.CredentialService",
HandlerType: (*CredentialServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Get",
Handler: _CredentialService_Get_Handler,
},
{
MethodName: "Create",
Handler: _CredentialService_Create_Handler,
},
{
MethodName: "Update",
Handler: _CredentialService_Update_Handler,
},
{
MethodName: "Delete",
Handler: _CredentialService_Delete_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "GetAllMetadata",
Handler: _CredentialService_GetAllMetadata_Handler,
ServerStreams: true,
},
},
Metadata: "credentials/protobuf/service.proto",
}

View File

@ -0,0 +1,62 @@
syntax = "proto3";
package selfpass.credentials;
option go_package = "protobuf";
import "google/protobuf/timestamp.proto";
service CredentialService {
rpc GetAllMetadata (GetAllMetadataRequest) returns (stream Metadata);
rpc Get (IdRequest) returns (Credential);
rpc Create (CredentialRequest) returns (Credential);
rpc Update (UpdateRequest) returns (Credential);
rpc Delete (IdRequest) returns (DeleteResponse);
}
message DeleteResponse {
bool success = 1;
}
message GetAllMetadataRequest {
string source_host = 1;
}
message IdRequest {
string id = 1;
}
message UpdateRequest {
string id = 1;
CredentialRequest credential = 2;
}
message Metadata {
string id = 1;
google.protobuf.Timestamp created_at = 2;
google.protobuf.Timestamp updated_at = 3;
string primary = 4;
string source_host = 5;
string login_url = 6;
}
message Credential {
string id = 1;
google.protobuf.Timestamp created_at = 2;
google.protobuf.Timestamp updated_at = 3;
string primary = 4;
string username = 5;
string email = 6;
string password = 7;
string source_host = 8;
string login_url = 9;
}
message CredentialRequest {
string primary = 1;
string username = 2;
string email = 3;
string password = 4;
string source_host = 5;
string login_url = 6;
}

View File

@ -0,0 +1,118 @@
package repositories
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws/external"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/dynamodbattribute"
"github.com/mitchell/selfpass/credentials/types"
)
// NewDynamoTable TODO
func NewDynamoTable(name string) DynamoTable {
cfg, err := external.LoadDefaultAWSConfig()
if err != nil {
panic(err.Error())
}
return DynamoTable{
name: name,
svc: dynamodb.New(cfg),
}
}
// DynamoTable TODO
type DynamoTable struct {
name string
svc *dynamodb.DynamoDB
}
// GetAllMetadata TODO
func (t DynamoTable) GetAllMetadata(ctx context.Context, sourceService string, errch chan<- error) (output <-chan types.Metadata) {
mdch := make(chan types.Metadata, 1)
in := &dynamodb.ScanInput{TableName: &t.name}
if sourceService != "" {
filterExpr := "SourceHost = :sh"
in.FilterExpression = &filterExpr
in.ExpressionAttributeValues = map[string]dynamodb.AttributeValue{
":sh": {S: &sourceService},
}
}
req := t.svc.ScanRequest(in)
go func() {
defer close(mdch)
pgr := req.Paginate()
for pgr.Next() {
mds := []types.Metadata{}
out := pgr.CurrentPage()
if err := dynamodbattribute.UnmarshalListOfMaps(out.Items, &mds); err != nil {
errch <- err
return
}
for _, md := range mds {
mdch <- md
}
}
if err := pgr.Err(); err != nil {
errch <- err
return
}
}()
return mdch
}
// Get TODO
func (t DynamoTable) Get(ctx context.Context, id string) (output types.Credential, err error) {
req := t.svc.GetItemRequest(&dynamodb.GetItemInput{
TableName: &t.name,
Key: map[string]dynamodb.AttributeValue{
"ID": {S: &id},
},
})
out, err := req.Send()
if err != nil {
return output, err
}
err = dynamodbattribute.UnmarshalMap(out.Item, &output)
return output, err
}
// Put TODO
func (t DynamoTable) Put(ctx context.Context, c types.Credential) (err error) {
item, err := dynamodbattribute.MarshalMap(c)
if err != nil {
return err
}
req := t.svc.PutItemRequest(&dynamodb.PutItemInput{
TableName: &t.name,
Item: item,
})
req.SetContext(ctx)
_, err = req.Send()
return err
}
// Delete TODO
func (t DynamoTable) Delete(ctx context.Context, id string) (err error) {
req := t.svc.DeleteItemRequest(&dynamodb.DeleteItemInput{
TableName: &t.name,
Key: map[string]dynamodb.AttributeValue{
"ID": {S: &id},
},
})
_, err = req.Send()
return err
}

View File

@ -0,0 +1,84 @@
package service
import (
"context"
"time"
"github.com/google/uuid"
"github.com/mitchell/selfpass/credentials/types"
)
// NewCredentials TODO
func NewCredentials(repo types.CredentialRepo) Credentials {
return Credentials{
repo: repo,
}
}
// Credentials TODO
type Credentials struct {
repo types.CredentialRepo
}
// GetAllMetadata TODO
func (svc Credentials) GetAllMetadata(ctx context.Context, sourceService string) (output <-chan types.Metadata, errch chan error) {
errch = make(chan error, 1)
output = svc.repo.GetAllMetadata(ctx, sourceService, errch)
return output, errch
}
// Get TODO
func (svc Credentials) Get(ctx context.Context, id string) (output types.Credential, err error) {
return svc.repo.Get(nil, id)
}
// Create TODO
func (svc Credentials) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
if err = validateCreate(ci); err != nil {
return output, err
}
var c types.Credential
c.ID = "cred-" + uuid.New().String()
c.CreatedAt = time.Now()
c.UpdatedAt = time.Now()
c.Primary = ci.Primary
c.LoginURL = ci.LoginURL
c.SourceHost = ci.SourceHost
c.Username = ci.Username
c.Email = ci.Email
c.Password = ci.Password
err = svc.repo.Put(ctx, c)
return c, err
}
func validateCreate(c types.CredentialInput) (err error) {
return err
}
// Update TODO
func (svc Credentials) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
c, err := svc.repo.Get(ctx, id)
if err != nil {
return output, err
}
c.UpdatedAt = time.Now()
c.Primary = ci.Primary
c.LoginURL = ci.LoginURL
c.SourceHost = ci.SourceHost
c.Password = ci.Password
c.Email = ci.Email
c.Username = ci.Username
return c, svc.repo.Put(ctx, c)
}
// Delete TODO
func (svc Credentials) Delete(ctx context.Context, id string) (err error) {
return svc.repo.Delete(nil, id)
}

View File

@ -0,0 +1,127 @@
package transport
import (
"context"
"github.com/golang/protobuf/ptypes"
"github.com/mitchell/selfpass/credentials/endpoints"
"github.com/mitchell/selfpass/credentials/protobuf"
"github.com/mitchell/selfpass/credentials/types"
)
func decodeGetAllMetadataRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.GetAllMetadataRequest)
return endpoints.GetAllMetadataRequest{
SourceHost: r.SourceHost,
}, nil
}
func encodeMetadataStreamResponse(ctx context.Context, response interface{}) (interface{}, error) {
r := response.(endpoints.MetadataStream)
pbmdch := make(chan protobuf.Metadata, 1)
go func() {
defer close(pbmdch)
for md := range r.Metadata {
createdAt, err := ptypes.TimestampProto(md.CreatedAt)
if err != nil {
r.Errors <- err
return
}
updatedAt, err := ptypes.TimestampProto(md.UpdatedAt)
if err != nil {
r.Errors <- err
return
}
pbmdch <- protobuf.Metadata{
Id: md.ID,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
SourceHost: md.SourceHost,
Primary: md.Primary,
LoginUrl: md.LoginURL,
}
}
}()
return protobufMetadataStream{
Metadata: pbmdch,
Errors: r.Errors,
}, nil
}
type protobufMetadataStream struct {
Metadata <-chan protobuf.Metadata
Errors chan error
}
func decodeCredentialRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.CredentialRequest)
return types.CredentialInput{
MetadataInput: types.MetadataInput{
Primary: r.Primary,
LoginURL: r.LoginUrl,
SourceHost: r.SourceHost,
},
Username: r.Username,
Email: r.Email,
Password: r.Password,
}, nil
}
func encodeCredentialResponse(ctx context.Context, response interface{}) (interface{}, error) {
r := response.(types.Credential)
createdAt, err := ptypes.TimestampProto(r.CreatedAt)
if err != nil {
return nil, err
}
updatedAt, err := ptypes.TimestampProto(r.UpdatedAt)
if err != nil {
return nil, err
}
return protobuf.Credential{
Id: r.ID,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
Primary: r.Primary,
SourceHost: r.SourceHost,
LoginUrl: r.LoginURL,
Username: r.Username,
Email: r.Email,
Password: r.Password,
}, nil
}
func decodeUpdateRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.UpdateRequest)
return endpoints.UpdateRequest{
ID: r.Id,
Credential: types.CredentialInput{
MetadataInput: types.MetadataInput{
Primary: r.Credential.Primary,
SourceHost: r.Credential.SourceHost,
LoginURL: r.Credential.LoginUrl,
},
Username: r.Credential.Username,
Email: r.Credential.Email,
Password: r.Credential.Password,
},
}, nil
}
func decodeIdRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.IdRequest)
return endpoints.IDRequest{
ID: r.Id,
}, nil
}
func noOpEncode(ctx context.Context, request interface{}) (interface{}, error) {
return nil, nil
}

View File

@ -0,0 +1,146 @@
package transport
import (
"context"
"fmt"
"strings"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/mitchell/selfpass/credentials/endpoints"
"github.com/mitchell/selfpass/credentials/protobuf"
"github.com/mitchell/selfpass/credentials/types"
)
// NewGRPCServer TODO
func NewGRPCServer(svc types.Service, logger log.Logger) GRPCServer {
return GRPCServer{
getAllMetadata: grpc.NewServer(
endpoints.MakeGetAllMetadataEndpoint(svc),
decodeGetAllMetadataRequest,
encodeMetadataStreamResponse,
grpc.ServerErrorLogger(logger),
),
create: grpc.NewServer(
endpoints.MakeCreateEndpoint(svc),
decodeCredentialRequest,
encodeCredentialResponse,
grpc.ServerErrorLogger(logger),
),
update: grpc.NewServer(
endpoints.MakeUpdateEndpoint(svc),
decodeUpdateRequest,
encodeCredentialResponse,
grpc.ServerErrorLogger(logger),
),
delete: grpc.NewServer(
endpoints.MakeDeleteEndpoint(svc),
decodeIdRequest,
noOpEncode,
grpc.ServerErrorLogger(logger),
),
}
}
// GRPCServer TODO
type GRPCServer struct {
getAllMetadata *grpc.Server
create *grpc.Server
update *grpc.Server
delete *grpc.Server
}
// GetAllMetadata TODO
func (s GRPCServer) GetAllMetadata(r *protobuf.GetAllMetadataRequest, srv protobuf.CredentialService_GetAllMetadataServer) (err error) {
defer func() {
err = handlerGRPCError(err)
}()
var i interface{}
ctx := srv.Context()
ctx, i, err = s.getAllMetadata.ServeGRPC(ctx, *r)
if err != nil {
return err
}
mds := i.(protobufMetadataStream)
receiveLoop:
for {
select {
case <-ctx.Done():
break receiveLoop
case err = <-mds.Errors:
break receiveLoop
case md, ok := <-mds.Metadata:
if !ok {
break receiveLoop
}
fmt.Println(md)
if err = srv.Send(&md); err != nil {
break receiveLoop
}
}
}
return err
}
// Get TODO
func (s GRPCServer) Get(context.Context, *protobuf.IdRequest) (*protobuf.Credential, error) {
panic("implement me")
}
// Create TODO
func (s GRPCServer) Create(ctx context.Context, ci *protobuf.CredentialRequest) (*protobuf.Credential, error) {
ctx, i, err := s.create.ServeGRPC(ctx, *ci)
if err != nil {
err = handlerGRPCError(err)
return nil, err
}
c := &protobuf.Credential{}
*c = i.(protobuf.Credential)
return c, nil
}
// Update TODO
func (s GRPCServer) Update(ctx context.Context, r *protobuf.UpdateRequest) (*protobuf.Credential, error) {
ctx, i, err := s.update.ServeGRPC(ctx, *r)
if err != nil {
err = handlerGRPCError(err)
return nil, err
}
c := &protobuf.Credential{}
*c = i.(protobuf.Credential)
return c, nil
}
// Delete TODO
func (s GRPCServer) Delete(ctx context.Context, r *protobuf.IdRequest) (*protobuf.DeleteResponse, error) {
ctx, _, err := s.delete.ServeGRPC(ctx, *r)
if err != nil {
return nil, err
}
return &protobuf.DeleteResponse{Success: true}, nil
}
func handlerGRPCError(err error) error {
if err != nil {
switch {
case strings.HasPrefix(err.Error(), types.InvalidArgument):
err = status.Error(codes.InvalidArgument, err.Error())
case strings.HasPrefix(err.Error(), types.NotFound):
err = status.Error(codes.NotFound, err.Error())
default:
err = status.Error(codes.Internal, "an internal error has occurred")
}
}
return err
}

View File

@ -0,0 +1,36 @@
package types
import "time"
// Credential TODO
type Credential struct {
Metadata
Username string
Email string
Password string
}
// CredentialInput TODO
type CredentialInput struct {
MetadataInput
Username string
Email string
Password string
}
// Metadata TODO
type Metadata struct {
ID string
CreatedAt time.Time
UpdatedAt time.Time
Primary string
SourceHost string
LoginURL string
}
// MetadataInput TODO
type MetadataInput struct {
Primary string
SourceHost string
LoginURL string
}

View File

@ -0,0 +1,8 @@
package types
// These constants are the prefixes of errors that should be exposed to the client.
// All error encoders should check for them.
const (
NotFound = "not found:"
InvalidArgument = "invalid argument:"
)

View File

@ -0,0 +1,20 @@
package types
import "context"
// Service TODO
type Service interface {
GetAllMetadata(ctx context.Context, sourceService string) (output <-chan Metadata, errch chan error)
Get(ctx context.Context, id string) (output Credential, err error)
Create(ctx context.Context, ci CredentialInput) (output Credential, err error)
Update(ctx context.Context, id string, ci CredentialInput) (output Credential, err error)
Delete(ctx context.Context, id string) (err error)
}
// CredentialRepo TODO
type CredentialRepo interface {
GetAllMetadata(ctx context.Context, sourceService string, errch chan<- error) (output <-chan Metadata)
Get(ctx context.Context, id string) (output Credential, err error)
Put(ctx context.Context, c Credential) (err error)
Delete(ctx context.Context, id string) (err error)
}

14
go.mod Normal file
View File

@ -0,0 +1,14 @@
module github.com/mitchell/selfpass
require (
github.com/aws/aws-sdk-go-v2 v0.7.0
github.com/go-kit/kit v0.8.0
github.com/go-logfmt/logfmt v0.4.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/protobuf v1.3.1
github.com/google/uuid v1.1.1
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
google.golang.org/grpc v1.20.0
)

64
go.sum Normal file
View File

@ -0,0 +1,64 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go-v2 v0.7.0 h1:a5xRI/tBmUFKuAA0SOyEY2P1YhQb+jVOEI9P/7KfrP0=
github.com/aws/aws-sdk-go-v2 v0.7.0/go.mod h1:17MaCZ9g0q5BIMxwzRQeiv8M3c8+W7iuBnlWAEprcxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gucumber/gucumber v0.0.0-20180127021336-7d5c79e832a2/go.mod h1:YbdHRK9ViqwGMS0rtRY+1I6faHvVyyurKPIPwifihxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.20.0 h1:DlsSIrgEBuZAUFJcta2B5i/lzeHHbnfkNFAfFXLVFYQ=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=