From 15734b1bff25aadcc7dca99398b8190a9da087e2 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Mon, 8 Dec 2025 21:39:26 +0300 Subject: [PATCH 01/14] Add SSO configuration and GRPC client for admin checks --- cmd/grpc/main.go | 2 +- config/local.yaml | 3 +++ go.mod | 15 ++++++----- go.sum | 6 +++++ internal/config/config.go | 1 + internal/config/sso.go | 6 +++++ internal/infra/mock/is_admin_provider.go | 32 ++++++++++++++++++------ 7 files changed, 49 insertions(+), 16 deletions(-) create mode 100644 internal/config/sso.go diff --git a/cmd/grpc/main.go b/cmd/grpc/main.go index c2b4284..47871c3 100644 --- a/cmd/grpc/main.go +++ b/cmd/grpc/main.go @@ -34,7 +34,7 @@ func main() { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := mock.NewIsAdminProvider() + mockIAP := mock.NewIsAdminProvider(cfg.Sso) jPub, jSub := watermill.NewJobPubSubGoChannels(l) diff --git a/config/local.yaml b/config/local.yaml index fc3c784..4f723c5 100644 --- a/config/local.yaml +++ b/config/local.yaml @@ -11,3 +11,6 @@ postgres: storage: base_path: "uploads" +sso: + host: "localhost" + port: "44044" \ No newline at end of file diff --git a/go.mod b/go.mod index 23434f4..0fb2d16 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,9 @@ module github.com/bmstu-itstech/scriptum-back -go 1.24.0 - -toolchain go1.24.3 +go 1.25.0 require ( + github.com/BOBAvov/protos_sso v0.0.17 github.com/ThreeDotsLabs/watermill v1.5.1 github.com/fatih/color v1.18.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 @@ -15,7 +14,7 @@ require ( github.com/stretchr/testify v1.11.1 github.com/zhikh23/pgutils v1.1.3 google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 - google.golang.org/grpc v1.74.2 + google.golang.org/grpc v1.76.0 google.golang.org/protobuf v1.36.10 ) @@ -52,11 +51,11 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel v1.36.0 // indirect - go.opentelemetry.io/otel/metric v1.36.0 // indirect - go.opentelemetry.io/otel/trace v1.36.0 // indirect + go.opentelemetry.io/otel v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.35.0 // indirect golang.org/x/text v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 868a5a6..9255b4a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BOBAvov/protos_sso v0.0.17/go.mod h1:+bhsk/b46aqFYW3w8q01IxAiL914SpU5UicLhg/Nrx0= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ThreeDotsLabs/watermill v1.5.1 h1:t5xMivyf9tpmU3iozPqyrCZXHvoV1XQDfihas4sV0fY= @@ -103,18 +104,22 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRND go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= @@ -125,6 +130,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/config/config.go b/internal/config/config.go index 6c0ad4f..9ef1f88 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,6 +12,7 @@ type Config struct { Logging Logging Postgres Postgres Storage Storage + Sso SSO } func Load(path string) (*Config, error) { diff --git a/internal/config/sso.go b/internal/config/sso.go new file mode 100644 index 0000000..4a547cb --- /dev/null +++ b/internal/config/sso.go @@ -0,0 +1,6 @@ +package config + +type SSO struct { + Host string + Port string +} diff --git a/internal/infra/mock/is_admin_provider.go b/internal/infra/mock/is_admin_provider.go index 5cd11a3..e774dfd 100644 --- a/internal/infra/mock/is_admin_provider.go +++ b/internal/infra/mock/is_admin_provider.go @@ -2,20 +2,38 @@ package mock import ( "context" + "log" + ssov1 "github.com/BOBAvov/protos_sso/gen/go/sso" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + "github.com/bmstu-itstech/scriptum-back/internal/config" "github.com/bmstu-itstech/scriptum-back/internal/domain/value" ) -type IsAdminProvider struct { - admins map[value.UserID]bool +type SSO struct { + api ssov1.AuthClient } -func NewIsAdminProvider() *IsAdminProvider { - return &IsAdminProvider{ - admins: make(map[value.UserID]bool), +func NewIsAdminProvider(config config.SSO) *SSO { + addr := config.Host + ":" + config.Port + cc, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + log.Fatal("did not connect: ", err) + return nil + } + return &SSO{ + api: ssov1.NewAuthClient(cc), } } -func (i *IsAdminProvider) IsAdmin(_ context.Context, uid value.UserID) (bool, error) { - return i.admins[uid], nil +func (i *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { + resp, err := i.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ + UserId: int64(uid), + }) + if err != nil { + return false, err + } + return resp.IsAdmin, nil } From 5a71efa25250f242230d97bb012036efd1bb568d Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Mon, 8 Dec 2025 21:43:48 +0300 Subject: [PATCH 02/14] Add SSO configuration and GRPC client for admin checks --- config/local.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/local.yaml b/config/local.yaml index 4f723c5..5f4313e 100644 --- a/config/local.yaml +++ b/config/local.yaml @@ -13,4 +13,4 @@ storage: sso: host: "localhost" - port: "44044" \ No newline at end of file + port: "44044" From 2f46fa24b762841aa09c3b4675027deaf4f6584b Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Mon, 8 Dec 2025 22:00:42 +0300 Subject: [PATCH 03/14] Rename IsAdminProvider to SSOClient and fix naming inconsistencies --- cmd/grpc/main.go | 2 +- internal/config/config.go | 2 +- internal/infra/mock/is_admin_provider.go | 4 ++-- tests/suite/suite.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/grpc/main.go b/cmd/grpc/main.go index 47871c3..5f20eff 100644 --- a/cmd/grpc/main.go +++ b/cmd/grpc/main.go @@ -34,7 +34,7 @@ func main() { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := mock.NewIsAdminProvider(cfg.Sso) + mockIAP := mock.NewSSOClient(cfg.SSO) jPub, jSub := watermill.NewJobPubSubGoChannels(l) diff --git a/internal/config/config.go b/internal/config/config.go index 9ef1f88..d0643e2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,7 +12,7 @@ type Config struct { Logging Logging Postgres Postgres Storage Storage - Sso SSO + SSO SSO } func Load(path string) (*Config, error) { diff --git a/internal/infra/mock/is_admin_provider.go b/internal/infra/mock/is_admin_provider.go index e774dfd..bcf646c 100644 --- a/internal/infra/mock/is_admin_provider.go +++ b/internal/infra/mock/is_admin_provider.go @@ -16,9 +16,9 @@ type SSO struct { api ssov1.AuthClient } -func NewIsAdminProvider(config config.SSO) *SSO { +func NewSSOClient(config config.SSO) *SSO { addr := config.Host + ":" + config.Port - cc, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal("did not connect: ", err) return nil diff --git a/tests/suite/suite.go b/tests/suite/suite.go index 1432263..9c14fe5 100644 --- a/tests/suite/suite.go +++ b/tests/suite/suite.go @@ -59,7 +59,7 @@ func New(t *testing.T) (context.Context, *Suite) { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := mock.NewIsAdminProvider() + mockIAP := mock.NewSSOClient(cfg.SSO) jPub, jSub := watermill.NewJobPubSubGoChannels(l) From b8ac57a13de0c9e8ca0b9f8430ed4181edd86a1e Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Mon, 8 Dec 2025 22:03:42 +0300 Subject: [PATCH 04/14] rename NewIsAdminProvider to NewSSOClient --- internal/infra/mock/is_admin_provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/infra/mock/is_admin_provider.go b/internal/infra/mock/is_admin_provider.go index bcf646c..be53855 100644 --- a/internal/infra/mock/is_admin_provider.go +++ b/internal/infra/mock/is_admin_provider.go @@ -18,6 +18,7 @@ type SSO struct { func NewSSOClient(config config.SSO) *SSO { addr := config.Host + ":" + config.Port + cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal("did not connect: ", err) From 3aea8963da9e2d5d8f5073b2221ee1fd3fb20162 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Tue, 9 Dec 2025 20:48:56 +0300 Subject: [PATCH 05/14] refactor: update package names and dependencies for SSO integration --- .golangci.yaml | 2 +- cmd/grpc/main.go | 4 +-- go.sum | 26 +++++++++---------- .../infra/{mock => sso}/is_admin_provider.go | 2 +- tests/suite/suite.go | 4 +-- 5 files changed, 18 insertions(+), 20 deletions(-) rename internal/infra/{mock => sso}/is_admin_provider.go (98%) diff --git a/.golangci.yaml b/.golangci.yaml index 6da0517..70c5b70 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -261,7 +261,7 @@ linters: - ^github.com/prometheus/client_golang/.+Opts$ - ^github.com/spf13/cobra.Command$ - ^github.com/spf13/cobra.CompletionOptions$ - - ^github.com/stretchr/testify/mock.Mock$ + - ^github.com/stretchr/testify/sso.Mock$ - ^github.com/testcontainers/testcontainers-go.+Request$ - ^github.com/testcontainers/testcontainers-go.FromDockerfile$ - ^golang.org/x/tools/go/analysis.Analyzer$ diff --git a/cmd/grpc/main.go b/cmd/grpc/main.go index 5f20eff..41c0ae9 100644 --- a/cmd/grpc/main.go +++ b/cmd/grpc/main.go @@ -16,8 +16,8 @@ import ( "github.com/bmstu-itstech/scriptum-back/internal/config" "github.com/bmstu-itstech/scriptum-back/internal/infra/docker" "github.com/bmstu-itstech/scriptum-back/internal/infra/local" - "github.com/bmstu-itstech/scriptum-back/internal/infra/mock" "github.com/bmstu-itstech/scriptum-back/internal/infra/postgres" + "github.com/bmstu-itstech/scriptum-back/internal/infra/sso" "github.com/bmstu-itstech/scriptum-back/internal/infra/watermill" "github.com/bmstu-itstech/scriptum-back/pkg/logs" "github.com/bmstu-itstech/scriptum-back/pkg/server" @@ -34,7 +34,7 @@ func main() { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := mock.NewSSOClient(cfg.SSO) + mockIAP := sso.NewSSOClient(cfg.SSO) jPub, jSub := watermill.NewJobPubSubGoChannels(l) diff --git a/go.sum b/go.sum index 9255b4a..ca5fc2d 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BOBAvov/protos_sso v0.0.17 h1:Dvhz4WnB8LNOKA5VE5RCCKWVqML1bdj6/Ck1f2vPKeU= github.com/BOBAvov/protos_sso v0.0.17/go.mod h1:+bhsk/b46aqFYW3w8q01IxAiL914SpU5UicLhg/Nrx0= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -102,23 +103,19 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= -go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= -go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= -go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= -go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= -go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= -go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= -go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -126,10 +123,11 @@ golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 h1:Wgl1rcDNThT+Zn47YyCXOXyX/COgMTIdhJ717F0l4xk= google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= -google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/internal/infra/mock/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go similarity index 98% rename from internal/infra/mock/is_admin_provider.go rename to internal/infra/sso/is_admin_provider.go index be53855..e141e12 100644 --- a/internal/infra/mock/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -1,4 +1,4 @@ -package mock +package sso import ( "context" diff --git a/tests/suite/suite.go b/tests/suite/suite.go index 9c14fe5..af7ea4f 100644 --- a/tests/suite/suite.go +++ b/tests/suite/suite.go @@ -20,8 +20,8 @@ import ( "github.com/bmstu-itstech/scriptum-back/internal/config" "github.com/bmstu-itstech/scriptum-back/internal/infra/docker" "github.com/bmstu-itstech/scriptum-back/internal/infra/local" - "github.com/bmstu-itstech/scriptum-back/internal/infra/mock" "github.com/bmstu-itstech/scriptum-back/internal/infra/postgres" + "github.com/bmstu-itstech/scriptum-back/internal/infra/sso" "github.com/bmstu-itstech/scriptum-back/internal/infra/watermill" "github.com/bmstu-itstech/scriptum-back/pkg/logs" "github.com/bmstu-itstech/scriptum-back/pkg/server/auth" @@ -59,7 +59,7 @@ func New(t *testing.T) (context.Context, *Suite) { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := mock.NewSSOClient(cfg.SSO) + mockIAP := sso.NewSSOClient(cfg.SSO) jPub, jSub := watermill.NewJobPubSubGoChannels(l) From c72aa93ba01d6ea685a82268613c445cb66ceae1 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Wed, 10 Dec 2025 10:56:12 +0300 Subject: [PATCH 06/14] refactor: update SSO client initialization and error handling --- cmd/grpc/main.go | 12 +++++-- internal/infra/sso/is_admin_provider.go | 43 ++++++++++++++++++------- tests/suite/suite.go | 9 +++++- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/cmd/grpc/main.go b/cmd/grpc/main.go index 41c0ae9..1c68aff 100644 --- a/cmd/grpc/main.go +++ b/cmd/grpc/main.go @@ -34,7 +34,15 @@ func main() { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := sso.NewSSOClient(cfg.SSO) + + ssoApi, closeFn := sso.MustNewSSOClient(cfg.SSO, l) + + defer func() { + err := closeFn() + if err != nil { + l.Error("failed to close SSO client", slog.String("error", err.Error())) + } + }() jPub, jSub := watermill.NewJobPubSubGoChannels(l) @@ -43,7 +51,7 @@ func main() { BoxRepo: repos, FileReader: storage, FileUploader: storage, - IsAdminProvider: mockIAP, + IsAdminProvider: ssoApi, JobProvider: repos, JobPublisher: jPub, JobRepository: repos, diff --git a/internal/infra/sso/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go index e141e12..c9eb969 100644 --- a/internal/infra/sso/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -2,39 +2,58 @@ package sso import ( "context" - "log" - ssov1 "github.com/BOBAvov/protos_sso/gen/go/sso" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "log/slog" "github.com/bmstu-itstech/scriptum-back/internal/config" "github.com/bmstu-itstech/scriptum-back/internal/domain/value" ) type SSO struct { - api ssov1.AuthClient + conn *grpc.ClientConn + api ssov1.AuthClient + l *slog.Logger +} + +func MustNewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error) { + sso, closeFn, err := NewSSOClient(config, l) + if err != nil { + panic("Error creating SSO client: " + err.Error()) + } + return sso, closeFn } -func NewSSOClient(config config.SSO) *SSO { +func NewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error, error) { addr := config.Host + ":" + config.Port cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - log.Fatal("did not connect: ", err) - return nil - } + closeFn := cc.Close + return &SSO{ - api: ssov1.NewAuthClient(cc), - } + api: ssov1.NewAuthClient(cc), + conn: cc, + l: l, + }, closeFn, err } -func (i *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { - resp, err := i.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ +// IsAdmin checks if the user with the given uid has admin privileges. uid is int64!!! +func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { + const op = "infra.SSO.IsAdmin" + + log := s.l.With(slog.String("op", op)) + log = log.With(slog.Int64("uid", int64(uid))) + + log.Debug("Checking admin status") + + resp, err := s.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ UserId: int64(uid), }) if err != nil { + log.Error("Failed to check admin status: ", err.Error()) return false, err } + log.Debug("Admin status: ", resp.IsAdmin) return resp.IsAdmin, nil } diff --git a/tests/suite/suite.go b/tests/suite/suite.go index af7ea4f..1d96042 100644 --- a/tests/suite/suite.go +++ b/tests/suite/suite.go @@ -2,6 +2,7 @@ package suite import ( "context" + "fmt" "math/rand/v2" "net" "os" @@ -59,7 +60,13 @@ func New(t *testing.T) (context.Context, *Suite) { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP := sso.NewSSOClient(cfg.SSO) + mockIAP, closeFn := sso.MustNewSSOClient(cfg.SSO, l) + defer func() { + err := closeFn() + if err != nil { + l.Error(fmt.Sprintf("failed to close sso client: %s", err.Error())) + } + }() jPub, jSub := watermill.NewJobPubSubGoChannels(l) From 804d52cc88ec2eb9f623759a7c064a6cb7b76197 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Wed, 10 Dec 2025 11:10:57 +0300 Subject: [PATCH 07/14] feat: add Dockerfile for building and running SSO service --- Dockerfile | 30 +++++++++++++++++++++++++ internal/infra/sso/is_admin_provider.go | 26 +++++++++++++-------- 2 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2015d24 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM golang:1.25-bookworm AS builder + +WORKDIR /src + +# Зависимости отдельно для кеша +COPY go.mod go.sum ./ +RUN go mod download + +# Исходники +COPY . . + +# Сборка бинарника (статически, без CGO) +RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/sso ./cmd/sso + + +FROM gcr.io/distroless/static:nonroot + +WORKDIR /app + +# Режим gin = release +ENV GIN_MODE=release + +# Бинарник +COPY --from=builder /out/sso /app/sso + +# Порт из конфигурации +EXPOSE 8080 + +# Запуск +ENTRYPOINT ["/app/sso"] diff --git a/internal/infra/sso/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go index c9eb969..f06a2a8 100644 --- a/internal/infra/sso/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -6,6 +6,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "log/slog" + "net" "github.com/bmstu-itstech/scriptum-back/internal/config" "github.com/bmstu-itstech/scriptum-back/internal/domain/value" @@ -26,34 +27,41 @@ func MustNewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error) { } func NewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error, error) { - addr := config.Host + ":" + config.Port - + addr := net.JoinHostPort(config.Host, config.Port) cc, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, func() error { return nil }, err + } + closeFn := cc.Close return &SSO{ api: ssov1.NewAuthClient(cc), conn: cc, l: l, - }, closeFn, err + }, closeFn, nil } // IsAdmin checks if the user with the given uid has admin privileges. uid is int64!!! func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { - const op = "infra.SSO.IsAdmin" + const op = "sso.SSO.IsAdmin" - log := s.l.With(slog.String("op", op)) - log = log.With(slog.Int64("uid", int64(uid))) + l := s.l.With( + slog.String("op", op), + slog.Int64("uid", int64(uid)), + ) - log.Debug("Checking admin status") + l.Debug("Checking admin status") resp, err := s.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ UserId: int64(uid), }) if err != nil { - log.Error("Failed to check admin status: ", err.Error()) + l.Error("Failed to check admin status: ", err.Error()) return false, err } - log.Debug("Admin status: ", resp.IsAdmin) + + l.Debug("Admin status: ", resp.IsAdmin) + return resp.IsAdmin, nil } From b44b6889cb4ebfb5823af55b6fcb031a967ab2ef Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Wed, 10 Dec 2025 11:47:41 +0300 Subject: [PATCH 08/14] up Dockerfile to goland:1.25 --- Dockerfile | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2015d24..91feb73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,30 +1,20 @@ -FROM golang:1.25-bookworm AS builder +FROM golang:1.25-alpine AS builder -WORKDIR /src +WORKDIR /app -# Зависимости отдельно для кеша COPY go.mod go.sum ./ RUN go mod download -# Исходники COPY . . -# Сборка бинарника (статически, без CGO) -RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/sso ./cmd/sso - - -FROM gcr.io/distroless/static:nonroot - -WORKDIR /app +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app ./cmd/grpc/main.go -# Режим gin = release -ENV GIN_MODE=release +FROM alpine:latest -# Бинарник -COPY --from=builder /out/sso /app/sso +WORKDIR /root/ -# Порт из конфигурации -EXPOSE 8080 +COPY --from=builder /app/app . +COPY --from=builder /app/config/ /etc/app/ -# Запуск -ENTRYPOINT ["/app/sso"] +ENTRYPOINT ["./app"] +CMD ["--config /etc/app/local.yaml"] \ No newline at end of file From 602c447260ed99fee5d32152df4e6d590944b6a5 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Sat, 13 Dec 2025 23:20:01 +0300 Subject: [PATCH 09/14] feat: add AppId to SSO configuration and update SSO client initialization --- config/local.yaml | 1 + go.mod | 1 + go.sum | 4 ++++ internal/config/config.go | 5 +++-- internal/infra/sso/is_admin_provider.go | 29 +++++++++++++++---------- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/config/local.yaml b/config/local.yaml index 20822d0..c6ea94d 100644 --- a/config/local.yaml +++ b/config/local.yaml @@ -11,3 +11,4 @@ storage: sso: host: "localhost" port: "44044" + app_id: 1 diff --git a/go.mod b/go.mod index 0fb2d16..b2e86ad 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/bmstu-itstech/sso v0.0.0-20251213182333-2ddc5c909188 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index ca5fc2d..6a6d307 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,10 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ThreeDotsLabs/watermill v1.5.1 h1:t5xMivyf9tpmU3iozPqyrCZXHvoV1XQDfihas4sV0fY= github.com/ThreeDotsLabs/watermill v1.5.1/go.mod h1:Uop10dA3VeJWsSvis9qO3vbVY892LARrKAdki6WtXS4= +github.com/bmstu-itstech/sso v0.0.0-20251205155522-708f9ee1be4d h1:7ih43sInLRb07sPn7ejDu3+MXNxX9XrWz6JQjXngRMc= +github.com/bmstu-itstech/sso v0.0.0-20251205155522-708f9ee1be4d/go.mod h1:2NBqeXeHbRJYQLYijEOJhLMHeXYxhywpUge6q4kSefk= +github.com/bmstu-itstech/sso v0.0.0-20251213182333-2ddc5c909188 h1:qodByqKo7PxHbSRPvEKgaWVYdw2zty6Y2t0MneTWyp8= +github.com/bmstu-itstech/sso v0.0.0-20251213182333-2ddc5c909188/go.mod h1:2NBqeXeHbRJYQLYijEOJhLMHeXYxhywpUge6q4kSefk= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= diff --git a/internal/config/config.go b/internal/config/config.go index ce55382..8f2edbe 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -39,8 +39,9 @@ type Storage struct { } type SSO struct { - Host string `mapstructure:"host"` - Port string `mapstructure:"port"` + Host string `mapstructure:"host"` + Port string `mapstructure:"port"` + AppId int32 `mapstructure:"app_id"` } func Load(path string) (*Config, error) { diff --git a/internal/infra/sso/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go index f06a2a8..9d55cb4 100644 --- a/internal/infra/sso/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -3,19 +3,21 @@ package sso import ( "context" ssov1 "github.com/BOBAvov/protos_sso/gen/go/sso" + "github.com/bmstu-itstech/scriptum-back/internal/config" + "github.com/bmstu-itstech/scriptum-back/internal/domain/value" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/metadata" "log/slog" "net" - - "github.com/bmstu-itstech/scriptum-back/internal/config" - "github.com/bmstu-itstech/scriptum-back/internal/domain/value" + "strconv" ) type SSO struct { - conn *grpc.ClientConn - api ssov1.AuthClient - l *slog.Logger + conn *grpc.ClientConn + api ssov1.AuthClient + l *slog.Logger + AppId int32 } func MustNewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error) { @@ -36,15 +38,16 @@ func NewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error, error) closeFn := cc.Close return &SSO{ - api: ssov1.NewAuthClient(cc), - conn: cc, - l: l, + api: ssov1.NewAuthClient(cc), + conn: cc, + l: l, + AppId: config.AppId, }, closeFn, nil } // IsAdmin checks if the user with the given uid has admin privileges. uid is int64!!! func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { - const op = "sso.SSO.IsAdmin" + const op = "infra.SSO.IsAdmin" l := s.l.With( slog.String("op", op), @@ -52,7 +55,11 @@ func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { ) l.Debug("Checking admin status") - + // Добавляем метаданные с AppId + ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs( + "x-user-id", strconv.FormatInt(int64(s.AppId), 10), + )) + // Вызываем метод IsAdmin на сервере SSO resp, err := s.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ UserId: int64(uid), }) From fcaf9e7f5fc5a8104ed40a1ef40764d674421be5 Mon Sep 17 00:00:00 2001 From: Kirill Zhikharev <130099896+zhikh23@users.noreply.github.com> Date: Sat, 13 Dec 2025 23:58:56 +0300 Subject: [PATCH 10/14] fix: apply suggestions from code review Copilot suggestions Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .golangci.yaml | 2 +- Dockerfile | 9 ++++++++- internal/config/config.go | 2 +- internal/infra/sso/is_admin_provider.go | 6 +++--- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 70c5b70..6da0517 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -261,7 +261,7 @@ linters: - ^github.com/prometheus/client_golang/.+Opts$ - ^github.com/spf13/cobra.Command$ - ^github.com/spf13/cobra.CompletionOptions$ - - ^github.com/stretchr/testify/sso.Mock$ + - ^github.com/stretchr/testify/mock.Mock$ - ^github.com/testcontainers/testcontainers-go.+Request$ - ^github.com/testcontainers/testcontainers-go.FromDockerfile$ - ^golang.org/x/tools/go/analysis.Analyzer$ diff --git a/Dockerfile b/Dockerfile index 171fd9d..c06ee15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,10 +11,17 @@ RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app ./cmd/grpc/ma FROM alpine:latest -WORKDIR /root/ +# Create an unprivileged user and group +RUN addgroup -S appgroup && adduser -S appuser -G appgroup + +WORKDIR /home/appuser COPY --from=builder /app/app . COPY --from=builder /app/config/ /etc/app/ +# Change ownership of files to appuser +RUN chown -R appuser:appgroup /home/appuser /etc/app + +USER appuser ENTRYPOINT ["./app"] CMD ["--config /etc/app/local.yaml"] diff --git a/internal/config/config.go b/internal/config/config.go index 8f2edbe..23f567a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -41,7 +41,7 @@ type Storage struct { type SSO struct { Host string `mapstructure:"host"` Port string `mapstructure:"port"` - AppId int32 `mapstructure:"app_id"` + AppID int32 `mapstructure:"app_id"` } func Load(path string) (*Config, error) { diff --git a/internal/infra/sso/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go index 9d55cb4..383c9b7 100644 --- a/internal/infra/sso/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -45,7 +45,7 @@ func NewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error, error) }, closeFn, nil } -// IsAdmin checks if the user with the given uid has admin privileges. uid is int64!!! +// IsAdmin checks if the user with the given uid has admin privileges. Note: uid parameter is of type value.UserID but is converted to int64 for the gRPC call. func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { const op = "infra.SSO.IsAdmin" @@ -64,11 +64,11 @@ func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { UserId: int64(uid), }) if err != nil { - l.Error("Failed to check admin status: ", err.Error()) + l.Error("Failed to check admin status", slog.String("error", err.Error())) return false, err } - l.Debug("Admin status: ", resp.IsAdmin) + l.Debug("Admin status", slog.Bool("is_admin", resp.IsAdmin)) return resp.IsAdmin, nil } From d3ebb6be1947cb3b7bbbd427f9a523fcf091eb5c Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Sun, 14 Dec 2025 00:04:43 +0300 Subject: [PATCH 11/14] fix: correct AppId to AppID in SSO client and update related metadata --- internal/infra/sso/is_admin_provider.go | 15 ++++++++------- tests/suite/suite.go | 9 +++++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/internal/infra/sso/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go index 9d55cb4..92d23ba 100644 --- a/internal/infra/sso/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -17,7 +17,7 @@ type SSO struct { conn *grpc.ClientConn api ssov1.AuthClient l *slog.Logger - AppId int32 + AppID int32 } func MustNewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error) { @@ -41,11 +41,12 @@ func NewSSOClient(config config.SSO, l *slog.Logger) (*SSO, func() error, error) api: ssov1.NewAuthClient(cc), conn: cc, l: l, - AppId: config.AppId, + AppID: config.AppId, }, closeFn, nil } -// IsAdmin checks if the user with the given uid has admin privileges. uid is int64!!! +// IsAdmin checks if the user with the given uid has admin privileges. +// Note: uid parameter is of type value.UserID but is converted to int64 for the gRPC call. func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { const op = "infra.SSO.IsAdmin" @@ -55,20 +56,20 @@ func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { ) l.Debug("Checking admin status") - // Добавляем метаданные с AppId + // Добавляем метаданные с AppID ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs( - "x-user-id", strconv.FormatInt(int64(s.AppId), 10), + "x-user-id", strconv.FormatInt(int64(s.AppID), 10), )) // Вызываем метод IsAdmin на сервере SSO resp, err := s.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ UserId: int64(uid), }) if err != nil { - l.Error("Failed to check admin status: ", err.Error()) + l.Error("Failed to check admin status: ", slog.String("error", err.Error())) return false, err } - l.Debug("Admin status: ", resp.IsAdmin) + l.Debug("Admin status", slog.Bool("is_admin", resp.IsAdmin)) return resp.IsAdmin, nil } diff --git a/tests/suite/suite.go b/tests/suite/suite.go index 1d96042..b6d01d1 100644 --- a/tests/suite/suite.go +++ b/tests/suite/suite.go @@ -50,6 +50,11 @@ func suiteConfig() config.Config { Storage: config.Storage{ BasePath: "../uploads", }, + SSO: config.SSO{ + Host: os.Getenv("SSO_HOST"), + Port: os.Getenv("SSO_PORT"), + AppId: 1, + }, } } @@ -60,7 +65,7 @@ func New(t *testing.T) (context.Context, *Suite) { repos := postgres.MustNewRepository(cfg.Postgres, l) runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) - mockIAP, closeFn := sso.MustNewSSOClient(cfg.SSO, l) + ssoApi, closeFn := sso.MustNewSSOClient(cfg.SSO, l) defer func() { err := closeFn() if err != nil { @@ -75,7 +80,7 @@ func New(t *testing.T) (context.Context, *Suite) { BoxRepo: repos, FileReader: storage, FileUploader: storage, - IsAdminProvider: mockIAP, + IsAdminProvider: ssoApi, JobProvider: repos, JobPublisher: jPub, JobRepository: repos, From f97e47c7a6dadca93dce9a5f452577e281863e78 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Sun, 14 Dec 2025 00:09:03 +0300 Subject: [PATCH 12/14] fix: correct AppId to AppID in SSO client and update related metadata --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index b2e86ad..0fb2d16 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,6 @@ require ( require ( github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/bmstu-itstech/sso v0.0.0-20251213182333-2ddc5c909188 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect From a0b201967924a1670fa9fb66c107ffe18ab18757 Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Sun, 14 Dec 2025 00:26:54 +0300 Subject: [PATCH 13/14] fix: correct AppId to AppID in SSO configuration and update comments for clarity --- internal/infra/sso/is_admin_provider.go | 6 +++--- tests/suite/suite.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/infra/sso/is_admin_provider.go b/internal/infra/sso/is_admin_provider.go index ecef1a6..0423ae2 100644 --- a/internal/infra/sso/is_admin_provider.go +++ b/internal/infra/sso/is_admin_provider.go @@ -56,16 +56,16 @@ func (s *SSO) IsAdmin(ctx context.Context, uid value.UserID) (bool, error) { ) l.Debug("Checking admin status") - // Добавляем метаданные с AppID + // Add metadata with application ID to the context ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs( "x-user-id", strconv.FormatInt(int64(s.AppID), 10), )) - // Вызываем метод IsAdmin на сервере SSO + // Call the IsAdmin method on the SSO server resp, err := s.api.IsAdmin(ctx, &ssov1.IsAdminRequest{ UserId: int64(uid), }) if err != nil { - l.Error("Failed to check admin status: ", slog.String("error", err.Error())) + l.Error("Failed to check admin status", slog.String("error", err.Error())) return false, err } diff --git a/tests/suite/suite.go b/tests/suite/suite.go index b6d01d1..d3c2225 100644 --- a/tests/suite/suite.go +++ b/tests/suite/suite.go @@ -53,7 +53,7 @@ func suiteConfig() config.Config { SSO: config.SSO{ Host: os.Getenv("SSO_HOST"), Port: os.Getenv("SSO_PORT"), - AppId: 1, + AppID: 1, }, } } @@ -66,12 +66,12 @@ func New(t *testing.T) (context.Context, *Suite) { runner := docker.MustNewRunner(cfg.Docker, l) storage := local.MustNewStorage(cfg.Storage, l) ssoApi, closeFn := sso.MustNewSSOClient(cfg.SSO, l) - defer func() { + t.Cleanup(func() { err := closeFn() if err != nil { l.Error(fmt.Sprintf("failed to close sso client: %s", err.Error())) } - }() + }) jPub, jSub := watermill.NewJobPubSubGoChannels(l) From d469252c5d36d5571424214d6f428429d928a52e Mon Sep 17 00:00:00 2001 From: BOBAvov Date: Sun, 28 Dec 2025 16:39:40 +0300 Subject: [PATCH 14/14] update easyp.yaml --- easyp.lock | 4 ++-- easyp.yaml | 44 ++++++++++++++++++++++++++++---------------- go.sum | 4 ---- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/easyp.lock b/easyp.lock index 8c69247..2303fd7 100644 --- a/easyp.lock +++ b/easyp.lock @@ -1,2 +1,2 @@ -github.com/googleapis/googleapis common-protos-1_3_1 h1:s8d5N7+VjksySahU4JpUGSju5SqkmQNtweRfsin9SyM= -github.com/grpc-ecosystem/grpc-gateway v0.0.0-20251127211339-d2d5e587243b4254ac96b76ce19636e0fd734a5e h1:qihtPAOYuB5MmdtIx/0GX3DZrVBCp/kZz2iolgsuOys= +github.com/googleapis/googleapis common-protos-1_3_1 h1:TsE+JW4H/zsB0phfwMO1DragQ4oaGfoVuGHV5aGfn2I= +github.com/grpc-ecosystem/grpc-gateway v0.0.0-20251127211339-d2d5e587243b4254ac96b76ce19636e0fd734a5e h1:48F3p4F2740v+ZV/mCXiBwQcK+LBbN8h+alOaIx9BD0= diff --git a/easyp.yaml b/easyp.yaml index 43ecb7d..21dbd96 100644 --- a/easyp.yaml +++ b/easyp.yaml @@ -1,19 +1,31 @@ -version: v1alpha lint: - use: - - DEFAULT + use: + - DEFAULT deps: - - github.com/googleapis/googleapis@common-protos-1_3_1 - - github.com/grpc-ecosystem/grpc-gateway + - github.com/googleapis/googleapis@common-protos-1_3_1 + - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 generate: - inputs: - - directory: "api/v2" - plugins: - - name: go - out: gen/go - opt: - paths: source_relative - - name: go-grpc - out: gen/go - opt: - paths: source_relative + inputs: + - directory: "api/v2" + plugins: + - name: go + out: gen/go + opt: + paths: source_relative + module: "github.com/bmstu-itstech/scriptum-back" + with_imports: true + + - name: go-grpc + out: gen/go + opt: + paths: source_relative + + - name: grpc-gateway + out: gen/go + opts: + paths: source_relative + + - name: openapiv2 + out: ./gen/openapi + opts: + simple_operation_ids: true diff --git a/go.sum b/go.sum index 6a6d307..ca5fc2d 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,6 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ThreeDotsLabs/watermill v1.5.1 h1:t5xMivyf9tpmU3iozPqyrCZXHvoV1XQDfihas4sV0fY= github.com/ThreeDotsLabs/watermill v1.5.1/go.mod h1:Uop10dA3VeJWsSvis9qO3vbVY892LARrKAdki6WtXS4= -github.com/bmstu-itstech/sso v0.0.0-20251205155522-708f9ee1be4d h1:7ih43sInLRb07sPn7ejDu3+MXNxX9XrWz6JQjXngRMc= -github.com/bmstu-itstech/sso v0.0.0-20251205155522-708f9ee1be4d/go.mod h1:2NBqeXeHbRJYQLYijEOJhLMHeXYxhywpUge6q4kSefk= -github.com/bmstu-itstech/sso v0.0.0-20251213182333-2ddc5c909188 h1:qodByqKo7PxHbSRPvEKgaWVYdw2zty6Y2t0MneTWyp8= -github.com/bmstu-itstech/sso v0.0.0-20251213182333-2ddc5c909188/go.mod h1:2NBqeXeHbRJYQLYijEOJhLMHeXYxhywpUge6q4kSefk= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=