-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathaction.go
103 lines (95 loc) · 2.78 KB
/
action.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/shurcooL/home/httputil"
"github.com/shurcooL/home/internal/code"
"github.com/shurcooL/httperror"
"github.com/shurcooL/httpgzip"
"github.com/shurcooL/users"
)
func initAction(code *code.Service, users users.Service) {
// "Create a New Repo" action.
http.Handle("/action/new-repo", cookieAuth{httputil.ErrorHandler(users, func(w http.ResponseWriter, req *http.Request) error {
if err := httputil.AllowMethods(req, http.MethodGet, http.MethodPost); err != nil {
return err
}
switch req.Method {
case http.MethodGet:
if user, err := users.GetAuthenticated(req.Context()); err != nil {
return err
} else if !user.SiteAdmin {
return os.ErrPermission
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
httpgzip.ServeContent(w, req, "", time.Time{}, strings.NewReader(newRepoHTML))
return nil
case http.MethodPost:
if err := req.ParseForm(); err != nil {
return httperror.BadRequest{Err: err}
}
repoSpec, err := getSingleValue(req.Form, "spec")
if err != nil {
return httperror.BadRequest{Err: err}
}
repoDescription, err := getSingleValue(req.Form, "description")
if err != nil {
return httperror.BadRequest{Err: err}
}
createRepoError := code.CreateRepo(req.Context(), repoSpec, repoDescription)
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
fmt.Fprintf(io.MultiWriter(os.Stdout, w), "creating new repo: spec=%q description=%q: err=%v\n", repoSpec, repoDescription, createRepoError)
return nil
default:
panic("unreachable")
}
})})
}
const newRepoHTML = `<!DOCTYPE html>
<html lang="en">
<head>
<title>Dmitri Shuralyov</title>
<link href="/icon.svg" rel="icon" type="image/svg+xml">
<meta name="viewport" content="width=device-width">
<link href="/assets/fonts/fonts.css" rel="stylesheet" type="text/css">
<style type="text/css">
body, input {
font-family: Go;
}
.wide {
width: 100%;
box-sizing: border-box;
}
</style>
</head>
<body>
<form method="post" action="/action/new-repo">
<h1>Create a New Repo</h1>
Repo Spec<br>
<input class="wide" name="spec" type="text" value="dmitri.shuralyov.com/"><br>
<br>
Description<br>
<input class="wide" name="description" type="text" placeholder="Description goes here." style="width: 100%;"><br>
<br>
<input type="submit" value="Create">
</form>
</body>
</html>
`
// getSingleValue returns the single value for key in form,
// or an error if there isn't exactly a single value.
func getSingleValue(form url.Values, key string) (string, error) {
v, ok := form[key]
if !ok {
return "", fmt.Errorf("key %q is not set", key)
}
if len(v) != 1 {
return "", fmt.Errorf("key %q has non-single value: %+v", key, v)
}
return v[0], nil
}