start thinking templates

This commit is contained in:
eyedeekay
2025-03-17 18:24:46 -04:00
parent 3e199c7466
commit 806fe00019
4 changed files with 231 additions and 2 deletions

View File

@ -1,7 +1,98 @@
package jumpserver
import "net/http"
import (
"html/template"
"net/http"
"path/filepath"
"time"
)
var templates *template.Template
func init() {
templates = template.Must(template.ParseFiles(
filepath.Join("tpl", "index.html"),
filepath.Join("tpl", "add.html"),
))
}
func (j *JumpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Serve the jump server
switch r.URL.Path {
case "/", "/index.html":
err := templates.ExecuteTemplate(w, "index.html", j)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
case "/add", "/add.html":
j.handleAdd(w, r)
case "/static/style.css":
http.ServeFile(w, r, filepath.Join("static", "style.css"))
case "/static/script.js":
http.ServeFile(w, r, filepath.Join("static", "script.js"))
default:
http.NotFound(w, r)
}
}
func (j *JumpServer) handleAdd(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
err := templates.ExecuteTemplate(w, "add.html", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
return
}
if r.Method == "POST" {
err := r.ParseForm()
if err != nil {
http.Error(w, "Failed to parse form", http.StatusBadRequest)
return
}
// Extract form data
hostname := r.Form.Get("hostname")
destination := r.Form.Get("destination")
regType := r.Form.Get("type")
name := r.Form.Get("name")
description := r.Form.Get("description")
tags := r.Form.Get("tags")
// Validate hostname
if hostname == "" {
http.Error(w, "Hostname is required", http.StatusBadRequest)
return
}
// Parse I2P address
addr, err := i2pkeys.DecodeFromString(destination)
if err != nil {
http.Error(w, "Invalid I2P destination", http.StatusBadRequest)
return
}
// Create new hostname entry
host := &Hostname{
I2PAddr: addr,
Time: time.Now(),
Registrant: Registrant{
Type: regType,
Name: name,
Description: description,
Tags: splitTags(tags),
},
Hostname: hostname,
}
// Add to jump server
j.AddHostname(host)
// Redirect to index page
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}

View File

@ -7,6 +7,7 @@ import (
type JumpServer struct {
*gohtmlmetadata.Extractor
Index string `json:"index"` // The intro page/index page content of the jump server
Hostnames []*Hostname `json:"hostnames"` // The hostnames of the jump server
Garlic *onramp.Garlic
}

View File

@ -0,0 +1,73 @@
pl/add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Host - I2P Jump Server</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<header>
<h1>Add Host to Jump Server</h1>
</header>
<main>
<section id="rules">
<h2>Rules for Adding Hosts</h2>
<ul>
<li>The hostname must be unique and not already registered</li>
<li>The I2P destination must be valid and reachable</li>
<li>The service must be actively running and maintained</li>
<li>No illegal or harmful content is allowed</li>
<li>Hostnames must be appropriate and not misleading</li>
</ul>
</section>
<section id="add-form">
<h2>Add New Host</h2>
<form method="POST" action="/add">
<div class="form-group">
<label for="hostname">Hostname:</label>
<input type="text" id="hostname" name="hostname" required
pattern="[a-zA-Z0-9.-]+"
title="Only letters, numbers, dots and hyphens allowed">
</div>
<div class="form-group">
<label for="destination">I2P Destination (Base32 or Base64):</label>
<textarea id="destination" name="destination" required></textarea>
</div>
<div class="form-group">
<label for="type">Type:</label>
<select id="type" name="type" required>
<option value="service">Service</option>
<option value="user">User</option>
</select>
</div>
<div class="form-group">
<label for="name">Registrant Name:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="description">Description:</label>
<textarea id="description" name="description"></textarea>
</div>
<div class="form-group">
<label for="tags">Tags (comma separated):</label>
<input type="text" id="tags" name="tags"
placeholder="e.g. blog, forum, social">
</div>
<button type="submit">Add Host</button>
</form>
</section>
</main>
<script src="/static/script.js"></script>
</body>
</html>

View File

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>I2P Jump Server</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<header>
<h1>I2P Jump Server</h1>
</header>
<main>
<section id="index-content">
{{if .Index}}
{{.Index}}
{{else}}
<p>Welcome to the I2P Jump Server. This service helps you discover and navigate I2P services.</p>
{{end}}
</section>
<section id="hostname-list">
<h2>Registered Hostnames</h2>
{{if .Hostnames}}
<table>
<thead>
<tr>
<th>Hostname</th>
<th>Base32 Address</th>
<th>Type</th>
<th>Registrant</th>
<th>Description</th>
<th>Tags</th>
<th>Added</th>
</tr>
</thead>
<tbody>
{{range .Hostnames}}
<tr>
<td>{{.Hostname}}</td>
<td>{{.I2PAddr.Base32}}</td>
<td>{{.Registrant.Type}}</td>
<td>{{.Registrant.Name}}</td>
<td>{{.Registrant.Description}}</td>
<td>
{{range .Registrant.Tags}}
<span class="tag">{{.}}</span>
{{end}}
</td>
<td>{{.Time.Format "2006-01-02"}}</td>
</tr>
{{end}}
</tbody>
</table>
{{else}}
<p>No hostnames registered yet.</p>
{{end}}
</section>
</main>
<script src="/static/script.js"></script>
</body>
</html>