@@ -7,70 +7,113 @@ import (
7
7
"net/http"
8
8
"net/url"
9
9
10
- sqlite "github.com/gwenn/gosqlite"
11
10
com "github.com/sqlitebrowser/dbhub.io/common"
12
11
)
13
12
14
- // collectInfo is an internal function which:
15
- // 1. Authenticates incoming requests
16
- // 2. Extracts the database owner, name, & commitID from the request
17
- // 3. Fetches the database from Minio (with appropriate permission checks)
18
- // 4. Opens the database, returning the connection handle
19
- // This function exists purely because this code is commonly to most of the handlers
20
- func collectInfo (w http.ResponseWriter , r * http.Request ) (sdb * sqlite.Conn , err error , httpStatus int ) {
21
- var loggedInUser string
22
- loggedInUser , err = checkAuth (w , r )
13
+ // diffHandler generates a diff between two databases or two versions of a database
14
+ // This can be run from the command line using curl, like this:
15
+ // $ curl -F apikey="YOUR_API_KEY_HERE" -F dbowner_a="justinclift" -F dbname_a="Join Testing.sqlite" -F commit_a="ea12..." -F commit_b="5a7c..." https://api.dbhub.io/v1/diff
16
+ // * "apikey" is one of your API keys. These can be generated from your Settings page once logged in
17
+ // * "dbowner_a" is the owner of the first database being diffed
18
+ // * "dbname_a" is the name of the first database being diffed
19
+ // * "dbowner_b" is the owner of the second database being diffed (optional, if not provided same as first owner)
20
+ // * "dbname_b" is the name of the second database being diffed (optional, if not provided same as first name)
21
+ // * "commit_a" is the first commit for diffing
22
+ // * "commit_b" is the second commit for diffing
23
+ func diffHandler (w http.ResponseWriter , r * http.Request ) {
24
+ loggedInUser , err := checkAuth (w , r )
23
25
if err != nil {
24
- httpStatus = http .StatusUnauthorized
26
+ jsonErr ( w , err . Error (), http .StatusUnauthorized )
25
27
return
26
28
}
27
29
28
- // Extract the database owner name, database name, and (optional) commit ID for the database from the request
29
- var dbOwner , dbName , commitID string
30
- dbOwner , dbName , commitID , err = com .GetFormODC (r )
31
- if err != nil {
32
- httpStatus = http .StatusInternalServerError
30
+ // Retrieve owner, name, and commit ids
31
+ oa := r .PostFormValue ("dbowner_a" )
32
+ na := r .PostFormValue ("dbname_a" )
33
+ ca := r .PostFormValue ("commit_a" )
34
+ ob := r .PostFormValue ("dbowner_a" )
35
+ nb := r .PostFormValue ("dbname_b" )
36
+ cb := r .PostFormValue ("commit_b" )
37
+
38
+ // If no primary database owner and name are given or if no commit ids are given, return
39
+ if oa == "" || na == "" || ca == "" || cb == "" {
40
+ jsonErr (w , err .Error (), http .StatusBadRequest )
33
41
return
34
42
}
35
- dbFolder := "/"
36
43
37
- // Check if the user has access to the requested database
38
- var bucket , id string
39
- bucket , id , _ , err = com .MinioLocation (dbOwner , dbFolder , dbName , commitID , loggedInUser )
44
+ // If no secondary database owner and name are provided, use the ones of the first database
45
+ if ob == "" || nb == "" {
46
+ ob = oa
47
+ nb = na
48
+ }
49
+
50
+ // Unescape, then validate the owner and database names and commit ids
51
+ dbOwnerA , err := url .QueryUnescape (oa )
40
52
if err != nil {
41
- httpStatus = http .StatusInternalServerError
53
+ jsonErr ( w , err . Error (), http .StatusBadRequest )
42
54
return
43
55
}
44
-
45
- // Sanity check
46
- if id == "" {
47
- // The requested database wasn't found, or the user doesn't have permission to access it
48
- err = fmt .Errorf ("Requested database not found" )
49
- log .Printf ("Requested database not found. Owner: '%s%s%s'" , dbOwner , dbFolder , dbName )
50
- httpStatus = http .StatusNotFound
56
+ dbOwnerB , err := url .QueryUnescape (ob )
57
+ if err != nil {
58
+ jsonErr (w , err .Error (), http .StatusBadRequest )
51
59
return
52
60
}
53
-
54
- // Retrieve database file from Minio, using locally cached version if it's already there
55
- newDB , err := com .RetrieveDatabaseFile (bucket , id )
61
+ dbNameA , err := url .QueryUnescape (na )
62
+ if err != nil {
63
+ jsonErr (w , err .Error (), http .StatusBadRequest )
64
+ return
65
+ }
66
+ dbNameB , err := url .QueryUnescape (nb )
56
67
if err != nil {
57
- httpStatus = http .StatusNotFound
68
+ jsonErr (w , err .Error (), http .StatusBadRequest )
69
+ return
70
+ }
71
+ err = com .ValidateUser (dbOwnerA )
72
+ if err != nil {
73
+ jsonErr (w , err .Error (), http .StatusBadRequest )
74
+ return
75
+ }
76
+ err = com .ValidateUser (dbOwnerB )
77
+ if err != nil {
78
+ jsonErr (w , err .Error (), http .StatusBadRequest )
79
+ return
80
+ }
81
+ err = com .ValidateDB (dbNameA )
82
+ if err != nil {
83
+ jsonErr (w , err .Error (), http .StatusBadRequest )
84
+ return
85
+ }
86
+ err = com .ValidateDB (dbNameB )
87
+ if err != nil {
88
+ jsonErr (w , err .Error (), http .StatusBadRequest )
89
+ return
90
+ }
91
+ err = com .ValidateCommitID (ca )
92
+ if err != nil {
93
+ jsonErr (w , err .Error (), http .StatusBadRequest )
94
+ return
95
+ }
96
+ err = com .ValidateCommitID (cb )
97
+ if err != nil {
98
+ jsonErr (w , err .Error (), http .StatusBadRequest )
58
99
return
59
100
}
60
101
61
- // Open the SQLite database in read only mode
62
- sdb , err = sqlite . Open ( newDB , sqlite . OpenReadOnly )
102
+ // Perform diff
103
+ diffs , err := com . Diff ( dbOwnerA , "/" , dbNameA , ca , dbOwnerB , "/" , dbNameB , cb , loggedInUser )
63
104
if err != nil {
64
- log .Printf ("Couldn't open database in viewsHandler(): %s" , err )
65
- httpStatus = http .StatusInternalServerError
105
+ jsonErr (w , err .Error (), http .StatusInternalServerError )
66
106
return
67
107
}
68
- if err = sdb .EnableExtendedResultCodes (true ); err != nil {
69
- log .Printf ("Couldn't enable extended result codes in viewsHandler(): %v\n " , err .Error ())
70
- httpStatus = http .StatusInternalServerError
108
+
109
+ // Return the results
110
+ jsonData , err := json .Marshal (diffs )
111
+ if err != nil {
112
+ log .Printf ("Error when JSON marshalling returned data in diffHandler(): %v\n " , err )
113
+ jsonErr (w , err .Error (), http .StatusInternalServerError )
71
114
return
72
115
}
73
- return
116
+ fmt . Fprintf ( w , string ( jsonData ))
74
117
}
75
118
76
119
// indexesHandler returns the list of indexes present in a SQLite database
@@ -256,109 +299,3 @@ func viewsHandler(w http.ResponseWriter, r *http.Request) {
256
299
}
257
300
fmt .Fprintf (w , string (jsonData ))
258
301
}
259
-
260
- // diffHandler generates a diff between two databases or two versions of a database
261
- // This can be run from the command line using curl, like this:
262
- // $ curl -F apikey="YOUR_API_KEY_HERE" -F dbowner_a="justinclift" -F dbname_a="Join Testing.sqlite" -F commit_a="ea12..." -F commit_b="5a7c..." https://api.dbhub.io/v1/diff
263
- // * "apikey" is one of your API keys. These can be generated from your Settings page once logged in
264
- // * "dbowner_a" is the owner of the first database being diffed
265
- // * "dbname_a" is the name of the first database being diffed
266
- // * "dbowner_b" is the owner of the second database being diffed (optional, if not provided same as first owner)
267
- // * "dbname_b" is the name of the second database being diffed (optional, if not provided same as first name)
268
- // * "commit_a" is the first commit for diffing
269
- // * "commit_b" is the second commit for diffing
270
- func diffHandler (w http.ResponseWriter , r * http.Request ) {
271
- loggedInUser , err := checkAuth (w , r )
272
- if err != nil {
273
- jsonErr (w , err .Error (), http .StatusUnauthorized )
274
- return
275
- }
276
-
277
- // Retrieve owner, name, and commit ids
278
- oa := r .PostFormValue ("dbowner_a" )
279
- na := r .PostFormValue ("dbname_a" )
280
- ca := r .PostFormValue ("commit_a" )
281
- ob := r .PostFormValue ("dbowner_a" )
282
- nb := r .PostFormValue ("dbname_b" )
283
- cb := r .PostFormValue ("commit_b" )
284
-
285
- // If no primary database owner and name are given or if no commit ids are given, return
286
- if oa == "" || na == "" || ca == "" || cb == "" {
287
- jsonErr (w , err .Error (), http .StatusBadRequest )
288
- return
289
- }
290
-
291
- // If no secondary database owner and name are provided, use the ones of the first database
292
- if ob == "" || nb == "" {
293
- ob = oa
294
- nb = na
295
- }
296
-
297
- // Unescape, then validate the owner and database names and commit ids
298
- dbOwnerA , err := url .QueryUnescape (oa )
299
- if err != nil {
300
- jsonErr (w , err .Error (), http .StatusBadRequest )
301
- return
302
- }
303
- dbOwnerB , err := url .QueryUnescape (ob )
304
- if err != nil {
305
- jsonErr (w , err .Error (), http .StatusBadRequest )
306
- return
307
- }
308
- dbNameA , err := url .QueryUnescape (na )
309
- if err != nil {
310
- jsonErr (w , err .Error (), http .StatusBadRequest )
311
- return
312
- }
313
- dbNameB , err := url .QueryUnescape (nb )
314
- if err != nil {
315
- jsonErr (w , err .Error (), http .StatusBadRequest )
316
- return
317
- }
318
- err = com .ValidateUser (dbOwnerA )
319
- if err != nil {
320
- jsonErr (w , err .Error (), http .StatusBadRequest )
321
- return
322
- }
323
- err = com .ValidateUser (dbOwnerB )
324
- if err != nil {
325
- jsonErr (w , err .Error (), http .StatusBadRequest )
326
- return
327
- }
328
- err = com .ValidateDB (dbNameA )
329
- if err != nil {
330
- jsonErr (w , err .Error (), http .StatusBadRequest )
331
- return
332
- }
333
- err = com .ValidateDB (dbNameB )
334
- if err != nil {
335
- jsonErr (w , err .Error (), http .StatusBadRequest )
336
- return
337
- }
338
- err = com .ValidateCommitID (ca )
339
- if err != nil {
340
- jsonErr (w , err .Error (), http .StatusBadRequest )
341
- return
342
- }
343
- err = com .ValidateCommitID (cb )
344
- if err != nil {
345
- jsonErr (w , err .Error (), http .StatusBadRequest )
346
- return
347
- }
348
-
349
- // Perform diff
350
- diffs , err := com .Diff (dbOwnerA , "/" , dbNameA , ca , dbOwnerB , "/" , dbNameB , cb , loggedInUser )
351
- if err != nil {
352
- jsonErr (w , err .Error (), http .StatusInternalServerError )
353
- return
354
- }
355
-
356
- // Return the results
357
- jsonData , err := json .Marshal (diffs )
358
- if err != nil {
359
- log .Printf ("Error when JSON marshalling returned data in diffHandler(): %v\n " , err )
360
- jsonErr (w , err .Error (), http .StatusInternalServerError )
361
- return
362
- }
363
- fmt .Fprintf (w , string (jsonData ))
364
- }
0 commit comments