-2
appview/db/db.go
-2
appview/db/db.go
+20
-6
appview/db/pubkeys.go
+20
-6
appview/db/pubkeys.go
···
1
package db
2
3
-
import "time"
4
5
func (d *DB) AddPublicKey(did, name, key string) error {
6
query := `insert into public_keys (did, name, key) values (?, ?, ?)`
···
15
}
16
17
type PublicKey struct {
18
-
Key string
19
-
Name string
20
-
DID string
21
Created time.Time
22
}
23
24
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
25
var keys []PublicKey
26
···
33
for rows.Next() {
34
var publicKey PublicKey
35
var createdAt *int64
36
-
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.DID, &createdAt); err != nil {
37
return nil, err
38
}
39
publicKey.Created = time.Unix(*createdAt, 0)
···
59
for rows.Next() {
60
var publicKey PublicKey
61
var createdAt *int64
62
-
if err := rows.Scan(&publicKey.DID, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
63
return nil, err
64
}
65
publicKey.Created = time.Unix(*createdAt, 0)
···
1
package db
2
3
+
import (
4
+
"encoding/json"
5
+
"time"
6
+
)
7
8
func (d *DB) AddPublicKey(did, name, key string) error {
9
query := `insert into public_keys (did, name, key) values (?, ?, ?)`
···
18
}
19
20
type PublicKey struct {
21
+
Did string `json:"did"`
22
+
Key string `json:"key"`
23
+
Name string `json:"name"`
24
Created time.Time
25
}
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
+
38
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
39
var keys []PublicKey
40
···
47
for rows.Next() {
48
var publicKey PublicKey
49
var createdAt *int64
50
+
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &createdAt); err != nil {
51
return nil, err
52
}
53
publicKey.Created = time.Unix(*createdAt, 0)
···
73
for rows.Next() {
74
var publicKey PublicKey
75
var createdAt *int64
76
+
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
77
return nil, err
78
}
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
package state
2
3
import (
4
"crypto/hmac"
5
"crypto/sha256"
6
"encoding/hex"
7
"fmt"
8
"log"
9
"net/http"
···
194
195
// create a signed request and check if a node responds to that
196
func (s *State) InitKnotServer(w http.ResponseWriter, r *http.Request) {
197
domain := chi.URLParam(r, "domain")
198
if domain == "" {
199
http.Error(w, "malformed url", http.StatusBadRequest)
200
return
201
}
202
203
-
log.Println("checking ", domain)
204
205
-
secret, err := s.db.GetRegistrationKey(domain)
206
if err != nil {
207
-
log.Printf("no key found for domain %s: %s\n", domain, err)
208
return
209
}
210
-
log.Println("has secret ", secret)
211
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)
216
if err != nil {
217
-
log.Println("failed to build ping request", err)
218
return
219
}
220
-
221
client := SignedClient(secret)
222
223
resp, err := client.Do(pingRequest)
···
227
return
228
}
229
230
-
if resp.StatusCode != http.StatusOK {
231
log.Println("status nok", resp.StatusCode)
232
w.Write([]byte("no dice"))
233
return
···
384
w.Write([]byte(fmt.Sprint("added member: ", memberIdent.Handle.String())))
385
}
386
387
-
// list members of domain, requires auth and requires owner status
388
func (s *State) RemoveMember(w http.ResponseWriter, r *http.Request) {
389
}
390
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
-
// }
408
409
func (s *State) Router() http.Handler {
410
r := chi.NewRouter()
···
429
r.Delete("/", s.RemoveMember)
430
})
431
})
432
})
433
434
r.Group(func(r chi.Router) {
···
1
package state
2
3
import (
4
+
"bytes"
5
"crypto/hmac"
6
"crypto/sha256"
7
"encoding/hex"
8
+
"encoding/json"
9
"fmt"
10
"log"
11
"net/http"
···
196
197
// create a signed request and check if a node responds to that
198
func (s *State) InitKnotServer(w http.ResponseWriter, r *http.Request) {
199
+
user := s.auth.GetUser(r)
200
+
201
domain := chi.URLParam(r, "domain")
202
if domain == "" {
203
http.Error(w, "malformed url", http.StatusBadRequest)
204
return
205
}
206
+
log.Println("checking ", domain)
207
208
+
url := fmt.Sprintf("http://%s/init", domain)
209
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))
215
if err != nil {
216
+
log.Println("failed to build ping request", err)
217
return
218
}
219
220
+
secret, err := s.db.GetRegistrationKey(domain)
221
if err != nil {
222
+
log.Printf("no key found for domain %s: %s\n", domain, err)
223
return
224
}
225
client := SignedClient(secret)
226
227
resp, err := client.Do(pingRequest)
···
231
return
232
}
233
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 {
241
log.Println("status nok", resp.StatusCode)
242
w.Write([]byte("no dice"))
243
return
···
394
w.Write([]byte(fmt.Sprint("added member: ", memberIdent.Handle.String())))
395
}
396
397
func (s *State) RemoveMember(w http.ResponseWriter, r *http.Request) {
398
}
399
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
+
}
456
457
func (s *State) Router() http.Handler {
458
r := chi.NewRouter()
···
477
r.Delete("/", s.RemoveMember)
478
})
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)
488
})
489
490
r.Group(func(r chi.Router) {