From 718466a4a1d8df303ba7a53555214e4c8c4bae60 Mon Sep 17 00:00:00 2001 From: Dominic Wong Date: Wed, 16 Feb 2022 21:41:48 +0000 Subject: [PATCH] Add logos to vehicle API (#380) --- vehicle/handler/vehicle.go | 45 ++++++- vehicle/main.go | 4 +- vehicle/proto/admin.pb.go | 211 ++++++++++++++++++++++++++++++++ vehicle/proto/admin.pb.micro.go | 93 ++++++++++++++ vehicle/proto/admin.proto | 16 +++ vehicle/proto/vehicle.pb.go | 29 +++-- vehicle/proto/vehicle.proto | 4 + 7 files changed, 391 insertions(+), 11 deletions(-) create mode 100644 vehicle/proto/admin.pb.go create mode 100644 vehicle/proto/admin.pb.micro.go create mode 100644 vehicle/proto/admin.proto diff --git a/vehicle/handler/vehicle.go b/vehicle/handler/vehicle.go index 3990260..19f0559 100644 --- a/vehicle/handler/vehicle.go +++ b/vehicle/handler/vehicle.go @@ -2,10 +2,15 @@ package handler import ( "context" + "encoding/json" + "fmt" + "strings" "github.com/micro/micro/v3/service/errors" "github.com/micro/micro/v3/service/logger" + "github.com/micro/micro/v3/service/store" "github.com/micro/services/pkg/api" + "github.com/micro/services/pkg/auth" pb "github.com/micro/services/vehicle/proto" ) @@ -60,6 +65,44 @@ func (v *Vehicle) Lookup(ctx context.Context, req *pb.LookupRequest, rsp *pb.Loo rsp.TypeApproval, _ = resp["typeApproval"].(string) rsp.Wheelplan, _ = resp["wheelplan"].(string) rsp.LastV5Issued, _ = resp["dateOfLastV5CIssued"].(string) - + rsp.LogoUrl = v.getLogo(rsp.Make) return nil } + +const ( + prefixLogo = "logo" +) + +func (v *Vehicle) getLogo(make string) string { + recs, err := store.Read(logoKey(make)) + if err != nil { + if err == store.ErrNotFound { + logger.Errorf("No logo found for make %s", make) + } else { + logger.Errorf("Error reading logo %s", err) + } + return "" + } + var ret string + json.Unmarshal(recs[0].Value, &ret) + return ret +} + +func (v *Vehicle) SetLogo(ctx context.Context, request *pb.SetLogoRequest, response *pb.SetLogoResponse) error { + if _, err := auth.VerifyMicroAdmin(ctx, "vehicleAdmin.SetLogo"); err != nil { + return err + } + + if len(request.Url) == 0 || len(request.Make) == 0 { + return errors.BadRequest("vehicleAdmin.SetLogo", "Missing params") + } + rec := store.NewRecord(logoKey(request.Make), request.Url) + if err := store.Write(rec); err != nil { + return err + } + return nil +} + +func logoKey(make string) string { + return fmt.Sprintf("%s/%s", prefixLogo, strings.ToLower(make)) +} diff --git a/vehicle/main.go b/vehicle/main.go index 885d49f..156f596 100644 --- a/vehicle/main.go +++ b/vehicle/main.go @@ -25,8 +25,10 @@ func main() { logger.Fatal("dvla.api_key config not found") } + h := handler.New(key) // Register handler - pb.RegisterVehicleHandler(srv.Server(), handler.New(key)) + pb.RegisterVehicleHandler(srv.Server(), h) + pb.RegisterVehicleAdminHandler(srv.Server(), h) // Run service if err := srv.Run(); err != nil { diff --git a/vehicle/proto/admin.pb.go b/vehicle/proto/admin.pb.go new file mode 100644 index 0000000..ef1767d --- /dev/null +++ b/vehicle/proto/admin.pb.go @@ -0,0 +1,211 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.15.5 +// source: proto/admin.proto + +package vehicle + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SetLogoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Make string `protobuf:"bytes,1,opt,name=make,proto3" json:"make,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *SetLogoRequest) Reset() { + *x = SetLogoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_admin_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetLogoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetLogoRequest) ProtoMessage() {} + +func (x *SetLogoRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_admin_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetLogoRequest.ProtoReflect.Descriptor instead. +func (*SetLogoRequest) Descriptor() ([]byte, []int) { + return file_proto_admin_proto_rawDescGZIP(), []int{0} +} + +func (x *SetLogoRequest) GetMake() string { + if x != nil { + return x.Make + } + return "" +} + +func (x *SetLogoRequest) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +type SetLogoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SetLogoResponse) Reset() { + *x = SetLogoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_admin_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetLogoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetLogoResponse) ProtoMessage() {} + +func (x *SetLogoResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_admin_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetLogoResponse.ProtoReflect.Descriptor instead. +func (*SetLogoResponse) Descriptor() ([]byte, []int) { + return file_proto_admin_proto_rawDescGZIP(), []int{1} +} + +var File_proto_admin_proto protoreflect.FileDescriptor + +var file_proto_admin_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x22, 0x36, 0x0a, 0x0e, + 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6d, 0x61, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x61, + 0x6b, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x75, 0x72, 0x6c, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x4e, 0x0a, 0x0c, 0x56, 0x65, 0x68, 0x69, 0x63, + 0x6c, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x3e, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x4c, 0x6f, + 0x67, 0x6f, 0x12, 0x17, 0x2e, 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x2e, 0x53, 0x65, 0x74, + 0x4c, 0x6f, 0x67, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x76, 0x65, + 0x68, 0x69, 0x63, 0x6c, 0x65, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x6f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x3b, 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_proto_admin_proto_rawDescOnce sync.Once + file_proto_admin_proto_rawDescData = file_proto_admin_proto_rawDesc +) + +func file_proto_admin_proto_rawDescGZIP() []byte { + file_proto_admin_proto_rawDescOnce.Do(func() { + file_proto_admin_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_admin_proto_rawDescData) + }) + return file_proto_admin_proto_rawDescData +} + +var file_proto_admin_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_admin_proto_goTypes = []interface{}{ + (*SetLogoRequest)(nil), // 0: vehicle.SetLogoRequest + (*SetLogoResponse)(nil), // 1: vehicle.SetLogoResponse +} +var file_proto_admin_proto_depIdxs = []int32{ + 0, // 0: vehicle.VehicleAdmin.SetLogo:input_type -> vehicle.SetLogoRequest + 1, // 1: vehicle.VehicleAdmin.SetLogo:output_type -> vehicle.SetLogoResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_proto_admin_proto_init() } +func file_proto_admin_proto_init() { + if File_proto_admin_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_admin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetLogoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_admin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetLogoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_admin_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_admin_proto_goTypes, + DependencyIndexes: file_proto_admin_proto_depIdxs, + MessageInfos: file_proto_admin_proto_msgTypes, + }.Build() + File_proto_admin_proto = out.File + file_proto_admin_proto_rawDesc = nil + file_proto_admin_proto_goTypes = nil + file_proto_admin_proto_depIdxs = nil +} diff --git a/vehicle/proto/admin.pb.micro.go b/vehicle/proto/admin.pb.micro.go new file mode 100644 index 0000000..372ea4f --- /dev/null +++ b/vehicle/proto/admin.pb.micro.go @@ -0,0 +1,93 @@ +// Code generated by protoc-gen-micro. DO NOT EDIT. +// source: proto/admin.proto + +package vehicle + +import ( + fmt "fmt" + proto "github.com/golang/protobuf/proto" + math "math" +) + +import ( + context "context" + api "github.com/micro/micro/v3/service/api" + client "github.com/micro/micro/v3/service/client" + server "github.com/micro/micro/v3/service/server" +) + +// 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 + +// Reference imports to suppress errors if they are not otherwise used. +var _ api.Endpoint +var _ context.Context +var _ client.Option +var _ server.Option + +// Api Endpoints for VehicleAdmin service + +func NewVehicleAdminEndpoints() []*api.Endpoint { + return []*api.Endpoint{} +} + +// Client API for VehicleAdmin service + +type VehicleAdminService interface { + SetLogo(ctx context.Context, in *SetLogoRequest, opts ...client.CallOption) (*SetLogoResponse, error) +} + +type vehicleAdminService struct { + c client.Client + name string +} + +func NewVehicleAdminService(name string, c client.Client) VehicleAdminService { + return &vehicleAdminService{ + c: c, + name: name, + } +} + +func (c *vehicleAdminService) SetLogo(ctx context.Context, in *SetLogoRequest, opts ...client.CallOption) (*SetLogoResponse, error) { + req := c.c.NewRequest(c.name, "VehicleAdmin.SetLogo", in) + out := new(SetLogoResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for VehicleAdmin service + +type VehicleAdminHandler interface { + SetLogo(context.Context, *SetLogoRequest, *SetLogoResponse) error +} + +func RegisterVehicleAdminHandler(s server.Server, hdlr VehicleAdminHandler, opts ...server.HandlerOption) error { + type vehicleAdmin interface { + SetLogo(ctx context.Context, in *SetLogoRequest, out *SetLogoResponse) error + } + type VehicleAdmin struct { + vehicleAdmin + } + h := &vehicleAdminHandler{hdlr} + return s.Handle(s.NewHandler(&VehicleAdmin{h}, opts...)) +} + +type vehicleAdminHandler struct { + VehicleAdminHandler +} + +func (h *vehicleAdminHandler) SetLogo(ctx context.Context, in *SetLogoRequest, out *SetLogoResponse) error { + return h.VehicleAdminHandler.SetLogo(ctx, in, out) +} diff --git a/vehicle/proto/admin.proto b/vehicle/proto/admin.proto new file mode 100644 index 0000000..5b420e9 --- /dev/null +++ b/vehicle/proto/admin.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package vehicle; + +option go_package = "./proto;vehicle"; + +service VehicleAdmin { + rpc SetLogo(SetLogoRequest) returns (SetLogoResponse) {} +} + +message SetLogoRequest { + string make = 1; + string url = 2; +} + +message SetLogoResponse {} diff --git a/vehicle/proto/vehicle.pb.go b/vehicle/proto/vehicle.pb.go index a0c0b0e..a658e1b 100644 --- a/vehicle/proto/vehicle.pb.go +++ b/vehicle/proto/vehicle.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.15.6 +// protoc v3.15.5 // source: proto/vehicle.proto package vehicle @@ -104,6 +104,8 @@ type LookupResponse struct { Wheelplan string `protobuf:"bytes,14,opt,name=wheelplan,proto3" json:"wheelplan,omitempty"` // date of last v5 issue LastV5Issued string `protobuf:"bytes,15,opt,name=last_v5_issued,json=lastV5Issued,proto3" json:"last_v5_issued,omitempty"` + // url of logo for the make + LogoUrl string `protobuf:"bytes,16,opt,name=logo_url,json=logoUrl,proto3" json:"logo_url,omitempty"` } func (x *LookupResponse) Reset() { @@ -243,6 +245,13 @@ func (x *LookupResponse) GetLastV5Issued() string { return "" } +func (x *LookupResponse) GetLogoUrl() string { + if x != nil { + return x.LogoUrl + } + return "" +} + var File_proto_vehicle_proto protoreflect.FileDescriptor var file_proto_vehicle_proto_rawDesc = []byte{ @@ -251,7 +260,7 @@ var file_proto_vehicle_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x04, 0x0a, 0x0e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, + 0x69, 0x6f, 0x6e, 0x22, 0xbd, 0x04, 0x0a, 0x0e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, @@ -285,13 +294,15 @@ var file_proto_vehicle_proto_rawDesc = []byte{ 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x35, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, - 0x56, 0x35, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x32, 0x46, 0x0a, 0x07, 0x56, 0x65, 0x68, 0x69, - 0x63, 0x6c, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x16, 0x2e, - 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x2e, - 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x76, 0x65, 0x68, 0x69, - 0x63, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x56, 0x35, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x6f, + 0x55, 0x72, 0x6c, 0x32, 0x46, 0x0a, 0x07, 0x56, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x12, 0x3b, + 0x0a, 0x06, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x16, 0x2e, 0x76, 0x65, 0x68, 0x69, 0x63, + 0x6c, 0x65, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x11, 0x5a, 0x0f, 0x2e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x76, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/vehicle/proto/vehicle.proto b/vehicle/proto/vehicle.proto index 4a24795..3379007 100644 --- a/vehicle/proto/vehicle.proto +++ b/vehicle/proto/vehicle.proto @@ -8,6 +8,7 @@ service Vehicle { rpc Lookup(LookupRequest) returns (LookupResponse) {} } + // Lookup a UK vehicle by it's registration number message LookupRequest { // the vehicle registration number @@ -45,4 +46,7 @@ message LookupResponse { string wheelplan = 14; // date of last v5 issue string last_v5_issued = 15; + // url of logo for the make + string logo_url = 16; } +