Skip to content

Commit 285de61

Browse files
committed
chore(multi-tenant): Creating multi tenant based on database
Creating multi tenant system based on database and being set on request
1 parent 13b80ec commit 285de61

File tree

22 files changed

+265
-102
lines changed

22 files changed

+265
-102
lines changed

cmd/cli/migrator/migrator.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ import (
1111
)
1212

1313
type Migrator struct {
14-
dsn string
15-
dsnTest string
14+
dsn string
15+
dsnTest string
16+
database string
1617
}
1718

1819
func NewMigrator() *Migrator {
@@ -34,27 +35,36 @@ func (m *Migrator) DeclareCommands(cmd *cobra.Command) {
3435
Run: m.Inspect,
3536
},
3637
&cobra.Command{
37-
Use: "generate",
38-
Short: "generate HCL from database",
38+
Use: "generate-schema-from-db",
39+
Short: "generate-schema-from-db <schema name>",
40+
Long: "generate HCL schema from database connected on env",
3941
PreRun: m.BootMigrator,
4042
Run: m.Generate,
4143
},
4244
)
4345
}
4446

45-
func (m *Migrator) Migrate(_ *cobra.Command, _ []string) {
46-
migratorInstance := migrator.NewMigrator(m.dsn, m.dsnTest)
47-
migratorInstance.MigrateAllDomains()
47+
func (m *Migrator) Migrate(_ *cobra.Command, args []string) {
48+
tenant := ""
49+
if len(args) > 0 {
50+
tenant = args[0]
51+
}
52+
migratorInstance := migrator.NewMigrator(m.dsn, m.dsnTest, m.database)
53+
migratorInstance.MigrateAllDomains(tenant)
4854
}
4955

5056
func (m *Migrator) Inspect(_ *cobra.Command, _ []string) {
51-
migratorInstance := migrator.NewMigrator(m.dsn, m.dsnTest)
57+
migratorInstance := migrator.NewMigrator(m.dsn, m.dsnTest, m.database)
5258
migratorInstance.Inspect()
5359
}
5460

55-
func (m *Migrator) Generate(_ *cobra.Command, _ []string) {
56-
migratorInstance := migrator.NewMigrator(m.dsn, m.dsnTest)
57-
migratorInstance.Generate()
61+
func (m *Migrator) Generate(_ *cobra.Command, args []string) {
62+
schema := ""
63+
if len(args) > 1 {
64+
schema = args[1]
65+
}
66+
migratorInstance := migrator.NewMigrator(m.dsn, m.dsnTest, m.database)
67+
migratorInstance.Generate(schema)
5868
}
5969

6070
func (m *Migrator) BootMigrator(_ *cobra.Command, _ []string) {
@@ -64,18 +74,19 @@ func (m *Migrator) BootMigrator(_ *cobra.Command, _ []string) {
6474
panic(err)
6575
}
6676

67-
dsn := "%s:%s@%s:%s/%s"
77+
m.database = conf.ReadConfig("DB_DATABASE")
78+
dsn := "%s:%s@%s:%s"
6879
m.dsn = fmt.Sprintf(
6980
dsn,
7081
url.QueryEscape(conf.ReadConfig("DB_USER")),
7182
url.QueryEscape(conf.ReadConfig("DB_PASS")),
7283
url.QueryEscape(conf.ReadConfig("DB_URL")),
7384
conf.ReadConfig("DB_PORT"),
74-
conf.ReadConfig("DB_DATABASE"),
7585
)
7686

87+
testDsn := "%s:%s@%s:%s/%s"
7788
m.dsnTest = fmt.Sprintf(
78-
dsn,
89+
testDsn,
7990
conf.ReadConfig("DB_USER"),
8091
conf.ReadConfig("DB_PASS"),
8192
conf.ReadConfig("DB_URL"),

cmd/http/handlers/dummy.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func NewDummyHandlers(reg *registry.Registry) *DummyHandlers {
4343
// @Accept json
4444
// @Produce json
4545
// @Param dummy_id path string true "Dummy ID"
46+
// @Param Tenant header string true "tenant name"
4647
// @Success 200 {object} dummyGet.Response
4748
// @Failure 400 {object} services.Error
4849
// @Failure 404 {object} services.Error
@@ -55,9 +56,9 @@ func (hs *DummyHandlers) HandleGetDummy(context echo.Context) error {
5556
if errors := context.Bind(data); errors != nil {
5657
return context.JSON(422, errors)
5758
}
58-
59+
tenant := context.Request().Header.Get("Tenant")
5960
s.Execute(
60-
dummyGet.NewRequest(data),
61+
dummyGet.NewRequest(data, tenant),
6162
)
6263

6364
response, err := s.GetResponse()
@@ -73,6 +74,7 @@ func (hs *DummyHandlers) HandleGetDummy(context echo.Context) error {
7374
// @Accept json
7475
// @Produce json
7576
// @Param request body dummyCreate.Data true "body model"
77+
// @Param Tenant header string true "tenant name"
7678
// @Success 200 {object} dummyCreate.Response
7779
// @Failure 400 {object} services.Error
7880
// @Failure 404 {object} services.Error
@@ -86,8 +88,9 @@ func (hs *DummyHandlers) HandleCreateDummy(context echo.Context) error {
8688
return context.JSON(http.StatusBadRequest, errors)
8789
}
8890

91+
tenant := context.Request().Header.Get("Tenant")
8992
s.Execute(
90-
dummyCreate.NewRequest(data, hs.validator),
93+
dummyCreate.NewRequest(data, hs.validator, tenant),
9194
)
9295

9396
response, err := s.GetResponse()
@@ -104,6 +107,7 @@ func (hs *DummyHandlers) HandleCreateDummy(context echo.Context) error {
104107
// @Produce json
105108
// @Param dummy_id path string true "Dummy ID"
106109
// @Param request body dummyEdit.Data true "body model"
110+
// @Param Tenant header string true "tenant name"
107111
// @Success 200 {object} dummyEdit.Response
108112
// @Failure 400 {object} services.Error
109113
// @Failure 404 {object} services.Error
@@ -118,8 +122,9 @@ func (hs *DummyHandlers) HandleEditDummy(context echo.Context) error {
118122
return context.JSON(http.StatusBadRequest, errors)
119123
}
120124

125+
tenant := context.Request().Header.Get("Tenant")
121126
s.Execute(
122-
dummyEdit.NewRequest(id, data, hs.validator),
127+
dummyEdit.NewRequest(id, data, hs.validator, tenant),
123128
)
124129

125130
response, err := s.GetResponse()
@@ -137,6 +142,7 @@ func (hs *DummyHandlers) HandleEditDummy(context echo.Context) error {
137142
// @Param page query int true "valid int"
138143
// @Param name query string false "value example: eql|lik,value"
139144
// @Param email query string false "value example: lik,value"
145+
// @Param Tenant header string true "tenant name"
140146
// @Success 200 {object} dummyList.Response
141147
// @Failure 400 {object} services.Error
142148
// @Failure 404 {object} services.Error
@@ -162,8 +168,9 @@ func (hs *DummyHandlers) HandleListDummy(context echo.Context) error {
162168

163169
f := filters.NewFilters()
164170

171+
tenant := context.Request().Header.Get("Tenant")
165172
s.Execute(
166-
dummyList.NewRequest(data, *f),
173+
dummyList.NewRequest(data, *f, tenant),
167174
)
168175

169176
response, err := s.GetResponse()
@@ -179,6 +186,7 @@ func (hs *DummyHandlers) HandleListDummy(context echo.Context) error {
179186
// @Accept json
180187
// @Produce json
181188
// @Param dummy_id path string true "Dummy ID"
189+
// @Param Tenant header string true "tenant name"
182190
// @Success 200 {object} dummyDelete.Response
183191
// @Failure 400 {object} services.Error
184192
// @Failure 404 {object} services.Error
@@ -192,8 +200,9 @@ func (hs *DummyHandlers) HandleDeleteDummy(context echo.Context) error {
192200
return context.JSON(http.StatusBadRequest, errors)
193201
}
194202

203+
tenant := context.Request().Header.Get("Tenant")
195204
s.Execute(
196-
dummyDelete.NewRequest(data),
205+
dummyDelete.NewRequest(data, tenant),
197206
)
198207

199208
response, err := s.GetResponse()

compose.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@ services:
2626
retries: 2
2727
environment:
2828
MYSQL_ROOT_PASSWORD: root
29-
MYSQL_DATABASE: skeleton
29+
MYSQL_DATABASE: test
3030
ports:
3131
- "3307:3306"
3232
volumes:
33-
- ./storage/mysql:/var/lib/mysql
33+
- storage:/var/lib/mysql
34+
35+
volumes:
36+
storage:
3437

3538
networks:
3639
default:

docs/docs.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ const docTemplate = `{
4646
"description": "value example: lik,value",
4747
"name": "email",
4848
"in": "query"
49+
},
50+
{
51+
"type": "string",
52+
"description": "tenant name",
53+
"name": "Tenant",
54+
"in": "header",
55+
"required": true
4956
}
5057
],
5158
"responses": {
@@ -95,6 +102,13 @@ const docTemplate = `{
95102
"schema": {
96103
"$ref": "#/definitions/go-skeleton_internal_application_services_dummy_CREATE.Data"
97104
}
105+
},
106+
{
107+
"type": "string",
108+
"description": "tenant name",
109+
"name": "Tenant",
110+
"in": "header",
111+
"required": true
98112
}
99113
],
100114
"responses": {
@@ -144,6 +158,13 @@ const docTemplate = `{
144158
"name": "dummy_id",
145159
"in": "path",
146160
"required": true
161+
},
162+
{
163+
"type": "string",
164+
"description": "tenant name",
165+
"name": "Tenant",
166+
"in": "header",
167+
"required": true
147168
}
148169
],
149170
"responses": {
@@ -200,6 +221,13 @@ const docTemplate = `{
200221
"schema": {
201222
"$ref": "#/definitions/go-skeleton_internal_application_services_dummy_EDIT.Data"
202223
}
224+
},
225+
{
226+
"type": "string",
227+
"description": "tenant name",
228+
"name": "Tenant",
229+
"in": "header",
230+
"required": true
203231
}
204232
],
205233
"responses": {
@@ -247,6 +275,13 @@ const docTemplate = `{
247275
"name": "dummy_id",
248276
"in": "path",
249277
"required": true
278+
},
279+
{
280+
"type": "string",
281+
"description": "tenant name",
282+
"name": "Tenant",
283+
"in": "header",
284+
"required": true
250285
}
251286
],
252287
"responses": {

docs/swagger.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@
3838
"description": "value example: lik,value",
3939
"name": "email",
4040
"in": "query"
41+
},
42+
{
43+
"type": "string",
44+
"description": "tenant name",
45+
"name": "Tenant",
46+
"in": "header",
47+
"required": true
4148
}
4249
],
4350
"responses": {
@@ -87,6 +94,13 @@
8794
"schema": {
8895
"$ref": "#/definitions/go-skeleton_internal_application_services_dummy_CREATE.Data"
8996
}
97+
},
98+
{
99+
"type": "string",
100+
"description": "tenant name",
101+
"name": "Tenant",
102+
"in": "header",
103+
"required": true
90104
}
91105
],
92106
"responses": {
@@ -136,6 +150,13 @@
136150
"name": "dummy_id",
137151
"in": "path",
138152
"required": true
153+
},
154+
{
155+
"type": "string",
156+
"description": "tenant name",
157+
"name": "Tenant",
158+
"in": "header",
159+
"required": true
139160
}
140161
],
141162
"responses": {
@@ -192,6 +213,13 @@
192213
"schema": {
193214
"$ref": "#/definitions/go-skeleton_internal_application_services_dummy_EDIT.Data"
194215
}
216+
},
217+
{
218+
"type": "string",
219+
"description": "tenant name",
220+
"name": "Tenant",
221+
"in": "header",
222+
"required": true
195223
}
196224
],
197225
"responses": {
@@ -239,6 +267,13 @@
239267
"name": "dummy_id",
240268
"in": "path",
241269
"required": true
270+
},
271+
{
272+
"type": "string",
273+
"description": "tenant name",
274+
"name": "Tenant",
275+
"in": "header",
276+
"required": true
242277
}
243278
],
244279
"responses": {

docs/swagger.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ paths:
9393
in: query
9494
name: email
9595
type: string
96+
- description: tenant name
97+
in: header
98+
name: Tenant
99+
required: true
100+
type: string
96101
produces:
97102
- application/json
98103
responses:
@@ -125,6 +130,11 @@ paths:
125130
required: true
126131
schema:
127132
$ref: '#/definitions/go-skeleton_internal_application_services_dummy_CREATE.Data'
133+
- description: tenant name
134+
in: header
135+
name: Tenant
136+
required: true
137+
type: string
128138
produces:
129139
- application/json
130140
responses:
@@ -157,6 +167,11 @@ paths:
157167
name: dummy_id
158168
required: true
159169
type: string
170+
- description: tenant name
171+
in: header
172+
name: Tenant
173+
required: true
174+
type: string
160175
produces:
161176
- application/json
162177
responses:
@@ -188,6 +203,11 @@ paths:
188203
name: dummy_id
189204
required: true
190205
type: string
206+
- description: tenant name
207+
in: header
208+
name: Tenant
209+
required: true
210+
type: string
191211
produces:
192212
- application/json
193213
responses:
@@ -225,6 +245,11 @@ paths:
225245
required: true
226246
schema:
227247
$ref: '#/definitions/go-skeleton_internal_application_services_dummy_EDIT.Data'
248+
- description: tenant name
249+
in: header
250+
name: Tenant
251+
required: true
252+
type: string
228253
produces:
229254
- application/json
230255
responses:

0 commit comments

Comments
 (0)