forked from tangled.org/core
this repo has no description

POC: create repos

Changed files
+130 -38
appview
-2
appview/db/db.go
···
return "", err
}
-
log.Println("domain, secret: ", domain, secret)
-
return secret, nil
}
···
return "", err
}
return secret, nil
}
+20 -6
appview/db/pubkeys.go
···
package db
-
import "time"
func (d *DB) AddPublicKey(did, name, key string) error {
query := `insert into public_keys (did, name, key) values (?, ?, ?)`
···
}
type PublicKey struct {
-
Key string
-
Name string
-
DID string
Created time.Time
}
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
var keys []PublicKey
···
for rows.Next() {
var publicKey PublicKey
var createdAt *int64
-
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.DID, &createdAt); err != nil {
return nil, err
}
publicKey.Created = time.Unix(*createdAt, 0)
···
for rows.Next() {
var publicKey PublicKey
var createdAt *int64
-
if err := rows.Scan(&publicKey.DID, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
return nil, err
}
publicKey.Created = time.Unix(*createdAt, 0)
···
package db
+
import (
+
"encoding/json"
+
"time"
+
)
func (d *DB) AddPublicKey(did, name, key string) error {
query := `insert into public_keys (did, name, key) values (?, ?, ?)`
···
}
type PublicKey struct {
+
Did string `json:"did"`
+
Key string `json:"key"`
+
Name string `json:"name"`
Created time.Time
}
+
func (p PublicKey) MarshalJSON() ([]byte, error) {
+
type Alias PublicKey
+
return json.Marshal(&struct {
+
Created int64 `json:"created"`
+
*Alias
+
}{
+
Created: p.Created.Unix(),
+
Alias: (*Alias)(&p),
+
})
+
}
+
func (d *DB) GetAllPublicKeys() ([]PublicKey, error) {
var keys []PublicKey
···
for rows.Next() {
var publicKey PublicKey
var createdAt *int64
+
if err := rows.Scan(&publicKey.Key, &publicKey.Name, &publicKey.Did, &createdAt); err != nil {
return nil, err
}
publicKey.Created = time.Unix(*createdAt, 0)
···
for rows.Next() {
var publicKey PublicKey
var createdAt *int64
+
if err := rows.Scan(&publicKey.Did, &publicKey.Key, &publicKey.Name, &createdAt); err != nil {
return nil, err
}
publicKey.Created = time.Unix(*createdAt, 0)
+1 -1
appview/pages/login.html
···
{{define "title"}}login{{end}}
{{define "content"}}
-
<h1>Login</h1>
<form method="POST" action="/login">
<label for="handle">handle</label>
<input type="text" id="handle" name="handle" required>
···
{{define "title"}}login{{end}}
{{define "content"}}
+
<h1>login</h1>
<form method="POST" action="/login">
<label for="handle">handle</label>
<input type="text" id="handle" name="handle" required>
+15
appview/pages/new-repo.html
···
···
+
{{define "title"}}new repo{{end}}
+
+
{{define "content"}}
+
<h1>new repo</h1>
+
<form method="POST" action="/repo/new">
+
<label for="name">repo name</label>
+
<input type="text" id="name" name="name" required>
+
+
<label for="domain">domain</label>
+
<input type="domain" id="domain" name="domain" required>
+
+
<button type="submit">create repo</button>
+
</form>
+
{{end}}
+
+8
appview/pages/pages.go
···
func Knot(w io.Writer, p KnotParams) error {
return parse("knot.html").Execute(w, p)
}
···
func Knot(w io.Writer, p KnotParams) error {
return parse("knot.html").Execute(w, p)
}
+
+
type NewRepoParams struct {
+
User *auth.User
+
}
+
+
func NewRepo(w io.Writer, p NewRepoParams) error {
+
return parse("new-repo.html").Execute(w, p)
+
}
+1
appview/pages/timeline.html
···
<p>logged in as {{ .User.Handle }}</p>
<a href="/settings">settings</a>
<a href="/knots">knots</a>
{{ else }}
<p>not logged in</p>
<a href="/login">login</a>
···
<p>logged in as {{ .User.Handle }}</p>
<a href="/settings">settings</a>
<a href="/knots">knots</a>
+
<a href="/repo/new">add repos</a>
{{ else }}
<p>not logged in</p>
<a href="/login">login</a>
+85 -29
appview/state/state.go
···
package state
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
"net/http"
···
// create a signed request and check if a node responds to that
func (s *State) InitKnotServer(w http.ResponseWriter, r *http.Request) {
domain := chi.URLParam(r, "domain")
if domain == "" {
http.Error(w, "malformed url", http.StatusBadRequest)
return
}
-
log.Println("checking ", domain)
-
secret, err := s.db.GetRegistrationKey(domain)
if err != nil {
-
log.Printf("no key found for domain %s: %s\n", domain, err)
return
}
-
log.Println("has secret ", secret)
-
// make a request do the knotserver with an empty body and above signature
-
url := fmt.Sprintf("http://%s/health", domain)
-
-
pingRequest, err := http.NewRequest("GET", url, nil)
if err != nil {
-
log.Println("failed to build ping request", err)
return
}
-
client := SignedClient(secret)
resp, err := client.Do(pingRequest)
···
return
}
-
if resp.StatusCode != http.StatusOK {
log.Println("status nok", resp.StatusCode)
w.Write([]byte("no dice"))
return
···
w.Write([]byte(fmt.Sprint("added member: ", memberIdent.Handle.String())))
}
-
// list members of domain, requires auth and requires owner status
func (s *State) RemoveMember(w http.ResponseWriter, r *http.Request) {
}
-
// func buildPingRequest(url, secret string) (*http.Request, error) {
-
// pingRequest, err := http.NewRequest("GET", url, nil)
-
// if err != nil {
-
// return nil, err
-
// }
-
//
-
// timestamp := time.Now().Format(time.RFC3339)
-
// mac := hmac.New(sha256.New, []byte(secret))
-
// message := pingRequest.Method + pingRequest.URL.Path + timestamp
-
// mac.Write([]byte(message))
-
// signature := hex.EncodeToString(mac.Sum(nil))
-
//
-
// pingRequest.Header.Set("X-Signature", signature)
-
// pingRequest.Header.Set("X-Timestamp", timestamp)
-
//
-
// return pingRequest, nil
-
// }
func (s *State) Router() http.Handler {
r := chi.NewRouter()
···
r.Delete("/", s.RemoveMember)
})
})
})
r.Group(func(r chi.Router) {
···
package state
import (
+
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
+
"encoding/json"
"fmt"
"log"
"net/http"
···
// create a signed request and check if a node responds to that
func (s *State) InitKnotServer(w http.ResponseWriter, r *http.Request) {
+
user := s.auth.GetUser(r)
+
domain := chi.URLParam(r, "domain")
if domain == "" {
http.Error(w, "malformed url", http.StatusBadRequest)
return
}
+
log.Println("checking ", domain)
+
url := fmt.Sprintf("http://%s/init", domain)
+
body, _ := json.Marshal(map[string]interface{}{
+
"did": user.Did,
+
"keys": []string{},
+
})
+
pingRequest, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
+
log.Println("failed to build ping request", err)
return
}
+
secret, err := s.db.GetRegistrationKey(domain)
if err != nil {
+
log.Printf("no key found for domain %s: %s\n", domain, err)
return
}
client := SignedClient(secret)
resp, err := client.Do(pingRequest)
···
return
}
+
if resp.StatusCode == http.StatusConflict {
+
log.Println("status conflict", resp.StatusCode)
+
w.Write([]byte("already registered, sorry!"))
+
return
+
}
+
+
if resp.StatusCode != http.StatusNoContent {
log.Println("status nok", resp.StatusCode)
w.Write([]byte("no dice"))
return
···
w.Write([]byte(fmt.Sprint("added member: ", memberIdent.Handle.String())))
}
func (s *State) RemoveMember(w http.ResponseWriter, r *http.Request) {
}
+
func (s *State) AddRepo(w http.ResponseWriter, r *http.Request) {
+
switch r.Method {
+
case http.MethodGet:
+
pages.NewRepo(w, pages.NewRepoParams{
+
User: s.auth.GetUser(r),
+
})
+
case http.MethodPost:
+
user := s.auth.GetUser(r)
+
+
domain := r.FormValue("domain")
+
if domain == "" {
+
log.Println("invalid form")
+
return
+
}
+
+
repoName := r.FormValue("name")
+
if repoName == "" {
+
log.Println("invalid form")
+
return
+
}
+
+
ok, err := s.enforcer.E.Enforce(user.Did, domain, domain, "repo:create")
+
if err != nil || !ok {
+
w.Write([]byte("domain inaccessible to you"))
+
return
+
}
+
+
secret, err := s.db.GetRegistrationKey(domain)
+
if err != nil {
+
log.Printf("no key found for domain %s: %s\n", domain, err)
+
return
+
}
+
+
client := SignedClient(secret)
+
url := fmt.Sprintf("http://%s/repo/new", domain)
+
body, _ := json.Marshal(map[string]interface{}{
+
"did": user.Did,
+
"name": repoName,
+
})
+
createRepoRequest, err := http.NewRequest("PUT", url, bytes.NewReader(body))
+
+
resp, err := client.Do(createRepoRequest)
+
+
if err != nil {
+
log.Println("failed to send create repo request", err)
+
return
+
}
+
+
if resp.StatusCode != http.StatusNoContent {
+
log.Println("server returned ", resp.StatusCode)
+
return
+
}
+
+
w.Write([]byte("created!"))
+
}
+
}
func (s *State) Router() http.Handler {
r := chi.NewRouter()
···
r.Delete("/", s.RemoveMember)
})
})
+
})
+
+
r.Route("/repo", func(r chi.Router) {
+
r.Route("/new", func(r chi.Router) {
+
r.Get("/", s.AddRepo)
+
r.Post("/", s.AddRepo)
+
})
+
// r.Post("/import", s.ImportRepo)
})
r.Group(func(r chi.Router) {