1
1
package controller
2
2
3
3
import (
4
+ "context"
4
5
"encoding/json"
5
6
"errors"
6
7
"fmt"
7
8
"net/http"
8
9
"strings"
10
+ "time"
9
11
12
+ "github.com/google/uuid"
10
13
"github.com/gorilla/mux"
11
14
"github.com/gravitl/netmaker/database"
15
+ "github.com/gravitl/netmaker/db"
12
16
"github.com/gravitl/netmaker/logger"
13
17
"github.com/gravitl/netmaker/logic"
14
18
"github.com/gravitl/netmaker/models"
15
19
"github.com/gravitl/netmaker/mq"
20
+ "github.com/gravitl/netmaker/schema"
16
21
"github.com/gravitl/netmaker/servercfg"
22
+ "gorm.io/datatypes"
17
23
)
18
24
19
25
func dnsHandlers (r * mux.Router ) {
@@ -34,6 +40,274 @@ func dnsHandlers(r *mux.Router) {
34
40
Methods (http .MethodPost )
35
41
r .HandleFunc ("/api/dns/{network}/{domain}" , logic .SecurityCheck (true , http .HandlerFunc (deleteDNS ))).
36
42
Methods (http .MethodDelete )
43
+ r .HandleFunc ("/api/v1/nameserver" , logic .SecurityCheck (true , http .HandlerFunc (createNs ))).Methods (http .MethodPost )
44
+ r .HandleFunc ("/api/v1/nameserver" , logic .SecurityCheck (true , http .HandlerFunc (listNs ))).Methods (http .MethodGet )
45
+ r .HandleFunc ("/api/v1/nameserver" , logic .SecurityCheck (true , http .HandlerFunc (updateNs ))).Methods (http .MethodPut )
46
+ r .HandleFunc ("/api/v1/nameserver" , logic .SecurityCheck (true , http .HandlerFunc (deleteNs ))).Methods (http .MethodDelete )
47
+ r .HandleFunc ("/api/v1/nameserver/global" , logic .SecurityCheck (true , http .HandlerFunc (getGlobalNs ))).Methods (http .MethodGet )
48
+ }
49
+
50
+ // @Summary List Global Nameservers
51
+ // @Router /api/v1/nameserver/global [get]
52
+ // @Tags Auth
53
+ // @Accept json
54
+ // @Param query network string
55
+ // @Success 200 {object} models.SuccessResponse
56
+ // @Failure 400 {object} models.ErrorResponse
57
+ // @Failure 401 {object} models.ErrorResponse
58
+ // @Failure 500 {object} models.ErrorResponse
59
+ func getGlobalNs (w http.ResponseWriter , r * http.Request ) {
60
+
61
+ logic .ReturnSuccessResponseWithJson (w , r , logic .GlobalNsList , "fetched nameservers" )
62
+ }
63
+
64
+ // @Summary Create Nameserver
65
+ // @Router /api/v1/nameserver [post]
66
+ // @Tags DNS
67
+ // @Accept json
68
+ // @Param body body models.NameserverReq
69
+ // @Success 200 {object} models.SuccessResponse
70
+ // @Failure 400 {object} models.ErrorResponse
71
+ // @Failure 401 {object} models.ErrorResponse
72
+ // @Failure 500 {object} models.ErrorResponse
73
+ func createNs (w http.ResponseWriter , r * http.Request ) {
74
+
75
+ var req schema.Nameserver
76
+ err := json .NewDecoder (r .Body ).Decode (& req )
77
+ if err != nil {
78
+ logger .Log (0 , "error decoding request body: " ,
79
+ err .Error ())
80
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , "badrequest" ))
81
+ return
82
+ }
83
+ if err := logic .ValidateNameserverReq (req ); err != nil {
84
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , "badrequest" ))
85
+ return
86
+ }
87
+ if req .Tags == nil {
88
+ req .Tags = make (datatypes.JSONMap )
89
+ }
90
+ if gNs , ok := logic .GlobalNsList [req .Name ]; ok {
91
+ req .Servers = gNs .IPs
92
+ }
93
+ if ! servercfg .IsPro {
94
+ req .Tags = datatypes.JSONMap {
95
+ "*" : struct {}{},
96
+ }
97
+ }
98
+ if req .MatchAll {
99
+ req .MatchDomains = []string {"." }
100
+ }
101
+ ns := schema.Nameserver {
102
+ ID : uuid .New ().String (),
103
+ Name : req .Name ,
104
+ NetworkID : req .NetworkID ,
105
+ Description : req .Description ,
106
+ MatchAll : req .MatchAll ,
107
+ MatchDomains : req .MatchDomains ,
108
+ Servers : req .Servers ,
109
+ Tags : req .Tags ,
110
+ Status : true ,
111
+ CreatedBy : r .Header .Get ("user" ),
112
+ CreatedAt : time .Now ().UTC (),
113
+ }
114
+
115
+ err = ns .Create (db .WithContext (r .Context ()))
116
+ if err != nil {
117
+ logic .ReturnErrorResponse (
118
+ w ,
119
+ r ,
120
+ logic .FormatError (errors .New ("error creating nameserver " + err .Error ()), logic .Internal ),
121
+ )
122
+ return
123
+ }
124
+ logic .LogEvent (& models.Event {
125
+ Action : models .Create ,
126
+ Source : models.Subject {
127
+ ID : r .Header .Get ("user" ),
128
+ Name : r .Header .Get ("user" ),
129
+ Type : models .UserSub ,
130
+ },
131
+ TriggeredBy : r .Header .Get ("user" ),
132
+ Target : models.Subject {
133
+ ID : ns .ID ,
134
+ Name : ns .Name ,
135
+ Type : models .NameserverSub ,
136
+ },
137
+ NetworkID : models .NetworkID (ns .NetworkID ),
138
+ Origin : models .Dashboard ,
139
+ })
140
+
141
+ go mq .PublishPeerUpdate (false )
142
+ logic .ReturnSuccessResponseWithJson (w , r , ns , "created nameserver" )
143
+ }
144
+
145
+ // @Summary List Nameservers
146
+ // @Router /api/v1/nameserver [get]
147
+ // @Tags Auth
148
+ // @Accept json
149
+ // @Param query network string
150
+ // @Success 200 {object} models.SuccessResponse
151
+ // @Failure 400 {object} models.ErrorResponse
152
+ // @Failure 401 {object} models.ErrorResponse
153
+ // @Failure 500 {object} models.ErrorResponse
154
+ func listNs (w http.ResponseWriter , r * http.Request ) {
155
+
156
+ network := r .URL .Query ().Get ("network" )
157
+ if network == "" {
158
+ logic .ReturnErrorResponse (w , r , logic .FormatError (errors .New ("network is required" ), "badrequest" ))
159
+ return
160
+ }
161
+ ns := schema.Nameserver {NetworkID : network }
162
+ list , err := ns .ListByNetwork (db .WithContext (r .Context ()))
163
+ if err != nil {
164
+ logic .ReturnErrorResponse (
165
+ w ,
166
+ r ,
167
+ logic .FormatError (errors .New ("error listing nameservers " + err .Error ()), "internal" ),
168
+ )
169
+ return
170
+ }
171
+ logic .ReturnSuccessResponseWithJson (w , r , list , "fetched nameservers" )
172
+ }
173
+
174
+ // @Summary Update Nameserver
175
+ // @Router /api/v1/nameserver [put]
176
+ // @Tags Auth
177
+ // @Accept json
178
+ // @Param body body models.NameserverReq
179
+ // @Success 200 {object} models.SuccessResponse
180
+ // @Failure 400 {object} models.ErrorResponse
181
+ // @Failure 401 {object} models.ErrorResponse
182
+ // @Failure 500 {object} models.ErrorResponse
183
+ func updateNs (w http.ResponseWriter , r * http.Request ) {
184
+
185
+ var updateNs schema.Nameserver
186
+ err := json .NewDecoder (r .Body ).Decode (& updateNs )
187
+ if err != nil {
188
+ logger .Log (0 , "error decoding request body: " ,
189
+ err .Error ())
190
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , "badrequest" ))
191
+ return
192
+ }
193
+
194
+ if err := logic .ValidateNameserverReq (updateNs ); err != nil {
195
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , "badrequest" ))
196
+ return
197
+ }
198
+ if updateNs .Tags == nil {
199
+ updateNs .Tags = make (datatypes.JSONMap )
200
+ }
201
+
202
+ ns := schema.Nameserver {ID : updateNs .ID }
203
+ err = ns .Get (db .WithContext (r .Context ()))
204
+ if err != nil {
205
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , "badrequest" ))
206
+ return
207
+ }
208
+ var updateStatus bool
209
+ var updateMatchAll bool
210
+ if updateNs .Status != ns .Status {
211
+ updateStatus = true
212
+ }
213
+ if updateNs .MatchAll != ns .MatchAll {
214
+ updateMatchAll = true
215
+ }
216
+ event := & models.Event {
217
+ Action : models .Update ,
218
+ Source : models.Subject {
219
+ ID : r .Header .Get ("user" ),
220
+ Name : r .Header .Get ("user" ),
221
+ Type : models .UserSub ,
222
+ },
223
+ TriggeredBy : r .Header .Get ("user" ),
224
+ Target : models.Subject {
225
+ ID : ns .ID ,
226
+ Name : updateNs .Name ,
227
+ Type : models .NameserverSub ,
228
+ },
229
+ Diff : models.Diff {
230
+ Old : ns ,
231
+ New : updateNs ,
232
+ },
233
+ NetworkID : models .NetworkID (ns .NetworkID ),
234
+ Origin : models .Dashboard ,
235
+ }
236
+ ns .Servers = updateNs .Servers
237
+ ns .Tags = updateNs .Tags
238
+ ns .MatchDomains = updateNs .MatchDomains
239
+ ns .MatchAll = updateNs .MatchAll
240
+ ns .Description = updateNs .Description
241
+ ns .Name = updateNs .Name
242
+ ns .Status = updateNs .Status
243
+ ns .UpdatedAt = time .Now ().UTC ()
244
+
245
+ err = ns .Update (db .WithContext (context .TODO ()))
246
+ if err != nil {
247
+ logic .ReturnErrorResponse (
248
+ w ,
249
+ r ,
250
+ logic .FormatError (errors .New ("error creating egress resource" + err .Error ()), "internal" ),
251
+ )
252
+ return
253
+ }
254
+ if updateStatus {
255
+ ns .UpdateStatus (db .WithContext (context .TODO ()))
256
+ }
257
+ if updateMatchAll {
258
+ ns .UpdateMatchAll (db .WithContext (context .TODO ()))
259
+ }
260
+ logic .LogEvent (event )
261
+ go mq .PublishPeerUpdate (false )
262
+ logic .ReturnSuccessResponseWithJson (w , r , ns , "updated nameserver" )
263
+ }
264
+
265
+ // @Summary Delete Nameserver Resource
266
+ // @Router /api/v1/nameserver [delete]
267
+ // @Tags Auth
268
+ // @Accept json
269
+ // @Param body body models.Egress
270
+ // @Success 200 {object} models.SuccessResponse
271
+ // @Failure 400 {object} models.ErrorResponse
272
+ // @Failure 401 {object} models.ErrorResponse
273
+ // @Failure 500 {object} models.ErrorResponse
274
+ func deleteNs (w http.ResponseWriter , r * http.Request ) {
275
+
276
+ id := r .URL .Query ().Get ("id" )
277
+ if id == "" {
278
+ logic .ReturnErrorResponse (w , r , logic .FormatError (errors .New ("id is required" ), "badrequest" ))
279
+ return
280
+ }
281
+ ns := schema.Nameserver {ID : id }
282
+ err := ns .Get (db .WithContext (r .Context ()))
283
+ if err != nil {
284
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , logic .BadReq ))
285
+ return
286
+ }
287
+ err = ns .Delete (db .WithContext (r .Context ()))
288
+ if err != nil {
289
+ logic .ReturnErrorResponse (w , r , logic .FormatError (err , logic .Internal ))
290
+ return
291
+ }
292
+ logic .LogEvent (& models.Event {
293
+ Action : models .Delete ,
294
+ Source : models.Subject {
295
+ ID : r .Header .Get ("user" ),
296
+ Name : r .Header .Get ("user" ),
297
+ Type : models .UserSub ,
298
+ },
299
+ TriggeredBy : r .Header .Get ("user" ),
300
+ Target : models.Subject {
301
+ ID : ns .ID ,
302
+ Name : ns .Name ,
303
+ Type : models .NameserverSub ,
304
+ },
305
+ NetworkID : models .NetworkID (ns .NetworkID ),
306
+ Origin : models .Dashboard ,
307
+ })
308
+
309
+ go mq .PublishPeerUpdate (false )
310
+ logic .ReturnSuccessResponseWithJson (w , r , nil , "deleted nameserver resource" )
37
311
}
38
312
39
313
// @Summary Gets node DNS entries associated with a network
0 commit comments