Auth-related stuffs
This commit is contained in:
parent
ea1ae0d078
commit
6d2df119d8
143
auth/auth.qtpl
143
auth/auth.qtpl
@ -1,143 +0,0 @@
|
||||
{% import "net/http" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/internal/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
|
||||
{% func Register(rq *http.Request) %}
|
||||
{% code
|
||||
lc := l18n.FromRequest(rq)
|
||||
%}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{% if cfg.AllowRegistration %}
|
||||
<form class="modal" method="post" action="/register?{%s rq.URL.RawQuery %}" id="register-form" enctype="multipart/form-data" autocomplete="off">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">{%s lc.Get("auth.register_header", &l18n.Replacements{"name": cfg.WikiName}) %}</legend>
|
||||
|
||||
<label for="register-form__username">{%s lc.Get("auth.username") %}</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username">
|
||||
<br>
|
||||
<label for="login-form__password">{%s lc.Get("auth.password") %}</label>
|
||||
<br>
|
||||
<input type="password" required name="password">
|
||||
<p>{%s lc.Get("auth.password_tip") %}</p>
|
||||
<p>{%s lc.Get("auth.cookie_tip") %}</p>
|
||||
<button class="btn" type="submit" value="Register">{%s lc.Get("auth.register_button") %}</button>
|
||||
<a class="btn btn_weak" href="/{%s rq.URL.RawQuery %}">{%s lc.Get("ui.cancel") %}</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
{%= telegramWidget(lc) %}
|
||||
{% elseif cfg.UseAuth %}
|
||||
<p>{%s lc.Get("auth.noregister") %}</p>
|
||||
<p><a href="/{%s rq.URL.RawQuery %}">← {%s lc.Get("auth.go_back") %}</a></p>
|
||||
{% else %}
|
||||
<p>{%s lc.Get("auth.noauth") %}</p>
|
||||
<p><a href="/{%s rq.URL.RawQuery %}">← {%s lc.Get("auth.go_back") %}</a></p>
|
||||
{% endif %}
|
||||
</section>
|
||||
</main>
|
||||
{% endfunc %}
|
||||
|
||||
{% func Login(lc *l18n.Localizer) %}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{% if cfg.UseAuth %}
|
||||
<form class="modal" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">{%s lc.Get("auth.login_header", &l18n.Replacements{"name": cfg.WikiName}) %}</legend>
|
||||
<label for="login-form__username">{%s lc.Get("auth.username") %}</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">{%s lc.Get("auth.password") %}</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<p>{%s lc.Get("auth.cookie_tip") %}</p>
|
||||
<button class="btn" type="submit" value="Log in">{%s lc.Get("auth.login_button") %}</button>
|
||||
<a class="btn btn_weak" href="/">{%s lc.Get("ui.cancel") %}</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
{%= telegramWidget(lc) %}
|
||||
{% else %}
|
||||
<p>{%s lc.Get("auth.noauth") %}</p>
|
||||
<p><a class="btn btn_weak" href="/">← {%s lc.Get("auth.go_home") %}</a></p>
|
||||
{% endif %}
|
||||
</section>
|
||||
</main>
|
||||
{% endfunc %}
|
||||
|
||||
Telegram auth widget was requested by Yogurt. As you can see, we don't offer user administrators control over it. Of course we don't.
|
||||
{% func telegramWidget(lc *l18n.Localizer) %}
|
||||
{% if cfg.TelegramEnabled %}
|
||||
<p class="telegram-notice">{%s lc.Get("auth.telegram_tip") %}</p>
|
||||
<script async src="https://telegram.org/js/telegram-widget.js?15" data-telegram-login="{%s cfg.TelegramBotName %}" data-size="medium" data-userpic="false" data-auth-url="{%s cfg.URL %}/telegram-login"></script>
|
||||
{% endif %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func LoginError(err string, lc *l18n.Localizer) %}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{% switch err %}
|
||||
{% case "unknown username" %}
|
||||
<p class="error">{%s lc.Get("auth.error_username") %}</p>
|
||||
{% case "wrong password" %}
|
||||
<p class="error">{%s lc.Get("auth.error_password") %}</p>
|
||||
{% default %}
|
||||
<p class="error">{%s err %}</p>
|
||||
{% endswitch %}
|
||||
<p><a href="/login">← {%s lc.Get("auth.try_again") %}</a></p>
|
||||
</section>
|
||||
</main>
|
||||
{% endfunc %}
|
||||
|
||||
{% func Logout(can bool, lc *l18n.Localizer) %}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{% if can %}
|
||||
<h1>{%s lc.Get("auth.logout_header") %}</h1>
|
||||
<form method="POST" action="/logout">
|
||||
<input class="btn btn_accent" type="submit" value="{%s lc.Get("auth.logout_button") %}"/>
|
||||
<a class="btn btn_weak" href="/">{%s lc.Get("auth.go_home") %}</a>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{%s lc.Get("auth.logout_anon") %}</p>
|
||||
<p><a href="/login">{%s lc.Get("auth.login_title") %}</a></p>
|
||||
<p><a href="/">← {%s lc.Get("auth.go_home") %}</a></p>
|
||||
{% endif %}
|
||||
</section>
|
||||
</main>
|
||||
{% endfunc %}
|
||||
|
||||
{% func Lock(lc *l18n.Localizer) %}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>🔒 {%s lc.Get("auth.lock_title") %}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="locked-notice main-width">
|
||||
<section class="locked-notice__message">
|
||||
<p class="locked-notice__lock">🔒</p>
|
||||
<h1 class="locked-notice__title">{%s lc.Get("auth.lock_title") %}</h1>
|
||||
<form class="locked-notice__login-form" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<label for="login-form__username">{%s lc.Get("auth.username") %}</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">{%s lc.Get("auth.password") %}</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<br>
|
||||
<button class="btn" type="submit" value="Log in">{%s lc.Get("auth.login_button") %}</button>
|
||||
</form>
|
||||
{%= telegramWidget(lc) %}
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{% endfunc %}
|
||||
|
||||
@ -1,597 +0,0 @@
|
||||
// Code generated by qtc from "auth.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line auth/auth.qtpl:1
|
||||
package auth
|
||||
|
||||
//line auth/auth.qtpl:1
|
||||
import "net/http"
|
||||
|
||||
//line auth/auth.qtpl:2
|
||||
import "github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
|
||||
//line auth/auth.qtpl:3
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
|
||||
//line auth/auth.qtpl:5
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line auth/auth.qtpl:5
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line auth/auth.qtpl:5
|
||||
func StreamRegister(qw422016 *qt422016.Writer, rq *http.Request) {
|
||||
//line auth/auth.qtpl:5
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line auth/auth.qtpl:7
|
||||
lc := l18n.FromRequest(rq)
|
||||
|
||||
//line auth/auth.qtpl:8
|
||||
qw422016.N().S(`
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line auth/auth.qtpl:11
|
||||
if cfg.AllowRegistration {
|
||||
//line auth/auth.qtpl:11
|
||||
qw422016.N().S(`
|
||||
<form class="modal" method="post" action="/register?`)
|
||||
//line auth/auth.qtpl:12
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line auth/auth.qtpl:12
|
||||
qw422016.N().S(`" id="register-form" enctype="multipart/form-data" autocomplete="off">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">`)
|
||||
//line auth/auth.qtpl:14
|
||||
qw422016.E().S(lc.Get("auth.register_header", &l18n.Replacements{"name": cfg.WikiName}))
|
||||
//line auth/auth.qtpl:14
|
||||
qw422016.N().S(`</legend>
|
||||
|
||||
<label for="register-form__username">`)
|
||||
//line auth/auth.qtpl:16
|
||||
qw422016.E().S(lc.Get("auth.username"))
|
||||
//line auth/auth.qtpl:16
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username">
|
||||
<br>
|
||||
<label for="login-form__password">`)
|
||||
//line auth/auth.qtpl:20
|
||||
qw422016.E().S(lc.Get("auth.password"))
|
||||
//line auth/auth.qtpl:20
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="password" required name="password">
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:23
|
||||
qw422016.E().S(lc.Get("auth.password_tip"))
|
||||
//line auth/auth.qtpl:23
|
||||
qw422016.N().S(`</p>
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:24
|
||||
qw422016.E().S(lc.Get("auth.cookie_tip"))
|
||||
//line auth/auth.qtpl:24
|
||||
qw422016.N().S(`</p>
|
||||
<button class="btn" type="submit" value="Register">`)
|
||||
//line auth/auth.qtpl:25
|
||||
qw422016.E().S(lc.Get("auth.register_button"))
|
||||
//line auth/auth.qtpl:25
|
||||
qw422016.N().S(`</button>
|
||||
<a class="btn btn_weak" href="/`)
|
||||
//line auth/auth.qtpl:26
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line auth/auth.qtpl:26
|
||||
qw422016.N().S(`">`)
|
||||
//line auth/auth.qtpl:26
|
||||
qw422016.E().S(lc.Get("ui.cancel"))
|
||||
//line auth/auth.qtpl:26
|
||||
qw422016.N().S(`</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line auth/auth.qtpl:29
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line auth/auth.qtpl:29
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line auth/auth.qtpl:30
|
||||
} else if cfg.UseAuth {
|
||||
//line auth/auth.qtpl:30
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:31
|
||||
qw422016.E().S(lc.Get("auth.noregister"))
|
||||
//line auth/auth.qtpl:31
|
||||
qw422016.N().S(`</p>
|
||||
<p><a href="/`)
|
||||
//line auth/auth.qtpl:32
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line auth/auth.qtpl:32
|
||||
qw422016.N().S(`">← `)
|
||||
//line auth/auth.qtpl:32
|
||||
qw422016.E().S(lc.Get("auth.go_back"))
|
||||
//line auth/auth.qtpl:32
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line auth/auth.qtpl:33
|
||||
} else {
|
||||
//line auth/auth.qtpl:33
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:34
|
||||
qw422016.E().S(lc.Get("auth.noauth"))
|
||||
//line auth/auth.qtpl:34
|
||||
qw422016.N().S(`</p>
|
||||
<p><a href="/`)
|
||||
//line auth/auth.qtpl:35
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line auth/auth.qtpl:35
|
||||
qw422016.N().S(`">← `)
|
||||
//line auth/auth.qtpl:35
|
||||
qw422016.E().S(lc.Get("auth.go_back"))
|
||||
//line auth/auth.qtpl:35
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line auth/auth.qtpl:36
|
||||
}
|
||||
//line auth/auth.qtpl:36
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line auth/auth.qtpl:39
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:39
|
||||
func WriteRegister(qq422016 qtio422016.Writer, rq *http.Request) {
|
||||
//line auth/auth.qtpl:39
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line auth/auth.qtpl:39
|
||||
StreamRegister(qw422016, rq)
|
||||
//line auth/auth.qtpl:39
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line auth/auth.qtpl:39
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:39
|
||||
func Register(rq *http.Request) string {
|
||||
//line auth/auth.qtpl:39
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line auth/auth.qtpl:39
|
||||
WriteRegister(qb422016, rq)
|
||||
//line auth/auth.qtpl:39
|
||||
qs422016 := string(qb422016.B)
|
||||
//line auth/auth.qtpl:39
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line auth/auth.qtpl:39
|
||||
return qs422016
|
||||
//line auth/auth.qtpl:39
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:41
|
||||
func StreamLogin(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:41
|
||||
qw422016.N().S(`
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line auth/auth.qtpl:44
|
||||
if cfg.UseAuth {
|
||||
//line auth/auth.qtpl:44
|
||||
qw422016.N().S(`
|
||||
<form class="modal" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">`)
|
||||
//line auth/auth.qtpl:47
|
||||
qw422016.E().S(lc.Get("auth.login_header", &l18n.Replacements{"name": cfg.WikiName}))
|
||||
//line auth/auth.qtpl:47
|
||||
qw422016.N().S(`</legend>
|
||||
<label for="login-form__username">`)
|
||||
//line auth/auth.qtpl:48
|
||||
qw422016.E().S(lc.Get("auth.username"))
|
||||
//line auth/auth.qtpl:48
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">`)
|
||||
//line auth/auth.qtpl:52
|
||||
qw422016.E().S(lc.Get("auth.password"))
|
||||
//line auth/auth.qtpl:52
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:55
|
||||
qw422016.E().S(lc.Get("auth.cookie_tip"))
|
||||
//line auth/auth.qtpl:55
|
||||
qw422016.N().S(`</p>
|
||||
<button class="btn" type="submit" value="Log in">`)
|
||||
//line auth/auth.qtpl:56
|
||||
qw422016.E().S(lc.Get("auth.login_button"))
|
||||
//line auth/auth.qtpl:56
|
||||
qw422016.N().S(`</button>
|
||||
<a class="btn btn_weak" href="/">`)
|
||||
//line auth/auth.qtpl:57
|
||||
qw422016.E().S(lc.Get("ui.cancel"))
|
||||
//line auth/auth.qtpl:57
|
||||
qw422016.N().S(`</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line auth/auth.qtpl:60
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line auth/auth.qtpl:60
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line auth/auth.qtpl:61
|
||||
} else {
|
||||
//line auth/auth.qtpl:61
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:62
|
||||
qw422016.E().S(lc.Get("auth.noauth"))
|
||||
//line auth/auth.qtpl:62
|
||||
qw422016.N().S(`</p>
|
||||
<p><a class="btn btn_weak" href="/">← `)
|
||||
//line auth/auth.qtpl:63
|
||||
qw422016.E().S(lc.Get("auth.go_home"))
|
||||
//line auth/auth.qtpl:63
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line auth/auth.qtpl:64
|
||||
}
|
||||
//line auth/auth.qtpl:64
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line auth/auth.qtpl:67
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:67
|
||||
func WriteLogin(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:67
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line auth/auth.qtpl:67
|
||||
StreamLogin(qw422016, lc)
|
||||
//line auth/auth.qtpl:67
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line auth/auth.qtpl:67
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:67
|
||||
func Login(lc *l18n.Localizer) string {
|
||||
//line auth/auth.qtpl:67
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line auth/auth.qtpl:67
|
||||
WriteLogin(qb422016, lc)
|
||||
//line auth/auth.qtpl:67
|
||||
qs422016 := string(qb422016.B)
|
||||
//line auth/auth.qtpl:67
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line auth/auth.qtpl:67
|
||||
return qs422016
|
||||
//line auth/auth.qtpl:67
|
||||
}
|
||||
|
||||
// Telegram auth widget was requested by Yogurt. As you can see, we don't offer user administrators control over it. Of course we don't.
|
||||
|
||||
//line auth/auth.qtpl:70
|
||||
func streamtelegramWidget(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:70
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line auth/auth.qtpl:71
|
||||
if cfg.TelegramEnabled {
|
||||
//line auth/auth.qtpl:71
|
||||
qw422016.N().S(`
|
||||
<p class="telegram-notice">`)
|
||||
//line auth/auth.qtpl:72
|
||||
qw422016.E().S(lc.Get("auth.telegram_tip"))
|
||||
//line auth/auth.qtpl:72
|
||||
qw422016.N().S(`</p>
|
||||
<script async src="https://telegram.org/js/telegram-widget.js?15" data-telegram-login="`)
|
||||
//line auth/auth.qtpl:73
|
||||
qw422016.E().S(cfg.TelegramBotName)
|
||||
//line auth/auth.qtpl:73
|
||||
qw422016.N().S(`" data-size="medium" data-userpic="false" data-auth-url="`)
|
||||
//line auth/auth.qtpl:73
|
||||
qw422016.E().S(cfg.URL)
|
||||
//line auth/auth.qtpl:73
|
||||
qw422016.N().S(`/telegram-login"></script>
|
||||
`)
|
||||
//line auth/auth.qtpl:74
|
||||
}
|
||||
//line auth/auth.qtpl:74
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line auth/auth.qtpl:75
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:75
|
||||
func writetelegramWidget(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:75
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line auth/auth.qtpl:75
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line auth/auth.qtpl:75
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line auth/auth.qtpl:75
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:75
|
||||
func telegramWidget(lc *l18n.Localizer) string {
|
||||
//line auth/auth.qtpl:75
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line auth/auth.qtpl:75
|
||||
writetelegramWidget(qb422016, lc)
|
||||
//line auth/auth.qtpl:75
|
||||
qs422016 := string(qb422016.B)
|
||||
//line auth/auth.qtpl:75
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line auth/auth.qtpl:75
|
||||
return qs422016
|
||||
//line auth/auth.qtpl:75
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:77
|
||||
func StreamLoginError(qw422016 *qt422016.Writer, err string, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:77
|
||||
qw422016.N().S(`
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line auth/auth.qtpl:80
|
||||
switch err {
|
||||
//line auth/auth.qtpl:81
|
||||
case "unknown username":
|
||||
//line auth/auth.qtpl:81
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line auth/auth.qtpl:82
|
||||
qw422016.E().S(lc.Get("auth.error_username"))
|
||||
//line auth/auth.qtpl:82
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line auth/auth.qtpl:83
|
||||
case "wrong password":
|
||||
//line auth/auth.qtpl:83
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line auth/auth.qtpl:84
|
||||
qw422016.E().S(lc.Get("auth.error_password"))
|
||||
//line auth/auth.qtpl:84
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line auth/auth.qtpl:85
|
||||
default:
|
||||
//line auth/auth.qtpl:85
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line auth/auth.qtpl:86
|
||||
qw422016.E().S(err)
|
||||
//line auth/auth.qtpl:86
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line auth/auth.qtpl:87
|
||||
}
|
||||
//line auth/auth.qtpl:87
|
||||
qw422016.N().S(`
|
||||
<p><a href="/login">← `)
|
||||
//line auth/auth.qtpl:88
|
||||
qw422016.E().S(lc.Get("auth.try_again"))
|
||||
//line auth/auth.qtpl:88
|
||||
qw422016.N().S(`</a></p>
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line auth/auth.qtpl:91
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:91
|
||||
func WriteLoginError(qq422016 qtio422016.Writer, err string, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:91
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line auth/auth.qtpl:91
|
||||
StreamLoginError(qw422016, err, lc)
|
||||
//line auth/auth.qtpl:91
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line auth/auth.qtpl:91
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:91
|
||||
func LoginError(err string, lc *l18n.Localizer) string {
|
||||
//line auth/auth.qtpl:91
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line auth/auth.qtpl:91
|
||||
WriteLoginError(qb422016, err, lc)
|
||||
//line auth/auth.qtpl:91
|
||||
qs422016 := string(qb422016.B)
|
||||
//line auth/auth.qtpl:91
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line auth/auth.qtpl:91
|
||||
return qs422016
|
||||
//line auth/auth.qtpl:91
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:93
|
||||
func StreamLogout(qw422016 *qt422016.Writer, can bool, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:93
|
||||
qw422016.N().S(`
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line auth/auth.qtpl:96
|
||||
if can {
|
||||
//line auth/auth.qtpl:96
|
||||
qw422016.N().S(`
|
||||
<h1>`)
|
||||
//line auth/auth.qtpl:97
|
||||
qw422016.E().S(lc.Get("auth.logout_header"))
|
||||
//line auth/auth.qtpl:97
|
||||
qw422016.N().S(`</h1>
|
||||
<form method="POST" action="/logout">
|
||||
<input class="btn btn_accent" type="submit" value="`)
|
||||
//line auth/auth.qtpl:99
|
||||
qw422016.E().S(lc.Get("auth.logout_button"))
|
||||
//line auth/auth.qtpl:99
|
||||
qw422016.N().S(`"/>
|
||||
<a class="btn btn_weak" href="/">`)
|
||||
//line auth/auth.qtpl:100
|
||||
qw422016.E().S(lc.Get("auth.go_home"))
|
||||
//line auth/auth.qtpl:100
|
||||
qw422016.N().S(`</a>
|
||||
</form>
|
||||
`)
|
||||
//line auth/auth.qtpl:102
|
||||
} else {
|
||||
//line auth/auth.qtpl:102
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line auth/auth.qtpl:103
|
||||
qw422016.E().S(lc.Get("auth.logout_anon"))
|
||||
//line auth/auth.qtpl:103
|
||||
qw422016.N().S(`</p>
|
||||
<p><a href="/login">`)
|
||||
//line auth/auth.qtpl:104
|
||||
qw422016.E().S(lc.Get("auth.login_title"))
|
||||
//line auth/auth.qtpl:104
|
||||
qw422016.N().S(`</a></p>
|
||||
<p><a href="/">← `)
|
||||
//line auth/auth.qtpl:105
|
||||
qw422016.E().S(lc.Get("auth.go_home"))
|
||||
//line auth/auth.qtpl:105
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line auth/auth.qtpl:106
|
||||
}
|
||||
//line auth/auth.qtpl:106
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line auth/auth.qtpl:109
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:109
|
||||
func WriteLogout(qq422016 qtio422016.Writer, can bool, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:109
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line auth/auth.qtpl:109
|
||||
StreamLogout(qw422016, can, lc)
|
||||
//line auth/auth.qtpl:109
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line auth/auth.qtpl:109
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:109
|
||||
func Logout(can bool, lc *l18n.Localizer) string {
|
||||
//line auth/auth.qtpl:109
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line auth/auth.qtpl:109
|
||||
WriteLogout(qb422016, can, lc)
|
||||
//line auth/auth.qtpl:109
|
||||
qs422016 := string(qb422016.B)
|
||||
//line auth/auth.qtpl:109
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line auth/auth.qtpl:109
|
||||
return qs422016
|
||||
//line auth/auth.qtpl:109
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:111
|
||||
func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:111
|
||||
qw422016.N().S(`
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>🔒 `)
|
||||
//line auth/auth.qtpl:117
|
||||
qw422016.E().S(lc.Get("auth.lock_title"))
|
||||
//line auth/auth.qtpl:117
|
||||
qw422016.N().S(`</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="locked-notice main-width">
|
||||
<section class="locked-notice__message">
|
||||
<p class="locked-notice__lock">🔒</p>
|
||||
<h1 class="locked-notice__title">`)
|
||||
//line auth/auth.qtpl:125
|
||||
qw422016.E().S(lc.Get("auth.lock_title"))
|
||||
//line auth/auth.qtpl:125
|
||||
qw422016.N().S(`</h1>
|
||||
<form class="locked-notice__login-form" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<label for="login-form__username">`)
|
||||
//line auth/auth.qtpl:127
|
||||
qw422016.E().S(lc.Get("auth.username"))
|
||||
//line auth/auth.qtpl:127
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">`)
|
||||
//line auth/auth.qtpl:131
|
||||
qw422016.E().S(lc.Get("auth.password"))
|
||||
//line auth/auth.qtpl:131
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<br>
|
||||
<button class="btn" type="submit" value="Log in">`)
|
||||
//line auth/auth.qtpl:135
|
||||
qw422016.E().S(lc.Get("auth.login_button"))
|
||||
//line auth/auth.qtpl:135
|
||||
qw422016.N().S(`</button>
|
||||
</form>
|
||||
`)
|
||||
//line auth/auth.qtpl:137
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line auth/auth.qtpl:137
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
//line auth/auth.qtpl:142
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:142
|
||||
func WriteLock(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line auth/auth.qtpl:142
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line auth/auth.qtpl:142
|
||||
StreamLock(qw422016, lc)
|
||||
//line auth/auth.qtpl:142
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line auth/auth.qtpl:142
|
||||
}
|
||||
|
||||
//line auth/auth.qtpl:142
|
||||
func Lock(lc *l18n.Localizer) string {
|
||||
//line auth/auth.qtpl:142
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line auth/auth.qtpl:142
|
||||
WriteLock(qb422016, lc)
|
||||
//line auth/auth.qtpl:142
|
||||
qs422016 := string(qb422016.B)
|
||||
//line auth/auth.qtpl:142
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line auth/auth.qtpl:142
|
||||
return qs422016
|
||||
//line auth/auth.qtpl:142
|
||||
}
|
||||
@ -79,6 +79,11 @@ func Register(username, password, group, source string, force bool) error {
|
||||
return SaveUserDatabase()
|
||||
}
|
||||
|
||||
var (
|
||||
ErrUnknownUsername = errors.New("unknown username")
|
||||
ErrWrongPassword = errors.New("wrong password")
|
||||
)
|
||||
|
||||
// LoginDataHTTP logs such user in and returns string representation of an error if there is any.
|
||||
//
|
||||
// The HTTP parameters are used for setting header status (bad request, if it is bad) and saving a cookie.
|
||||
@ -87,12 +92,12 @@ func LoginDataHTTP(w http.ResponseWriter, username, password string) error {
|
||||
if !HasUsername(username) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
log.Println("Unknown username", username, "was entered")
|
||||
return errors.New("unknown username")
|
||||
return ErrUnknownUsername
|
||||
}
|
||||
if !CredentialsOK(username, password) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
log.Println("A wrong password was entered for username", username)
|
||||
return errors.New("wrong password")
|
||||
return ErrWrongPassword
|
||||
}
|
||||
token, err := AddSession(username)
|
||||
if err != nil {
|
||||
|
||||
@ -3,33 +3,29 @@
|
||||
"password": "Password",
|
||||
|
||||
"register_title": "Register",
|
||||
"register_header": "Register on {{.name}}",
|
||||
"register_header": "",
|
||||
"register_button": "Register",
|
||||
|
||||
"login_title": "Login",
|
||||
"login_header": "Log in to {{.name}}",
|
||||
"login_button": "Log in",
|
||||
|
||||
"logout_title": "Logout?",
|
||||
"logout_title": "",
|
||||
"logout_header": "Log out?",
|
||||
"logout_button": "Confirm",
|
||||
"logout_anon": "You cannot log out because you are not logged in.",
|
||||
"logout_anon": "",
|
||||
|
||||
"lock_title": "Locked",
|
||||
|
||||
"password_tip": "The server stores your password in an encrypted form; even administrators cannot read it.",
|
||||
"cookie_tip": "By submitting this form you give this wiki a permission to store cookies in your browser. It lets the engine associate your edits with you. You will stay logged in until you log out.",
|
||||
"telegram_tip": "You can log in using Telegram. It only works if you have set your @username in Telegram and this username is free on this wiki.",
|
||||
"password_tip": "",
|
||||
"cookie_tip": "",
|
||||
"telegram_tip": "",
|
||||
|
||||
"noauth": "Authentication is disabled. You can make edits anonymously.",
|
||||
"noauth": "",
|
||||
"noregister": "Registrations are currently closed. Administrators can make an account for you by hand; contact them.",
|
||||
|
||||
"error_username": "Unknown username.",
|
||||
"error_password": "Wrong password.",
|
||||
"error_telegram": "Could not authorize using Telegram.",
|
||||
"error_username": "",
|
||||
"error_password": "",
|
||||
"error_telegram": "",
|
||||
|
||||
"go_back": "Go back",
|
||||
"go_home": "Go home",
|
||||
"go_home": "",
|
||||
"go_login": "Go to the login page",
|
||||
"try_again": "Try again"
|
||||
}
|
||||
|
||||
@ -2,31 +2,31 @@
|
||||
"username": "Логин",
|
||||
"password": "Пароль",
|
||||
|
||||
"register_title": "Регистрация",
|
||||
"register_header": "Регистрация на «{{.name}}»",
|
||||
"register_button": "Зарегистрироваться",
|
||||
"register_title": "",
|
||||
"register_header": "",
|
||||
"register_button": "",
|
||||
|
||||
"login_title": "Вход",
|
||||
"login_header": "Вход в «{{.name}}»",
|
||||
"login_button": "Войти",
|
||||
"login_header": "",
|
||||
"login_button": "",
|
||||
|
||||
"logout_title": "Выйти?",
|
||||
"logout_header": "Выйти?",
|
||||
"logout_title": "",
|
||||
"logout_header": "?",
|
||||
"logout_button": "Подтвердить",
|
||||
"logout_anon": "Вы не можете выйти, потому что ещё не вошли.",
|
||||
"logout_anon": "",
|
||||
|
||||
"lock_title": "Доступ закрыт",
|
||||
"lock_title": "",
|
||||
|
||||
"password_tip": "Сервер хранит ваш пароль в зашифрованном виде, даже администраторы не смогут его прочесть.",
|
||||
"cookie_tip": "Отправляя эту форму, вы разрешаете вики хранить cookie в вашем браузере. Это позволит движку связывать ваши правки с вашей учётной записью. Вы будете авторизованы, пока не выйдете из учётной записи.",
|
||||
"password_tip": "",
|
||||
"cookie_tip": "",
|
||||
"telegram_tip": "Вы можете войти с помощью Телеграм. Это сработает, если у вашего профиля есть @имя, и оно не занято в этой вики.",
|
||||
|
||||
"noauth": "Аутентификация отключена. Вы можете делать правки анонимно.",
|
||||
"noauth": "",
|
||||
"noregister": "Регистрация в текущее время недоступна. Администраторы могут вручную создать вам учётную запись, свяжитесь с ними.",
|
||||
|
||||
"error_username": "Неизвестное имя пользователя.",
|
||||
"error_username": "",
|
||||
"error_password": "Неверный пароль.",
|
||||
"error_telegram": "Не удалось авторизоваться через Телеграм.",
|
||||
"error_telegram": "",
|
||||
|
||||
"go_back": "Назад",
|
||||
"go_home": "Домой",
|
||||
|
||||
1
main.go
1
main.go
@ -2,7 +2,6 @@
|
||||
//
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=history
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=mycoopts
|
||||
//go:generate go run github.com/valyala/quicktemplate/qtc -dir=auth
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
87
web/admin.go
87
web/admin.go
@ -2,16 +2,17 @@ package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
user2 "github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
viewutil2 "github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const adminTranslationRu = `
|
||||
@ -52,53 +53,53 @@ const adminTranslationRu = `
|
||||
{{define "delete user warning"}}Вы уверены, что хотите удалить этого пользователя из базы данных? Это действие нельзя отменить.{{end}}
|
||||
`
|
||||
|
||||
func viewPanel(meta viewutil2.Meta) {
|
||||
viewutil2.ExecutePage(meta, panelChain, &viewutil2.BaseData{})
|
||||
func viewPanel(meta viewutil.Meta) {
|
||||
viewutil.ExecutePage(meta, panelChain, &viewutil.BaseData{})
|
||||
}
|
||||
|
||||
type listData struct {
|
||||
*viewutil2.BaseData
|
||||
*viewutil.BaseData
|
||||
UserHypha string
|
||||
Users []*user2.User
|
||||
Users []*user.User
|
||||
}
|
||||
|
||||
func viewList(meta viewutil2.Meta, users []*user2.User) {
|
||||
viewutil2.ExecutePage(meta, listChain, listData{
|
||||
BaseData: &viewutil2.BaseData{},
|
||||
func viewList(meta viewutil.Meta, users []*user.User) {
|
||||
viewutil.ExecutePage(meta, listChain, listData{
|
||||
BaseData: &viewutil.BaseData{},
|
||||
UserHypha: cfg.UserHypha,
|
||||
Users: users,
|
||||
})
|
||||
}
|
||||
|
||||
type newUserData struct {
|
||||
*viewutil2.BaseData
|
||||
*viewutil.BaseData
|
||||
Form util.FormData
|
||||
}
|
||||
|
||||
func viewNewUser(meta viewutil2.Meta, form util.FormData) {
|
||||
viewutil2.ExecutePage(meta, newUserChain, newUserData{
|
||||
BaseData: &viewutil2.BaseData{},
|
||||
func viewNewUser(meta viewutil.Meta, form util.FormData) {
|
||||
viewutil.ExecutePage(meta, newUserChain, newUserData{
|
||||
BaseData: &viewutil.BaseData{},
|
||||
Form: form,
|
||||
})
|
||||
}
|
||||
|
||||
type editDeleteUserData struct {
|
||||
*viewutil2.BaseData
|
||||
*viewutil.BaseData
|
||||
Form util.FormData
|
||||
U *user2.User
|
||||
U *user.User
|
||||
}
|
||||
|
||||
func viewEditUser(meta viewutil2.Meta, form util.FormData, u *user2.User) {
|
||||
viewutil2.ExecutePage(meta, editUserChain, editDeleteUserData{
|
||||
BaseData: &viewutil2.BaseData{},
|
||||
func viewEditUser(meta viewutil.Meta, form util.FormData, u *user.User) {
|
||||
viewutil.ExecutePage(meta, editUserChain, editDeleteUserData{
|
||||
BaseData: &viewutil.BaseData{},
|
||||
Form: form,
|
||||
U: u,
|
||||
})
|
||||
}
|
||||
|
||||
func viewDeleteUser(meta viewutil2.Meta, form util.FormData, u *user2.User) {
|
||||
viewutil2.ExecutePage(meta, deleteUserChain, editDeleteUserData{
|
||||
BaseData: &viewutil2.BaseData{},
|
||||
func viewDeleteUser(meta viewutil.Meta, form util.FormData, u *user.User) {
|
||||
viewutil.ExecutePage(meta, deleteUserChain, editDeleteUserData{
|
||||
BaseData: &viewutil.BaseData{},
|
||||
Form: form,
|
||||
U: u,
|
||||
})
|
||||
@ -108,12 +109,12 @@ func viewDeleteUser(meta viewutil2.Meta, form util.FormData, u *user2.User) {
|
||||
func handlerAdmin(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
viewPanel(viewutil2.MetaFrom(w, rq))
|
||||
viewPanel(viewutil.MetaFrom(w, rq))
|
||||
}
|
||||
|
||||
// handlerAdminShutdown kills the wiki.
|
||||
func handlerAdminShutdown(w http.ResponseWriter, rq *http.Request) {
|
||||
if user2.CanProceed(rq, "admin/shutdown") {
|
||||
if user.CanProceed(rq, "admin/shutdown") {
|
||||
log.Println("An admin commanded the wiki to shutdown")
|
||||
os.Exit(0)
|
||||
}
|
||||
@ -121,7 +122,7 @@ func handlerAdminShutdown(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
// handlerAdminReindexUsers reinitialises the user system.
|
||||
func handlerAdminReindexUsers(w http.ResponseWriter, rq *http.Request) {
|
||||
user2.ReadUsersFromFilesystem()
|
||||
user.ReadUsersFromFilesystem()
|
||||
redirectTo := rq.Referer()
|
||||
if redirectTo == "" {
|
||||
redirectTo = "/hypha/" + cfg.UserHypha
|
||||
@ -131,8 +132,8 @@ func handlerAdminReindexUsers(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
func handlerAdminUsers(w http.ResponseWriter, rq *http.Request) {
|
||||
// Get a sorted list of users
|
||||
var users []*user2.User
|
||||
for u := range user2.YieldUsers() {
|
||||
var users []*user.User
|
||||
for u := range user.YieldUsers() {
|
||||
users = append(users, u)
|
||||
}
|
||||
|
||||
@ -140,12 +141,12 @@ func handlerAdminUsers(w http.ResponseWriter, rq *http.Request) {
|
||||
less := users[i].RegisteredAt.Before(users[j].RegisteredAt)
|
||||
return less
|
||||
})
|
||||
viewList(viewutil2.MetaFrom(w, rq), users)
|
||||
viewList(viewutil.MetaFrom(w, rq), users)
|
||||
}
|
||||
|
||||
func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
vars := mux.Vars(rq)
|
||||
u := user2.ByName(vars["username"])
|
||||
u := user.ByName(vars["username"])
|
||||
if u == nil {
|
||||
util.HTTP404Page(w, "404 page not found")
|
||||
return
|
||||
@ -157,9 +158,9 @@ func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
oldGroup := u.Group
|
||||
newGroup := f.Get("group")
|
||||
|
||||
if user2.ValidGroup(newGroup) {
|
||||
if user.ValidGroup(newGroup) {
|
||||
u.Group = newGroup
|
||||
if err := user2.SaveUserDatabase(); err != nil {
|
||||
if err := user.SaveUserDatabase(); err != nil {
|
||||
u.Group = oldGroup
|
||||
log.Println(err)
|
||||
f = f.WithError(err)
|
||||
@ -179,12 +180,12 @@ func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
|
||||
viewEditUser(viewutil2.MetaFrom(w, rq), f, u)
|
||||
viewEditUser(viewutil.MetaFrom(w, rq), f, u)
|
||||
}
|
||||
|
||||
func handlerAdminUserChangePassword(w http.ResponseWriter, rq *http.Request) {
|
||||
vars := mux.Vars(rq)
|
||||
u := user2.ByName(vars["username"])
|
||||
u := user.ByName(vars["username"])
|
||||
if u == nil {
|
||||
util.HTTP404Page(w, "404 page not found")
|
||||
return
|
||||
@ -204,7 +205,7 @@ func handlerAdminUserChangePassword(w http.ResponseWriter, rq *http.Request) {
|
||||
if err := u.ChangePassword(password); err != nil {
|
||||
f = f.WithError(err)
|
||||
} else {
|
||||
if err := user2.SaveUserDatabase(); err != nil {
|
||||
if err := user.SaveUserDatabase(); err != nil {
|
||||
u.Password = previousPassword
|
||||
f = f.WithError(err)
|
||||
} else {
|
||||
@ -222,12 +223,12 @@ func handlerAdminUserChangePassword(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
|
||||
viewEditUser(viewutil2.MetaFrom(w, rq), f, u)
|
||||
viewEditUser(viewutil.MetaFrom(w, rq), f, u)
|
||||
}
|
||||
|
||||
func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
vars := mux.Vars(rq)
|
||||
u := user2.ByName(vars["username"])
|
||||
u := user.ByName(vars["username"])
|
||||
if u == nil {
|
||||
util.HTTP404Page(w, "404 page not found")
|
||||
return
|
||||
@ -236,7 +237,7 @@ func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
f := util.NewFormData()
|
||||
|
||||
if rq.Method == http.MethodPost {
|
||||
f = f.WithError(user2.DeleteUser(u.Name))
|
||||
f = f.WithError(user.DeleteUser(u.Name))
|
||||
if !f.HasError() {
|
||||
http.Redirect(w, rq, "/admin/users/", http.StatusSeeOther)
|
||||
} else {
|
||||
@ -248,23 +249,23 @@ func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
viewDeleteUser(viewutil2.MetaFrom(w, rq), f, u)
|
||||
viewDeleteUser(viewutil.MetaFrom(w, rq), f, u)
|
||||
}
|
||||
|
||||
func handlerAdminUserNew(w http.ResponseWriter, rq *http.Request) {
|
||||
if rq.Method == http.MethodGet {
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
viewNewUser(viewutil2.MetaFrom(w, rq), util.NewFormData())
|
||||
viewNewUser(viewutil.MetaFrom(w, rq), util.NewFormData())
|
||||
} else if rq.Method == http.MethodPost {
|
||||
// Create a user
|
||||
f := util.FormDataFromRequest(rq, []string{"name", "password", "group"})
|
||||
|
||||
err := user2.Register(f.Get("name"), f.Get("password"), f.Get("group"), "local", true)
|
||||
err := user.Register(f.Get("name"), f.Get("password"), f.Get("group"), "local", true)
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
viewNewUser(viewutil2.MetaFrom(w, rq), f.WithError(err))
|
||||
viewNewUser(viewutil.MetaFrom(w, rq), f.WithError(err))
|
||||
} else {
|
||||
http.Redirect(w, rq, "/admin/users/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
@ -107,6 +107,7 @@ func (p *Page) RenderTo(meta viewutil.Meta, data map[string]any) error {
|
||||
data["CommonScripts"] = cfg.CommonScripts
|
||||
data["EditScripts"] = cfg.EditScripts
|
||||
data["HeaderLinks"] = viewutil.HeaderLinks
|
||||
data["UseAuth"] = cfg.UseAuth
|
||||
|
||||
tmpl := p.TemplateEnglish
|
||||
if meta.LocaleIsRussian() {
|
||||
|
||||
40
web/pages.go
40
web/pages.go
@ -12,6 +12,8 @@ var fs embed.FS
|
||||
var pageOrphans, pageBacklinks, pageUserList, pageChangePassword *newtmpl.Page
|
||||
var pageHyphaDelete, pageHyphaEdit, pageHyphaEmpty, pageHypha *newtmpl.Page
|
||||
var pageRevision, pageMedia *newtmpl.Page
|
||||
var pageAuthLock, pageAuthLogin, pageAuthLogout, pageAuthRegister, pageAuthTelegram *newtmpl.Page
|
||||
|
||||
var panelChain, listChain, newUserChain, editUserChain, deleteUserChain viewutil.Chain
|
||||
|
||||
func initPages() {
|
||||
@ -136,4 +138,42 @@ func initPages() {
|
||||
"remove tip": "Заметьте, чтобы заменить медиа, вам не нужно его перед этим откреплять.",
|
||||
"remove btn": "Открепить",
|
||||
}, "views/hypha-media.html")
|
||||
|
||||
pageAuthLock = newtmpl.NewPage(fs, map[string]string{
|
||||
"lock title": "Доступ закрыт",
|
||||
"username": "Логин",
|
||||
"password": "Пароль",
|
||||
"log in": "Войти",
|
||||
}, "views/auth-telegram.html", "views/auth-lock.html")
|
||||
|
||||
pageAuthLogin = newtmpl.NewPage(fs, map[string]string{
|
||||
"username": "Логин",
|
||||
"password": "Пароль",
|
||||
"log in": "Войти",
|
||||
"cookie tip": "Отправляя эту форму, вы разрешаете вики хранить cookie в вашем браузере. Это позволит движку связывать ваши правки с вашей учётной записью. Вы будете авторизованы, пока не выйдете из учётной записи.",
|
||||
"log in to x": "Войти в {{.}}",
|
||||
"auth disabled": "Аутентификация отключена. Вы можете делать правки анонимно.",
|
||||
"error username": "Неизвестное имя пользователя.",
|
||||
"error password": "Неправильный пароль.",
|
||||
"error telegram": "Не удалось войти через Телеграм.",
|
||||
"go home": "Домой",
|
||||
}, "views/auth-telegram.html", "views/auth-login.html")
|
||||
|
||||
pageAuthLogout = newtmpl.NewPage(fs, map[string]string{
|
||||
"log out?": "Выйти?",
|
||||
"log out": "Выйти",
|
||||
"cannot log out anon": "Вы не можете выйти, потому что ещё не вошли.",
|
||||
"log in": "Войти",
|
||||
"go home": "Домой",
|
||||
}, "views/auth-logout.html")
|
||||
|
||||
pageAuthRegister = newtmpl.NewPage(fs, map[string]string{
|
||||
"username": "Логин",
|
||||
"password": "Пароль",
|
||||
"cookie tip": "Отправляя эту форму, вы разрешаете вики хранить cookie в вашем браузере. Это позволит движку связывать ваши правки с вашей учётной записью. Вы будете авторизованы, пока не выйдете из учётной записи.",
|
||||
"password tip": "Сервер хранит ваш пароль в зашифрованном виде, даже администраторы не смогут его прочесть.",
|
||||
"register btn": "Зарегистрироваться",
|
||||
"register on x": "Регистрация на {{.}}",
|
||||
}, "views/auth-telegram.html", "views/auth-register.html")
|
||||
|
||||
}
|
||||
|
||||
33
web/views/auth-lock.html
Normal file
33
web/views/auth-lock.html
Normal file
@ -0,0 +1,33 @@
|
||||
{{define "title"}}{{block "lock title" .}}Locked{{end}}{{end}}
|
||||
{{define "page"}}
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>🔒 {{template "lock title" .}}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="locked-notice main-width">
|
||||
<section class="locked-notice__message">
|
||||
<p class="locked-notice__lock">🔒</p>
|
||||
<h1 class="locked-notice__title">{{template "lock title" .}}</h1>
|
||||
<form class="locked-notice__login-form" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<label for="login-form__username">{{block "username" .}}Username{{end}}</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">{{block "password" .}}Password{{end}}</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password" id="login-form__password">
|
||||
<br>
|
||||
<button class="btn" type="submit" value="Log in">{{block "log in" .}}Log in{{end}}</button>
|
||||
</form>
|
||||
{{template "telegram widget"}}
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
39
web/views/auth-login.html
Normal file
39
web/views/auth-login.html
Normal file
@ -0,0 +1,39 @@
|
||||
{{define "log in to x"}}Log in to {{.}}{{end}}
|
||||
{{define "title"}}{{template "log in to x" .WikiName}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{{if .UseAuth}}
|
||||
{{if .ErrUnknownUsername}}
|
||||
<p class="error">{{block "error username" .}}Unknown username.{{end}}</p>
|
||||
{{else if .ErrWrongPassword}}
|
||||
<p class="error">{{block "error password" .}}Wrong password.{{end}}</p>
|
||||
{{else if .ErrTelegram}}
|
||||
<p class="error">{{block "error telegram" .}}Could not authorize using Telegram.{{end}}</p>
|
||||
{{else if .Err}}
|
||||
<p class="error">{{.Err}}</p>
|
||||
{{end}}
|
||||
|
||||
<form class="modal" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">{{template "log in to x" .WikiName}}</legend>
|
||||
<label for="login-form__username">{{block "username" .}}Username{{end}}</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username"{{if .Username}} value="{{.Username}}"{{end}}>
|
||||
<br>
|
||||
<label for="login-form__password">{{block "password" .}}Password{{end}}</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<p>{{block "cookie tip" .}}By submitting this form you give this wiki a permission to store cookies in your browser. It lets the engine associate your edits with you. You will stay logged in until you log out.{{end}}</p>
|
||||
<button class="btn" type="submit" value="Log in">{{block "log in" .}}Log in{{end}}</button>
|
||||
<a class="btn btn_weak" href="/">{{block "cancel" .}}Cancel{{end}}</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{template "telegram widget" .}}
|
||||
{{else}}
|
||||
<p>{{block "auth disabled" .}}Authentication is disabled. You can make edits anonymously.{{end}}</p>
|
||||
<p><a class="btn btn_weak" href="/">← {{block "go home" .}}Go home{{end}}</a></p>
|
||||
{{end}}
|
||||
</section>
|
||||
</main>
|
||||
{{end}}
|
||||
18
web/views/auth-logout.html
Normal file
18
web/views/auth-logout.html
Normal file
@ -0,0 +1,18 @@
|
||||
{{define "title"}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{{if .CanLogout}}
|
||||
<h1>{{block "log out?" .}}Log out?{{end}}</h1>
|
||||
<form method="POST" action="/logout">
|
||||
<input class="btn btn_accent" type="submit" value='{{block "log out" .}}Log out{{end}}'/>
|
||||
<p><a class="btn btn_weak" href="/">← {{block "go home" .}}Go home{{end}}</a></p>
|
||||
</form>
|
||||
{{else}}
|
||||
<p>{{block "cannot log out anon" .}}You cannot log out because you are not logged in.{{end}}</p>
|
||||
<p><a href="/login">{{block "log in" .}}Log in{{end}}</a></p>
|
||||
<p><a href="/">← {{template "go home"}}</a></p>
|
||||
{{end}}
|
||||
</section>
|
||||
</main>
|
||||
{{end}}
|
||||
35
web/views/auth-register.html
Normal file
35
web/views/auth-register.html
Normal file
@ -0,0 +1,35 @@
|
||||
{{define "register on x"}}Register on {{.}}{{end}}
|
||||
{{define "title"}}{{template "register on x" .WikiName}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width">
|
||||
<section>
|
||||
{{if .AllowRegistration}}
|
||||
<form class="modal" method="post" action="/register?{{.RawQuery}}" id="register-form" enctype="multipart/form-data" autocomplete="off">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">{{template "register on x" .WikiName}}</legend>
|
||||
{{if .Err}}<p class="error">{{.Err.Error}}</p>{{end}}
|
||||
|
||||
<label for="register-form__username">{{block "username" .}}Username{{end}}</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="register-form__username" name="username"{{if .Username}} value="{{.Username}}"{{end}}>
|
||||
<br>
|
||||
<label for="register-form__password">{{block "password" .}}Password{{end}}</label>
|
||||
<br>
|
||||
<input type="password" required name="password" id="register-form__password"{{if .Password}} value="{{.Password}}"{{end}}>
|
||||
<p>{{block "password tip" .}}The server stores your password in an encrypted form; even administrators cannot read it.{{end}}</p>
|
||||
<p>{{block "cookie tip" .}}By submitting this form you give this wiki a permission to store cookies in your browser. It lets the engine associate your edits with you. You will stay logged in until you log out.{{end}}</p>
|
||||
<button class="btn" type="submit">{{block "register btn" .}}Register{{end}}</button>
|
||||
<a class="btn btn_weak" href="/{{.RawQuery}}">{{block "cancel" .}}Cancel{{end}}</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{template "telegram widget" .}}
|
||||
{{else if .UseAuth}}
|
||||
<p>{%s lc.Get("auth.noregister") %}</p>
|
||||
<p><a href="/{{.RawQuery}}">← {%s lc.Get("auth.go_back") %}</a></p>
|
||||
{{else}}
|
||||
<p>{%s lc.Get("auth.noauth") %}</p>
|
||||
<p><a href="/{{.RawQuery}}">← {%s lc.Get("auth.go_back") %}</a></p>
|
||||
{{end}}
|
||||
</section>
|
||||
</main>
|
||||
{{end}}
|
||||
11
web/views/auth-telegram.html
Normal file
11
web/views/auth-telegram.html
Normal file
@ -0,0 +1,11 @@
|
||||
{{define "telegram widget"}}
|
||||
{{if .TelegramEnabled}}<!-- TODO: translate -->
|
||||
<p class="telegram-notice">{{block "telegram tip" .}}You can log in using Telegram. It only works if you have set your @username in Telegram and this username is free on this wiki.{{end}}</p>
|
||||
<script async
|
||||
src="https://telegram.org/js/telegram-widget.js?15"
|
||||
data-telegram-login="{{.TelegramBotName}}"
|
||||
data-size="medium"
|
||||
data-userpic="false"
|
||||
data-auth-url="{{.URL}}/telegram-login"></script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
182
web/web.go
182
web/web.go
@ -5,17 +5,17 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/cfg"
|
||||
user2 "github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
"github.com/bouncepaw/mycorrhiza/internal/user"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
viewutil2 "github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"github.com/bouncepaw/mycorrhiza/web/viewutil"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/auth"
|
||||
"github.com/bouncepaw/mycorrhiza/categories"
|
||||
"github.com/bouncepaw/mycorrhiza/help"
|
||||
"github.com/bouncepaw/mycorrhiza/history/histweb"
|
||||
@ -63,7 +63,7 @@ func Handler() http.Handler {
|
||||
r := router.PathPrefix("").Subrouter()
|
||||
r.Use(func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, rq *http.Request) {
|
||||
user := user2.FromRequest(rq)
|
||||
user := user.FromRequest(rq)
|
||||
if !user.ShowLockMaybe(w, rq) {
|
||||
next.ServeHTTP(w, rq)
|
||||
}
|
||||
@ -117,7 +117,7 @@ func Handler() http.Handler {
|
||||
func groupMiddleware(group string) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, rq *http.Request) {
|
||||
if cfg.UseAuth && user2.CanProceed(rq, group) {
|
||||
if cfg.UseAuth && user.CanProceed(rq, group) {
|
||||
next.ServeHTTP(w, rq)
|
||||
return
|
||||
}
|
||||
@ -133,8 +133,8 @@ func groupMiddleware(group string) func(http.Handler) http.Handler {
|
||||
|
||||
// Auth
|
||||
func handlerUserList(w http.ResponseWriter, rq *http.Request) {
|
||||
admins, moderators, editors, readers := user2.UsersInGroups()
|
||||
_ = pageUserList.RenderTo(viewutil2.MetaFrom(w, rq),
|
||||
admins, moderators, editors, readers := user.UsersInGroups()
|
||||
_ = pageUserList.RenderTo(viewutil.MetaFrom(w, rq),
|
||||
map[string]any{
|
||||
"Admins": admins,
|
||||
"Moderators": moderators,
|
||||
@ -144,53 +144,47 @@ func handlerUserList(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
|
||||
func handlerLock(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(w, auth.Lock(l18n.FromRequest(rq)))
|
||||
_ = pageAuthLock.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{})
|
||||
}
|
||||
|
||||
// handlerRegister displays the register form (GET) or registers the user (POST).
|
||||
func handlerRegister(w http.ResponseWriter, rq *http.Request) {
|
||||
lc := l18n.FromRequest(rq)
|
||||
util.PrepareRq(rq)
|
||||
if rq.Method == http.MethodGet {
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil2.Base(
|
||||
viewutil2.MetaFrom(w, rq),
|
||||
lc.Get("auth.register_title"),
|
||||
auth.Register(rq),
|
||||
map[string]string{},
|
||||
),
|
||||
)
|
||||
slog.Info("Showing registration form")
|
||||
_ = pageAuthRegister.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
|
||||
"UseAuth": cfg.UseAuth,
|
||||
"AllowRegistration": cfg.AllowRegistration,
|
||||
"RawQuery": rq.URL.RawQuery,
|
||||
"WikiName": cfg.WikiName,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
username = rq.PostFormValue("username")
|
||||
password = rq.PostFormValue("password")
|
||||
err = user2.Register(username, password, "editor", "local", false)
|
||||
err = user.Register(username, password, "editor", "local", false)
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("Failed to register ‘%s’: %s", username, err.Error())
|
||||
slog.Info("Failed to register", "username", username, "err", err.Error())
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil2.Base(
|
||||
viewutil2.MetaFrom(w, rq),
|
||||
lc.Get("auth.register_title"),
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s</p><p><a href="/register">%s<a></p></main>`,
|
||||
err.Error(),
|
||||
lc.Get("auth.try_again"),
|
||||
),
|
||||
map[string]string{},
|
||||
),
|
||||
)
|
||||
_ = pageAuthRegister.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
|
||||
"UseAuth": cfg.UseAuth,
|
||||
"AllowRegistration": cfg.AllowRegistration,
|
||||
"RawQuery": rq.URL.RawQuery,
|
||||
"WikiName": cfg.WikiName,
|
||||
|
||||
"Err": err,
|
||||
"Username": username,
|
||||
"Password": password,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Successfully registered ‘%s’", username)
|
||||
if err := user2.LoginDataHTTP(w, username, password); err != nil {
|
||||
slog.Info("Registered user", "username", username)
|
||||
if err := user.LoginDataHTTP(w, username, password); err != nil {
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/"+rq.URL.RawQuery, http.StatusSeeOther)
|
||||
@ -198,71 +192,79 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
// handlerLogout shows the logout form (GET) or logs the user out (POST).
|
||||
func handlerLogout(w http.ResponseWriter, rq *http.Request) {
|
||||
if rq.Method == http.MethodGet {
|
||||
var (
|
||||
u = user2.FromRequest(rq)
|
||||
can = u != nil
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
if can {
|
||||
log.Println("User", u.Name, "tries to log out")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
log.Println("Unknown user tries to log out")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil2.Base(viewutil2.MetaFrom(w, rq), lc.Get("auth.logout_title"), auth.Logout(can, lc), map[string]string{}),
|
||||
)
|
||||
} else if rq.Method == http.MethodPost {
|
||||
user2.LogoutFromRequest(w, rq)
|
||||
if rq.Method == http.MethodPost {
|
||||
slog.Info("Somebody logged out")
|
||||
user.LogoutFromRequest(w, rq)
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
u = user.FromRequest(rq)
|
||||
can = u != nil
|
||||
)
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
if can {
|
||||
slog.Info("Logging out", "username", u.Name)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
slog.Info("Unknown user logging out")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
_ = pageAuthLogout.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
|
||||
"CanLogout": can,
|
||||
})
|
||||
}
|
||||
|
||||
// handlerLogin shows the login form (GET) or logs the user in (POST).
|
||||
func handlerLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
lc := l18n.FromRequest(rq)
|
||||
if rq.Method == http.MethodGet {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil2.Base(
|
||||
viewutil2.MetaFrom(w, rq),
|
||||
lc.Get("auth.login_title"),
|
||||
auth.Login(lc),
|
||||
map[string]string{},
|
||||
),
|
||||
)
|
||||
} else if rq.Method == http.MethodPost {
|
||||
var (
|
||||
username = util.CanonicalName(rq.PostFormValue("username"))
|
||||
password = rq.PostFormValue("password")
|
||||
err = user2.LoginDataHTTP(w, username, password)
|
||||
)
|
||||
if err != nil {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = io.WriteString(w, viewutil2.Base(viewutil2.MetaFrom(w, rq), err.Error(), auth.LoginError(err.Error(), lc), map[string]string{}))
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
_ = pageAuthLogin.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
|
||||
"UseAuth": cfg.UseAuth,
|
||||
"ErrUnknownUsername": false,
|
||||
"ErrWrongPassword": false,
|
||||
"ErrTelegram": false,
|
||||
"Err": nil,
|
||||
"WikiName": cfg.WikiName,
|
||||
})
|
||||
slog.Info("Somebody logging in")
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
username = util.CanonicalName(rq.PostFormValue("username"))
|
||||
password = rq.PostFormValue("password")
|
||||
err = user.LoginDataHTTP(w, username, password)
|
||||
)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_ = pageAuthLogin.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
|
||||
"UseAuth": cfg.UseAuth,
|
||||
"ErrUnknownUsername": errors.Is(err, user.ErrUnknownUsername),
|
||||
"ErrWrongPassword": errors.Is(err, user.ErrWrongPassword),
|
||||
"ErrTelegram": false, // TODO: ?
|
||||
"Err": err.Error(),
|
||||
"WikiName": cfg.WikiName,
|
||||
"Username": username,
|
||||
})
|
||||
slog.Info("Failed to log in", "username", username, "err", err.Error())
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
slog.Info("Logged in", "username", username)
|
||||
}
|
||||
|
||||
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()
|
||||
_ = rq.ParseForm()
|
||||
var (
|
||||
values = rq.URL.Query()
|
||||
username = strings.ToLower(values.Get("username"))
|
||||
seemsValid = user2.TelegramAuthParamsAreValid(values)
|
||||
err = user2.Register(
|
||||
seemsValid = user.TelegramAuthParamsAreValid(values)
|
||||
err = user.Register(
|
||||
username,
|
||||
"", // Password matters not
|
||||
"editor",
|
||||
@ -272,7 +274,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
)
|
||||
// If registering a user via Telegram failed, because a Telegram user with this name
|
||||
// has already registered, then everything is actually ok!
|
||||
if user2.HasUsername(username) && user2.ByName(username).Source == "telegram" {
|
||||
if user.HasUsername(username) && user.ByName(username).Source == "telegram" {
|
||||
err = nil
|
||||
}
|
||||
|
||||
@ -281,12 +283,12 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to register ‘%s’ using Telegram: %s", username, err.Error())
|
||||
slog.Info("Failed to register", "username", username, "err", err.Error(), "method", "telegram")
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
viewutil2.Base(
|
||||
viewutil2.MetaFrom(w, rq),
|
||||
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>`,
|
||||
@ -300,14 +302,14 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
errmsg := user2.LoginDataHTTP(w, username, "")
|
||||
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,
|
||||
viewutil2.Base(
|
||||
viewutil2.MetaFrom(w, rq),
|
||||
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>`,
|
||||
@ -320,6 +322,6 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
)
|
||||
return
|
||||
}
|
||||
log.Printf("Authorize ‘%s’ from Telegram", username)
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
slog.Info("Logged in", "username", username, "method", "telegram")
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user