mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-10-29 19:26:16 +00:00
Adjsut terminology and add MOTDs
This commit is contained in:
parent
55d8dbd7be
commit
1fbef60857
77
auth/web.go
77
auth/web.go
@ -1,13 +1,11 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
|
||||
@ -29,9 +27,7 @@ func InitAuth(r *mux.Router) {
|
||||
if cfg.AllowRegistration {
|
||||
r.HandleFunc("/register", handlerRegister).Methods(http.MethodPost, http.MethodGet)
|
||||
}
|
||||
if cfg.TelegramEnabled {
|
||||
r.HandleFunc("/telegram-login", handlerTelegramLogin)
|
||||
}
|
||||
|
||||
r.HandleFunc("/login", handlerLogin)
|
||||
r.HandleFunc("/logout", handlerLogout)
|
||||
}
|
||||
@ -152,74 +148,3 @@ func handlerLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
// Note there is no lock here.
|
||||
lc := l18n.FromRequest(rq)
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
rq.ParseForm()
|
||||
var (
|
||||
values = rq.URL.Query()
|
||||
username = strings.ToLower(values.Get("username"))
|
||||
seemsValid = user.TelegramAuthParamsAreValid(values)
|
||||
err = user.Register(
|
||||
username,
|
||||
"", // Password matters not
|
||||
"editor",
|
||||
"telegram",
|
||||
false,
|
||||
)
|
||||
)
|
||||
// If registering a user via Telegram failed, because a Telegram user with this name
|
||||
// has already registered, then everything is actually ok!
|
||||
if user.HasUsername(username) && user.ByName(username).Source == "telegram" {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if !seemsValid {
|
||||
err = errors.New("Wrong parameters")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to register ‘%s’ using Telegram: %s", username, err.Error())
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.error"),
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s</p><p>%s</p><p><a href="/login">%s<a></p></main>`,
|
||||
lc.Get("auth.error_telegram"),
|
||||
err.Error(),
|
||||
lc.Get("auth.go_login"),
|
||||
),
|
||||
map[string]string{},
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
errmsg := user.LoginDataHTTP(w, username, "")
|
||||
if errmsg != nil {
|
||||
log.Printf("Failed to login ‘%s’ using Telegram: %s", username, err.Error())
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s</p><p>%s</p><p><a href="/login">%s<a></p></main>`,
|
||||
lc.Get("auth.error_telegram"),
|
||||
err.Error(),
|
||||
lc.Get("auth.go_login"),
|
||||
),
|
||||
map[string]string{},
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
log.Printf("Authorize ‘%s’ from Telegram", username)
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ var (
|
||||
|
||||
ReplaceFrom []string
|
||||
ReplaceTo []string
|
||||
|
||||
Motds []string
|
||||
)
|
||||
|
||||
// WikiDir is a full path to the wiki storage directory, which also must be a
|
||||
@ -64,6 +66,7 @@ type Config struct {
|
||||
Telegram `comment:"You can enable Telegram authorization. Follow these instructions: https://core.telegram.org/widgets/login#setting-up-a-bot"`
|
||||
ReplaceFrom []string
|
||||
ReplaceTo []string
|
||||
Motds []string
|
||||
}
|
||||
|
||||
// Hyphae is a section of Config which has fields related to special hyphae.
|
||||
@ -153,17 +156,17 @@ func ReadConfigFile(path string) error {
|
||||
// Save the default configuration
|
||||
err = f.ReflectFrom(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to serialize the config: %w", err)
|
||||
return fmt.Errorf("failed to serialize the config: %w", err)
|
||||
}
|
||||
|
||||
// Disable key-value auto-aligning, but retain spaces around '=' sign
|
||||
ini.PrettyFormat = false
|
||||
ini.PrettyEqual = true
|
||||
if err = f.SaveTo(path); err != nil {
|
||||
return fmt.Errorf("Failed to save the config file: %w", err)
|
||||
return fmt.Errorf("failed to save the config file: %w", err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("Failed to open the config file: %w", err)
|
||||
return fmt.Errorf("failed to open the config file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,6 +201,7 @@ func ReadConfigFile(path string) error {
|
||||
TelegramEnabled = (TelegramBotToken != "") && (TelegramBotName != "")
|
||||
ReplaceFrom = cfg.ReplaceFrom
|
||||
ReplaceTo = cfg.ReplaceTo
|
||||
Motds = cfg.Motds
|
||||
|
||||
// This URL makes much more sense. If no URL is set or the protocol is forgotten, assume HTTP.
|
||||
if URL == "" {
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{define "list of hyphae"}}List of hyphae{{end}}
|
||||
{{define "list of hyphae"}}List of pages{{end}}
|
||||
{{define "title"}}{{template "list of hyphae"}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width">
|
||||
|
@ -1,25 +1,2 @@
|
||||
User-agent: *
|
||||
Allow: /help/
|
||||
Allow: /hypha/
|
||||
Allow: /recent-changes
|
||||
Allow: /list
|
||||
Disallow: /page/
|
||||
Disallow: /admin/
|
||||
Disallow: /lock
|
||||
Disallow: /text/
|
||||
Disallow: /binary/
|
||||
Disallow: /rev/
|
||||
Disallow: /rev-text/
|
||||
Disallow: /primitive-diff/
|
||||
Disallow: /media/
|
||||
Disallow: /edit/
|
||||
Disallow: /delete/
|
||||
Disallow: /rename/
|
||||
Disallow: /remove-media/
|
||||
Disallow: /history/
|
||||
Disallow: /orphans
|
||||
Disallow: /random
|
||||
Disallow: /title-search/
|
||||
Disallow: /backlinks/
|
||||
Disallow: /user-list
|
||||
Crawl-delay: 5
|
||||
Allow: /
|
@ -290,24 +290,24 @@ function openHelp() {
|
||||
rrh.shortcuts.addGroup(new ShortcutGroup('Common', null, [
|
||||
new Shortcut('g', $$('.top-bar__highlight-link'), 'First 9 header links'),
|
||||
new Shortcut('g h', '/', 'Home'),
|
||||
new Shortcut('g l', '/list/', 'List of hyphae'),
|
||||
new Shortcut('g l', '/list/', 'List of page'),
|
||||
new Shortcut('g r', '/recent-changes/', 'Recent changes'),
|
||||
new Shortcut('g u', $('.auth-links__user-link'), 'Your profile′s hypha'),
|
||||
new Shortcut('g u', $('.auth-links__user-link'), 'Your profile′s page'),
|
||||
new Shortcut(['?', isMac ? 'Meta+/' : 'Ctrl+/'], openHelp, 'Shortcut help', { force: true }),
|
||||
]))
|
||||
|
||||
if (document.body.dataset.rrhAddr.startsWith('/hypha')) {
|
||||
rrh.shortcuts.addGroup(new ShortcutGroup('Hypha', null, [
|
||||
new Shortcut('', $$('article .wikilink'), 'First 9 hypha′s links'),
|
||||
new Shortcut(['p', 'Alt+ArrowLeft', 'Ctrl+Alt+ArrowLeft'], $('.prevnext__prev'), 'Previous hypha'),
|
||||
new Shortcut(['n', 'Alt+ArrowRight', 'Ctrl+Alt+ArrowRight'], $('.prevnext__next'), 'Next hypha'),
|
||||
new Shortcut(['s', 'Alt+ArrowUp', 'Ctrl+Alt+ArrowUp'], $$('.navi-title a').slice(1, -1).slice(-1)[0], 'Parent hypha'),
|
||||
new Shortcut(['c', 'Alt+ArrowDown', 'Ctrl+Alt+ArrowDown'], $('.subhyphae__link'), 'First child hypha'),
|
||||
new Shortcut(['e', isMac ? 'Meta+Enter' : 'Ctrl+Enter'], $('.btn__link_navititle[href^="/edit/"]'), 'Edit this hypha'),
|
||||
new Shortcut('v', $('.hypha-info__link[href^="/hypha/"]'), 'Go to hypha′s page'),
|
||||
rrh.shortcuts.addGroup(new ShortcutGroup('Page', null, [
|
||||
new Shortcut('', $$('article .wikilink'), 'First 9 pages′ links'),
|
||||
new Shortcut(['p', 'Alt+ArrowLeft', 'Ctrl+Alt+ArrowLeft'], $('.prevnext__prev'), 'Previous page'),
|
||||
new Shortcut(['n', 'Alt+ArrowRight', 'Ctrl+Alt+ArrowRight'], $('.prevnext__next'), 'Next page'),
|
||||
new Shortcut(['s', 'Alt+ArrowUp', 'Ctrl+Alt+ArrowUp'], $$('.navi-title a').slice(1, -1).slice(-1)[0], 'Parent page'),
|
||||
new Shortcut(['c', 'Alt+ArrowDown', 'Ctrl+Alt+ArrowDown'], $('.subhyphae__link'), 'First child page'),
|
||||
new Shortcut(['e', isMac ? 'Meta+Enter' : 'Ctrl+Enter'], $('.btn__link_navititle[href^="/edit/"]'), 'Edit this page'),
|
||||
new Shortcut('v', $('.hypha-info__link[href^="/hypha/"]'), 'Go to page overview'),
|
||||
new Shortcut('a', $('.hypha-info__link[href^="/media/"]'), 'Go to media management'),
|
||||
new Shortcut('h', $('.hypha-info__link[href^="/history/"]'), 'Go to history'),
|
||||
new Shortcut('r', $('.hypha-info__link[href^="/rename/"]'), 'Rename this hypha'),
|
||||
new Shortcut('r', $('.hypha-info__link[href^="/rename/"]'), 'Rename this page'),
|
||||
new Shortcut('b', $('.hypha-info__link[href^="/backlinks/"]'), 'Backlinks'),
|
||||
]))
|
||||
}
|
||||
|
37
user/net.go
37
user/net.go
@ -1,15 +1,10 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@ -123,35 +118,3 @@ func cookie(nameSuffix, val string, t time.Time) *http.Cookie {
|
||||
Path: "/",
|
||||
}
|
||||
}
|
||||
|
||||
// TelegramAuthParamsAreValid is true if the given params are ok.
|
||||
func TelegramAuthParamsAreValid(params map[string][]string) bool {
|
||||
// According to the Telegram documentation,
|
||||
// > You can verify the authentication and the integrity of the data received by comparing the received hash parameter with the hexadecimal representation of the HMAC-SHA-256 signature of the data-check-string with the SHA256 hash of the bot's token used as a secret key.
|
||||
tokenHash := sha256.New()
|
||||
tokenHash.Write([]byte(cfg.TelegramBotToken))
|
||||
secretKey := tokenHash.Sum(nil)
|
||||
|
||||
hash := hmac.New(sha256.New, secretKey)
|
||||
hash.Write([]byte(telegramDataCheckString(params)))
|
||||
hexHash := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
passedHash := params["hash"][0]
|
||||
return passedHash == hexHash
|
||||
}
|
||||
|
||||
// According to the Telegram documentation,
|
||||
// > Data-check-string is a concatenation of all received fields, sorted in alphabetical order, in the format key=<value> with a line feed character ('\n', 0x0A) used as separator – e.g., 'auth_date=<auth_date>\nfirst_name=<first_name>\nid=<id>\nusername=<username>'.
|
||||
//
|
||||
// Note that hash is not used here.
|
||||
func telegramDataCheckString(params map[string][]string) string {
|
||||
var lines []string
|
||||
for key, value := range params {
|
||||
if key == "hash" {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf("%s=%s", key, value[0]))
|
||||
}
|
||||
sort.Strings(lines)
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
10
util/util.go
10
util/util.go
@ -3,10 +3,12 @@ package util
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"github.com/bouncepaw/mycorrhiza/files"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/files"
|
||||
|
||||
"git.sr.ht/~bouncepaw/mycomarkup/v5/util"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
@ -154,3 +156,9 @@ func IsRevHash(revHash string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func GetMotd() string {
|
||||
now := time.Now().UTC().Unix()
|
||||
dayIndex := now / 86400
|
||||
return cfg.Motds[dayIndex%int64(len(cfg.Motds))]
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
<body data-rrh-addr="{{if .Addr}}{{.Addr}}{{else}}{{.Meta.Addr}}{{end}}"{{range $key, $value := .BodyAttributes}} data-rrh-{{$key}}="{{$value}}"{{end}}>
|
||||
<header>
|
||||
<div class="logo">
|
||||
<img src="/static/favicon.ico" alt="A picture of Euler, stretched into a square" />
|
||||
<div class="ominous"><span>It's already far too late.</span></div>
|
||||
<img src="/static/favicon.ico" alt="A picture of mathematician Leonhard Euler, stretched into a square" />
|
||||
<div class="ominous"><span>{{.Motd}}</span></div>
|
||||
</div>
|
||||
<nav class="main-width top-bar">
|
||||
<ul class="top-bar__wrapper">
|
||||
|
@ -100,6 +100,7 @@ type BaseData struct {
|
||||
Title string // TODO: remove
|
||||
Body string // TODO: remove
|
||||
BodyAttributes map[string]string
|
||||
Motd string
|
||||
}
|
||||
|
||||
func (bd *BaseData) withBaseValues(meta Meta, headerLinks []HeaderLink, commonScripts []string) {
|
||||
@ -123,6 +124,7 @@ func Base(meta Meta, title, body string, bodyAttributes map[string]string, headE
|
||||
EditScripts: cfg.EditScripts,
|
||||
Body: body,
|
||||
BodyAttributes: bodyAttributes,
|
||||
Motd: util.GetMotd(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/admin"
|
||||
"github.com/bouncepaw/mycorrhiza/settings"
|
||||
"github.com/bouncepaw/mycorrhiza/auth"
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/categories"
|
||||
@ -16,6 +15,7 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/hypview"
|
||||
"github.com/bouncepaw/mycorrhiza/interwiki"
|
||||
"github.com/bouncepaw/mycorrhiza/misc"
|
||||
"github.com/bouncepaw/mycorrhiza/settings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
@ -31,7 +31,7 @@ func Handler() http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
w.Header().Add("Content-Security-Policy",
|
||||
"default-src 'self' telegram.org *.telegram.org; "+
|
||||
"default-src 'self'; "+
|
||||
"img-src * data:; media-src *; style-src *; font-src * data:")
|
||||
next.ServeHTTP(w, rq)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user