Compare commits
No commits in common. "75ba836d6072235fc7a71659f8630ab3c1b210ad" and "68f3bd53328606a921dd72870f38723286d803e1" have entirely different histories.
75ba836d60
...
68f3bd5332
23
api/dns.go
23
api/dns.go
|
@ -1,23 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.hatecomputers.club/hatecomputers/hatecomputers.club/database"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ListDNSRecordsContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
|
||||||
return func(success Continuation, failure Continuation) ContinuationChain {
|
|
||||||
dnsRecords, err := database.GetUserDNSRecords(context.DBConn, context.User.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
resp.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return failure(context, req, resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
(*context.TemplateData)["DNSRecords"] = dnsRecords
|
|
||||||
|
|
||||||
return success(context, req, resp)
|
|
||||||
}
|
|
||||||
}
|
|
14
api/serve.go
14
api/serve.go
|
@ -19,8 +19,7 @@ type RequestContext struct {
|
||||||
Id string
|
Id string
|
||||||
Start time.Time
|
Start time.Time
|
||||||
|
|
||||||
TemplateData *map[string]interface{}
|
User *database.User
|
||||||
User *database.User
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Continuation func(*RequestContext, *http.Request, http.ResponseWriter) ContinuationChain
|
type Continuation func(*RequestContext, *http.Request, http.ResponseWriter) ContinuationChain
|
||||||
|
@ -76,14 +75,12 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server {
|
||||||
return &RequestContext{
|
return &RequestContext{
|
||||||
DBConn: dbConn,
|
DBConn: dbConn,
|
||||||
Args: argv,
|
Args: argv,
|
||||||
|
|
||||||
TemplateData: &map[string]interface{}{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestContext := makeRequestContext()
|
requestContext := makeRequestContext()
|
||||||
LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation("home.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation("home.html", nil, true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.HandleFunc("GET /api/health", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("GET /api/health", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -111,15 +108,10 @@ func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server {
|
||||||
LogRequestContinuation(requestContext, r, w)(LogoutContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
LogRequestContinuation(requestContext, r, w)(LogoutContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.HandleFunc("GET /dns", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
requestContext := makeRequestContext()
|
|
||||||
LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(ListDNSRecordsContinuation, GoLoginContinuation)(TemplateContinuation("dns.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
|
||||||
})
|
|
||||||
|
|
||||||
mux.HandleFunc("GET /{name}", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("GET /{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
requestContext := makeRequestContext()
|
requestContext := makeRequestContext()
|
||||||
name := r.PathValue("name")
|
name := r.PathValue("name")
|
||||||
LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation(name+".html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
LogRequestContinuation(requestContext, r, w)(VerifySessionContinuation, FailurePassingContinuation)(IdContinuation, IdContinuation)(TemplateContinuation(name+".html", nil, true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
||||||
})
|
})
|
||||||
|
|
||||||
return &http.Server{
|
return &http.Server{
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func renderTemplate(context *RequestContext, templateName string, showBaseHtml bool) (bytes.Buffer, error) {
|
func renderTemplate(context *RequestContext, templateName string, showBaseHtml bool, data interface{}) (bytes.Buffer, error) {
|
||||||
templatePath := context.Args.TemplatePath
|
templatePath := context.Args.TemplatePath
|
||||||
basePath := templatePath + "/base_empty.html"
|
basePath := templatePath + "/base_empty.html"
|
||||||
if showBaseHtml {
|
if showBaseHtml {
|
||||||
|
@ -22,14 +22,11 @@ func renderTemplate(context *RequestContext, templateName string, showBaseHtml b
|
||||||
return bytes.Buffer{}, err
|
return bytes.Buffer{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dataPtr := context.TemplateData
|
if data == nil {
|
||||||
if dataPtr == nil {
|
data = map[string]interface{}{}
|
||||||
dataPtr = &map[string]interface{}{}
|
|
||||||
}
|
}
|
||||||
|
if context.User != nil {
|
||||||
data := *dataPtr
|
data.(map[string]interface{})["User"] = context.User
|
||||||
if data["User"] == nil {
|
|
||||||
data["User"] = context.User
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
|
@ -41,13 +38,13 @@ func renderTemplate(context *RequestContext, templateName string, showBaseHtml b
|
||||||
return buffer, nil
|
return buffer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TemplateContinuation(path string, showBase bool) Continuation {
|
func TemplateContinuation(path string, data interface{}, showBase bool) Continuation {
|
||||||
return func(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
return func(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
||||||
return func(success Continuation, failure Continuation) ContinuationChain {
|
return func(success Continuation, failure Continuation) ContinuationChain {
|
||||||
html, err := renderTemplate(context, path, true)
|
html, err := renderTemplate(context, path, true, data)
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
resp.WriteHeader(404)
|
resp.WriteHeader(404)
|
||||||
html, err = renderTemplate(context, "404.html", true)
|
html, err = renderTemplate(context, "404.html", true, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error rendering 404 template", err)
|
log.Println("error rendering 404 template", err)
|
||||||
resp.WriteHeader(500)
|
resp.WriteHeader(500)
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
"log"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DNSRecord struct {
|
|
||||||
ID string
|
|
||||||
UserID string
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
Content string
|
|
||||||
TTL int
|
|
||||||
CreatedAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserDNSRecords(db *sql.DB, userID string) ([]DNSRecord, error) {
|
|
||||||
log.Println("getting dns records for user", userID)
|
|
||||||
|
|
||||||
rows, err := db.Query("SELECT * FROM dns_records WHERE user_id = ?", userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var records []DNSRecord
|
|
||||||
for rows.Next() {
|
|
||||||
var record DNSRecord
|
|
||||||
err := rows.Scan(&record.ID, &record.UserID, &record.Name, &record.Type, &record.Content, &record.TTL, &record.CreatedAt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
records = append(records, record)
|
|
||||||
}
|
|
||||||
|
|
||||||
return records, nil
|
|
||||||
}
|
|
|
@ -1,33 +1,13 @@
|
||||||
:root {
|
:root {
|
||||||
--background-color-light: #f4e8e9;
|
--background-color: #f4e8e9;
|
||||||
--background-color-light-2: #f7f7f7;
|
--text-color: #333;
|
||||||
--text-color-light: #333;
|
--link-color: #d291bc;
|
||||||
--link-color-light: #d291bc;
|
--container-bg: #fff7f8;
|
||||||
--container-bg-light: #fff7f87a;
|
|
||||||
--border-color-light: #692fcc;
|
|
||||||
|
|
||||||
--background-color-dark: #333;
|
|
||||||
--background-color-dark-2: #2c2c2c;
|
|
||||||
--text-color-dark: #f4e8e9;
|
|
||||||
--link-color-dark: #b86b77;
|
|
||||||
--container-bg-dark: #424242ea;
|
|
||||||
--border-color-dark: #956ade;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="DARK"] {
|
[data-theme="DARK"] {
|
||||||
--background-color: var(--background-color-dark);
|
--background-color: #333;
|
||||||
--background-color-2: var(--background-color-dark-2);
|
--text-color: #f4e8e9;
|
||||||
--text-color: var(--text-color-dark);
|
--link-color: #b86b77;
|
||||||
--link-color: var(--link-color-dark);
|
--container-bg: #424242;
|
||||||
--container-bg: var(--container-bg-dark);
|
|
||||||
--border-color: var(--border-color-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-theme="LIGHT"] {
|
|
||||||
--background-color: var(--background-color-light);
|
|
||||||
--background-color-2: var(--background-color-light-2);
|
|
||||||
--text-color: var(--text-color-light);
|
|
||||||
--link-color: var(--link-color-light);
|
|
||||||
--container-bg: var(--container-bg-light);
|
|
||||||
--border-color: var(--border-color-light);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
form {
|
|
||||||
max-width: 600px;
|
|
||||||
padding: 1em;
|
|
||||||
background: var(--background-color-2);
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
margin: 0 0 1em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.5em;
|
|
||||||
margin: 0 0 1em;
|
|
||||||
border: 1px solid var(--border-color);
|
|
||||||
background: var(--container-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
input[type="submit"] {
|
|
||||||
padding: 0.5em 1em;
|
|
||||||
background: var(--link-color);
|
|
||||||
color: var(--text-color);
|
|
||||||
border: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
@import "/static/css/colors.css";
|
@import "/static/css/colors.css";
|
||||||
@import "/static/css/blinky.css";
|
@import "/static/css/blinky.css";
|
||||||
@import "/static/css/table.css";
|
|
||||||
@import "/static/css/form.css";
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "ComicSans";
|
font-family: "ComicSans";
|
||||||
|
@ -13,10 +11,10 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-family: "ComicSans", sans-serif;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
font-family: "ComicSans", sans-serif;
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
background-image: url("/static/img/stars.gif");
|
background-image: url("/static/img/stars.gif");
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
@ -37,6 +35,7 @@ a:hover {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
background-color: var(--container-bg);
|
background-color: var(--container-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
opacity: 0.95;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
|
@ -45,11 +44,3 @@ hr {
|
||||||
|
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blinkies {
|
|
||||||
display: flex;
|
|
||||||
justify-content: left;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
max-width: 900px;
|
|
||||||
gap: 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
table {
|
|
||||||
width: auto;
|
|
||||||
border-collapse: collapse;
|
|
||||||
border: 1px solid var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 12px 20px;
|
|
||||||
text-align: left;
|
|
||||||
border-bottom: 1px solid var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(odd) {
|
|
||||||
background-color: var(--link-color);
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr {
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:hover {
|
|
||||||
background-color: #ff47daa0;
|
|
||||||
color: #2a2a2a;
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 704 B |
|
@ -24,4 +24,4 @@ themeSwitcher.addEventListener("click", () =>
|
||||||
setTheme(flipFlopTheme(document.documentElement.getAttribute("data-theme"))),
|
setTheme(flipFlopTheme(document.documentElement.getAttribute("data-theme"))),
|
||||||
);
|
);
|
||||||
|
|
||||||
setTheme(localStorage.getItem("theme") || THEMES.LIGHT);
|
setTheme(localStorage.getItem("theme") ?? THEMES.LIGHT);
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
const preferredMode = window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
||||||
? "DARK"
|
|
||||||
: "LIGHT";
|
|
||||||
|
|
||||||
// sets theme before rendering & jquery loaded to prevent flashing of uninitialized theme
|
// sets theme before rendering & jquery loaded to prevent flashing of uninitialized theme
|
||||||
// (ugly white background)
|
// (ugly white background)
|
||||||
localStorage.setItem("theme", localStorage.getItem("theme") || preferredMode);
|
|
||||||
document.documentElement.setAttribute(
|
document.documentElement.setAttribute(
|
||||||
"data-theme",
|
"data-theme",
|
||||||
localStorage.getItem("theme"),
|
localStorage.getItem("theme"),
|
||||||
|
|
|
@ -50,31 +50,23 @@
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div>
|
<div>
|
||||||
{{ if .User }}
|
<img width="150" height="20" src="/static/img/blinkies/hatecomputers-club.gif">
|
||||||
<a href="https://git.hatecomputers.club/{{ .User.Username }}">git.</a>
|
<img width="150" height="20" src="/static/img/blinkies/loveuguys.gif">
|
||||||
{{ else }}
|
<img width="150" height="20" src="/static/img/blinkies/autism.gif">
|
||||||
<a href="https://git.hatecomputers.club">git.</a>
|
<img width="150" height="20" src="/static/img/blinkies/fuckcomputers.gif">
|
||||||
{{ end }}
|
<img width="150" height="20" src="/static/img/blinkies/connection.gif">
|
||||||
|
|
||||||
<span> | </span>
|
|
||||||
<a href="https://mail.hatecomputers.club">e-mail.</a>
|
|
||||||
<span> | </span>
|
|
||||||
<a href="https://auth.hatecomputers.club">sso.</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
{{ if .User }}
|
||||||
|
<a href="https://git.hatecomputers.club/{{ .User.Username }}">git.</a>
|
||||||
|
{{ else }}
|
||||||
|
<a href="https://git.hatecomputers.club">git.</a>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
<div class="blinkies">
|
<span> | </span>
|
||||||
<img width='150' height='20' src='/static/img/blinkies/hatecomputers-club.gif'>
|
<a href="https://mail.hatecomputers.club">e-mail.</a>
|
||||||
<img width='150' height='20' src='/static/img/blinkies/autism.gif'>
|
<span> | </span>
|
||||||
<img width='150' height='20' src='/static/img/blinkies/fuckcomputers.gif'>
|
<a href="https://auth.hatecomputers.club">sso.</a>
|
||||||
<img width='150' height='20' src='/static/img/blinkies/bee.gif'>
|
|
||||||
<img width='150' height='20' src='/static/img/blinkies/begaydocrime.gif'>
|
|
||||||
<img width='150' height='20' src='/static/img/blinkies/bored.gif'>
|
|
||||||
<img width='150' height='20' src='/static/img/blinkies/connection.gif'>
|
|
||||||
<img width='150' height='20' src='/static/img/blinkies/eepy.gif'>
|
|
||||||
<img width='150' height='20' src='/static/img/blinkies/loveuguys.gif'>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
{{ define "content" }}
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Content</th>
|
|
||||||
<th>TTL</th>
|
|
||||||
</tr>
|
|
||||||
{{ if (eq (len .DNSRecords) 0) }}
|
|
||||||
<tr>
|
|
||||||
<td colspan="4"><span class="blinky">No DNS records found</span></td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
{{ range $record := .DNSRecords }}
|
|
||||||
<tr>
|
|
||||||
<td>{{ $record.Type }}</td>
|
|
||||||
<td>{{ $record.Name }}</td>
|
|
||||||
<td>{{ $record.Content }}</td>
|
|
||||||
<td>{{ $record.TTL }}</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</table>
|
|
||||||
<br>
|
|
||||||
<form method="POST" action="/dns">
|
|
||||||
<h2>Add DNS Records</h2>
|
|
||||||
<hr>
|
|
||||||
<label for="type">Type</label>
|
|
||||||
<input type="text" name="type" placeholder="CNAME" required />
|
|
||||||
<label for="name">Name</label>
|
|
||||||
<input type="text" name="name" placeholder="{{ .User.Username }}" required />
|
|
||||||
<label for="content">Content</label>
|
|
||||||
<input type="text" name="content" placeholder="{{ .User.Username }}.dev" required />
|
|
||||||
<label for="ttl">TTL</label>
|
|
||||||
<input type="text" name="ttl" placeholder="43200" required />
|
|
||||||
<input type="submit" value="Add" />
|
|
||||||
</form>
|
|
||||||
{{ end }}
|
|
Loading…
Reference in New Issue