diff --git a/internal/dao/project.go b/internal/dao/project.go index dccbc4e..04f1800 100644 --- a/internal/dao/project.go +++ b/internal/dao/project.go @@ -9,7 +9,7 @@ import ( "github.com/uptrace/bun" ) -func GetProjectOrganization(ctx context.Context, db bun.IDB, id uuid.UUID) (string, string, error) { +func GetProjectOrganization(ctx context.Context, db bun.IDB, name string) (string, string, error) { type projectOrg struct { Project string Organization string @@ -19,7 +19,7 @@ func GetProjectOrganization(ctx context.Context, db bun.IDB, id uuid.UUID) (stri ColumnExpr("authsrv_project.name as project"). ColumnExpr("authsrv_organization.name as organization"). Join(`JOIN authsrv_organization ON authsrv_project.organization_id=authsrv_organization.id`). - Where("authsrv_project.id = ?", id). + Where("authsrv_project.name = ?", name). Where("authsrv_project.trash = ?", false). Where("authsrv_organization.trash = ?", false). Scan(ctx, &r) diff --git a/pkg/auth/v3/middleware.go b/pkg/auth/v3/middleware.go index 3e220be..804f70b 100644 --- a/pkg/auth/v3/middleware.go +++ b/pkg/auth/v3/middleware.go @@ -9,7 +9,6 @@ import ( "github.com/RafayLabs/rcloud-base/internal/dao" "github.com/RafayLabs/rcloud-base/pkg/common" commonpbv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3" - "github.com/google/uuid" "github.com/uptrace/bun" "github.com/urfave/negroni" "go.uber.org/zap" @@ -48,24 +47,17 @@ func (am *authMiddleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, nex var org string if strings.HasPrefix(r.URL.String(), "/v2/debug/prompt/project/") { - // /v2/debug/prompt/project/:project_id/cluster/:cluster_name + // /v2/debug/prompt/project/:project/cluster/:cluster_name splits := strings.Split(r.URL.String(), "/") if len(splits) > 5 { - projid, err := uuid.Parse(splits[5]) - if err != nil { - _log.Errorf("Failed to authenticate: unable to parse project uuid") - http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden) - return - } - // What gets sent for project is the id unlike most other - // api routes, so we have to fetch the name as well as the - // org info for casbin - proj, org, err = dao.GetProjectOrganization(r.Context(), am.db, projid) + // we have to fetch the org info for casbin + proj, org, err := dao.GetProjectOrganization(r.Context(), am.db, splits[5]) if err != nil { _log.Errorf("Failed to authenticate: unable to find project") http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden) return } + _log.Info("found project with organization %s %s", proj, org) } } else { // The middleware to only used with routes which does not have diff --git a/pkg/service/project.go b/pkg/service/project.go index 175e691..86318d2 100644 --- a/pkg/service/project.go +++ b/pkg/service/project.go @@ -200,6 +200,7 @@ func (s *projectService) GetByName(ctx context.Context, name string) (*systemv3. project.Metadata = &v3.Metadata{ Name: proj.Name, Description: proj.Description, + Id: proj.ID.String(), Organization: org.Name, Partner: partner.Name, ModifiedAt: timestamppb.New(proj.ModifiedAt), diff --git a/proto/rpc/system/internal.go b/proto/rpc/system/internal.go new file mode 100644 index 0000000..df2fde8 --- /dev/null +++ b/proto/rpc/system/internal.go @@ -0,0 +1,110 @@ +package rpcv3 + +import ( + "context" + + "github.com/RafayLabs/rcloud-base/pkg/pool" + grpcpool "github.com/processout/grpc-go-pool" +) + +// SystemClient is the interface for accessing all the RPCs +// exposed by Rafay Base +type SystemClient interface { + Unhealthy() + Close() error + ProjectClient + OrganizationClient + PartnerClient +} + +type systemClient struct { + *grpcpool.ClientConn + *projectClient + *organizationClient + *partnerClient +} + +var _ SystemClient = (*systemClient)(nil) + +// SystemPool maintains pool of grpc connections to system base services +type SystemPool interface { + Close() + NewClient(ctx context.Context) (SystemClient, error) +} + +// NewSystemPool new system pool +func NewSystemPool(addr string, maxConn int) SystemPool { + return &systemPool{ + GRPCPool: pool.NewGRPCPool(addr, maxConn, nil), + } +} + +type systemPool struct { + *pool.GRPCPool +} + +func (p *systemPool) Close() { + if p.GRPCPool != nil { + p.GRPCPool.Close() + } +} + +func (p *systemPool) NewClient(ctx context.Context) (SystemClient, error) { + cc, err := p.GetConnection(ctx) + if err != nil { + return nil, err + } + return &systemClient{ + cc, + &projectClient{cc.ClientConn}, + &organizationClient{cc.ClientConn}, + &partnerClient{cc.ClientConn}, + }, nil +} + +type options struct { + addr string + maxConn int + cert []byte + key []byte + caCert []byte +} + +// Option is the functional argument for Pool options +type Option func(*options) + +// WithAddr sets address of the pool +func WithAddr(addr string) Option { + return func(o *options) { + o.addr = addr + } +} + +// WithMaxConn sets maximum number of connections of the pool +// if not set defaults to 10 +func WithMaxConn(maxConn int) Option { + return func(o *options) { + o.maxConn = maxConn + } +} + +// WithClientCertPEM sets PEM encoded client cert for pool +func WithClientCertPEM(cert []byte) Option { + return func(o *options) { + o.cert = cert + } +} + +// WithClientKeyPEM sets PEM encoded client key for pool +func WithClientKeyPEM(key []byte) Option { + return func(o *options) { + o.key = key + } +} + +// WithCaCertPEM sets PEM encoded CA cert for pool +func WithCaCertPEM(caCert []byte) Option { + return func(o *options) { + o.caCert = caCert + } +} diff --git a/proto/rpc/user/internal.go b/proto/rpc/user/internal.go new file mode 100644 index 0000000..8b9e152 --- /dev/null +++ b/proto/rpc/user/internal.go @@ -0,0 +1,104 @@ +package rpcv3 + +import ( + "context" + + "github.com/RafayLabs/rcloud-base/pkg/pool" + grpcpool "github.com/processout/grpc-go-pool" +) + +// UserClient is the interface for accessing all User & Group RPCs +// exposed by Rafay Base +type UGClient interface { + Unhealthy() + Close() error + UserClient +} + +type ugClient struct { + *grpcpool.ClientConn + *userClient +} + +var _ UGClient = (*ugClient)(nil) + +// UGPool maintains pool of grpc connections to system base services +type UGPool interface { + Close() + NewClient(ctx context.Context) (UGClient, error) +} + +// NewUGPool new user group pool +func NewUGPool(addr string, maxConn int) UGPool { + return &ugPool{ + GRPCPool: pool.NewGRPCPool(addr, maxConn, nil), + } +} + +type ugPool struct { + *pool.GRPCPool +} + +func (p *ugPool) Close() { + if p.GRPCPool != nil { + p.GRPCPool.Close() + } +} + +func (p *ugPool) NewClient(ctx context.Context) (UGClient, error) { + cc, err := p.GetConnection(ctx) + if err != nil { + return nil, err + } + return &ugClient{ + cc, + &userClient{cc.ClientConn}, + }, nil +} + +type options struct { + addr string + maxConn int + cert []byte + key []byte + caCert []byte +} + +// Option is the functional argument for Pool options +type Option func(*options) + +// WithAddr sets address of the pool +func WithAddr(addr string) Option { + return func(o *options) { + o.addr = addr + } +} + +// WithMaxConn sets maximum number of connections of the pool +// if not set defaults to 10 +func WithMaxConn(maxConn int) Option { + return func(o *options) { + o.maxConn = maxConn + } +} + +// WithClientCertPEM sets PEM encoded client cert for pool +func WithClientCertPEM(cert []byte) Option { + return func(o *options) { + o.cert = cert + } +} + +// WithClientKeyPEM sets PEM encoded client key for pool +func WithClientKeyPEM(key []byte) Option { + return func(o *options) { + o.key = key + } +} + +// WithCaCertPEM sets PEM encoded CA cert for pool +func WithCaCertPEM(caCert []byte) Option { + return func(o *options) { + o.caCert = caCert + } +}