Added support for word filters.
Added support for temporary bans. Moved the Gosora specific template logic out of main.go and into template_init.go Added an internal temporary group API. We now use h1s in the theme headers. There may be some issues with the themes other than Shadow which we may need to resolve. Added ARIA attributes in a few places for improved accessibility. Added support for inputs in links for the .edit_field API. Removed a few unneccesary prepared statements.
This commit is contained in:
parent
34b02336ed
commit
99da1fcbaa
|
@ -17,7 +17,7 @@ var error_notfound []byte
|
||||||
|
|
||||||
func init_errors() error {
|
func init_errors() error {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
user := User{0,"guest","Guest","",0,false,false,false,false,false,false,GuestPerms,nil,"",false,"","","","","",0,0,"0.0.0.0.0"}
|
user := User{0,"guest","Guest","",0,false,false,false,false,false,false,GuestPerms,nil,"",false,"","","","","",0,0,"0.0.0.0.0",0}
|
||||||
pi := Page{"Internal Server Error",user,hvars,tList,"A problem has occurred in the system."}
|
pi := Page{"Internal Server Error",user,hvars,tList,"A problem has occurred in the system."}
|
||||||
err := templates.ExecuteTemplate(&b,"error.html", pi)
|
err := templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -57,6 +57,8 @@ var pre_render_hooks map[string][]func(http.ResponseWriter, *http.Request, *User
|
||||||
"pre_render_panel_edit_forum": nil,
|
"pre_render_panel_edit_forum": nil,
|
||||||
"pre_render_panel_settings": nil,
|
"pre_render_panel_settings": nil,
|
||||||
"pre_render_panel_setting": nil,
|
"pre_render_panel_setting": nil,
|
||||||
|
"pre_render_panel_word_filters": nil,
|
||||||
|
"pre_render_panel_word_filters_edit": nil,
|
||||||
"pre_render_panel_plugins": nil,
|
"pre_render_panel_plugins": nil,
|
||||||
"pre_render_panel_users": nil,
|
"pre_render_panel_users": nil,
|
||||||
"pre_render_panel_edit_user": nil,
|
"pre_render_panel_edit_user": nil,
|
||||||
|
|
63
gen_mysql.go
63
gen_mysql.go
|
@ -24,6 +24,7 @@ var get_widgets_stmt *sql.Stmt
|
||||||
var is_plugin_active_stmt *sql.Stmt
|
var is_plugin_active_stmt *sql.Stmt
|
||||||
var get_users_stmt *sql.Stmt
|
var get_users_stmt *sql.Stmt
|
||||||
var get_users_offset_stmt *sql.Stmt
|
var get_users_offset_stmt *sql.Stmt
|
||||||
|
var get_word_filters_stmt *sql.Stmt
|
||||||
var is_theme_default_stmt *sql.Stmt
|
var is_theme_default_stmt *sql.Stmt
|
||||||
var get_modlogs_stmt *sql.Stmt
|
var get_modlogs_stmt *sql.Stmt
|
||||||
var get_modlogs_offset_stmt *sql.Stmt
|
var get_modlogs_offset_stmt *sql.Stmt
|
||||||
|
@ -33,15 +34,14 @@ var get_user_reply_uid_stmt *sql.Stmt
|
||||||
var has_liked_topic_stmt *sql.Stmt
|
var has_liked_topic_stmt *sql.Stmt
|
||||||
var has_liked_reply_stmt *sql.Stmt
|
var has_liked_reply_stmt *sql.Stmt
|
||||||
var get_user_name_stmt *sql.Stmt
|
var get_user_name_stmt *sql.Stmt
|
||||||
var get_user_rank_stmt *sql.Stmt
|
|
||||||
var get_user_active_stmt *sql.Stmt
|
var get_user_active_stmt *sql.Stmt
|
||||||
var get_user_group_stmt *sql.Stmt
|
|
||||||
var get_emails_by_user_stmt *sql.Stmt
|
var get_emails_by_user_stmt *sql.Stmt
|
||||||
var get_topic_basic_stmt *sql.Stmt
|
var get_topic_basic_stmt *sql.Stmt
|
||||||
var get_activity_entry_stmt *sql.Stmt
|
var get_activity_entry_stmt *sql.Stmt
|
||||||
var forum_entry_exists_stmt *sql.Stmt
|
var forum_entry_exists_stmt *sql.Stmt
|
||||||
var group_entry_exists_stmt *sql.Stmt
|
var group_entry_exists_stmt *sql.Stmt
|
||||||
var get_forum_topics_offset_stmt *sql.Stmt
|
var get_forum_topics_offset_stmt *sql.Stmt
|
||||||
|
var get_expired_scheduled_groups_stmt *sql.Stmt
|
||||||
var get_topic_replies_offset_stmt *sql.Stmt
|
var get_topic_replies_offset_stmt *sql.Stmt
|
||||||
var get_topic_list_stmt *sql.Stmt
|
var get_topic_list_stmt *sql.Stmt
|
||||||
var get_topic_user_stmt *sql.Stmt
|
var get_topic_user_stmt *sql.Stmt
|
||||||
|
@ -67,7 +67,9 @@ var add_theme_stmt *sql.Stmt
|
||||||
var create_group_stmt *sql.Stmt
|
var create_group_stmt *sql.Stmt
|
||||||
var add_modlog_entry_stmt *sql.Stmt
|
var add_modlog_entry_stmt *sql.Stmt
|
||||||
var add_adminlog_entry_stmt *sql.Stmt
|
var add_adminlog_entry_stmt *sql.Stmt
|
||||||
|
var create_word_filter_stmt *sql.Stmt
|
||||||
var add_forum_perms_to_group_stmt *sql.Stmt
|
var add_forum_perms_to_group_stmt *sql.Stmt
|
||||||
|
var replace_schedule_group_stmt *sql.Stmt
|
||||||
var add_replies_to_topic_stmt *sql.Stmt
|
var add_replies_to_topic_stmt *sql.Stmt
|
||||||
var remove_replies_from_topic_stmt *sql.Stmt
|
var remove_replies_from_topic_stmt *sql.Stmt
|
||||||
var add_topics_to_forum_stmt *sql.Stmt
|
var add_topics_to_forum_stmt *sql.Stmt
|
||||||
|
@ -105,11 +107,14 @@ var update_group_rank_stmt *sql.Stmt
|
||||||
var update_group_stmt *sql.Stmt
|
var update_group_stmt *sql.Stmt
|
||||||
var update_email_stmt *sql.Stmt
|
var update_email_stmt *sql.Stmt
|
||||||
var verify_email_stmt *sql.Stmt
|
var verify_email_stmt *sql.Stmt
|
||||||
|
var set_temp_group_stmt *sql.Stmt
|
||||||
|
var update_word_filter_stmt *sql.Stmt
|
||||||
var delete_reply_stmt *sql.Stmt
|
var delete_reply_stmt *sql.Stmt
|
||||||
var delete_topic_stmt *sql.Stmt
|
var delete_topic_stmt *sql.Stmt
|
||||||
var delete_profile_reply_stmt *sql.Stmt
|
var delete_profile_reply_stmt *sql.Stmt
|
||||||
var delete_forum_perms_by_forum_stmt *sql.Stmt
|
var delete_forum_perms_by_forum_stmt *sql.Stmt
|
||||||
var delete_activity_stream_match_stmt *sql.Stmt
|
var delete_activity_stream_match_stmt *sql.Stmt
|
||||||
|
var delete_word_filter_stmt *sql.Stmt
|
||||||
var report_exists_stmt *sql.Stmt
|
var report_exists_stmt *sql.Stmt
|
||||||
var group_count_stmt *sql.Stmt
|
var group_count_stmt *sql.Stmt
|
||||||
var modlog_count_stmt *sql.Stmt
|
var modlog_count_stmt *sql.Stmt
|
||||||
|
@ -225,6 +230,12 @@ func _gen_mysql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing get_word_filters statement.")
|
||||||
|
get_word_filters_stmt, err = db.Prepare("SELECT `wfid`,`find`,`replacement` FROM `word_filters`")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing is_theme_default statement.")
|
log.Print("Preparing is_theme_default statement.")
|
||||||
is_theme_default_stmt, err = db.Prepare("SELECT `default` FROM `themes` WHERE `uname` = ?")
|
is_theme_default_stmt, err = db.Prepare("SELECT `default` FROM `themes` WHERE `uname` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -279,24 +290,12 @@ func _gen_mysql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Print("Preparing get_user_rank statement.")
|
|
||||||
get_user_rank_stmt, err = db.Prepare("SELECT `group`,`is_super_admin` FROM `users` WHERE `uid` = ?")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Print("Preparing get_user_active statement.")
|
log.Print("Preparing get_user_active statement.")
|
||||||
get_user_active_stmt, err = db.Prepare("SELECT `active` FROM `users` WHERE `uid` = ?")
|
get_user_active_stmt, err = db.Prepare("SELECT `active` FROM `users` WHERE `uid` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Print("Preparing get_user_group statement.")
|
|
||||||
get_user_group_stmt, err = db.Prepare("SELECT `group` FROM `users` WHERE `uid` = ?")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Print("Preparing get_emails_by_user statement.")
|
log.Print("Preparing get_emails_by_user statement.")
|
||||||
get_emails_by_user_stmt, err = db.Prepare("SELECT `email`,`validated`,`token` FROM `emails` WHERE `uid` = ?")
|
get_emails_by_user_stmt, err = db.Prepare("SELECT `email`,`validated`,`token` FROM `emails` WHERE `uid` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -333,6 +332,12 @@ func _gen_mysql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing get_expired_scheduled_groups statement.")
|
||||||
|
get_expired_scheduled_groups_stmt, err = db.Prepare("SELECT `uid` FROM `users_groups_scheduler` WHERE UTC_TIMESTAMP() > `revert_at` AND `temporary` = 1")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing get_topic_replies_offset statement.")
|
log.Print("Preparing get_topic_replies_offset statement.")
|
||||||
get_topic_replies_offset_stmt, err = db.Prepare("SELECT `replies`.`rid`,`replies`.`content`,`replies`.`createdBy`,`replies`.`createdAt`,`replies`.`lastEdit`,`replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group`,`users`.`url_prefix`,`users`.`url_name`,`users`.`level`,`replies`.`ipaddress`,`replies`.`likeCount`,`replies`.`actionType` FROM `replies` LEFT JOIN `users` ON `replies`.`createdBy` = `users`.`uid` WHERE `tid` = ? LIMIT ?,?")
|
get_topic_replies_offset_stmt, err = db.Prepare("SELECT `replies`.`rid`,`replies`.`content`,`replies`.`createdBy`,`replies`.`createdAt`,`replies`.`lastEdit`,`replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group`,`users`.`url_prefix`,`users`.`url_name`,`users`.`level`,`replies`.`ipaddress`,`replies`.`likeCount`,`replies`.`actionType` FROM `replies` LEFT JOIN `users` ON `replies`.`createdBy` = `users`.`uid` WHERE `tid` = ? LIMIT ?,?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -483,12 +488,24 @@ func _gen_mysql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing create_word_filter statement.")
|
||||||
|
create_word_filter_stmt, err = db.Prepare("INSERT INTO `word_filters`(`find`,`replacement`) VALUES (?,?)")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing add_forum_perms_to_group statement.")
|
log.Print("Preparing add_forum_perms_to_group statement.")
|
||||||
add_forum_perms_to_group_stmt, err = db.Prepare("REPLACE INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) VALUES (?,?,?,?)")
|
add_forum_perms_to_group_stmt, err = db.Prepare("REPLACE INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) VALUES (?,?,?,?)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing replace_schedule_group statement.")
|
||||||
|
replace_schedule_group_stmt, err = db.Prepare("REPLACE INTO `users_groups_scheduler`(`uid`,`set_group`,`issued_by`,`issued_at`,`revert_at`,`temporary`) VALUES (?,?,?,UTC_TIMESTAMP(),?,?)")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing add_replies_to_topic statement.")
|
log.Print("Preparing add_replies_to_topic statement.")
|
||||||
add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyBy` = ?,`lastReplyAt` = UTC_TIMESTAMP() WHERE `tid` = ?")
|
add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyBy` = ?,`lastReplyAt` = UTC_TIMESTAMP() WHERE `tid` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -711,6 +728,18 @@ func _gen_mysql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing set_temp_group statement.")
|
||||||
|
set_temp_group_stmt, err = db.Prepare("UPDATE `users` SET `temp_group` = ? WHERE `uid` = ?")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing update_word_filter statement.")
|
||||||
|
update_word_filter_stmt, err = db.Prepare("UPDATE `word_filters` SET `find` = ?,`replacement` = ? WHERE `wfid` = ?")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing delete_reply statement.")
|
log.Print("Preparing delete_reply statement.")
|
||||||
delete_reply_stmt, err = db.Prepare("DELETE FROM `replies` WHERE `rid` = ?")
|
delete_reply_stmt, err = db.Prepare("DELETE FROM `replies` WHERE `rid` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -741,6 +770,12 @@ func _gen_mysql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing delete_word_filter statement.")
|
||||||
|
delete_word_filter_stmt, err = db.Prepare("DELETE FROM `word_filters` WHERE `wfid` = ?")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing report_exists statement.")
|
log.Print("Preparing report_exists statement.")
|
||||||
report_exists_stmt, err = db.Prepare("SELECT COUNT(*) AS `count` FROM `topics` WHERE `data` = ? AND `data` != '' AND `parentID` = 1")
|
report_exists_stmt, err = db.Prepare("SELECT COUNT(*) AS `count` FROM `topics` WHERE `data` = ? AND `data` != '' AND `parentID` = 1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
14
gen_pgsql.go
14
gen_pgsql.go
|
@ -43,6 +43,8 @@ var update_group_rank_stmt *sql.Stmt
|
||||||
var update_group_stmt *sql.Stmt
|
var update_group_stmt *sql.Stmt
|
||||||
var update_email_stmt *sql.Stmt
|
var update_email_stmt *sql.Stmt
|
||||||
var verify_email_stmt *sql.Stmt
|
var verify_email_stmt *sql.Stmt
|
||||||
|
var set_temp_group_stmt *sql.Stmt
|
||||||
|
var update_word_filter_stmt *sql.Stmt
|
||||||
|
|
||||||
func _gen_pgsql() (err error) {
|
func _gen_pgsql() (err error) {
|
||||||
if dev.DebugMode {
|
if dev.DebugMode {
|
||||||
|
@ -271,5 +273,17 @@ func _gen_pgsql() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing set_temp_group statement.")
|
||||||
|
set_temp_group_stmt, err = db.Prepare("UPDATE `users` SET `temp_group` = ? WHERE `uid` = ?")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing update_word_filter statement.")
|
||||||
|
update_word_filter_stmt, err = db.Prepare("UPDATE `word_filters` SET `find` = ?,`replacement` = ? WHERE `wfid` = ?")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,21 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
case "/panel/settings/edit/submit/":
|
case "/panel/settings/edit/submit/":
|
||||||
route_panel_setting_edit(w,req,user,extra_data)
|
route_panel_setting_edit(w,req,user,extra_data)
|
||||||
return
|
return
|
||||||
|
case "/panel/settings/word-filters/":
|
||||||
|
route_panel_word_filters(w,req,user)
|
||||||
|
return
|
||||||
|
case "/panel/settings/word-filters/create/":
|
||||||
|
route_panel_word_filters_create(w,req,user)
|
||||||
|
return
|
||||||
|
case "/panel/settings/word-filters/edit/":
|
||||||
|
route_panel_word_filters_edit(w,req,user,extra_data)
|
||||||
|
return
|
||||||
|
case "/panel/settings/word-filters/edit/submit/":
|
||||||
|
route_panel_word_filters_edit_submit(w,req,user,extra_data)
|
||||||
|
return
|
||||||
|
case "/panel/settings/word-filters/delete/submit/":
|
||||||
|
route_panel_word_filters_delete_submit(w,req,user,extra_data)
|
||||||
|
return
|
||||||
case "/panel/themes/":
|
case "/panel/themes/":
|
||||||
route_panel_themes(w,req,user)
|
route_panel_themes(w,req,user)
|
||||||
return
|
return
|
||||||
|
|
|
@ -25,7 +25,7 @@ var db_test *sql.DB
|
||||||
var db_prod *sql.DB
|
var db_prod *sql.DB
|
||||||
var gloinited bool
|
var gloinited bool
|
||||||
|
|
||||||
func gloinit() {
|
func gloinit() error {
|
||||||
dev.DebugMode = false
|
dev.DebugMode = false
|
||||||
//nogrouplog = true
|
//nogrouplog = true
|
||||||
|
|
||||||
|
@ -40,20 +40,20 @@ func gloinit() {
|
||||||
init_themes()
|
init_themes()
|
||||||
err := init_database()
|
err := init_database()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
db_prod = db
|
db_prod = db
|
||||||
//db_test, err = sql.Open("testdb","")
|
//db_test, err = sql.Open("testdb","")
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// log.Fatal(err)
|
// return err
|
||||||
//}
|
//}
|
||||||
|
|
||||||
init_templates()
|
init_templates()
|
||||||
db_prod.SetMaxOpenConns(64)
|
db_prod.SetMaxOpenConns(64)
|
||||||
err = init_errors()
|
err = init_errors()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.CacheTopicUser == CACHE_STATIC {
|
if config.CacheTopicUser == CACHE_STATIC {
|
||||||
|
@ -68,8 +68,14 @@ func gloinit() {
|
||||||
//log.SetOutput(os.Stdout)
|
//log.SetOutput(os.Stdout)
|
||||||
auth = NewDefaultAuth()
|
auth = NewDefaultAuth()
|
||||||
|
|
||||||
|
err = init_word_filters()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
router = NewGenRouter(http.FileServer(http.Dir("./uploads")))
|
router = NewGenRouter(http.FileServer(http.Dir("./uploads")))
|
||||||
gloinited = true
|
gloinited = true
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
271
main.go
271
main.go
|
@ -8,8 +8,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"sync/atomic"
|
||||||
"net/http"
|
"net/http"
|
||||||
"html/template"
|
|
||||||
//"runtime/pprof"
|
//"runtime/pprof"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ var version Version = Version{Major:0,Minor:1,Patch:0,Tag:"dev"}
|
||||||
|
|
||||||
const hour int = 60 * 60
|
const hour int = 60 * 60
|
||||||
const day int = hour * 24
|
const day int = hour * 24
|
||||||
|
const week int = day * 7
|
||||||
const month int = day * 30
|
const month int = day * 30
|
||||||
const year int = day * 365
|
const year int = day * 365
|
||||||
const kilobyte int = 1024
|
const kilobyte int = 1024
|
||||||
|
@ -29,9 +30,6 @@ var enable_websockets bool = false // Don't change this, the value is overwritte
|
||||||
|
|
||||||
var router *GenRouter
|
var router *GenRouter
|
||||||
var startTime time.Time
|
var startTime time.Time
|
||||||
//var timeLocation *time.Location
|
|
||||||
var templates = template.New("")
|
|
||||||
//var no_css_tmpl template.CSS = template.CSS("")
|
|
||||||
var external_sites map[string]string = map[string]string{
|
var external_sites map[string]string = map[string]string{
|
||||||
"YT":"https://www.youtube.com/",
|
"YT":"https://www.youtube.com/",
|
||||||
}
|
}
|
||||||
|
@ -40,236 +38,45 @@ var groupCapCount int
|
||||||
var static_files map[string]SFile = make(map[string]SFile)
|
var static_files map[string]SFile = make(map[string]SFile)
|
||||||
var logWriter io.Writer = io.MultiWriter(os.Stderr)
|
var logWriter io.Writer = io.MultiWriter(os.Stderr)
|
||||||
|
|
||||||
func interpreted_topic_template(pi TopicPage, w http.ResponseWriter) {
|
type WordFilter struct {
|
||||||
mapping, ok := themes[defaultTheme].TemplatesMap["topic"]
|
ID int
|
||||||
if !ok {
|
Find string
|
||||||
mapping = "topic"
|
Replacement string
|
||||||
}
|
}
|
||||||
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
type WordFilterBox map[int]WordFilter
|
||||||
if err != nil {
|
var wordFilterBox atomic.Value // An atomic value holding a WordFilterBox
|
||||||
InternalError(err,w)
|
|
||||||
}
|
func init() {
|
||||||
|
wordFilterBox.Store(WordFilterBox(make(map[int]WordFilter)))
|
||||||
}
|
}
|
||||||
|
|
||||||
var template_topic_handle func(TopicPage,http.ResponseWriter) = interpreted_topic_template
|
func init_word_filters() error {
|
||||||
var template_topic_alt_handle func(TopicPage,http.ResponseWriter) = interpreted_topic_template
|
rows, err := get_word_filters_stmt.Query()
|
||||||
var template_topics_handle func(TopicsPage,http.ResponseWriter) = func(pi TopicsPage, w http.ResponseWriter) {
|
|
||||||
mapping, ok := themes[defaultTheme].TemplatesMap["topics"]
|
|
||||||
if !ok {
|
|
||||||
mapping = "topics"
|
|
||||||
}
|
|
||||||
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
|
||||||
if err != nil {
|
|
||||||
InternalError(err,w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var template_forum_handle func(ForumPage,http.ResponseWriter) = func(pi ForumPage, w http.ResponseWriter) {
|
|
||||||
mapping, ok := themes[defaultTheme].TemplatesMap["forum"]
|
|
||||||
if !ok {
|
|
||||||
mapping = "forum"
|
|
||||||
}
|
|
||||||
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
|
||||||
if err != nil {
|
|
||||||
InternalError(err,w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var template_forums_handle func(ForumsPage,http.ResponseWriter) = func(pi ForumsPage, w http.ResponseWriter) {
|
|
||||||
mapping, ok := themes[defaultTheme].TemplatesMap["forums"]
|
|
||||||
if !ok {
|
|
||||||
mapping = "forums"
|
|
||||||
}
|
|
||||||
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
|
||||||
if err != nil {
|
|
||||||
InternalError(err,w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var template_profile_handle func(ProfilePage,http.ResponseWriter) = func(pi ProfilePage, w http.ResponseWriter) {
|
|
||||||
mapping, ok := themes[defaultTheme].TemplatesMap["profile"]
|
|
||||||
if !ok {
|
|
||||||
mapping = "profile"
|
|
||||||
}
|
|
||||||
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
|
||||||
if err != nil {
|
|
||||||
InternalError(err,w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var template_create_topic_handle func(CreateTopicPage,http.ResponseWriter) = func(pi CreateTopicPage, w http.ResponseWriter) {
|
|
||||||
mapping, ok := themes[defaultTheme].TemplatesMap["create-topic"]
|
|
||||||
if !ok {
|
|
||||||
mapping = "create-topic"
|
|
||||||
}
|
|
||||||
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
|
||||||
if err != nil {
|
|
||||||
InternalError(err,w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func compile_templates() error {
|
|
||||||
var c CTemplateSet
|
|
||||||
user := User{62,build_profile_url("fake-user",62),"Fake User","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"0.0.0.0.0"}
|
|
||||||
// TO-DO: Do a more accurate level calculation for this?
|
|
||||||
user2 := User{1,build_profile_url("admin-alice",1),"Admin Alice","alice@localhost",1,true,true,true,true,false,false,AllPerms,make(map[string]bool),"",true,"","","","","",58,1000,"127.0.0.1"}
|
|
||||||
user3 := User{2,build_profile_url("admin-fred",62),"Admin Fred","fred@localhost",1,true,true,true,true,false,false,AllPerms,make(map[string]bool),"",true,"","","","","",42,900,"::1"}
|
|
||||||
headerVars := HeaderVars{
|
|
||||||
Site:site,
|
|
||||||
NoticeList:[]string{"test"},
|
|
||||||
Stylesheets:[]string{"panel"},
|
|
||||||
Scripts:[]string{"whatever"},
|
|
||||||
Widgets:PageWidgets{
|
|
||||||
LeftSidebar: template.HTML("lalala"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Print("Compiling the templates")
|
|
||||||
|
|
||||||
topic := TopicUser{1,"blah","Blah","Hey there!",0,false,false,"Date","Date",0,"","127.0.0.1",0,1,"classname","weird-data",build_profile_url("fake-user",62),"Fake User",config.DefaultGroup,"",0,"","","","",58,false}
|
|
||||||
var replyList []Reply
|
|
||||||
replyList = append(replyList, Reply{0,0,"Yo!","Yo!",0,"alice","Alice",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""})
|
|
||||||
|
|
||||||
var varList map[string]VarItem = make(map[string]VarItem)
|
|
||||||
tpage := TopicPage{"Title",user,headerVars,replyList,topic,1,1,extData}
|
|
||||||
topic_id_tmpl, err := c.compile_template("topic.html","templates/","TopicPage", tpage, varList)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
topic_id_alt_tmpl, err := c.compile_template("topic_alt.html","templates/","TopicPage", tpage, varList)
|
defer rows.Close()
|
||||||
|
|
||||||
|
var wordFilters WordFilterBox = wordFilterBox.Load().(WordFilterBox)
|
||||||
|
var wfid int
|
||||||
|
var find string
|
||||||
|
var replacement string
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
err := rows.Scan(&wfid, &find, &replacement)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
wordFilters[wfid] = WordFilter{ID:wfid,Find:find,Replacement:replacement}
|
||||||
varList = make(map[string]VarItem)
|
|
||||||
ppage := ProfilePage{"User 526",user,headerVars,replyList,user,extData}
|
|
||||||
profile_tmpl, err := c.compile_template("profile.html","templates/","ProfilePage", ppage, varList)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
wordFilterBox.Store(wordFilters)
|
||||||
var forumList []Forum
|
return rows.Err()
|
||||||
forums, err := fstore.GetAll()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, forum := range forums {
|
|
||||||
if forum.Active {
|
|
||||||
forumList = append(forumList,*forum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
varList = make(map[string]VarItem)
|
|
||||||
forums_page := ForumsPage{"Forum List",user,headerVars,forumList,extData}
|
|
||||||
forums_tmpl, err := c.compile_template("forums.html","templates/","ForumsPage",forums_page,varList)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var topicsList []*TopicsRow
|
|
||||||
topicsList = append(topicsList,&TopicsRow{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",user3.ID,1,"","127.0.0.1",0,1,"classname","",&user2,"",0,&user3,"General","/forum/general.2"})
|
|
||||||
topics_page := TopicsPage{"Topic List",user,headerVars,topicsList,extData}
|
|
||||||
topics_tmpl, err := c.compile_template("topics.html","templates/","TopicsPage",topics_page,varList)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//var topicList []TopicUser
|
|
||||||
//topicList = append(topicList,TopicUser{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",1,"","127.0.0.1",0,1,"classname","","admin-fred","Admin Fred",config.DefaultGroup,"",0,"","","","",58,false})
|
|
||||||
forum_item := Forum{1,"general","General Forum","Where the general stuff happens",true,"all",0,"",0,"","",0,"",0,""}
|
|
||||||
forum_page := ForumPage{"General Forum",user,headerVars,topicsList,forum_item,1,1,extData}
|
|
||||||
forum_tmpl, err := c.compile_template("forum.html","templates/","ForumPage",forum_page,varList)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Print("Writing the templates")
|
|
||||||
go write_template("topic", topic_id_tmpl)
|
|
||||||
go write_template("topic_alt", topic_id_alt_tmpl)
|
|
||||||
go write_template("profile", profile_tmpl)
|
|
||||||
go write_template("forums", forums_tmpl)
|
|
||||||
go write_template("topics", topics_tmpl)
|
|
||||||
go write_template("forum", forum_tmpl)
|
|
||||||
go func() {
|
|
||||||
err := write_file("./template_list.go","package main\n\n" + c.FragOut)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func write_template(name string, content string) {
|
func add_word_filter(id int, find string, replacement string) {
|
||||||
err := write_file("./template_" + name + ".go", content)
|
wordFilters := wordFilterBox.Load().(WordFilterBox)
|
||||||
if err != nil {
|
wordFilters[id] = WordFilter{ID:id,Find:find,Replacement:replacement}
|
||||||
log.Fatal(err)
|
wordFilterBox.Store(wordFilters)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init_templates() {
|
|
||||||
if dev.DebugMode {
|
|
||||||
log.Print("Initialising the template system")
|
|
||||||
}
|
|
||||||
compile_templates()
|
|
||||||
|
|
||||||
// TO-DO: Add support for 64-bit integers
|
|
||||||
// TO-DO: Add support for floats
|
|
||||||
fmap := make(map[string]interface{})
|
|
||||||
fmap["add"] = func(left interface{}, right interface{})interface{} {
|
|
||||||
var left_int int
|
|
||||||
var right_int int
|
|
||||||
switch left := left.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
|
||||||
}
|
|
||||||
switch right := right.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
|
||||||
}
|
|
||||||
return left_int + right_int
|
|
||||||
}
|
|
||||||
|
|
||||||
fmap["subtract"] = func(left interface{}, right interface{})interface{} {
|
|
||||||
var left_int int
|
|
||||||
var right_int int
|
|
||||||
switch left := left.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
|
||||||
}
|
|
||||||
switch right := right.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
|
||||||
}
|
|
||||||
return left_int - right_int
|
|
||||||
}
|
|
||||||
|
|
||||||
fmap["multiply"] = func(left interface{}, right interface{})interface{} {
|
|
||||||
var left_int int
|
|
||||||
var right_int int
|
|
||||||
switch left := left.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
|
||||||
}
|
|
||||||
switch right := right.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
|
||||||
}
|
|
||||||
return left_int * right_int
|
|
||||||
}
|
|
||||||
|
|
||||||
fmap["divide"] = func(left interface{}, right interface{})interface{} {
|
|
||||||
var left_int int
|
|
||||||
var right_int int
|
|
||||||
switch left := left.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
|
||||||
}
|
|
||||||
switch right := right.(type) {
|
|
||||||
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
|
||||||
}
|
|
||||||
if left_int == 0 || right_int == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return left_int / right_int
|
|
||||||
}
|
|
||||||
|
|
||||||
// The interpreted templates...
|
|
||||||
if dev.DebugMode {
|
|
||||||
log.Print("Loading the template files...")
|
|
||||||
}
|
|
||||||
templates.Funcs(fmap)
|
|
||||||
template.Must(templates.ParseGlob("templates/*"))
|
|
||||||
template.Must(templates.ParseGlob("pages/*"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func process_config() {
|
func process_config() {
|
||||||
|
@ -339,6 +146,11 @@ func main(){
|
||||||
log.Print("Initialising the authentication system")
|
log.Print("Initialising the authentication system")
|
||||||
auth = NewDefaultAuth()
|
auth = NewDefaultAuth()
|
||||||
|
|
||||||
|
err = init_word_filters()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Run this goroutine once a second
|
// Run this goroutine once a second
|
||||||
second_ticker := time.NewTicker(1 * time.Second)
|
second_ticker := time.NewTicker(1 * time.Second)
|
||||||
fifteen_minute_ticker := time.NewTicker(15 * time.Minute)
|
fifteen_minute_ticker := time.NewTicker(15 * time.Minute)
|
||||||
|
@ -347,6 +159,11 @@ func main(){
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <- second_ticker.C:
|
case <- second_ticker.C:
|
||||||
|
//log.Print("Running the second ticker")
|
||||||
|
err := handle_expired_scheduled_groups()
|
||||||
|
if err != nil {
|
||||||
|
LogError(err)
|
||||||
|
}
|
||||||
// TO-DO: Handle delayed moderation tasks
|
// TO-DO: Handle delayed moderation tasks
|
||||||
// TO-DO: Handle the daily clean-up. Move this to a 24 hour task?
|
// TO-DO: Handle the daily clean-up. Move this to a 24 hour task?
|
||||||
// TO-DO: Sync with the database, if there are any changes
|
// TO-DO: Sync with the database, if there are any changes
|
||||||
|
@ -354,9 +171,9 @@ func main(){
|
||||||
// TO-DO: Alert the admin, if CPU usage, RAM usage, or the number of posts in the past second are too high
|
// TO-DO: Alert the admin, if CPU usage, RAM usage, or the number of posts in the past second are too high
|
||||||
// TO-DO: Clean-up alerts with no unread matches which are over two weeks old. Move this to a 24 hour task?
|
// TO-DO: Clean-up alerts with no unread matches which are over two weeks old. Move this to a 24 hour task?
|
||||||
case <- fifteen_minute_ticker.C:
|
case <- fifteen_minute_ticker.C:
|
||||||
// TO-DO: Handle temporary bans.
|
|
||||||
// TO-DO: Automatically lock topics, if they're really old, and the associated setting is enabled.
|
// TO-DO: Automatically lock topics, if they're really old, and the associated setting is enabled.
|
||||||
// TO-DO: Publish scheduled posts. Move this to a 15 minute task?
|
// TO-DO: Publish scheduled posts.
|
||||||
|
// TO-DO: Delete the empty users_groups_scheduler entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -409,8 +226,8 @@ func main(){
|
||||||
router.HandleFunc("/profile/reply/create/", route_profile_reply_create)
|
router.HandleFunc("/profile/reply/create/", route_profile_reply_create)
|
||||||
router.HandleFunc("/profile/reply/edit/submit/", route_profile_reply_edit_submit)
|
router.HandleFunc("/profile/reply/edit/submit/", route_profile_reply_edit_submit)
|
||||||
router.HandleFunc("/profile/reply/delete/submit/", route_profile_reply_delete_submit)
|
router.HandleFunc("/profile/reply/delete/submit/", route_profile_reply_delete_submit)
|
||||||
//router.HandleFunc("/user/edit/submit/", route_logout)
|
//router.HandleFunc("/user/edit/submit/", route_logout) // route_logout? what on earth? o.o
|
||||||
router.HandleFunc("/users/ban/", route_ban)
|
//router.HandleFunc("/users/ban/", route_ban)
|
||||||
router.HandleFunc("/users/ban/submit/", route_ban_submit)
|
router.HandleFunc("/users/ban/submit/", route_ban_submit)
|
||||||
router.HandleFunc("/users/unban/", route_unban)
|
router.HandleFunc("/users/unban/", route_unban)
|
||||||
router.HandleFunc("/users/activate/", route_activate)
|
router.HandleFunc("/users/activate/", route_activate)
|
||||||
|
|
|
@ -521,7 +521,8 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func route_ban(w http.ResponseWriter, r *http.Request, user User) {
|
// TO-DO: This is being replaced with the new ban route system
|
||||||
|
/*func route_ban(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
headerVars, ok := SessionCheck(w,r,&user)
|
headerVars, ok := SessionCheck(w,r,&user)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
|
@ -557,7 +558,7 @@ func route_ban(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templates.ExecuteTemplate(w,"areyousure.html",pi)
|
templates.ExecuteTemplate(w,"areyousure.html",pi)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) {
|
func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
if !user.Perms.BanUsers {
|
if !user.Perms.BanUsers {
|
||||||
|
@ -575,13 +576,11 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
/*if uid == -2 {
|
/*if uid == -2 {
|
||||||
LocalError("Sigh, are you really trying to ban me? Do you despise so much? Despite all of our adventures over at /arcane-tower/...?",w,r,user)
|
LocalError("Stop trying to ban Merlin! Ban admin! Bad! No!",w,r,user)
|
||||||
return
|
return
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
var group int
|
targetUser, err := users.CascadeGet(uid)
|
||||||
var is_super_admin bool
|
|
||||||
err = get_user_rank_stmt.QueryRow(uid).Scan(&group, &is_super_admin)
|
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
LocalError("The user you're trying to ban no longer exists.",w,r,user)
|
LocalError("The user you're trying to ban no longer exists.",w,r,user)
|
||||||
return
|
return
|
||||||
|
@ -590,7 +589,7 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_super_admin || groups[group].Is_Admin || groups[group].Is_Mod {
|
if targetUser.Is_Super_Admin || targetUser.Is_Admin || targetUser.Is_Mod {
|
||||||
LocalError("You may not ban another staff member.",w,r,user)
|
LocalError("You may not ban another staff member.",w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -599,13 +598,45 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if groups[group].Is_Banned {
|
if targetUser.Is_Banned {
|
||||||
LocalError("The user you're trying to unban is already banned.",w,r,user)
|
LocalError("The user you're trying to unban is already banned.",w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = change_group_stmt.Exec(4, uid)
|
duration_days, err := strconv.Atoi(r.FormValue("ban-duration-days"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
LocalError("You can only use whole numbers for the number of days",w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
duration_weeks, err := strconv.Atoi(r.FormValue("ban-duration-weeks"))
|
||||||
|
if err != nil {
|
||||||
|
LocalError("You can only use whole numbers for the number of weeks",w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
duration_months, err := strconv.Atoi(r.FormValue("ban-duration-months"))
|
||||||
|
if err != nil {
|
||||||
|
LocalError("You can only use whole numbers for the number of months",w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var duration time.Duration
|
||||||
|
if duration_days > 1 && duration_weeks > 1 && duration_months > 1 {
|
||||||
|
duration, _ = time.ParseDuration("0")
|
||||||
|
} else {
|
||||||
|
var seconds int
|
||||||
|
seconds += duration_days * day
|
||||||
|
seconds += duration_weeks * week
|
||||||
|
seconds += duration_months * month
|
||||||
|
duration, _ = time.ParseDuration(strconv.Itoa(seconds) + "s")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = targetUser.Ban(duration,user.ID)
|
||||||
|
if err == ErrNoRows {
|
||||||
|
LocalError("The user you're trying to ban no longer exists.",w,r,user)
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
InternalError(err,w)
|
InternalError(err,w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -621,11 +652,6 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = users.Load(uid)
|
|
||||||
if err != nil {
|
|
||||||
LocalError("This user no longer exists!",w,r,user)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther)
|
http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,8 +671,7 @@ func route_unban(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var group int
|
targetUser, err := users.CascadeGet(uid)
|
||||||
err = get_user_group_stmt.QueryRow(uid).Scan(&group)
|
|
||||||
if err == ErrNoRows {
|
if err == ErrNoRows {
|
||||||
LocalError("The user you're trying to unban no longer exists.",w,r,user)
|
LocalError("The user you're trying to unban no longer exists.",w,r,user)
|
||||||
return
|
return
|
||||||
|
@ -655,13 +680,16 @@ func route_unban(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !groups[group].Is_Banned {
|
if !targetUser.Is_Banned {
|
||||||
LocalError("The user you're trying to unban isn't banned.",w,r,user)
|
LocalError("The user you're trying to unban isn't banned.",w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = change_group_stmt.Exec(config.DefaultGroup, uid)
|
err = targetUser.Unban()
|
||||||
if err != nil {
|
if err == ErrNoRows {
|
||||||
|
LocalError("The user you're trying to unban no longer exists.",w,r,user)
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
InternalError(err,w)
|
InternalError(err,w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -677,15 +705,6 @@ func route_unban(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = users.Load(uid)
|
|
||||||
if err != nil && err == ErrNoRows {
|
|
||||||
LocalError("This user no longer exists!",w,r,user)
|
|
||||||
return
|
|
||||||
} else if err != nil {
|
|
||||||
InternalError(err,w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther)
|
http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
pages.go
7
pages.go
|
@ -120,6 +120,7 @@ type PanelStats struct
|
||||||
Groups int
|
Groups int
|
||||||
Forums int
|
Forums int
|
||||||
Settings int
|
Settings int
|
||||||
|
WordFilters int
|
||||||
Themes int
|
Themes int
|
||||||
Reports int
|
Reports int
|
||||||
}
|
}
|
||||||
|
@ -463,6 +464,12 @@ func parse_message(msg string/*, user User*/) string {
|
||||||
msg = strings.Replace(msg,":o","😲",-1)
|
msg = strings.Replace(msg,":o","😲",-1)
|
||||||
//msg = url_reg.ReplaceAllString(msg,"<a href=\"$2$3//$4\" rel=\"nofollow\">$2$3//$4</a>")
|
//msg = url_reg.ReplaceAllString(msg,"<a href=\"$2$3//$4\" rel=\"nofollow\">$2$3//$4</a>")
|
||||||
|
|
||||||
|
// Word filter list. E.g. Swear words and other things the admins don't like
|
||||||
|
wordFilters := wordFilterBox.Load().(WordFilterBox)
|
||||||
|
for _, filter := range wordFilters {
|
||||||
|
msg = strings.Replace(msg,filter.Find,filter.Replacement,-1)
|
||||||
|
}
|
||||||
|
|
||||||
// Search for URLs, mentions and hashlinks in the messages...
|
// Search for URLs, mentions and hashlinks in the messages...
|
||||||
//log.Print("Parser Loop!")
|
//log.Print("Parser Loop!")
|
||||||
var msgbytes = []byte(msg)
|
var msgbytes = []byte(msg)
|
||||||
|
|
178
panel_routes.go
178
panel_routes.go
|
@ -722,6 +722,184 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, user User,
|
||||||
http.Redirect(w,r,"/panel/settings/",http.StatusSeeOther)
|
http.Redirect(w,r,"/panel/settings/",http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func route_panel_word_filters(w http.ResponseWriter, r *http.Request, user User){
|
||||||
|
headerVars, stats, ok := PanelSessionCheck(w,r,&user)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.Perms.EditSettings {
|
||||||
|
NoPermissions(w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var filterList WordFilterBox = wordFilterBox.Load().(WordFilterBox)
|
||||||
|
pi := PanelPage{"Word Filter Manager",user,headerVars,stats,tList,filterList}
|
||||||
|
if pre_render_hooks["pre_render_panel_word_filters"] != nil {
|
||||||
|
if run_pre_render_hook("pre_render_panel_word_filters", w, r, &user, &pi) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,"panel-word-filters.html",pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_panel_word_filters_create(w http.ResponseWriter, r *http.Request, user User){
|
||||||
|
_, ok := SimplePanelSessionCheck(w,r,&user)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.Perms.EditSettings {
|
||||||
|
NoPermissions(w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
PreError("Bad Form",w,r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
is_js := r.PostFormValue("js")
|
||||||
|
if is_js == "" {
|
||||||
|
is_js = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
find := strings.TrimSpace(r.PostFormValue("find"))
|
||||||
|
if find == "" {
|
||||||
|
LocalErrorJSQ("You need to specify what word you want to match",w,r,user,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement
|
||||||
|
replacement := strings.TrimSpace(r.PostFormValue("replacement"))
|
||||||
|
|
||||||
|
res, err := create_word_filter_stmt.Exec(find,replacement)
|
||||||
|
if err != nil {
|
||||||
|
InternalErrorJSQ(err,w,r,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastId, err := res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
InternalErrorJSQ(err,w,r,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
add_word_filter(int(lastId),find,replacement)
|
||||||
|
http.Redirect(w,r,"/panel/settings/word-filters/",http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_panel_word_filters_edit(w http.ResponseWriter, r *http.Request, user User, wfid string){
|
||||||
|
headerVars, stats, ok := PanelSessionCheck(w,r,&user)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.Perms.EditSettings {
|
||||||
|
NoPermissions(w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = wfid
|
||||||
|
|
||||||
|
pi := PanelPage{"Edit Word Filter",user,headerVars,stats,tList,nil}
|
||||||
|
if pre_render_hooks["pre_render_panel_word_filters_edit"] != nil {
|
||||||
|
if run_pre_render_hook("pre_render_panel_word_filters_edit", w, r, &user, &pi) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,"panel-word-filters-edit.html",pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_panel_word_filters_edit_submit(w http.ResponseWriter, r *http.Request, user User, wfid string){
|
||||||
|
_, ok := SimplePanelSessionCheck(w,r,&user)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
PreError("Bad Form",w,r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
is_js := r.PostFormValue("is_js")
|
||||||
|
if is_js == "" {
|
||||||
|
is_js = "0"
|
||||||
|
}
|
||||||
|
if !user.Perms.EditSettings {
|
||||||
|
NoPermissionsJSQ(w,r,user,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.Atoi(wfid)
|
||||||
|
if err != nil {
|
||||||
|
LocalErrorJSQ("The word filter ID must be an integer.",w,r,user,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
find := strings.TrimSpace(r.PostFormValue("find"))
|
||||||
|
if find == "" {
|
||||||
|
LocalErrorJSQ("You need to specify what word you want to match",w,r,user,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement
|
||||||
|
replacement := strings.TrimSpace(r.PostFormValue("replacement"))
|
||||||
|
|
||||||
|
_, err = update_word_filter_stmt.Exec(find,replacement,id)
|
||||||
|
if err != nil {
|
||||||
|
InternalErrorJSQ(err,w,r,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wordFilters := wordFilterBox.Load().(WordFilterBox)
|
||||||
|
wordFilters[id] = WordFilter{ID:id,Find:find,Replacement:replacement}
|
||||||
|
wordFilterBox.Store(wordFilters)
|
||||||
|
|
||||||
|
http.Redirect(w,r,"/panel/settings/word-filters/",http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_panel_word_filters_delete_submit(w http.ResponseWriter, r *http.Request, user User, wfid string){
|
||||||
|
_, ok := SimplePanelSessionCheck(w,r,&user)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
PreError("Bad Form",w,r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
is_js := r.PostFormValue("is_js")
|
||||||
|
if is_js == "" {
|
||||||
|
is_js = "0"
|
||||||
|
}
|
||||||
|
if !user.Perms.EditSettings {
|
||||||
|
NoPermissionsJSQ(w,r,user,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := strconv.Atoi(wfid)
|
||||||
|
if err != nil {
|
||||||
|
LocalErrorJSQ("The word filter ID must be an integer.",w,r,user,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = delete_word_filter_stmt.Exec(id)
|
||||||
|
if err != nil {
|
||||||
|
InternalErrorJSQ(err,w,r,is_js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wordFilters := wordFilterBox.Load().(WordFilterBox)
|
||||||
|
delete(wordFilters,id)
|
||||||
|
wordFilterBox.Store(wordFilters)
|
||||||
|
|
||||||
|
http.Redirect(w,r,"/panel/settings/word-filters/",http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
func route_panel_plugins(w http.ResponseWriter, r *http.Request, user User){
|
func route_panel_plugins(w http.ResponseWriter, r *http.Request, user User){
|
||||||
headerVars, stats, ok := PanelSessionCheck(w,r,&user)
|
headerVars, stats, ok := PanelSessionCheck(w,r,&user)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -284,6 +284,7 @@ $(document).ready(function(){
|
||||||
$(".edit_fields").click(function(event)
|
$(".edit_fields").click(function(event)
|
||||||
{
|
{
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
if($(this).find("input").length !== 0) return;
|
||||||
//console.log("clicked .edit_fields");
|
//console.log("clicked .edit_fields");
|
||||||
var block_parent = $(this).closest('.editable_parent');
|
var block_parent = $(this).closest('.editable_parent');
|
||||||
//console.log(block_parent);
|
//console.log(block_parent);
|
||||||
|
@ -353,6 +354,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
// This one's for Tempra Conflux
|
// This one's for Tempra Conflux
|
||||||
|
// TO-DO: We might want to use pure JS here
|
||||||
$(".ip_item").each(function(){
|
$(".ip_item").each(function(){
|
||||||
var ip = this.textContent;
|
var ip = this.textContent;
|
||||||
if(ip.length > 10){
|
if(ip.length > 10){
|
||||||
|
|
|
@ -110,6 +110,7 @@ func create_tables(adapter qgen.DB_Adapter) error {
|
||||||
qgen.DB_Table_Column{"megaposts","int",0,false,false,"0"},
|
qgen.DB_Table_Column{"megaposts","int",0,false,false,"0"},
|
||||||
qgen.DB_Table_Column{"topics","int",0,false,false,"0"},
|
qgen.DB_Table_Column{"topics","int",0,false,false,"0"},
|
||||||
//qgen.DB_Table_Column{"penalty_count","int",0,false,false,"0"},
|
//qgen.DB_Table_Column{"penalty_count","int",0,false,false,"0"},
|
||||||
|
qgen.DB_Table_Column{"temp_group","int",0,false,false,"0"}, // For temporary groups, set this to zero when a temporary group isn't in effect
|
||||||
},
|
},
|
||||||
[]qgen.DB_Table_Key{
|
[]qgen.DB_Table_Key{
|
||||||
qgen.DB_Table_Key{"uid","primary"},
|
qgen.DB_Table_Key{"uid","primary"},
|
||||||
|
@ -117,35 +118,63 @@ func create_tables(adapter qgen.DB_Adapter) error {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Coming Soon!
|
|
||||||
// What should we do about global penalties? Put them on the users table for speed? Or keep them here?
|
// What should we do about global penalties? Put them on the users table for speed? Or keep them here?
|
||||||
// Should we add IP Penalties?
|
// Should we add IP Penalties? No, that's a stupid idea, just implement IP Bans properly. What about shadowbans?
|
||||||
|
// TO-DO: Perm overrides
|
||||||
|
// TO-DO: Add a mod-queue and other basic auto-mod features. This is needed for awaiting activation and the mod_queue penalty flag
|
||||||
|
// TO-DO: Add a penalty type where a user is stopped from creating plugin_socialgroups social groups
|
||||||
|
// TO-DO: Shadow bans. We will probably have a CanShadowBan permission for this, as we *really* don't want people using this lightly.
|
||||||
/*qgen.Install.CreateTable("users_penalties","","",
|
/*qgen.Install.CreateTable("users_penalties","","",
|
||||||
[]qgen.DB_Table_Column{
|
[]qgen.DB_Table_Column{
|
||||||
qgen.DB_Table_Column{"uid","int",0,false,false,""},
|
qgen.DB_Table_Column{"uid","int",0,false,false,""},
|
||||||
qgen.DB_Table_Column{"element_id","int",0,false,false,""},
|
qgen.DB_Table_Column{"element_id","int",0,false,false,""},
|
||||||
qgen.DB_Table_Column{"element_type","varchar",50,false,false,""}, //global,forum,profile?,social_group
|
qgen.DB_Table_Column{"element_type","varchar",50,false,false,""}, //forum, profile?, and social_group. Leave blank for global.
|
||||||
qgen.DB_Table_Column{"overrides","text",0,false,false,"{}"}, // Perm overrides. Coming Soon
|
qgen.DB_Table_Column{"overrides","text",0,false,false,"{}"},
|
||||||
qgen.DB_Table_Column{"mod_queue","boolean",0,false,false,"0"}, // All of this user's posts will go through the mod_queue. Coming Soon
|
|
||||||
// TO-DO: Add a mod-queue and other basic auto-mod features. This is needed for awaiting activation and the mod_queue penalty flag
|
|
||||||
// TO-DO: Add a penalty type where a user is stopped from creating plugin_socialgroups social groups
|
|
||||||
|
|
||||||
qgen.DB_Table_Column{"shadow_ban","boolean",0,false,false,"0"}, // Coming Soon. CanShadowBan permission.
|
qgen.DB_Table_Column{"mod_queue","boolean",0,false,false,"0"},
|
||||||
|
qgen.DB_Table_Column{"shadow_ban","boolean",0,false,false,"0"},
|
||||||
qgen.DB_Table_Column{"no_avatar","boolean",0,false,false,"0"}, // Coming Soon. Should this be a perm override instead?
|
qgen.DB_Table_Column{"no_avatar","boolean",0,false,false,"0"}, // Coming Soon. Should this be a perm override instead?
|
||||||
|
|
||||||
//qgen.DB_Table_Column{"posts_per_hour","int",0,false,false,"0"}, // Rate-limit penalty type. Coming soon
|
// Do we *really* need rate-limit penalty types? Are we going to be allowing bots or something?
|
||||||
//qgen.DB_Table_Column{"topics_per_hour","int",0,false,false,"0"}, // Coming Soon
|
//qgen.DB_Table_Column{"posts_per_hour","int",0,false,false,"0"},
|
||||||
|
//qgen.DB_Table_Column{"topics_per_hour","int",0,false,false,"0"},
|
||||||
//qgen.DB_Table_Column{"posts_count","int",0,false,false,"0"}, // Coming soon
|
//qgen.DB_Table_Column{"posts_count","int",0,false,false,"0"},
|
||||||
//qgen.DB_Table_Column{"topic_count","int",0,false,false,"0"}, // Coming Soon
|
//qgen.DB_Table_Column{"topic_count","int",0,false,false,"0"},
|
||||||
//qgen.DB_Table_Column{"last_hour","int",0,false,false,"0"}, // UNIX Time, as we don't need to do anything too fancy here. When an hour has elapsed since that time, reset the hourly penalty counters.
|
//qgen.DB_Table_Column{"last_hour","int",0,false,false,"0"}, // UNIX Time, as we don't need to do anything too fancy here. When an hour has elapsed since that time, reset the hourly penalty counters.
|
||||||
|
|
||||||
qgen.DB_Table_Column{"issued_by","int",0,false,false,""},
|
qgen.DB_Table_Column{"issued_by","int",0,false,false,""},
|
||||||
qgen.DB_Table_Column{"issued_at","createdAt",0,false,false,""},
|
qgen.DB_Table_Column{"issued_at","createdAt",0,false,false,""},
|
||||||
qgen.DB_Table_Column{"expiry","duration",0,false,false,""}, // TO-DO: Implement the duration parsing code on the adapter side
|
qgen.DB_Table_Column{"expires_at","datetime",0,false,false,""},
|
||||||
},
|
},
|
||||||
[]qgen.DB_Table_Key{},
|
[]qgen.DB_Table_Key{},
|
||||||
)*/
|
)*/
|
||||||
|
|
||||||
|
qgen.Install.CreateTable("users_groups_scheduler","","",
|
||||||
|
[]qgen.DB_Table_Column{
|
||||||
|
qgen.DB_Table_Column{"uid","int",0,false,false,""},
|
||||||
|
qgen.DB_Table_Column{"set_group","int",0,false,false,""},
|
||||||
|
|
||||||
|
qgen.DB_Table_Column{"issued_by","int",0,false,false,""},
|
||||||
|
qgen.DB_Table_Column{"issued_at","createdAt",0,false,false,""},
|
||||||
|
qgen.DB_Table_Column{"revert_at","datetime",0,false,false,""},
|
||||||
|
qgen.DB_Table_Column{"temporary","boolean",0,false,false,""}, // special case for permanent bans to do the necessary bookkeeping, might be removed in the future
|
||||||
|
},
|
||||||
|
[]qgen.DB_Table_Key{
|
||||||
|
qgen.DB_Table_Key{"uid","primary"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
qgen.Install.CreateTable("word_filters","","",
|
||||||
|
[]qgen.DB_Table_Column{
|
||||||
|
qgen.DB_Table_Column{"wfid","int",0,false,true,""},
|
||||||
|
qgen.DB_Table_Column{"find","varchar",200,false,false,""},
|
||||||
|
qgen.DB_Table_Column{"replacement","varchar",200,false,false,""},
|
||||||
|
},
|
||||||
|
[]qgen.DB_Table_Key{
|
||||||
|
qgen.DB_Table_Key{"wfid","primary"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +223,8 @@ func write_selects(adapter qgen.DB_Adapter) error {
|
||||||
|
|
||||||
adapter.SimpleSelect("get_users_offset","users","uid, name, group, active, is_super_admin, avatar","","","?,?")
|
adapter.SimpleSelect("get_users_offset","users","uid, name, group, active, is_super_admin, avatar","","","?,?")
|
||||||
|
|
||||||
|
adapter.SimpleSelect("get_word_filters","word_filters","wfid, find, replacement","","","")
|
||||||
|
|
||||||
adapter.SimpleSelect("is_theme_default","themes","default","uname = ?","","")
|
adapter.SimpleSelect("is_theme_default","themes","default","uname = ?","","")
|
||||||
|
|
||||||
adapter.SimpleSelect("get_modlogs","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","","","")
|
adapter.SimpleSelect("get_modlogs","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","","","")
|
||||||
|
@ -212,12 +243,8 @@ func write_selects(adapter qgen.DB_Adapter) error {
|
||||||
|
|
||||||
adapter.SimpleSelect("get_user_name","users","name","uid = ?","","")
|
adapter.SimpleSelect("get_user_name","users","name","uid = ?","","")
|
||||||
|
|
||||||
adapter.SimpleSelect("get_user_rank","users","group, is_super_admin","uid = ?","","")
|
|
||||||
|
|
||||||
adapter.SimpleSelect("get_user_active","users","active","uid = ?","","")
|
adapter.SimpleSelect("get_user_active","users","active","uid = ?","","")
|
||||||
|
|
||||||
adapter.SimpleSelect("get_user_group","users","group","uid = ?","","")
|
|
||||||
|
|
||||||
adapter.SimpleSelect("get_emails_by_user","emails","email, validated, token","uid = ?","","")
|
adapter.SimpleSelect("get_emails_by_user","emails","email, validated, token","uid = ?","","")
|
||||||
|
|
||||||
adapter.SimpleSelect("get_topic_basic","topics","title, content","tid = ?","","")
|
adapter.SimpleSelect("get_topic_basic","topics","title, content","tid = ?","","")
|
||||||
|
@ -230,6 +257,8 @@ func write_selects(adapter qgen.DB_Adapter) error {
|
||||||
|
|
||||||
adapter.SimpleSelect("get_forum_topics_offset","topics","tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount","parentID = ?","sticky DESC, lastReplyAt DESC, createdBy DESC","?,?")
|
adapter.SimpleSelect("get_forum_topics_offset","topics","tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount","parentID = ?","sticky DESC, lastReplyAt DESC, createdBy DESC","?,?")
|
||||||
|
|
||||||
|
adapter.SimpleSelect("get_expired_scheduled_groups","users_groups_scheduler","uid","UTC_TIMESTAMP() > revert_at AND temporary = 1","","")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,12 +322,16 @@ func write_inserts(adapter qgen.DB_Adapter) error {
|
||||||
|
|
||||||
adapter.SimpleInsert("add_adminlog_entry","administration_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,UTC_TIMESTAMP()")
|
adapter.SimpleInsert("add_adminlog_entry","administration_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,UTC_TIMESTAMP()")
|
||||||
|
|
||||||
|
adapter.SimpleInsert("create_word_filter","word_filters","find, replacement","?,?")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func write_replaces(adapter qgen.DB_Adapter) error {
|
func write_replaces(adapter qgen.DB_Adapter) error {
|
||||||
adapter.SimpleReplace("add_forum_perms_to_group","forums_permissions","gid,fid,preset,permissions","?,?,?,?")
|
adapter.SimpleReplace("add_forum_perms_to_group","forums_permissions","gid,fid,preset,permissions","?,?,?,?")
|
||||||
|
|
||||||
|
adapter.SimpleReplace("replace_schedule_group","users_groups_scheduler","uid, set_group, issued_by, issued_at, revert_at, temporary","?,?,?,UTC_TIMESTAMP(),?,?")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +409,11 @@ func write_updates(adapter qgen.DB_Adapter) error {
|
||||||
|
|
||||||
adapter.SimpleUpdate("update_email","emails","email = ?, uid = ?, validated = ?, token = ?","email = ?")
|
adapter.SimpleUpdate("update_email","emails","email = ?, uid = ?, validated = ?, token = ?","email = ?")
|
||||||
|
|
||||||
adapter.SimpleUpdate("verify_email","emails","validated = 1, token = ''","email = ?") // Need to fix this: Empty string isn't working, it gets set to 1 instead x.x
|
adapter.SimpleUpdate("verify_email","emails","validated = 1, token = ''","email = ?") // Need to fix this: Empty string isn't working, it gets set to 1 instead x.x -- Has this been fixed?
|
||||||
|
|
||||||
|
adapter.SimpleUpdate("set_temp_group","users","temp_group = ?","uid = ?")
|
||||||
|
|
||||||
|
adapter.SimpleUpdate("update_word_filter","word_filters","find = ?, replacement = ?","wfid = ?")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -392,9 +429,10 @@ func write_deletes(adapter qgen.DB_Adapter) error {
|
||||||
adapter.SimpleDelete("delete_forum_perms_by_forum","forums_permissions","fid = ?")
|
adapter.SimpleDelete("delete_forum_perms_by_forum","forums_permissions","fid = ?")
|
||||||
|
|
||||||
adapter.SimpleDelete("delete_activity_stream_match","activity_stream_matches","watcher = ? AND asid = ?")
|
adapter.SimpleDelete("delete_activity_stream_match","activity_stream_matches","watcher = ? AND asid = ?")
|
||||||
|
|
||||||
//adapter.SimpleDelete("delete_activity_stream_matches_by_watcher","activity_stream_matches","watcher = ?")
|
//adapter.SimpleDelete("delete_activity_stream_matches_by_watcher","activity_stream_matches","watcher = ?")
|
||||||
|
|
||||||
|
adapter.SimpleDelete("delete_word_filter","word_filters","wfid = ?")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,12 @@ func routes() {
|
||||||
Route{"route_panel_setting","/panel/settings/edit/","",[]string{"extra_data"}},
|
Route{"route_panel_setting","/panel/settings/edit/","",[]string{"extra_data"}},
|
||||||
Route{"route_panel_setting_edit","/panel/settings/edit/submit/","",[]string{"extra_data"}},
|
Route{"route_panel_setting_edit","/panel/settings/edit/submit/","",[]string{"extra_data"}},
|
||||||
|
|
||||||
|
Route{"route_panel_word_filters","/panel/settings/word-filters/","",[]string{}},
|
||||||
|
Route{"route_panel_word_filters_create","/panel/settings/word-filters/create/","",[]string{}},
|
||||||
|
Route{"route_panel_word_filters_edit","/panel/settings/word-filters/edit/","",[]string{"extra_data"}},
|
||||||
|
Route{"route_panel_word_filters_edit_submit","/panel/settings/word-filters/edit/submit/","",[]string{"extra_data"}},
|
||||||
|
Route{"route_panel_word_filters_delete_submit","/panel/settings/word-filters/delete/submit/","",[]string{"extra_data"}},
|
||||||
|
|
||||||
Route{"route_panel_themes","/panel/themes/","",[]string{}},
|
Route{"route_panel_themes","/panel/themes/","",[]string{}},
|
||||||
Route{"route_panel_themes_default","/panel/themes/default/","",[]string{"extra_data"}},
|
Route{"route_panel_themes_default","/panel/themes/default/","",[]string{"extra_data"}},
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ CREATE TABLE `users` (
|
||||||
`bigposts` int DEFAULT 0 not null,
|
`bigposts` int DEFAULT 0 not null,
|
||||||
`megaposts` int DEFAULT 0 not null,
|
`megaposts` int DEFAULT 0 not null,
|
||||||
`topics` int DEFAULT 0 not null,
|
`topics` int DEFAULT 0 not null,
|
||||||
|
`temp_group` int DEFAULT 0 not null,
|
||||||
primary key(`uid`),
|
primary key(`uid`),
|
||||||
unique(`name`)
|
unique(`name`)
|
||||||
) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
|
) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE `users_groups_scheduler` (
|
||||||
|
`uid` int not null,
|
||||||
|
`set_group` int not null,
|
||||||
|
`issued_by` int not null,
|
||||||
|
`issued_at` datetime not null,
|
||||||
|
`revert_at` datetime not null,
|
||||||
|
`temporary` boolean not null,
|
||||||
|
primary key(`uid`)
|
||||||
|
);
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE `word_filters` (
|
||||||
|
`wfid` int not null AUTO_INCREMENT,
|
||||||
|
`find` varchar(200) not null,
|
||||||
|
`replacement` varchar(200) not null,
|
||||||
|
primary key(`wfid`)
|
||||||
|
);
|
|
@ -21,6 +21,7 @@ CREATE TABLE `users` (
|
||||||
`bigposts` int DEFAULT 0 not null,
|
`bigposts` int DEFAULT 0 not null,
|
||||||
`megaposts` int DEFAULT 0 not null,
|
`megaposts` int DEFAULT 0 not null,
|
||||||
`topics` int DEFAULT 0 not null,
|
`topics` int DEFAULT 0 not null,
|
||||||
|
`temp_group` int DEFAULT 0 not null,
|
||||||
primary key(`uid`),
|
primary key(`uid`),
|
||||||
unique(`name`)
|
unique(`name`)
|
||||||
);
|
);
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE `users_groups_scheduler` (
|
||||||
|
`uid` int not null,
|
||||||
|
`set_group` int not null,
|
||||||
|
`issued_by` int not null,
|
||||||
|
`issued_at` timestamp not null,
|
||||||
|
`revert_at` timestamp not null,
|
||||||
|
`temporary` boolean not null,
|
||||||
|
primary key(`uid`)
|
||||||
|
);
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE `word_filters` (
|
||||||
|
`wfid` serial not null,
|
||||||
|
`find` varchar (200) not null,
|
||||||
|
`replacement` varchar (200) not null,
|
||||||
|
primary key(`wfid`)
|
||||||
|
);
|
|
@ -0,0 +1,29 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func handle_expired_scheduled_groups() error {
|
||||||
|
rows, err := get_expired_scheduled_groups_stmt.Query()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var uid int
|
||||||
|
for rows.Next() {
|
||||||
|
err := rows.Scan(&uid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = replace_schedule_group_stmt.Exec(uid, 0, 0, time.Now(), false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = set_temp_group_stmt.Exec(0,uid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_ = users.Load(uid)
|
||||||
|
}
|
||||||
|
return rows.Err()
|
||||||
|
}
|
|
@ -0,0 +1,244 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
import "html/template"
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
var templates = template.New("")
|
||||||
|
|
||||||
|
func interpreted_topic_template(pi TopicPage, w http.ResponseWriter) {
|
||||||
|
mapping, ok := themes[defaultTheme].TemplatesMap["topic"]
|
||||||
|
if !ok {
|
||||||
|
mapping = "topic"
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var template_topic_handle func(TopicPage,http.ResponseWriter) = interpreted_topic_template
|
||||||
|
var template_topic_alt_handle func(TopicPage,http.ResponseWriter) = interpreted_topic_template
|
||||||
|
|
||||||
|
var template_topics_handle func(TopicsPage,http.ResponseWriter) = func(pi TopicsPage, w http.ResponseWriter) {
|
||||||
|
mapping, ok := themes[defaultTheme].TemplatesMap["topics"]
|
||||||
|
if !ok {
|
||||||
|
mapping = "topics"
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var template_forum_handle func(ForumPage,http.ResponseWriter) = func(pi ForumPage, w http.ResponseWriter) {
|
||||||
|
mapping, ok := themes[defaultTheme].TemplatesMap["forum"]
|
||||||
|
if !ok {
|
||||||
|
mapping = "forum"
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var template_forums_handle func(ForumsPage,http.ResponseWriter) = func(pi ForumsPage, w http.ResponseWriter) {
|
||||||
|
mapping, ok := themes[defaultTheme].TemplatesMap["forums"]
|
||||||
|
if !ok {
|
||||||
|
mapping = "forums"
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var template_profile_handle func(ProfilePage,http.ResponseWriter) = func(pi ProfilePage, w http.ResponseWriter) {
|
||||||
|
mapping, ok := themes[defaultTheme].TemplatesMap["profile"]
|
||||||
|
if !ok {
|
||||||
|
mapping = "profile"
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var template_create_topic_handle func(CreateTopicPage,http.ResponseWriter) = func(pi CreateTopicPage, w http.ResponseWriter) {
|
||||||
|
mapping, ok := themes[defaultTheme].TemplatesMap["create-topic"]
|
||||||
|
if !ok {
|
||||||
|
mapping = "create-topic"
|
||||||
|
}
|
||||||
|
err := templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func compile_templates() error {
|
||||||
|
var c CTemplateSet
|
||||||
|
user := User{62,build_profile_url("fake-user",62),"Fake User","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"0.0.0.0.0",0}
|
||||||
|
// TO-DO: Do a more accurate level calculation for this?
|
||||||
|
user2 := User{1,build_profile_url("admin-alice",1),"Admin Alice","alice@localhost",1,true,true,true,true,false,false,AllPerms,make(map[string]bool),"",true,"","","","","",58,1000,"127.0.0.1",0}
|
||||||
|
user3 := User{2,build_profile_url("admin-fred",62),"Admin Fred","fred@localhost",1,true,true,true,true,false,false,AllPerms,make(map[string]bool),"",true,"","","","","",42,900,"::1",0}
|
||||||
|
headerVars := HeaderVars{
|
||||||
|
Site: site,
|
||||||
|
NoticeList: []string{"test"},
|
||||||
|
Stylesheets: []string{"panel"},
|
||||||
|
Scripts: []string{"whatever"},
|
||||||
|
Widgets: PageWidgets{
|
||||||
|
LeftSidebar: template.HTML("lalala"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Compiling the templates")
|
||||||
|
|
||||||
|
topic := TopicUser{1,"blah","Blah","Hey there!",0,false,false,"Date","Date",0,"","127.0.0.1",0,1,"classname","weird-data",build_profile_url("fake-user",62),"Fake User",config.DefaultGroup,"",0,"","","","",58,false}
|
||||||
|
var replyList []Reply
|
||||||
|
replyList = append(replyList, Reply{0,0,"Yo!","Yo!",0,"alice","Alice",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""})
|
||||||
|
|
||||||
|
var varList map[string]VarItem = make(map[string]VarItem)
|
||||||
|
tpage := TopicPage{"Title",user,headerVars,replyList,topic,1,1,extData}
|
||||||
|
topic_id_tmpl, err := c.compile_template("topic.html","templates/","TopicPage", tpage, varList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
topic_id_alt_tmpl, err := c.compile_template("topic_alt.html","templates/","TopicPage", tpage, varList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
varList = make(map[string]VarItem)
|
||||||
|
ppage := ProfilePage{"User 526",user,headerVars,replyList,user,extData}
|
||||||
|
profile_tmpl, err := c.compile_template("profile.html","templates/","ProfilePage", ppage, varList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var forumList []Forum
|
||||||
|
forums, err := fstore.GetAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, forum := range forums {
|
||||||
|
if forum.Active {
|
||||||
|
forumList = append(forumList,*forum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
varList = make(map[string]VarItem)
|
||||||
|
forums_page := ForumsPage{"Forum List",user,headerVars,forumList,extData}
|
||||||
|
forums_tmpl, err := c.compile_template("forums.html","templates/","ForumsPage",forums_page,varList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var topicsList []*TopicsRow
|
||||||
|
topicsList = append(topicsList,&TopicsRow{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",user3.ID,1,"","127.0.0.1",0,1,"classname","",&user2,"",0,&user3,"General","/forum/general.2"})
|
||||||
|
topics_page := TopicsPage{"Topic List",user,headerVars,topicsList,extData}
|
||||||
|
topics_tmpl, err := c.compile_template("topics.html","templates/","TopicsPage",topics_page,varList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//var topicList []TopicUser
|
||||||
|
//topicList = append(topicList,TopicUser{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",1,"","127.0.0.1",0,1,"classname","","admin-fred","Admin Fred",config.DefaultGroup,"",0,"","","","",58,false})
|
||||||
|
forum_item := Forum{1,"general","General Forum","Where the general stuff happens",true,"all",0,"",0,"","",0,"",0,""}
|
||||||
|
forum_page := ForumPage{"General Forum",user,headerVars,topicsList,forum_item,1,1,extData}
|
||||||
|
forum_tmpl, err := c.compile_template("forum.html","templates/","ForumPage",forum_page,varList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Writing the templates")
|
||||||
|
go write_template("topic", topic_id_tmpl)
|
||||||
|
go write_template("topic_alt", topic_id_alt_tmpl)
|
||||||
|
go write_template("profile", profile_tmpl)
|
||||||
|
go write_template("forums", forums_tmpl)
|
||||||
|
go write_template("topics", topics_tmpl)
|
||||||
|
go write_template("forum", forum_tmpl)
|
||||||
|
go func() {
|
||||||
|
err := write_file("./template_list.go","package main\n\n" + c.FragOut)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func write_template(name string, content string) {
|
||||||
|
err := write_file("./template_" + name + ".go", content)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init_templates() {
|
||||||
|
if dev.DebugMode {
|
||||||
|
log.Print("Initialising the template system")
|
||||||
|
}
|
||||||
|
compile_templates()
|
||||||
|
|
||||||
|
// TO-DO: Add support for 64-bit integers
|
||||||
|
// TO-DO: Add support for floats
|
||||||
|
fmap := make(map[string]interface{})
|
||||||
|
fmap["add"] = func(left interface{}, right interface{})interface{} {
|
||||||
|
var left_int int
|
||||||
|
var right_int int
|
||||||
|
switch left := left.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
||||||
|
}
|
||||||
|
switch right := right.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
||||||
|
}
|
||||||
|
return left_int + right_int
|
||||||
|
}
|
||||||
|
|
||||||
|
fmap["subtract"] = func(left interface{}, right interface{})interface{} {
|
||||||
|
var left_int int
|
||||||
|
var right_int int
|
||||||
|
switch left := left.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
||||||
|
}
|
||||||
|
switch right := right.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
||||||
|
}
|
||||||
|
return left_int - right_int
|
||||||
|
}
|
||||||
|
|
||||||
|
fmap["multiply"] = func(left interface{}, right interface{})interface{} {
|
||||||
|
var left_int int
|
||||||
|
var right_int int
|
||||||
|
switch left := left.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
||||||
|
}
|
||||||
|
switch right := right.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
||||||
|
}
|
||||||
|
return left_int * right_int
|
||||||
|
}
|
||||||
|
|
||||||
|
fmap["divide"] = func(left interface{}, right interface{})interface{} {
|
||||||
|
var left_int int
|
||||||
|
var right_int int
|
||||||
|
switch left := left.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: left_int = left.(int)
|
||||||
|
}
|
||||||
|
switch right := right.(type) {
|
||||||
|
case uint, uint8, uint16, int, int32: right_int = right.(int)
|
||||||
|
}
|
||||||
|
if left_int == 0 || right_int == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return left_int / right_int
|
||||||
|
}
|
||||||
|
|
||||||
|
// The interpreted templates...
|
||||||
|
if dev.DebugMode {
|
||||||
|
log.Print("Loading the template files...")
|
||||||
|
}
|
||||||
|
templates.Funcs(fmap)
|
||||||
|
template.Must(templates.ParseGlob("templates/*"))
|
||||||
|
template.Must(templates.ParseGlob("pages/*"))
|
||||||
|
}
|
167
template_list.go
167
template_list.go
|
@ -34,7 +34,7 @@ var menu_0 []byte = []byte(`<nav class="nav">
|
||||||
<div class="move_left">
|
<div class="move_left">
|
||||||
<div class="move_right">
|
<div class="move_right">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="menu_left menu_overview"><a href="/">`)
|
<li class="menu_left menu_overview"><a href="/" rel="home">`)
|
||||||
var menu_1 []byte = []byte(`</a></li>
|
var menu_1 []byte = []byte(`</a></li>
|
||||||
<li class="menu_left menu_forums"><a href="/forums/">Forums</a></li>
|
<li class="menu_left menu_forums"><a href="/forums/">Forums</a></li>
|
||||||
<li class="menu_left menu_topics"><a href="/">Topics</a></li>
|
<li class="menu_left menu_topics"><a href="/">Topics</a></li>
|
||||||
|
@ -77,14 +77,14 @@ var topic_0 []byte = []byte(`
|
||||||
<form id="edit_topic_form" action='/topic/edit/submit/`)
|
<form id="edit_topic_form" action='/topic/edit/submit/`)
|
||||||
var topic_1 []byte = []byte(`' method="post"></form>
|
var topic_1 []byte = []byte(`' method="post"></form>
|
||||||
`)
|
`)
|
||||||
var topic_2 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/`)
|
var topic_2 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" aria-label="Go to the previous page" rel="prev" href="/topic/`)
|
||||||
var topic_3 []byte = []byte(`?page=`)
|
var topic_3 []byte = []byte(`?page=`)
|
||||||
var topic_4 []byte = []byte(`"><</a></div>`)
|
var topic_4 []byte = []byte(`"><</a></div>`)
|
||||||
var topic_5 []byte = []byte(`<link rel="prerender" href="/topic/`)
|
var topic_5 []byte = []byte(`<link rel="prerender" href="/topic/`)
|
||||||
var topic_6 []byte = []byte(`?page=`)
|
var topic_6 []byte = []byte(`?page=`)
|
||||||
var topic_7 []byte = []byte(`" />
|
var topic_7 []byte = []byte(`" />
|
||||||
<div id="nextFloat" class="next_button">
|
<div id="nextFloat" class="next_button">
|
||||||
<a class="next_link" href="/topic/`)
|
<a class="next_link" aria-label="Go to the next page" rel="next" href="/topic/`)
|
||||||
var topic_8 []byte = []byte(`?page=`)
|
var topic_8 []byte = []byte(`?page=`)
|
||||||
var topic_9 []byte = []byte(`">></a>
|
var topic_9 []byte = []byte(`">></a>
|
||||||
</div>`)
|
</div>`)
|
||||||
|
@ -97,8 +97,8 @@ var topic_10 []byte = []byte(`
|
||||||
var topic_11 []byte = []byte(` topic_sticky_head`)
|
var topic_11 []byte = []byte(` topic_sticky_head`)
|
||||||
var topic_12 []byte = []byte(` topic_closed_head`)
|
var topic_12 []byte = []byte(` topic_closed_head`)
|
||||||
var topic_13 []byte = []byte(`">
|
var topic_13 []byte = []byte(`">
|
||||||
<a class='topic_name hide_on_edit'>`)
|
<h1 class='topic_name hide_on_edit'>`)
|
||||||
var topic_14 []byte = []byte(`</a>
|
var topic_14 []byte = []byte(`</h1>
|
||||||
`)
|
`)
|
||||||
var topic_15 []byte = []byte(`<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>`)
|
var topic_15 []byte = []byte(`<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>`)
|
||||||
var topic_16 []byte = []byte(`
|
var topic_16 []byte = []byte(`
|
||||||
|
@ -240,8 +240,8 @@ var topic_87 []byte = []byte(`
|
||||||
`)
|
`)
|
||||||
var footer_0 []byte = []byte(` </div>
|
var footer_0 []byte = []byte(` </div>
|
||||||
`)
|
`)
|
||||||
var footer_1 []byte = []byte(`<div class="sidebar">`)
|
var footer_1 []byte = []byte(`<aside class="sidebar">`)
|
||||||
var footer_2 []byte = []byte(`</div>`)
|
var footer_2 []byte = []byte(`</aside>`)
|
||||||
var footer_3 []byte = []byte(`
|
var footer_3 []byte = []byte(`
|
||||||
<div style="clear: both;"></div>
|
<div style="clear: both;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -249,13 +249,13 @@ var footer_3 []byte = []byte(`
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`)
|
`)
|
||||||
var topic_alt_0 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/`)
|
var topic_alt_0 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" aria-label="Go to the previous page" rel="prev" href="/topic/`)
|
||||||
var topic_alt_1 []byte = []byte(`?page=`)
|
var topic_alt_1 []byte = []byte(`?page=`)
|
||||||
var topic_alt_2 []byte = []byte(`"><</a></div>`)
|
var topic_alt_2 []byte = []byte(`"><</a></div>`)
|
||||||
var topic_alt_3 []byte = []byte(`<link rel="prerender" href="/topic/`)
|
var topic_alt_3 []byte = []byte(`<link rel="prerender" href="/topic/`)
|
||||||
var topic_alt_4 []byte = []byte(`?page=`)
|
var topic_alt_4 []byte = []byte(`?page=`)
|
||||||
var topic_alt_5 []byte = []byte(`" />
|
var topic_alt_5 []byte = []byte(`" />
|
||||||
<div id="nextFloat" class="next_button"><a class="next_link" href="/topic/`)
|
<div id="nextFloat" class="next_button"><a class="next_link" aria-label="Go to the next page" rel="next" href="/topic/`)
|
||||||
var topic_alt_6 []byte = []byte(`?page=`)
|
var topic_alt_6 []byte = []byte(`?page=`)
|
||||||
var topic_alt_7 []byte = []byte(`">></a></div>`)
|
var topic_alt_7 []byte = []byte(`">></a></div>`)
|
||||||
var topic_alt_8 []byte = []byte(`
|
var topic_alt_8 []byte = []byte(`
|
||||||
|
@ -269,8 +269,8 @@ var topic_alt_9 []byte = []byte(`' method="post">
|
||||||
var topic_alt_10 []byte = []byte(` topic_sticky_head`)
|
var topic_alt_10 []byte = []byte(` topic_sticky_head`)
|
||||||
var topic_alt_11 []byte = []byte(` topic_closed_head`)
|
var topic_alt_11 []byte = []byte(` topic_closed_head`)
|
||||||
var topic_alt_12 []byte = []byte(`">
|
var topic_alt_12 []byte = []byte(`">
|
||||||
<a class='topic_name hide_on_edit'>`)
|
<h1 class='topic_name hide_on_edit'>`)
|
||||||
var topic_alt_13 []byte = []byte(`</a>
|
var topic_alt_13 []byte = []byte(`</h1>
|
||||||
`)
|
`)
|
||||||
var topic_alt_14 []byte = []byte(`<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>`)
|
var topic_alt_14 []byte = []byte(`<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>`)
|
||||||
var topic_alt_15 []byte = []byte(`
|
var topic_alt_15 []byte = []byte(`
|
||||||
|
@ -424,9 +424,9 @@ var topic_alt_88 []byte = []byte(`
|
||||||
var profile_0 []byte = []byte(`
|
var profile_0 []byte = []byte(`
|
||||||
|
|
||||||
<div id="profile_left_lane" class="colstack_left">
|
<div id="profile_left_lane" class="colstack_left">
|
||||||
<!--<div class="colstack_item colstack_head rowhead">
|
<!--<header class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>Profile</a></div>
|
<div class="rowitem"><h1>Profile</h1></div>
|
||||||
</div>-->
|
</header>-->
|
||||||
<div id="profile_left_pane" class="rowmenu">
|
<div id="profile_left_pane" class="rowmenu">
|
||||||
<div class="rowitem avatarRow" style="padding: 0;">
|
<div class="rowitem avatarRow" style="padding: 0;">
|
||||||
<img src="`)
|
<img src="`)
|
||||||
|
@ -449,67 +449,108 @@ var profile_7 []byte = []byte(`<a href="/users/unban/`)
|
||||||
var profile_8 []byte = []byte(`?session=`)
|
var profile_8 []byte = []byte(`?session=`)
|
||||||
var profile_9 []byte = []byte(`" class="profile_menu_item">Unban</a>
|
var profile_9 []byte = []byte(`" class="profile_menu_item">Unban</a>
|
||||||
`)
|
`)
|
||||||
var profile_10 []byte = []byte(`<a href="/users/ban/`)
|
var profile_10 []byte = []byte(`<a href="#ban_user" class="profile_menu_item">Ban</a>`)
|
||||||
var profile_11 []byte = []byte(`?session=`)
|
var profile_11 []byte = []byte(`
|
||||||
var profile_12 []byte = []byte(`" class="profile_menu_item">Ban</a>`)
|
|
||||||
var profile_13 []byte = []byte(`
|
|
||||||
</div>`)
|
</div>`)
|
||||||
var profile_14 []byte = []byte(`
|
var profile_12 []byte = []byte(`
|
||||||
<div class="rowitem passive">
|
<div class="rowitem passive">
|
||||||
<a href="/report/submit/`)
|
<a href="/report/submit/`)
|
||||||
var profile_15 []byte = []byte(`?session=`)
|
var profile_13 []byte = []byte(`?session=`)
|
||||||
var profile_16 []byte = []byte(`&type=user" class="profile_menu_item report_item">Report</a>
|
var profile_14 []byte = []byte(`&type=user" class="profile_menu_item report_item">Report</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="profile_right_lane" class="colstack_right">
|
<div id="profile_right_lane" class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
`)
|
||||||
<div class="rowitem"><a>Comments</a></div>
|
var profile_15 []byte = []byte(`
|
||||||
|
<!-- TO-DO: Inline the display: none; CSS -->
|
||||||
|
<div id="ban_user_head" class="colstack_item colstack_head hash_hide ban_user_hash" style="display: none;">
|
||||||
|
<div class="rowitem"><h1>Ban User</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="profile_comments" class="colstack_item" style="overflow: hidden;border-top: none;">`)
|
<form id="ban_user_form" class="hash_hide ban_user_hash" action="/users/ban/submit/`)
|
||||||
var profile_17 []byte = []byte(`
|
var profile_16 []byte = []byte(`?session=`)
|
||||||
|
var profile_17 []byte = []byte(`" method="post" style="display: none;">
|
||||||
|
`)
|
||||||
|
var profile_18 []byte = []byte(`
|
||||||
|
<div class="colline">If all the fields are left blank, the ban will be permanent.</div>
|
||||||
|
<div class="colstack_item">
|
||||||
|
<div class="formrow real_first_child">
|
||||||
|
<div class="formitem formlabel"><a>Days</a></div>
|
||||||
|
<div class="formitem">
|
||||||
|
<input name="ban-duration-days" type="number" value="0" min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Weeks</a></div>
|
||||||
|
<div class="formitem">
|
||||||
|
<input name="ban-duration-weeks" type="number" value="0" min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Months</a></div>
|
||||||
|
<div class="formitem">
|
||||||
|
<input name="ban-duration-months" type="number" value="0" min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Reason</a></div>
|
||||||
|
<div class="formitem"><textarea name="ban-reason" placeholder="A really horrible person" required></textarea></div>
|
||||||
|
</div>-->
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><button name="ban-button" class="formbutton form_middle_button">Ban User</button></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
`)
|
||||||
|
var profile_19 []byte = []byte(`
|
||||||
|
|
||||||
|
<div id="profile_comments_head" class="colstack_item colstack_head hash_hide">
|
||||||
|
<div class="rowitem"><h1>Comments</h1></div>
|
||||||
|
</div>
|
||||||
|
<div id="profile_comments" class="colstack_item hash_hide" style="overflow: hidden;border-top: none;">`)
|
||||||
|
var profile_20 []byte = []byte(`
|
||||||
<div class="rowitem passive deletable_block editable_parent simple `)
|
<div class="rowitem passive deletable_block editable_parent simple `)
|
||||||
var profile_18 []byte = []byte(`" style="`)
|
var profile_21 []byte = []byte(`" style="`)
|
||||||
var profile_19 []byte = []byte(`background-image: url(`)
|
var profile_22 []byte = []byte(`background-image: url(`)
|
||||||
var profile_20 []byte = []byte(`), url(/static/post-avatar-bg.jpg);background-position: 0px `)
|
var profile_23 []byte = []byte(`), url(/static/post-avatar-bg.jpg);background-position: 0px `)
|
||||||
var profile_21 []byte = []byte(`-1`)
|
var profile_24 []byte = []byte(`-1`)
|
||||||
var profile_22 []byte = []byte(`0px;`)
|
var profile_25 []byte = []byte(`0px;`)
|
||||||
var profile_23 []byte = []byte(`">
|
var profile_26 []byte = []byte(`">
|
||||||
<span class="editable_block user_content simple">`)
|
<span class="editable_block user_content simple">`)
|
||||||
var profile_24 []byte = []byte(`</span>
|
var profile_27 []byte = []byte(`</span>
|
||||||
|
|
||||||
<span class="controls">
|
<span class="controls">
|
||||||
<a href="`)
|
<a href="`)
|
||||||
var profile_25 []byte = []byte(`" class="real_username username">`)
|
var profile_28 []byte = []byte(`" class="real_username username">`)
|
||||||
var profile_26 []byte = []byte(`</a>
|
var profile_29 []byte = []byte(`</a>
|
||||||
|
|
||||||
`)
|
`)
|
||||||
var profile_27 []byte = []byte(`<a href="/profile/reply/edit/submit/`)
|
var profile_30 []byte = []byte(`<a href="/profile/reply/edit/submit/`)
|
||||||
var profile_28 []byte = []byte(`" class="mod_button" title="Edit Item"><button class="username edit_item edit_label"></button></a>
|
var profile_31 []byte = []byte(`" class="mod_button" title="Edit Item"><button class="username edit_item edit_label"></button></a>
|
||||||
|
|
||||||
<a href="/profile/reply/delete/submit/`)
|
<a href="/profile/reply/delete/submit/`)
|
||||||
var profile_29 []byte = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`)
|
var profile_32 []byte = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`)
|
||||||
var profile_30 []byte = []byte(`
|
var profile_33 []byte = []byte(`
|
||||||
|
|
||||||
<a class="mod_button" href="/report/submit/`)
|
<a class="mod_button" href="/report/submit/`)
|
||||||
var profile_31 []byte = []byte(`?session=`)
|
var profile_34 []byte = []byte(`?session=`)
|
||||||
var profile_32 []byte = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a>
|
var profile_35 []byte = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a>
|
||||||
|
|
||||||
`)
|
`)
|
||||||
var profile_33 []byte = []byte(`<a class="username hide_on_mobile user_tag" style="float: right;">`)
|
var profile_36 []byte = []byte(`<a class="username hide_on_mobile user_tag" style="float: right;">`)
|
||||||
var profile_34 []byte = []byte(`</a>`)
|
var profile_37 []byte = []byte(`</a>`)
|
||||||
var profile_35 []byte = []byte(`
|
var profile_38 []byte = []byte(`
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
var profile_36 []byte = []byte(`</div>
|
var profile_39 []byte = []byte(`</div>
|
||||||
|
|
||||||
`)
|
`)
|
||||||
var profile_37 []byte = []byte(`
|
var profile_40 []byte = []byte(`
|
||||||
<form action="/profile/reply/create/" method="post">
|
<form id="profile_comments_form" class="hash_hide" action="/profile/reply/create/" method="post">
|
||||||
<input name="uid" value='`)
|
<input name="uid" value='`)
|
||||||
var profile_38 []byte = []byte(`' type="hidden" />
|
var profile_41 []byte = []byte(`' 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 name="reply-content" placeholder="Insert reply here"></textarea></div>
|
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
|
||||||
|
@ -520,9 +561,29 @@ var profile_38 []byte = []byte(`' type="hidden" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
`)
|
`)
|
||||||
var profile_39 []byte = []byte(`
|
var profile_42 []byte = []byte(`
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
`)
|
||||||
|
var profile_43 []byte = []byte(`
|
||||||
|
<script type="text/javascript">
|
||||||
|
function handle_profile_hashbit() {
|
||||||
|
var hash_class = ""
|
||||||
|
switch(window.location.hash.substr(1)) {
|
||||||
|
case "ban_user":
|
||||||
|
hash_class = "ban_user_hash"
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
console.log("Unknown hashbit")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$(".hash_hide").hide()
|
||||||
|
$("." + hash_class).show()
|
||||||
|
}
|
||||||
|
if(window.location.hash) handle_profile_hashbit()
|
||||||
|
window.addEventListener("hashchange", handle_profile_hashbit, false)
|
||||||
|
</script>
|
||||||
|
|
||||||
`)
|
`)
|
||||||
var forums_0 []byte = []byte(`
|
var forums_0 []byte = []byte(`
|
||||||
<main>
|
<main>
|
||||||
|
@ -573,7 +634,7 @@ var topics_0 []byte = []byte(`
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Topic List</a></div>
|
<div class="rowitem"><h1>Topic List</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="topic_list" class="rowblock topic_list">
|
<div id="topic_list" class="rowblock topic_list">
|
||||||
`)
|
`)
|
||||||
|
@ -628,13 +689,13 @@ var topics_30 []byte = []byte(`
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
`)
|
`)
|
||||||
var forum_0 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" href="/forum/`)
|
var forum_0 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" aria-label="Go to the previous page" rel="prev" href="/forum/`)
|
||||||
var forum_1 []byte = []byte(`?page=`)
|
var forum_1 []byte = []byte(`?page=`)
|
||||||
var forum_2 []byte = []byte(`"><</a></div>`)
|
var forum_2 []byte = []byte(`"><</a></div>`)
|
||||||
var forum_3 []byte = []byte(`<link rel="prerender" href="/forum/`)
|
var forum_3 []byte = []byte(`<link rel="prerender" href="/forum/`)
|
||||||
var forum_4 []byte = []byte(`?page=`)
|
var forum_4 []byte = []byte(`?page=`)
|
||||||
var forum_5 []byte = []byte(`" />
|
var forum_5 []byte = []byte(`" />
|
||||||
<div id="nextFloat" class="next_button"><a class="next_link" href="/forum/`)
|
<div id="nextFloat" class="next_button"><a class="next_link" aria-label="Go to the next page" rel="next" href="/forum/`)
|
||||||
var forum_6 []byte = []byte(`?page=`)
|
var forum_6 []byte = []byte(`?page=`)
|
||||||
var forum_7 []byte = []byte(`">></a></div>`)
|
var forum_7 []byte = []byte(`">></a></div>`)
|
||||||
var forum_8 []byte = []byte(`
|
var forum_8 []byte = []byte(`
|
||||||
|
@ -644,8 +705,8 @@ var forum_8 []byte = []byte(`
|
||||||
<div id="forum_head_block" class="rowblock rowhead">
|
<div id="forum_head_block" class="rowblock rowhead">
|
||||||
<div class="rowitem forum_title`)
|
<div class="rowitem forum_title`)
|
||||||
var forum_9 []byte = []byte(` has_opt`)
|
var forum_9 []byte = []byte(` has_opt`)
|
||||||
var forum_10 []byte = []byte(`"><a>`)
|
var forum_10 []byte = []byte(`"><h1>`)
|
||||||
var forum_11 []byte = []byte(`</a>
|
var forum_11 []byte = []byte(`</h1>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
var forum_12 []byte = []byte(`
|
var forum_12 []byte = []byte(`
|
||||||
|
|
|
@ -86,66 +86,72 @@ w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
w.Write(profile_9)
|
w.Write(profile_9)
|
||||||
} else {
|
} else {
|
||||||
w.Write(profile_10)
|
w.Write(profile_10)
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
}
|
||||||
w.Write(profile_11)
|
w.Write(profile_11)
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
}
|
||||||
w.Write(profile_12)
|
w.Write(profile_12)
|
||||||
}
|
|
||||||
w.Write(profile_13)
|
|
||||||
}
|
|
||||||
w.Write(profile_14)
|
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
w.Write(profile_15)
|
w.Write(profile_13)
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
|
w.Write(profile_14)
|
||||||
|
if tmpl_profile_vars.CurrentUser.Perms.BanUsers {
|
||||||
|
w.Write(profile_15)
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
w.Write(profile_16)
|
w.Write(profile_16)
|
||||||
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
|
w.Write(profile_17)
|
||||||
|
w.Write(profile_18)
|
||||||
|
}
|
||||||
|
w.Write(profile_19)
|
||||||
if len(tmpl_profile_vars.ItemList) != 0 {
|
if len(tmpl_profile_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_profile_vars.ItemList {
|
for _, item := range tmpl_profile_vars.ItemList {
|
||||||
w.Write(profile_17)
|
|
||||||
w.Write([]byte(item.ClassName))
|
|
||||||
w.Write(profile_18)
|
|
||||||
if item.Avatar != "" {
|
|
||||||
w.Write(profile_19)
|
|
||||||
w.Write([]byte(item.Avatar))
|
|
||||||
w.Write(profile_20)
|
w.Write(profile_20)
|
||||||
if item.ContentLines <= 5 {
|
w.Write([]byte(item.ClassName))
|
||||||
w.Write(profile_21)
|
w.Write(profile_21)
|
||||||
}
|
if item.Avatar != "" {
|
||||||
w.Write(profile_22)
|
w.Write(profile_22)
|
||||||
}
|
w.Write([]byte(item.Avatar))
|
||||||
w.Write(profile_23)
|
w.Write(profile_23)
|
||||||
w.Write([]byte(item.ContentHtml))
|
if item.ContentLines <= 5 {
|
||||||
w.Write(profile_24)
|
w.Write(profile_24)
|
||||||
w.Write([]byte(item.UserLink))
|
|
||||||
w.Write(profile_25)
|
|
||||||
w.Write([]byte(item.CreatedByName))
|
|
||||||
w.Write(profile_26)
|
|
||||||
if tmpl_profile_vars.CurrentUser.Is_Mod {
|
|
||||||
w.Write(profile_27)
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(profile_28)
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(profile_29)
|
|
||||||
}
|
}
|
||||||
|
w.Write(profile_25)
|
||||||
|
}
|
||||||
|
w.Write(profile_26)
|
||||||
|
w.Write([]byte(item.ContentHtml))
|
||||||
|
w.Write(profile_27)
|
||||||
|
w.Write([]byte(item.UserLink))
|
||||||
|
w.Write(profile_28)
|
||||||
|
w.Write([]byte(item.CreatedByName))
|
||||||
|
w.Write(profile_29)
|
||||||
|
if tmpl_profile_vars.CurrentUser.Is_Mod {
|
||||||
w.Write(profile_30)
|
w.Write(profile_30)
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(profile_31)
|
w.Write(profile_31)
|
||||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(profile_32)
|
w.Write(profile_32)
|
||||||
if item.Tag != "" {
|
}
|
||||||
w.Write(profile_33)
|
w.Write(profile_33)
|
||||||
w.Write([]byte(item.Tag))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(profile_34)
|
w.Write(profile_34)
|
||||||
}
|
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||||
w.Write(profile_35)
|
w.Write(profile_35)
|
||||||
}
|
if item.Tag != "" {
|
||||||
}
|
|
||||||
w.Write(profile_36)
|
w.Write(profile_36)
|
||||||
if !tmpl_profile_vars.CurrentUser.Is_Banned {
|
w.Write([]byte(item.Tag))
|
||||||
w.Write(profile_37)
|
w.Write(profile_37)
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
}
|
||||||
w.Write(profile_38)
|
w.Write(profile_38)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
w.Write(profile_39)
|
w.Write(profile_39)
|
||||||
|
if !tmpl_profile_vars.CurrentUser.Is_Banned {
|
||||||
|
w.Write(profile_40)
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||||
|
w.Write(profile_41)
|
||||||
|
}
|
||||||
|
w.Write(profile_42)
|
||||||
|
w.Write(profile_43)
|
||||||
w.Write(footer_0)
|
w.Write(footer_0)
|
||||||
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
|
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
|
||||||
w.Write(footer_1)
|
w.Write(footer_1)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<nav class="colstack_left">
|
<nav class="colstack_left">
|
||||||
<div class="colstack_item colstack_head rowhead">
|
<div class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>My Account</a></div>
|
<div class="rowitem"><h1>My Account</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item rowmenu">
|
<div class="colstack_item rowmenu">
|
||||||
<div class="rowitem passive"><a href="/user/edit/avatar/">Avatar</a></div>
|
<div class="rowitem passive"><a href="/user/edit/avatar/">Avatar</a></div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "account-menu.html" . }}
|
{{template "account-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head rowhead">
|
<div class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>Edit Avatar</a></div>
|
<div class="rowitem"><h1>Edit Avatar</h1></div>
|
||||||
</div>
|
</div>
|
||||||
{{if .CurrentUser.Avatar}}
|
{{if .CurrentUser.Avatar}}
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "account-menu.html" . }}
|
{{template "account-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head rowhead">
|
<div class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>Emails</a></div>
|
<div class="rowitem"><h1>Emails</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
<!-- TO-DO: Do we need this inline CSS? -->
|
<!-- TO-DO: Do we need this inline CSS? -->
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "account-menu.html" . }}
|
{{template "account-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head rowhead">
|
<div class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>Edit Username</a></div>
|
<div class="rowitem"><h1>Edit Username</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
<form action="/user/edit/username/submit/" method="post">
|
<form action="/user/edit/username/submit/" method="post">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "account-menu.html" . }}
|
{{template "account-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head rowhead">
|
<div class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>Edit Password</a></div>
|
<div class="rowitem"><h1>Edit Password</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
<form action="/user/edit/critical/submit/" method="post">
|
<form action="/user/edit/critical/submit/" method="post">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<main>
|
<main>
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Are you sure?</a></div>
|
<div class="rowitem"><h1>Are you sure?</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<div class="rowitem passive">{{.Something.Message}}<br /><br />
|
<div class="rowitem passive">{{.Something.Message}}<br /><br />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<main>
|
<main>
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Create Topic</a></div>
|
<div class="rowitem"><h1>Create Topic</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<form action="/topic/create/submit/" method="post">
|
<form action="/topic/create/submit/" method="post">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<main>
|
<main>
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>An error has occured</a></div>
|
<div class="rowitem"><h1>An error has occured</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<div class="rowitem passive">{{.Something}}</div>
|
<div class="rowitem passive">{{.Something}}</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
</div>
|
</div>
|
||||||
{{if .Header.Widgets.RightSidebar}}<div class="sidebar">{{.Header.Widgets.RightSidebar}}</div>{{end}}
|
{{if .Header.Widgets.RightSidebar}}<aside class="sidebar">{{.Header.Widgets.RightSidebar}}</aside>{{end}}
|
||||||
<div style="clear: both;"></div>
|
<div style="clear: both;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
|
|
||||||
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" href="/forum/{{.Forum.ID}}?page={{subtract .Page 1}}"><</a></div>{{end}}
|
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" aria-label="Go to the previous page" rel="prev" href="/forum/{{.Forum.ID}}?page={{subtract .Page 1}}"><</a></div>{{end}}
|
||||||
{{if ne .LastPage .Page}}<link rel="prerender" href="/forum/{{.Forum.ID}}?page={{add .Page 1}}" />
|
{{if ne .LastPage .Page}}<link rel="prerender" href="/forum/{{.Forum.ID}}?page={{add .Page 1}}" />
|
||||||
<div id="nextFloat" class="next_button"><a class="next_link" href="/forum/{{.Forum.ID}}?page={{add .Page 1}}">></a></div>{{end}}
|
<div id="nextFloat" class="next_button"><a class="next_link" aria-label="Go to the next page" rel="next" href="/forum/{{.Forum.ID}}?page={{add .Page 1}}">></a></div>{{end}}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div id="forum_head_block" class="rowblock rowhead">
|
<div id="forum_head_block" class="rowblock rowhead">
|
||||||
<div class="rowitem forum_title{{if ne .CurrentUser.ID 0}} has_opt{{end}}"><a>{{.Title}}</a>
|
<div class="rowitem forum_title{{if ne .CurrentUser.ID 0}} has_opt{{end}}"><h1>{{.Title}}</h1>
|
||||||
</div>
|
</div>
|
||||||
{{if ne .CurrentUser.ID 0}}
|
{{if ne .CurrentUser.ID 0}}
|
||||||
{{if .CurrentUser.Perms.CreateTopic}}
|
{{if .CurrentUser.Perms.CreateTopic}}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Login</a></div>
|
<div class="rowitem"><h1>Login</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<form action="/accounts/login/submit/" method="post">
|
<form action="/accounts/login/submit/" method="post">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="move_left">
|
<div class="move_left">
|
||||||
<div class="move_right">
|
<div class="move_right">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="menu_left menu_overview"><a href="/">{{.Header.Site.Name}}</a></li>
|
<li class="menu_left menu_overview"><a href="/" rel="home">{{.Header.Site.Name}}</a></li>
|
||||||
<li class="menu_left menu_forums"><a href="/forums/">Forums</a></li>
|
<li class="menu_left menu_forums"><a href="/forums/">Forums</a></li>
|
||||||
<li class="menu_left menu_topics"><a href="/">Topics</a></li>
|
<li class="menu_left menu_topics"><a href="/">Topics</a></li>
|
||||||
<li class="menu_left menu_create_topic"><a href="/topics/create/">Create Topic</a></li>
|
<li class="menu_left menu_create_topic"><a href="/topics/create/">Create Topic</a></li>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Administration Logs</a></div>
|
<div class="rowitem"><h1>Administration Logs</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_adminlogs" class="colstack_item rowlist">
|
<div id="panel_adminlogs" class="colstack_item rowlist">
|
||||||
{{range .Logs}}
|
{{range .Logs}}
|
||||||
|
|
|
@ -6,7 +6,7 @@ var form_vars = {'perm_preset': ['can_moderate','can_post','read_only','no_acces
|
||||||
|
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>{{.Name}} Forum</a></div>
|
<div class="rowitem"><h1>{{.Name}} Forum</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_forum" class="colstack_item">
|
<div id="panel_forum" class="colstack_item">
|
||||||
<form action="/panel/forums/edit/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/forums/edit/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Forums</a></div>
|
<div class="rowitem"><h1>Forums</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_forums" class="colstack_item rowlist">
|
<div id="panel_forums" class="colstack_item rowlist">
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Add Forum</a></div>
|
<div class="rowitem"><h1>Add Forum</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
<form action="/panel/forums/create/?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/forums/create/?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>{{.Name}} Group</a></div>
|
<div class="rowitem"><h1>{{.Name}} Group</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<form action="/panel/groups/edit/perms/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/groups/edit/perms/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
|
||||||
<div id="panel_group" class="colstack_item rowlist">
|
<div id="panel_group" class="colstack_item rowlist">
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Extended Permissions</a></div>
|
<div class="rowitem"><h1>Extended Permissions</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item rowlist">
|
<div class="colstack_item rowlist">
|
||||||
{{if .CurrentUser.Perms.EditGroupGlobalPerms}}
|
{{if .CurrentUser.Perms.EditGroupGlobalPerms}}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>{{.Name}} Group</a></div>
|
<div class="rowitem"><h1>{{.Name}} Group</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_group" class="colstack_item">
|
<div id="panel_group" class="colstack_item">
|
||||||
<form action="/panel/groups/edit/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/groups/edit/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Groups</a></div>
|
<div class="rowitem"><h1>Groups</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_groups" class="colstack_item rowlist">
|
<div id="panel_groups" class="colstack_item rowlist">
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Create Group</a></div>
|
<div class="rowitem"><h1>Create Group</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
<form action="/panel/groups/create/?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/groups/create/?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditSettings}}<div class="rowitem passive">
|
{{if .CurrentUser.Perms.EditSettings}}<div class="rowitem passive">
|
||||||
<a href="/panel/settings/">Settings</a> <a class="menu_stats" href="#">({{.Stats.Settings}})</a>
|
<a href="/panel/settings/">Settings</a> <a class="menu_stats" href="#">({{.Stats.Settings}})</a>
|
||||||
|
</div>
|
||||||
|
<div class="rowitem passive">
|
||||||
|
<a href="/panel/settings/word-filters/">Word Filters</a> <a class="menu_stats" href="#">({{.Stats.WordFilters}})</a>
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
{{if .CurrentUser.Perms.ManageThemes}}<div class="rowitem passive">
|
{{if .CurrentUser.Perms.ManageThemes}}<div class="rowitem passive">
|
||||||
<a href="/panel/themes/">Themes</a> <a class="menu_stats" href="#">({{.Stats.Themes}})</a>
|
<a href="/panel/themes/">Themes</a> <a class="menu_stats" href="#">({{.Stats.Themes}})</a>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</nav>
|
</nav>
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Moderation Logs</a></div>
|
<div class="rowitem"><h1>Moderation Logs</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_modlogs" class="colstack_item rowlist">
|
<div id="panel_modlogs" class="colstack_item rowlist">
|
||||||
{{range .Logs}}
|
{{range .Logs}}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "panel-menu.html" . }}
|
{{template "panel-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Plugins</a></div>
|
<div class="rowitem"><h1>Plugins</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_plugins" class="colstack_item">
|
<div id="panel_plugins" class="colstack_item">
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "panel-menu.html" . }}
|
{{template "panel-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Edit Setting</a></div>
|
<div class="rowitem"><h1>Edit Setting</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_setting" class="colstack_item">
|
<div id="panel_setting" class="colstack_item">
|
||||||
<form action="/panel/settings/edit/submit/{{.Something.Name}}?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/settings/edit/submit/{{.Something.Name}}?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "panel-menu.html" . }}
|
{{template "panel-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Settings</a></div>
|
<div class="rowitem"><h1>Settings</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_settings" class="colstack_item rowlist">
|
<div id="panel_settings" class="colstack_item rowlist">
|
||||||
{{range $key, $value := .Something}}
|
{{range $key, $value := .Something}}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Primary Themes</a></div>
|
<div class="rowitem"><h1>Primary Themes</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_primary_themes" class="colstack_item panel_themes">
|
<div id="panel_primary_themes" class="colstack_item panel_themes">
|
||||||
{{range .PrimaryThemes}}
|
{{range .PrimaryThemes}}
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Variant Themes</a></div>
|
<div class="rowitem"><h1>Variant Themes</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_variant_themes" class="colstack_item panel_themes">
|
<div id="panel_variant_themes" class="colstack_item panel_themes">
|
||||||
{{range .VariantThemes}}
|
{{range .VariantThemes}}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{{template "panel-menu.html" . }}
|
{{template "panel-menu.html" . }}
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>User Editor</a></div>
|
<div class="rowitem"><h1>User Editor</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_user" class="colstack_item">
|
<div id="panel_user" class="colstack_item">
|
||||||
<form action="/panel/users/edit/submit/{{.Something.ID}}?session={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/users/edit/submit/{{.Something.ID}}?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><a>Users</a></div>
|
<div class="rowitem"><h1>Users</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_users" class="colstack_item rowlist bgavatars">
|
<div id="panel_users" class="colstack_item rowlist bgavatars">
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
{{if (.Tag) and (.Is_Super_Mod)}}<span style="float: right;"><span class="panel_tag" style="margin-left 4px;">{{.Tag}}</span></span>{{end}}
|
{{if (.Tag) and (.Is_Super_Mod)}}<span style="float: right;"><span class="panel_tag" style="margin-left 4px;">{{.Tag}}</span></span>{{end}}
|
||||||
|
|
||||||
<span class="panel_floater">
|
<span class="panel_floater">
|
||||||
{{if .Is_Banned}}<a href="/users/unban/{{.ID}}?session={{$.CurrentUser.Session}}" class="panel_tag panel_right_button ban_button">Unban</a>{{else if not .Is_Super_Mod}}<a href="/users/ban/{{.ID}}?session={{$.CurrentUser.Session}}" class="panel_tag panel_right_button ban_button">Ban</a>{{end}}
|
{{if .Is_Banned}}<a href="/users/unban/{{.ID}}?session={{$.CurrentUser.Session}}" class="panel_tag panel_right_button ban_button">Unban</a>{{else if not .Is_Super_Mod}}<a href="/user/{{.ID}}#ban_user" class="panel_tag panel_right_button ban_button">Ban</a>{{end}}
|
||||||
{{if not .Active}}<a href="/users/activate/{{.ID}}?session={{$.CurrentUser.Session}}" class="panel_tag panel_right_button">Activate</a>{{end}}
|
{{if not .Active}}<a href="/users/activate/{{.ID}}?session={{$.CurrentUser.Session}}" class="panel_tag panel_right_button">Activate</a>{{end}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
{{template "header.html" . }}
|
||||||
|
{{template "panel-menu.html" . }}
|
||||||
|
<main class="colstack_right">
|
||||||
|
<div class="colstack_item colstack_head">
|
||||||
|
<div class="rowitem"><h1>Word Filters</h1></div>
|
||||||
|
</div>
|
||||||
|
<div id="panel_word_filters" class="colstack_item rowlist">
|
||||||
|
{{range .Something}}
|
||||||
|
<div class="rowitem panel_compactrow editable_parent">
|
||||||
|
<a data-field="find" data-type="text" href="/panel/settings/word-filters/edit/{{.ID}}" class="editable_block panel_upshift edit_fields">{{.Find}}</a>
|
||||||
|
<span style="padding-left: 2px;padding-right: 2px;"> || </span>
|
||||||
|
<a data-field="replacement" data-type="text" class="editable_block panel_compacttext">{{.Replacement}}</a>
|
||||||
|
<span class="panel_buttons">
|
||||||
|
<a class="panel_tag edit_fields hide_on_edit panel_right_button">Edit</a>
|
||||||
|
<a class="panel_right_button" href="/panel/settings/word-filters/edit/submit/{{.ID}}"><button class='panel_tag submit_edit show_on_edit' type='submit'>Update</button></a>
|
||||||
|
<a href="/panel/settings/word-filters/delete/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="panel_tag panel_right_button hide_on_edit">Delete</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="rowitem editable_parent">
|
||||||
|
<a>You don't have any word filters yet.</a>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="colstack_item colstack_head">
|
||||||
|
<div class="rowitem"><h1>Add Filter</h1></div>
|
||||||
|
</div>
|
||||||
|
<div class="colstack_item">
|
||||||
|
<form action="/panel/settings/word-filters/create/?session={{.CurrentUser.Session}}" method="post">
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Find</a></div>
|
||||||
|
<div class="formitem"><input name="find" type="text" placeholder="fuck" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Replacement</a></div>
|
||||||
|
<div class="formitem"><input name="replacement" type="text" placeholder="fudge" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><button name="panel-button" class="formbutton form_middle_button">Add Filter</button></div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{template "footer.html" . }}
|
|
@ -1,9 +1,9 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
|
|
||||||
<div id="profile_left_lane" class="colstack_left">
|
<div id="profile_left_lane" class="colstack_left">
|
||||||
<!--<div class="colstack_item colstack_head rowhead">
|
<!--<header class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem"><a>Profile</a></div>
|
<div class="rowitem"><h1>Profile</h1></div>
|
||||||
</div>-->
|
</header>-->
|
||||||
<div id="profile_left_pane" class="rowmenu">
|
<div id="profile_left_pane" class="rowmenu">
|
||||||
<div class="rowitem avatarRow" style="padding: 0;">
|
<div class="rowitem avatarRow" style="padding: 0;">
|
||||||
<img src="{{.ProfileOwner.Avatar}}" class="avatar" />
|
<img src="{{.ProfileOwner.Avatar}}" class="avatar" />
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{if (.CurrentUser.Is_Super_Mod) and not (.ProfileOwner.Is_Super_Mod) }}<div class="rowitem passive">
|
{{if (.CurrentUser.Is_Super_Mod) and not (.ProfileOwner.Is_Super_Mod) }}<div class="rowitem passive">
|
||||||
{{if .ProfileOwner.Is_Banned }}<a href="/users/unban/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}" class="profile_menu_item">Unban</a>
|
{{if .ProfileOwner.Is_Banned }}<a href="/users/unban/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}" class="profile_menu_item">Unban</a>
|
||||||
{{else}}<a href="/users/ban/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}" class="profile_menu_item">Ban</a>{{end}}
|
{{else}}<a href="#ban_user" class="profile_menu_item">Ban</a>{{end}}
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
<div class="rowitem passive">
|
<div class="rowitem passive">
|
||||||
<a href="/report/submit/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}&type=user" class="profile_menu_item report_item">Report</a>
|
<a href="/report/submit/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}&type=user" class="profile_menu_item report_item">Report</a>
|
||||||
|
@ -25,10 +25,48 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="profile_right_lane" class="colstack_right">
|
<div id="profile_right_lane" class="colstack_right">
|
||||||
<div class="colstack_item colstack_head">
|
{{if .CurrentUser.Perms.BanUsers}}
|
||||||
<div class="rowitem"><a>Comments</a></div>
|
<!-- TO-DO: Inline the display: none; CSS -->
|
||||||
|
<div id="ban_user_head" class="colstack_item colstack_head hash_hide ban_user_hash" style="display: none;">
|
||||||
|
<div class="rowitem"><h1>Ban User</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="profile_comments" class="colstack_item" style="overflow: hidden;border-top: none;">{{range .ItemList}}
|
<form id="ban_user_form" class="hash_hide ban_user_hash" action="/users/ban/submit/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}" method="post" style="display: none;">
|
||||||
|
{{/** TO-DO: Put a JS duration calculator here instead of this text? **/}}
|
||||||
|
<div class="colline">If all the fields are left blank, the ban will be permanent.</div>
|
||||||
|
<div class="colstack_item">
|
||||||
|
<div class="formrow real_first_child">
|
||||||
|
<div class="formitem formlabel"><a>Days</a></div>
|
||||||
|
<div class="formitem">
|
||||||
|
<input name="ban-duration-days" type="number" value="0" min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Weeks</a></div>
|
||||||
|
<div class="formitem">
|
||||||
|
<input name="ban-duration-weeks" type="number" value="0" min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Months</a></div>
|
||||||
|
<div class="formitem">
|
||||||
|
<input name="ban-duration-months" type="number" value="0" min="0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--<div class="formrow">
|
||||||
|
<div class="formitem formlabel"><a>Reason</a></div>
|
||||||
|
<div class="formitem"><textarea name="ban-reason" placeholder="A really horrible person" required></textarea></div>
|
||||||
|
</div>-->
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><button name="ban-button" class="formbutton form_middle_button">Ban User</button></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
<div id="profile_comments_head" class="colstack_item colstack_head hash_hide">
|
||||||
|
<div class="rowitem"><h1>Comments</h1></div>
|
||||||
|
</div>
|
||||||
|
<div id="profile_comments" class="colstack_item hash_hide" style="overflow: hidden;border-top: none;">{{range .ItemList}}
|
||||||
<div class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="{{if .Avatar}}background-image: url({{.Avatar}}), url(/static/post-avatar-bg.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;{{end}}">
|
<div class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="{{if .Avatar}}background-image: url({{.Avatar}}), url(/static/post-avatar-bg.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;{{end}}">
|
||||||
<span class="editable_block user_content simple">{{.ContentHtml}}</span>
|
<span class="editable_block user_content simple">{{.ContentHtml}}</span>
|
||||||
|
|
||||||
|
@ -47,7 +85,7 @@
|
||||||
{{end}}</div>
|
{{end}}</div>
|
||||||
|
|
||||||
{{if not .CurrentUser.Is_Banned}}
|
{{if not .CurrentUser.Is_Banned}}
|
||||||
<form action="/profile/reply/create/" method="post">
|
<form id="profile_comments_form" class="hash_hide" action="/profile/reply/create/" 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">
|
||||||
|
@ -61,4 +99,24 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{/** Quick subpage switcher **/}}
|
||||||
|
{{/** TO-DO: Stop inlining this **/}}
|
||||||
|
<script type="text/javascript">
|
||||||
|
function handle_profile_hashbit() {
|
||||||
|
var hash_class = ""
|
||||||
|
switch(window.location.hash.substr(1)) {
|
||||||
|
case "ban_user":
|
||||||
|
hash_class = "ban_user_hash"
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
console.log("Unknown hashbit")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$(".hash_hide").hide()
|
||||||
|
$("." + hash_class).show()
|
||||||
|
}
|
||||||
|
if(window.location.hash) handle_profile_hashbit()
|
||||||
|
window.addEventListener("hashchange", handle_profile_hashbit, false)
|
||||||
|
</script>
|
||||||
|
|
||||||
{{template "footer.html" . }}
|
{{template "footer.html" . }}
|
||||||
|
|
|
@ -2,25 +2,25 @@
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Create Account</a></div>
|
<div class="rowitem"><h1>Create Account</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<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>Account Name</a></div>
|
<div class="formitem formlabel"><a id="username_label">Account Name</a></div>
|
||||||
<div class="formitem"><input name="username" type="text" placeholder="Account Name" required /></div>
|
<div class="formitem"><input name="username" type="text" placeholder="Account Name" aria-labelledby="username_label" required /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>Email</a></div>
|
<div class="formitem formlabel"><a id="email_label">Email</a></div>
|
||||||
<div class="formitem"><input name="email" type="email" placeholder="joe.doe@example.com" required /></div>
|
<div class="formitem"><input name="email" type="email" placeholder="joe.doe@example.com" aria-labelledby="email_label" required /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>Password</a></div>
|
<div class="formitem formlabel"><a id="password_label">Password</a></div>
|
||||||
<div class="formitem"><input name="password" type="password" autocomplete="new-password" placeholder="*****" 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>Confirm Password</a></div>
|
<div class="formitem formlabel"><a id="confirm_password_label">Confirm Password</a></div>
|
||||||
<div class="formitem"><input name="confirm_password" type="password" placeholder="*****" required /></div>
|
<div class="formitem"><input name="confirm_password" type="password" placeholder="*****" aria-labelledby="confirm_password_label" required /></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem"><button name="register-button" class="formbutton">Create Account</div></div>
|
<div class="formitem"><button name="register-button" class="formbutton">Create Account</div></div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Create Group</a></div>
|
<div class="rowitem"><h1>Create Group</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<form action="/group/create/submit/" method="post">
|
<form action="/group/create/submit/" method="post">
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
|
|
||||||
<form id="edit_topic_form" action='/topic/edit/submit/{{.Topic.ID}}' method="post"></form>
|
<form id="edit_topic_form" action='/topic/edit/submit/{{.Topic.ID}}' method="post"></form>
|
||||||
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/{{.Topic.ID}}?page={{subtract .Page 1}}"><</a></div>{{end}}
|
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" aria-label="Go to the previous page" rel="prev" href="/topic/{{.Topic.ID}}?page={{subtract .Page 1}}"><</a></div>{{end}}
|
||||||
|
|
||||||
{{if ne .LastPage .Page}}<link rel="prerender" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}" />
|
{{if ne .LastPage .Page}}<link rel="prerender" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}" />
|
||||||
<div id="nextFloat" class="next_button">
|
<div id="nextFloat" class="next_button">
|
||||||
<a class="next_link" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}">></a>
|
<a class="next_link" aria-label="Go to the next page" rel="next" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}">></a>
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead topic_block">
|
<div class="rowblock rowhead topic_block">
|
||||||
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.Is_Closed}} topic_closed_head{{end}}">
|
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.Is_Closed}} topic_closed_head{{end}}">
|
||||||
<a class='topic_name hide_on_edit'>{{.Topic.Title}}</a>
|
<h1 class='topic_name hide_on_edit'>{{.Topic.Title}}</h1>
|
||||||
{{if .Topic.Is_Closed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
{{if .Topic.Is_Closed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}
|
{{if .CurrentUser.Perms.EditTopic}}
|
||||||
<input form='edit_topic_form' class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
<input form='edit_topic_form' class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/{{.Topic.ID}}?page={{subtract .Page 1}}"><</a></div>{{end}}
|
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" aria-label="Go to the previous page" rel="prev" href="/topic/{{.Topic.ID}}?page={{subtract .Page 1}}"><</a></div>{{end}}
|
||||||
{{if ne .LastPage .Page}}<link rel="prerender" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}" />
|
{{if ne .LastPage .Page}}<link rel="prerender" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}" />
|
||||||
<div id="nextFloat" class="next_button"><a class="next_link" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}">></a></div>{{end}}
|
<div id="nextFloat" class="next_button"><a class="next_link" aria-label="Go to the next page" rel="next" href="/topic/{{.Topic.ID}}?page={{add .Page 1}}">></a></div>{{end}}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead topic_block">
|
<div class="rowblock rowhead topic_block">
|
||||||
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
|
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
|
||||||
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.Is_Closed}} topic_closed_head{{end}}">
|
<div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.Is_Closed}} topic_closed_head{{end}}">
|
||||||
<a class='topic_name hide_on_edit'>{{.Topic.Title}}</a>
|
<h1 class='topic_name hide_on_edit'>{{.Topic.Title}}</h1>
|
||||||
{{if .Topic.Is_Closed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
{{if .Topic.Is_Closed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">🔒︎</span>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}
|
{{if .CurrentUser.Perms.EditTopic}}
|
||||||
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<main>
|
<main>
|
||||||
|
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem"><a>Topic List</a></div>
|
<div class="rowitem"><h1>Topic List</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="topic_list" class="rowblock topic_list">
|
<div id="topic_list" class="rowblock topic_list">
|
||||||
{{range .ItemList}}<div class="rowitem topic_left passive datarow {{if .Sticky}}topic_sticky{{else if .Is_Closed}}topic_closed{{end}}" style="{{if .Creator.Avatar}}background-image: url({{.Creator.Avatar}});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}">
|
{{range .ItemList}}<div class="rowitem topic_left passive datarow {{if .Sticky}}topic_sticky{{else if .Is_Closed}}topic_closed{{end}}" style="{{if .Creator.Avatar}}background-image: url({{.Creator.Avatar}});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem">{{.Name}}</div>
|
<div class="rowitem"><h1>{{.Name}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<nav class="rowblock">{{range .MenuList}}
|
<nav class="rowblock">{{range .MenuList}}
|
||||||
<div class="rowitem {{if .Compact}}datarow{{end}}"><a href="{{.Location}}">{{.Text}}</a></div>
|
<div class="rowitem {{if .Compact}}datarow{{end}}"><a href="{{.Location}}">{{.Text}}</a></div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="rowblock rowhead">
|
<div class="rowblock rowhead">
|
||||||
<div class="rowitem">{{.Name}}</div>
|
<div class="rowitem"><h1>{{.Name}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<div class="rowitem">{{.Text}}</div>
|
<div class="rowitem">{{.Text}}</div>
|
||||||
|
|
|
@ -147,6 +147,14 @@ a {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rowitem h1 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: normal;
|
||||||
|
-webkit-margin-before: 0;
|
||||||
|
-webkit-margin-after: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.rowsmall {
|
.rowsmall {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
@ -166,6 +174,13 @@ a {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.colline {
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: rgb(61,61,61);
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Topic View */
|
/* Topic View */
|
||||||
|
|
||||||
/* TO-DO: How should we handle the sticky headers? */
|
/* TO-DO: How should we handle the sticky headers? */
|
||||||
|
|
|
@ -38,9 +38,9 @@ func NewMemoryTopicStore(capacity int) *MemoryTopicStore {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
return &MemoryTopicStore{
|
return &MemoryTopicStore{
|
||||||
items:make(map[int]*Topic),
|
items: make(map[int]*Topic),
|
||||||
capacity:capacity,
|
capacity: capacity,
|
||||||
get:stmt,
|
get: stmt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
56
user.go
56
user.go
|
@ -1,9 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
//"log"
|
||||||
//"fmt"
|
//"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
@ -51,6 +53,7 @@ type User struct
|
||||||
Level int
|
Level int
|
||||||
Score int
|
Score int
|
||||||
Last_IP string
|
Last_IP string
|
||||||
|
TempGroup int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Email struct
|
type Email struct
|
||||||
|
@ -62,6 +65,52 @@ type Email struct
|
||||||
Token string
|
Token string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// duration in seconds
|
||||||
|
func (user *User) Ban(duration time.Duration, issuedBy int) error {
|
||||||
|
return user.ScheduleGroupUpdate(4,issuedBy,duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (user *User) Unban() error {
|
||||||
|
err := user.RevertGroupUpdate()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return users.Load(user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TO-DO: Use a transaction to avoid race conditions
|
||||||
|
// Make this more stateless?
|
||||||
|
func (user *User) ScheduleGroupUpdate(gid int, issuedBy int, duration time.Duration) error {
|
||||||
|
var temporary bool
|
||||||
|
if duration.Nanoseconds() != 0 {
|
||||||
|
temporary = true
|
||||||
|
}
|
||||||
|
|
||||||
|
revertAt := time.Now().Add(duration)
|
||||||
|
_, err := replace_schedule_group_stmt.Exec(user.ID, gid, issuedBy, revertAt, temporary)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = set_temp_group_stmt.Exec(gid,user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return users.Load(user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TO-DO: Use a transaction to avoid race conditions
|
||||||
|
func (user *User) RevertGroupUpdate() error {
|
||||||
|
_, err := replace_schedule_group_stmt.Exec(user.ID, 0, 0, time.Now(), false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = set_temp_group_stmt.Exec(0,user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return users.Load(user.ID)
|
||||||
|
}
|
||||||
|
|
||||||
func BcryptCheckPassword(real_password string, password string, salt string) (err error) {
|
func BcryptCheckPassword(real_password string, password string, salt string) (err error) {
|
||||||
return bcrypt.CompareHashAndPassword([]byte(real_password), []byte(password + salt))
|
return bcrypt.CompareHashAndPassword([]byte(real_password), []byte(password + salt))
|
||||||
}
|
}
|
||||||
|
@ -245,7 +294,8 @@ func _panel_session_check(w http.ResponseWriter, r *http.Request, user *User) (h
|
||||||
|
|
||||||
stats.Users = users.GetGlobalCount()
|
stats.Users = users.GetGlobalCount()
|
||||||
stats.Forums = fstore.GetGlobalCount() // TO-DO: Stop it from showing the blanked forums
|
stats.Forums = fstore.GetGlobalCount() // TO-DO: Stop it from showing the blanked forums
|
||||||
stats.Settings = len(headerVars.Settings) // TO-DO: IS this racey?
|
stats.Settings = len(headerVars.Settings)
|
||||||
|
stats.WordFilters = len(wordFilterBox.Load().(WordFilterBox))
|
||||||
stats.Themes = len(themes)
|
stats.Themes = len(themes)
|
||||||
stats.Reports = 0 // TO-DO: Do the report count. Only show open threads?
|
stats.Reports = 0 // TO-DO: Do the report count. Only show open threads?
|
||||||
|
|
||||||
|
@ -447,6 +497,10 @@ func init_user_perms(user *User) {
|
||||||
user.PluginPerms = groups[user.Group].PluginPerms
|
user.PluginPerms = groups[user.Group].PluginPerms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.TempGroup != 0 {
|
||||||
|
user.Group = user.TempGroup
|
||||||
|
}
|
||||||
|
|
||||||
user.Is_Admin = user.Is_Super_Admin || groups[user.Group].Is_Admin
|
user.Is_Admin = user.Is_Super_Admin || groups[user.Group].Is_Admin
|
||||||
user.Is_Super_Mod = user.Is_Admin || groups[user.Group].Is_Mod
|
user.Is_Super_Mod = user.Is_Admin || groups[user.Group].Is_Mod
|
||||||
user.Is_Mod = user.Is_Super_Mod
|
user.Is_Mod = user.Is_Super_Mod
|
||||||
|
|
|
@ -47,7 +47,7 @@ type MemoryUserStore struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemoryUserStore(capacity int) *MemoryUserStore {
|
func NewMemoryUserStore(capacity int) *MemoryUserStore {
|
||||||
get_stmt, err := qgen.Builder.SimpleSelect("users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid = ?","","")
|
get_stmt, err := qgen.Builder.SimpleSelect("users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group","uid = ?","","")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -70,12 +70,12 @@ func NewMemoryUserStore(capacity int) *MemoryUserStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &MemoryUserStore{
|
return &MemoryUserStore{
|
||||||
items:make(map[int]*User),
|
items: make(map[int]*User),
|
||||||
capacity:capacity,
|
capacity: capacity,
|
||||||
get:get_stmt,
|
get: get_stmt,
|
||||||
register:register_stmt,
|
register: register_stmt,
|
||||||
username_exists:username_exists_stmt,
|
username_exists: username_exists_stmt,
|
||||||
user_count:user_count_stmt,
|
user_count: user_count_stmt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ func (sus *MemoryUserStore) CascadeGet(id int) (*User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
user = &User{ID:id,Loggedin:true}
|
user = &User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
|
|
||||||
if user.Avatar != "" {
|
if user.Avatar != "" {
|
||||||
if user.Avatar[0] == '.' {
|
if user.Avatar[0] == '.' {
|
||||||
|
@ -168,7 +168,7 @@ func (sus *MemoryUserStore) BulkCascadeGetMap(ids []int) (list map[int]*User, er
|
||||||
}
|
}
|
||||||
qlist = qlist[0:len(qlist) - 1]
|
qlist = qlist[0:len(qlist) - 1]
|
||||||
|
|
||||||
stmt, err := qgen.Builder.SimpleSelect("users","uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid IN("+qlist+")","","")
|
stmt, err := qgen.Builder.SimpleSelect("users","uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group","uid IN("+qlist+")","","")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func (sus *MemoryUserStore) BulkCascadeGetMap(ids []int) (list map[int]*User, er
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
user := &User{Loggedin:true}
|
user := &User{Loggedin:true}
|
||||||
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ func (sus *MemoryUserStore) BulkCascadeGetMap(ids []int) (list map[int]*User, er
|
||||||
|
|
||||||
func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
|
func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
|
||||||
user := &User{ID:id,Loggedin:true}
|
user := &User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
|
|
||||||
if user.Avatar != "" {
|
if user.Avatar != "" {
|
||||||
if user.Avatar[0] == '.' {
|
if user.Avatar[0] == '.' {
|
||||||
|
@ -251,7 +251,7 @@ func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
|
||||||
|
|
||||||
func (sus *MemoryUserStore) Load(id int) error {
|
func (sus *MemoryUserStore) Load(id int) error {
|
||||||
user := &User{ID:id,Loggedin:true}
|
user := &User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sus.Remove(id)
|
sus.Remove(id)
|
||||||
return err
|
return err
|
||||||
|
@ -378,7 +378,7 @@ type SqlUserStore struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSqlUserStore() *SqlUserStore {
|
func NewSqlUserStore() *SqlUserStore {
|
||||||
get_stmt, err := qgen.Builder.SimpleSelect("users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid = ?","","")
|
get_stmt, err := qgen.Builder.SimpleSelect("users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group","uid = ?","","")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -410,7 +410,7 @@ func NewSqlUserStore() *SqlUserStore {
|
||||||
|
|
||||||
func (sus *SqlUserStore) Get(id int) (*User, error) {
|
func (sus *SqlUserStore) Get(id int) (*User, error) {
|
||||||
user := User{ID:id,Loggedin:true}
|
user := User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
|
|
||||||
if user.Avatar != "" {
|
if user.Avatar != "" {
|
||||||
if user.Avatar[0] == '.' {
|
if user.Avatar[0] == '.' {
|
||||||
|
@ -427,7 +427,7 @@ func (sus *SqlUserStore) Get(id int) (*User, error) {
|
||||||
|
|
||||||
func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) {
|
func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) {
|
||||||
user := User{ID:id,Loggedin:true}
|
user := User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
|
|
||||||
if user.Avatar != "" {
|
if user.Avatar != "" {
|
||||||
if user.Avatar[0] == '.' {
|
if user.Avatar[0] == '.' {
|
||||||
|
@ -444,7 +444,7 @@ func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) {
|
||||||
|
|
||||||
func (sus *SqlUserStore) CascadeGet(id int) (*User, error) {
|
func (sus *SqlUserStore) CascadeGet(id int) (*User, error) {
|
||||||
user := User{ID:id,Loggedin:true}
|
user := User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
|
|
||||||
if user.Avatar != "" {
|
if user.Avatar != "" {
|
||||||
if user.Avatar[0] == '.' {
|
if user.Avatar[0] == '.' {
|
||||||
|
@ -469,7 +469,7 @@ func (sus *SqlUserStore) BulkCascadeGetMap(ids []int) (list map[int]*User, err e
|
||||||
}
|
}
|
||||||
qlist = qlist[0:len(qlist) - 1]
|
qlist = qlist[0:len(qlist) - 1]
|
||||||
|
|
||||||
stmt, err := qgen.Builder.SimpleSelect("users","uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid IN("+qlist+")","","")
|
stmt, err := qgen.Builder.SimpleSelect("users","uid, name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip, temp_group","uid IN("+qlist+")","","")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -482,7 +482,7 @@ func (sus *SqlUserStore) BulkCascadeGetMap(ids []int) (list map[int]*User, err e
|
||||||
list = make(map[int]*User)
|
list = make(map[int]*User)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
user := &User{Loggedin:true}
|
user := &User{Loggedin:true}
|
||||||
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := rows.Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -508,7 +508,7 @@ func (sus *SqlUserStore) BulkCascadeGetMap(ids []int) (list map[int]*User, err e
|
||||||
|
|
||||||
func (sus *SqlUserStore) BypassGet(id int) (*User, error) {
|
func (sus *SqlUserStore) BypassGet(id int) (*User, error) {
|
||||||
user := User{ID:id,Loggedin:true}
|
user := User{ID:id,Loggedin:true}
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
|
|
||||||
if user.Avatar != "" {
|
if user.Avatar != "" {
|
||||||
if user.Avatar[0] == '.' {
|
if user.Avatar[0] == '.' {
|
||||||
|
@ -525,9 +525,8 @@ func (sus *SqlUserStore) BypassGet(id int) (*User, error) {
|
||||||
|
|
||||||
func (sus *SqlUserStore) Load(id int) error {
|
func (sus *SqlUserStore) Load(id int) error {
|
||||||
user := &User{ID:id}
|
user := &User{ID:id}
|
||||||
// Simplify this into a quick check whether the user exists
|
// Simplify this into a quick check to see whether the user exists. Add an Exists method to facilitate this?
|
||||||
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
|
return sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP, &user.TempGroup)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sus *SqlUserStore) CreateUser(username string, password string, email string, group int, active int) (int, error) {
|
func (sus *SqlUserStore) CreateUser(username string, password string, email string, group int, active int) (int, error) {
|
||||||
|
|
Loading…
Reference in New Issue