Added the User Editor.
Added the EditUser, EditUserEmail, EditUserPassword, EditUserGroup, EditUserGroupSuperMod and EditUserGroupAdmin permissions. Allocations are now tracked in the benchmarks. The topics template is now tracked in the benchmarks. The entire topic, topics, forum and forums routes are now benchmarked. Initial attempts to benchmark the router have begun, I'll probably have a benchmark in a later commit without the fluff so that it's easier to see it's performance impact. Improved the security on some of the moderation routes. SettingLabel is now OptionLabel for easier reuse. Moved one of the inline queries into a prepared statement. Added the initial draft for the new router. Fixed a bug where you lose all of your guest permissions when your session is invalidated.
|
@ -98,7 +98,7 @@ Add a plugin system.
|
|||
|
||||
Tweak the CSS to make it responsive.
|
||||
|
||||
Nest the moderation routes to possibly speed routing up a little...?
|
||||
Implement a faster router.
|
||||
|
||||
Add a friend system.
|
||||
|
||||
|
|
20
data.sql
|
@ -102,14 +102,20 @@ CREATE TABLE `plugins`(
|
|||
INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool');
|
||||
INSERT INTO settings(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3',);
|
||||
|
||||
INSERT INTO users(`name`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`)
|
||||
VALUES ('Admin',1,1,NOW(),NOW(),'');
|
||||
INSERT INTO users(`name`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`)
|
||||
VALUES ('Admin','admin@localhost',1,1,NOW(),NOW(),'');
|
||||
|
||||
/*
|
||||
The Permissions:
|
||||
|
||||
BanUsers
|
||||
ActivateUsers
|
||||
EditUser
|
||||
EditUserEmail
|
||||
EditUserPassword
|
||||
EditUserGroup
|
||||
EditUserGroupSuperMod
|
||||
EditUserGroupAdmin
|
||||
ManageForums
|
||||
EditSettings
|
||||
ManagePlugins
|
||||
|
@ -126,11 +132,11 @@ PinTopic
|
|||
CloseTopic
|
||||
*/
|
||||
|
||||
INSERT INTO users_groups(`name`,`permissions`,`active`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"ManageForums":true,"EditSettings":true,"ManagePlugins":true,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,1,1,"Admin");
|
||||
INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,"Mod");
|
||||
INSERT INTO users_groups(`name`,`permissions`) VALUES ('Member','{"BanUsers":false,"ActivateUsers":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":true,"EditTopic":false,"DeleteTopic":false,"CreateReply":true,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
||||
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Banned','{"BanUsers":false,"ActivateUsers":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}',1);
|
||||
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
||||
INSERT INTO users_groups(`name`,`permissions`,`active`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManagePlugins":true,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,1,1,"Admin");
|
||||
INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":true,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,"Mod");
|
||||
INSERT INTO users_groups(`name`,`permissions`) VALUES ('Member','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":true,"EditTopic":false,"DeleteTopic":false,"CreateReply":true,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
||||
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Banned','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}',1);
|
||||
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
||||
|
||||
INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',NOW());
|
||||
INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`)
|
||||
|
|
237
general_test.go
|
@ -1,17 +1,24 @@
|
|||
package main
|
||||
//import "fmt"
|
||||
import "log"
|
||||
import "bytes"
|
||||
import "testing"
|
||||
import "net/http"
|
||||
import "net/http/httptest"
|
||||
import "io/ioutil"
|
||||
import "html/template"
|
||||
|
||||
func BenchmarkTemplates(b *testing.B) {
|
||||
user := User{0,"Bob",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
||||
admin := User{1,"Admin",0,true,true,true,true,true,false,AllPerms,"",false,"","","","",""}
|
||||
func BenchmarkTopicTemplate(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
||||
admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","",""}
|
||||
var noticeList map[int]string = make(map[int]string)
|
||||
noticeList[0] = "test"
|
||||
|
||||
topic := TopicUser{0,"Lol",template.HTML("Hey everyone!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
|
||||
|
||||
var replyList []interface{}
|
||||
var replyList []Reply
|
||||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
|
@ -23,65 +30,203 @@ func BenchmarkTemplates(b *testing.B) {
|
|||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
|
||||
|
||||
var replyList2 []Reply
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
replyList2 = append(replyList2, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||
|
||||
pi := Page{"Topic Blah","topic",user,noticeList,replyList,topic}
|
||||
pi2 := Page{"Topic Blah","topic",admin,noticeList,replyList,topic}
|
||||
tpage := TopicPage{"Topic Blah","topic",user,noticeList,replyList2,topic,false}
|
||||
tpage2 := TopicPage{"Topic Blah","topic",admin,noticeList,replyList2,topic,false}
|
||||
tpage := TopicPage{"Topic Blah","topic",user,noticeList,replyList,topic,false}
|
||||
tpage2 := TopicPage{"Topic Blah","topic",admin,noticeList,replyList,topic,false}
|
||||
w := ioutil.Discard
|
||||
|
||||
b.Run("compiled_useradmin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
template_topic_2(pi2,w)
|
||||
}
|
||||
})
|
||||
/*b.Run("interpreted_useradmin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates.ExecuteTemplate(w,"topic.html", pi2)
|
||||
}
|
||||
})*/
|
||||
b.Run("compiled_userguest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
template_topic_2(pi,w)
|
||||
}
|
||||
})
|
||||
/*b.Run("interpreted_userguest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates.ExecuteTemplate(w,"topic.html", pi)
|
||||
}
|
||||
})*/
|
||||
|
||||
|
||||
b.Run("compiled_customstruct_useradmin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
template_topic(tpage2,w)
|
||||
}
|
||||
})
|
||||
b.Run("interpreted_customstruct_useradmin", func(b *testing.B) {
|
||||
b.Run("interpreted_useradmin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates.ExecuteTemplate(w,"topic.html", tpage2)
|
||||
}
|
||||
})
|
||||
b.Run("compiled_customstruct_userguest", func(b *testing.B) {
|
||||
b.Run("compiled_userguest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
template_topic(tpage,w)
|
||||
}
|
||||
})
|
||||
b.Run("interpreted_customstruct_userguest", func(b *testing.B) {
|
||||
b.Run("interpreted_userguest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates.ExecuteTemplate(w,"topic.html", tpage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkTopicsTemplate(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
||||
admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","",""}
|
||||
var noticeList map[int]string = make(map[int]string)
|
||||
noticeList[0] = "test"
|
||||
|
||||
var topicList []interface{}
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||
|
||||
tpage := Page{"Topic Blah","topic",user,noticeList,topicList,0}
|
||||
tpage2 := Page{"Topic Blah","topic",admin,noticeList,topicList,0}
|
||||
w := ioutil.Discard
|
||||
|
||||
b.Run("compiled_useradmin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
template_topics(tpage2,w)
|
||||
}
|
||||
})
|
||||
b.Run("interpreted_useradmin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates.ExecuteTemplate(w,"topics.html", tpage2)
|
||||
}
|
||||
})
|
||||
b.Run("compiled_userguest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
template_topics(tpage,w)
|
||||
}
|
||||
})
|
||||
b.Run("interpreted_userguest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
templates.ExecuteTemplate(w,"topics.html", tpage)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkRoute(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
admin_uid_cookie := http.Cookie{Name: "uid",Value: "1",Path: "/",MaxAge: year}
|
||||
// TO-DO: Stop hard-coding this value
|
||||
admin_session_cookie := http.Cookie{Name: "session",Value: "TKBh5Z-qEQhWDBnV6_XVmOhKAowMYPhHeRlrQjjbNc0QRrRiglvWOYFDc1AaMXQIywvEsyA2AOBRYUrZ5kvnGhThY1GhOW6FSJADnRWm_bI=",Path: "/",MaxAge: year}
|
||||
|
||||
topic_w := httptest.NewRecorder()
|
||||
topic_req := httptest.NewRequest("get","/topic/1",bytes.NewReader(nil))
|
||||
topic_req_admin := topic_req
|
||||
topic_req_admin.AddCookie(&admin_uid_cookie)
|
||||
topic_req_admin.AddCookie(&admin_session_cookie)
|
||||
topic_handler := http.HandlerFunc(route_topic_id)
|
||||
|
||||
topics_w := httptest.NewRecorder()
|
||||
topics_req := httptest.NewRequest("get","/topics/",bytes.NewReader(nil))
|
||||
topics_req_admin := topics_req
|
||||
topics_req_admin.AddCookie(&admin_uid_cookie)
|
||||
topics_req_admin.AddCookie(&admin_session_cookie)
|
||||
topics_handler := http.HandlerFunc(route_topics)
|
||||
|
||||
forum_w := httptest.NewRecorder()
|
||||
forum_req := httptest.NewRequest("get","/forum/1",bytes.NewReader(nil))
|
||||
forum_req_admin := forum_req
|
||||
forum_req_admin.AddCookie(&admin_uid_cookie)
|
||||
forum_req_admin.AddCookie(&admin_session_cookie)
|
||||
forum_handler := http.HandlerFunc(route_forum)
|
||||
|
||||
forums_w := httptest.NewRecorder()
|
||||
forums_req := httptest.NewRequest("get","/forums/",bytes.NewReader(nil))
|
||||
forums_req_admin := forums_req
|
||||
forums_req_admin.AddCookie(&admin_uid_cookie)
|
||||
forums_req_admin.AddCookie(&admin_session_cookie)
|
||||
forums_handler := http.HandlerFunc(route_forums)
|
||||
|
||||
debug = false
|
||||
nogrouplog = true
|
||||
|
||||
// init_database is a little noisy for a benchmark
|
||||
discard := ioutil.Discard
|
||||
log.SetOutput(discard)
|
||||
|
||||
var err error
|
||||
init_database(err);
|
||||
external_sites["YT"] = "https://www.youtube.com/"
|
||||
hooks["trow_assign"] = nil
|
||||
hooks["rrow_assign"] = nil
|
||||
|
||||
for name, body := range plugins {
|
||||
if body.Active {
|
||||
plugins[name].Init()
|
||||
}
|
||||
}
|
||||
|
||||
b.Run("topic_admin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//topic_w.Code = 200
|
||||
topic_w.Body.Reset()
|
||||
topic_handler.ServeHTTP(topic_w,topic_req_admin)
|
||||
//if topic_w.Code != 200 {
|
||||
// fmt.Println(topic_w.Body)
|
||||
// panic("HTTP Error!")
|
||||
//}
|
||||
}
|
||||
})
|
||||
b.Run("topic_guest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//topic_w.Code = 200
|
||||
topic_w.Body.Reset()
|
||||
topic_handler.ServeHTTP(topic_w,topic_req)
|
||||
}
|
||||
})
|
||||
b.Run("topics_admin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//topics_w.Code = 200
|
||||
topics_w.Body.Reset()
|
||||
topics_handler.ServeHTTP(topics_w,topics_req_admin)
|
||||
}
|
||||
})
|
||||
b.Run("topics_guest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//topics_w.Code = 200
|
||||
topics_w.Body.Reset()
|
||||
topics_handler.ServeHTTP(topics_w,topics_req)
|
||||
}
|
||||
})
|
||||
b.Run("forum_admin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//forum_w.Code = 200
|
||||
forum_w.Body.Reset()
|
||||
forum_handler.ServeHTTP(forum_w,forum_req_admin)
|
||||
}
|
||||
})
|
||||
b.Run("forum_guest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//forum_w.Code = 200
|
||||
forum_w.Body.Reset()
|
||||
forum_handler.ServeHTTP(forum_w,forum_req)
|
||||
}
|
||||
})
|
||||
b.Run("forums_admin", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//forums_w.Code = 200
|
||||
forums_w.Body.Reset()
|
||||
forums_handler.ServeHTTP(forums_w,forums_req_admin)
|
||||
}
|
||||
})
|
||||
b.Run("forums_guest", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
//forums_w.Code = 200
|
||||
forums_w.Body.Reset()
|
||||
forums_handler.ServeHTTP(forums_w,forums_req)
|
||||
}
|
||||
})
|
||||
|
||||
serveMux := http.NewServeMux()
|
||||
serveMux.HandleFunc("/topics/", route_topics)
|
||||
b.Run("topics_guest_plus_router", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
topics_w.Body.Reset()
|
||||
serveMux.ServeHTTP(topics_w,topics_req)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*func TestRoute(b *testing.T) {
|
||||
|
||||
}*/
|
BIN
gosora.exe
13
group.go
|
@ -16,11 +16,18 @@ type Group struct
|
|||
Tag string
|
||||
}
|
||||
|
||||
// Permission Structure: ActionComponent[Subcomponent]Flag
|
||||
type Perms struct
|
||||
{
|
||||
// Global Permissions
|
||||
BanUsers bool
|
||||
ActivateUsers bool
|
||||
EditUser bool
|
||||
EditUserEmail bool
|
||||
EditUserPassword bool
|
||||
EditUserGroup bool
|
||||
EditUserGroupSuperMod bool
|
||||
EditUserGroupAdmin bool
|
||||
ManageForums bool // This could be local, albeit limited for per-forum managers
|
||||
EditSettings bool
|
||||
ManagePlugins bool
|
||||
|
@ -71,6 +78,12 @@ func init() {
|
|||
AllPerms = Perms{
|
||||
BanUsers: true,
|
||||
ActivateUsers: true,
|
||||
EditUser: true,
|
||||
EditUserEmail: true,
|
||||
EditUserPassword: true,
|
||||
EditUserGroup: true,
|
||||
EditUserGroupSuperMod: true,
|
||||
EditUserGroupAdmin: true,
|
||||
ManageForums: true,
|
||||
EditSettings: true,
|
||||
ManagePlugins: true,
|
||||
|
|
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 23 KiB |
4
main.go
|
@ -21,6 +21,7 @@ const kilobyte int = 1024
|
|||
const megabyte int = 1024 * 1024
|
||||
const saltLength int = 32
|
||||
const sessionLength int = 80
|
||||
var nogrouplog bool = false // This is mainly for benchmarks, as we don't want a lot of information getting in the way of the results
|
||||
|
||||
var templates = template.Must(template.ParseGlob("templates/*"))
|
||||
var no_css_tmpl = template.CSS("")
|
||||
|
@ -39,7 +40,7 @@ var template_profile_handle func(Page,io.Writer) = nil
|
|||
|
||||
func compile_templates() {
|
||||
var c CTemplateSet
|
||||
user := User{0,"",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
||||
user := User{0,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
||||
var noticeList map[int]string = make(map[int]string)
|
||||
noticeList[0] = "test"
|
||||
|
||||
|
@ -206,6 +207,7 @@ func main(){
|
|||
http.HandleFunc("/panel/plugins/deactivate/", route_panel_plugins_deactivate)
|
||||
http.HandleFunc("/panel/users/", route_panel_users)
|
||||
http.HandleFunc("/panel/users/edit/", route_panel_users_edit)
|
||||
http.HandleFunc("/panel/users/edit/submit/", route_panel_users_edit_submit)
|
||||
|
||||
http.HandleFunc("/", default_route)
|
||||
|
||||
|
|
170
mod_routes.go
|
@ -446,6 +446,11 @@ func route_unban(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
uid, err := strconv.Atoi(r.URL.Path[len("/users/unban/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided User ID is not a valid number.",w,r,user)
|
||||
|
@ -486,6 +491,11 @@ func route_activate(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
uid, err := strconv.Atoi(r.URL.Path[len("/users/activate/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided User ID is not a valid number.",w,r,user)
|
||||
|
@ -678,7 +688,6 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
forum_name := r.PostFormValue("edit_item")
|
||||
|
||||
forum, ok := forums[fid];
|
||||
if !ok {
|
||||
LocalError("The forum you're trying to edit doesn't exist.",w,r,user)
|
||||
|
@ -790,7 +799,7 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request){
|
|||
|
||||
labels := strings.Split(llist,",")
|
||||
for index, label := range labels {
|
||||
itemList = append(itemList, SettingLabel{
|
||||
itemList = append(itemList, OptionLabel{
|
||||
Label: label,
|
||||
Value: index + 1,
|
||||
Selected: conv == (index + 1),
|
||||
|
@ -887,6 +896,11 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){
|
|||
return
|
||||
}
|
||||
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
uname := r.URL.Path[len("/panel/plugins/activate/"):]
|
||||
plugin, ok := plugins[uname]
|
||||
if !ok {
|
||||
|
@ -945,6 +959,11 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request){
|
|||
return
|
||||
}
|
||||
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
uname := r.URL.Path[len("/panel/plugins/deactivate/"):]
|
||||
plugin, ok := plugins[uname]
|
||||
if !ok {
|
||||
|
@ -990,7 +1009,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){
|
|||
}
|
||||
|
||||
var userList []interface{}
|
||||
rows, err := db.Query("SELECT `uid`, `name`, `group`, `active`, `is_super_admin`, `avatar` FROM users")
|
||||
rows, err := db.Query("SELECT `uid`,`name`,`group`,`active`,`is_super_admin`,`avatar` FROM users")
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
|
@ -1043,5 +1062,150 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){
|
|||
}
|
||||
|
||||
func route_panel_users_edit(w http.ResponseWriter, r *http.Request){
|
||||
user, noticeList, ok := SessionCheck(w,r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with
|
||||
if !user.Is_Super_Mod || !user.Perms.EditUser {
|
||||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
targetUser := User{ID: 0,}
|
||||
targetUser.ID, err = strconv.Atoi(r.URL.Path[len("/panel/users/edit/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided User ID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = db.QueryRow("SELECT `name`, `email`, `group` from `users` where `uid` = ?", targetUser.ID).Scan(&targetUser.Name, &targetUser.Email, &targetUser.Group)
|
||||
if err == sql.ErrNoRows {
|
||||
LocalError("The user you're trying to edit doesn't exist.",w,r,user)
|
||||
return
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
targetUser.Is_Admin = targetUser.Is_Super_Admin || groups[targetUser.Group].Is_Admin
|
||||
targetUser.Is_Super_Mod = groups[targetUser.Group].Is_Mod || targetUser.Is_Admin
|
||||
if targetUser.Is_Admin && !user.Is_Admin {
|
||||
LocalError("Only administrators can edit the account of an administrator.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
var groupList []interface{}
|
||||
for _, group := range groups {
|
||||
if !user.Perms.EditUserGroupAdmin && group.Is_Admin {
|
||||
continue
|
||||
}
|
||||
if !user.Perms.EditUserGroupSuperMod && group.Is_Mod {
|
||||
continue
|
||||
}
|
||||
groupList = append(groupList, group)
|
||||
}
|
||||
|
||||
pi := Page{"User Editor","panel-user-edit",user,noticeList,groupList,targetUser}
|
||||
err = templates.ExecuteTemplate(w,"panel-user-edit.html", pi)
|
||||
if err != nil {
|
||||
InternalError(err, w, r, user)
|
||||
}
|
||||
}
|
||||
|
||||
func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request){
|
||||
user, ok := SimpleSessionCheck(w,r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !user.Is_Super_Mod || !user.Perms.EditUser {
|
||||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
targetUser := User{ID: 0,}
|
||||
targetUser.ID, err = strconv.Atoi(r.URL.Path[len("/panel/users/edit/submit/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided User ID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = db.QueryRow("SELECT `name`, `email`, `group` from `users` where `uid` = ?", targetUser.ID).Scan(&targetUser.Name, &targetUser.Email, &targetUser.Group)
|
||||
if err == sql.ErrNoRows {
|
||||
LocalError("The user you're trying to edit doesn't exist.",w,r,user)
|
||||
return
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
targetUser.Is_Admin = targetUser.Is_Super_Admin || groups[targetUser.Group].Is_Admin
|
||||
targetUser.Is_Super_Mod = groups[targetUser.Group].Is_Mod || targetUser.Is_Admin
|
||||
if targetUser.Is_Admin && !user.Is_Admin {
|
||||
LocalError("Only administrators can edit the account of an administrator.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
newname := html.EscapeString(r.PostFormValue("user-name"))
|
||||
if newname == "" {
|
||||
LocalError("You didn't put in a username.", w, r, user)
|
||||
return
|
||||
}
|
||||
|
||||
newemail := html.EscapeString(r.PostFormValue("user-email"))
|
||||
if newemail == "" {
|
||||
LocalError("You didn't put in an email address.", w, r, user)
|
||||
return
|
||||
}
|
||||
if (newemail != targetUser.Email) && !user.Perms.EditUserEmail {
|
||||
LocalError("You need the EditUserEmail permission to edit the email address of a user.", w, r, user)
|
||||
return
|
||||
}
|
||||
|
||||
newpassword := r.PostFormValue("user-password")
|
||||
if newpassword != "" && !user.Perms.EditUserPassword {
|
||||
LocalError("You need the EditUserPassword permission to edit the password of a user.", w, r, user)
|
||||
return
|
||||
}
|
||||
|
||||
newgroup, err := strconv.Atoi(r.PostFormValue("user-group"))
|
||||
if err != nil {
|
||||
LocalError("The provided GroupID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok = groups[newgroup]
|
||||
if !ok {
|
||||
LocalError("The group you're trying to place this user in doesn't exist.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
if !user.Perms.EditUserGroupAdmin && groups[newgroup].Is_Admin {
|
||||
LocalError("You need the EditUserGroupAdmin permission to assign someone to an administrator group.",w,r,user)
|
||||
return
|
||||
}
|
||||
if !user.Perms.EditUserGroupSuperMod && groups[newgroup].Is_Mod {
|
||||
LocalError("You need the EditUserGroupAdmin permission to assign someone to a super mod group.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = update_user_stmt.Exec(newname,newemail,newgroup,targetUser.ID)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
if newpassword != "" {
|
||||
SetPassword(targetUser.ID, newpassword)
|
||||
}
|
||||
|
||||
http.Redirect(w,r,"/panel/users/edit/" + strconv.Itoa(targetUser.ID),http.StatusSeeOther)
|
||||
}
|
24
mysql.go
|
@ -9,6 +9,7 @@ import "encoding/json"
|
|||
|
||||
var db *sql.DB
|
||||
var get_session_stmt *sql.Stmt
|
||||
var get_topic_list_stmt *sql.Stmt
|
||||
var create_topic_stmt *sql.Stmt
|
||||
var create_report_stmt *sql.Stmt
|
||||
var create_reply_stmt *sql.Stmt
|
||||
|
@ -40,6 +41,7 @@ var update_forum_stmt *sql.Stmt
|
|||
var update_setting_stmt *sql.Stmt
|
||||
var add_plugin_stmt *sql.Stmt
|
||||
var update_plugin_stmt *sql.Stmt
|
||||
var update_user_stmt *sql.Stmt
|
||||
|
||||
func init_database(err error) {
|
||||
if(dbpassword != ""){
|
||||
|
@ -57,13 +59,19 @@ func init_database(err error) {
|
|||
}
|
||||
|
||||
log.Print("Preparing get_session statement.")
|
||||
get_session_stmt, err = db.Prepare("SELECT `uid`, `name`, `group`, `is_super_admin`, `session`, `avatar`, `message`, `url_prefix`, `url_name` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''")
|
||||
get_session_stmt, err = db.Prepare("select `uid`, `name`, `group`, `is_super_admin`, `session`, `avatar`, `message`, `url_prefix`, `url_name` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Preparing get_topic_list statement.")
|
||||
get_topic_list_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Preparing create_topic statement.")
|
||||
create_topic_stmt, err = db.Prepare("INSERT INTO topics(title,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)")
|
||||
create_topic_stmt, err = db.Prepare("insert into topics(title,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -245,6 +253,12 @@ func init_database(err error) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Preparing update_user statement.")
|
||||
update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?, `email` = ?, `group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Loading the usergroups.")
|
||||
rows, err := db.Query("SELECT gid,name,permissions,is_mod,is_admin,is_banned,tag FROM users_groups")
|
||||
if err != nil {
|
||||
|
@ -264,8 +278,10 @@ func init_database(err error) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(group.Name + ": ")
|
||||
fmt.Printf("%+v\n", group.Perms)
|
||||
if !nogrouplog {
|
||||
fmt.Println(group.Name + ": ")
|
||||
fmt.Printf("%+v\n", group.Perms)
|
||||
}
|
||||
|
||||
group.Perms.ExtData = make(map[string]bool)
|
||||
groups[group.ID] = group
|
||||
|
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
/*import "sync"
|
||||
import "net/http"
|
||||
|
||||
type Router struct {
|
||||
mu sync.RWMutex
|
||||
routes map[string]http.Handler
|
||||
}
|
||||
|
||||
func (route *Router) ServeHTTP() {
|
||||
route.mu.RLock()
|
||||
defer route.mu.RUnlock()
|
||||
|
||||
if path[0] != "/" {
|
||||
return route.routes["/"]
|
||||
}
|
||||
|
||||
// Do something on the path to turn slashes facing the wrong way "\" into "/" slashes. If it's bytes, then alter the bytes in place for the maximum speed
|
||||
|
||||
handle := route.routes[path]
|
||||
if !ok {
|
||||
if path[-1] != "/" {
|
||||
handle = route.routes[path + "/"]
|
||||
if !ok {
|
||||
return route.routes["/"]
|
||||
}
|
||||
return handle
|
||||
}
|
||||
}
|
||||
return handle
|
||||
}*/
|
|
@ -98,7 +98,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){
|
|||
avatar string
|
||||
)
|
||||
|
||||
rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC")
|
||||
rows, err := get_topic_list_stmt.Query()
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
|
@ -287,14 +287,16 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
|||
|
||||
replyList []Reply
|
||||
)
|
||||
topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
|
||||
|
||||
topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
|
||||
topic.ID, err = strconv.Atoi(r.URL.Path[len("/topic/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided TopicID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
if !user.Perms.ViewTopic {
|
||||
//fmt.Printf("%+v\n", user)
|
||||
//fmt.Printf("%+v\n", user.Perms)
|
||||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import "strings"
|
|||
|
||||
var settingLabels map[string]string
|
||||
|
||||
type SettingLabel struct
|
||||
type OptionLabel struct
|
||||
{
|
||||
Label string
|
||||
Value int
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
package main
|
||||
import "io"
|
||||
import "strconv"
|
||||
import "html/template"
|
||||
|
||||
/*func init() {
|
||||
ctemplates["topic"] = template_topic
|
||||
}*/
|
||||
|
||||
func template_topic_2(tmpl_topic_vars Page, w io.Writer) {
|
||||
var extra_data TopicUser = tmpl_topic_vars.Something.(TopicUser)
|
||||
w.Write([]byte(`<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>` + tmpl_topic_vars.Title + `</title>
|
||||
<link href="/static/main.css" rel="stylesheet" type="text/css">
|
||||
<script type="text/javascript" src="/static/jquery-1.12.3.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var session = "` + tmpl_topic_vars.CurrentUser.Session + `";
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/global.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="nav">
|
||||
<div class="move_left">
|
||||
<div class="move_right">
|
||||
<ul>
|
||||
<li class="menu_left menu_overview"><a href="/">Overview</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_create_topic"><a href="/topics/create/">Create Topic</a></li>
|
||||
`))
|
||||
if tmpl_topic_vars.CurrentUser.Loggedin {
|
||||
w.Write([]byte(`
|
||||
<li class="menu_left menu_account"><a href="/user/edit/critical/">Account</a></li>
|
||||
<li class="menu_left menu_account"><a href="/user/` + strconv.Itoa(tmpl_topic_vars.CurrentUser.ID) + `">Profile</a></li>
|
||||
`))
|
||||
if tmpl_topic_vars.CurrentUser.Is_Super_Mod {
|
||||
w.Write([]byte(`<li class="menu_left menu_account"><a href="/panel/forums/">Panel</a></li>`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
<li class="menu_left menu_logout"><a href="/accounts/logout?session=` + tmpl_topic_vars.CurrentUser.Session + `">Logout</a></li>
|
||||
`))
|
||||
} else {
|
||||
w.Write([]byte(`
|
||||
<li class="menu_left menu_register"><a href="/accounts/create/">Register</a></li>
|
||||
<li class="menu_left menu_login"><a href="/accounts/login/">Login</a></li>
|
||||
`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
`))
|
||||
if len(tmpl_topic_vars.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topic_vars.NoticeList {
|
||||
w.Write([]byte(`<div class="alert">` + item + `</div>`))
|
||||
}
|
||||
}
|
||||
w.Write([]byte(`
|
||||
<div class="rowblock">
|
||||
<form action='/topic/edit/submit/` + strconv.Itoa(extra_data.ID) + `' method="post">
|
||||
<div class="rowitem"`))
|
||||
if extra_data.Sticky {
|
||||
w.Write([]byte(` style="background-color: #FFFFEA;"`))
|
||||
}
|
||||
w.Write([]byte(`>
|
||||
<a class='topic_name hide_on_edit'>` + extra_data.Title + `</a>
|
||||
<span class='username topic_status_e topic_status_` + extra_data.Status + ` hide_on_edit' style="font-weight:normal;float: right;">` + extra_data.Status + `</span>
|
||||
<span class="username" style="border-right: 0;font-weight: normal;float: right;">Status</span>
|
||||
`))
|
||||
if tmpl_topic_vars.CurrentUser.Is_Mod {
|
||||
w.Write([]byte(`
|
||||
<a href='/topic/edit/` + strconv.Itoa(extra_data.ID) + `' class="username hide_on_edit open_edit" style="font-weight: normal;margin-left: 6px;">Edit</a>
|
||||
<a href='/topic/delete/submit/` + strconv.Itoa(extra_data.ID) + `' class="username" style="font-weight: normal;">Delete</a>
|
||||
`))
|
||||
if extra_data.Sticky {
|
||||
w.Write([]byte(`<a href='/topic/unstick/submit/` + strconv.Itoa(extra_data.ID) + `' class="username" style="font-weight: normal;">Unpin</a>`))
|
||||
} else {
|
||||
w.Write([]byte(`<a href='/topic/stick/submit/` + strconv.Itoa(extra_data.ID) + `' class="username" style="font-weight: normal;">Pin</a>`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
|
||||
<input class='show_on_edit topic_name_input' name="topic_name" value='` + extra_data.Title + `' type="text" />
|
||||
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
||||
<option>open</option>
|
||||
<option>closed</option>
|
||||
</select>
|
||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
||||
`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
<a href="/report/submit/` + strconv.Itoa(extra_data.ID) + `?session=` + tmpl_topic_vars.CurrentUser.Session + `&type=topic" class="username report_item" style="font-weight: normal;">Report</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
<div class="rowitem passive editable_parent" style="border-bottom: none;`))
|
||||
if extra_data.Avatar != "" {
|
||||
w.Write([]byte(`background-image: url(` + extra_data.Avatar + `), url(/static/white-dot.jpg);background-position: 0px `))
|
||||
if extra_data.ContentLines <= 5 {
|
||||
w.Write([]byte(`-1`))
|
||||
}
|
||||
w.Write([]byte(`0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;` + string(extra_data.Css)))
|
||||
}
|
||||
w.Write([]byte(`">
|
||||
<span class="hide_on_edit topic_content user_content">` + string(extra_data.Content.(template.HTML)) + `</span>
|
||||
<textarea name="topic_content" class="show_on_edit topic_content_input">` + string(extra_data.Content.(template.HTML)) + `</textarea>
|
||||
<br /><br />
|
||||
<a href="/user/` + strconv.Itoa(extra_data.CreatedBy) + `" class="username">` + extra_data.CreatedByName + `</a>
|
||||
`))
|
||||
if extra_data.Tag != "" {
|
||||
w.Write([]byte(`<a class="username" style="float: right;">` + extra_data.Tag + `</a>`))
|
||||
} else {
|
||||
if extra_data.URLName != "" {
|
||||
w.Write([]byte(`<a href="` + extra_data.URL + `" class="username" style="color: #505050;float: right;">` + extra_data.URLName + `</a>
|
||||
<a class="username" style="color: #505050;float: right;border-right: 0;">` + extra_data.URLPrefix + `</a>`))
|
||||
}
|
||||
}
|
||||
w.Write([]byte(`
|
||||
</div>
|
||||
</div><br />
|
||||
<div class="rowblock" style="overflow: hidden;">
|
||||
`))
|
||||
if len(tmpl_topic_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_topic_vars.ItemList {
|
||||
w.Write([]byte(`
|
||||
<div class="rowitem passive deletable_block editable_parent" style="`))
|
||||
if item.(Reply).Avatar != "" {
|
||||
w.Write([]byte(`background-image: url(` + item.(Reply).Avatar + `), url(/static/white-dot.jpg);background-position: 0px `))
|
||||
if item.(Reply).ContentLines <= 5 {
|
||||
w.Write([]byte(`-1`))
|
||||
}
|
||||
w.Write([]byte(`0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;` + string(item.(Reply).Css)))
|
||||
}
|
||||
w.Write([]byte(`">
|
||||
<span class="editable_block user_content">` + string(item.(Reply).ContentHtml) + `</span>
|
||||
<br /><br />
|
||||
<a href="/user/` + strconv.Itoa(item.(Reply).CreatedBy) + `" class="username">` + item.(Reply).CreatedByName + `</a>
|
||||
`))
|
||||
if tmpl_topic_vars.CurrentUser.Is_Mod {
|
||||
w.Write([]byte(`<a href="/reply/edit/submit/` + strconv.Itoa(item.(Reply).ID) + `"><button class="username edit_item">Edit</button></a>
|
||||
<a href="/reply/delete/submit/` + strconv.Itoa(item.(Reply).ID) + `"><button class="username delete_item">Delete</button></a>`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
<a href="/report/submit/` + strconv.Itoa(item.(Reply).ID) + `?session=` + tmpl_topic_vars.CurrentUser.Session + `&type=reply"><button class="username report_item">Report</button></a>
|
||||
`))
|
||||
if item.(Reply).Tag != "" {
|
||||
w.Write([]byte(`<a class="username" style="float: right;">` + item.(Reply).Tag + `</a>`))
|
||||
} else {
|
||||
if item.(Reply).URLName != "" {
|
||||
w.Write([]byte(`<a href="` + item.(Reply).URL + `" class="username" style="color: #505050;float: right;" rel="nofollow">` + item.(Reply).URLName + `</a>
|
||||
<a class="username" style="color: #505050;float: right;border-right: 0;">` + item.(Reply).URLPrefix + `</a>`))
|
||||
}
|
||||
}
|
||||
w.Write([]byte(`
|
||||
</div>`))
|
||||
}
|
||||
}
|
||||
w.Write([]byte(`
|
||||
</div>
|
||||
`))
|
||||
if !tmpl_topic_vars.CurrentUser.Is_Banned && tmpl_topic_vars.CurrentUser.Loggedin {
|
||||
w.Write([]byte(`
|
||||
<div class="rowblock">
|
||||
<form action="/reply/create/" method="post">
|
||||
<input name="tid" value='` + strconv.Itoa(extra_data.ID) + `' type="hidden" />
|
||||
<div class="formrow">
|
||||
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem"><button name="reply-button" class="formbutton">Create Reply</button></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`))
|
||||
}
|
||||
w.Write([]byte(`
|
||||
<!--<link rel="stylesheet" href="https://use.fontawesome.com/8670aa03ca.css">-->
|
||||
</div>
|
||||
</body>
|
||||
</html>`))
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="colblock_left">
|
||||
<div class="rowitem"><a>Control Panel</a></div>
|
||||
<div class="rowitem passive"><a href="/panel/forums/">Forums</a></div>
|
||||
<div class="rowitem passive"><a href="/panel/settings/">Settings</a></div>
|
||||
<div class="rowitem passive"><a href="/panel/plugins/">Plugins</a></div>
|
||||
<div class="rowitem passive"><a href="/panel/users/">Users</a></div>
|
||||
<div class="rowitem passive"><a href="/panel/groups/">Groups</a></div>
|
||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a href="/forum/-1">Reports</a></div>
|
||||
</div>
|
||||
<div class="colblock_right">
|
||||
<div class="rowitem"><a>User Editor</a></div>
|
||||
</div>
|
||||
<div class="colblock_right">
|
||||
<form action="/panel/users/edit/submit/{{.Something.ID}}?session={{.CurrentUser.Session}}" method="post">
|
||||
<div class="formrow">
|
||||
<div class="formitem"><a>Name</a></div>
|
||||
<div class="formitem"><input name="user-name" type="text" value="{{.Something.Name}}" placeholder="Jane Doe" /></div>
|
||||
</div>
|
||||
{{if .CurrentUser.Perms.EditUserPassword}}<div class="formrow">
|
||||
<div class="formitem"><a>Password</a></div>
|
||||
<div class="formitem"><input name="user-password" type="password" placeholder="*****" /></div>
|
||||
</div>{{end}}
|
||||
{{if .CurrentUser.Perms.EditUserEmail}}<div class="formrow">
|
||||
<div class="formitem"><a>Email</a></div>
|
||||
<div class="formitem"><input name="user-email" type="email" value="{{.Something.Email}}" placeholder="example@localhost" /></div>
|
||||
</div>{{end}}
|
||||
{{if .CurrentUser.Perms.EditUserGroup}}
|
||||
<div class="formrow">
|
||||
<div class="formitem"><a>Group</a></div>
|
||||
<div class="formitem">
|
||||
<select name="user-group">
|
||||
{{range .ItemList}}<option {{if eq .ID $.Something.Group}}selected {{end}}value="{{.ID}}">{{.Name}}</option>{{end}}
|
||||
</select>
|
||||
</div>
|
||||
</div>{{end}}
|
||||
<div class="formrow">
|
||||
<div class="formitem"><button name="panel-button" class="formbutton">Update User</div></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{template "footer.html" . }}
|
|
@ -17,7 +17,7 @@
|
|||
<div class="colblock_right">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem editable_parent" style="font-weight: normal;text-transform: none;">
|
||||
<a href="/panel/users/edit/{{.ID}}?session={{$.CurrentUser.Session}}" class="editable_block" style="font-size: 20px;position:relative;top: -2px;">{{.Name}}</a>
|
||||
<a {{if $.CurrentUser.Perms.EditUser}}href="/panel/users/edit/{{.ID}}?session={{$.CurrentUser.Session}} "{{end}}class="editable_block" style="font-size: 20px;position:relative;top: -2px;">{{.Name}}</a>
|
||||
<a href="/user/{{.ID}}" class="tag-mini" style="margin-left: 3px;position: relative;top:-5px;color: #505050;">Profile</a>
|
||||
{{if .Tag}}<span class="username" style="margin-left 4px;{{if (.Is_Super_Mod) and (.Active)}}float: right;{{end}}">{{.Tag}}</span>{{end}}
|
||||
<span style="float: right;">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="rowitem passive">
|
||||
<a class="username">Add Friend</a>
|
||||
{{if (.CurrentUser.Is_Super_Mod) and not (.Something.Is_Super_Mod) }}
|
||||
{{if .Something.Is_Banned }}<a href="/users/unban/{{.Something.ID}}" class="username">Unban</a>{{else}}<a href="/users/ban/{{.Something.ID}}" class="username">Ban</a>{{end}}
|
||||
{{if .Something.Is_Banned }}<a href="/users/unban/{{.Something.ID}}?session={{.CurrentUser.Session}}" class="username">Unban</a>{{else}}<a href="/users/ban/{{.Something.ID}}?session={{.CurrentUser.Session}}" class="username">Ban</a>{{end}}
|
||||
{{end}}
|
||||
<a href="/report/submit/{{.Something.ID}}?session={{.CurrentUser.Session}}&type=user" class="username report_item">Report</a>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,657 @@
|
|||
package main
|
||||
import "log"
|
||||
import "fmt"
|
||||
import "strings"
|
||||
import "reflect"
|
||||
import "path/filepath"
|
||||
import "io/ioutil"
|
||||
import "text/template/parse"
|
||||
|
||||
/* Keeping this so I can benchmark against it */
|
||||
|
||||
type CTemplateSet2 struct
|
||||
{
|
||||
tlist map[string]*parse.Tree
|
||||
dir string
|
||||
funcMap map[string]interface{}
|
||||
importMap map[string]string
|
||||
varList map[string]VarItem
|
||||
localVars map[string]map[string]VarItemReflect
|
||||
//tempVars map[string]string
|
||||
doImports bool
|
||||
expectsInt interface{}
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_template_2(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string) {
|
||||
c.dir = dir
|
||||
c.doImports = true
|
||||
c.funcMap = make(map[string]interface{})
|
||||
c.funcMap["and"] = "&&"
|
||||
c.funcMap["not"] = "!"
|
||||
c.funcMap["or"] = "||"
|
||||
c.funcMap["eq"] = true
|
||||
c.funcMap["ge"] = true
|
||||
c.funcMap["gt"] = true
|
||||
c.funcMap["le"] = true
|
||||
c.funcMap["lt"] = true
|
||||
c.funcMap["ne"] = true
|
||||
c.importMap = make(map[string]string)
|
||||
c.importMap["strconv"] = "strconv"
|
||||
c.varList = varList
|
||||
c.expectsInt = expectsInt
|
||||
holdreflect := reflect.ValueOf(expectsInt)
|
||||
|
||||
res, err := ioutil.ReadFile(dir + name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
content := string(res)
|
||||
|
||||
tree := parse.New(name, c.funcMap)
|
||||
var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree)
|
||||
tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println(name)
|
||||
}
|
||||
|
||||
out = ""
|
||||
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
||||
c.tlist = make(map[string]*parse.Tree)
|
||||
c.tlist[fname] = tree
|
||||
varholder := "tmpl_" + fname + "_vars"
|
||||
|
||||
if debug {
|
||||
fmt.Println(c.tlist)
|
||||
}
|
||||
|
||||
c.localVars = make(map[string]map[string]VarItemReflect)
|
||||
c.localVars[fname] = make(map[string]VarItemReflect)
|
||||
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
||||
|
||||
subtree := c.tlist[fname]
|
||||
if debug {
|
||||
fmt.Println(subtree.Root)
|
||||
}
|
||||
|
||||
for _, node := range subtree.Root.Nodes {
|
||||
if debug {
|
||||
fmt.Println("Node: " + node.String())
|
||||
}
|
||||
out += c.compile_switch(varholder, holdreflect, fname, node)
|
||||
}
|
||||
|
||||
var importList string
|
||||
if c.doImports {
|
||||
for _, item := range c.importMap {
|
||||
importList += "import \"" + item + "\"\n"
|
||||
}
|
||||
}
|
||||
|
||||
var varString string
|
||||
for _, varItem := range c.varList {
|
||||
varString += "var " + varItem.Name + " " + varItem.Type + " = " + varItem.Destination + "\n"
|
||||
}
|
||||
|
||||
out = "package main\n" + importList + "\nfunc init() {\nctemplates[\"" + fname + "\"] = template_" + fname + "\n}\n\nfunc template_" + fname + "(tmpl_" + fname + "_vars " + expects + ") (tmpl string) {\n" + varString + out + "return tmpl\n}\n"
|
||||
if debug {
|
||||
fmt.Println("Output!")
|
||||
fmt.Println(out)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) {
|
||||
switch node := node.(type) {
|
||||
case *parse.ActionNode:
|
||||
if debug {
|
||||
fmt.Println("Action Node")
|
||||
}
|
||||
|
||||
if node.Pipe == nil {
|
||||
break
|
||||
}
|
||||
for _, cmd := range node.Pipe.Cmds {
|
||||
out += c.compile_subswitch(varholder, holdreflect, template_name, cmd)
|
||||
}
|
||||
return out
|
||||
case *parse.IfNode:
|
||||
if debug {
|
||||
fmt.Println("If Node: ")
|
||||
fmt.Println(node.Pipe)
|
||||
}
|
||||
|
||||
var expr string
|
||||
for _, cmd := range node.Pipe.Cmds {
|
||||
if debug {
|
||||
fmt.Println("If Node Bit: ")
|
||||
fmt.Println(cmd)
|
||||
fmt.Println(reflect.ValueOf(cmd).Type().Name())
|
||||
}
|
||||
expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd)
|
||||
}
|
||||
|
||||
if node.ElseList == nil {
|
||||
if debug {
|
||||
fmt.Println("Branch 1")
|
||||
}
|
||||
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n"
|
||||
} else {
|
||||
if debug {
|
||||
fmt.Println("Branch 2")
|
||||
}
|
||||
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
|
||||
}
|
||||
case *parse.ListNode:
|
||||
if debug {
|
||||
fmt.Println("List Node")
|
||||
}
|
||||
for _, subnode := range node.Nodes {
|
||||
out += c.compile_switch(varholder, holdreflect, template_name, subnode)
|
||||
}
|
||||
return out
|
||||
case *parse.RangeNode:
|
||||
if debug {
|
||||
fmt.Println("Range Node!")
|
||||
fmt.Println(node.Pipe)
|
||||
}
|
||||
|
||||
var outVal reflect.Value
|
||||
for _, cmd := range node.Pipe.Cmds {
|
||||
if debug {
|
||||
fmt.Println("Range Bit: ")
|
||||
fmt.Println(cmd)
|
||||
}
|
||||
out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd)
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println("Returned: ")
|
||||
fmt.Println(out)
|
||||
fmt.Println("Range Kind Switch!")
|
||||
}
|
||||
|
||||
switch outVal.Kind() {
|
||||
case reflect.Map:
|
||||
var item reflect.Value
|
||||
for _, key := range outVal.MapKeys() {
|
||||
item = outVal.MapIndex(key)
|
||||
}
|
||||
|
||||
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}"
|
||||
case reflect.Invalid:
|
||||
return ""
|
||||
}
|
||||
|
||||
if node.ElseList != nil {
|
||||
out += " else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
|
||||
} else {
|
||||
out += "\n"
|
||||
}
|
||||
return out
|
||||
case *parse.TemplateNode:
|
||||
if debug {
|
||||
fmt.Println("Template Node")
|
||||
}
|
||||
return c.compile_subtemplate(varholder, holdreflect, node)
|
||||
case *parse.TextNode:
|
||||
return "tmpl += `" + string(node.Text) + "`\n"
|
||||
default:
|
||||
panic("Unknown Node in main switch")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
||||
firstWord := node.Args[0]
|
||||
switch n := firstWord.(type) {
|
||||
case *parse.FieldNode:
|
||||
if debug {
|
||||
fmt.Println("Field Node: ")
|
||||
fmt.Println(n.Ident)
|
||||
}
|
||||
|
||||
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
||||
cur := holdreflect
|
||||
|
||||
var varbit string
|
||||
if cur.Kind() == reflect.Interface {
|
||||
cur = cur.Elem()
|
||||
varbit += ".(" + cur.Type().Name() + ")"
|
||||
}
|
||||
|
||||
for _, id := range n.Ident {
|
||||
if debug {
|
||||
fmt.Println("Data Kind: ")
|
||||
fmt.Println(cur.Kind().String())
|
||||
fmt.Println("Field Bit: ")
|
||||
fmt.Println(id)
|
||||
}
|
||||
|
||||
cur = cur.FieldByName(id)
|
||||
if cur.Kind() == reflect.Interface {
|
||||
cur = cur.Elem()
|
||||
/*if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
||||
varbit = "string(" + varbit + "." + id + ")"*/
|
||||
//if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
||||
if cur.Type().PkgPath() != "main" {
|
||||
c.importMap["html/template"] = "html/template"
|
||||
varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(),"html/") + "." + cur.Type().Name() + ")"
|
||||
} else {
|
||||
varbit += "." + id + ".(" + cur.Type().Name() + ")"
|
||||
}
|
||||
} else {
|
||||
varbit += "." + id
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println("End Cycle")
|
||||
}
|
||||
}
|
||||
out = c.compile_varsub(varholder + varbit, cur)
|
||||
|
||||
for _, varItem := range c.varList {
|
||||
if strings.HasPrefix(out, varItem.Destination) {
|
||||
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
||||
}
|
||||
}
|
||||
return out
|
||||
case *parse.DotNode:
|
||||
if debug {
|
||||
fmt.Println("Dot Node")
|
||||
fmt.Println(node.String())
|
||||
}
|
||||
return c.compile_varsub(varholder, holdreflect)
|
||||
case *parse.NilNode:
|
||||
panic("Nil is not a command x.x")
|
||||
case *parse.VariableNode:
|
||||
if debug {
|
||||
fmt.Println("Variable Node")
|
||||
fmt.Println(n.String())
|
||||
fmt.Println(n.Ident)
|
||||
}
|
||||
|
||||
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
||||
return "tmpl += " + out + "\n"
|
||||
case *parse.StringNode:
|
||||
return n.Quoted
|
||||
default:
|
||||
fmt.Println("Unknown Kind: ")
|
||||
fmt.Println(reflect.ValueOf(firstWord).Elem().Kind())
|
||||
fmt.Println("Unknown Type: ")
|
||||
fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name())
|
||||
panic("I don't know what node this is")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
||||
firstWord := node.Args[0]
|
||||
switch n := firstWord.(type) {
|
||||
case *parse.FieldNode:
|
||||
if debug {
|
||||
fmt.Println("Field Node: ")
|
||||
fmt.Println(n.Ident)
|
||||
|
||||
for _, id := range n.Ident {
|
||||
fmt.Println("Field Bit: ")
|
||||
fmt.Println(id)
|
||||
}
|
||||
}
|
||||
|
||||
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
||||
return c.compile_boolsub(n.String(), varholder, template_name, holdreflect)
|
||||
case *parse.ChainNode:
|
||||
if debug {
|
||||
fmt.Println("Chain Node: ")
|
||||
fmt.Println(n.Node)
|
||||
fmt.Println(node.Args)
|
||||
}
|
||||
break
|
||||
case *parse.IdentifierNode:
|
||||
if debug {
|
||||
fmt.Println("Identifier Node: ")
|
||||
fmt.Println(node)
|
||||
fmt.Println(node.Args)
|
||||
}
|
||||
return c.compile_identswitch(varholder, holdreflect, template_name, node)
|
||||
case *parse.DotNode:
|
||||
return varholder
|
||||
case *parse.VariableNode:
|
||||
if debug {
|
||||
fmt.Println("Variable Node")
|
||||
fmt.Println(n.String())
|
||||
fmt.Println(n.Ident)
|
||||
}
|
||||
|
||||
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
||||
return out
|
||||
case *parse.NilNode:
|
||||
panic("Nil is not a command x.x")
|
||||
case *parse.PipeNode:
|
||||
if debug {
|
||||
fmt.Println("Pipe Node!")
|
||||
fmt.Println(n)
|
||||
}
|
||||
|
||||
/*for _, cmd := range n.Cmds {
|
||||
if debug {
|
||||
fmt.Println("Pipe Bit: ")
|
||||
fmt.Println(cmd)
|
||||
}
|
||||
out += c.compile_if_varsub_n(n.String(), varholder, template_name, holdreflect)
|
||||
}*/
|
||||
|
||||
if debug {
|
||||
fmt.Println("Args: ")
|
||||
fmt.Println(node.Args)
|
||||
}
|
||||
|
||||
/*argcopy := node.Args[1:]
|
||||
for _, arg := range argcopy {
|
||||
if debug {
|
||||
fmt.Println("Pipe Arg: ")
|
||||
fmt.Println(arg)
|
||||
fmt.Println(reflect.ValueOf(arg).Elem().Type().Name())
|
||||
fmt.Println(reflect.ValueOf(arg).Kind())
|
||||
}
|
||||
|
||||
switch arg.(type) {
|
||||
case *parse.IdentifierNode:
|
||||
out += c.compile_identswitch(varholder, holdreflect, template_name, node)
|
||||
break
|
||||
case *parse.PipeNode:
|
||||
break
|
||||
//out += c.compile_if_varsub_n(a.String(), varholder, template_name, holdreflect)
|
||||
default:
|
||||
panic("Unknown Pipe Arg type! Did Mario get stuck in the pipes again?")
|
||||
}
|
||||
//out += c.compile_varswitch(arg.String(), holdreflect, template_name, arg)
|
||||
}*/
|
||||
out += c.compile_identswitch(varholder, holdreflect, template_name, node)
|
||||
|
||||
if debug {
|
||||
fmt.Println("Out: ")
|
||||
fmt.Println(out)
|
||||
}
|
||||
return out
|
||||
default:
|
||||
fmt.Println("Unknown Kind: ")
|
||||
fmt.Println(reflect.ValueOf(firstWord).Elem().Kind())
|
||||
fmt.Println("Unknown Type: ")
|
||||
fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name())
|
||||
panic("I don't know what node this is! Grr...")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
||||
ArgLoop:
|
||||
for pos, id := range node.Args {
|
||||
if debug {
|
||||
fmt.Println(id)
|
||||
}
|
||||
|
||||
switch id.String() {
|
||||
case "not":
|
||||
out += "!"
|
||||
case "or":
|
||||
out += " || "
|
||||
case "and":
|
||||
out += " && "
|
||||
case "le":
|
||||
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
||||
break ArgLoop
|
||||
default:
|
||||
if debug {
|
||||
fmt.Println("Variable!")
|
||||
}
|
||||
out += c.compile_if_varsub_n(id.String(), varholder, template_name, holdreflect)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) {
|
||||
firstWord := node.Args[0]
|
||||
switch n := firstWord.(type) {
|
||||
case *parse.FieldNode:
|
||||
if debug {
|
||||
fmt.Println("Field Node: ")
|
||||
fmt.Println(n.Ident)
|
||||
|
||||
for _, id := range n.Ident {
|
||||
fmt.Println("Field Bit: ")
|
||||
fmt.Println(id)
|
||||
}
|
||||
}
|
||||
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
||||
return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
||||
case *parse.ChainNode:
|
||||
if debug {
|
||||
fmt.Println("Chain Node: ")
|
||||
fmt.Println(n.Node)
|
||||
fmt.Println(node.Args)
|
||||
}
|
||||
return "", outVal
|
||||
/*case *parse.IdentifierNode:
|
||||
fmt.Println("Identifier Node: ")
|
||||
fmt.Println(node)
|
||||
fmt.Println(node.Args)
|
||||
|
||||
ArgLoop:
|
||||
for pos, id := range node.Args {
|
||||
fmt.Println(id)
|
||||
switch id.String() {
|
||||
case "not":
|
||||
out += "!"
|
||||
case "or":
|
||||
out += " || "
|
||||
case "and":
|
||||
out += " && "
|
||||
case "le":
|
||||
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, holdreflect)
|
||||
break ArgLoop
|
||||
default:
|
||||
fmt.Println("Variable!")
|
||||
out += c.compile_if_varsub_n(id.String(), varholder, holdreflect)
|
||||
}
|
||||
}
|
||||
return out*/
|
||||
case *parse.DotNode:
|
||||
return varholder, holdreflect
|
||||
case *parse.NilNode:
|
||||
panic("Nil is not a command x.x")
|
||||
default:
|
||||
//panic("I don't know what node this is")
|
||||
}
|
||||
return "", outVal
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) {
|
||||
out, _ = c.compile_if_varsub(varname, varholder, template_name, cur)
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) {
|
||||
if varname[0] != '.' && varname[0] != '$' {
|
||||
return varname, cur
|
||||
}
|
||||
|
||||
bits := strings.Split(varname,".")
|
||||
if varname[0] == '$' {
|
||||
var res VarItemReflect
|
||||
if varname[1] == '.' {
|
||||
res = c.localVars[template_name]["."]
|
||||
} else {
|
||||
res = c.localVars[template_name][strings.TrimPrefix(bits[0],"$")]
|
||||
}
|
||||
out += res.Destination
|
||||
cur = res.Value
|
||||
|
||||
if cur.Kind() == reflect.Interface {
|
||||
cur = cur.Elem()
|
||||
}
|
||||
} else {
|
||||
if cur.Kind() == reflect.Interface {
|
||||
cur = cur.Elem()
|
||||
out += varholder + ".(" + cur.Type().Name() + ")"
|
||||
} else {
|
||||
out += varholder
|
||||
}
|
||||
}
|
||||
bits[0] = strings.TrimPrefix(bits[0],"$")
|
||||
|
||||
if debug {
|
||||
fmt.Println("Cur Kind: ")
|
||||
fmt.Println(cur.Kind())
|
||||
fmt.Println("Cur Type: ")
|
||||
fmt.Println(cur.Type().Name())
|
||||
}
|
||||
|
||||
for _, bit := range bits {
|
||||
if debug {
|
||||
fmt.Println("Variable Field!")
|
||||
fmt.Println(bit)
|
||||
}
|
||||
|
||||
if bit == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
cur = cur.FieldByName(bit)
|
||||
if cur.Kind() == reflect.Interface {
|
||||
cur = cur.Elem()
|
||||
out += "." + bit + ".(" + cur.Type().Name() + ")"
|
||||
} else {
|
||||
out += "." + bit
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println("Data Kind: ")
|
||||
fmt.Println(cur.Kind())
|
||||
fmt.Println("Data Type: ")
|
||||
fmt.Println(cur.Type().Name())
|
||||
}
|
||||
}
|
||||
|
||||
for _, varItem := range c.varList {
|
||||
if strings.HasPrefix(out, varItem.Destination) {
|
||||
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
||||
}
|
||||
}
|
||||
return out, cur
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string {
|
||||
out, val := c.compile_if_varsub(varname, varholder, template_name, val)
|
||||
switch val.Kind() {
|
||||
case reflect.Int:
|
||||
out += " > 0"
|
||||
case reflect.Bool:
|
||||
// Do nothing
|
||||
case reflect.String:
|
||||
out += " != \"\""
|
||||
case reflect.Int64:
|
||||
out += " > 0"
|
||||
default:
|
||||
panic("I don't know what this variable's type is o.o\n")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_varsub(varname string, val reflect.Value) string {
|
||||
for _, varItem := range c.varList {
|
||||
if strings.HasPrefix(varname, varItem.Destination) {
|
||||
varname = strings.Replace(varname, varItem.Destination, varItem.Name, 1)
|
||||
}
|
||||
}
|
||||
|
||||
if val.Kind() == reflect.Interface {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Int:
|
||||
return "tmpl += strconv.Itoa(" + varname + ")\n"
|
||||
case reflect.Bool:
|
||||
return "if " + varname + " {\ntmpl += \"true\"} else {\ntmpl += \"false\"\n}\n"
|
||||
case reflect.String:
|
||||
if val.Type().Name() != "string" && !strings.HasPrefix(varname,"string(") {
|
||||
return "tmpl += string(" + varname + ")\n"
|
||||
} else {
|
||||
return "tmpl += " + varname + "\n"
|
||||
}
|
||||
case reflect.Int64:
|
||||
return "tmpl += strconv.FormatInt(" + varname + ", 10)"
|
||||
default:
|
||||
fmt.Println("Unknown Kind: ")
|
||||
fmt.Println(val.Kind())
|
||||
fmt.Println("Unknown Type: ")
|
||||
fmt.Println(val.Type().Name())
|
||||
panic("// I don't know what this variable's type is o.o\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) {
|
||||
if debug {
|
||||
fmt.Println("Template Node: " + node.Name)
|
||||
}
|
||||
|
||||
fname := strings.TrimSuffix(node.Name, filepath.Ext(node.Name))
|
||||
varholder := "tmpl_" + fname + "_vars"
|
||||
var holdreflect reflect.Value
|
||||
if node.Pipe != nil {
|
||||
for _, cmd := range node.Pipe.Cmds {
|
||||
firstWord := cmd.Args[0]
|
||||
switch firstWord.(type) {
|
||||
case *parse.DotNode:
|
||||
varholder = pvarholder
|
||||
holdreflect = pholdreflect
|
||||
break
|
||||
case *parse.NilNode:
|
||||
panic("Nil is not a command x.x")
|
||||
default:
|
||||
out = "var " + varholder + " := false\n"
|
||||
out += c.compile_command(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res, err := ioutil.ReadFile(c.dir + node.Name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
content := string(res)
|
||||
|
||||
tree := parse.New(node.Name, c.funcMap)
|
||||
var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree)
|
||||
tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
c.tlist[fname] = tree
|
||||
subtree := c.tlist[fname]
|
||||
if debug {
|
||||
fmt.Println(subtree.Root)
|
||||
}
|
||||
|
||||
c.localVars[fname] = make(map[string]VarItemReflect)
|
||||
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
||||
|
||||
for _, node := range subtree.Root.Nodes {
|
||||
if debug {
|
||||
fmt.Println("Node: " + node.String())
|
||||
}
|
||||
out += c.compile_switch(varholder, holdreflect, fname, node)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *CTemplateSet2) compile_command(*parse.CommandNode) (out string) {
|
||||
return ""
|
||||
}
|
7
user.go
|
@ -10,6 +10,7 @@ type User struct
|
|||
{
|
||||
ID int
|
||||
Name string
|
||||
Email string
|
||||
Group int
|
||||
Active bool
|
||||
Is_Mod bool
|
||||
|
@ -72,6 +73,9 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList
|
|||
// Is this session valid..?
|
||||
err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName)
|
||||
if err == sql.ErrNoRows {
|
||||
user.ID = 0
|
||||
user.Session = ""
|
||||
user.Perms = GuestPerms
|
||||
return user, noticeList, true
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
|
@ -131,6 +135,9 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ
|
|||
// Is this session valid..?
|
||||
err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName)
|
||||
if err == sql.ErrNoRows {
|
||||
user.ID = 0
|
||||
user.Session = ""
|
||||
user.Perms = GuestPerms
|
||||
return user, true
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
|
|