-2
appview/db/db.go
-2
appview/db/db.go
+20
-6
appview/db/pubkeys.go
+20
-6
appview/db/pubkeys.go
···
1
1
package db
2
2
3
-
import "time"
3
+
import (
4
+
"encoding/json"
5
+
"time"
6
+
)
4
7
5
8
func (d *DB) AddPublicKey(did, name, key string) error {
6
9
query := `insert into public_keys (did, name, key) values (?, ?, ?)`
···
15
18
}
16
19
17
20
type PublicKey struct {
18
-
Key string
19
-
Name string
20
-
DID string
21
+
Did string `json:"did"`
22
+
Key string `json:"key"`
23
+
Name string `json:"name"`
21
24
Created time.Time
22
25
}
23
26
27
+
func (p PublicKey) MarshalJSON() ([]byte, error) {
28
+
type Alias PublicKey
29
+
return json.Marshal(&struct {
30
+
Created int64 `json:"created"`
31
+
*Alias
32
+
}{
33
+
Created: p.Created.Unix(),
34
+
Alias: (*Alias)(&p),
35
+
})
36
+
}
37
+
24
38
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
25
39
var keys []PublicKey
26
40
···
33
47
for rows.Next() {
34
48
var publicKey PublicKey
35
49
var createdAt *int64
36
-
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.DID, &createdAt); err != nil {
50
+
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &createdAt); err != nil {
37
51
return nil, err
38
52
}
39
53
publicKey.Created = time.Unix(*createdAt, 0)
···
59
73
for rows.Next() {
60
74
var publicKey PublicKey
61
75
var createdAt *int64
62
-
if err := rows.Scan(&publicKey.DID, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
76
+
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
63
77
return nil, err
64
78
}
65
79
publicKey.Created = time.Unix(*createdAt, 0)
+1
-1
appview/pages/login.html
+1
-1
appview/pages/login.html
+15
appview/pages/new-repo.html
+15
appview/pages/new-repo.html
···
1
+
{{define "title"}}new repo{{end}}
2
+
3
+
{{define "content"}}
4
+
<h1>new repo</h1>
5
+
<form method="POST" action="/repo/new">
6
+
<label for="name">repo name</label>
7
+
<input type="text" id="name" name="name" required>
8
+
9
+
<label for="domain">domain</label>
10
+
<input type="domain" id="domain" name="domain" required>
11
+
12
+
<button type="submit">create repo</button>
13
+
</form>
14
+
{{end}}
15
+
+8
appview/pages/pages.go
+8
appview/pages/pages.go
+1
appview/pages/timeline.html
+1
appview/pages/timeline.html
+85
-29
appview/state/state.go
+85
-29
appview/state/state.go
···
1
1
package state
2
2
3
3
import (
4
+
"bytes"
4
5
"crypto/hmac"
5
6
"crypto/sha256"
6
7
"encoding/hex"
8
+
"encoding/json"
7
9
"fmt"
8
10
"log"
9
11
"net/http"
···
194
196
195
197
// create a signed request and check if a node responds to that
196
198
func (s *State) InitKnotServer(w http.ResponseWriter, r *http.Request) {
199
+
user := s.auth.GetUser(r)
200
+
197
201
domain := chi.URLParam(r, "domain")
198
202
if domain == "" {
199
203
http.Error(w, "malformed url", http.StatusBadRequest)
200
204
return
201
205
}
206
+
log.Println("checking ", domain)
202
207
203
-
log.Println("checking ", domain)
208
+
url := fmt.Sprintf("http://%s/init", domain)
204
209
205
-
secret, err := s.db.GetRegistrationKey(domain)
210
+
body, _ := json.Marshal(map[string]interface{}{
211
+
"did": user.Did,
212
+
"keys": []string{},
213
+
})
214
+
pingRequest, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
206
215
if err != nil {
207
-
log.Printf("no key found for domain %s: %s\n", domain, err)
216
+
log.Println("failed to build ping request", err)
208
217
return
209
218
}
210
-
log.Println("has secret ", secret)
211
219
212
-
// make a request do the knotserver with an empty body and above signature
213
-
url := fmt.Sprintf("http://%s/health", domain)
214
-
215
-
pingRequest, err := http.NewRequest("GET", url, nil)
220
+
secret, err := s.db.GetRegistrationKey(domain)
216
221
if err != nil {
217
-
log.Println("failed to build ping request", err)
222
+
log.Printf("no key found for domain %s: %s\n", domain, err)
218
223
return
219
224
}
220
-
221
225
client := SignedClient(secret)
222
226
223
227
resp, err := client.Do(pingRequest)
···
227
231
return
228
232
}
229
233
230
-
if resp.StatusCode != http.StatusOK {
234
+
if resp.StatusCode == http.StatusConflict {
235
+
log.Println("status conflict", resp.StatusCode)
236
+
w.Write([]byte("already registered, sorry!"))
237
+
return
238
+
}
239
+
240
+
if resp.StatusCode != http.StatusNoContent {
231
241
log.Println("status nok", resp.StatusCode)
232
242
w.Write([]byte("no dice"))
233
243
return
···
384
394
w.Write([]byte(fmt.Sprint("added member: ", memberIdent.Handle.String())))
385
395
}
386
396
387
-
// list members of domain, requires auth and requires owner status
388
397
func (s *State) RemoveMember(w http.ResponseWriter, r *http.Request) {
389
398
}
390
399
391
-
// func buildPingRequest(url, secret string) (*http.Request, error) {
392
-
// pingRequest, err := http.NewRequest("GET", url, nil)
393
-
// if err != nil {
394
-
// return nil, err
395
-
// }
396
-
//
397
-
// timestamp := time.Now().Format(time.RFC3339)
398
-
// mac := hmac.New(sha256.New, []byte(secret))
399
-
// message := pingRequest.Method + pingRequest.URL.Path + timestamp
400
-
// mac.Write([]byte(message))
401
-
// signature := hex.EncodeToString(mac.Sum(nil))
402
-
//
403
-
// pingRequest.Header.Set("X-Signature", signature)
404
-
// pingRequest.Header.Set("X-Timestamp", timestamp)
405
-
//
406
-
// return pingRequest, nil
407
-
// }
400
+
func (s *State) AddRepo(w http.ResponseWriter, r *http.Request) {
401
+
switch r.Method {
402
+
case http.MethodGet:
403
+
pages.NewRepo(w, pages.NewRepoParams{
404
+
User: s.auth.GetUser(r),
405
+
})
406
+
case http.MethodPost:
407
+
user := s.auth.GetUser(r)
408
+
409
+
domain := r.FormValue("domain")
410
+
if domain == "" {
411
+
log.Println("invalid form")
412
+
return
413
+
}
414
+
415
+
repoName := r.FormValue("name")
416
+
if repoName == "" {
417
+
log.Println("invalid form")
418
+
return
419
+
}
420
+
421
+
ok, err := s.enforcer.E.Enforce(user.Did, domain, domain, "repo:create")
422
+
if err != nil || !ok {
423
+
w.Write([]byte("domain inaccessible to you"))
424
+
return
425
+
}
426
+
427
+
secret, err := s.db.GetRegistrationKey(domain)
428
+
if err != nil {
429
+
log.Printf("no key found for domain %s: %s\n", domain, err)
430
+
return
431
+
}
432
+
433
+
client := SignedClient(secret)
434
+
url := fmt.Sprintf("http://%s/repo/new", domain)
435
+
body, _ := json.Marshal(map[string]interface{}{
436
+
"did": user.Did,
437
+
"name": repoName,
438
+
})
439
+
createRepoRequest, err := http.NewRequest("PUT", url, bytes.NewReader(body))
440
+
441
+
resp, err := client.Do(createRepoRequest)
442
+
443
+
if err != nil {
444
+
log.Println("failed to send create repo request", err)
445
+
return
446
+
}
447
+
448
+
if resp.StatusCode != http.StatusNoContent {
449
+
log.Println("server returned ", resp.StatusCode)
450
+
return
451
+
}
452
+
453
+
w.Write([]byte("created!"))
454
+
}
455
+
}
408
456
409
457
func (s *State) Router() http.Handler {
410
458
r := chi.NewRouter()
···
429
477
r.Delete("/", s.RemoveMember)
430
478
})
431
479
})
480
+
})
481
+
482
+
r.Route("/repo", func(r chi.Router) {
483
+
r.Route("/new", func(r chi.Router) {
484
+
r.Get("/", s.AddRepo)
485
+
r.Post("/", s.AddRepo)
486
+
})
487
+
// r.Post("/import", s.ImportRepo)
432
488
})
433
489
434
490
r.Group(func(r chi.Router) {