1// SPDX-FileCopyrightText: 2022 Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5package main
6
7import (
8 "io"
9 "log"
10 "net/http"
11 "net/url"
12 "strconv"
13 "strings"
14
15 "github.com/dchest/uniuri"
16 "github.com/dgraph-io/badger/v3"
17)
18
19func (m model) root(writer http.ResponseWriter, request *http.Request) {
20 path := request.URL.Path
21 if path != "/" {
22 destinationKey := strings.TrimPrefix(path, "/")
23 err := m.database.View(func(txn *badger.Txn) error {
24 destinationEntry, err := txn.Get([]byte(destinationKey))
25 if err == nil {
26 destinationValue, err := destinationEntry.ValueCopy(nil)
27 if err != nil {
28 return err
29 }
30 log.Println("Redirecting visitor to \"" + string(destinationValue) + "\"")
31 http.Redirect(writer, request, string(destinationValue), 302)
32 }
33 return err
34 })
35 if err != nil {
36 _, err = io.WriteString(writer, string(err.Error()))
37 if err != nil {
38 log.Println(err)
39 }
40 }
41 return
42 }
43
44 cookie, err := request.Cookie("access_token")
45 if err != nil || cookie.Value != m.AccessToken {
46 _, err = io.WriteString(writer, unauthenticated())
47 if err != nil {
48 log.Println(err)
49 }
50 return
51 }
52
53 query := request.URL.Query()
54
55 action := query.Get("action")
56 if len(action) == 0 {
57 start := query.Get("start")
58 end := query.Get("end")
59
60 if len(start) > 0 && len(end) > 0 {
61 http.Error(writer, "Submit either start OR end parameter, not both", 400)
62 }
63
64 countQuery := query.Get("count")
65 var count int
66 if len(countQuery) == 0 {
67 count = 20
68 } else {
69 count, err = strconv.Atoi(countQuery)
70 if err != nil {
71 http.Error(writer, err.Error(), 400)
72 return
73 }
74 }
75
76 links, err := m.read(start, end, count)
77 if err != nil {
78 http.Error(writer, err.Error(), 400)
79 return
80 }
81
82 if len(links) == 0 {
83 links, err = m.read("", "", count)
84 if err != nil {
85 http.Error(writer, err.Error(), 400)
86 return
87 }
88 }
89
90 _, err = io.WriteString(writer, m.authenticated(links))
91 if err != nil {
92 log.Println(err)
93 }
94 }
95
96 destination := query.Get("url")
97 name := query.Get("name")
98 oldName := query.Get("oldName")
99
100 var message string
101
102 if action == "create" {
103 if len(destination) == 0 {
104 message = "URL field is required"
105 http.Redirect(writer, request, "/?message="+message, 302)
106 return
107 }
108
109 if len(name) == 0 {
110 name = uniuri.NewLen(4)
111 for m.nameExists(name) {
112 name = uniuri.NewLen(4)
113 log.Println("Generated new name:", name)
114 }
115 } else if m.nameExists(name) {
116 http.Error(writer, "406 Not Acceptable: A shortened URL with this name already exists", 406)
117 message = "A shortened URL with this name already exists"
118 http.Redirect(writer, request, "/?message="+message, 302)
119 return
120 }
121
122 message = url.QueryEscape(m.create(name, destination))
123 http.Redirect(writer, request, "/?message="+message, 302)
124 return
125 }
126
127 if action == "edit" {
128 _, err = io.WriteString(writer, m.edit(name, destination))
129 if err != nil {
130 log.Println(err)
131 }
132 }
133
134 if action == "update" {
135 if len(destination) == 0 {
136 message = "URL field is required"
137 http.Redirect(writer, request, "/?message="+message, 302)
138 return
139 }
140
141 if len(name) == 0 {
142 message = "Name field is required"
143 http.Redirect(writer, request, "/?message="+message, 302)
144 return
145 }
146
147 if len(oldName) == 0 {
148 message = "oldName field is required"
149 http.Redirect(writer, request, "/?message="+message, 302)
150 return
151 }
152
153 if len(name) != 0 && oldName != name {
154 if m.nameExists(name) {
155 message = "A shortened URL with this name already exists"
156 http.Redirect(writer, request, "/?message="+message, 302)
157 return
158 }
159 }
160
161 message := url.QueryEscape(m.update(name, destination, oldName))
162 http.Redirect(writer, request, "/?message="+message, 302)
163 }
164
165 if action == "delete" {
166 if len(name) == 0 {
167 message = "Name field is required"
168 http.Redirect(writer, request, "/?message="+message, 302)
169 }
170 message := url.QueryEscape(m.delete(name))
171 log.Println(message)
172 http.Redirect(writer, request, "/?message="+message, 302)
173 }
174}