feat:#36 added new event grpc message

This commit is contained in:
Elmar Kresse
2024-06-18 12:50:21 +02:00
parent 56e77630b5
commit 08140b5802
14 changed files with 510 additions and 50 deletions

View File

@ -10,7 +10,7 @@ build-ical:
gen: gen:
@protoc \ @protoc \
--proto_path=protobuf "protobuf/modules.proto" \ --proto_path=protobuf "protobuf/modules.proto" \
--go_out=common/genproto/modules \ --go_out="common/genproto/modules" \
--go_opt=paths=source_relative \ --go_opt=paths=source_relative \
--go-grpc_out=common/genproto/modules \ --go-grpc_out="common/genproto/modules" \
--go-grpc_opt=paths=source_relative --go-grpc_opt=paths=source_relative

6
services/README.md Normal file
View File

@ -0,0 +1,6 @@
To execute the protobuf gen script, install the protobuf compiler and the python protobuf library. Then run the following command:
```bash
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
```

View File

@ -305,6 +305,53 @@ func (x *GetModuleRequest) GetUuid() string {
return "" return ""
} }
type GetModulesRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Uuids []string `protobuf:"bytes,1,rep,name=uuids,proto3" json:"uuids,omitempty"`
}
func (x *GetModulesRequest) Reset() {
*x = GetModulesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_modules_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetModulesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetModulesRequest) ProtoMessage() {}
func (x *GetModulesRequest) ProtoReflect() protoreflect.Message {
mi := &file_modules_proto_msgTypes[3]
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 GetModulesRequest.ProtoReflect.Descriptor instead.
func (*GetModulesRequest) Descriptor() ([]byte, []int) {
return file_modules_proto_rawDescGZIP(), []int{3}
}
func (x *GetModulesRequest) GetUuids() []string {
if x != nil {
return x.Uuids
}
return nil
}
type GetModuleResponse struct { type GetModuleResponse struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@ -316,7 +363,7 @@ type GetModuleResponse struct {
func (x *GetModuleResponse) Reset() { func (x *GetModuleResponse) Reset() {
*x = GetModuleResponse{} *x = GetModuleResponse{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_modules_proto_msgTypes[3] mi := &file_modules_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -329,7 +376,7 @@ func (x *GetModuleResponse) String() string {
func (*GetModuleResponse) ProtoMessage() {} func (*GetModuleResponse) ProtoMessage() {}
func (x *GetModuleResponse) ProtoReflect() protoreflect.Message { func (x *GetModuleResponse) ProtoReflect() protoreflect.Message {
mi := &file_modules_proto_msgTypes[3] mi := &file_modules_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -342,7 +389,7 @@ func (x *GetModuleResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetModuleResponse.ProtoReflect.Descriptor instead. // Deprecated: Use GetModuleResponse.ProtoReflect.Descriptor instead.
func (*GetModuleResponse) Descriptor() ([]byte, []int) { func (*GetModuleResponse) Descriptor() ([]byte, []int) {
return file_modules_proto_rawDescGZIP(), []int{3} return file_modules_proto_rawDescGZIP(), []int{4}
} }
func (x *GetModuleResponse) GetModule() *Module { func (x *GetModuleResponse) GetModule() *Module {
@ -352,6 +399,100 @@ func (x *GetModuleResponse) GetModule() *Module {
return nil return nil
} }
type GetModulesResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Modules []*Module `protobuf:"bytes,1,rep,name=modules,proto3" json:"modules,omitempty"`
}
func (x *GetModulesResponse) Reset() {
*x = GetModulesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_modules_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetModulesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetModulesResponse) ProtoMessage() {}
func (x *GetModulesResponse) ProtoReflect() protoreflect.Message {
mi := &file_modules_proto_msgTypes[5]
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 GetModulesResponse.ProtoReflect.Descriptor instead.
func (*GetModulesResponse) Descriptor() ([]byte, []int) {
return file_modules_proto_rawDescGZIP(), []int{5}
}
func (x *GetModulesResponse) GetModules() []*Module {
if x != nil {
return x.Modules
}
return nil
}
type GetEventsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Events []*Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
}
func (x *GetEventsResponse) Reset() {
*x = GetEventsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_modules_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetEventsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetEventsResponse) ProtoMessage() {}
func (x *GetEventsResponse) ProtoReflect() protoreflect.Message {
mi := &file_modules_proto_msgTypes[6]
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 GetEventsResponse.ProtoReflect.Descriptor instead.
func (*GetEventsResponse) Descriptor() ([]byte, []int) {
return file_modules_proto_rawDescGZIP(), []int{6}
}
func (x *GetEventsResponse) GetEvents() []*Event {
if x != nil {
return x.Events
}
return nil
}
var File_modules_proto protoreflect.FileDescriptor var File_modules_proto protoreflect.FileDescriptor
var file_modules_proto_rawDesc = []byte{ var file_modules_proto_rawDesc = []byte{
@ -389,17 +530,34 @@ var file_modules_proto_rawDesc = []byte{
0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x26, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x26, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d,
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64,
0x22, 0x34, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x22, 0x29, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x75, 0x69, 0x64, 0x73, 0x18, 0x01,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x75, 0x69, 0x64, 0x73, 0x22, 0x34, 0x0a, 0x11, 0x47,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x32, 0x45, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x12, 0x1f, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x64, 0x75, 0x6c, 0x65, 0x12, 0x11, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x32, 0x07, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x37, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52,
0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x1c, 0x5a, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
0x1a, 0x68, 0x74, 0x77, 0x6b, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x33, 0x0a, 0x11, 0x47, 0x65,
0x74, 0x6f, 0x33, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x1e, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x06, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x32,
0xbf, 0x01, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x34, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x11,
0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x12, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x12, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x47, 0x65, 0x74, 0x4d,
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x12, 0x3f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x6f, 0x72,
0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x12, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64,
0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x47, 0x65,
0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x42, 0x1c, 0x5a, 0x1a, 0x68, 0x74, 0x77, 0x6b, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -414,23 +572,32 @@ func file_modules_proto_rawDescGZIP() []byte {
return file_modules_proto_rawDescData return file_modules_proto_rawDescData
} }
var file_modules_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_modules_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_modules_proto_goTypes = []interface{}{ var file_modules_proto_goTypes = []interface{}{
(*Event)(nil), // 0: Event (*Event)(nil), // 0: Event
(*Module)(nil), // 1: Module (*Module)(nil), // 1: Module
(*GetModuleRequest)(nil), // 2: GetModuleRequest (*GetModuleRequest)(nil), // 2: GetModuleRequest
(*GetModuleResponse)(nil), // 3: GetModuleResponse (*GetModulesRequest)(nil), // 3: GetModulesRequest
(*GetModuleResponse)(nil), // 4: GetModuleResponse
(*GetModulesResponse)(nil), // 5: GetModulesResponse
(*GetEventsResponse)(nil), // 6: GetEventsResponse
} }
var file_modules_proto_depIdxs = []int32{ var file_modules_proto_depIdxs = []int32{
0, // 0: Module.events:type_name -> Event 0, // 0: Module.events:type_name -> Event
1, // 1: GetModuleResponse.module:type_name -> Module 1, // 1: GetModuleResponse.module:type_name -> Module
2, // 2: ModuleService.GetModule:input_type -> GetModuleRequest 1, // 2: GetModulesResponse.modules:type_name -> Module
3, // 3: ModuleService.GetModule:output_type -> GetModuleResponse 0, // 3: GetEventsResponse.events:type_name -> Event
3, // [3:4] is the sub-list for method output_type 2, // 4: ModuleService.GetModule:input_type -> GetModuleRequest
2, // [2:3] is the sub-list for method input_type 3, // 5: ModuleService.GetModules:input_type -> GetModulesRequest
2, // [2:2] is the sub-list for extension type_name 3, // 6: ModuleService.GetEventsForModules:input_type -> GetModulesRequest
2, // [2:2] is the sub-list for extension extendee 4, // 7: ModuleService.GetModule:output_type -> GetModuleResponse
0, // [0:2] is the sub-list for field type_name 5, // 8: ModuleService.GetModules:output_type -> GetModulesResponse
6, // 9: ModuleService.GetEventsForModules:output_type -> GetEventsResponse
7, // [7:10] is the sub-list for method output_type
4, // [4:7] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
} }
func init() { file_modules_proto_init() } func init() { file_modules_proto_init() }
@ -476,6 +643,18 @@ func file_modules_proto_init() {
} }
} }
file_modules_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { file_modules_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetModulesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_modules_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetModuleResponse); i { switch v := v.(*GetModuleResponse); i {
case 0: case 0:
return &v.state return &v.state
@ -487,6 +666,30 @@ func file_modules_proto_init() {
return nil return nil
} }
} }
file_modules_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetModulesResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_modules_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetEventsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
@ -494,7 +697,7 @@ func file_modules_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_modules_proto_rawDesc, RawDescriptor: file_modules_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 4, NumMessages: 7,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View File

@ -23,6 +23,8 @@ const _ = grpc.SupportPackageIsVersion7
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type ModuleServiceClient interface { type ModuleServiceClient interface {
GetModule(ctx context.Context, in *GetModuleRequest, opts ...grpc.CallOption) (*GetModuleResponse, error) GetModule(ctx context.Context, in *GetModuleRequest, opts ...grpc.CallOption) (*GetModuleResponse, error)
GetModules(ctx context.Context, in *GetModulesRequest, opts ...grpc.CallOption) (*GetModulesResponse, error)
GetEventsForModules(ctx context.Context, in *GetModulesRequest, opts ...grpc.CallOption) (*GetEventsResponse, error)
} }
type moduleServiceClient struct { type moduleServiceClient struct {
@ -42,11 +44,31 @@ func (c *moduleServiceClient) GetModule(ctx context.Context, in *GetModuleReques
return out, nil return out, nil
} }
func (c *moduleServiceClient) GetModules(ctx context.Context, in *GetModulesRequest, opts ...grpc.CallOption) (*GetModulesResponse, error) {
out := new(GetModulesResponse)
err := c.cc.Invoke(ctx, "/ModuleService/GetModules", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *moduleServiceClient) GetEventsForModules(ctx context.Context, in *GetModulesRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) {
out := new(GetEventsResponse)
err := c.cc.Invoke(ctx, "/ModuleService/GetEventsForModules", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ModuleServiceServer is the server API for ModuleService service. // ModuleServiceServer is the server API for ModuleService service.
// All implementations must embed UnimplementedModuleServiceServer // All implementations must embed UnimplementedModuleServiceServer
// for forward compatibility // for forward compatibility
type ModuleServiceServer interface { type ModuleServiceServer interface {
GetModule(context.Context, *GetModuleRequest) (*GetModuleResponse, error) GetModule(context.Context, *GetModuleRequest) (*GetModuleResponse, error)
GetModules(context.Context, *GetModulesRequest) (*GetModulesResponse, error)
GetEventsForModules(context.Context, *GetModulesRequest) (*GetEventsResponse, error)
mustEmbedUnimplementedModuleServiceServer() mustEmbedUnimplementedModuleServiceServer()
} }
@ -57,6 +79,12 @@ type UnimplementedModuleServiceServer struct {
func (UnimplementedModuleServiceServer) GetModule(context.Context, *GetModuleRequest) (*GetModuleResponse, error) { func (UnimplementedModuleServiceServer) GetModule(context.Context, *GetModuleRequest) (*GetModuleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetModule not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetModule not implemented")
} }
func (UnimplementedModuleServiceServer) GetModules(context.Context, *GetModulesRequest) (*GetModulesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetModules not implemented")
}
func (UnimplementedModuleServiceServer) GetEventsForModules(context.Context, *GetModulesRequest) (*GetEventsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetEventsForModules not implemented")
}
func (UnimplementedModuleServiceServer) mustEmbedUnimplementedModuleServiceServer() {} func (UnimplementedModuleServiceServer) mustEmbedUnimplementedModuleServiceServer() {}
// UnsafeModuleServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeModuleServiceServer may be embedded to opt out of forward compatibility for this service.
@ -88,6 +116,42 @@ func _ModuleService_GetModule_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _ModuleService_GetModules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetModulesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ModuleServiceServer).GetModules(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ModuleService/GetModules",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ModuleServiceServer).GetModules(ctx, req.(*GetModulesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ModuleService_GetEventsForModules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetModulesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ModuleServiceServer).GetEventsForModules(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ModuleService/GetEventsForModules",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ModuleServiceServer).GetEventsForModules(ctx, req.(*GetModulesRequest))
}
return interceptor(ctx, in, info, handler)
}
// ModuleService_ServiceDesc is the grpc.ServiceDesc for ModuleService service. // ModuleService_ServiceDesc is the grpc.ServiceDesc for ModuleService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@ -99,6 +163,14 @@ var ModuleService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetModule", MethodName: "GetModule",
Handler: _ModuleService_GetModule_Handler, Handler: _ModuleService_GetModule_Handler,
}, },
{
MethodName: "GetModules",
Handler: _ModuleService_GetModules_Handler,
},
{
MethodName: "GetEventsForModules",
Handler: _ModuleService_GetEventsForModules_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "modules.proto", Metadata: "modules.proto",

View File

@ -131,25 +131,37 @@ func findEventByDayWeekStartEndNameCourse(event model.Event, course string, dao
} }
} }
func buildIcalQueryForModules(modules []model.FeedCollection) dbx.Expression { func buildIcalQueryForModules(modulesUuid []string) dbx.Expression {
// check uuids against sql injection
// uuids are generated by the system and are not user input
// following the pattern of only containing alphanumeric characters and dashes
for _, moduleUuid := range modulesUuid {
if !IsSafeIdentifier(moduleUuid) {
slog.Warn("Module UUID is not safe: ", "moduleUuid", moduleUuid)
return dbx.HashExp{}
}
}
// build where conditions for each module // build where conditions for each module
//first check if modules is empty //first check if modules is empty
if len(modules) == 0 { if len(modulesUuid) == 0 {
return dbx.HashExp{} return dbx.HashExp{}
} }
//second check if modules has only one element //second check if modules has only one element
if len(modules) == 1 { if len(modulesUuid) == 1 {
return dbx.HashExp{"uuid": modules[0].UUID} return dbx.HashExp{"uuid": modulesUuid[0]}
} }
//third check if modules has more than one element //third check if modules has more than one element
var wheres []dbx.Expression var wheres []dbx.Expression
for _, module := range modules { for _, moduleUuid := range modulesUuid {
where := dbx.HashExp{"uuid": module.UUID} where := dbx.HashExp{"uuid": moduleUuid}
wheres = append(wheres, where) wheres = append(wheres, where)
} }
@ -162,18 +174,18 @@ func buildIcalQueryForModules(modules []model.FeedCollection) dbx.Expression {
// GetPlanForModules returns all events for the given modules with the given course // GetPlanForModules returns all events for the given modules with the given course
// used for the ical feed // used for the ical feed
func GetPlanForModules(app *pocketbase.PocketBase, modules map[string]model.FeedCollection) (model.Events, error) { func GetPlanForModules(app *pocketbase.PocketBase, modules []string) (model.Events, error) {
var events model.Events var events model.Events
modulesArray := make([]model.FeedCollection, 0, len(modules)) modulesArray := make([]string, 0, len(modules))
for _, value := range modules { for _, value := range modules {
modulesArray = append(modulesArray, value) modulesArray = append(modulesArray, value)
} }
// iterate over modules in 100 batch sizes // iterate over modules in 100 batch sizes
for i := 0; i < len(modules); i += 100 { for i := 0; i < len(modules); i += 100 {
var moduleBatch []model.FeedCollection var moduleBatch []string
if i+100 > len(modules) { if i+100 > len(modules) {
moduleBatch = modulesArray[i:] moduleBatch = modulesArray[i:]

View File

@ -18,14 +18,13 @@ package db
import ( import (
"github.com/pocketbase/dbx" "github.com/pocketbase/dbx"
"htwkalender/data-manager/model"
"reflect" "reflect"
"testing" "testing"
) )
func Test_buildIcalQueryForModules(t *testing.T) { func Test_buildIcalQueryForModules(t *testing.T) {
type args struct { type args struct {
modules []model.FeedCollection modules []string
} }
tests := []struct { tests := []struct {
name string name string
@ -34,17 +33,17 @@ func Test_buildIcalQueryForModules(t *testing.T) {
}{ }{
{ {
name: "empty modules", name: "empty modules",
args: args{modules: []model.FeedCollection{}}, args: args{modules: []string{}},
want: dbx.HashExp{}, want: dbx.HashExp{},
}, },
{ {
name: "one module", name: "one module",
args: args{modules: []model.FeedCollection{{Name: "test", Course: "test", UUID: "test"}}}, args: args{modules: []string{"test"}},
want: dbx.HashExp{"uuid": "test"}, want: dbx.HashExp{"uuid": "test"},
}, },
{ {
name: "two modules", name: "two modules",
args: args{modules: []model.FeedCollection{{Name: "test", Course: "test", UUID: "test"}, {Name: "test2", Course: "test2", UUID: "test2"}}}, args: args{modules: []string{"test", "test2"}},
want: dbx.Or(dbx.HashExp{"uuid": "test"}, dbx.HashExp{"uuid": "test2"}), want: dbx.Or(dbx.HashExp{"uuid": "test"}, dbx.HashExp{"uuid": "test2"}),
}, },
} }

View File

@ -19,9 +19,26 @@ package db
import ( import (
"github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/models"
"log/slog"
"regexp"
) )
func FindCollection(app *pocketbase.PocketBase, collectionName string) (*models.Collection, error) { func FindCollection(app *pocketbase.PocketBase, collectionName string) (*models.Collection, error) {
collection, dbError := app.Dao().FindCollectionByNameOrId(collectionName) collection, dbError := app.Dao().FindCollectionByNameOrId(collectionName)
return collection, dbError return collection, dbError
} }
// IsSafeIdentifier check uuids against sql injection
// uuids are generated by the system and are not user input
// following the pattern of only containing alphanumeric characters and dashes
func IsSafeIdentifier(uuid string) bool {
// Define a regular expression that matches only valid UUID characters (alphanumeric and dashes)
validUUIDPattern := `^[a-zA-Z0-9-]+$`
match, err := regexp.MatchString(validUUIDPattern, uuid)
if err != nil {
// Handle the error according to your application's needs
slog.Warn("Invalid UUID pattern", "uuid", uuid)
return false
}
return match
}

View File

@ -0,0 +1,50 @@
package db
import "testing"
func TestIsSafeIdentifier(t *testing.T) {
type args struct {
uuid string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Test safe identifier",
args: args{
uuid: "1234567890-1234567890-1234567890-1234567890",
},
want: true,
},
{
name: "Test safe identifier",
args: args{
uuid: "1234567890-1234567890-1234567890-1234567890",
},
want: true,
},
{
name: "Test safe identifier",
args: args{
uuid: "77eddc32-c49d-5d0a-8c36-17b266396641",
},
want: true,
},
{
name: "Test unsafe identifier",
args: args{
uuid: "77eddc32-c49d-5d0a-8c36-17/1!!b266396641-",
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsSafeIdentifier(tt.args.uuid); got != tt.want {
t.Errorf("IsSafeIdentifier() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -23,3 +23,11 @@ func eventToProto(event *model.Event) *pb.Event {
Semester: event.Semester, Semester: event.Semester,
} }
} }
func eventsToProto(events model.Events) []*pb.Event {
protoEvents := make([]*pb.Event, 0)
for _, event := range events {
protoEvents = append(protoEvents, eventToProto(&event))
}
return protoEvents
}

View File

@ -67,3 +67,15 @@ func StartGRPCServer(app *pocketbase.PocketBase) {
log.Fatalf("failed to serve: %v", err) log.Fatalf("failed to serve: %v", err)
} }
} }
func (s *ModulesGrpcHandler) GetEventsForModules(ctx context.Context, in *pb.GetModulesRequest) (*pb.GetEventsResponse, error) {
events, err := db.GetPlanForModules(s.app, in.Uuids)
if err != nil {
return nil, err
}
return &pb.GetEventsResponse{
Events: eventsToProto(events),
}, nil
}

View File

@ -0,0 +1,34 @@
package grpc
import (
"context"
"google.golang.org/grpc"
pb "htwkalender/common/genproto/modules"
"htwkalender/ical/model"
"log/slog"
"time"
)
func GetEvents(modules []model.FeedModule, conn *grpc.ClientConn) (model.Events, error) {
c := pb.NewModuleServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// List of uuids
uuids := make([]string, 0)
for _, module := range modules {
uuids = append(uuids, module.UUID)
}
r, err := c.GetEventsForModules(ctx, &pb.GetModulesRequest{Uuids: uuids})
if err != nil {
slog.Error("could not get modules: %v", "error", err)
}
events := make(model.Events, 0)
for _, event := range r.GetEvents() {
events = append(events, protoToEvent(event))
}
return events, nil
}

View File

@ -33,6 +33,42 @@ func GetModuleWithEvents(module model.FeedModule, conn *grpc.ClientConn) (model.
}, nil }, nil
} }
func GetModulesWithEvents(modules []model.FeedModule, conn *grpc.ClientConn) ([]model.Module, error) {
c := pb.NewModuleServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// List of uuids
uuids := make([]string, 0)
for _, module := range modules {
uuids = append(uuids, module.UUID)
}
r, err := c.GetModules(ctx, &pb.GetModulesRequest{Uuids: uuids})
if err != nil {
slog.Error("could not get modules: %v", "error", err)
}
moduleList := make([]model.Module, 0)
for _, module := range r.GetModules() {
events := make([]model.Event, 0)
for _, event := range module.Events {
events = append(events, protoToEvent(event))
}
moduleList = append(moduleList, model.Module{
UUID: module.Uuid,
Name: module.Name,
Prof: module.Prof,
Course: module.Course,
Semester: module.Semester,
Events: events,
})
}
return moduleList, nil
}
func protoToEvent(event *pb.Event) model.Event { func protoToEvent(event *pb.Event) model.Event {
return model.Event{ return model.Event{

View File

@ -21,15 +21,12 @@ func Feed(app model.AppType, token string) (string, error) {
var events model.Events var events model.Events
for _, module := range feed.Modules { // Get all events for modules
moduleWithEvents, err := htwkalenderGrpc.GetModuleWithEvents(module, app.GrpcClient) events, err = htwkalenderGrpc.GetEvents(feed.Modules, app.GrpcClient)
if err != nil { if err != nil {
return "", err return "", err
} }
events = append(events, moduleWithEvents.Events...)
}
// Sort events by start date // Sort events by start date
events.Sort() events.Sort()

View File

@ -4,6 +4,8 @@ option go_package = "htwkalender/common/modules";
service ModuleService { service ModuleService {
rpc GetModule(GetModuleRequest) returns (GetModuleResponse) {} rpc GetModule(GetModuleRequest) returns (GetModuleResponse) {}
rpc GetModules(GetModulesRequest) returns (GetModulesResponse) {}
rpc GetEventsForModules(GetModulesRequest) returns (GetEventsResponse) {}
} }
message Event { message Event {
@ -36,6 +38,18 @@ message GetModuleRequest {
string uuid = 1; string uuid = 1;
} }
message GetModulesRequest {
repeated string uuids = 1;
}
message GetModuleResponse { message GetModuleResponse {
Module module = 1; Module module = 1;
} }
message GetModulesResponse {
repeated Module modules = 1;
}
message GetEventsResponse {
repeated Event events = 1;
}