save bytes

This commit is contained in:
Azareal 2020-04-05 13:18:36 +10:00
parent 22af6f19cd
commit 709b0d5541
13 changed files with 91 additions and 91 deletions

View File

@ -17,7 +17,7 @@ import (
"strings" "strings"
"github.com/Azareal/Gosora/common/gauth" "github.com/Azareal/Gosora/common/gauth"
"github.com/Azareal/Gosora/query_gen" qgen "github.com/Azareal/Gosora/query_gen"
//"golang.org/x/crypto/argon2" //"golang.org/x/crypto/argon2"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -66,16 +66,16 @@ var HashPrefixes = map[string]string{
// AuthInt is the main authentication interface. // AuthInt is the main authentication interface.
type AuthInt interface { type AuthInt interface {
Authenticate(username string, password string) (uid int, err error, requiresExtraAuth bool) Authenticate(name, password string) (uid int, err error, requiresExtraAuth bool)
ValidateMFAToken(mfaToken string, uid int) error ValidateMFAToken(mfaToken string, uid int) error
Logout(w http.ResponseWriter, uid int) Logout(w http.ResponseWriter, uid int)
ForceLogout(uid int) error ForceLogout(uid int) error
SetCookies(w http.ResponseWriter, uid int, session string) SetCookies(w http.ResponseWriter, uid int, session string)
SetProvisionalCookies(w http.ResponseWriter, uid int, session string, signedSession string) // To avoid logging someone in until they've passed the MFA check SetProvisionalCookies(w http.ResponseWriter, uid int, session, signedSession string) // To avoid logging someone in until they've passed the MFA check
GetCookies(r *http.Request) (uid int, session string, err error) GetCookies(r *http.Request) (uid int, session string, err error)
SessionCheck(w http.ResponseWriter, r *http.Request) (user *User, halt bool) SessionCheck(w http.ResponseWriter, r *http.Request) (u *User, halt bool)
CreateSession(uid int) (session string, err error) CreateSession(uid int) (session string, err error)
CreateProvisionalSession(uid int) (provSession string, signedSession string, err error) // To avoid logging someone in until they've passed the MFA check CreateProvisionalSession(uid int) (provSession, signedSession string, err error) // To avoid logging someone in until they've passed the MFA check
} }
// DefaultAuth is the default authenticator used by Gosora, may be swapped with an alternate authenticator in some situations. E.g. To support LDAP. // DefaultAuth is the default authenticator used by Gosora, may be swapped with an alternate authenticator in some situations. E.g. To support LDAP.
@ -98,9 +98,9 @@ func NewDefaultAuth() (*DefaultAuth, error) {
// Authenticate checks if a specific username and password is valid and returns the UID for the corresponding user, if so. Otherwise, a user safe error. // Authenticate checks if a specific username and password is valid and returns the UID for the corresponding user, if so. Otherwise, a user safe error.
// IF MFA is enabled, then pass it back a flag telling the caller that authentication isn't complete yet // IF MFA is enabled, then pass it back a flag telling the caller that authentication isn't complete yet
// TODO: Find a better way of handling errors we don't want to reach the user // TODO: Find a better way of handling errors we don't want to reach the user
func (auth *DefaultAuth) Authenticate(username string, password string) (uid int, err error, requiresExtraAuth bool) { func (auth *DefaultAuth) Authenticate(name string, password string) (uid int, err error, requiresExtraAuth bool) {
var realPassword, salt string var realPassword, salt string
err = auth.login.QueryRow(username).Scan(&uid, &realPassword, &salt) err = auth.login.QueryRow(name).Scan(&uid, &realPassword, &salt)
if err == ErrNoRows { if err == ErrNoRows {
return 0, ErrNoUserByName, false return 0, ErrNoUserByName, false
} else if err != nil { } else if err != nil {
@ -295,7 +295,7 @@ func (auth *DefaultAuth) CreateProvisionalSession(uid int) (provSession string,
return provSession, hex.EncodeToString(h.Sum(nil)), nil return provSession, hex.EncodeToString(h.Sum(nil)), nil
} }
func CheckPassword(realPassword string, password string, salt string) (err error) { func CheckPassword(realPassword, password, salt string) (err error) {
blasted := strings.Split(realPassword, "$") blasted := strings.Split(realPassword, "$")
prefix := blasted[0] prefix := blasted[0]
if len(blasted) > 1 { if len(blasted) > 1 {
@ -309,7 +309,7 @@ func CheckPassword(realPassword string, password string, salt string) (err error
return checker(realPassword, password, salt) return checker(realPassword, password, salt)
} }
func GeneratePassword(password string) (hash string, salt string, err error) { func GeneratePassword(password string) (hash, salt string, err error) {
gen, ok := GeneratePasswordFuncs[DefaultHashAlgo] gen, ok := GeneratePasswordFuncs[DefaultHashAlgo]
if !ok { if !ok {
return "", "", ErrHashNotExist return "", "", ErrHashNotExist
@ -317,12 +317,12 @@ func GeneratePassword(password string) (hash string, salt string, err error) {
return gen(password) return gen(password)
} }
func BcryptCheckPassword(realPassword string, password string, salt string) (err error) { func BcryptCheckPassword(realPassword, password, salt string) (err error) {
return bcrypt.CompareHashAndPassword([]byte(realPassword), []byte(password+salt)) return bcrypt.CompareHashAndPassword([]byte(realPassword), []byte(password+salt))
} }
// Note: The salt is in the hash, therefore the salt parameter is blank // Note: The salt is in the hash, therefore the salt parameter is blank
func BcryptGeneratePassword(password string) (hash string, salt string, err error) { func BcryptGeneratePassword(password string) (hash, salt string, err error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil { if err != nil {
return "", "", err return "", "", err
@ -337,7 +337,7 @@ func BcryptGeneratePassword(password string) (hash string, salt string, err erro
argon2KeyLen uint32 = 32 argon2KeyLen uint32 = 32
) )
func Argon2CheckPassword(realPassword string, password string, salt string) (err error) { func Argon2CheckPassword(realPassword, password, salt string) (err error) {
split := strings.Split(realPassword, "$") split := strings.Split(realPassword, "$")
// TODO: Better validation // TODO: Better validation
if len(split) < 5 { if len(split) < 5 {
@ -355,7 +355,7 @@ func Argon2CheckPassword(realPassword string, password string, salt string) (err
return nil return nil
} }
func Argon2GeneratePassword(password string) (hash string, salt string, err error) { func Argon2GeneratePassword(password string) (hash, salt string, err error) {
sbytes := make([]byte, SaltLength) sbytes := make([]byte, SaltLength)
_, err = rand.Read(sbytes) _, err = rand.Read(sbytes)
if err != nil { if err != nil {
@ -380,7 +380,7 @@ func FriendlyGAuthSecret(secret string) (out string) {
func GenerateGAuthSecret() (string, error) { func GenerateGAuthSecret() (string, error) {
return GenerateStd32SafeString(14) return GenerateStd32SafeString(14)
} }
func VerifyGAuthToken(secret string, token string) (bool, error) { func VerifyGAuthToken(secret, token string) (bool, error) {
trueToken, err := gauth.GetTOTPToken(secret) trueToken, err := gauth.GetTOTPToken(secret)
return subtle.ConstantTimeCompare([]byte(trueToken), []byte(token)) == 1, err return subtle.ConstantTimeCompare([]byte(trueToken), []byte(token)) == 1, err
} }

View File

@ -4,19 +4,19 @@
// TODO: Move this into a JS file to reduce the number of possible problems // TODO: Move this into a JS file to reduce the number of possible problems
var menuItems = {}; var menuItems = {};
let items = document.getElementsByClassName("panel_menu_item"); let items = document.getElementsByClassName("panel_menu_item");
for(let i = 0; item = items[i]; i++) menuItems[i] = item.getAttribute("data-miid"); for(let i=0; item=items[i]; i++) menuItems[i] = item.getAttribute("data-miid");
Sortable.create(document.getElementById("panel_menu_item_holder"), { Sortable.create(document.getElementById("panel_menu_item_holder"), {
sort: true, sort: true,
onEnd: (evt) => { onEnd: evt => {
console.log("pre menuItems", menuItems) console.log("pre menuItems",menuItems)
console.log("evt", evt) console.log("evt",evt)
let oldMiid = menuItems[evt.newIndex]; let oldMiid = menuItems[evt.newIndex];
menuItems[evt.oldIndex] = oldMiid; menuItems[evt.oldIndex] = oldMiid;
let newMiid = evt.item.getAttribute("data-miid"); let newMiid = evt.item.getAttribute("data-miid");
console.log("newMiid", newMiid); console.log("newMiid",newMiid);
menuItems[evt.newIndex] = newMiid; menuItems[evt.newIndex] = newMiid;
console.log("post menuItems", menuItems); console.log("post menuItems",menuItems);
} }
}); });
@ -32,22 +32,22 @@ document.getElementById("panel_menu_items_order_button").addEventListener("click
// TODO: Signal the error with a notice // TODO: Signal the error with a notice
if(req.status===200) { if(req.status===200) {
let resp = JSON.parse(req.responseText); let resp = JSON.parse(req.responseText);
console.log("resp", resp); console.log("resp",resp);
// TODO: Should we move other notices into TmplPhrases like this one? // TODO: Should we move other notices into TmplPhrases like this one?
pushNotice(phraseBox["panel"]["panel.themes_menus_items_order_updated"]); pushNotice(phraseBox["panel"]["panel.themes_menus_items_order_updated"]);
if(resp.success==1) return; if(resp.success==1) return;
} }
} catch(ex) { } catch(e) {
console.error("ex", ex) console.error("e",e)
} }
console.trace(); console.trace();
} }
// ? - Is encodeURIComponent the right function for this? // ? - Is encodeURIComponent the right function for this?
let spl = document.location.pathname.split("/"); let spl = document.location.pathname.split("/");
req.open("POST","/panel/themes/menus/item/order/edit/submit/"+parseInt(spl[spl.length-1],10)+"?s=" + encodeURIComponent(me.User.S)); req.open("POST","/panel/themes/menus/item/order/edit/submit/"+parseInt(spl[spl.length-1],10)+"?s="+encodeURIComponent(me.User.S));
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
let items = ""; let items = "";
for(let i = 0; item = menuItems[i];i++) items += item+","; for(let i=0; item=menuItems[i];i++) items += item+",";
if(items.length > 0) items = items.slice(0,-1); if(items.length > 0) items = items.slice(0,-1);
req.send("js=1&amp;items={"+items+"}"); req.send("js=1&amp;items={"+items+"}");
}); });

View File

@ -2,11 +2,11 @@
<div class="formitem formlabel"><a>{{lang "panel_themes_widgets_type"}}</a></div> <div class="formitem formlabel"><a>{{lang "panel_themes_widgets_type"}}</a></div>
<div class="formitem"> <div class="formitem">
<select class="wtype_sel" name="wtype"> <select class="wtype_sel" name="wtype">
<option value="about"{{if eq .Type "about"}} selected{{end}}>{{lang "panel_themes_widgets_type_about"}}</option> <option value="about"{{if eq .Type "about"}}selected{{end}}>{{lang "panel_themes_widgets_type_about"}}</option>
<option value="simple"{{if eq .Type "simple"}} selected{{end}}>{{lang "panel_themes_widgets_type_simple"}}</option> <option value="simple"{{if eq .Type "simple"}}selected{{end}}>{{lang "panel_themes_widgets_type_simple"}}</option>
<option value="wol"{{if eq .Type "wol"}} selected{{end}}>{{lang "panel_themes_widgets_type_wol"}}</option> <option value="wol"{{if eq .Type "wol"}}selected{{end}}>{{lang "panel_themes_widgets_type_wol"}}</option>
<option value="wol_context"{{if eq .Type "wol_context"}} selected{{end}}>{{lang "panel_themes_widgets_type_wol_context"}}</option> <option value="wol_context"{{if eq .Type "wol_context"}}selected{{end}}>{{lang "panel_themes_widgets_type_wol_context"}}</option>
<option value="search_and_filter"{{if eq .Type "search_and_filter"}} selected{{end}}>{{lang "panel_themes_widgets_type_search_and_filter"}}</option> <option value="search_and_filter"{{if eq .Type "search_and_filter"}}selected{{end}}>{{lang "panel_themes_widgets_type_search_and_filter"}}</option>
</select> </select>
</div> </div>
</div> </div>
@ -47,9 +47,9 @@
</div> </div>
<div class="formrow form_button_row"> <div class="formrow form_button_row">
<div class="formitem"> <div class="formitem">
<button name="panel-button" class="formbutton widget_save">{{lang "panel_themes_widgets_save"}}</button> <button name="panel-button"class="formbutton widget_save">{{lang "panel_themes_widgets_save"}}</button>
<a href="/panel/themes/widgets/delete/submit/{{.ID}}"> <a href="/panel/themes/widgets/delete/submit/{{.ID}}">
<button name="panel-button" class="formbutton widget_delete">{{lang "panel_themes_widgets_delete"}}</button> <button name="panel-button"class="formbutton widget_delete">{{lang "panel_themes_widgets_delete"}}</button>
</a> </a>
</div> </div>
</div> </div>

View File

@ -1,14 +1,14 @@
{{template "header.html" . }} {{template "header.html" . }}
<div id="profile_container" class="colstack"> <div id="profile_container"class="colstack">
<div id="profile_left_lane" class="colstack_left"> <div id="profile_left_lane"class="colstack_left">
<div id="profile_left_pane" class="rowmenu"> <div id="profile_left_pane"class="rowmenu">
<div class="topBlock"> <div class="topBlock">
<div class="rowitem avatarRow"> <div class="rowitem avatarRow">
<a href="{{.ProfileOwner.Avatar}}"><img src="{{.ProfileOwner.Avatar}}"class="avatar"alt="Avatar"title="{{.ProfileOwner.Name}}'s Avatar"aria-hidden="true"></a> <a href="{{.ProfileOwner.Avatar}}"><img src="{{.ProfileOwner.Avatar}}"class="avatar"alt="Avatar"title="{{.ProfileOwner.Name}}'s Avatar"aria-hidden="true"></a>
</div> </div>
<div class="rowitem nameRow"> <div class="rowitem nameRow">
<span class="profileName" title="{{.ProfileOwner.Name}}">{{.ProfileOwner.Name}}</span>{{if .ProfileOwner.Tag}}<span class="username" title="{{.ProfileOwner.Tag}}">{{.ProfileOwner.Tag}}</span>{{end}} <span class="profileName"title="{{.ProfileOwner.Name}}">{{.ProfileOwner.Name}}</span>{{if .ProfileOwner.Tag}}<span class="username"title="{{.ProfileOwner.Tag}}">{{.ProfileOwner.Tag}}</span>{{end}}
</div> </div>
</div> </div>
<div class="levelBlock"> <div class="levelBlock">
@ -17,7 +17,7 @@
<div class="levelBit"> <div class="levelBit">
<a>{{level .ProfileOwner.Level}}</a> <a>{{level .ProfileOwner.Level}}</a>
</div> </div>
<div class="progressWrap"{{if ne .CurrentScore 0}} style="width:40%"{{end}}> <div class="progressWrap"{{if ne .CurrentScore 0}}style="width:40%"{{end}}>
<div>{{.CurrentScore}} / {{.NextScore}}</div> <div>{{.CurrentScore}} / {{.NextScore}}</div>
</div> </div>
</div> </div>
@ -36,25 +36,25 @@
{{if (.CurrentUser.IsSuperMod) and not (.ProfileOwner.IsSuperMod)}}<div class="rowitem passive"> {{if (.CurrentUser.IsSuperMod) and not (.ProfileOwner.IsSuperMod)}}<div class="rowitem passive">
{{if .ProfileOwner.IsBanned}}<a href="/users/unban/{{.ProfileOwner.ID}}?s={{.CurrentUser.Session}}" class="profile_menu_item">{{lang "profile.unban"}}</a> {{if .ProfileOwner.IsBanned}}<a href="/users/unban/{{.ProfileOwner.ID}}?s={{.CurrentUser.Session}}" class="profile_menu_item">{{lang "profile.unban"}}</a>
{{else}}<a href="#ban_user" class="profile_menu_item">{{lang "profile.ban"}}</a>{{end}} {{else}}<a href="#ban_user"class="profile_menu_item">{{lang "profile.ban"}}</a>{{end}}
</div> </div>
<div class="rowitem passive"> <div class="rowitem passive">
<a href="#delete_posts" class="profile_menu_item">{{lang "profile.delete_posts"}}</a> <a href="#delete_posts"class="profile_menu_item">{{lang "profile.delete_posts"}}</a>
</div> </div>
{{end}} {{end}}
<div class="rowitem passive"> <div class="rowitem passive">
{{if .Blocked}}<a href="/user/block/remove/{{.ProfileOwner.ID}}" class="profile_menu_item">{{lang "profile.unblock"}}</a>{{else}}<a href="/user/block/create/{{.ProfileOwner.ID}}" class="profile_menu_item">{{lang "profile.block"}}</a>{{end}} {{if .Blocked}}<a href="/user/block/remove/{{.ProfileOwner.ID}}"class="profile_menu_item">{{lang "profile.unblock"}}</a>{{else}}<a href="/user/block/create/{{.ProfileOwner.ID}}"class="profile_menu_item">{{lang "profile.block"}}</a>{{end}}
</div> </div>
<div class="rowitem passive"> <div class="rowitem passive">
<a href="/report/submit/{{.ProfileOwner.ID}}?s={{.CurrentUser.Session}}&type=user" class="profile_menu_item report_item" aria-label="{{lang "profile.report_user_aria"}}" title="{{lang "profile.report_user_tooltip"}}"></a> <a href="/report/submit/{{.ProfileOwner.ID}}?s={{.CurrentUser.Session}}&type=user"class="profile_menu_item report_item"aria-label="{{lang "profile.report_user_aria"}}"title="{{lang "profile.report_user_tooltip"}}"></a>
</div> </div>
{{end}} {{end}}
</div> </div>
</div> </div>
</div> </div>
<div id="profile_right_lane" class="colstack_right"> <div id="profile_right_lane"class="colstack_right">
{{if .CurrentUser.Loggedin}} {{if .CurrentUser.Loggedin}}
{{if .CurrentUser.Perms.BanUsers}} {{if .CurrentUser.Perms.BanUsers}}
<!-- TODO: Inline the display:none; CSS --> <!-- TODO: Inline the display:none; CSS -->
@ -69,19 +69,19 @@
<div class="formrow real_first_child"> <div class="formrow real_first_child">
<div class="formitem formlabel"><a>{{lang "profile.ban_user_days"}}</a></div> <div class="formitem formlabel"><a>{{lang "profile.ban_user_days"}}</a></div>
<div class="formitem"> <div class="formitem">
<input name="dur-days" type="number" value=0 min=0> <input name="dur-days"type="number"value=0 min=0>
</div> </div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a>{{lang "profile.ban_user_weeks"}}</a></div> <div class="formitem formlabel"><a>{{lang "profile.ban_user_weeks"}}</a></div>
<div class="formitem"> <div class="formitem">
<input name="dur-weeks" type="number" value=0 min=0> <input name="dur-weeks"type="number"value=0 min=0>
</div> </div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a>{{lang "profile.ban_user_months"}}</a></div> <div class="formitem formlabel"><a>{{lang "profile.ban_user_months"}}</a></div>
<div class="formitem"> <div class="formitem">
<input name="dur-months" type="number" value=0 min=0> <input name="dur-months"type="number"value=0 min=0>
</div> </div>
</div> </div>
<div class="formrow"> <div class="formrow">
@ -93,16 +93,16 @@
</div> </div>
{{/**<!--<div class="formrow"> {{/**<!--<div class="formrow">
<div class="formitem formlabel"><a>{{lang "profile.ban_user_reason"}}</a></div> <div class="formitem formlabel"><a>{{lang "profile.ban_user_reason"}}</a></div>
<div class="formitem"><textarea name="ban-reason" placeholder="A really horrible person" required></textarea></div> <div class="formitem"><textarea name="ban-reason" placeholder="A really horrible person"required></textarea></div>
</div>-->**/}} </div>-->**/}}
<div class="formrow"> <div class="formrow">
<div class="formitem"><button name="ban-button" class="formbutton form_middle_button">{{lang "profile.ban_user_button"}}</button></div> <div class="formitem"><button name="ban-button"class="formbutton form_middle_button">{{lang "profile.ban_user_button"}}</button></div>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
<div id="delete_posts_head" class="colstack_item colstack_head hash_hide delete_posts_hash" style="display:none;"> <div id="delete_posts_head"class="colstack_item colstack_head hash_hide delete_posts_hash"style="display:none;">
<div class="rowitem"><h1><a>{{lang "profile.delete_posts_head"}}</a></h1></div> <div class="rowitem"><h1><a>{{lang "profile.delete_posts_head"}}</a></h1></div>
</div> </div>
<form id="delete_posts_form" class="hash_hide delete_posts_hash" action="/users/delete-posts/submit/{{.ProfileOwner.ID}}?s={{.CurrentUser.Session}}" method="post" style="display:none;"> <form id="delete_posts_form" class="hash_hide delete_posts_hash" action="/users/delete-posts/submit/{{.ProfileOwner.ID}}?s={{.CurrentUser.Session}}" method="post" style="display:none;">
@ -110,7 +110,7 @@
<div class="colline">{{langf "profile.delete_posts_notice" .ProfileOwner.Posts}}</div> <div class="colline">{{langf "profile.delete_posts_notice" .ProfileOwner.Posts}}</div>
<div class="colstack_item"> <div class="colstack_item">
<div class="formrow real_first_child"> <div class="formrow real_first_child">
<div class="formitem"><button name="delete-posts-button" class="formbutton form_middle_button">{{lang "profile.delete_posts_button"}}</button></div> <div class="formitem"><button name="delete-posts-button"class="formbutton form_middle_button">{{lang "profile.delete_posts_button"}}</button></div>
</div> </div>
</div> </div>
</div> </div>
@ -118,27 +118,27 @@
{{end}} {{end}}
{{end}} {{end}}
<div id="profile_comments_head" class="colstack_item colstack_head hash_hide"> <div id="profile_comments_head"class="colstack_item colstack_head hash_hide">
<div class="rowitem"><h1><a>{{lang "profile.comments_head"}}</a></h1></div> <div class="rowitem"><h1><a>{{lang "profile.comments_head"}}</a></h1></div>
</div> </div>
<div id="profile_comments" class="colstack_item hash_hide">{{template "profile_comments_row.html" . }}</div> <div id="profile_comments"class="colstack_item hash_hide">{{template "profile_comments_row.html" . }}</div>
{{if .CurrentUser.Loggedin}} {{if .CurrentUser.Loggedin}}
{{if .CanComment}} {{if .CanComment}}
<form id="profile_comments_form" class="hash_hide" action="/profile/reply/create/?s={{.CurrentUser.Session}}" method="post"> <form id="profile_comments_form"class="hash_hide"action="/profile/reply/create/?s={{.CurrentUser.Session}}"method="post">
<input name="uid"value='{{.ProfileOwner.ID}}'type="hidden"> <input name="uid"value='{{.ProfileOwner.ID}}'type="hidden">
<div class="colstack_item topic_reply_form" style="border-top:none;"> <div class="colstack_item topic_reply_form"style="border-top:none;">
<div class="formrow"> <div class="formrow">
<div class="formitem"><textarea class="input_content" name="content" placeholder="{{lang "profile.comments_form_content"}}"></textarea></div> <div class="formitem"><textarea class="input_content"name="content"placeholder="{{lang "profile.comments_form_content"}}"></textarea></div>
</div> </div>
<div class="formrow quick_button_row"> <div class="formrow quick_button_row">
<div class="formitem"><button name="reply-button" class="formbutton">{{lang "profile.comments_form_button"}}</button></div> <div class="formitem"><button name="reply-button"class="formbutton">{{lang "profile.comments_form_button"}}</button></div>
</div> </div>
</div> </div>
</form> </form>
{{end}} {{end}}
{{else}} {{else}}
<div class="colstack_item" style="border-top:none;"> <div class="colstack_item"style="border-top:none;">
<div class="rowitem passive">{{lang "profile.comments_form_guest"}}</div> <div class="rowitem passive">{{lang "profile.comments_form_guest"}}</div>
</div> </div>
{{end}} {{end}}

View File

@ -6,11 +6,11 @@
<span class="controls"> <span class="controls">
<a href="{{.UserLink}}"class="real_username username">{{.CreatedByName}}</a>&nbsp;&nbsp; <a href="{{.UserLink}}"class="real_username username">{{.CreatedByName}}</a>&nbsp;&nbsp;
{{if $.CurrentUser.IsMod}}<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}"class="mod_button"title="{{lang "profile.comments_edit_tooltip"}}" aria-label="{{lang "profile.comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a> {{if $.CurrentUser.IsMod}}<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}"class="mod_button"title="{{lang "profile.comments_edit_tooltip"}}"aria-label="{{lang "profile.comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}"class="mod_button"title="{{lang "profile.comments_delete_tooltip"}}" aria-label="{{lang "profile.comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}} <a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}"class="mod_button"title="{{lang "profile.comments_delete_tooltip"}}"aria-label="{{lang "profile.comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
<a class="mod_button"href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label"title="{{lang "profile.comments_report_tooltip"}}" aria-label="{{lang "profile.comments_report_aria"}}"></button></a> <a class="mod_button"href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label"title="{{lang "profile.comments_report_tooltip"}}"aria-label="{{lang "profile.comments_report_aria"}}"></button></a>
{{if .Tag}}<a class="username hide_on_mobile user_tag"style="float:right;">{{.Tag}}</a>{{end}} {{if .Tag}}<a class="username hide_on_mobile user_tag"style="float:right;">{{.Tag}}</a>{{end}}
</span> </span>

View File

@ -7,31 +7,31 @@
<form action="/accounts/create/submit/" method="post"> <form action="/accounts/create/submit/" method="post">
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a id="name_label">{{lang "register_account_name"}}</a></div> <div class="formitem formlabel"><a id="name_label">{{lang "register_account_name"}}</a></div>
<div class="formitem"><input name="name" type="text" placeholder="{{lang "register_account_name"}}" aria-labelledby="name_label" required></div> <div class="formitem"><input name="name"type="text"placeholder="{{lang "register_account_name"}}" aria-labelledby="name_label"required></div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a id="email_label">{{if not .Something}}{{lang "register_account_email"}}{{else}}{{lang "register_account_email_optional"}}{{end}}</a></div> <div class="formitem formlabel"><a id="email_label">{{if not .Something}}{{lang "register_account_email"}}{{else}}{{lang "register_account_email_optional"}}{{end}}</a></div>
<div class="formitem"><input name="email" type="email" placeholder="joe.doe@example.com" aria-labelledby="email_label"{{if not .Something}} required{{end}}></div> <div class="formitem"><input name="email"type="email"placeholder="joe.doe@example.com"aria-labelledby="email_label"{{if not .Something}}required{{end}}></div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a id="password_label">{{lang "register_account_password"}}</a></div> <div class="formitem formlabel"><a id="password_label">{{lang "register_account_password"}}</a></div>
<div class="formitem"><input name="password" type="password" autocomplete="new-password" placeholder="*****" aria-labelledby="password_label" required></div> <div class="formitem"><input name="password"type="password"autocomplete="new-password"placeholder="*****"aria-labelledby="password_label"required></div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a id="confirm_password_label">{{lang "register_account_confirm_password"}}</a></div> <div class="formitem formlabel"><a id="confirm_password_label">{{lang "register_account_confirm_password"}}</a></div>
<div class="formitem"><input name="confirm_password" type="password" placeholder="*****" autocomplete="new-password" aria-labelledby="confirm_password_label" required></div> <div class="formitem"><input name="confirm_password"type="password"placeholder="*****"autocomplete="new-password"aria-labelledby="confirm_password_label"required></div>
</div> </div>
<div class="formrow">{{/** This is not a TOS, that text is there to fool the spambots **/}} <div class="formrow">{{/** This is not a TOS, that text is there to fool the spambots **/}}
<div class="formitem formlabel"><a id="accept_tos_label">{{lang "register_account_anti_spam"}}</a></div> <div class="formitem formlabel"><a id="accept_tos_label">{{lang "register_account_anti_spam"}}</a></div>
<div class="formitem"><select name="tos" aria-labelledby="accept_tos_label" required> <div class="formitem"><select name="tos"aria-labelledby="accept_tos_label"required>
<option value="1" selected>{{lang "option_yes"}}</option> <option value="1"selected>{{lang "option_yes"}}</option>
<option value="0">{{lang "option_no"}}</option> <option value="0">{{lang "option_no"}}</option>
</select></div> </select></div>
</div> </div>
<div class="formrow register_button_row form_button_row"> <div class="formrow register_button_row form_button_row">
<div class="formitem"><button name="register-button" class="formbutton">{{lang "register_submit_button"}}</button></div> <div class="formitem"><button name="register-button"class="formbutton">{{lang "register_submit_button"}}</button></div>
</div> </div>
<input id="golden-watch" name="golden-watch" value="$500" type="hidden"> <input id="golden-watch"name="golden-watch"value="$500"type="hidden">
</form> </form>
</div> </div>
</main> </main>

View File

@ -1,4 +1,4 @@
<div id="back" class="zone_{{.Header.Zone}}{{if hasWidgets "rightSidebar" .Header }} shrink_main{{end}}"> <div id="back"class="zone_{{.Header.Zone}}{{if hasWidgets "rightSidebar" .Header }} shrink_main{{end}}">
<div id="main"> <div id="main">
<div class="alertbox initial_alertbox">{{range .Header.NoticeList}}{{template "notice.html" . }}{{end}}</div> <div class="alertbox initial_alertbox">{{range .Header.NoticeList}}{{template "notice.html" . }}{{end}}</div>
{{template "topic_alt_inner.html" . }} {{template "topic_alt_inner.html" . }}

View File

@ -1,8 +1,8 @@
<div class="rowblock topic_reply_container"> <div class="rowblock topic_reply_container">
<div class="userinfo" aria-label="{{lang "topic.your_information"}}"> <div class="userinfo"aria-label="{{lang "topic.your_information"}}">
<img class="aitem"src="{{.CurrentUser.Avatar}}"alt="Avatar"> <img class="aitem"src="{{.CurrentUser.Avatar}}"alt="Avatar">
<div class="user_meta"> <div class="user_meta">
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a> <a href="{{.CurrentUser.Link}}"class="the_name"rel="author">{{.CurrentUser.Name}}</a>
<div class="tag_block"> <div class="tag_block">
<div class="tag_pre"></div> <div class="tag_pre"></div>
{{if .CurrentUser.Tag}}<div class="post_tag">{{.CurrentUser.Tag}}</div>{{else}}<div class="post_tag post_level">{{level .CurrentUser.Level}}</div>{{end}} {{if .CurrentUser.Tag}}<div class="post_tag">{{.CurrentUser.Tag}}</div>{{else}}<div class="post_tag post_level">{{level .CurrentUser.Level}}</div>{{end}}
@ -10,31 +10,31 @@
</div> </div>
</div> </div>
</div> </div>
<div class="rowblock topic_reply_form quick_create_form" aria-label="{{lang "topic.reply_aria"}}"> <div class="rowblock topic_reply_form quick_create_form"aria-label="{{lang "topic.reply_aria"}}">
<form id="quick_post_form" enctype="multipart/form-data" action="/reply/create/?s={{.CurrentUser.Session}}" method="post"></form> <form id="quick_post_form"enctype="multipart/form-data"action="/reply/create/?s={{.CurrentUser.Session}}"method="post"></form>
<input form="quick_post_form" name="tid" value='{{.Topic.ID}}' type="hidden"> <input form="quick_post_form"name="tid"value='{{.Topic.ID}}'type="hidden">
<input form="quick_post_form" id="has_poll_input" name="has_poll" value=0 type="hidden"> <input form="quick_post_form"id="has_poll_input"name="has_poll"type="hidden"value=0>
<div class="formrow real_first_child"> <div class="formrow real_first_child">
<div class="formitem"> <div class="formitem">
<textarea id="input_content" form="quick_post_form" name="content" placeholder="{{lang "topic.reply_content_alt"}}" required></textarea> <textarea id="input_content"form="quick_post_form"name="content"placeholder="{{lang "topic.reply_content_alt"}}" required></textarea>
</div> </div>
</div> </div>
<div class="formrow poll_content_row auto_hide"> <div class="formrow poll_content_row auto_hide">
<div class="formitem"> <div class="formitem">
<div class="pollinput" data-pollinput=0> <div class="pollinput"data-pollinput=0>
<input type="checkbox" disabled> <input type="checkbox"disabled>
<label class="pollinputlabel"></label> <label class="pollinputlabel"></label>
<input form="quick_post_form" name="pollinputitem[0]" class="pollinputinput" type="text" placeholder="{{lang "topic.reply_add_poll_option_first"}}"> <input form="quick_post_form"name="pollinputitem[0]"class="pollinputinput"type="text"placeholder="{{lang "topic.reply_add_poll_option_first"}}">
</div> </div>
</div> </div>
</div> </div>
<div class="formrow quick_button_row"> <div class="formrow quick_button_row">
<div class="formitem"> <div class="formitem">
<button form="quick_post_form" name="reply-button" class="formbutton">{{lang "topic.reply_button"}}</button> <button form="quick_post_form"name="reply-button"class="formbutton">{{lang "topic.reply_button"}}</button>
<button form="quick_post_form" class="formbutton" id="add_poll_button">{{lang "topic.reply_add_poll_button"}}</button> <button form="quick_post_form"class="formbutton"id="add_poll_button">{{lang "topic.reply_add_poll_button"}}</button>
{{if .CurrentUser.Perms.UploadFiles}} {{if .CurrentUser.Perms.UploadFiles}}
<input name="upload_files" form="quick_post_form" id="upload_files" multiple type="file" class="auto_hide"> <input name="upload_files"form="quick_post_form"id="upload_files"multiple type="file" class="auto_hide">
<label for="upload_files" class="formbutton add_file_button">{{lang "topic.reply_add_file_button"}}</label> <label for="upload_files"class="formbutton add_file_button">{{lang "topic.reply_add_file_button"}}</label>
<div id="upload_file_dock"></div>{{end}} <div id="upload_file_dock"></div>{{end}}
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class='pollinput'data-pollinput={{.Index}}> <div class='pollinput'data-pollinput={{.Index}}>
<input type='checkbox' disabled> <input type='checkbox'disabled>
<label class='pollinputlabel'></label> <label class='pollinputlabel'></label>
<input form='quick_post_form'name='pollinputitem[{{.Index}}]'class='pollinputinput'type='text'placeholder='{{.Place}}'> <input form='quick_post_form'name='pollinputitem[{{.Index}}]'class='pollinputinput'type='text'placeholder='{{.Place}}'>
</div> </div>

View File

@ -1,4 +1,4 @@
<div id="back" class="zone_{{.Header.Zone}}{{if hasWidgets "rightSidebar" .Header }} shrink_main{{end}}"> <div id="back"class="zone_{{.Header.Zone}}{{if hasWidgets "rightSidebar" .Header }} shrink_main{{end}}">
<div id="main"> <div id="main">
<div class="alertbox initial_alertbox">{{range .Header.NoticeList}}{{template "notice.html" . }}{{end}}</div> <div class="alertbox initial_alertbox">{{range .Header.NoticeList}}{{template "notice.html" . }}{{end}}</div>
{{template "topic_inner.html" . }} {{template "topic_inner.html" . }}

View File

@ -1,6 +1,6 @@
{{template "header.html" . }} {{template "header.html" . }}
<main id="topicsItemList" itemscope itemtype="http://schema.org/ItemList"> <main id="topicsItemList" itemscope itemtype="http://schema.org/ItemList">
{{if not .CurrentUser.Loggedin}}<link rel="canonical"href="//{{.Site.URL}}/topics/{{if eq .Sort.SortBy "mostviewed"}}most-viewed/{{end}}{{if gt .Page 1}}?page={{.Page}}{{end}}"/>{{end}} {{if not .CurrentUser.Loggedin}}<link rel="canonical"href="//{{.Site.URL}}/topics/{{if eq .Sort.SortBy "mostviewed"}}most-viewed/{{end}}{{if gt .Page 1}}?page={{.Page}}{{end}}">{{end}}
<div class="rowblock rowhead topic_list_title_block{{if .CurrentUser.Loggedin}} has_opt{{end}}"> <div class="rowblock rowhead topic_list_title_block{{if .CurrentUser.Loggedin}} has_opt{{end}}">
<div class="rowitem topic_list_title"><h1 itemprop="name">{{.Title}}</h1></div> <div class="rowitem topic_list_title"><h1 itemprop="name">{{.Title}}</h1></div>
@ -59,7 +59,7 @@
<div class="topic_meta"> <div class="topic_meta">
<div class="formrow topic_board_row real_first_child"> <div class="formrow topic_board_row real_first_child">
<div class="formitem"><select form="quick_post_form" id="topic_board_input" name="board"> <div class="formitem"><select form="quick_post_form" id="topic_board_input" name="board">
{{range .ForumList}}<option{{if eq .ID $.DefaultForum}} selected{{end}} value="{{.ID}}">{{.Name}}</option>{{end}} {{range .ForumList}}<option value="{{.ID}}"{{if eq .ID $.DefaultForum}}selected{{end}}>{{.Name}}</option>{{end}}
</select></div> </select></div>
</div> </div>
<div class="formrow topic_name_row"> <div class="formrow topic_name_row">
@ -76,7 +76,7 @@
<div class="rowblock more_topic_block more_topic_block_initial"> <div class="rowblock more_topic_block more_topic_block_initial">
<div class="rowitem rowmsg"><a href=""class="more_topics"></a></div> <div class="rowitem rowmsg"><a href=""class="more_topics"></a></div>
</div> </div>
<div id="topic_list" class="rowblock topic_list topic_list_{{.Sort.SortBy}}" aria-label="{{lang "topics_list_aria"}}"> <div id="topic_list"class="rowblock topic_list topic_list_{{.Sort.SortBy}}"aria-label="{{lang "topics_list_aria"}}">
{{range .TopicList}}{{template "topics_topic.html" . }}{{else}}<div class="rowitem passive rowmsg">{{lang "topics_no_topics"}}{{if .CurrentUser.Loggedin}}{{if .CurrentUser.Perms.CreateTopic}}&nbsp;<a href="/topics/create/">{{lang "topics_start_one"}}</a>{{end}}{{end}}</div>{{end}} {{range .TopicList}}{{template "topics_topic.html" . }}{{else}}<div class="rowitem passive rowmsg">{{lang "topics_no_topics"}}{{if .CurrentUser.Loggedin}}{{if .CurrentUser.Perms.CreateTopic}}&nbsp;<a href="/topics/create/">{{lang "topics_start_one"}}</a>{{end}}{{end}}</div>{{end}}
</div> </div>

View File

@ -7,11 +7,11 @@
<form action="/accounts/login/submit/" method="post"> <form action="/accounts/login/submit/" method="post">
<div class="formrow login_name_row"> <div class="formrow login_name_row">
<div class="formitem formlabel"><a id="login_name_label">{{lang "login_account_name"}}</a></div> <div class="formitem formlabel"><a id="login_name_label">{{lang "login_account_name"}}</a></div>
<div class="formitem"><input name="username"type="text"placeholder="{{lang "login_account_name"}}" aria-labelledby="login_name_label" required></div> <div class="formitem"><input name="username"type="text"placeholder="{{lang "login_account_name"}}" aria-labelledby="login_name_label"required></div>
</div> </div>
<div class="formrow login_password_row"> <div class="formrow login_password_row">
<div class="formitem formlabel"><a id="login_password_label">{{lang "login_account_password"}}</a></div> <div class="formitem formlabel"><a id="login_password_label">{{lang "login_account_password"}}</a></div>
<div class="formitem"><input name="password"type="password"autocomplete="current-password"placeholder="*****"aria-labelledby="login_password_label" required></div> <div class="formitem"><input name="password"type="password"autocomplete="current-password"placeholder="*****"aria-labelledby="login_password_label"required></div>
</div> </div>
<div class="formrow login_button_row form_button_row"> <div class="formrow login_button_row form_button_row">
<div class="formitem"><button name="login-button" class="formbutton">{{lang "login_submit_button"}}</button></div> <div class="formitem"><button name="login-button" class="formbutton">{{lang "login_submit_button"}}</button></div>

View File

@ -1,6 +1,6 @@
<div class="above_right"> <div class="above_right">
<div class="left_bit"><a href="/">{{lang "panel_back_to_site"}}</a></div> <div class="left_bit"><a href="/">{{lang "panel_back_to_site"}}</a></div>
<div class="right_bit"> <div class="right_bit">
<img src="{{.CurrentUser.MicroAvatar}}" height=32 width=32> <img src="{{.CurrentUser.MicroAvatar}}"height=32 width=32>
<span>{{lang "panel_welcome"}}{{.CurrentUser.Name}}</span></div> <span>{{lang "panel_welcome"}}{{.CurrentUser.Name}}</span></div>
</div> </div>