diff --git a/.gitignore b/.gitignore
index c66e6eb..871e43c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
.DS_Store
workspace.xml
**/.idea/
-.sass-cache/
\ No newline at end of file
+.sass-cache/
+/services/pb_data/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3f0822b..49ca5e0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -19,7 +19,6 @@ stages:
- build
- test
- sonarqube-check
- - sonarqube-vulnerability-report
- oci-build
- deploy
- deploy-dev # New stage for development deployment
@@ -179,7 +178,7 @@ build-data-manager-image:
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- - docker build --pull -t $IMAGE_TAG -f ./services/data-manager/Dockerfile --target prod ./services/data-manager
+ - docker build --pull -t $IMAGE_TAG -f ./services/data-manager/Dockerfile --target prod ./services
- docker push $IMAGE_TAG
rules:
- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "development"
@@ -202,7 +201,7 @@ build-ical-image:
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- - docker build --pull -t $IMAGE_TAG -f ./services/ical/Dockerfile --target prod ./services/ical
+ - docker build --pull -t $IMAGE_TAG -f ./services/ical/Dockerfile --target prod ./services
- docker push $IMAGE_TAG
rules:
- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "development"
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 26fdc84..719de55 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -29,6 +29,8 @@ services:
image: DOCKER_REGISTRY_REPO-ical # DOCKER_REGISTRY_REPO will be replaced by CI
pull_policy: always
restart: always
+ environment:
+ - DATA_MANAGER_URL=htwkalender-data-manager
networks:
- "net"
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index 8358f31..f52e1aa 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -29,6 +29,8 @@ services:
image: DOCKER_REGISTRY_REPO-ical # DOCKER_REGISTRY_REPO will be replaced by CI
pull_policy: always
restart: always
+ environment:
+ - DATA_MANAGER_URL=htwkalender-data-manager
networks:
- "net"
diff --git a/docker-compose.yml b/docker-compose.yml
index c6a28f6..922610f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,8 +17,8 @@
services:
htwkalender-data-manager:
build:
- dockerfile: Dockerfile
- context: services/data-manager
+ dockerfile: ./data-manager/Dockerfile
+ context: ./services
target: dev # prod
command: "--http=0.0.0.0:8090 --dir=/htwkalender-data-manager/data/pb_data"
#ports:
@@ -29,10 +29,11 @@ services:
htwkalender-ical:
build:
- dockerfile: Dockerfile
- context: services/ical
+ dockerfile: ./ical/Dockerfile
+ context: ./services
target: dev # prod
-
+ environment:
+ - DATA_MANAGER_URL=htwkalender-data-manager
htwkalender-frontend:
build:
diff --git a/reverseproxy.conf b/reverseproxy.conf
index c01c32c..55220e6 100644
--- a/reverseproxy.conf
+++ b/reverseproxy.conf
@@ -93,6 +93,13 @@ http {
proxy_temp_file_write_size 64k;
proxy_max_temp_file_size 1024m;
+ proxy_set_header X-Forwarded-Host $host;
+ proxy_set_header X-Forwarded-Server $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $host;
+
geo $admin {
default 1;
10.0.0.0/8 0; # Private Network
@@ -107,9 +114,15 @@ http {
1 $binary_remote_addr;
}
+ # Different rate limits for different request methods
+ map $request_method $ratelimit_key {
+ POST $binary_remote_addr;
+ default "";
+ }
+
+ limit_req_zone $ratelimit_key zone=createFeed:10m rate=1r/m;
# Limit the number of requests per IP
limit_req_zone $limit_key zone=feed:20m rate=20r/m;
- limit_req_zone $limit_key zone=createFeed:10m rate=1r/m;
limit_req_zone $limit_key zone=modules:10m rate=30r/m;
server {
@@ -119,13 +132,14 @@ http {
server_name cal.htwk-leipzig.de;
location /api/feed {
+ limit_req zone=createFeed nodelay;
+ limit_req zone=feed burst=10 nodelay;
proxy_pass http://htwkalender-ical:8091;
client_max_body_size 2m;
proxy_connect_timeout 600s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
- limit_req zone=$limit_zone burst=10 nodelay;
limit_req_status 429;
}
@@ -141,18 +155,14 @@ http {
server_name htwkalender.de;
location /api/feed {
+ limit_req zone=createFeed nodelay;
+ limit_req zone=feed burst=10 nodelay;
proxy_pass http://htwkalender-ical:8091;
client_max_body_size 2m;
proxy_connect_timeout 600s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
-
- # Apply rate limiting
- if ($request_method = POST) {
- limit_req zone=createFeed burst=10 nodelay;
- }
- limit_req zone=feed burst=10 nodelay;
limit_req_status 429;
}
@@ -182,13 +192,14 @@ http {
ssl_certificate_key cal.htwk-leipzig.de.key.pem;
location /api/feed {
+ limit_req zone=createFeed nodelay;
+ limit_req zone=feed burst=10 nodelay;
proxy_pass http://htwkalender-ical:8091;
client_max_body_size 2m;
proxy_connect_timeout 600s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
- limit_req zone=$limit_zone burst=10 nodelay;
limit_req_status 429;
}
diff --git a/reverseproxy.dev.conf b/reverseproxy.dev.conf
index 7a6bf6b..31656bc 100644
--- a/reverseproxy.dev.conf
+++ b/reverseproxy.dev.conf
@@ -94,6 +94,13 @@ http {
proxy_temp_file_write_size 64k;
proxy_max_temp_file_size 1024m;
+ proxy_set_header X-Forwarded-Host $host;
+ proxy_set_header X-Forwarded-Server $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header Host $host;
+
geo $admin {
default 1;
10.0.0.0/8 0; # Private Network
@@ -109,20 +116,15 @@ http {
}
# Different rate limits for different request methods
- map $request_method $limit_feed {
- POST ''; # Create feed is limited to 1 request per minute
- default $binary_remote_addr; # All other requests are limited to 20 requests per minute
+ map $request_method $ratelimit_key {
+ POST $binary_remote_addr;
+ default "";
}
-
- map $request_method $limit_createFeed {
- POST $binary_remote_addr; # Create feed is limited to 1 request per minute
- default ''; # All other requests are limited to 20 requests per minute
- }
+ limit_req_zone $ratelimit_key zone=createFeed:10m rate=1r/m;
# Limit the number of requests per IP
limit_req_zone $limit_feed zone=feed:20m rate=20r/m;
- limit_req_zone $limit_createFeed zone=createFeed:10m rate=1r/m;
limit_req_zone $limit_key zone=modules:10m rate=30r/m;
server {
@@ -142,14 +144,14 @@ http {
ssl_certificate_key dev_htwkalender_de.key.pem;
location /api/feed {
+ limit_req zone=createFeed nodelay;
+ limit_req zone=feed burst=10 nodelay;
proxy_pass http://htwkalender-ical:8091;
client_max_body_size 2m;
proxy_connect_timeout 600s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
- limit_req zone=feed burst=10 nodelay;
- limit_req zone=createFeed burst=10 nodelay;
limit_req_status 429;
}
diff --git a/reverseproxy.local.conf b/reverseproxy.local.conf
index 16c5eba..05f99c2 100644
--- a/reverseproxy.local.conf
+++ b/reverseproxy.local.conf
@@ -1,22 +1,6 @@
-#Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
-#Copyright (C) 2024 HTWKalender support@htwkalender.de
-
-#This program is free software: you can redistribute it and/or modify
-#it under the terms of the GNU Affero General Public License as published by
-#the Free Software Foundation, either version 3 of the License, or
-#(at your option) any later version.
-
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU Affero General Public License for more details.
-
-#You should have received a copy of the GNU Affero General Public License
-#along with this program. If not, see .
-
worker_processes 4;
-error_log /opt/bitnami/nginx/logs/error.log;
+error_log /opt/bitnami/nginx/logs/error.log debug;
pid /opt/bitnami/nginx/tmp/nginx.pid;
events {
@@ -27,29 +11,12 @@ http {
include mime.types;
default_type application/octet-stream;
- gzip on;
- gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
-
- access_log /opt/bitnami/nginx/logs/proxy_access.log;
- error_log /opt/bitnami/nginx/logs/proxy_error.log;
-
- sendfile on;
- keepalive_timeout 180s;
- send_timeout 180s;
-
- client_body_temp_path /opt/bitnami/nginx/tmp/client_temp;
- proxy_temp_path /opt/bitnami/nginx/tmp/proxy_temp_path;
- fastcgi_temp_path /opt/bitnami/nginx/tmp/fastcgi_temp;
- uwsgi_temp_path /opt/bitnami/nginx/tmp/uwsgi_temp;
- scgi_temp_path /opt/bitnami/nginx/tmp/scgi_temp;
-
- proxy_buffering on;
- proxy_buffers 8 16k;
- proxy_buffer_size 16k;
- proxy_busy_buffers_size 64k;
- proxy_temp_file_write_size 64k;
- proxy_max_temp_file_size 1024m;
+ map $request_method $ratelimit_key {
+ POST $binary_remote_addr;
+ default "";
+ }
+ limit_req_zone $ratelimit_key zone=createFeed:10m rate=1r/m;
server {
listen 80;
@@ -57,12 +24,14 @@ http {
http2 on;
location /api/feed {
+ limit_req zone=createFeed nodelay;
proxy_pass http://htwkalender-ical:8091;
client_max_body_size 20m;
proxy_connect_timeout 600s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
+ limit_req_status 429;
}
location /api {
@@ -76,7 +45,6 @@ http {
location /_ {
proxy_pass http://htwkalender-data-manager:8090;
- # Increase upload file size
client_max_body_size 100m;
}
diff --git a/services/Makefile b/services/Makefile
new file mode 100644
index 0000000..1cf2ba8
--- /dev/null
+++ b/services/Makefile
@@ -0,0 +1,16 @@
+run-data-manager:
+ @go run data-manager/main.go serve
+
+run-ical:
+ @go run ical/main.go
+
+build-ical:
+ @go build ical/main.go
+
+gen:
+ @protoc \
+ --proto_path=protobuf "protobuf/*" \
+ --go_out="common/genproto/modules" \
+ --go_opt=paths=source_relative \
+ --go-grpc_out="common/genproto/modules" \
+ --go-grpc_opt=paths=source_relative
\ No newline at end of file
diff --git a/services/README.md b/services/README.md
new file mode 100644
index 0000000..c309315
--- /dev/null
+++ b/services/README.md
@@ -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
+```
diff --git a/services/common/genproto/modules/feeds.pb.go b/services/common/genproto/modules/feeds.pb.go
new file mode 100644
index 0000000..97aaa32
--- /dev/null
+++ b/services/common/genproto/modules/feeds.pb.go
@@ -0,0 +1,312 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc v5.27.1
+// source: feeds.proto
+
+package modules
+
+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 Feed struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ Modules string `protobuf:"bytes,2,opt,name=modules,proto3" json:"modules,omitempty"`
+ Retrieved string `protobuf:"bytes,3,opt,name=retrieved,proto3" json:"retrieved,omitempty"`
+ Created string `protobuf:"bytes,4,opt,name=created,proto3" json:"created,omitempty"`
+ Updated string `protobuf:"bytes,5,opt,name=updated,proto3" json:"updated,omitempty"`
+}
+
+func (x *Feed) Reset() {
+ *x = Feed{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_feeds_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Feed) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Feed) ProtoMessage() {}
+
+func (x *Feed) ProtoReflect() protoreflect.Message {
+ mi := &file_feeds_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 Feed.ProtoReflect.Descriptor instead.
+func (*Feed) Descriptor() ([]byte, []int) {
+ return file_feeds_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Feed) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+func (x *Feed) GetModules() string {
+ if x != nil {
+ return x.Modules
+ }
+ return ""
+}
+
+func (x *Feed) GetRetrieved() string {
+ if x != nil {
+ return x.Retrieved
+ }
+ return ""
+}
+
+func (x *Feed) GetCreated() string {
+ if x != nil {
+ return x.Created
+ }
+ return ""
+}
+
+func (x *Feed) GetUpdated() string {
+ if x != nil {
+ return x.Updated
+ }
+ return ""
+}
+
+type GetFeedRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+}
+
+func (x *GetFeedRequest) Reset() {
+ *x = GetFeedRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_feeds_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetFeedRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetFeedRequest) ProtoMessage() {}
+
+func (x *GetFeedRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_feeds_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 GetFeedRequest.ProtoReflect.Descriptor instead.
+func (*GetFeedRequest) Descriptor() ([]byte, []int) {
+ return file_feeds_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *GetFeedRequest) GetId() string {
+ if x != nil {
+ return x.Id
+ }
+ return ""
+}
+
+type GetFeedResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Feed *Feed `protobuf:"bytes,1,opt,name=feed,proto3" json:"feed,omitempty"`
+}
+
+func (x *GetFeedResponse) Reset() {
+ *x = GetFeedResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_feeds_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetFeedResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetFeedResponse) ProtoMessage() {}
+
+func (x *GetFeedResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_feeds_proto_msgTypes[2]
+ 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 GetFeedResponse.ProtoReflect.Descriptor instead.
+func (*GetFeedResponse) Descriptor() ([]byte, []int) {
+ return file_feeds_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *GetFeedResponse) GetFeed() *Feed {
+ if x != nil {
+ return x.Feed
+ }
+ return nil
+}
+
+var File_feeds_proto protoreflect.FileDescriptor
+
+var file_feeds_proto_rawDesc = []byte{
+ 0x0a, 0x0b, 0x66, 0x65, 0x65, 0x64, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01,
+ 0x0a, 0x04, 0x46, 0x65, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
+ 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x12, 0x18,
+ 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74,
+ 0x65, 0x64, 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x64, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x64, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x66, 0x65, 0x65, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x46, 0x65, 0x65, 0x64, 0x52, 0x04, 0x66, 0x65,
+ 0x65, 0x64, 0x32, 0x3d, 0x0a, 0x0b, 0x46, 0x65, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x64, 0x12, 0x0f, 0x2e, 0x47,
+ 0x65, 0x74, 0x46, 0x65, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e,
+ 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x64, 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 (
+ file_feeds_proto_rawDescOnce sync.Once
+ file_feeds_proto_rawDescData = file_feeds_proto_rawDesc
+)
+
+func file_feeds_proto_rawDescGZIP() []byte {
+ file_feeds_proto_rawDescOnce.Do(func() {
+ file_feeds_proto_rawDescData = protoimpl.X.CompressGZIP(file_feeds_proto_rawDescData)
+ })
+ return file_feeds_proto_rawDescData
+}
+
+var file_feeds_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_feeds_proto_goTypes = []interface{}{
+ (*Feed)(nil), // 0: Feed
+ (*GetFeedRequest)(nil), // 1: GetFeedRequest
+ (*GetFeedResponse)(nil), // 2: GetFeedResponse
+}
+var file_feeds_proto_depIdxs = []int32{
+ 0, // 0: GetFeedResponse.feed:type_name -> Feed
+ 1, // 1: FeedService.GetFeed:input_type -> GetFeedRequest
+ 2, // 2: FeedService.GetFeed:output_type -> GetFeedResponse
+ 2, // [2:3] is the sub-list for method output_type
+ 1, // [1:2] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_feeds_proto_init() }
+func file_feeds_proto_init() {
+ if File_feeds_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_feeds_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Feed); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_feeds_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetFeedRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_feeds_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetFeedResponse); 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_feeds_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 3,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_feeds_proto_goTypes,
+ DependencyIndexes: file_feeds_proto_depIdxs,
+ MessageInfos: file_feeds_proto_msgTypes,
+ }.Build()
+ File_feeds_proto = out.File
+ file_feeds_proto_rawDesc = nil
+ file_feeds_proto_goTypes = nil
+ file_feeds_proto_depIdxs = nil
+}
diff --git a/services/common/genproto/modules/feeds_grpc.pb.go b/services/common/genproto/modules/feeds_grpc.pb.go
new file mode 100644
index 0000000..10d1fc2
--- /dev/null
+++ b/services/common/genproto/modules/feeds_grpc.pb.go
@@ -0,0 +1,105 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc v5.27.1
+// source: feeds.proto
+
+package modules
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// FeedServiceClient is the client API for FeedService service.
+//
+// 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 FeedServiceClient interface {
+ GetFeed(ctx context.Context, in *GetFeedRequest, opts ...grpc.CallOption) (*GetFeedResponse, error)
+}
+
+type feedServiceClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewFeedServiceClient(cc grpc.ClientConnInterface) FeedServiceClient {
+ return &feedServiceClient{cc}
+}
+
+func (c *feedServiceClient) GetFeed(ctx context.Context, in *GetFeedRequest, opts ...grpc.CallOption) (*GetFeedResponse, error) {
+ out := new(GetFeedResponse)
+ err := c.cc.Invoke(ctx, "/FeedService/GetFeed", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// FeedServiceServer is the server API for FeedService service.
+// All implementations must embed UnimplementedFeedServiceServer
+// for forward compatibility
+type FeedServiceServer interface {
+ GetFeed(context.Context, *GetFeedRequest) (*GetFeedResponse, error)
+ mustEmbedUnimplementedFeedServiceServer()
+}
+
+// UnimplementedFeedServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedFeedServiceServer struct {
+}
+
+func (UnimplementedFeedServiceServer) GetFeed(context.Context, *GetFeedRequest) (*GetFeedResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetFeed not implemented")
+}
+func (UnimplementedFeedServiceServer) mustEmbedUnimplementedFeedServiceServer() {}
+
+// UnsafeFeedServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to FeedServiceServer will
+// result in compilation errors.
+type UnsafeFeedServiceServer interface {
+ mustEmbedUnimplementedFeedServiceServer()
+}
+
+func RegisterFeedServiceServer(s grpc.ServiceRegistrar, srv FeedServiceServer) {
+ s.RegisterService(&FeedService_ServiceDesc, srv)
+}
+
+func _FeedService_GetFeed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(GetFeedRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(FeedServiceServer).GetFeed(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/FeedService/GetFeed",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(FeedServiceServer).GetFeed(ctx, req.(*GetFeedRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// FeedService_ServiceDesc is the grpc.ServiceDesc for FeedService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var FeedService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "FeedService",
+ HandlerType: (*FeedServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "GetFeed",
+ Handler: _FeedService_GetFeed_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "feeds.proto",
+}
diff --git a/services/common/genproto/modules/modules.pb.go b/services/common/genproto/modules/modules.pb.go
new file mode 100644
index 0000000..3ce1b6b
--- /dev/null
+++ b/services/common/genproto/modules/modules.pb.go
@@ -0,0 +1,712 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.1
+// protoc v5.27.1
+// source: modules.proto
+
+package modules
+
+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 Event struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+ Day string `protobuf:"bytes,2,opt,name=day,proto3" json:"day,omitempty"`
+ Week string `protobuf:"bytes,3,opt,name=week,proto3" json:"week,omitempty"`
+ Start string `protobuf:"bytes,4,opt,name=start,proto3" json:"start,omitempty"`
+ End string `protobuf:"bytes,5,opt,name=end,proto3" json:"end,omitempty"`
+ Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
+ EventType string `protobuf:"bytes,7,opt,name=eventType,proto3" json:"eventType,omitempty"`
+ Compulsory string `protobuf:"bytes,8,opt,name=compulsory,proto3" json:"compulsory,omitempty"`
+ Prof string `protobuf:"bytes,9,opt,name=prof,proto3" json:"prof,omitempty"`
+ Rooms string `protobuf:"bytes,10,opt,name=rooms,proto3" json:"rooms,omitempty"`
+ Notes string `protobuf:"bytes,11,opt,name=notes,proto3" json:"notes,omitempty"`
+ BookedAt string `protobuf:"bytes,12,opt,name=bookedAt,proto3" json:"bookedAt,omitempty"`
+ Course string `protobuf:"bytes,13,opt,name=course,proto3" json:"course,omitempty"`
+ Semester string `protobuf:"bytes,14,opt,name=semester,proto3" json:"semester,omitempty"`
+}
+
+func (x *Event) Reset() {
+ *x = Event{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_modules_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Event) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Event) ProtoMessage() {}
+
+func (x *Event) ProtoReflect() protoreflect.Message {
+ mi := &file_modules_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 Event.ProtoReflect.Descriptor instead.
+func (*Event) Descriptor() ([]byte, []int) {
+ return file_modules_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Event) GetUuid() string {
+ if x != nil {
+ return x.Uuid
+ }
+ return ""
+}
+
+func (x *Event) GetDay() string {
+ if x != nil {
+ return x.Day
+ }
+ return ""
+}
+
+func (x *Event) GetWeek() string {
+ if x != nil {
+ return x.Week
+ }
+ return ""
+}
+
+func (x *Event) GetStart() string {
+ if x != nil {
+ return x.Start
+ }
+ return ""
+}
+
+func (x *Event) GetEnd() string {
+ if x != nil {
+ return x.End
+ }
+ return ""
+}
+
+func (x *Event) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *Event) GetEventType() string {
+ if x != nil {
+ return x.EventType
+ }
+ return ""
+}
+
+func (x *Event) GetCompulsory() string {
+ if x != nil {
+ return x.Compulsory
+ }
+ return ""
+}
+
+func (x *Event) GetProf() string {
+ if x != nil {
+ return x.Prof
+ }
+ return ""
+}
+
+func (x *Event) GetRooms() string {
+ if x != nil {
+ return x.Rooms
+ }
+ return ""
+}
+
+func (x *Event) GetNotes() string {
+ if x != nil {
+ return x.Notes
+ }
+ return ""
+}
+
+func (x *Event) GetBookedAt() string {
+ if x != nil {
+ return x.BookedAt
+ }
+ return ""
+}
+
+func (x *Event) GetCourse() string {
+ if x != nil {
+ return x.Course
+ }
+ return ""
+}
+
+func (x *Event) GetSemester() string {
+ if x != nil {
+ return x.Semester
+ }
+ return ""
+}
+
+type Module struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ Prof string `protobuf:"bytes,3,opt,name=prof,proto3" json:"prof,omitempty"`
+ Course string `protobuf:"bytes,4,opt,name=course,proto3" json:"course,omitempty"`
+ Semester string `protobuf:"bytes,5,opt,name=semester,proto3" json:"semester,omitempty"`
+ Events []*Event `protobuf:"bytes,6,rep,name=events,proto3" json:"events,omitempty"`
+}
+
+func (x *Module) Reset() {
+ *x = Module{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_modules_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Module) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Module) ProtoMessage() {}
+
+func (x *Module) ProtoReflect() protoreflect.Message {
+ mi := &file_modules_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 Module.ProtoReflect.Descriptor instead.
+func (*Module) Descriptor() ([]byte, []int) {
+ return file_modules_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Module) GetUuid() string {
+ if x != nil {
+ return x.Uuid
+ }
+ return ""
+}
+
+func (x *Module) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
+}
+
+func (x *Module) GetProf() string {
+ if x != nil {
+ return x.Prof
+ }
+ return ""
+}
+
+func (x *Module) GetCourse() string {
+ if x != nil {
+ return x.Course
+ }
+ return ""
+}
+
+func (x *Module) GetSemester() string {
+ if x != nil {
+ return x.Semester
+ }
+ return ""
+}
+
+func (x *Module) GetEvents() []*Event {
+ if x != nil {
+ return x.Events
+ }
+ return nil
+}
+
+type GetModuleRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+}
+
+func (x *GetModuleRequest) Reset() {
+ *x = GetModuleRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_modules_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetModuleRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetModuleRequest) ProtoMessage() {}
+
+func (x *GetModuleRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_modules_proto_msgTypes[2]
+ 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 GetModuleRequest.ProtoReflect.Descriptor instead.
+func (*GetModuleRequest) Descriptor() ([]byte, []int) {
+ return file_modules_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *GetModuleRequest) GetUuid() string {
+ if x != nil {
+ return x.Uuid
+ }
+ 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 {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Module *Module `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"`
+}
+
+func (x *GetModuleResponse) Reset() {
+ *x = GetModuleResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_modules_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *GetModuleResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetModuleResponse) ProtoMessage() {}
+
+func (x *GetModuleResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_modules_proto_msgTypes[4]
+ 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 GetModuleResponse.ProtoReflect.Descriptor instead.
+func (*GetModuleResponse) Descriptor() ([]byte, []int) {
+ return file_modules_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *GetModuleResponse) GetModule() *Module {
+ if x != nil {
+ return x.Module
+ }
+ 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_rawDesc = []byte{
+ 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0xcb, 0x02, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a,
+ 0x03, 0x64, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x61, 0x79, 0x12,
+ 0x12, 0x0a, 0x04, 0x77, 0x65, 0x65, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x77,
+ 0x65, 0x65, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+ 0x1c, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a,
+ 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x6c, 0x73, 0x6f, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x6c, 0x73, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a,
+ 0x04, 0x70, 0x72, 0x6f, 0x66, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x72, 0x6f,
+ 0x66, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73,
+ 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a,
+ 0x08, 0x62, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x08, 0x62, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x75,
+ 0x72, 0x73, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x72, 0x73,
+ 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0e, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x72, 0x22, 0x98, 0x01,
+ 0x0a, 0x06, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x12, 0x0a, 0x04, 0x70, 0x72, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+ 0x70, 0x72, 0x6f, 0x66, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08,
+ 0x73, 0x65, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
+ 0x73, 0x65, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e,
+ 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x06, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74,
+ 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,
+ 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64,
+ 0x22, 0x29, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65,
+ 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x75, 0x69, 0x64, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x75, 0x75, 0x69, 0x64, 0x73, 0x22, 0x34, 0x0a, 0x11, 0x47,
+ 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+ 0x12, 0x1f, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x07, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x22, 0x37, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x33, 0x0a, 0x11, 0x47, 0x65,
+ 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 (
+ file_modules_proto_rawDescOnce sync.Once
+ file_modules_proto_rawDescData = file_modules_proto_rawDesc
+)
+
+func file_modules_proto_rawDescGZIP() []byte {
+ file_modules_proto_rawDescOnce.Do(func() {
+ file_modules_proto_rawDescData = protoimpl.X.CompressGZIP(file_modules_proto_rawDescData)
+ })
+ return file_modules_proto_rawDescData
+}
+
+var file_modules_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
+var file_modules_proto_goTypes = []interface{}{
+ (*Event)(nil), // 0: Event
+ (*Module)(nil), // 1: Module
+ (*GetModuleRequest)(nil), // 2: GetModuleRequest
+ (*GetModulesRequest)(nil), // 3: GetModulesRequest
+ (*GetModuleResponse)(nil), // 4: GetModuleResponse
+ (*GetModulesResponse)(nil), // 5: GetModulesResponse
+ (*GetEventsResponse)(nil), // 6: GetEventsResponse
+}
+var file_modules_proto_depIdxs = []int32{
+ 0, // 0: Module.events:type_name -> Event
+ 1, // 1: GetModuleResponse.module:type_name -> Module
+ 1, // 2: GetModulesResponse.modules:type_name -> Module
+ 0, // 3: GetEventsResponse.events:type_name -> Event
+ 2, // 4: ModuleService.GetModule:input_type -> GetModuleRequest
+ 3, // 5: ModuleService.GetModules:input_type -> GetModulesRequest
+ 3, // 6: ModuleService.GetEventsForModules:input_type -> GetModulesRequest
+ 4, // 7: ModuleService.GetModule:output_type -> GetModuleResponse
+ 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 file_modules_proto_init() {
+ if File_modules_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_modules_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Event); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_modules_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Module); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_modules_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*GetModuleRequest); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ 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 {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ 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{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_modules_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 7,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_modules_proto_goTypes,
+ DependencyIndexes: file_modules_proto_depIdxs,
+ MessageInfos: file_modules_proto_msgTypes,
+ }.Build()
+ File_modules_proto = out.File
+ file_modules_proto_rawDesc = nil
+ file_modules_proto_goTypes = nil
+ file_modules_proto_depIdxs = nil
+}
diff --git a/services/common/genproto/modules/modules_grpc.pb.go b/services/common/genproto/modules/modules_grpc.pb.go
new file mode 100644
index 0000000..5c6a689
--- /dev/null
+++ b/services/common/genproto/modules/modules_grpc.pb.go
@@ -0,0 +1,177 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc v5.27.1
+// source: modules.proto
+
+package modules
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// ModuleServiceClient is the client API for ModuleService service.
+//
+// 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 {
+ 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 {
+ cc grpc.ClientConnInterface
+}
+
+func NewModuleServiceClient(cc grpc.ClientConnInterface) ModuleServiceClient {
+ return &moduleServiceClient{cc}
+}
+
+func (c *moduleServiceClient) GetModule(ctx context.Context, in *GetModuleRequest, opts ...grpc.CallOption) (*GetModuleResponse, error) {
+ out := new(GetModuleResponse)
+ err := c.cc.Invoke(ctx, "/ModuleService/GetModule", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ 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.
+// All implementations must embed UnimplementedModuleServiceServer
+// for forward compatibility
+type ModuleServiceServer interface {
+ GetModule(context.Context, *GetModuleRequest) (*GetModuleResponse, error)
+ GetModules(context.Context, *GetModulesRequest) (*GetModulesResponse, error)
+ GetEventsForModules(context.Context, *GetModulesRequest) (*GetEventsResponse, error)
+ mustEmbedUnimplementedModuleServiceServer()
+}
+
+// UnimplementedModuleServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedModuleServiceServer struct {
+}
+
+func (UnimplementedModuleServiceServer) GetModule(context.Context, *GetModuleRequest) (*GetModuleResponse, error) {
+ 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() {}
+
+// UnsafeModuleServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to ModuleServiceServer will
+// result in compilation errors.
+type UnsafeModuleServiceServer interface {
+ mustEmbedUnimplementedModuleServiceServer()
+}
+
+func RegisterModuleServiceServer(s grpc.ServiceRegistrar, srv ModuleServiceServer) {
+ s.RegisterService(&ModuleService_ServiceDesc, srv)
+}
+
+func _ModuleService_GetModule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(GetModuleRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(ModuleServiceServer).GetModule(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/ModuleService/GetModule",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(ModuleServiceServer).GetModule(ctx, req.(*GetModuleRequest))
+ }
+ 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.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var ModuleService_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "ModuleService",
+ HandlerType: (*ModuleServiceServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "GetModule",
+ Handler: _ModuleService_GetModule_Handler,
+ },
+ {
+ MethodName: "GetModules",
+ Handler: _ModuleService_GetModules_Handler,
+ },
+ {
+ MethodName: "GetEventsForModules",
+ Handler: _ModuleService_GetEventsForModules_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "modules.proto",
+}
diff --git a/services/data-manager/Dockerfile b/services/data-manager/Dockerfile
index 35dd5c8..f1bcae8 100644
--- a/services/data-manager/Dockerfile
+++ b/services/data-manager/Dockerfile
@@ -17,14 +17,16 @@
# build stage
FROM golang:alpine AS build
-WORKDIR /app
+WORKDIR /htwkalender-data-manager
+RUN apk add --no-cache --update go gcc g++
# Copy the source from the current directory to the Working Directory inside the container
-COPY . ./
-# download needed modules
-RUN apk add --no-cache --update go gcc g++ && \
- go mod download && \
- CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-data-manager
+COPY go.mod go.sum ./
+RUN go mod download
+
+COPY data-manager/. ./data-manager
+COPY common/. ./common
+RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-data-manager data-manager/main.go
# production stage
FROM alpine:latest AS prod
@@ -44,7 +46,7 @@ COPY --chown=$USER:$USER --from=build /htwkalender-data-manager ./
# Expose port 8090 to the outside world
EXPOSE 8090
-ENTRYPOINT ["./htwkalender-data-manager", "serve"]
+ENTRYPOINT ["./main", "serve"]
FROM golang:1.21.6 AS dev
@@ -57,14 +59,14 @@ COPY go.mod go.sum ./
RUN go mod download
# Copy the source from the current directory to the Working Directory inside the container
-COPY *.go ./
-COPY . .
+COPY data-manager/. ./data-manager
+COPY common/. ./common
# Build the Go app
-RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-data-manager
+RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-data-manager data-manager/main.go
-# Expose port 8090 to the outside world
-EXPOSE 8090
+# Expose port 8091 to the outside world
+EXPOSE 8091
# Entry point
-ENTRYPOINT ["./htwkalender-data-manager", "serve"]
\ No newline at end of file
+ENTRYPOINT ["./main", "serve"]
\ No newline at end of file
diff --git a/services/data-manager/go.mod b/services/data-manager/go.mod
deleted file mode 100644
index 7a92cc2..0000000
--- a/services/data-manager/go.mod
+++ /dev/null
@@ -1,93 +0,0 @@
-module htwkalender
-
-go 1.21
-
-require (
- github.com/PuerkitoBio/goquery v1.8.1
- github.com/google/uuid v1.5.0
- github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0
- github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
- github.com/pocketbase/dbx v1.10.1
- github.com/pocketbase/pocketbase v0.20.5
- golang.org/x/net v0.20.0
-)
-
-require (
- github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
- github.com/andybalholm/cascadia v1.3.2 // indirect
- github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
- github.com/aws/aws-sdk-go v1.49.20 // indirect
- github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
- github.com/aws/aws-sdk-go-v2/config v1.26.3 // indirect
- github.com/aws/aws-sdk-go-v2/credentials v1.16.14 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
- github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.11 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
- github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect
- github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10 // indirect
- github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.18.6 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.6 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
- github.com/aws/smithy-go v1.19.0 // indirect
- github.com/disintegration/imaging v1.6.2 // indirect
- github.com/domodwyer/mailyak/v3 v3.6.2 // indirect
- github.com/dustin/go-humanize v1.0.1 // indirect
- github.com/fatih/color v1.16.0 // indirect
- github.com/gabriel-vasile/mimetype v1.4.3 // indirect
- github.com/ganigeorgiev/fexpr v0.4.0 // indirect
- github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
- github.com/goccy/go-json v0.10.2 // indirect
- github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
- github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/google/wire v0.5.0 // indirect
- github.com/googleapis/gax-go/v2 v2.12.0 // indirect
- github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/jmespath/go-jmespath v0.4.0 // indirect
- github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/mattn/go-sqlite3 v1.14.19 // indirect
- github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
- github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
- github.com/spf13/cast v1.6.0 // indirect
- github.com/spf13/cobra v1.8.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.2 // indirect
- go.opencensus.io v0.24.0 // indirect
- gocloud.dev v0.36.0 // indirect
- golang.org/x/crypto v0.18.0 // indirect
- golang.org/x/image v0.14.0 // indirect
- golang.org/x/mod v0.14.0 // indirect
- golang.org/x/oauth2 v0.15.0 // indirect
- golang.org/x/sync v0.5.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
- golang.org/x/term v0.16.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/time v0.5.0 // indirect
- golang.org/x/tools v0.16.0 // indirect
- golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
- google.golang.org/api v0.153.0 // indirect
- google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
- google.golang.org/grpc v1.59.0 // indirect
- google.golang.org/protobuf v1.32.0 // indirect
- lukechampine.com/uint128 v1.3.0 // indirect
- modernc.org/cc/v3 v3.41.0 // indirect
- modernc.org/ccgo/v3 v3.16.15 // indirect
- modernc.org/libc v1.37.0 // indirect
- modernc.org/mathutil v1.6.0 // indirect
- modernc.org/memory v1.7.2 // indirect
- modernc.org/opt v0.1.3 // indirect
- modernc.org/sqlite v1.27.0 // indirect
- modernc.org/strutil v1.2.0 // indirect
- modernc.org/token v1.1.0 // indirect
-)
diff --git a/services/data-manager/go.sum b/services/data-manager/go.sum
deleted file mode 100644
index ad5fe1f..0000000
--- a/services/data-manager/go.sum
+++ /dev/null
@@ -1,385 +0,0 @@
-cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y=
-cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic=
-cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
-cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
-cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
-cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
-cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
-cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
-cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
-cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
-github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
-github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
-github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
-github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
-github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
-github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
-github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
-github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
-github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
-github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
-github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
-github.com/aws/aws-sdk-go v1.49.20 h1:VgEUq2/ZbUkLbqPyDcxrirfXB+PgiZUUF5XbsgWe2S0=
-github.com/aws/aws-sdk-go v1.49.20/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
-github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU=
-github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs=
-github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo=
-github.com/aws/aws-sdk-go-v2/config v1.26.3 h1:dKuc2jdp10y13dEEvPqWxqLoc0vF3Z9FC45MvuQSxOA=
-github.com/aws/aws-sdk-go-v2/config v1.26.3/go.mod h1:Bxgi+DeeswYofcYO0XyGClwlrq3DZEXli0kLf4hkGA0=
-github.com/aws/aws-sdk-go-v2/credentials v1.16.14 h1:mMDTwwYO9A0/JbOCOG7EOZHtYM+o7OfGWfu0toa23VE=
-github.com/aws/aws-sdk-go-v2/credentials v1.16.14/go.mod h1:cniAUh3ErQPHtCQGPT5ouvSAQ0od8caTO9OOuufZOAE=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y=
-github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.11 h1:I6lAa3wBWfCz/cKkOpAcumsETRkFAl70sWi8ItcMEsM=
-github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.11/go.mod h1:be1NIO30kJA23ORBLqPo1LttEM6tPNSEcjkd1eKzNW0=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 h1:5oE2WzJE56/mVveuDZPJESKlg/00AaS2pY2QZcnxg4M=
-github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10/go.mod h1:FHbKWQtRBYUz4vO5WBWjzMD2by126ny5y/1EoaWoLfI=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10 h1:L0ai8WICYHozIKK+OtPzVJBugL7culcuM4E4JOpIEm8=
-github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10/go.mod h1:byqfyxJBshFk0fF9YmK0M0ugIO8OWjzH2T3bPG4eGuA=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10 h1:KOxnQeWy5sXyS37fdKEvAsGHOr9fa/qvwxfJurR/BzE=
-github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10/go.mod h1:jMx5INQFYFYB3lQD9W0D8Ohgq6Wnl7NYOJ2TQndbulI=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0 h1:PJTdBMsyvra6FtED7JZtDpQrIAflYDHFoZAu/sKYkwU=
-github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0/go.mod h1:4qXHrG1Ne3VGIMZPCB8OjH/pLFO94sKABIusjh0KWPU=
-github.com/aws/aws-sdk-go-v2/service/sso v1.18.6 h1:dGrs+Q/WzhsiUKh82SfTVN66QzyulXuMDTV/G8ZxOac=
-github.com/aws/aws-sdk-go-v2/service/sso v1.18.6/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.6 h1:Yf2MIo9x+0tyv76GljxzqA3WtC5mw7NmazD2chwjxE4=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.6/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8=
-github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0=
-github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U=
-github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
-github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
-github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
-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/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
-github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
-github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8=
-github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
-github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
-github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
-github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
-github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
-github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
-github.com/ganigeorgiev/fexpr v0.4.0 h1:ojitI+VMNZX/odeNL1x3RzTTE8qAIVvnSSYPNAnQFDI=
-github.com/ganigeorgiev/fexpr v0.4.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
-github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
-github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
-github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
-github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
-github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
-github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
-github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
-github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
-github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk=
-github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg=
-github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
-github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
-github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
-github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
-github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
-github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
-github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
-github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
-github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
-github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
-github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
-github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
-github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
-github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
-github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
-github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
-github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
-github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
-github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
-github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
-github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
-github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0 h1:p+k2RozdR141dIkAbOuZafkZjrcjT/YvwYYH7qCSG+c=
-github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0/go.mod h1:YHaw6sOIeFRob8Y9q/blEAMfVcLpeE9+vdhrwyEMxoI=
-github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
-github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
-github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
-github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 h1:FwuzbVh87iLiUQj1+uQUsuw9x5t9m5n5g7rG7o4svW4=
-github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61/go.mod h1:paQfF1YtHe+GrGg5fOgjsjoCX/UKDr9bc1DoWpZfns8=
-github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
-github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
-github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
-github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
-github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
-github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
-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/pocketbase/dbx v1.10.1 h1:cw+vsyfCJD8YObOVeqb93YErnlxwYMkNZ4rwN0G0AaA=
-github.com/pocketbase/dbx v1.10.1/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
-github.com/pocketbase/pocketbase v0.20.5 h1:unrGe6MG/D2AQDjjdcyh1WrbXI10wWe1gFcGdG/yaNU=
-github.com/pocketbase/pocketbase v0.20.5/go.mod h1:uy7WOxXoICrwe8HlyR78vTvK0RdG5REkhDx4SvYi4FY=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
-github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
-github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
-github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
-github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
-github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
-github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
-go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-gocloud.dev v0.36.0 h1:q5zoXux4xkOZP473e1EZbG8Gq9f0vlg1VNH5Du/ybus=
-gocloud.dev v0.36.0/go.mod h1:bLxah6JQVKBaIxzsr5BQLYB4IYdWHkMZdzCXlo6F0gg=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
-golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
-golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
-golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
-golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
-golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
-golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
-golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
-golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
-golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
-golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
-golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
-golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
-golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
-google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4=
-google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY=
-google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
-google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f h1:Vn+VyHU5guc9KjB5KrjI2q0wCOWEOIh0OEsleqakHJg=
-google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f/go.mod h1:nWSwAFPb+qfNJXsoeO3Io7zf4tMSfN8EA8RlDA04GhY=
-google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY=
-google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
-google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
-lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
-modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q=
-modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y=
-modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0=
-modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI=
-modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
-modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
-modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
-modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
-modernc.org/libc v1.37.0 h1:WerjebcsP6A7Jy+f2lCnHAkiSTLf7IaSftBYUtoswak=
-modernc.org/libc v1.37.0/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
-modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
-modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
-modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
-modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
-modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
-modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
-modernc.org/sqlite v1.27.0 h1:MpKAHoyYB7xqcwnUwkuD+npwEa0fojF0B5QRbN+auJ8=
-modernc.org/sqlite v1.27.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
-modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
-modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
-modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
-modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c=
-modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
-modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
-modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
-modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=
diff --git a/services/data-manager/main.go b/services/data-manager/main.go
index 8b78ba1..c49c157 100644
--- a/services/data-manager/main.go
+++ b/services/data-manager/main.go
@@ -19,8 +19,9 @@ package main
import (
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/plugins/migratecmd"
- _ "htwkalender/migrations"
- "htwkalender/service"
+ _ "htwkalender/data-manager/migrations"
+ "htwkalender/data-manager/service"
+ "htwkalender/data-manager/service/grpc"
"log/slog"
"os"
"strings"
@@ -32,6 +33,9 @@ func main() {
// loosely check if it was executed using "go run"
isGoRun := strings.HasPrefix(os.Args[0], os.TempDir())
+ //start grpc server
+ go grpc.StartGRPCServer(app)
+
migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{
// enable auto creation of migration files when making collection changes in the Admin UI
// (the isGoRun check is to enable it only during development)
@@ -43,4 +47,5 @@ func main() {
if err := app.Start(); err != nil {
slog.Error("Failed to start app: ", "error", err)
}
+
}
diff --git a/services/data-manager/service/addCalDavRoutes.go b/services/data-manager/service/addCalDavRoutes.go
index 9aae82f..f487031 100644
--- a/services/data-manager/service/addCalDavRoutes.go
+++ b/services/data-manager/service/addCalDavRoutes.go
@@ -21,8 +21,8 @@ import (
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core"
- "htwkalender/service/db"
- "htwkalender/service/ical"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/ical"
"io"
"log/slog"
"net/http"
diff --git a/services/data-manager/service/addRoute.go b/services/data-manager/service/addRoute.go
index 0f131bf..8dadd40 100644
--- a/services/data-manager/service/addRoute.go
+++ b/services/data-manager/service/addRoute.go
@@ -17,13 +17,13 @@
package service
import (
- "htwkalender/service/course"
- "htwkalender/service/events"
- "htwkalender/service/fetch/sport"
- v1 "htwkalender/service/fetch/v1"
- v2 "htwkalender/service/fetch/v2"
- "htwkalender/service/functions/time"
- "htwkalender/service/room"
+ "htwkalender/data-manager/service/course"
+ "htwkalender/data-manager/service/events"
+ "htwkalender/data-manager/service/fetch/sport"
+ v1 "htwkalender/data-manager/service/fetch/v1"
+ v2 "htwkalender/data-manager/service/fetch/v2"
+ "htwkalender/data-manager/service/functions/time"
+ "htwkalender/data-manager/service/room"
"log/slog"
"net/http"
diff --git a/services/data-manager/service/addSchedule.go b/services/data-manager/service/addSchedule.go
index 9d2b901..c24f2e1 100644
--- a/services/data-manager/service/addSchedule.go
+++ b/services/data-manager/service/addSchedule.go
@@ -20,12 +20,12 @@ import (
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/cron"
- "htwkalender/service/course"
- "htwkalender/service/feed"
- "htwkalender/service/fetch/sport"
- v1 "htwkalender/service/fetch/v1"
- v2 "htwkalender/service/fetch/v2"
- "htwkalender/service/functions/time"
+ "htwkalender/data-manager/service/course"
+ "htwkalender/data-manager/service/feed"
+ "htwkalender/data-manager/service/fetch/sport"
+ v1 "htwkalender/data-manager/service/fetch/v1"
+ v2 "htwkalender/data-manager/service/fetch/v2"
+ "htwkalender/data-manager/service/functions/time"
"log/slog"
"strconv"
)
diff --git a/services/data-manager/service/course/courseFunctions.go b/services/data-manager/service/course/courseFunctions.go
index d51ad00..0612d97 100644
--- a/services/data-manager/service/course/courseFunctions.go
+++ b/services/data-manager/service/course/courseFunctions.go
@@ -18,7 +18,7 @@ package course
import (
"github.com/pocketbase/pocketbase"
- "htwkalender/service/events"
+ "htwkalender/data-manager/service/events"
"log/slog"
)
diff --git a/services/data-manager/service/db/dbEvents.go b/services/data-manager/service/db/dbEvents.go
index 8c971f4..7c7c174 100644
--- a/services/data-manager/service/db/dbEvents.go
+++ b/services/data-manager/service/db/dbEvents.go
@@ -18,9 +18,10 @@ package db
import (
"fmt"
+ "github.com/google/uuid"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/tools/types"
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"log/slog"
"time"
@@ -131,25 +132,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 {
+ err := uuid.Validate(moduleUuid)
+ if err != nil {
+ slog.Warn("Module UUID is not safe: ", "moduleUuid", moduleUuid)
+ return dbx.HashExp{}
+ }
+ }
// build where conditions for each module
//first check if modules is empty
- if len(modules) == 0 {
+ if len(modulesUuid) == 0 {
return dbx.HashExp{}
}
//second check if modules has only one element
- if len(modules) == 1 {
- return dbx.HashExp{"uuid": modules[0].UUID}
+ if len(modulesUuid) == 1 {
+ return dbx.HashExp{"uuid": modulesUuid[0]}
}
//third check if modules has more than one element
var wheres []dbx.Expression
- for _, module := range modules {
- where := dbx.HashExp{"uuid": module.UUID}
+ for _, moduleUuid := range modulesUuid {
+ where := dbx.HashExp{"uuid": moduleUuid}
wheres = append(wheres, where)
}
@@ -162,23 +175,18 @@ func buildIcalQueryForModules(modules []model.FeedCollection) dbx.Expression {
// GetPlanForModules returns all events for the given modules with the given course
// 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
- modulesArray := make([]model.FeedCollection, 0, len(modules))
- for _, value := range modules {
- modulesArray = append(modulesArray, value)
- }
-
// iterate over modules in 100 batch sizes
for i := 0; i < len(modules); i += 100 {
- var moduleBatch []model.FeedCollection
+ var moduleBatch []string
if i+100 > len(modules) {
- moduleBatch = modulesArray[i:]
+ moduleBatch = modules[i:]
} else {
- moduleBatch = modulesArray[i : i+100]
+ moduleBatch = modules[i : i+100]
}
var selectedModulesQuery = buildIcalQueryForModules(moduleBatch)
diff --git a/services/data-manager/service/db/dbEvents_test.go b/services/data-manager/service/db/dbEvents_test.go
index 20505a6..8708394 100644
--- a/services/data-manager/service/db/dbEvents_test.go
+++ b/services/data-manager/service/db/dbEvents_test.go
@@ -18,14 +18,13 @@ package db
import (
"github.com/pocketbase/dbx"
- "htwkalender/model"
"reflect"
"testing"
)
func Test_buildIcalQueryForModules(t *testing.T) {
type args struct {
- modules []model.FeedCollection
+ modules []string
}
tests := []struct {
name string
@@ -34,18 +33,18 @@ func Test_buildIcalQueryForModules(t *testing.T) {
}{
{
name: "empty modules",
- args: args{modules: []model.FeedCollection{}},
+ args: args{modules: []string{}},
want: dbx.HashExp{},
},
{
name: "one module",
- args: args{modules: []model.FeedCollection{{Name: "test", Course: "test", UUID: "test"}}},
- want: dbx.HashExp{"uuid": "test"},
+ args: args{modules: []string{"77eddc32-c49d-5d0a-8c36-17b266396641"}},
+ want: dbx.HashExp{"uuid": "77eddc32-c49d-5d0a-8c36-17b266396641"},
},
{
name: "two modules",
- args: args{modules: []model.FeedCollection{{Name: "test", Course: "test", UUID: "test"}, {Name: "test2", Course: "test2", UUID: "test2"}}},
- want: dbx.Or(dbx.HashExp{"uuid": "test"}, dbx.HashExp{"uuid": "test2"}),
+ args: args{modules: []string{"9e5081e6-4c56-57b9-9965-f6dc74559755", "48cd8c4e-fb70-595c-9dfb-7035f56326d9"}},
+ want: dbx.Or(dbx.HashExp{"uuid": "9e5081e6-4c56-57b9-9965-f6dc74559755"}, dbx.HashExp{"uuid": "48cd8c4e-fb70-595c-9dfb-7035f56326d9"}),
},
}
for _, tt := range tests {
diff --git a/services/data-manager/service/db/dbFeeds.go b/services/data-manager/service/db/dbFeeds.go
index 49ea58b..2ae46e1 100644
--- a/services/data-manager/service/db/dbFeeds.go
+++ b/services/data-manager/service/db/dbFeeds.go
@@ -22,7 +22,7 @@ import (
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"time"
)
@@ -37,7 +37,7 @@ func SaveFeed(feed model.Feed, collection *models.Collection, app *pocketbase.Po
return record, nil
}
-func FindFeedByToken(token string, app *pocketbase.PocketBase) (*model.Feed, error) {
+func FindFeedByToken(app *pocketbase.PocketBase, token string) (*model.Feed, error) {
record, err := app.Dao().FindRecordById("feeds", token)
diff --git a/services/data-manager/service/db/dbGroups.go b/services/data-manager/service/db/dbGroups.go
index 1e5d02c..f4776c3 100644
--- a/services/data-manager/service/db/dbGroups.go
+++ b/services/data-manager/service/db/dbGroups.go
@@ -20,7 +20,7 @@ import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/models"
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"log/slog"
)
diff --git a/services/data-manager/service/db/dbRooms.go b/services/data-manager/service/db/dbRooms.go
index f89bbdc..45564c1 100644
--- a/services/data-manager/service/db/dbRooms.go
+++ b/services/data-manager/service/db/dbRooms.go
@@ -17,8 +17,8 @@
package db
import (
- "htwkalender/model"
- "htwkalender/service/functions"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/functions"
"strings"
"time"
diff --git a/services/data-manager/service/events/courseService.go b/services/data-manager/service/events/courseService.go
index 308e049..389a428 100644
--- a/services/data-manager/service/events/courseService.go
+++ b/services/data-manager/service/events/courseService.go
@@ -18,8 +18,8 @@ package events
import (
"github.com/pocketbase/pocketbase"
- "htwkalender/service/db"
- "htwkalender/service/functions"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/functions"
)
func GetAllCourses(app *pocketbase.PocketBase) []string {
diff --git a/services/data-manager/service/events/eventService.go b/services/data-manager/service/events/eventService.go
index c9184c5..383640c 100644
--- a/services/data-manager/service/events/eventService.go
+++ b/services/data-manager/service/events/eventService.go
@@ -18,10 +18,10 @@ package events
import (
"github.com/pocketbase/pocketbase"
- "htwkalender/model"
- "htwkalender/service/db"
- "htwkalender/service/fetch/v1"
- "htwkalender/service/functions"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/fetch/v1"
+ "htwkalender/data-manager/service/functions"
"log/slog"
"strconv"
)
diff --git a/services/data-manager/service/events/eventService_test.go b/services/data-manager/service/events/eventService_test.go
index 6c5c23e..e4f7b68 100644
--- a/services/data-manager/service/events/eventService_test.go
+++ b/services/data-manager/service/events/eventService_test.go
@@ -1,7 +1,7 @@
package events
import (
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"testing"
)
diff --git a/services/data-manager/service/feed/feedFunctions.go b/services/data-manager/service/feed/feedFunctions.go
index 894f322..6c3da36 100644
--- a/services/data-manager/service/feed/feedFunctions.go
+++ b/services/data-manager/service/feed/feedFunctions.go
@@ -20,9 +20,9 @@ import (
"database/sql"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
- "htwkalender/model"
- database "htwkalender/service/db"
- localTime "htwkalender/service/functions/time"
+ "htwkalender/data-manager/model"
+ database "htwkalender/data-manager/service/db"
+ localTime "htwkalender/data-manager/service/functions/time"
"log/slog"
"strings"
)
diff --git a/services/data-manager/service/feed/feedFunctions_test.go b/services/data-manager/service/feed/feedFunctions_test.go
index e35f3f8..53286ba 100644
--- a/services/data-manager/service/feed/feedFunctions_test.go
+++ b/services/data-manager/service/feed/feedFunctions_test.go
@@ -19,8 +19,8 @@ package feed
import (
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/tests"
- "htwkalender/model"
- mockTime "htwkalender/service/functions/time"
+ "htwkalender/data-manager/model"
+ mockTime "htwkalender/data-manager/service/functions/time"
"reflect"
"testing"
"time"
diff --git a/services/data-manager/service/fetch/sport/sportFetcher.go b/services/data-manager/service/fetch/sport/sportFetcher.go
index 4cb619c..93ecdfc 100644
--- a/services/data-manager/service/fetch/sport/sportFetcher.go
+++ b/services/data-manager/service/fetch/sport/sportFetcher.go
@@ -21,10 +21,10 @@ import (
"github.com/google/uuid"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/tools/types"
- "htwkalender/model"
- "htwkalender/service/db"
- "htwkalender/service/functions"
- clock "htwkalender/service/functions/time"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/functions"
+ clock "htwkalender/data-manager/service/functions/time"
"io"
"log/slog"
"net/http"
diff --git a/services/data-manager/service/fetch/v1/fetchSeminarEventService.go b/services/data-manager/service/fetch/v1/fetchSeminarEventService.go
index ca02906..4f3679d 100644
--- a/services/data-manager/service/fetch/v1/fetchSeminarEventService.go
+++ b/services/data-manager/service/fetch/v1/fetchSeminarEventService.go
@@ -21,10 +21,10 @@ import (
"github.com/google/uuid"
"github.com/pocketbase/pocketbase/tools/types"
"golang.org/x/net/html"
- "htwkalender/model"
- "htwkalender/service/date"
- "htwkalender/service/fetch"
- "htwkalender/service/functions"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/date"
+ "htwkalender/data-manager/service/fetch"
+ "htwkalender/data-manager/service/functions"
"log/slog"
"regexp"
"strconv"
diff --git a/services/data-manager/service/fetch/v1/fetchSeminarEventService_test.go b/services/data-manager/service/fetch/v1/fetchSeminarEventService_test.go
index a5c103b..10b55cd 100644
--- a/services/data-manager/service/fetch/v1/fetchSeminarEventService_test.go
+++ b/services/data-manager/service/fetch/v1/fetchSeminarEventService_test.go
@@ -19,7 +19,7 @@ package v1
import (
"fmt"
"github.com/pocketbase/pocketbase/tools/types"
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"reflect"
"testing"
"time"
diff --git a/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go b/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go
index 9e909e5..32cfff0 100644
--- a/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go
+++ b/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go
@@ -21,10 +21,10 @@ import (
"fmt"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/models"
- "htwkalender/model"
- "htwkalender/service/db"
- "htwkalender/service/functions"
- "htwkalender/service/functions/time"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/functions"
+ "htwkalender/data-manager/service/functions/time"
"io"
"log/slog"
"net/http"
diff --git a/services/data-manager/service/fetch/v1/fetchSeminarGroupService_test.go b/services/data-manager/service/fetch/v1/fetchSeminarGroupService_test.go
index 16cdee0..6c2cfbe 100644
--- a/services/data-manager/service/fetch/v1/fetchSeminarGroupService_test.go
+++ b/services/data-manager/service/fetch/v1/fetchSeminarGroupService_test.go
@@ -17,7 +17,7 @@
package v1
import (
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"testing"
)
diff --git a/services/data-manager/service/fetch/v2/eventParser.go b/services/data-manager/service/fetch/v2/eventParser.go
index 94eafe2..3482bd7 100644
--- a/services/data-manager/service/fetch/v2/eventParser.go
+++ b/services/data-manager/service/fetch/v2/eventParser.go
@@ -19,9 +19,9 @@ package v2
import (
"github.com/pocketbase/pocketbase/tools/types"
"golang.org/x/net/html"
- "htwkalender/model"
- "htwkalender/service/date"
- "htwkalender/service/functions"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/date"
+ "htwkalender/data-manager/service/functions"
"strings"
)
diff --git a/services/data-manager/service/fetch/v2/fetcher.go b/services/data-manager/service/fetch/v2/fetcher.go
index 35cc75a..ed1e77a 100644
--- a/services/data-manager/service/fetch/v2/fetcher.go
+++ b/services/data-manager/service/fetch/v2/fetcher.go
@@ -22,12 +22,12 @@ import (
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/daos"
"golang.org/x/net/html"
- "htwkalender/model"
- "htwkalender/service/db"
- "htwkalender/service/fetch"
- v1 "htwkalender/service/fetch/v1"
- "htwkalender/service/functions"
- localTime "htwkalender/service/functions/time"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/fetch"
+ v1 "htwkalender/data-manager/service/fetch/v1"
+ "htwkalender/data-manager/service/functions"
+ localTime "htwkalender/data-manager/service/functions/time"
"log/slog"
"strings"
)
@@ -195,6 +195,8 @@ func parseHTML(webpage string) (*html.Node, error) {
return doc, nil
}
+// generateUUIDs generates a UUID for each event based on the event name, course and semester
+// the UUID is used to identify the event in the database
func generateUUIDs(events []model.Event) []model.Event {
for i, event := range events {
// generate a hash value from the event name, course and semester
diff --git a/services/data-manager/service/fetch/v2/fetcher_test.go b/services/data-manager/service/fetch/v2/fetcher_test.go
index 9b2dec1..0a3e2ad 100644
--- a/services/data-manager/service/fetch/v2/fetcher_test.go
+++ b/services/data-manager/service/fetch/v2/fetcher_test.go
@@ -17,7 +17,7 @@
package v2
import (
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"reflect"
"testing"
)
diff --git a/services/data-manager/service/fetch/v2/htmlParsingFunctions.go b/services/data-manager/service/fetch/v2/htmlParsingFunctions.go
index fc240b5..4f09a57 100644
--- a/services/data-manager/service/fetch/v2/htmlParsingFunctions.go
+++ b/services/data-manager/service/fetch/v2/htmlParsingFunctions.go
@@ -19,8 +19,8 @@ package v2
import (
"github.com/pocketbase/pocketbase/tools/types"
"golang.org/x/net/html"
- "htwkalender/model"
- "htwkalender/service/date"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/date"
"regexp"
"strconv"
"strings"
diff --git a/services/data-manager/service/functions/semester.go b/services/data-manager/service/functions/semester.go
index 2ac4ea6..c95191a 100644
--- a/services/data-manager/service/functions/semester.go
+++ b/services/data-manager/service/functions/semester.go
@@ -17,7 +17,7 @@
package functions
import (
- localTime "htwkalender/service/functions/time"
+ localTime "htwkalender/data-manager/service/functions/time"
"time"
)
diff --git a/services/data-manager/service/functions/semester_test.go b/services/data-manager/service/functions/semester_test.go
index eb71898..35a8f9c 100644
--- a/services/data-manager/service/functions/semester_test.go
+++ b/services/data-manager/service/functions/semester_test.go
@@ -1,7 +1,7 @@
package functions
import (
- mockTime "htwkalender/service/functions/time"
+ mockTime "htwkalender/data-manager/service/functions/time"
"reflect"
"testing"
"time"
diff --git a/services/data-manager/service/grpc/feedService.go b/services/data-manager/service/grpc/feedService.go
new file mode 100644
index 0000000..67870c8
--- /dev/null
+++ b/services/data-manager/service/grpc/feedService.go
@@ -0,0 +1,33 @@
+package grpc
+
+import (
+ "context"
+ "github.com/pocketbase/pocketbase"
+ pb "htwkalender/common/genproto/modules"
+ "htwkalender/data-manager/service/db"
+)
+
+type FeedServiceHandler struct {
+ app *pocketbase.PocketBase
+ pb.UnimplementedFeedServiceServer
+}
+
+func (s *FeedServiceHandler) GetFeed(ctx context.Context, in *pb.GetFeedRequest) (*pb.GetFeedResponse, error) {
+
+ s.app.Logger().Info(
+ "Protobuf - GetFeed",
+ "uuid", in.Id,
+ )
+
+ // get feed from database by UUID
+ feed, err := db.FindFeedByToken(s.app, in.Id)
+ if err != nil {
+ return nil, err
+ }
+
+ // Implement your logic here to fetch feed data based on the UUID
+ // Example response
+ return &pb.GetFeedResponse{
+ Feed: feedToProto(feed),
+ }, nil
+}
diff --git a/services/data-manager/service/grpc/mapper.go b/services/data-manager/service/grpc/mapper.go
new file mode 100644
index 0000000..ee3ea58
--- /dev/null
+++ b/services/data-manager/service/grpc/mapper.go
@@ -0,0 +1,43 @@
+package grpc
+
+import (
+ pb "htwkalender/common/genproto/modules"
+ "htwkalender/data-manager/model"
+)
+
+func eventToProto(event *model.Event) *pb.Event {
+ return &pb.Event{
+ Uuid: event.UUID,
+ Day: event.Day,
+ Week: event.Week,
+ Start: event.Start.String(),
+ End: event.End.String(),
+ Name: event.Name,
+ EventType: event.EventType,
+ Compulsory: event.Compulsory,
+ Prof: event.Prof,
+ Rooms: event.Rooms,
+ Notes: event.Notes,
+ BookedAt: event.BookedAt,
+ Course: event.Course,
+ 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
+}
+
+func feedToProto(feed *model.Feed) *pb.Feed {
+ return &pb.Feed{
+ Id: feed.Id,
+ Created: feed.Created.String(),
+ Updated: feed.Updated.String(),
+ Retrieved: feed.Retrieved.String(),
+ Modules: feed.Modules,
+ }
+}
diff --git a/services/data-manager/service/grpc/moduleService.go b/services/data-manager/service/grpc/moduleService.go
new file mode 100644
index 0000000..b220809
--- /dev/null
+++ b/services/data-manager/service/grpc/moduleService.go
@@ -0,0 +1,69 @@
+package grpc
+
+import (
+ "context"
+ "github.com/pocketbase/pocketbase"
+ pb "htwkalender/common/genproto/modules"
+ "htwkalender/data-manager/service/db"
+)
+
+type ModuleServiceHandler struct {
+ app *pocketbase.PocketBase
+ pb.UnimplementedModuleServiceServer
+}
+
+func (s *ModuleServiceHandler) GetModule(ctx context.Context, in *pb.GetModuleRequest) (*pb.GetModuleResponse, error) {
+
+ s.app.Logger().Info(
+ "Protobuf - GetModule",
+ "uuid", in.Uuid,
+ )
+
+ // get module from database by UUID
+ module, err := db.FindModuleByUUID(s.app, in.Uuid)
+ if err != nil {
+ return nil, err
+ }
+
+ events, err := db.FindAllEventsByModule(s.app, module)
+ if err != nil {
+ return nil, err
+ }
+
+ //map module Events to proto struct Events
+ protoEvents := make([]*pb.Event, 0)
+ for _, event := range events {
+ protoEvents = append(protoEvents, eventToProto(&event))
+ }
+ //map module to proto struct
+ protoModule := &pb.Module{
+ Uuid: module.UUID,
+ Name: module.Name,
+ Prof: module.Prof,
+ Course: module.Course,
+ Semester: module.Semester,
+ Events: protoEvents,
+ }
+ // Implement your logic here to fetch module data based on the UUID
+ // Example response
+ return &pb.GetModuleResponse{
+ Module: protoModule,
+ }, nil
+}
+
+func (s *ModuleServiceHandler) GetEventsForModules(ctx context.Context, in *pb.GetModulesRequest) (*pb.GetEventsResponse, error) {
+
+ s.app.Logger().Info(
+ "Protobuf - GetEventsForModules",
+ "uuids", in.Uuids,
+ )
+
+ events, err := db.GetPlanForModules(s.app, in.Uuids)
+ if err != nil {
+ return nil, err
+ }
+
+ return &pb.GetEventsResponse{
+ Events: eventsToProto(events),
+ }, nil
+}
diff --git a/services/data-manager/service/grpc/server.go b/services/data-manager/service/grpc/server.go
new file mode 100644
index 0000000..f5b6ad3
--- /dev/null
+++ b/services/data-manager/service/grpc/server.go
@@ -0,0 +1,31 @@
+package grpc
+
+import (
+ "github.com/pocketbase/pocketbase"
+ "log"
+ "net"
+
+ "google.golang.org/grpc"
+ pb "htwkalender/common/genproto/modules"
+)
+
+func StartGRPCServer(app *pocketbase.PocketBase) {
+ lis, err := net.Listen("tcp", ":50051")
+ if err != nil {
+ log.Fatalf("failed to listen: %v", err)
+ }
+ s := grpc.NewServer()
+
+ pb.RegisterModuleServiceServer(s, &ModuleServiceHandler{
+ app: app,
+ })
+
+ pb.RegisterFeedServiceServer(s, &FeedServiceHandler{
+ app: app,
+ })
+
+ log.Printf("server listening at %v", lis.Addr())
+ if err := s.Serve(lis); err != nil {
+ log.Fatalf("failed to serve: %v", err)
+ }
+}
diff --git a/services/data-manager/service/ical/ical.go b/services/data-manager/service/ical/ical.go
index ec604fc..9711f11 100644
--- a/services/data-manager/service/ical/ical.go
+++ b/services/data-manager/service/ical/ical.go
@@ -20,8 +20,8 @@ import (
"encoding/json"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis"
- "htwkalender/model"
- "htwkalender/service/db"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/db"
)
func CreateIndividualFeed(requestBody []byte, app *pocketbase.PocketBase) (string, error) {
diff --git a/services/data-manager/service/ical/icalFileGeneration.go b/services/data-manager/service/ical/icalFileGeneration.go
deleted file mode 100644
index 31ba7d7..0000000
--- a/services/data-manager/service/ical/icalFileGeneration.go
+++ /dev/null
@@ -1,173 +0,0 @@
-//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
-//Copyright (C) 2024 HTWKalender support@htwkalender.de
-
-//This program is free software: you can redistribute it and/or modify
-//it under the terms of the GNU Affero General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//This program is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU Affero General Public License for more details.
-
-//You should have received a copy of the GNU Affero General Public License
-//along with this program. If not, see .
-
-package ical
-
-import (
- "htwkalender/model"
- "htwkalender/service/functions"
- clock "htwkalender/service/functions/time"
- "htwkalender/service/names"
- "time"
-
- "github.com/jordic/goics"
- _ "time/tzdata"
-)
-
-// IcalModel local type for EmitICal function
-type IcalModel struct {
- Events model.Events
- Mapping map[string]model.FeedCollection
-}
-
-// EmitICal implements the interface for goics
-func (icalModel IcalModel) EmitICal() goics.Componenter {
- internalClock := clock.RealClock{}
- c := generateIcalEmit(icalModel, internalClock)
- return c
-}
-
-func generateIcalEmit(icalModel IcalModel, internalClock clock.Clock) *goics.Component {
- europeTime, _ := time.LoadLocation("Europe/Berlin")
- c := goics.NewComponent()
- c.SetType("VCALENDAR")
- // PRODID is required by the standard
- c.AddProperty("PRODID", "-//HTWK Kalender//htwkalender.de//DE")
-
- c.AddProperty("VERSION", "2.0")
- c.AddProperty("CALSCALE", "GREGORIAN")
- c.AddProperty("TZID", "EUROPE/BERLIN")
- c.AddProperty("X-WR-CALNAME", "HTWK Kalender")
- c.AddProperty("X-WR-TIMEZONE", "EUROPE/BERLIN")
- //add v time zone
- icalModel.vtimezone(c)
-
- for _, event := range icalModel.Events {
- mapEntry, mappingFound := icalModel.Mapping[event.UUID]
-
- s := goics.NewComponent()
- s.SetType("VEVENT")
-
- s.AddProperty(goics.FormatDateTime("DTSTAMP", internalClock.Now().Local().In(europeTime)))
-
- // create a unique id for the event by hashing the event start, end, course and name
- var eventHash = functions.HashString(event.Start.String() + event.End.String() + event.Course + event.Name + event.Rooms)
-
- s.AddProperty("UID", eventHash+"@htwkalender.de")
- s.AddProperty(goics.FormatDateTime("DTEND", event.End.Time().Local().In(europeTime)))
- s.AddProperty(goics.FormatDateTime("DTSTART", event.Start.Time().Local().In(europeTime)))
-
- if mappingFound {
- addPropertyIfNotEmpty(s, "SUMMARY", replaceNameIfUserDefined(&event, mapEntry))
- addAlarmIfSpecified(s, event, mapEntry, internalClock)
- } else {
- addPropertyIfNotEmpty(s, "SUMMARY", event.Name)
- }
-
- addPropertyIfNotEmpty(s, "DESCRIPTION", generateDescription(event))
- addPropertyIfNotEmpty(s, "LOCATION", event.Rooms)
- c.AddComponent(s)
- }
- return c
-}
-
-func (icalModel IcalModel) vtimezone(c *goics.Component) {
- tz := goics.NewComponent()
- tz.SetType("VTIMEZONE")
- tz.AddProperty("TZID", "EUROPE/BERLIN")
- //add standard time
- icalModel.standard(tz)
- //add daylight time
- icalModel.daylight(tz)
-
- c.AddComponent(tz)
-}
-
-func (icalModel IcalModel) standard(tz *goics.Component) {
- st := NewHtwkalenderComponent()
- st.SetType("STANDARD")
- st.AddProperty("DTSTART", "19701025T030000")
- st.AddProperty("RRULE", "FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU")
- st.AddProperty("TZOFFSETFROM", "+0200")
- st.AddProperty("TZOFFSETTO", "+0100")
- st.AddProperty("TZNAME", "CET")
- tz.AddComponent(st)
-}
-
-// create an override for goics component function Write
-// to add the RRULE property
-
-func (icalModel IcalModel) daylight(tz *goics.Component) {
- dt := NewHtwkalenderComponent()
- dt.SetType("DAYLIGHT")
- dt.AddProperty("DTSTART", "19700329T020000")
- dt.AddProperty("TZOFFSETFROM", "+0100")
- dt.AddProperty("TZOFFSETTO", "+0200")
- dt.AddProperty("TZNAME", "CEST")
- dt.AddProperty("RRULE", "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU")
- tz.AddComponent(dt)
-}
-
-// if reminder is specified in the configuration for this event, an alarm will be added to the event
-func addAlarmIfSpecified(s *goics.Component, event model.Event, mapping model.FeedCollection, clock clock.Clock) {
- // if event.Start > now
- // then add alarm
- if event.Start.Time().Local().After(clock.Now().Local()) && mapping.Reminder {
- a := goics.NewComponent()
- a.SetType("VALARM")
- a.AddProperty("TRIGGER", "-P0DT0H15M0S")
- a.AddProperty("ACTION", "DISPLAY")
- a.AddProperty("DESCRIPTION", "Next course: "+replaceNameIfUserDefined(&event, mapping)+" in "+event.Rooms)
- s.AddComponent(a)
- }
-}
-
-// replaceNameIfUserDefined replaces the name of the event with the user defined name if it is not empty
-// all contained template strings will be replaced with the corresponding values from the event
-func replaceNameIfUserDefined(event *model.Event, mapping model.FeedCollection) string {
- if !functions.OnlyWhitespace(mapping.UserDefinedName) {
- return names.ReplaceTemplateSubStrings(mapping.UserDefinedName, *event)
- }
-
- return event.Name
-}
-
-// AddPropertyIfNotEmpty adds a property to the component if the value is not empty
-// or contains only whitespaces
-func addPropertyIfNotEmpty(component *goics.Component, key string, value string) {
- if !functions.OnlyWhitespace(value) {
- component.AddProperty(key, value)
- }
-}
-
-func generateDescription(event model.Event) string {
- var description string
-
- if !functions.OnlyWhitespace(event.Prof) {
- description += "Profs: " + event.Prof + "\n"
- }
- if !functions.OnlyWhitespace(event.Course) {
- description += "Gruppen: " + event.Course + "\n"
- }
- if !functions.OnlyWhitespace(event.EventType) {
- description += "Typ: " + event.EventType + event.Compulsory + "\n"
- }
- if !functions.OnlyWhitespace(event.Notes) {
- description += "Notizen: " + event.Notes + "\n"
- }
-
- return description
-}
diff --git a/services/data-manager/service/ical/icalFileGeneration_test.go b/services/data-manager/service/ical/icalFileGeneration_test.go
deleted file mode 100644
index f48f413..0000000
--- a/services/data-manager/service/ical/icalFileGeneration_test.go
+++ /dev/null
@@ -1,258 +0,0 @@
-//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
-//Copyright (C) 2024 HTWKalender support@htwkalender.de
-
-//This program is free software: you can redistribute it and/or modify
-//it under the terms of the GNU Affero General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//This program is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU Affero General Public License for more details.
-
-//You should have received a copy of the GNU Affero General Public License
-//along with this program. If not, see .
-
-package ical
-
-import (
- "github.com/jordic/goics"
- "htwkalender/model"
- mockTime "htwkalender/service/functions/time"
- "reflect"
- "testing"
- "time"
-)
-
-func TestIcalModel_EmitICal(t *testing.T) {
- type fields struct {
- Events model.Events
- Mapping map[string]model.FeedCollection
- }
- tests := []struct {
- name string
- fields fields
- want *goics.Component
- }{
- {
- name: "Test EmitICal",
- fields: fields{
- Events: model.Events{
- {
- UUID: "123",
- Name: "Test",
- EventType: "Test",
- Notes: "Test",
- Prof: "Test",
- Rooms: "Test",
- BookedAt: "Test",
- },
- },
- Mapping: map[string]model.FeedCollection{
- "123": {
- UUID: "123",
- Name: "Test",
- Course: "Test",
- UserDefinedName: "Test",
- },
- },
- },
- want: &goics.Component{
- Tipo: "VCALENDAR",
- Elements: []goics.Componenter{
- &goics.Component{
- Tipo: "VTIMEZONE",
- Elements: []goics.Componenter{
- &HtwkalenderComponent{
- Component: &goics.Component{
- Tipo: "STANDARD",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTART": {"19701025T030000"},
- "RRULE": {"FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU"},
- "TZOFFSETFROM": {"+0200"},
- "TZOFFSETTO": {"+0100"},
- "TZNAME": {"CET"},
- },
- },
- },
- &HtwkalenderComponent{
- Component: &goics.Component{
- Tipo: "DAYLIGHT",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTART": {"19700329T020000"},
- "TZOFFSETFROM": {"+0100"},
- "TZOFFSETTO": {"+0200"},
- "TZNAME": {"CEST"},
- "RRULE": {"FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"},
- },
- },
- },
- },
- Properties: map[string][]string{
- "TZID": {"EUROPE/BERLIN"},
- },
- },
- &goics.Component{
- Tipo: "VEVENT",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTAMP": {"20231201T000000Z"},
- "UID": {"a8d627d93f518e9096b6f40e36d27b7660fa26d318ef1adc43da750e49ebe4be@htwkalender.de"},
- "DTEND": {"00010101T000000Z"},
- "DTSTART": {"00010101T000000Z"},
- "SUMMARY": {"Test"},
- "DESCRIPTION": {"Profs: Test\nTyp: Test\nNotizen: Test\n"},
- "LOCATION": {"Test"},
- },
- },
- },
- Properties: map[string][]string{
- "PRODID": {"-//HTWK Kalender//htwkalender.de//DE"},
- "VERSION": {"2.0"},
- "CALSCALE": {"GREGORIAN"},
- "TZID": {"EUROPE/BERLIN"},
- "X-WR-CALNAME": {"HTWK Kalender"},
- "X-WR-TIMEZONE": {"EUROPE/BERLIN"},
- },
- },
- },
- {
- name: "Test Similar Events like Sport Courses",
- fields: fields{
- Events: model.Events{
- {
- UUID: "123",
- Name: "Test",
- Course: "Test",
- EventType: "Test",
- Notes: "Test",
- Prof: "Test",
- Rooms: "ZU430",
- BookedAt: "Test",
- Start: mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 0, 0, 0, 0, time.UTC)),
- End: mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 1, 0, 0, 0, time.UTC)),
- },
- {
- UUID: "123",
- Name: "Test",
- Course: "Test",
- EventType: "Test",
- Notes: "Test",
- Prof: "Test",
- Rooms: "ZU221",
- BookedAt: "Test",
- Start: mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 0, 0, 0, 0, time.UTC)),
- End: mockTime.ParseAsTypesDatetime(time.Date(2023, 12, 1, 1, 0, 0, 0, time.UTC)),
- },
- },
- Mapping: map[string]model.FeedCollection{
- "123": {
- UUID: "123",
- Name: "Test",
- Course: "Test",
- UserDefinedName: "UserDefinedName",
- },
- },
- },
- want: &goics.Component{
- Tipo: "VCALENDAR",
- Elements: []goics.Componenter{
- &goics.Component{
- Tipo: "VTIMEZONE",
- Elements: []goics.Componenter{
- &HtwkalenderComponent{
- Component: &goics.Component{
- Tipo: "STANDARD",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTART": {"19701025T030000"},
- "RRULE": {"FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU"},
- "TZOFFSETFROM": {"+0200"},
- "TZOFFSETTO": {"+0100"},
- "TZNAME": {"CET"},
- },
- },
- },
- &HtwkalenderComponent{
- Component: &goics.Component{
- Tipo: "DAYLIGHT",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTART": {"19700329T020000"},
- "TZOFFSETFROM": {"+0100"},
- "TZOFFSETTO": {"+0200"},
- "TZNAME": {"CEST"},
- "RRULE": {"FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU"},
- },
- },
- },
- },
- Properties: map[string][]string{
- "TZID": {"EUROPE/BERLIN"},
- },
- },
- &goics.Component{
- Tipo: "VEVENT",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTAMP": {"20231201T000000Z"},
- "UID": {"b52a7a081f46eeba9b402114493278a34a48b572c84e53d7ac4da9dea15cdff2@htwkalender.de"},
- "DTEND": {"20231201T010000Z"},
- "DTSTART": {"20231201T000000Z"},
- "SUMMARY": {"UserDefinedName"},
- "DESCRIPTION": {"Profs: Test\nGruppen: Test\nTyp: Test\nNotizen: Test\n"},
- "LOCATION": {"ZU430"},
- },
- },
- &goics.Component{
- Tipo: "VEVENT",
- Elements: []goics.Componenter{},
- Properties: map[string][]string{
- "DTSTAMP": {"20231201T000000Z"},
- "UID": {"5e946c0c4474bc6e6337262093e3ef31477e026bbc6bab398d755b002506d9d7@htwkalender.de"},
- "DTEND": {"20231201T010000Z"},
- "DTSTART": {"20231201T000000Z"},
- "SUMMARY": {"UserDefinedName"},
- "DESCRIPTION": {"Profs: Test\nGruppen: Test\nTyp: Test\nNotizen: Test\n"},
- "LOCATION": {"ZU221"},
- },
- },
- },
- Properties: map[string][]string{
- "PRODID": {"-//HTWK Kalender//htwkalender.de//DE"},
- "VERSION": {"2.0"},
- "CALSCALE": {"GREGORIAN"},
- "TZID": {"EUROPE/BERLIN"},
- "X-WR-CALNAME": {"HTWK Kalender"},
- "X-WR-TIMEZONE": {"EUROPE/BERLIN"},
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- icalModel := IcalModel{
- Events: tt.fields.Events,
- Mapping: tt.fields.Mapping,
- }
-
- mockClock := mockTime.MockClock{
- NowTime: time.Date(2023, 12, 1, 0, 0, 0, 0, time.UTC),
- }
-
- if got := generateIcalEmit(icalModel, mockClock); !reflect.DeepEqual(got, tt.want) {
- t.Errorf("EmitICal() = \n%v, want \n%v", got, tt.want)
-
- // Print the differences
- for i, element := range got.Elements {
- if !reflect.DeepEqual(element, tt.want.Elements[i]) {
- t.Errorf("Element %d: got \n%v, want \n%v", i, element, tt.want.Elements[i])
- }
- }
- }
- })
- }
-}
diff --git a/services/data-manager/service/ical/icsComponenter.go b/services/data-manager/service/ical/icsComponenter.go
deleted file mode 100644
index b8c3deb..0000000
--- a/services/data-manager/service/ical/icsComponenter.go
+++ /dev/null
@@ -1,62 +0,0 @@
-//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
-//Copyright (C) 2024 HTWKalender support@htwkalender.de
-
-//This program is free software: you can redistribute it and/or modify
-//it under the terms of the GNU Affero General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//This program is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU Affero General Public License for more details.
-
-//You should have received a copy of the GNU Affero General Public License
-//along with this program. If not, see .
-
-package ical
-
-import (
- "github.com/jordic/goics"
- "sort"
- "strings"
-)
-
-type HtwkalenderComponent struct {
- *goics.Component
-}
-
-func NewHtwkalenderComponent() *HtwkalenderComponent {
- return &HtwkalenderComponent{
- Component: goics.NewComponent(),
- }
-}
-
-// Writes the component to the Writer
-func (c *HtwkalenderComponent) Write(w *goics.ICalEncode) {
- w.WriteLine("BEGIN:" + c.Tipo + goics.CRLF)
-
- // Iterate over component properties
- var keys []string
- for k := range c.Properties {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, key := range keys {
- vals := c.Properties[key]
- for _, val := range vals {
- w.WriteLine(WriteStringField(key, val))
- }
- }
-
- for _, xc := range c.Elements {
- xc.Write(w)
- }
-
- w.WriteLine("END:" + c.Tipo + goics.CRLF)
-}
-
-// WriteStringField UID:asdfasdfаs@dfasdf.com
-func WriteStringField(key string, val string) string {
- return strings.ToUpper(key) + ":" + (val) + goics.CRLF
-}
diff --git a/services/data-manager/service/names/userDefinedNameTemplates.go b/services/data-manager/service/names/userDefinedNameTemplates.go
index 3033623..11425bb 100644
--- a/services/data-manager/service/names/userDefinedNameTemplates.go
+++ b/services/data-manager/service/names/userDefinedNameTemplates.go
@@ -17,7 +17,7 @@
package names
import (
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"regexp"
)
diff --git a/services/data-manager/service/names/userDefinedNameTemplates_test.go b/services/data-manager/service/names/userDefinedNameTemplates_test.go
index 9fe9c7d..a1b88c3 100644
--- a/services/data-manager/service/names/userDefinedNameTemplates_test.go
+++ b/services/data-manager/service/names/userDefinedNameTemplates_test.go
@@ -17,7 +17,7 @@
package names
import (
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"testing"
)
diff --git a/services/data-manager/service/room/roomService.go b/services/data-manager/service/room/roomService.go
index fdf9ab9..151746d 100644
--- a/services/data-manager/service/room/roomService.go
+++ b/services/data-manager/service/room/roomService.go
@@ -18,9 +18,9 @@ package room
import (
"github.com/pocketbase/pocketbase"
- "htwkalender/model"
- "htwkalender/service/db"
- "htwkalender/service/functions"
+ "htwkalender/data-manager/model"
+ "htwkalender/data-manager/service/db"
+ "htwkalender/data-manager/service/functions"
"time"
)
diff --git a/services/data-manager/service/room/roomService_test.go b/services/data-manager/service/room/roomService_test.go
index 4f0f91f..b4bf733 100644
--- a/services/data-manager/service/room/roomService_test.go
+++ b/services/data-manager/service/room/roomService_test.go
@@ -18,7 +18,7 @@ package room
import (
"github.com/pocketbase/pocketbase/tools/types"
- "htwkalender/model"
+ "htwkalender/data-manager/model"
"reflect"
"testing"
)
diff --git a/services/ical/go.mod b/services/go.mod
similarity index 81%
rename from services/ical/go.mod
rename to services/go.mod
index c087dbe..015e6a1 100644
--- a/services/ical/go.mod
+++ b/services/go.mod
@@ -1,16 +1,25 @@
-module htwkalender-ical
+module htwkalender
-go 1.21.6
+go 1.21
require (
+ github.com/PuerkitoBio/goquery v1.9.2
github.com/gofiber/fiber/v3 v3.0.0-beta.2
+ github.com/google/uuid v1.6.0
github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0
+ github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
+ github.com/pocketbase/dbx v1.10.1
github.com/pocketbase/pocketbase v0.22.12
+ github.com/samber/slog-fiber v1.15.3
+ golang.org/x/net v0.26.0
+ google.golang.org/grpc v1.63.2
+ google.golang.org/protobuf v1.34.1
)
require (
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
+ github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
@@ -39,47 +48,46 @@ require (
github.com/ganigeorgiev/fexpr v0.4.0 // indirect
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
+ github.com/gofiber/fiber/v2 v2.52.1 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/gax-go/v2 v2.12.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
- github.com/klauspost/compress v1.17.8 // indirect
- github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 // indirect
+ github.com/klauspost/compress v1.17.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
- github.com/pocketbase/dbx v1.10.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasthttp v1.54.0 // indirect
+ github.com/valyala/fasthttp v1.52.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
+ go.opentelemetry.io/otel v1.24.0 // indirect
+ go.opentelemetry.io/otel/trace v1.24.0 // indirect
gocloud.dev v0.37.0 // indirect
- golang.org/x/crypto v0.23.0 // indirect
+ golang.org/x/crypto v0.24.0 // indirect
golang.org/x/image v0.16.0 // indirect
- golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sync v0.7.0 // indirect
- golang.org/x/sys v0.20.0 // indirect
- golang.org/x/term v0.20.0 // indirect
- golang.org/x/text v0.15.0 // indirect
+ golang.org/x/sys v0.21.0 // indirect
+ golang.org/x/term v0.21.0 // indirect
+ golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.180.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect
- google.golang.org/grpc v1.63.2 // indirect
- google.golang.org/protobuf v1.34.1 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.50.5 // indirect
modernc.org/mathutil v1.6.0 // indirect
diff --git a/services/ical/go.sum b/services/go.sum
similarity index 91%
rename from services/ical/go.sum
rename to services/go.sum
index e4d76bd..2d8a28a 100644
--- a/services/ical/go.sum
+++ b/services/go.sum
@@ -19,8 +19,12 @@ github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1r
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
+github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
+github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
+github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
+github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
@@ -105,6 +109,8 @@ github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVH
github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/gofiber/fiber/v2 v2.52.1 h1:1RoU2NS+b98o1L77sdl5mboGPiW+0Ypsi5oLmcYlgHI=
+github.com/gofiber/fiber/v2 v2.52.1/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/gofiber/fiber/v3 v3.0.0-beta.2 h1:mVVgt8PTaHGup3NGl/+7U7nEoZaXJ5OComV4E+HpAao=
github.com/gofiber/fiber/v3 v3.0.0-beta.2/go.mod h1:w7sdfTY0okjZ1oVH6rSOGvuACUIt0By1iK0HKUb3uqM=
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
@@ -165,8 +171,8 @@ github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0 h1:p+k2RozdR141dIkAbO
github.com/jordic/goics v0.0.0-20210404174824-5a0337b716a0/go.mod h1:YHaw6sOIeFRob8Y9q/blEAMfVcLpeE9+vdhrwyEMxoI=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
-github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
-github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
+github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -181,6 +187,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
+github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
@@ -198,9 +206,13 @@ github.com/pocketbase/pocketbase v0.22.12/go.mod h1:yY/3IGi1tUbcI6yGVFspAyKi/IDH
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/samber/slog-fiber v1.15.3 h1:RbfC0v2QPIEXoRdort2QxAsRG42LVaFTEgTNS/0GwRQ=
+github.com/samber/slog-fiber v1.15.3/go.mod h1:I0b8eJ060SlpA65LXiqH7lZixUCkAPKiEGZqkT9QJOM=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
@@ -219,8 +231,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasthttp v1.54.0 h1:cCL+ZZR3z3HPLMVfEYVUMtJqVaui0+gu7Lx63unHwS0=
-github.com/valyala/fasthttp v1.54.0/go.mod h1:6dt4/8olwq9QARP/TDuPmWyWcl4byhpvTJ4AAtcz+QM=
+github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0=
+github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
@@ -243,8 +255,8 @@ gocloud.dev v0.37.0/go.mod h1:7/O4kqdInCNsc6LqgmuFnS0GRew4XNNYWpA44yQnwco=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
+golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.16.0 h1:9kloLAKhUufZhA12l5fwnx2NZW39/we1UhBesW433jw=
@@ -253,8 +265,9 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
-golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -265,8 +278,10 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
@@ -274,6 +289,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -286,20 +302,26 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
+golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
+golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
+golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
+golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -309,8 +331,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
-golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
diff --git a/services/ical/Dockerfile b/services/ical/Dockerfile
index 2bc4c3b..19d231c 100644
--- a/services/ical/Dockerfile
+++ b/services/ical/Dockerfile
@@ -17,14 +17,16 @@
# build stage
FROM golang:alpine AS build
-WORKDIR /app
+WORKDIR /htwkalender-ical
+RUN apk add --no-cache --update go gcc g++
# Copy the source from the current directory to the Working Directory inside the container
-COPY . ./
-# download needed modules
-RUN apk add --no-cache --update go gcc g++ && \
- go mod download && \
- CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-ical
+COPY go.mod go.sum ./
+RUN go mod download
+
+COPY ical/. ./ical
+COPY common/. ./common
+RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-ical ical/main.go
# production stage
FROM alpine:latest AS prod
@@ -44,7 +46,7 @@ COPY --chown=$USER:$USER --from=build /htwkalender-ical ./
# Expose port 8091 to the outside world
EXPOSE 8091
-ENTRYPOINT ["./htwkalender-ical"]
+ENTRYPOINT ["./main"]
FROM golang:1.21.6 AS dev
@@ -57,14 +59,14 @@ COPY go.mod go.sum ./
RUN go mod download
# Copy the source from the current directory to the Working Directory inside the container
-COPY *.go ./
-COPY . .
+COPY ical/. ./ical
+COPY common/. ./common
# Build the Go app
-RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-ical
+RUN CGO_ENABLED=1 GOOS=linux go build -o /htwkalender-ical ical/main.go
# Expose port 8091 to the outside world
EXPOSE 8091
# Entry point
-ENTRYPOINT ["./htwkalender-ical"]
\ No newline at end of file
+ENTRYPOINT ["./main"]
\ No newline at end of file
diff --git a/services/ical/main.go b/services/ical/main.go
index 4865e7c..1769786 100644
--- a/services/ical/main.go
+++ b/services/ical/main.go
@@ -18,9 +18,12 @@ package main
import (
"github.com/gofiber/fiber/v3"
- "github.com/gofiber/fiber/v3/log"
"github.com/gofiber/fiber/v3/middleware/logger"
- "htwkalender-ical/service"
+ "htwkalender/ical/model"
+ "htwkalender/ical/service"
+ "htwkalender/ical/service/connector/grpc"
+ "log/slog"
+ "os"
)
// main function for the ical service
@@ -28,21 +31,41 @@ import (
// exposes rest api endpoints with fiber to serve the data for clients
func main() {
+ // get host from env if this is not set use default value 127.0.0.1
+
+ host := os.Getenv("DATA_MANAGER_URL")
+ if host == "" {
+ host = "127.0.0.1"
+ }
+
+ grpcClient := grpc.ConnectGRPCServer(host)
+ defer grpc.CloseGRPCServer(grpcClient)
+
// Initialize a new Fiber app
webdavRequestMethods := []string{"PROPFIND", "MKCOL", "COPY", "MOVE"}
- app := fiber.New(fiber.Config{
- CaseSensitive: true,
- StrictRouting: true,
- ServerHeader: "Fiber",
- AppName: "App Name",
- RequestMethods: append(fiber.DefaultMethods[:], webdavRequestMethods...),
+ fiberApp := fiber.New(fiber.Config{
+ CaseSensitive: true,
+ StrictRouting: true,
+ ServerHeader: "HTWKalender iCal Service",
+ AppName: "HTWKalender iCal Service",
+ RequestMethods: append(fiber.DefaultMethods[:], webdavRequestMethods...),
+ EnableTrustedProxyCheck: true,
+ TrustedProxies: []string{"172.16.0.0/12", "172.18.0.5", "172.18.0.1"},
+ ProxyHeader: "X-Forwarded-For",
})
- app.Use(logger.New())
+ var app = model.AppType{
+ GrpcClient: grpcClient,
+ Host: host,
+ Fiber: fiberApp,
+ DataManagerURL: "http://" + host + ":8090",
+ }
+
+ fiberApp.Use(logger.New())
// Add routes to the app instance for the data-manager ical service
service.AddFeedRoutes(app)
- log.Fatal(app.Listen(":8091"))
+ slog.Info("Starting ical service", "fiberApp", fiberApp.Listen(":8091"))
}
diff --git a/services/ical/model/appModel.go b/services/ical/model/appModel.go
new file mode 100644
index 0000000..2238b09
--- /dev/null
+++ b/services/ical/model/appModel.go
@@ -0,0 +1,13 @@
+package model
+
+import (
+ "github.com/gofiber/fiber/v3"
+ googleGRPC "google.golang.org/grpc"
+)
+
+type AppType struct {
+ GrpcClient *googleGRPC.ClientConn
+ Host string
+ Fiber *fiber.App
+ DataManagerURL string
+}
diff --git a/services/ical/model/icalModel.go b/services/ical/model/icalModel.go
index a8b09ed..7ff9263 100644
--- a/services/ical/model/icalModel.go
+++ b/services/ical/model/icalModel.go
@@ -23,6 +23,9 @@ import (
"time"
)
+// DefaultDateLayout specifies the default app date strings layout.
+const DefaultDateLayout = "2006-01-02 15:04:05.000Z"
+
// IcalModel local type for EmitICal function
type IcalModel struct {
Events Events
@@ -73,10 +76,18 @@ func (jt *JSONTime) UnmarshalJSON(b []byte) error {
if timeString == "null" || timeString == "" {
return nil
}
- t, err := time.Parse("2006-01-02 15:04:05.000Z", timeString)
+ t, err := time.Parse(DefaultDateLayout, timeString)
if err == nil {
*jt = JSONTime(t)
return nil
}
return fmt.Errorf("error parsing time string %s: %w", timeString, err)
}
+
+func ToJSONTime(timeString string) JSONTime {
+ t, err := time.Parse(DefaultDateLayout, timeString)
+ if err != nil {
+ return JSONTime(time.Time{})
+ }
+ return JSONTime(t)
+}
diff --git a/services/ical/service/connector/feedConnector.go b/services/ical/service/connector/feedConnector.go
index 7c98663..e545791 100644
--- a/services/ical/service/connector/feedConnector.go
+++ b/services/ical/service/connector/feedConnector.go
@@ -3,17 +3,18 @@ package connector
import (
"encoding/json"
"errors"
- "htwkalender-ical/model"
+ "htwkalender/ical/model"
"log/slog"
)
-func GetFeedByToken(token string) (model.FeedRecord, error) {
+func GetFeedByToken(host string, token string) (model.FeedRecord, error) {
var feed model.FeedRecord
// /api/collections/feeds/records/{id}
- response, err := RequestApi("/api/collections/feeds/records/" + token)
+ response, err := RequestApi(host, "/api/collections/feeds/records/"+token)
if err != nil {
+ slog.Error("Failed to get feed record", "error", err)
return model.FeedRecord{}, err
}
@@ -39,8 +40,8 @@ func parseResponse(response []byte) (model.FeedRecord, error) {
return feedRecord, nil
}
-func DeleteFeedRecord(token string) error {
- err := DeleteRequestApi("/api/feed?token=" + token)
+func DeleteFeedRecord(app model.AppType, token string) error {
+ err := DeleteRequestApi(app.DataManagerURL, "/api/feed?token="+token)
if err != nil {
return err
}
@@ -48,12 +49,10 @@ func DeleteFeedRecord(token string) error {
return nil
}
-func GetModuleWithEvents(module model.FeedModule) (model.Module, error) {
+func GetModuleWithEvents(app model.AppType, module model.FeedModule) (model.Module, error) {
var modules model.Module
- // /api/module?uuid=
-
- response, err := RequestApi("/api/module?uuid=" + module.UUID)
+ response, err := RequestApi(app.DataManagerURL, "/api/module?uuid="+module.UUID)
if err != nil {
return model.Module{}, err
}
@@ -79,10 +78,10 @@ func parseModuleResponse(body []byte) (model.Module, error) {
return module, nil
}
-func SaveFeedRecord(modules []model.FeedCollection) (string, error) {
+func SaveFeedRecord(app model.AppType, modules []model.FeedCollection) (string, error) {
var token string
- response, err := PostRequestApi("/api/feed", modules)
+ response, err := PostRequestApi(app.DataManagerURL, "/api/feed", modules)
if err != nil {
return "", err
}
diff --git a/services/ical/service/connector/grpc/client.go b/services/ical/service/connector/grpc/client.go
new file mode 100644
index 0000000..f9c7275
--- /dev/null
+++ b/services/ical/service/connector/grpc/client.go
@@ -0,0 +1,22 @@
+package grpc
+
+import (
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials/insecure"
+ "log/slog"
+)
+
+func ConnectGRPCServer(host string) *grpc.ClientConn {
+ conn, err := grpc.Dial(host+":50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
+ if err != nil {
+ slog.Error("could not connect to grpc server", "error", err)
+ }
+ return conn
+}
+
+func CloseGRPCServer(conn *grpc.ClientConn) {
+ err := conn.Close()
+ if err != nil {
+ slog.Error("could not close connection", "error", err)
+ }
+}
diff --git a/services/ical/service/connector/grpc/events.go b/services/ical/service/connector/grpc/events.go
new file mode 100644
index 0000000..fc82755
--- /dev/null
+++ b/services/ical/service/connector/grpc/events.go
@@ -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
+}
diff --git a/services/ical/service/connector/grpc/feeds.go b/services/ical/service/connector/grpc/feeds.go
new file mode 100644
index 0000000..0f1f082
--- /dev/null
+++ b/services/ical/service/connector/grpc/feeds.go
@@ -0,0 +1,52 @@
+package grpc
+
+import (
+ "context"
+ "github.com/goccy/go-json"
+ "google.golang.org/grpc"
+ pb "htwkalender/common/genproto/modules"
+ "htwkalender/ical/model"
+ "log/slog"
+ "time"
+)
+
+func GetFeed(feedId string, conn *grpc.ClientConn) (model.FeedRecord, error) {
+ c := pb.NewFeedServiceClient(conn)
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ defer cancel()
+
+ r, err := c.GetFeed(ctx, &pb.GetFeedRequest{Id: feedId})
+ if err != nil {
+ slog.Error("could not get modules: %v", "error", err)
+ return model.FeedRecord{}, err
+ }
+
+ feed, err := protoToFeed(r.GetFeed())
+ if err != nil {
+ slog.Error("could not convert feed: %v", "error", err)
+ return model.FeedRecord{}, err
+ }
+
+ return feed, nil
+}
+
+func protoToFeed(feed *pb.Feed) (model.FeedRecord, error) {
+
+ // unmarshal the []model.FeedModule from json
+ var modules []model.FeedModule
+ err := json.Unmarshal([]byte(feed.Modules), &modules)
+ if err != nil {
+ slog.Error("could not unmarshal modules: %v", "error", err)
+ return model.FeedRecord{}, err
+ }
+
+ return model.FeedRecord{
+ BaseModel: model.BaseModel{
+ Id: feed.Id,
+ Created: model.ToJSONTime(feed.Created),
+ Updated: model.ToJSONTime(feed.Updated),
+ },
+ Retrieved: model.ToJSONTime(feed.Retrieved),
+ Modules: modules,
+ }, nil
+}
diff --git a/services/ical/service/connector/grpc/modules.go b/services/ical/service/connector/grpc/modules.go
new file mode 100644
index 0000000..aa47d79
--- /dev/null
+++ b/services/ical/service/connector/grpc/modules.go
@@ -0,0 +1,90 @@
+package grpc
+
+import (
+ "context"
+ "google.golang.org/grpc"
+ pb "htwkalender/common/genproto/modules"
+ "htwkalender/ical/model"
+ "log/slog"
+ "time"
+)
+
+func GetModuleWithEvents(module model.FeedModule, conn *grpc.ClientConn) (model.Module, error) {
+ c := pb.NewModuleServiceClient(conn)
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+ defer cancel()
+ r, err := c.GetModule(ctx, &pb.GetModuleRequest{Uuid: module.UUID})
+ if err != nil {
+ slog.Error("could not get module: %v", "error", err)
+ }
+
+ events := make([]model.Event, 0)
+ for _, event := range r.GetModule().Events {
+ events = append(events, protoToEvent(event))
+ }
+
+ return model.Module{
+ UUID: r.GetModule().Uuid,
+ Name: r.GetModule().Name,
+ Prof: r.GetModule().Prof,
+ Course: r.GetModule().Course,
+ Semester: r.GetModule().Semester,
+ Events: events,
+ }, 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 {
+
+ return model.Event{
+ UUID: event.Uuid,
+ Day: event.Day,
+ Week: event.Week,
+ Start: model.ToJSONTime(event.Start),
+ End: model.ToJSONTime(event.End),
+ Name: event.Name,
+ EventType: event.EventType,
+ Compulsory: event.Compulsory,
+ Prof: event.Prof,
+ Rooms: event.Rooms,
+ Notes: event.Notes,
+ BookedAt: event.BookedAt,
+ Course: event.Course,
+ Semester: event.Semester,
+ }
+}
diff --git a/services/ical/service/connector/restHandler.go b/services/ical/service/connector/restHandler.go
index 7fc3381..4af7ba0 100644
--- a/services/ical/service/connector/restHandler.go
+++ b/services/ical/service/connector/restHandler.go
@@ -2,13 +2,11 @@ package connector
import (
"github.com/gofiber/fiber/v3/client"
- "htwkalender-ical/model"
+ "htwkalender/ical/model"
"time"
)
-const host = "http://htwkalender-data-manager:8090"
-
-func RequestApi(path string) (*client.Response, error) {
+func RequestApi(host string, path string) (*client.Response, error) {
cc := client.New()
cc.SetTimeout(5 * time.Second)
@@ -22,7 +20,7 @@ func RequestApi(path string) (*client.Response, error) {
return response, nil
}
-func DeleteRequestApi(path string) error {
+func DeleteRequestApi(host string, path string) error {
cc := client.New()
cc.SetTimeout(5 * time.Second)
@@ -36,7 +34,7 @@ func DeleteRequestApi(path string) error {
return nil
}
-func PostRequestApi(path string, body []model.FeedCollection) (*client.Response, error) {
+func PostRequestApi(host string, path string, body []model.FeedCollection) (*client.Response, error) {
cc := client.New()
cc.SetTimeout(5 * time.Second)
diff --git a/services/ical/service/functions/semester.go b/services/ical/service/functions/semester.go
index 9cf7006..001fe73 100644
--- a/services/ical/service/functions/semester.go
+++ b/services/ical/service/functions/semester.go
@@ -17,7 +17,7 @@
package functions
import (
- localTime "htwkalender-ical/service/functions/time"
+ localTime "htwkalender/ical/service/functions/time"
"time"
)
diff --git a/services/ical/service/functions/semester_test.go b/services/ical/service/functions/semester_test.go
index 5a5f96c..0f46f11 100644
--- a/services/ical/service/functions/semester_test.go
+++ b/services/ical/service/functions/semester_test.go
@@ -1,7 +1,7 @@
package functions
import (
- mockTime "htwkalender-ical/service/functions/time"
+ mockTime "htwkalender/ical/service/functions/time"
"reflect"
"testing"
"time"
diff --git a/services/ical/service/functions/time/parse.go b/services/ical/service/functions/time/parse.go
index 97a4f22..dc3ff4a 100644
--- a/services/ical/service/functions/time/parse.go
+++ b/services/ical/service/functions/time/parse.go
@@ -17,7 +17,7 @@
package time
import (
- "htwkalender-ical/model"
+ "htwkalender/ical/model"
"time"
)
diff --git a/services/ical/service/ical/ical.go b/services/ical/service/ical/ical.go
index 05ae05d..baa6160 100644
--- a/services/ical/service/ical/ical.go
+++ b/services/ical/service/ical/ical.go
@@ -3,33 +3,31 @@ package ical
import (
"bytes"
"github.com/jordic/goics"
- "htwkalender-ical/model"
- "htwkalender-ical/service/connector"
+ "htwkalender/ical/model"
+ "htwkalender/ical/service/connector"
+ htwkalenderGrpc "htwkalender/ical/service/connector/grpc"
"log/slog"
"time"
)
const expirationTime = 5 * time.Minute
-func Feed(token string) (string, error) {
+func Feed(app model.AppType, token string) (string, error) {
// get feed by token
- feed, err := connector.GetFeedByToken(token)
+ feed, err := htwkalenderGrpc.GetFeed(token, app.GrpcClient)
if err != nil {
return "", err
}
var events model.Events
- for _, module := range feed.Modules {
- moduleWithEvents, err := connector.GetModuleWithEvents(module)
- if err != nil {
- return "", err
- }
-
- events = append(events, moduleWithEvents.Events...)
+ // Get all events for modules
+ events, err = htwkalenderGrpc.GetEvents(feed.Modules, app.GrpcClient)
+ if err != nil {
+ return "", err
}
- // Sorte events by start date
+ // Sort events by start date
events.Sort()
modules := make(map[string]model.FeedCollection)
@@ -44,9 +42,9 @@ func Feed(token string) (string, error) {
return icalFeed.Content, nil
}
-func FeedRecord(token string) (model.FeedRecord, error) {
+func FeedRecord(app model.AppType, token string) (model.FeedRecord, error) {
- feedRecord, err := connector.GetFeedByToken(token)
+ feedRecord, err := connector.GetFeedByToken(app.DataManagerURL, token)
if err != nil {
return model.FeedRecord{}, err
}
@@ -55,18 +53,18 @@ func FeedRecord(token string) (model.FeedRecord, error) {
}
-func DeleteFeedRecord(token string) error {
- err := connector.DeleteFeedRecord(token)
+func DeleteFeedRecord(app model.AppType, token string) error {
+ err := connector.DeleteFeedRecord(app, token)
if err != nil {
return err
}
return nil
}
-func CreateFeed(modules []model.FeedCollection) (string, error) {
+func CreateFeed(app model.AppType, modules []model.FeedCollection) (string, error) {
// Save feed
- token, err := connector.SaveFeedRecord(modules)
+ token, err := connector.SaveFeedRecord(app, modules)
if err != nil {
slog.Error("Failed to save feed", "error", err)
return "", err
diff --git a/services/ical/service/ical/icalFileGeneration.go b/services/ical/service/ical/icalFileGeneration.go
index 57eb4a3..9af0c60 100644
--- a/services/ical/service/ical/icalFileGeneration.go
+++ b/services/ical/service/ical/icalFileGeneration.go
@@ -17,10 +17,10 @@
package ical
import (
- "htwkalender-ical/model"
- "htwkalender-ical/service/functions"
- clock "htwkalender-ical/service/functions/time"
- "htwkalender-ical/service/names"
+ "htwkalender/ical/model"
+ "htwkalender/ical/service/functions"
+ clock "htwkalender/ical/service/functions/time"
+ "htwkalender/ical/service/names"
"time"
"github.com/jordic/goics"
diff --git a/services/ical/service/ical/icalFileGeneration_test.go b/services/ical/service/ical/icalFileGeneration_test.go
index c1a92f0..f85702f 100644
--- a/services/ical/service/ical/icalFileGeneration_test.go
+++ b/services/ical/service/ical/icalFileGeneration_test.go
@@ -18,8 +18,8 @@ package ical
import (
"github.com/jordic/goics"
- "htwkalender-ical/model"
- mockTime "htwkalender-ical/service/functions/time"
+ "htwkalender/ical/model"
+ mockTime "htwkalender/ical/service/functions/time"
"reflect"
"testing"
"time"
diff --git a/services/ical/service/names/userDefinedNameTemplates.go b/services/ical/service/names/userDefinedNameTemplates.go
index 59250ff..ee05e6e 100644
--- a/services/ical/service/names/userDefinedNameTemplates.go
+++ b/services/ical/service/names/userDefinedNameTemplates.go
@@ -17,7 +17,7 @@
package names
import (
- "htwkalender-ical/model"
+ "htwkalender/ical/model"
"regexp"
)
diff --git a/services/ical/service/names/userDefinedNameTemplates_test.go b/services/ical/service/names/userDefinedNameTemplates_test.go
index bb5ee2b..8915551 100644
--- a/services/ical/service/names/userDefinedNameTemplates_test.go
+++ b/services/ical/service/names/userDefinedNameTemplates_test.go
@@ -17,7 +17,7 @@
package names
import (
- "htwkalender-ical/model"
+ "htwkalender/ical/model"
"testing"
)
diff --git a/services/ical/service/routes.go b/services/ical/service/routes.go
index ee59f0f..3aa0381 100644
--- a/services/ical/service/routes.go
+++ b/services/ical/service/routes.go
@@ -3,26 +3,25 @@ package service
import (
"encoding/json"
"github.com/gofiber/fiber/v3"
- "github.com/gofiber/fiber/v3/log"
- "htwkalender-ical/model"
- "htwkalender-ical/service/ical"
+ "htwkalender/ical/model"
+ "htwkalender/ical/service/ical"
"log/slog"
"net/http"
)
// AddFeedRoutes add routes to the app instance for the data-manager ical service
// with golang fiber
-func AddFeedRoutes(app *fiber.App) {
+func AddFeedRoutes(app model.AppType) {
// Define a route for the GET method on the root path '/'
- app.Get("/api/feed", func(c fiber.Ctx) error {
+ app.Fiber.Get("/api/feed", func(c fiber.Ctx) error {
token := c.Query("token")
- results, err := ical.Feed(token)
+ results, err := ical.Feed(app, token)
if err != nil {
- slog.Error("Failed to get feed", "error", err)
- return c.SendStatus(fiber.StatusInternalServerError)
+ slog.Error("Failed to get feed", "error", err, "token", token)
+ return c.SendStatus(fiber.StatusBadRequest)
}
c.Response().Header.Set("Content-type", "text/calendar")
c.Response().Header.Set("charset", "utf-8")
@@ -33,75 +32,75 @@ func AddFeedRoutes(app *fiber.App) {
})
// Define a route for the POST method on the root path '/api/feed'
- app.Post("/api/feed", func(c fiber.Ctx) error {
+ app.Fiber.Post("/api/feed", func(c fiber.Ctx) error {
var modules []model.FeedCollection
//obtain the body of the request
err := json.Unmarshal(c.Body(), &modules)
if err != nil {
- log.Error("Failed to unmarshal request body", "error", err)
+ slog.Error("Failed to parse request body", "error", err, "body", string(c.Body()))
return c.SendStatus(fiber.StatusBadRequest)
}
//create a new feed
- token, err := ical.CreateFeed(modules)
+ token, err := ical.CreateFeed(app, modules)
if err != nil {
println(err)
- log.Error("Failed to create feed", "error", err)
- return c.SendStatus(fiber.StatusInternalServerError)
+ slog.Error("Failed to create feed", "error", err)
+ return c.SendStatus(fiber.StatusBadRequest)
}
return c.JSON(token)
})
// Define a route for the GET method on the root path '/'
- app.Get("/api/collections/feeds/records/:token", func(c fiber.Ctx) error {
+ app.Fiber.Get("/api/collections/feeds/records/:token", func(c fiber.Ctx) error {
token := c.Params("token")
- results, err := ical.FeedRecord(token)
+ results, err := ical.FeedRecord(app, token)
if err != nil {
- slog.Error("Failed to get feed", "error", err)
- return c.SendStatus(fiber.StatusInternalServerError)
+ slog.Error("Failed to get feed", "error", err, "token", token)
+ return c.SendStatus(fiber.StatusBadRequest)
}
c.Response().Header.Set("Content-type", "application/json; charset=UTF-8")
return c.JSON(results)
})
- app.Delete("/api/feed", func(c fiber.Ctx) error {
+ app.Fiber.Delete("/api/feed", func(c fiber.Ctx) error {
token := c.Query("token")
- err := ical.DeleteFeedRecord(token)
+ err := ical.DeleteFeedRecord(app, token)
if err != nil {
- slog.Error("Feed could not be deleted", "error", err)
+ slog.Error("Feed could not be deleted", "error", err, "token", token)
return c.JSON(http.StatusNotFound, "Feed could not be deleted")
} else {
return c.JSON(http.StatusOK, "Feed deleted")
}
})
- app.Put("/api/feed", func(c fiber.Ctx) error {
+ app.Fiber.Put("/api/feed", func(c fiber.Ctx) error {
token := c.Query("token")
return c.JSON(http.StatusOK, "token: "+token)
})
- app.Head("/api/feed", func(c fiber.Ctx) error {
+ app.Fiber.Head("/api/feed", func(c fiber.Ctx) error {
return c.JSON(http.StatusOK, "")
})
- app.Add([]string{"PROPFIND"}, "/api/feed", func(c fiber.Ctx) error {
+ app.Fiber.Add([]string{"PROPFIND"}, "/api/feed", func(c fiber.Ctx) error {
return c.JSON(http.StatusOK, "")
})
// Route for Thunderbird to get calendar server information
// Response is a 200 OK without additional content
- app.Add([]string{"PROPFIND"}, "/.well-known/caldav", func(c fiber.Ctx) error {
+ app.Fiber.Add([]string{"PROPFIND"}, "/.well-known/caldav", func(c fiber.Ctx) error {
return c.JSON(http.StatusOK, "")
})
// Route for Thunderbird to get calendar server information
// Response is a 200 OK without additional content
- app.Add([]string{"PROPFIND"}, "/", func(c fiber.Ctx) error {
+ app.Fiber.Add([]string{"PROPFIND"}, "/", func(c fiber.Ctx) error {
return c.JSON(http.StatusOK, "")
})
diff --git a/services/protobuf/feeds.proto b/services/protobuf/feeds.proto
new file mode 100644
index 0000000..7580cbd
--- /dev/null
+++ b/services/protobuf/feeds.proto
@@ -0,0 +1,23 @@
+syntax = "proto3";
+
+option go_package = "htwkalender/common/modules";
+
+service FeedService {
+ rpc GetFeed(GetFeedRequest) returns (GetFeedResponse) {}
+}
+
+message Feed {
+ string id = 1;
+ string modules = 2;
+ string retrieved = 3;
+ string created = 4;
+ string updated = 5;
+}
+
+message GetFeedRequest {
+ string id = 1;
+}
+
+message GetFeedResponse {
+ Feed feed = 1;
+}
\ No newline at end of file
diff --git a/services/protobuf/modules.proto b/services/protobuf/modules.proto
new file mode 100644
index 0000000..1ba6c27
--- /dev/null
+++ b/services/protobuf/modules.proto
@@ -0,0 +1,55 @@
+syntax = "proto3";
+
+option go_package = "htwkalender/common/modules";
+
+service ModuleService {
+ rpc GetModule(GetModuleRequest) returns (GetModuleResponse) {}
+ rpc GetModules(GetModulesRequest) returns (GetModulesResponse) {}
+ rpc GetEventsForModules(GetModulesRequest) returns (GetEventsResponse) {}
+}
+
+message Event {
+ string uuid = 1;
+ string day = 2;
+ string week = 3;
+ string start = 4;
+ string end = 5;
+ string name = 6;
+ string eventType = 7;
+ string compulsory = 8;
+ string prof = 9;
+ string rooms = 10;
+ string notes = 11;
+ string bookedAt = 12;
+ string course = 13;
+ string semester = 14;
+}
+
+message Module {
+ string uuid = 1;
+ string name = 2;
+ string prof = 3;
+ string course = 4;
+ string semester = 5;
+ repeated Event events = 6;
+}
+
+message GetModuleRequest {
+ string uuid = 1;
+}
+
+message GetModulesRequest {
+ repeated string uuids = 1;
+}
+
+message GetModuleResponse {
+ Module module = 1;
+}
+
+message GetModulesResponse {
+ repeated Module modules = 1;
+}
+
+message GetEventsResponse {
+ repeated Event events = 1;
+}
\ No newline at end of file