Added Per-Forum Permissions. The admin side of this is under development.

Added the Not Loggedin group.
The Reports Forum is now only available to staff.
Groups are now stored in a slice instead of a map for extra concurrency and speed.
Testing background SVGs.
You can now toggle a forum's visibility via the Forum Manager.
Added the Inline Form API to global.js
The reports forum can now be edited but not deleted.
Tempra Simple and Tempra Conflux now support backgrounds.
This commit is contained in:
Azareal 2017-01-31 05:13:38 +00:00
parent 5e3b61d910
commit f5c6f6b552
20 changed files with 522 additions and 155 deletions

View File

@ -56,6 +56,12 @@ CREATE TABLE `forums`(
primary key(`fid`)
) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE `forums_permissions`(
`fid` int not null,
`gid` int not null,
`permissions` text not null
);
CREATE TABLE `topics`(
`tid` int not null AUTO_INCREMENT,
`title` varchar(100) not null,
@ -169,9 +175,16 @@ INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator
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,"ManageThemes":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,"ManageThemes":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`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":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`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','Guest');
INSERT INTO forums(`name`,`active`) VALUES ('Reports',0);
INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',NOW());
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (3,1,'{}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (4,1,'{}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (5,1,'{}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (6,1,'{}');
INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`)
VALUES ('Test Topic','A topic automatically generated by the software.',NOW(),NOW(),1,1);

View File

@ -1,6 +1,8 @@
package main
import "fmt"
var BlankPerms Perms
var BlankForumPerms ForumPerms
var GuestPerms Perms
var AllPerms Perms
@ -8,12 +10,14 @@ type Group struct
{
ID int
Name string
Perms Perms
PermissionsText []byte
Is_Mod bool
Is_Admin bool
Is_Banned bool
Tag string
Perms Perms
PermissionsText []byte
Forums []ForumPerms
CanSee []int // The IDs of the forums this group can see
}
// Permission Structure: ActionComponent[Subcomponent]Flag
@ -67,10 +71,19 @@ type ForumPerms struct
CloseTopic bool
//CloseOwnTopic bool
Overrides bool
ExtData map[string]bool
}
func init() {
BlankPerms = Perms{
ExtData: make(map[string]bool),
}
BlankForumPerms = ForumPerms{
ExtData: make(map[string]bool),
}
GuestPerms = Perms{
ViewTopic: true,
ExtData: make(map[string]bool),

View File

@ -29,8 +29,9 @@ var no_css_tmpl = template.CSS("")
var staff_css_tmpl = template.CSS(staff_css)
var settings map[string]interface{} = make(map[string]interface{})
var external_sites map[string]string = make(map[string]string)
var groups map[int]Group = make(map[int]Group)
var groups []Group
var forums []Forum // The IDs for a forum tend to be low and sequential for the most part, so we can get more performance out of using a slice instead of a map AND it has better concurrency
var forum_perms [][]ForumPerms // [gid][fid]Perms
var groupCapCount int
var forumCapCount int
var static_files map[string]SFile = make(map[string]SFile)
@ -227,6 +228,7 @@ func main(){
router.HandleFunc("/panel/forums/create/", route_panel_forums_create_submit)
router.HandleFunc("/panel/forums/delete/", route_panel_forums_delete)
router.HandleFunc("/panel/forums/delete/submit/", route_panel_forums_delete_submit)
router.HandleFunc("/panel/forums/edit/", route_panel_forums_edit)
router.HandleFunc("/panel/forums/edit/submit/", route_panel_forums_edit_submit)
router.HandleFunc("/panel/settings/", route_panel_settings)
router.HandleFunc("/panel/settings/edit/", route_panel_setting)

View File

@ -24,18 +24,39 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) {
if is_js == "" {
is_js = "0"
}
if !user.Perms.ViewTopic || !user.Perms.EditTopic {
NoPermissionsJSQ(w,r,user,is_js)
return
}
var tid int
var fid int
tid, err = strconv.Atoi(r.URL.Path[len("/topic/edit/submit/"):])
if err != nil {
LocalErrorJSQ("The provided TopicID is not a valid number.",w,r,user,is_js)
return
}
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid)
if err == sql.ErrNoRows {
LocalError("The topic you tried to edit doesn't exist.",w,r,user)
return
} else if err != nil {
InternalError(err,w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic || !groups[user.Group].Forums[fid].EditTopic {
NoPermissionsJSQ(w,r,user,is_js)
return
}
} else if !user.Perms.ViewTopic || !user.Perms.EditTopic {
NoPermissionsJSQ(w,r,user,is_js)
return
}
topic_name := r.PostFormValue("topic_name")
topic_status := r.PostFormValue("topic_status")
is_closed := (topic_status == "closed")
@ -59,10 +80,6 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) {
if !ok {
return
}
if !user.Perms.ViewTopic || !user.Perms.DeleteTopic {
NoPermissions(w,r,user)
return
}
tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):])
if err != nil {
@ -73,7 +90,7 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) {
var content string
var createdBy int
var fid int
err = db.QueryRow("select tid, content, createdBy, parentID from topics where tid = ?", tid).Scan(&tid, &content, &createdBy, &fid)
err = db.QueryRow("select content, createdBy, parentID from topics where tid = ?", tid).Scan(&content, &createdBy, &fid)
if err == sql.ErrNoRows {
LocalError("The topic you tried to delete doesn't exist.",w,r,user)
return
@ -82,6 +99,21 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) {
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic || !groups[user.Group].Forums[fid].DeleteTopic {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic || !user.Perms.DeleteTopic {
NoPermissions(w,r,user)
return
}
_, err = delete_topic_stmt.Exec(tid)
if err != nil {
InternalError(err,w,r,user)
@ -97,10 +129,6 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) {
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
_, err = remove_topics_from_forum_stmt.Exec(1, fid)
if err != nil {
InternalError(err,w,r,user)
@ -115,10 +143,6 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) {
if !ok {
return
}
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
NoPermissions(w,r,user)
return
}
tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):])
if err != nil {
@ -126,6 +150,31 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) {
return
}
var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid)
if err == sql.ErrNoRows {
LocalError("The topic you tried to pin doesn't exist.",w,r,user)
return
} else if err != nil {
InternalError(err,w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic || !groups[user.Group].Forums[fid].PinTopic {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic || !user.Perms.PinTopic {
NoPermissions(w,r,user)
return
}
_, err = stick_topic_stmt.Exec(tid)
if err != nil {
InternalError(err,w,r,user)
@ -139,10 +188,6 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) {
if !ok {
return
}
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
NoPermissions(w,r,user)
return
}
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):])
if err != nil {
@ -150,6 +195,31 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) {
return
}
var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid)
if err == sql.ErrNoRows {
LocalError("The topic you tried to unpin doesn't exist.",w,r,user)
return
} else if err != nil {
InternalError(err,w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic || !groups[user.Group].Forums[fid].PinTopic {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic || !user.Perms.PinTopic {
NoPermissions(w,r,user)
return
}
_, err = unstick_topic_stmt.Exec(tid)
if err != nil {
InternalError(err,w,r,user)
@ -173,10 +243,6 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) {
if is_js == "" {
is_js = "0"
}
if !user.Perms.ViewTopic || !user.Perms.EditReply {
NoPermissionsJSQ(w,r,user,is_js)
return
}
rid, err := strconv.Atoi(r.URL.Path[len("/reply/edit/submit/"):])
if err != nil {
@ -199,6 +265,31 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) {
return
}
var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid)
if err == sql.ErrNoRows {
LocalError("The parent topic doesn't exist.",w,r,user)
return
} else if err != nil {
InternalError(err,w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic || !groups[user.Group].Forums[fid].EditReply {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic || !user.Perms.EditReply {
NoPermissions(w,r,user)
return
}
if is_js == "0" {
http.Redirect(w,r, "/topic/" + strconv.Itoa(tid) + "#reply-" + strconv.Itoa(rid), http.StatusSeeOther)
} else {
@ -236,7 +327,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
var tid int
var content string
var createdBy int
err = db.QueryRow("SELECT tid, content, createdBy from replies where rid = ?", rid).Scan(&tid, &content, &createdBy)
err = db.QueryRow("select tid, content, createdBy from replies where rid = ?", rid).Scan(&tid, &content, &createdBy)
if err == sql.ErrNoRows {
LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js)
return
@ -245,6 +336,31 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
return
}
var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid)
if err == sql.ErrNoRows {
LocalError("The parent topic doesn't exist.",w,r,user)
return
} else if err != nil {
InternalError(err,w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic || !groups[user.Group].Forums[fid].DeleteReply {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic || !user.Perms.DeleteReply {
NoPermissions(w,r,user)
return
}
_, err = delete_reply_stmt.Exec(rid)
if err != nil {
InternalErrorJSQ(err,w,r,user,is_js)
@ -389,7 +505,7 @@ func route_ban(w http.ResponseWriter, r *http.Request) {
}
var uname string
err = db.QueryRow("SELECT name from users where uid = ?", uid).Scan(&uname)
err = db.QueryRow("select name from users where uid = ?", uid).Scan(&uname)
if err == sql.ErrNoRows {
LocalError("The user you're trying to ban no longer exists.",w,r,user)
return
@ -428,7 +544,7 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request) {
var group int
var is_super_admin bool
err = db.QueryRow("SELECT `group`, `is_super_admin` from `users` where `uid` = ?", uid).Scan(&group, &is_super_admin)
err = db.QueryRow("select `group`, `is_super_admin` from `users` where `uid` = ?", uid).Scan(&group, &is_super_admin)
if err == sql.ErrNoRows {
LocalError("The user you're trying to ban no longer exists.",w,r,user)
return
@ -486,7 +602,7 @@ func route_unban(w http.ResponseWriter, r *http.Request) {
var uname string
var group int
err = db.QueryRow("SELECT `name`, `group` from users where `uid` = ?", uid).Scan(&uname, &group)
err = db.QueryRow("select `name`, `group` from users where `uid` = ?", uid).Scan(&uname, &group)
if err == sql.ErrNoRows {
LocalError("The user you're trying to unban no longer exists.",w,r,user)
return
@ -530,7 +646,7 @@ func route_activate(w http.ResponseWriter, r *http.Request) {
var uname string
var active bool
err = db.QueryRow("SELECT `name`, `active` from users where `uid` = ?", uid).Scan(&uname, &active)
err = db.QueryRow("select `name`, `active` from users where `uid` = ?", uid).Scan(&uname, &active)
if err == sql.ErrNoRows {
LocalError("The account you're trying to activate no longer exists.",w,r,user)
return
@ -567,8 +683,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){
NoPermissions(w,r,user)
return
}
pi := Page{"Control Panel Dashboard",user,noticeList,tList,0}
pi := Page{"Control Panel Dashboard",user,noticeList,tList,nil}
templates.ExecuteTemplate(w,"panel-dashboard.html", pi)
}
@ -588,7 +703,6 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){
forumList = append(forumList,forum)
}
}
pi := Page{"Forum Manager",user,noticeList,forumList,nil}
templates.ExecuteTemplate(w,"panel-forums.html", pi)
}
@ -671,7 +785,6 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) {
NoPermissions(w,r,user)
return
}
if r.FormValue("session") != user.Session {
SecurityError(w,r,user)
return
@ -682,7 +795,6 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) {
LocalError("The provided Forum ID is not a valid number.",w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The forum you're trying to delete doesn't exist.",w,r,user)
return
@ -693,10 +805,33 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) {
InternalError(err,w,r,user)
return
}
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
}
func route_panel_forums_edit(w http.ResponseWriter, r *http.Request) {
user, noticeList, ok := SessionCheck(w,r)
if !ok {
return
}
if !user.Is_Super_Mod || !user.Perms.ManageForums {
NoPermissions(w,r,user)
return
}
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/edit/"):])
if err != nil {
LocalError("The provided Forum ID is not a valid number.",w,r,user)
return
}
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The forum you're trying to edit doesn't exist.",w,r,user)
return
}
pi := Page{"Forum Editor",user,noticeList,tList,nil}
templates.ExecuteTemplate(w,"panel-forum-edit.html", pi)
}
func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) {
user, ok := SimpleSessionCheck(w,r)
if !ok {
@ -716,27 +851,60 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) {
SecurityError(w,r,user)
return
}
is_js := r.PostFormValue("js")
if is_js == "" {
is_js = "0"
}
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/edit/submit/"):])
if err != nil {
LocalError("The provided Forum ID is not a valid number.",w,r,user)
LocalErrorJSQ("The provided Forum ID is not a valid number.",w,r,user,is_js)
return
}
forum_name := r.PostFormValue("edit_item")
forum_name := r.PostFormValue("forum-name")
forum_active := r.PostFormValue("forum-active")
if (fid > forumCapCount) || (fid < 0) || forums[fid].Name=="" {
LocalError("The forum you're trying to edit doesn't exist.",w,r,user)
LocalErrorJSQ("The forum you're trying to edit doesn't exist.",w,r,user,is_js)
return
}
_, err = update_forum_stmt.Exec(forum_name, fid)
if forum_name == "" && forum_active == "" {
LocalErrorJSQ("You haven't changed anything!",w,r,user,is_js)
return
}
if forum_name == "" {
forum_name = forums[fid].Name
}
var active bool
if forum_active == "" {
active = forums[fid].Active
} else if forum_active == "1" || forum_active == "Show" {
active = true
} else {
active = false
}
_, err = update_forum_stmt.Exec(forum_name, active, fid)
if err != nil {
InternalError(err,w,r,user)
InternalErrorJSQ(err,w,r,user,is_js)
return
}
forums[fid].Name = forum_name
if forums[fid].Name != forum_name {
forums[fid].Name = forum_name
}
if forums[fid].Active != active {
forums[fid].Active = active
}
if is_js == "0" {
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
} else {
fmt.Fprintf(w,"{'success': '1'}")
}
}
func route_panel_settings(w http.ResponseWriter, r *http.Request){
@ -750,7 +918,7 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request){
}
var settingList map[string]interface{} = make(map[string]interface{})
rows, err := db.Query("SELECT name, content, type FROM settings")
rows, err := db.Query("select name, content, type from settings")
if err != nil {
InternalError(err,w,r,user)
return
@ -808,7 +976,7 @@ func route_panel_setting(w http.ResponseWriter, r *http.Request){
setting := Setting{"","","",""}
setting.Name = r.URL.Path[len("/panel/settings/edit/"):]
err := db.QueryRow("SELECT content, type from settings where name = ?", setting.Name).Scan(&setting.Content, &setting.Type)
err := db.QueryRow("select content, type from settings where name = ?", setting.Name).Scan(&setting.Content,&setting.Type)
if err == sql.ErrNoRows {
LocalError("The setting you want to edit doesn't exist.",w,r,user)
return
@ -916,7 +1084,7 @@ func route_panel_plugins(w http.ResponseWriter, r *http.Request){
pluginList = append(pluginList, plugin)
}
pi := Page{"Plugin Manager",user,noticeList,pluginList,0}
pi := Page{"Plugin Manager",user,noticeList,pluginList,nil}
templates.ExecuteTemplate(w,"panel-plugins.html", pi)
}
@ -942,7 +1110,7 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){
}
var active bool
err := db.QueryRow("SELECT active from plugins where uname = ?", uname).Scan(&active)
err := db.QueryRow("select active from plugins where uname = ?", uname).Scan(&active)
if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r,user)
return
@ -1005,7 +1173,7 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request){
}
var active bool
err := db.QueryRow("SELECT active from plugins where uname = ?", uname).Scan(&active)
err := db.QueryRow("select active from plugins where uname = ?", uname).Scan(&active)
if err == sql.ErrNoRows {
LocalError("The plugin you're trying to deactivate isn't active",w,r,user)
return
@ -1042,7 +1210,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
@ -1087,7 +1255,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){
return
}
pi := Page{"User Manager",user,noticeList,userList,0}
pi := Page{"User Manager",user,noticeList,userList,nil}
err = templates.ExecuteTemplate(w,"panel-users.html", pi)
if err != nil {
InternalError(err,w,r,user)
@ -1114,7 +1282,7 @@ func route_panel_users_edit(w http.ResponseWriter, r *http.Request){
return
}
err = db.QueryRow("SELECT `name`, `email`, `group` from `users` where `uid` = ?", targetUser.ID).Scan(&targetUser.Name, &targetUser.Email, &targetUser.Group)
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
@ -1131,7 +1299,7 @@ func route_panel_users_edit(w http.ResponseWriter, r *http.Request){
}
var groupList []interface{}
for _, group := range groups {
for _, group := range groups[1:] {
if !user.Perms.EditUserGroupAdmin && group.Is_Admin {
continue
}
@ -1171,7 +1339,7 @@ func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request){
return
}
err = db.QueryRow("SELECT `name`, `email`, `group` from `users` where `uid` = ?", targetUser.ID).Scan(&targetUser.Name, &targetUser.Email, &targetUser.Group)
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
@ -1215,8 +1383,7 @@ func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request){
return
}
_, ok = groups[newgroup]
if !ok {
if (newgroup > groupCapCount) || (newgroup < 0) || groups[newgroup].Name=="" {
LocalError("The group you're trying to place this user in doesn't exist.",w,r,user)
return
}
@ -1254,11 +1421,11 @@ func route_panel_groups(w http.ResponseWriter, r *http.Request){
}
var groupList []interface{}
for _, group := range groups {
for _, group := range groups[1:] {
groupList = append(groupList, group)
}
pi := Page{"Group Manager",user,noticeList,groupList,0}
pi := Page{"Group Manager",user,noticeList,groupList,nil}
templates.ExecuteTemplate(w,"panel-groups.html", pi)
}
@ -1310,7 +1477,7 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request){
}
var isDefault bool
err := db.QueryRow("SELECT `default` from `themes` where `uname` = ?", uname).Scan(&isDefault)
err := db.QueryRow("select `default` from `themes` where `uname` = ?", uname).Scan(&isDefault)
if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r,user)
return

View File

@ -410,25 +410,34 @@ func init_database(err error) {
}
log.Print("Preparing update_user statement.")
update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?, `email` = ?, `group` = ? WHERE `uid` = ?")
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")
groups = append(groups, Group{ID:0,Name:"System"})
rows, err := db.Query("select gid,name,permissions,is_mod,is_admin,is_banned,tag from users_groups")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
i := 1
for ;rows.Next();i++ {
group := Group{ID: 0,}
err := rows.Scan(&group.ID, &group.Name, &group.PermissionsText, &group.Is_Mod, &group.Is_Admin, &group.Is_Banned, &group.Tag)
if err != nil {
log.Fatal(err)
}
// Ugh, you really shouldn't physically delete these items, it makes a big mess of things
if group.ID != i {
fmt.Println("Stop physically deleting groups. You are messing up the IDs. Use the Group Manager or delete_group() instead x.x")
fill_group_id_gap(i, group.ID)
}
err = json.Unmarshal(group.PermissionsText, &group.Perms)
if err != nil {
log.Fatal(err)
@ -439,25 +448,28 @@ func init_database(err error) {
}
group.Perms.ExtData = make(map[string]bool)
groups[group.ID] = group
groups = append(groups, group)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
log.Print("Binding the Not Loggedin Group")
GuestPerms = groups[6].Perms
log.Print("Loading the forums.")
log.Print("Adding the uncategorised forum")
forums = append(forums, Forum{0,"Uncategorised",uncategorised_forum_visible,0,"",0,"",0,""})
//rows, err = db.Query("SELECT fid, name, active, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums")
rows, err = db.Query("SELECT fid, name, active, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums ORDER BY fid ASC")
rows, err = db.Query("select fid, name, active, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime from forums order by fid asc")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
i := 1
i = 1
for ;rows.Next();i++ {
forum := Forum{0,"",true,0,"",0,"",0,""}
err := rows.Scan(&forum.ID, &forum.Name, &forum.Active, &forum.TopicCount, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime)
@ -467,7 +479,7 @@ func init_database(err error) {
// Ugh, you really shouldn't physically delete these items, it makes a big mess of things
if forum.ID != i {
fmt.Println("Stop physically deleting forums. You are messing up the IDs. Use the Forum Manager or delete_forums() instead x.x")
fmt.Println("Stop physically deleting forums. You are messing up the IDs. Use the Forum Manager or delete_forum() instead x.x")
fill_forum_id_gap(i, forum.ID)
}
@ -493,8 +505,68 @@ func init_database(err error) {
//log.Print("Adding the reports forum")
//forums[-1] = Forum{-1,"Reports",false,0,"",0,"",0,""}
log.Print("Loading the forum permissions")
rows, err = db.Query("select gid, fid, permissions from forums_permissions order by gid asc, fid asc")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Temporarily store the forum perms in a map before transferring it to a much faster slice
log.Print("Adding the forum permissions")
forum_perms := make(map[int]map[int]ForumPerms)
for ;rows.Next();i++ {
var gid int
var fid int
var perms []byte
var pperms ForumPerms
err := rows.Scan(&gid, &fid, &perms)
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(perms, &pperms)
if err != nil {
log.Fatal(err)
}
pperms.ExtData = make(map[string]bool)
pperms.Overrides = true
_, ok := forum_perms[gid]
if !ok {
forum_perms[gid] = make(map[int]ForumPerms)
}
forum_perms[gid][fid] = pperms
}
for gid, _ := range groups {
log.Print("Adding the forum permissions for Group #" + strconv.Itoa(gid))
//groups[gid].Forums = append(groups[gid].Forums,BlankForumPerms) // GID 0. I sometimes wish MySQL's AUTO_INCREMENT would start at zero
for fid, _ := range forums {
forum_perm, ok := forum_perms[gid][fid]
if ok {
// Override group perms
//log.Print("Overriding permissions for forum #" + strconv.Itoa(fid))
groups[gid].Forums = append(groups[gid].Forums,forum_perm)
} else {
// Inherit from Group
//log.Print("Inheriting from default for forum #" + strconv.Itoa(fid))
forum_perm = BlankForumPerms
groups[gid].Forums = append(groups[gid].Forums,forum_perm)
}
if forum_perm.Overrides {
if forum_perm.ViewTopic {
groups[gid].CanSee = append(groups[gid].CanSee, fid)
}
} else if groups[gid].Perms.ViewTopic {
groups[gid].CanSee = append(groups[gid].CanSee, fid)
}
}
//fmt.Printf("%+v\n", groups[gid].CanSee)
//fmt.Printf("%+v\n", groups[gid].Forums)
//fmt.Println(len(groups[gid].Forums))
}
log.Print("Loading the settings.")
rows, err = db.Query("SELECT name, content, type, constraints FROM settings")
rows, err = db.Query("select name, content, type, constraints from settings")
if err != nil {
log.Fatal(err)
}
@ -520,7 +592,7 @@ func init_database(err error) {
}
log.Print("Loading the plugins.")
rows, err = db.Query("SELECT uname, active FROM plugins")
rows, err = db.Query("select uname, active from plugins")
if err != nil {
log.Fatal(err)
}
@ -548,7 +620,7 @@ func init_database(err error) {
}
log.Print("Loading the themes.")
rows, err = db.Query("SELECT `uname`, `default` FROM `themes`")
rows, err = db.Query("select `uname`, `default` from `themes`")
if err != nil {
log.Fatal(err)
}

View File

@ -1,14 +1,11 @@
var form_vars = {};
function post_link(event)
{
event.preventDefault();
var form_action = $(event.target).closest('a').attr("href");
console.log("Form Action: " + form_action);
$.ajax({
url: form_action,
type: "POST",
dataType: "json",
data: {js: "1"}
});
$.ajax({ url: form_action, type: "POST", dataType: "json", data: { js: "1" } });
}
$(document).ready(function(){
@ -19,9 +16,8 @@ $(document).ready(function(){
$(".show_on_edit").show();
});
$(".submit_edit").click(function(event){
$(".topic_item .submit_edit").click(function(event){
event.preventDefault();
$(".topic_name").html($(".topic_name_input").val());
$(".topic_content").html($(".topic_content_input").val());
$(".topic_status_e:not(.open_edit)").html($(".topic_status_input").val());
@ -74,11 +70,7 @@ $(document).ready(function(){
var form_action = $(this).closest('a').attr("href");
console.log("Form Action: " + form_action);
$.ajax({
url: form_action,
type: "POST",
dataType: "json",
data: {is_js: "1",edit_item: newContent}
$.ajax({ url: form_action, type: "POST", dataType: "json", data: { is_js: "1", edit_item: newContent }
});
});
});
@ -109,25 +101,70 @@ $(document).ready(function(){
});
});
$(".edit_fields").click(function(event)
{
event.preventDefault();
var block_parent = $(this).closest('.editable_parent');
block_parent.find('.hide_on_edit').hide();
block_parent.find('.editable_block').show();
block_parent.find('.editable_block').each(function(){
var field_name = $(this).data("field");
var field_type = $(this).data("type");
if(field_type=="list") {
var field_value = $(this).data("value");
if(field_name in form_vars) var it = form_vars[field_name];
else var it = ['No','Yes'];
var itLen = it.length;
var out = "";
for (var i = 0; i < itLen; i++){
if(field_value==i) sel = "selected ";
else sel = "";
out += "<option "+sel+"value='"+i+"'>"+it[i]+"</option>";
}
$(this).html("<select data-field='"+field_name+"' name='"+field_name+"'>" + out + "</select>");
}
else $(this).html("<input name='"+field_name+"' value='" + $(this).text() + "' type='text'/>");
});
block_parent.find('.show_on_edit').eq(0).show();
$(".submit_edit").click(function(event)
{
event.preventDefault();
var out_data = {is_js: "1"}
var block_parent = $(this).closest('.editable_parent');
var block = block_parent.find('.editable_block').each(function(){
var field_name = $(this).data("field");
var field_type = $(this).data("type");
if(field_type == "list") var newContent = $(this).find('select :selected').text();
else var newContent = $(this).find('input').eq(0).val();
$(this).html(newContent);
out_data[field_name] = newContent
});
var form_action = $(this).closest('a').attr("href");
console.log("Form Action: " + form_action);
console.log(out_data);
$.ajax({ url: form_action + "?session=" + session, type:"POST", dataType:"json", data: out_data });
block_parent.find('.hide_on_edit').show();
block_parent.find('.show_on_edit').hide();
});
});
$(this).find(".ip_item").each(function(){
var ip = $(this).text();
//var ip_width = $(this).width();
console.log("IP: " + ip);
if(ip.length > 10){
$(this).html("Show IP");
$(this).click(function(event){
event.preventDefault();
$(this).text(ip);/*.animate({width: ip.width},{duration: 1000, easing: 'easeOutBounce'});*/
$(this).text(ip);
});
}
});
$(this).keyup(function(event){
if(event.which == 37) {
$("#prevFloat a")[0].click();
}
if(event.which == 39) {
$("#nextFloat a")[0].click();
}
if(event.which == 37) $("#prevFloat a")[0].click();
if(event.which == 39) $("#nextFloat a")[0].click();
});
});

12
public/test_bg2.svg Normal file
View File

@ -0,0 +1,12 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs>
<pattern id="wooblies" width="50" height="43.4" patternUnits="userSpaceOnUse" patternTransform="scale(0.5) rotate(30)">
<polygon points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 2.3,33.7 12.3,29.2" id="hex" fill="rgb(240,240,240)" stroke="darkgray" stroke-width="1" />
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#wooblies)" />
</svg>

After

Width:  |  Height:  |  Size: 686 B

12
public/test_bg3.svg Normal file
View File

@ -0,0 +1,12 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs>
<pattern id="wooblies" width="50" height="43.4" patternUnits="userSpaceOnUse" patternTransform="scale(0.5) rotate(30)">
<polygon points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 2.3,33.7 12.3,29.2" id="hex" fill="rgba(240,240,240)" stroke="darkgray" stroke-width="0.5" fill-opacity="0.1" />
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#wooblies)" />
</svg>

After

Width:  |  Height:  |  Size: 708 B

View File

@ -80,7 +80,7 @@ func route_custom_page(w http.ResponseWriter, r *http.Request){
NotFound(w,r,user)
return
}
pi := Page{"Page",user,noticeList,tList,0}
pi := Page{"Page",user,noticeList,tList,nil}
err := templates.ExecuteTemplate(w,"page_" + name,pi)
if err != nil {
InternalError(err,w,r,user)
@ -92,11 +92,6 @@ func route_topics(w http.ResponseWriter, r *http.Request){
if !ok {
return
}
// I'll have to find a solution which doesn't involve shutting down all of the routes for a user, if they don't have ANY permissions
/*if !user.Perms.ViewTopic {
NoPermissions(w,r,user)
return
}*/
var topicList []TopicUser
rows, err := get_topic_list_stmt.Query()
@ -161,7 +156,14 @@ func route_forum(w http.ResponseWriter, r *http.Request){
NotFound(w,r,user)
return
}
if !user.Perms.ViewTopic {
//fmt.Printf("%+v\n", groups[user.Group].Forums)
if groups[user.Group].Forums[fid].Overrides {
if !groups[user.Group].Forums[fid].ViewTopic {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic {
NoPermissions(w,r,user)
return
}
@ -230,9 +232,10 @@ func route_forums(w http.ResponseWriter, r *http.Request){
}
var forumList []Forum
for _, forum := range forums {
if forum.Active {
forumList = append(forumList, forum)
group := groups[user.Group]
for fid, _ := range group.CanSee {
if forums[fid].Active && forums[fid].Name != "" {
forumList = append(forumList, forums[fid])
}
}
@ -268,12 +271,6 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
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
}
// Get the topic..
err = get_topic_user_stmt.QueryRow(topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.CreatedByName, &topic.Avatar, &group, &topic.URLPrefix, &topic.URLName, &topic.Level)
@ -285,6 +282,21 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
return
}
if (topic.ParentID > forumCapCount) || (topic.ParentID < 0) || forums[topic.ParentID].Name=="" {
LocalError("The topic's parent forum doesn't exist.",w,r,user)
return
}
if groups[user.Group].Forums[topic.ParentID].Overrides {
if !groups[user.Group].Forums[topic.ParentID].ViewTopic {
NoPermissions(w,r,user)
return
}
} else if !user.Perms.ViewTopic {
NoPermissions(w,r,user)
return
}
topic.Content = template.HTML(parse_message(content))
topic.ContentLines = strings.Count(content,"\n")

View File

@ -1,7 +1,7 @@
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
package main
import "io"
import "strconv"
import "io"
func init() {
template_forum_handle = template_forum

View File

@ -60,10 +60,10 @@ var topic_5 []byte = []byte(`" />
var topic_6 []byte = []byte(`?page=`)
var topic_7 []byte = []byte(`">&gt;</a></div>`)
var topic_8 []byte = []byte(`
<div class="rowblock">
<div class="rowblock topic_block">
<form action='/topic/edit/submit/`)
var topic_9 []byte = []byte(`' method="post">
<div class="rowitem"`)
<div class="rowitem topic_item"`)
var topic_10 []byte = []byte(` style="background-color: #FFFFEA;"`)
var topic_11 []byte = []byte(` style="background-color: #eaeaea;"`)
var topic_12 []byte = []byte(`>
@ -176,10 +176,10 @@ var topic_alt_5 []byte = []byte(`" />
var topic_alt_6 []byte = []byte(`?page=`)
var topic_alt_7 []byte = []byte(`">&gt;</a></div>`)
var topic_alt_8 []byte = []byte(`
<div class="rowblock">
<div class="rowblock topic_block">
<form action='/topic/edit/submit/`)
var topic_alt_9 []byte = []byte(`' method="post">
<div class="rowitem rowhead`)
<div class="rowitem topic_item rowhead`)
var topic_alt_10 []byte = []byte(` topic_sticky_head`)
var topic_alt_11 []byte = []byte(` topic_closed_head`)
var topic_alt_12 []byte = []byte(`">

View File

@ -1,8 +1,8 @@
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
package main
import "io"
import "strconv"
import "html/template"
import "io"
func init() {
template_topic_alt_handle = template_topic_alt

View File

@ -1,18 +1,18 @@
{{template "header.html" . }}
{{template "panel-menu.html" . }}
<script>var form_vars = {'forum-active': ['Hide','Show']};</script>
<div class="colblock_right">
<div class="rowitem rowhead"><a>Forums</a></div>
</div>
<div class="colblock_right">
{{range .ItemList}}
<div class="rowitem editable_parent" style="font-weight: normal;{{if eq .ID 1}}border-bottom-style:solid;{{end}}">
<a class="editable_block" style="font-size: 20px;position:relative;top: -2px;text-transform: none;{{if not .Active}}color:#707070;{{end}}">{{.Name}}</a>
<a data-field="forum-name" data-type="text" class="editable_block" style="font-size: 20px;position:relative;top: -2px;text-transform: none;{{if not .Active}}color:#707070;{{end}}">{{.Name}}</a>
<span style="float: right;">
{{if not .Active}}<span class="username" style="color: black;">Hidden</span>{{end}}
{{if gt .ID 1}}
<a href="/panel/forums/edit/submit/{{.ID}}" class="username edit_field">Edit</a>
<a href="/panel/forums/delete/{{.ID}}?session={{$.CurrentUser.Session}}" class="username">Delete</a>
{{end}}
<span data-field="forum-active" data-type="list" class="username editable_block hide_on_zero" style="color: black;{{if .Active}}display:none;" data-value="1"{{else}}" data-value="0"{{end}}>Hidden</span>
{{if gt .ID 0}}<a class="username edit_fields hide_on_edit">Edit</a>
<a href="/panel/forums/edit/submit/{{.ID}}"><button class='username submit_edit show_on_edit' type='submit'>Update</button></a>{{end}}
{{if gt .ID 1}}<a href="/panel/forums/delete/{{.ID}}?session={{$.CurrentUser.Session}}" class="username">Delete</a>{{end}}
</span>
</div>
{{end}}
@ -33,6 +33,17 @@
<option value="0">No</option>
</select></div>
</div>
<!--<div class="formrow">
<div class="formitem"><a>Preset</a></div>
<div class="formitem"><select name="forum-preset">
<option selected value="all">Everyone</option>
<option value="announce">Announcements</option>
<option value="members">Member Only</option>
<option value="staff">Staff Only</option>
<option value="admins">Admin Only</option>
<option value="archive">Archive</option>
</select></div>
</div>-->
<div class="formrow">
<div class="formitem"><button name="panel-button" class="formbutton">Add Forum</button></div>
</div>

View File

@ -6,5 +6,5 @@
{{if .CurrentUser.Perms.EditSettings}}<div class="rowitem passive"><a href="/panel/settings/">Settings</a></div>{{end}}
{{if .CurrentUser.Perms.ManageThemes}}<div class="rowitem passive"><a href="/panel/themes/">Themes</a></div>{{end}}
{{if .CurrentUser.Perms.ManagePlugins}}<div class="rowitem passive"><a href="/panel/plugins/">Plugins</a></div>{{end}}
<div class="rowitem passive"><a href="/forum/1">Reported Content</a></div>
<div class="rowitem passive"><a href="/forum/1">Reports</a></div>
</div>

View File

@ -2,9 +2,9 @@
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/{{.Topic.ID}}?page={{subtract .Page 1}}">&lt;</a></div>{{end}}
{{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}}">&gt;</a></div>{{end}}
<div class="rowblock">
<div class="rowblock topic_block">
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
<div class="rowitem"{{if .Topic.Sticky}} style="background-color: #FFFFEA;"{{else if .Topic.Is_Closed}} style="background-color: #eaeaea;"{{end}}>
<div class="rowitem topic_item"{{if .Topic.Sticky}} style="background-color: #FFFFEA;"{{else if .Topic.Is_Closed}} style="background-color: #eaeaea;"{{end}}>
<a class='topic_name hide_on_edit'>{{.Topic.Title}}</a>
{{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;">&#x1F512;&#xFE0E</span>{{end}}
{{if .CurrentUser.Is_Mod}}

View File

@ -2,9 +2,9 @@
{{if gt .Page 1}}<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/{{.Topic.ID}}?page={{subtract .Page 1}}">&lt;</a></div>{{end}}
{{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}}">&gt;</a></div>{{end}}
<div class="rowblock">
<div class="rowblock topic_block">
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
<div class="rowitem rowhead{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.Is_Closed}} topic_closed_head{{end}}">
<div class="rowitem topic_item rowhead{{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>
{{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;">&#x1F512;&#xFE0E</span>{{end}}
{{if .CurrentUser.Is_Mod}}

View File

@ -8,6 +8,8 @@ body
{
font-family: arial;
padding-bottom: 8px;
background-image: url('/static/test_bg2.svg');
background-size: cover;
}
/* Patch for Edge */
@ -24,6 +26,7 @@ ul
height: 28px;
list-style-type: none;
border: 1px solid #ccc;
background-color: white;
}
li
{
@ -110,6 +113,7 @@ li a
padding-bottom: 12px;
font-weight: bold;
text-transform: uppercase;
background-color: white;
}
.rowitem.passive
{
@ -167,15 +171,14 @@ li a
.formrow
{
width: 100%;
background-color: white;
}
/* Clearfix */
.formrow:before, .formrow:after {
content: " ";
display: table;
}
.formrow:after {
clear: both;
}
.formrow:after { clear: both; }
.formrow:not(:last-child)
{
border-bottom: 1px dotted #ccc;

View File

@ -24,6 +24,7 @@ ul
height: 28px;
list-style-type: none;
border: 1px solid #ccc;
background-color: white;
}
li
{
@ -101,6 +102,7 @@ li a
padding-bottom: 12px;
font-weight: bold;
text-transform: uppercase;
background-color: white;
}
.rowitem.passive
{
@ -151,20 +153,16 @@ li a
.formrow
{
/*height: 40px;*/
width: 100%;
background-color: white;
}
/*Clearfix*/
.formrow:before,
.formrow:after {
.formrow:before, .formrow:after {
content: " ";
display: table;
}
.formrow:after {
clear: both;
}
.formrow:after { clear: both; }
.formrow:not(:last-child)
{

View File

@ -77,16 +77,19 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList
// Are there any session cookies..?
cookie, err := r.Cookie("uid")
if err != nil {
user.Group = 6
user.Perms = GuestPerms
return user, noticeList, true
}
user.ID, err = strconv.Atoi(cookie.Value)
if err != nil {
user.Group = 6
user.Perms = GuestPerms
return user, noticeList, true
}
cookie, err = r.Cookie("session")
if err != nil {
user.Group = 6
user.Perms = GuestPerms
return user, noticeList, true
}
@ -96,6 +99,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList
if err == sql.ErrNoRows {
user.ID = 0
user.Session = ""
user.Group = 6
user.Perms = GuestPerms
return user, noticeList, true
} else if err != nil {
@ -145,16 +149,19 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ
// Are there any session cookies..?
cookie, err := r.Cookie("uid")
if err != nil {
user.Group = 6
user.Perms = GuestPerms
return user, true
}
user.ID, err = strconv.Atoi(cookie.Value)
if err != nil {
user.Group = 6
user.Perms = GuestPerms
return user, true
}
cookie, err = r.Cookie("session")
if err != nil {
user.Group = 6
user.Perms = GuestPerms
return user, true
}
@ -164,6 +171,7 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ
if err == sql.ErrNoRows {
user.ID = 0
user.Session = ""
user.Group = 6
user.Perms = GuestPerms
return user, true
} else if err != nil {

View File

@ -193,3 +193,10 @@ func fill_forum_id_gap(biggerID int, smallerID int) {
forums = append(forums, dummy)
}
}
func fill_group_id_gap(biggerID int, smallerID int) {
dummy := Group{ID:0, Name:""}
for i := smallerID; i > biggerID;i++ {
groups = append(groups, dummy)
}
}