1 package services
2
3 import (
4 "context"
5 "database/sql"
6 "fmt"
7 "net/http"
8
9 sqlerr "edge-infra.dev/pkg/edge/api/apierror/sql"
10 sqlerror "edge-infra.dev/pkg/edge/api/apierror/sql"
11 "edge-infra.dev/pkg/edge/api/bsl/types"
12 "edge-infra.dev/pkg/edge/api/graph/model"
13 sqlquery "edge-infra.dev/pkg/edge/api/sql"
14 "edge-infra.dev/pkg/edge/bsl"
15 )
16
17 const (
18 effectiveOrganizations = "/provisioning/user-profiles/effective-organizations?pageNumber=%d&pageSize=%d"
19 )
20
21
22 type TenantService interface {
23 Create(ctx context.Context, input *model.TenantInput) (*model.Tenant, error)
24 List(ctx context.Context) ([]*model.Tenant, error)
25 Get(ctx context.Context, id string) (*model.Tenant, error)
26 GetTenantByBannerID(ctx context.Context, id string) (*model.Tenant, error)
27 GetTenantByClusterEdgeID(ctx context.Context, id string) (*model.Tenant, error)
28 GetByName(ctx context.Context, name string) (*model.Tenant, error)
29 GetOktaTenants(ctx context.Context, token string) ([]*model.Tenant, error)
30 }
31
32 type tenantService struct {
33 SQLDB *sql.DB
34 BSLClient *bsl.Client
35 BSPConfig *types.BSPConfig
36 }
37
38 func (o *tenantService) GetTenantByBannerID(ctx context.Context, id string) (*model.Tenant, error) {
39 var orgUUID, bslID, name string
40 row := o.SQLDB.QueryRowContext(ctx, sqlquery.GetTenantByBannerEdgeID, id)
41 err := row.Scan(&orgUUID, &bslID, &name)
42 if err != nil {
43 return nil, sqlerror.Wrap(err)
44 }
45 tenant := &model.Tenant{
46 TenantEdgeID: orgUUID,
47 TenantBSLId: bslID,
48 OrgName: name,
49 }
50 return tenant, nil
51 }
52
53 func (o *tenantService) GetTenantByClusterEdgeID(ctx context.Context, id string) (*model.Tenant, error) {
54 var orgUUID, bslID, name string
55 row := o.SQLDB.QueryRowContext(ctx, sqlquery.GetTenantByClusterEdgeID, id)
56 err := row.Scan(&orgUUID, &bslID, &name)
57 if err != nil {
58 return nil, sqlerror.Wrap(err)
59 }
60 tenant := &model.Tenant{
61 TenantEdgeID: orgUUID,
62 TenantBSLId: bslID,
63 OrgName: name,
64 }
65 return tenant, nil
66 }
67
68 func (o *tenantService) Create(ctx context.Context, input *model.TenantInput) (*model.Tenant, error) {
69 if _, err := o.SQLDB.ExecContext(ctx, sqlquery.TenantInsertQuery, input.TenantBSLId, input.OrgName); err != nil {
70 return nil, sqlerror.Wrap(err)
71 }
72
73 var tenant model.Tenant
74 row := o.SQLDB.QueryRowContext(ctx, sqlquery.TenantGetNoIDQuery, input.TenantBSLId, input.OrgName)
75 if err := row.Scan(&tenant.TenantEdgeID, &tenant.TenantBSLId, &tenant.OrgName); err != nil {
76 return nil, sqlerror.Wrap(err)
77 }
78 return &tenant, nil
79 }
80
81 func (o *tenantService) List(ctx context.Context) ([]*model.Tenant, error) {
82 rows, err := o.SQLDB.QueryContext(ctx, sqlquery.TenantListQuery)
83 if err != nil {
84 return nil, sqlerror.Wrap(err)
85 }
86 tenants := []*model.Tenant{}
87 defer rows.Close()
88 for rows.Next() {
89 var tenant model.Tenant
90 if err = rows.Scan(&tenant.TenantEdgeID, &tenant.TenantBSLId, &tenant.OrgName); err != nil {
91 return nil, sqlerror.Wrap(err)
92 }
93 tenants = append(tenants, &tenant)
94 }
95 if err := rows.Err(); err != nil {
96 return nil, sqlerr.Wrap(err)
97 }
98 return tenants, nil
99 }
100
101 func (o *tenantService) Get(ctx context.Context, id string) (*model.Tenant, error) {
102 var tenant model.Tenant
103 row := o.SQLDB.QueryRowContext(ctx, sqlquery.TenantGetQuery, id)
104 if err := row.Scan(&tenant.TenantEdgeID, &tenant.TenantBSLId, &tenant.OrgName); err != nil {
105 return nil, sqlerror.Wrap(err)
106 }
107 return &tenant, nil
108 }
109
110 func (o *tenantService) GetByName(ctx context.Context, name string) (*model.Tenant, error) {
111 var tenant model.Tenant
112 row := o.SQLDB.QueryRowContext(ctx, sqlquery.TenantGetByName, name)
113 if err := row.Scan(&tenant.TenantEdgeID, &tenant.TenantBSLId, &tenant.OrgName); err != nil {
114 return nil, sqlerror.Wrap(err)
115 }
116 return &tenant, nil
117 }
118
119 func (o *tenantService) GetOktaTenants(ctx context.Context, token string) ([]*model.Tenant, error) {
120 tenants := make([]*model.Tenant, 0)
121 uniqueTenants := make(map[string]bool, 0)
122 data := &types.EffectiveOrganizationsResponse{}
123 pageNumber := 0
124 client := o.BSLClient.WithOktaToken(ctx, token)
125 for !data.LastPage {
126 err := client.JSON(http.MethodGet, fmt.Sprintf(effectiveOrganizations, pageNumber, pageSize), data)
127 if err != nil {
128 return tenants, err
129 }
130 for _, pageContent := range data.PageContent {
131 orgTenant := bsl.GetTenant(o.BSPConfig.Root, pageContent.OrganizationName)
132 if _, exists := uniqueTenants[orgTenant]; !exists {
133 tenant, err := o.GetByName(ctx, orgTenant)
134 if err != nil {
135 return tenants, err
136 }
137 uniqueTenants[tenant.OrgName] = true
138 tenants = append(tenants, tenant)
139 }
140 }
141 pageNumber++
142 }
143 return tenants, nil
144 }
145
146 func NewTenantService(sqlDB *sql.DB, bslClient *bsl.Client, bspConfig *types.BSPConfig) *tenantService {
147 return &tenantService{
148 SQLDB: sqlDB,
149 BSLClient: bslClient,
150 BSPConfig: bspConfig,
151 }
152 }
153
View as plain text