1package main
2
3import (
4 "fmt"
5 "io"
6 "log"
7 "net/http"
8 "net/url"
9 "strings"
10
11 "github.com/dchest/uniuri"
12 "github.com/dgraph-io/badger/v3"
13)
14
15func (m model) root(writer http.ResponseWriter, request *http.Request) {
16 path := request.URL.Path
17 if path != "/" {
18 destinationKey := strings.TrimPrefix(path, "/")
19 err := m.database.View(func(txn *badger.Txn) error {
20 destinationEntry, err := txn.Get([]byte(destinationKey))
21 if err == nil {
22 destinationValue, err := destinationEntry.ValueCopy(nil)
23 if err != nil {
24 return err
25 }
26 log.Println("Redirecting visitor to \"" + string(destinationValue) + "\"")
27 http.Redirect(writer, request, string(destinationValue), 302)
28 }
29 return err
30 })
31 if err != nil {
32 io.WriteString(writer, string(err.Error()))
33 }
34 return
35 }
36
37 cookie, err := request.Cookie("access_token")
38 if err != nil || cookie.Value != m.AccessToken {
39 io.WriteString(writer, unauthenticated())
40 return
41 }
42
43 query := request.URL.Query()
44
45 action := query.Get("action")
46 if len(action) == 0 {
47 io.WriteString(writer, m.authenticated())
48 }
49
50 destination := query.Get("url")
51 name := query.Get("name")
52 oldName := query.Get("oldName")
53
54 var message string
55
56 if action == "create" {
57 if len(destination) == 0 {
58 message = "URL field is required"
59 http.Redirect(writer, request, "/?message="+message, 302)
60 return
61 }
62
63 if len(name) == 0 {
64 name = uniuri.NewLen(4)
65 for m.nameExists(name) {
66 name = uniuri.NewLen(4)
67 log.Println("Generated new name:", name)
68 }
69 } else if m.nameExists(name) {
70 http.Error(writer, "406 Not Acceptable: A shortened URL with this name already exists", 406)
71 message = "A shortened URL with this name already exists"
72 http.Redirect(writer, request, "/?message="+message, 302)
73 return
74 }
75
76 message = url.QueryEscape(m.create(name, destination))
77 http.Redirect(writer, request, "/?message="+message, 302)
78 return
79 }
80
81 if action == "edit" {
82 io.WriteString(writer, m.edit(name, destination))
83 }
84
85 if action == "update" {
86 if len(destination) == 0 {
87 message = "URL field is required"
88 http.Redirect(writer, request, "/?message="+message, 302)
89 return
90 }
91
92 if len(name) == 0 {
93 message = "Name field is required"
94 http.Redirect(writer, request, "/?message="+message, 302)
95 return
96 }
97
98 if len(oldName) == 0 {
99 message = "oldName field is required"
100 http.Redirect(writer, request, "/?message="+message, 302)
101 return
102 }
103
104 if len(name) != 0 && oldName != name {
105 if m.nameExists(name) {
106 message = "A shortened URL with this name already exists"
107 http.Redirect(writer, request, "/?message="+message, 302)
108 return
109 }
110 }
111
112 message := url.QueryEscape(m.update(name, destination, oldName))
113 http.Redirect(writer, request, "/?message="+message, 302)
114 }
115
116 if action == "delete" {
117 if len(name) == 0 {
118 message = "Name field is required"
119 http.Redirect(writer, request, "/?message="+message, 302)
120 }
121 message := url.QueryEscape(m.delete(name))
122 log.Println(message)
123 http.Redirect(writer, request, "/?message="+message, 302)
124 }
125}
126
127func (m model) genTable() string {
128 var table string
129 err := m.database.View(func(txn *badger.Txn) error {
130 opts := badger.DefaultIteratorOptions
131 opts.PrefetchSize = 10
132 iterator := txn.NewIterator(opts)
133 defer iterator.Close()
134 for iterator.Rewind(); iterator.Valid(); iterator.Next() {
135 item := iterator.Item()
136 k := item.Key()
137 err := item.Value(func(v []byte) error {
138 table = table + fmt.Sprintf(`<tr>
139 <td><p>%s</p></td>
140 <td><p>%s</p></td>
141 <td><a href="/?action=edit&name=%s&url=%s">Edit</a><a href="/?action=delete&name=%s">Delete</a></td>
142</tr>`, k, v, k, url.QueryEscape(string(v)), k)
143 return nil
144 })
145 if err != nil {
146 return err
147 }
148 }
149 return nil
150 })
151 if err != nil {
152 return err.Error()
153 }
154 return table
155}