formatting
This commit is contained in:
parent
5c18b9938d
commit
e1afb206ae
11 changed files with 97 additions and 6 deletions
|
|
@ -5,6 +5,8 @@ import "os"
|
||||||
type (
|
type (
|
||||||
Config struct {
|
Config struct {
|
||||||
DatabaseURL string
|
DatabaseURL string
|
||||||
|
VpubDatabaseURL string
|
||||||
|
VpubAESKey string
|
||||||
SessionKey string
|
SessionKey string
|
||||||
Env string
|
Env string
|
||||||
CertFile string
|
CertFile string
|
||||||
|
|
@ -22,6 +24,8 @@ type (
|
||||||
func New() *Config {
|
func New() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
DatabaseURL: os.Getenv("DATABASE_URL"),
|
DatabaseURL: os.Getenv("DATABASE_URL"),
|
||||||
|
VpubDatabaseURL: os.Getenv("VPUB_DATABASE_URL"),
|
||||||
|
VpubAESKey: os.Getenv("VPUB_AES_KEY"),
|
||||||
SessionKey: os.Getenv("SESSION_KEY"),
|
SessionKey: os.Getenv("SESSION_KEY"),
|
||||||
Env: os.Getenv("ENV"),
|
Env: os.Getenv("ENV"),
|
||||||
CertFile: os.Getenv("CERT_FILE"),
|
CertFile: os.Getenv("CERT_FILE"),
|
||||||
|
|
|
||||||
7
main.go
7
main.go
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"status/config"
|
"status/config"
|
||||||
"status/storage"
|
"status/storage"
|
||||||
|
"status/vpub"
|
||||||
"status/web"
|
"status/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -15,7 +16,11 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
data := storage.New(db)
|
data := storage.New(db)
|
||||||
|
v, err := vpub.New(cfg.VpubDatabaseURL, []byte(cfg.VpubAESKey))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
log.Fatal(
|
log.Fatal(
|
||||||
web.Serve(data, cfg),
|
web.Serve(data, v, cfg),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
vpub/vpub.go
Normal file
45
vpub/vpub.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package vpub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Vpub struct {
|
||||||
|
db *sql.DB
|
||||||
|
key []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(databaseURL string, key []byte) (Vpub, error) {
|
||||||
|
db, err := sql.Open("postgres", databaseURL)
|
||||||
|
return Vpub{db: db, key: key}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncryptAES(key []byte, plaintext string) string {
|
||||||
|
c, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
out := make([]byte, len(plaintext))
|
||||||
|
c.Encrypt(out, []byte(plaintext))
|
||||||
|
return hex.EncodeToString(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Vpub) FindOrCreateKey(name string) string {
|
||||||
|
padded := fmt.Sprintf("%16s", name)
|
||||||
|
key := EncryptAES(v.key, padded)[0:20]
|
||||||
|
|
||||||
|
query := `
|
||||||
|
insert into keys (key) values ($1) ON CONFLICT do nothing
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := v.db.Exec(query, key[:20])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
@ -27,7 +27,7 @@ var TplCommonMap = map[string]string{
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<nav>
|
<nav>
|
||||||
<a href="/">status.cafe</a>
|
<a href="/">status.cafe</a> <a href="https://forum.status.cafe">forum</a>
|
||||||
{{ if .logged }}
|
{{ if .logged }}
|
||||||
<a href="/settings">settings</a> <a href="/users/{{ .logged }}">{{ .logged }}</a> (<a href="/logout">logout</a>)
|
<a href="/settings">settings</a> <a href="/users/{{ .logged }}">{{ .logged }}</a> (<a href="/logout">logout</a>)
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"status/config"
|
"status/config"
|
||||||
"status/storage"
|
"status/storage"
|
||||||
|
"status/vpub"
|
||||||
"status/web/session"
|
"status/web/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,6 +29,7 @@ type Handler struct {
|
||||||
mux *mux.Router
|
mux *mux.Router
|
||||||
storage *storage.Storage
|
storage *storage.Storage
|
||||||
sess *session.Session
|
sess *session.Session
|
||||||
|
vpub vpub.Vpub
|
||||||
}
|
}
|
||||||
|
|
||||||
func protectClickJacking(w http.ResponseWriter) {
|
func protectClickJacking(w http.ResponseWriter) {
|
||||||
|
|
@ -43,13 +45,14 @@ func (h *Handler) getUser(r *http.Request) (string, error) {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http.Handler, error) {
|
func New(cfg *config.Config, sess *session.Session, data *storage.Storage, v vpub.Vpub) (http.Handler, error) {
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
mux: router,
|
mux: router,
|
||||||
storage: data,
|
storage: data,
|
||||||
sess: sess,
|
sess: sess,
|
||||||
|
vpub: v,
|
||||||
}
|
}
|
||||||
h.initTpl()
|
h.initTpl()
|
||||||
|
|
||||||
|
|
@ -66,6 +69,7 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http
|
||||||
|
|
||||||
router.HandleFunc("/settings", h.showSettingsView).Methods(http.MethodGet)
|
router.HandleFunc("/settings", h.showSettingsView).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/settings-update", h.updateSettings).Methods(http.MethodPost)
|
router.HandleFunc("/settings-update", h.updateSettings).Methods(http.MethodPost)
|
||||||
|
router.HandleFunc("/forum-key", h.showKeyView).Methods(http.MethodGet)
|
||||||
|
|
||||||
router.HandleFunc("/add", h.showNewStatusView).Methods(http.MethodGet)
|
router.HandleFunc("/add", h.showNewStatusView).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/add", h.saveStatus).Methods(http.MethodPost)
|
router.HandleFunc("/add", h.saveStatus).Methods(http.MethodPost)
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,12 @@ var TplMap = map[string]string{
|
||||||
{{ .csrfField }}
|
{{ .csrfField }}
|
||||||
{{ template "status_form" .status }}
|
{{ template "status_form" .status }}
|
||||||
</form>
|
</form>
|
||||||
|
{{ end }}`,
|
||||||
|
"forum-key": `{{ define "content" }}
|
||||||
|
<h1>Forum key</h1>
|
||||||
|
|
||||||
|
<p>Your forum key is:</p>
|
||||||
|
<pre>{{ .key }}</pre>
|
||||||
{{ end }}`,
|
{{ end }}`,
|
||||||
"index": `{{ define "head" }}
|
"index": `{{ define "head" }}
|
||||||
<link rel="alternate" type="application/atom+xml" title="Atom feed" href="/feed.atom" />
|
<link rel="alternate" type="application/atom+xml" title="Atom feed" href="/feed.atom" />
|
||||||
|
|
@ -180,6 +186,7 @@ var TplMap = map[string]string{
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Status stream</h2>
|
<h2>Status stream</h2>
|
||||||
|
<p class="flash">The <a href="https://forum.status.cafe">forum</a> has opened! <a href="/forum-key">Generate your key</a> to <a href="https://forum.status.cafe/register">register</a>. Best viewed with a hot beverage.</p>
|
||||||
{{ range .statuses }}
|
{{ range .statuses }}
|
||||||
<article class="status">
|
<article class="status">
|
||||||
{{ template "status" . }}
|
{{ template "status" . }}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<nav>
|
<nav>
|
||||||
<a href="/">status.cafe</a>
|
<a href="/">status.cafe</a> <a href="https://forum.status.cafe">forum</a>
|
||||||
{{ if .logged }}
|
{{ if .logged }}
|
||||||
<a href="/settings">settings</a> <a href="/users/{{ .logged }}">{{ .logged }}</a> (<a href="/logout">logout</a>)
|
<a href="/settings">settings</a> <a href="/users/{{ .logged }}">{{ .logged }}</a> (<a href="/logout">logout</a>)
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
|
|
||||||
6
web/handler/html/forum-key.html
Normal file
6
web/handler/html/forum-key.html
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
<h1>Forum key</h1>
|
||||||
|
|
||||||
|
<p>Your forum key is:</p>
|
||||||
|
<pre>{{ .key }}</pre>
|
||||||
|
{{ end }}
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Status stream</h2>
|
<h2>Status stream</h2>
|
||||||
|
<p class="flash">The <a href="https://forum.status.cafe">forum</a> has opened! <a href="/forum-key">Generate your key</a> to <a href="https://forum.status.cafe/register">register</a>. Best viewed with a hot beverage.</p>
|
||||||
{{ range .statuses }}
|
{{ range .statuses }}
|
||||||
<article class="status">
|
<article class="status">
|
||||||
{{ template "status" . }}
|
{{ template "status" . }}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,24 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (h *Handler) showKeyView(w http.ResponseWriter, r *http.Request) {
|
||||||
|
protectClickJacking(w)
|
||||||
|
username, err := h.getUser(r)
|
||||||
|
if err != nil {
|
||||||
|
unauthorized(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user, err := h.storage.UserByName(username)
|
||||||
|
if err != nil {
|
||||||
|
unauthorized(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key := h.vpub.FindOrCreateKey(user.Name)
|
||||||
|
h.renderLayout(w, "forum-key", map[string]interface{}{
|
||||||
|
"key": key,
|
||||||
|
}, username)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) showSettingsView(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) showSettingsView(w http.ResponseWriter, r *http.Request) {
|
||||||
protectClickJacking(w)
|
protectClickJacking(w)
|
||||||
username, err := h.getUser(r)
|
username, err := h.getUser(r)
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,15 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"status/config"
|
"status/config"
|
||||||
"status/storage"
|
"status/storage"
|
||||||
|
"status/vpub"
|
||||||
"status/web/handler"
|
"status/web/handler"
|
||||||
"status/web/session"
|
"status/web/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Serve(data *storage.Storage, cfg *config.Config) error {
|
func Serve(data *storage.Storage, v vpub.Vpub, cfg *config.Config) error {
|
||||||
var err error
|
var err error
|
||||||
sess := session.New(cfg.SessionKey, data)
|
sess := session.New(cfg.SessionKey, data)
|
||||||
s, err := handler.New(cfg, sess, data)
|
s, err := handler.New(cfg, sess, data, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue