mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-01-06 10:00:26 +00:00
Implement initial Telegram integration
This commit is contained in:
parent
9ad9db9825
commit
df78f75efb
@ -34,6 +34,11 @@ var (
|
||||
CommonScripts []string
|
||||
ViewScripts []string
|
||||
EditScripts []string
|
||||
|
||||
// TelegramEnabled if both TelegramBotToken and TelegramBotName are not empty strings.
|
||||
TelegramEnabled bool
|
||||
TelegramBotToken string
|
||||
TelegramBotName string
|
||||
)
|
||||
|
||||
// WikiDir is a full path to the wiki storage directory, which also must be a
|
||||
@ -49,6 +54,7 @@ type Config struct {
|
||||
Network
|
||||
Authorization
|
||||
CustomScripts `comment:"You can specify additional scripts to load on different kinds of pages, delimited by a comma ',' sign."`
|
||||
Telegram `comment:"You can enable Telegram authorization. Follow these instructions: https://core.telegram.org/widgets/login#setting-up-a-bot"`
|
||||
}
|
||||
|
||||
// Hyphae is a section of Config which has fields related to special hyphae.
|
||||
@ -85,6 +91,12 @@ type Authorization struct {
|
||||
Locked bool `comment:"Set if users have to authorize to see anything on the wiki."`
|
||||
}
|
||||
|
||||
// Telegram is the section of Config that sets Telegram authorization.
|
||||
type Telegram struct {
|
||||
TelegramBotToken string `comment:"Token of your bot.`
|
||||
TelegramBotName string `comment:"Username of your bot, sans @.`
|
||||
}
|
||||
|
||||
// ReadConfigFile reads a config on the given path and stores the
|
||||
// configuration. Call it sometime during the initialization.
|
||||
func ReadConfigFile(path string) error {
|
||||
@ -111,6 +123,10 @@ func ReadConfigFile(path string) error {
|
||||
ViewScripts: []string{},
|
||||
EditScripts: []string{},
|
||||
},
|
||||
Telegram: Telegram{
|
||||
TelegramBotToken: "",
|
||||
TelegramBotName: "",
|
||||
},
|
||||
}
|
||||
|
||||
f, err := ini.Load(path)
|
||||
@ -158,6 +174,9 @@ func ReadConfigFile(path string) error {
|
||||
CommonScripts = cfg.CommonScripts
|
||||
ViewScripts = cfg.ViewScripts
|
||||
EditScripts = cfg.EditScripts
|
||||
TelegramBotToken = cfg.TelegramBotToken
|
||||
TelegramBotName = cfg.TelegramBotName
|
||||
TelegramEnabled = (TelegramBotToken != "") && (TelegramBotName != "")
|
||||
|
||||
// This URL makes much more sense.
|
||||
if URL == "" {
|
||||
|
39
user/net.go
39
user/net.go
@ -5,6 +5,11 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
@ -65,6 +70,8 @@ func Register(username, password, group string, force bool) error {
|
||||
}
|
||||
|
||||
// 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.
|
||||
func LoginDataHTTP(w http.ResponseWriter, rq *http.Request, username, password string) string {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
if !HasUsername(username) {
|
||||
@ -106,3 +113,35 @@ func cookie(name_suffix, 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")
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ var groups = []string{
|
||||
"anon",
|
||||
"editor",
|
||||
"trusted",
|
||||
"telegram",
|
||||
"moderator",
|
||||
"admin",
|
||||
}
|
||||
@ -53,6 +54,7 @@ var groupRight = map[string]int{
|
||||
"anon": 0,
|
||||
"editor": 1,
|
||||
"trusted": 2,
|
||||
"telegram": 2,
|
||||
"moderator": 3,
|
||||
"admin": 4,
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
<a class="btn btn_weak" href="/{%s rq.URL.RawQuery %}">Cancel</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
{%= telegramWidgetHTML() %}
|
||||
{% elseif cfg.UseAuth %}
|
||||
<p>Registrations are currently closed. Administrators can make an account for you by hand; contact them.</p>
|
||||
<p><a href="/{%s rq.URL.RawQuery %}">← Go back</a></p>
|
||||
@ -55,6 +56,7 @@
|
||||
<a class="btn btn_weak" href="/">Cancel</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
{%= telegramWidgetHTML() %}
|
||||
{% else %}
|
||||
<p>Authentication is disabled. You can make edits anonymously.</p>
|
||||
<p><a class="btn btn_weak" href="/">← Go home</a></p>
|
||||
@ -64,6 +66,13 @@
|
||||
</div>
|
||||
{% 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 telegramWidgetHTML() %}
|
||||
{% if cfg.TelegramEnabled %}
|
||||
<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 LoginErrorHTML(err string) %}
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
@ -130,4 +139,4 @@
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{% endfunc %}
|
||||
{% endfunc %}
|
||||
|
@ -64,84 +64,89 @@ func StreamRegisterHTML(qw422016 *qt422016.Writer, rq *http.Request) {
|
||||
qw422016.N().S(`">Cancel</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line views/auth.qtpl:26
|
||||
streamtelegramWidgetHTML(qw422016)
|
||||
//line views/auth.qtpl:26
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:26
|
||||
//line views/auth.qtpl:27
|
||||
} else if cfg.UseAuth {
|
||||
//line views/auth.qtpl:26
|
||||
//line views/auth.qtpl:27
|
||||
qw422016.N().S(`
|
||||
<p>Registrations are currently closed. Administrators can make an account for you by hand; contact them.</p>
|
||||
<p><a href="/`)
|
||||
//line views/auth.qtpl:28
|
||||
//line views/auth.qtpl:29
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line views/auth.qtpl:28
|
||||
//line views/auth.qtpl:29
|
||||
qw422016.N().S(`">← Go back</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:29
|
||||
//line views/auth.qtpl:30
|
||||
} else {
|
||||
//line views/auth.qtpl:29
|
||||
//line views/auth.qtpl:30
|
||||
qw422016.N().S(`
|
||||
<p>Authentication is disabled. You can make edits anonymously.</p>
|
||||
<p><a href="/`)
|
||||
//line views/auth.qtpl:31
|
||||
//line views/auth.qtpl:32
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line views/auth.qtpl:31
|
||||
//line views/auth.qtpl:32
|
||||
qw422016.N().S(`">← Go back</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:32
|
||||
//line views/auth.qtpl:33
|
||||
}
|
||||
//line views/auth.qtpl:32
|
||||
//line views/auth.qtpl:33
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
func WriteRegisterHTML(qq422016 qtio422016.Writer, rq *http.Request) {
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
StreamRegisterHTML(qw422016, rq)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
func RegisterHTML(rq *http.Request) string {
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
WriteRegisterHTML(qb422016, rq)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
return qs422016
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:37
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:38
|
||||
//line views/auth.qtpl:39
|
||||
func StreamLoginHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/auth.qtpl:38
|
||||
//line views/auth.qtpl:39
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:42
|
||||
//line views/auth.qtpl:43
|
||||
if cfg.UseAuth {
|
||||
//line views/auth.qtpl:42
|
||||
//line views/auth.qtpl:43
|
||||
qw422016.N().S(`
|
||||
<form class="modal" method="post" action="/login-data" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">Log in to `)
|
||||
//line views/auth.qtpl:45
|
||||
//line views/auth.qtpl:46
|
||||
qw422016.E().S(cfg.WikiName)
|
||||
//line views/auth.qtpl:45
|
||||
//line views/auth.qtpl:46
|
||||
qw422016.N().S(`</legend>
|
||||
<label for="login-form__username">Username</label>
|
||||
<br>
|
||||
@ -155,185 +160,245 @@ func StreamLoginHTML(qw422016 *qt422016.Writer) {
|
||||
<a class="btn btn_weak" href="/">Cancel</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line views/auth.qtpl:59
|
||||
streamtelegramWidgetHTML(qw422016)
|
||||
//line views/auth.qtpl:59
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:58
|
||||
//line views/auth.qtpl:60
|
||||
} else {
|
||||
//line views/auth.qtpl:58
|
||||
//line views/auth.qtpl:60
|
||||
qw422016.N().S(`
|
||||
<p>Authentication is disabled. You can make edits anonymously.</p>
|
||||
<p><a class="btn btn_weak" href="/">← Go home</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:61
|
||||
//line views/auth.qtpl:63
|
||||
}
|
||||
//line views/auth.qtpl:61
|
||||
//line views/auth.qtpl:63
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
func WriteLoginHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
StreamLoginHTML(qw422016)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
func LoginHTML() string {
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
WriteLoginHTML(qb422016)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
return qs422016
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
}
|
||||
|
||||
//line views/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 views/auth.qtpl:70
|
||||
func streamtelegramWidgetHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/auth.qtpl:70
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:71
|
||||
if cfg.TelegramEnabled {
|
||||
//line views/auth.qtpl:71
|
||||
qw422016.N().S(`
|
||||
<script async src="https://telegram.org/js/telegram-widget.js?15" data-telegram-login="`)
|
||||
//line views/auth.qtpl:72
|
||||
qw422016.E().S(cfg.TelegramBotName)
|
||||
//line views/auth.qtpl:72
|
||||
qw422016.N().S(`" data-size="medium" data-userpic="false" data-auth-url="`)
|
||||
//line views/auth.qtpl:72
|
||||
qw422016.E().S(cfg.URL)
|
||||
//line views/auth.qtpl:72
|
||||
qw422016.N().S(`/telegram-login"></script>
|
||||
`)
|
||||
//line views/auth.qtpl:73
|
||||
}
|
||||
//line views/auth.qtpl:73
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:74
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:74
|
||||
func writetelegramWidgetHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/auth.qtpl:74
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:74
|
||||
streamtelegramWidgetHTML(qw422016)
|
||||
//line views/auth.qtpl:74
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:74
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:74
|
||||
func telegramWidgetHTML() string {
|
||||
//line views/auth.qtpl:74
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:74
|
||||
writetelegramWidgetHTML(qb422016)
|
||||
//line views/auth.qtpl:74
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:74
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:74
|
||||
return qs422016
|
||||
//line views/auth.qtpl:74
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:76
|
||||
func StreamLoginErrorHTML(qw422016 *qt422016.Writer, err string) {
|
||||
//line views/auth.qtpl:67
|
||||
//line views/auth.qtpl:76
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:80
|
||||
switch err {
|
||||
//line views/auth.qtpl:72
|
||||
//line views/auth.qtpl:81
|
||||
case "unknown username":
|
||||
//line views/auth.qtpl:72
|
||||
//line views/auth.qtpl:81
|
||||
qw422016.N().S(`
|
||||
<p class="error">Unknown username.</p>
|
||||
`)
|
||||
//line views/auth.qtpl:74
|
||||
//line views/auth.qtpl:83
|
||||
case "wrong password":
|
||||
//line views/auth.qtpl:74
|
||||
//line views/auth.qtpl:83
|
||||
qw422016.N().S(`
|
||||
<p class="error">Wrong password.</p>
|
||||
`)
|
||||
//line views/auth.qtpl:76
|
||||
//line views/auth.qtpl:85
|
||||
default:
|
||||
//line views/auth.qtpl:76
|
||||
//line views/auth.qtpl:85
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line views/auth.qtpl:77
|
||||
//line views/auth.qtpl:86
|
||||
qw422016.E().S(err)
|
||||
//line views/auth.qtpl:77
|
||||
//line views/auth.qtpl:86
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line views/auth.qtpl:78
|
||||
//line views/auth.qtpl:87
|
||||
}
|
||||
//line views/auth.qtpl:78
|
||||
//line views/auth.qtpl:87
|
||||
qw422016.N().S(`
|
||||
<p><a href="/login">← Try again</a></p>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
func WriteLoginErrorHTML(qq422016 qtio422016.Writer, err string) {
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
StreamLoginErrorHTML(qw422016, err)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
func LoginErrorHTML(err string) string {
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
WriteLoginErrorHTML(qb422016, err)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
return qs422016
|
||||
//line views/auth.qtpl:83
|
||||
//line views/auth.qtpl:92
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:85
|
||||
//line views/auth.qtpl:94
|
||||
func StreamLogoutHTML(qw422016 *qt422016.Writer, can bool) {
|
||||
//line views/auth.qtpl:85
|
||||
//line views/auth.qtpl:94
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:89
|
||||
//line views/auth.qtpl:98
|
||||
if can {
|
||||
//line views/auth.qtpl:89
|
||||
//line views/auth.qtpl:98
|
||||
qw422016.N().S(`
|
||||
<h1>Log out?</h1>
|
||||
<p><a href="/logout-confirm"><strong>Confirm</strong></a></p>
|
||||
<p><a href="/">Cancel</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:93
|
||||
//line views/auth.qtpl:102
|
||||
} else {
|
||||
//line views/auth.qtpl:93
|
||||
//line views/auth.qtpl:102
|
||||
qw422016.N().S(`
|
||||
<p>You cannot log out because you are not logged in.</p>
|
||||
<p><a href="/login">Login</a></p>
|
||||
<p><a href="/login">← Home</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:106
|
||||
}
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:106
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
func WriteLogoutHTML(qq422016 qtio422016.Writer, can bool) {
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
StreamLogoutHTML(qw422016, can)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
func LogoutHTML(can bool) string {
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
WriteLogoutHTML(qb422016, can)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
return qs422016
|
||||
//line views/auth.qtpl:101
|
||||
//line views/auth.qtpl:110
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:103
|
||||
//line views/auth.qtpl:112
|
||||
func StreamLockHTML(qw422016 *qt422016.Writer) {
|
||||
//line views/auth.qtpl:103
|
||||
//line views/auth.qtpl:112
|
||||
qw422016.N().S(`
|
||||
<!doctype html>
|
||||
<html>
|
||||
@ -365,31 +430,31 @@ func StreamLockHTML(qw422016 *qt422016.Writer) {
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
func WriteLockHTML(qq422016 qtio422016.Writer) {
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
StreamLockHTML(qw422016)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
func LockHTML() string {
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
WriteLockHTML(qb422016)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
return qs422016
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:142
|
||||
}
|
||||
|
67
web/auth.go
67
web/auth.go
@ -1,11 +1,13 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
@ -21,6 +23,9 @@ func initAuth() {
|
||||
if cfg.AllowRegistration {
|
||||
http.HandleFunc("/register", handlerRegister)
|
||||
}
|
||||
if cfg.TelegramEnabled {
|
||||
http.HandleFunc("/telegram-login", handlerTelegramLogin)
|
||||
}
|
||||
http.HandleFunc("/login", handlerLogin)
|
||||
http.HandleFunc("/login-data", handlerLoginData)
|
||||
http.HandleFunc("/logout", handlerLogout)
|
||||
@ -118,6 +123,68 @@ func handlerLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Write([]byte(views.BaseHTML("Login", views.LoginHTML(), user.EmptyUser())))
|
||||
}
|
||||
|
||||
func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
// Note there is no lock here.
|
||||
w.Header().Set("Content-Type", "text/plain;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
|
||||
"telegram",
|
||||
false,
|
||||
)
|
||||
)
|
||||
if user.HasUsername(username) && user.UserByName(username).Group == "telegram" {
|
||||
// Problems is something we put blankets on.
|
||||
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)
|
||||
fmt.Fprint(
|
||||
w,
|
||||
views.BaseHTML(
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>Could not authorize using Telegram.</p><p>%s</p><p><a href="/login">Go to the login page<a></p></main>`,
|
||||
err.Error(),
|
||||
),
|
||||
user.FromRequest(rq),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
errmsg := user.LoginDataHTTP(w, rq, username, "")
|
||||
if errmsg != "" {
|
||||
log.Printf("Failed to login ‘%s’ using Telegram: %s", username, err.Error())
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprint(
|
||||
w,
|
||||
views.BaseHTML(
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>Could not authorize using Telegram.</p><p>%s</p><p><a href="/login">Go to the login page<a></p></main>`,
|
||||
err.Error(),
|
||||
),
|
||||
user.FromRequest(rq),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
log.Printf("Authorize ‘%s’ from Telegram", username)
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerLoginData logs the user in.
|
||||
//
|
||||
// TODO: merge into handlerLogin as POST method.
|
||||
|
Loading…
Reference in New Issue
Block a user