diff --git a/common/group.go b/common/group.go index 0ce623dc..8627d90c 100644 --- a/common/group.go +++ b/common/group.go @@ -1,7 +1,11 @@ package common -import "database/sql" -import "../query_gen/lib" +import ( + "database/sql" + "encoding/json" + + "../query_gen/lib" +) var blankGroup = Group{ID: 0, Name: ""} @@ -31,7 +35,9 @@ type Group struct { } type GroupStmts struct { - updateGroupRank *sql.Stmt + updateGroup *sql.Stmt + updateGroupRank *sql.Stmt + updateGroupPerms *sql.Stmt } var groupStmts GroupStmts @@ -39,7 +45,9 @@ var groupStmts GroupStmts func init() { DbInits.Add(func(acc *qgen.Accumulator) error { groupStmts = GroupStmts{ - updateGroupRank: acc.Update("users_groups").Set("is_admin = ?, is_mod = ?, is_banned = ?").Where("gid = ?").Prepare(), + updateGroup: acc.Update("users_groups").Set("name = ?, tag = ?").Where("gid = ?").Prepare(), + updateGroupRank: acc.Update("users_groups").Set("is_admin = ?, is_mod = ?, is_banned = ?").Where("gid = ?").Prepare(), + updateGroupPerms: acc.Update("users_groups").Set("permissions = ?").Where("gid = ?").Prepare(), } return acc.FirstError() }) @@ -55,11 +63,40 @@ func (group *Group) ChangeRank(isAdmin bool, isMod bool, isBanned bool) (err err return nil } +func (group *Group) Update(name string, tag string) (err error) { + _, err = groupStmts.updateGroup.Exec(name, tag, group.ID) + if err != nil { + return err + } + + Groups.Reload(group.ID) + return nil +} + +// Please don't pass arbitrary inputs to this method +func (group *Group) UpdatePerms(perms map[string]bool) (err error) { + pjson, err := json.Marshal(perms) + if err != nil { + return err + } + _, err = groupStmts.updateGroupPerms.Exec(pjson, group.ID) + if err != nil { + return err + } + return RebuildGroupPermissions(group.ID) +} + // Copy gives you a non-pointer concurrency safe copy of the group func (group *Group) Copy() Group { return *group } +func (group *Group) CopyPtr() (co *Group) { + co = new(Group) + *co = *group + return co +} + // TODO: Replace this sorting mechanism with something a lot more efficient // ? - Use sort.Slice instead? type SortGroup []*Group diff --git a/gen_mssql.go b/gen_mssql.go index b43ed5e5..48cd78f2 100644 --- a/gen_mssql.go +++ b/gen_mssql.go @@ -16,8 +16,6 @@ type Stmts struct { addForumPermsToForum *sql.Stmt addTheme *sql.Stmt updateTheme *sql.Stmt - updateGroupPerms *sql.Stmt - updateGroup *sql.Stmt updateEmail *sql.Stmt setTempGroup *sql.Stmt bumpSync *sql.Stmt @@ -93,22 +91,6 @@ func _gen_mssql() (err error) { return err } - common.DebugLog("Preparing updateGroupPerms statement.") - stmts.updateGroupPerms, err = db.Prepare("UPDATE [users_groups] SET [permissions] = ? WHERE [gid] = ?") - if err != nil { - log.Print("Error in updateGroupPerms statement.") - log.Print("Bad Query: ","UPDATE [users_groups] SET [permissions] = ? WHERE [gid] = ?") - return err - } - - common.DebugLog("Preparing updateGroup statement.") - stmts.updateGroup, err = db.Prepare("UPDATE [users_groups] SET [name] = ?,[tag] = ? WHERE [gid] = ?") - if err != nil { - log.Print("Error in updateGroup statement.") - log.Print("Bad Query: ","UPDATE [users_groups] SET [name] = ?,[tag] = ? WHERE [gid] = ?") - return err - } - common.DebugLog("Preparing updateEmail statement.") stmts.updateEmail, err = db.Prepare("UPDATE [emails] SET [email] = ?,[uid] = ?,[validated] = ?,[token] = ? WHERE [email] = ?") if err != nil { diff --git a/gen_mysql.go b/gen_mysql.go index 9b74205f..c6337443 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -18,8 +18,6 @@ type Stmts struct { addForumPermsToForum *sql.Stmt addTheme *sql.Stmt updateTheme *sql.Stmt - updateGroupPerms *sql.Stmt - updateGroup *sql.Stmt updateEmail *sql.Stmt setTempGroup *sql.Stmt bumpSync *sql.Stmt @@ -88,20 +86,6 @@ func _gen_mysql() (err error) { return err } - common.DebugLog("Preparing updateGroupPerms statement.") - stmts.updateGroupPerms, err = db.Prepare("UPDATE `users_groups` SET `permissions` = ? WHERE `gid` = ?") - if err != nil { - log.Print("Error in updateGroupPerms statement.") - return err - } - - common.DebugLog("Preparing updateGroup statement.") - stmts.updateGroup, err = db.Prepare("UPDATE `users_groups` SET `name` = ?,`tag` = ? WHERE `gid` = ?") - if err != nil { - log.Print("Error in updateGroup statement.") - return err - } - common.DebugLog("Preparing updateEmail statement.") stmts.updateEmail, err = db.Prepare("UPDATE `emails` SET `email` = ?,`uid` = ?,`validated` = ?,`token` = ? WHERE `email` = ?") if err != nil { diff --git a/gen_pgsql.go b/gen_pgsql.go index 8030eb66..488d7feb 100644 --- a/gen_pgsql.go +++ b/gen_pgsql.go @@ -12,8 +12,6 @@ type Stmts struct { addForumPermsToForum *sql.Stmt addTheme *sql.Stmt updateTheme *sql.Stmt - updateGroupPerms *sql.Stmt - updateGroup *sql.Stmt updateEmail *sql.Stmt setTempGroup *sql.Stmt bumpSync *sql.Stmt @@ -53,20 +51,6 @@ func _gen_pgsql() (err error) { return err } - common.DebugLog("Preparing updateGroupPerms statement.") - stmts.updateGroupPerms, err = db.Prepare("UPDATE \"users_groups\" SET `permissions` = ? WHERE `gid` = ?") - if err != nil { - log.Print("Error in updateGroupPerms statement.") - return err - } - - common.DebugLog("Preparing updateGroup statement.") - stmts.updateGroup, err = db.Prepare("UPDATE \"users_groups\" SET `name` = ?,`tag` = ? WHERE `gid` = ?") - if err != nil { - log.Print("Error in updateGroup statement.") - return err - } - common.DebugLog("Preparing updateEmail statement.") stmts.updateEmail, err = db.Prepare("UPDATE \"emails\" SET `email` = ?,`uid` = ?,`validated` = ?,`token` = ? WHERE `email` = ?") if err != nil { diff --git a/gen_router.go b/gen_router.go index 303d1db3..92d91b93 100644 --- a/gen_router.go +++ b/gen_router.go @@ -91,12 +91,12 @@ var RouteMap = map[string]interface{}{ "panel.AnalyticsPosts": panel.AnalyticsPosts, "panel.AnalyticsTopics": panel.AnalyticsTopics, "panel.AnalyticsForums": panel.AnalyticsForums, - "routePanelGroups": routePanelGroups, - "routePanelGroupsEdit": routePanelGroupsEdit, - "routePanelGroupsEditPerms": routePanelGroupsEditPerms, - "routePanelGroupsEditSubmit": routePanelGroupsEditSubmit, - "routePanelGroupsEditPermsSubmit": routePanelGroupsEditPermsSubmit, - "routePanelGroupsCreateSubmit": routePanelGroupsCreateSubmit, + "panel.Groups": panel.Groups, + "panel.GroupsEdit": panel.GroupsEdit, + "panel.GroupsEditPerms": panel.GroupsEditPerms, + "panel.GroupsEditSubmit": panel.GroupsEditSubmit, + "panel.GroupsEditPermsSubmit": panel.GroupsEditPermsSubmit, + "panel.GroupsCreateSubmit": panel.GroupsCreateSubmit, "panel.Backups": panel.Backups, "panel.LogsRegs": panel.LogsRegs, "panel.LogsMod": panel.LogsMod, @@ -222,12 +222,12 @@ var routeMapEnum = map[string]int{ "panel.AnalyticsPosts": 65, "panel.AnalyticsTopics": 66, "panel.AnalyticsForums": 67, - "routePanelGroups": 68, - "routePanelGroupsEdit": 69, - "routePanelGroupsEditPerms": 70, - "routePanelGroupsEditSubmit": 71, - "routePanelGroupsEditPermsSubmit": 72, - "routePanelGroupsCreateSubmit": 73, + "panel.Groups": 68, + "panel.GroupsEdit": 69, + "panel.GroupsEditPerms": 70, + "panel.GroupsEditSubmit": 71, + "panel.GroupsEditPermsSubmit": 72, + "panel.GroupsCreateSubmit": 73, "panel.Backups": 74, "panel.LogsRegs": 75, "panel.LogsMod": 76, @@ -351,12 +351,12 @@ var reverseRouteMapEnum = map[int]string{ 65: "panel.AnalyticsPosts", 66: "panel.AnalyticsTopics", 67: "panel.AnalyticsForums", - 68: "routePanelGroups", - 69: "routePanelGroupsEdit", - 70: "routePanelGroupsEditPerms", - 71: "routePanelGroupsEditSubmit", - 72: "routePanelGroupsEditPermsSubmit", - 73: "routePanelGroupsCreateSubmit", + 68: "panel.Groups", + 69: "panel.GroupsEdit", + 70: "panel.GroupsEditPerms", + 71: "panel.GroupsEditSubmit", + 72: "panel.GroupsEditPermsSubmit", + 73: "panel.GroupsCreateSubmit", 74: "panel.Backups", 75: "panel.LogsRegs", 76: "panel.LogsMod", @@ -1376,13 +1376,13 @@ func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, u err = panel.AnalyticsForums(w,req,user) case "/panel/groups/": counters.RouteViewCounter.Bump(68) - err = routePanelGroups(w,req,user) + err = panel.Groups(w,req,user) case "/panel/groups/edit/": counters.RouteViewCounter.Bump(69) - err = routePanelGroupsEdit(w,req,user,extraData) + err = panel.GroupsEdit(w,req,user,extraData) case "/panel/groups/edit/perms/": counters.RouteViewCounter.Bump(70) - err = routePanelGroupsEditPerms(w,req,user,extraData) + err = panel.GroupsEditPerms(w,req,user,extraData) case "/panel/groups/edit/submit/": err = common.NoSessionMismatch(w,req,user) if err != nil { @@ -1391,7 +1391,7 @@ func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, u } counters.RouteViewCounter.Bump(71) - err = routePanelGroupsEditSubmit(w,req,user,extraData) + err = panel.GroupsEditSubmit(w,req,user,extraData) case "/panel/groups/edit/perms/submit/": err = common.NoSessionMismatch(w,req,user) if err != nil { @@ -1400,7 +1400,7 @@ func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, u } counters.RouteViewCounter.Bump(72) - err = routePanelGroupsEditPermsSubmit(w,req,user,extraData) + err = panel.GroupsEditPermsSubmit(w,req,user,extraData) case "/panel/groups/create/": err = common.NoSessionMismatch(w,req,user) if err != nil { @@ -1409,7 +1409,7 @@ func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, u } counters.RouteViewCounter.Bump(73) - err = routePanelGroupsCreateSubmit(w,req,user) + err = panel.GroupsCreateSubmit(w,req,user) case "/panel/backups/": err = common.SuperAdminOnly(w,req,user) if err != nil { diff --git a/panel_routes.go b/panel_routes.go index e4073705..53208bfe 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -2,7 +2,6 @@ package main import ( "database/sql" - "encoding/json" "errors" "fmt" "log" @@ -171,402 +170,6 @@ func routePanelDashboard(w http.ResponseWriter, r *http.Request, user common.Use return panelRenderTemplate("panel_dashboard", w, r, user, &pi) } -func routePanelGroups(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { - header, stats, ferr := common.PanelUserCheck(w, r, &user) - if ferr != nil { - return ferr - } - header.Title = common.GetTitlePhrase("panel_groups") - - page, _ := strconv.Atoi(r.FormValue("page")) - perPage := 9 - offset, page, lastPage := common.PageOffset(stats.Groups, page, perPage) - - // Skip the 'Unknown' group - offset++ - - var count int - var groupList []common.GroupAdmin - groups, _ := common.Groups.GetRange(offset, 0) - for _, group := range groups { - if count == perPage { - break - } - - var rank string - var rankClass string - var canEdit bool - var canDelete = false - - // TODO: Use a switch for this - // TODO: Localise this - if group.IsAdmin { - rank = "Admin" - rankClass = "admin" - } else if group.IsMod { - rank = "Mod" - rankClass = "mod" - } else if group.IsBanned { - rank = "Banned" - rankClass = "banned" - } else if group.ID == 6 { - rank = "Guest" - rankClass = "guest" - } else { - rank = "Member" - rankClass = "member" - } - - canEdit = user.Perms.EditGroup && (!group.IsAdmin || user.Perms.EditGroupAdmin) && (!group.IsMod || user.Perms.EditGroupSuperMod) - groupList = append(groupList, common.GroupAdmin{group.ID, group.Name, rank, rankClass, canEdit, canDelete}) - count++ - } - //log.Printf("groupList: %+v\n", groupList) - - pageList := common.Paginate(stats.Groups, perPage, 5) - pi := common.PanelGroupPage{&common.BasePanelPage{header, stats, "groups", common.ReportForumID}, groupList, common.Paginator{pageList, page, lastPage}} - return panelRenderTemplate("panel_groups", w, r, user, &pi) -} - -func routePanelGroupsEdit(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { - header, stats, ferr := common.PanelUserCheck(w, r, &user) - if ferr != nil { - return ferr - } - if !user.Perms.EditGroup { - return common.NoPermissions(w, r, user) - } - header.Title = common.GetTitlePhrase("panel_edit_group") - - gid, err := strconv.Atoi(sgid) - if err != nil { - return common.LocalError("You need to provide a whole number for the group ID", w, r, user) - } - - group, err := common.Groups.Get(gid) - if err == ErrNoRows { - //log.Print("aaaaa monsters") - return common.NotFound(w, r, header) - } else if err != nil { - return common.InternalError(err, w, r) - } - - if group.IsAdmin && !user.Perms.EditGroupAdmin { - return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) - } - if group.IsMod && !user.Perms.EditGroupSuperMod { - return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) - } - - var rank string - switch { - case group.IsAdmin: - rank = "Admin" - case group.IsMod: - rank = "Mod" - case group.IsBanned: - rank = "Banned" - case group.ID == 6: - rank = "Guest" - default: - rank = "Member" - } - - disableRank := !user.Perms.EditGroupGlobalPerms || (group.ID == 6) - - pi := common.PanelEditGroupPage{&common.BasePanelPage{header, stats, "groups", common.ReportForumID}, group.ID, group.Name, group.Tag, rank, disableRank} - if common.RunPreRenderHook("pre_render_panel_edit_group", w, r, &user, &pi) { - return nil - } - err = common.Templates.ExecuteTemplate(w, "panel_group_edit.html", pi) - if err != nil { - return common.InternalError(err, w, r) - } - return nil -} - -func routePanelGroupsEditPerms(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { - header, stats, ferr := common.PanelUserCheck(w, r, &user) - if ferr != nil { - return ferr - } - if !user.Perms.EditGroup { - return common.NoPermissions(w, r, user) - } - header.Title = common.GetTitlePhrase("panel_edit_group") - - gid, err := strconv.Atoi(sgid) - if err != nil { - return common.LocalError("The Group ID is not a valid integer.", w, r, user) - } - - group, err := common.Groups.Get(gid) - if err == ErrNoRows { - //log.Print("aaaaa monsters") - return common.NotFound(w, r, header) - } else if err != nil { - return common.InternalError(err, w, r) - } - - if group.IsAdmin && !user.Perms.EditGroupAdmin { - return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) - } - if group.IsMod && !user.Perms.EditGroupSuperMod { - return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) - } - - // TODO: Load the phrases in bulk for efficiency? - var localPerms []common.NameLangToggle - - var addLocalPerm = func(permStr string, perm bool) { - localPerms = append(localPerms, common.NameLangToggle{permStr, common.GetLocalPermPhrase(permStr), perm}) - } - - addLocalPerm("ViewTopic", group.Perms.ViewTopic) - addLocalPerm("LikeItem", group.Perms.LikeItem) - addLocalPerm("CreateTopic", group.Perms.CreateTopic) - //<-- - addLocalPerm("EditTopic", group.Perms.EditTopic) - addLocalPerm("DeleteTopic", group.Perms.DeleteTopic) - addLocalPerm("CreateReply", group.Perms.CreateReply) - addLocalPerm("EditReply", group.Perms.EditReply) - addLocalPerm("DeleteReply", group.Perms.DeleteReply) - addLocalPerm("PinTopic", group.Perms.PinTopic) - addLocalPerm("CloseTopic", group.Perms.CloseTopic) - addLocalPerm("MoveTopic", group.Perms.MoveTopic) - - var globalPerms []common.NameLangToggle - var addGlobalPerm = func(permStr string, perm bool) { - globalPerms = append(globalPerms, common.NameLangToggle{permStr, common.GetGlobalPermPhrase(permStr), perm}) - } - - addGlobalPerm("BanUsers", group.Perms.BanUsers) - addGlobalPerm("ActivateUsers", group.Perms.ActivateUsers) - addGlobalPerm("EditUser", group.Perms.EditUser) - addGlobalPerm("EditUserEmail", group.Perms.EditUserEmail) - addGlobalPerm("EditUserPassword", group.Perms.EditUserPassword) - addGlobalPerm("EditUserGroup", group.Perms.EditUserGroup) - addGlobalPerm("EditUserGroupSuperMod", group.Perms.EditUserGroupSuperMod) - addGlobalPerm("EditUserGroupAdmin", group.Perms.EditUserGroupAdmin) - addGlobalPerm("EditGroup", group.Perms.EditGroup) - addGlobalPerm("EditGroupLocalPerms", group.Perms.EditGroupLocalPerms) - addGlobalPerm("EditGroupGlobalPerms", group.Perms.EditGroupGlobalPerms) - addGlobalPerm("EditGroupSuperMod", group.Perms.EditGroupSuperMod) - addGlobalPerm("EditGroupAdmin", group.Perms.EditGroupAdmin) - addGlobalPerm("ManageForums", group.Perms.ManageForums) - addGlobalPerm("EditSettings", group.Perms.EditSettings) - addGlobalPerm("ManageThemes", group.Perms.ManageThemes) - addGlobalPerm("ManagePlugins", group.Perms.ManagePlugins) - addGlobalPerm("ViewAdminLogs", group.Perms.ViewAdminLogs) - addGlobalPerm("ViewIPs", group.Perms.ViewIPs) - addGlobalPerm("UploadFiles", group.Perms.UploadFiles) - - pi := common.PanelEditGroupPermsPage{&common.BasePanelPage{header, stats, "groups", common.ReportForumID}, group.ID, group.Name, localPerms, globalPerms} - if common.RunPreRenderHook("pre_render_panel_edit_group_perms", w, r, &user, &pi) { - return nil - } - err = common.Templates.ExecuteTemplate(w, "panel_group_edit_perms.html", pi) - if err != nil { - return common.InternalError(err, w, r) - } - return nil -} - -func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { - _, ferr := common.SimplePanelUserCheck(w, r, &user) - if ferr != nil { - return ferr - } - if !user.Perms.EditGroup { - return common.NoPermissions(w, r, user) - } - - gid, err := strconv.Atoi(sgid) - if err != nil { - return common.LocalError("You need to provide a whole number for the group ID", w, r, user) - } - - group, err := common.Groups.Get(gid) - if err == ErrNoRows { - //log.Print("aaaaa monsters") - return common.NotFound(w, r, nil) - } else if err != nil { - return common.InternalError(err, w, r) - } - - if group.IsAdmin && !user.Perms.EditGroupAdmin { - return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) - } - if group.IsMod && !user.Perms.EditGroupSuperMod { - return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) - } - - gname := r.FormValue("group-name") - if gname == "" { - return common.LocalError("The group name can't be left blank.", w, r, user) - } - gtag := r.FormValue("group-tag") - rank := r.FormValue("group-type") - - var originalRank string - // TODO: Use a switch for this - if group.IsAdmin { - originalRank = "Admin" - } else if group.IsMod { - originalRank = "Mod" - } else if group.IsBanned { - originalRank = "Banned" - } else if group.ID == 6 { - originalRank = "Guest" - } else { - originalRank = "Member" - } - - if rank != originalRank { - if !user.Perms.EditGroupGlobalPerms { - return common.LocalError("You need the EditGroupGlobalPerms permission to change the group type.", w, r, user) - } - - switch rank { - case "Admin": - if !user.Perms.EditGroupAdmin { - return common.LocalError("You need the EditGroupAdmin permission to designate this group as an admin group.", w, r, user) - } - err = group.ChangeRank(true, true, false) - case "Mod": - if !user.Perms.EditGroupSuperMod { - return common.LocalError("You need the EditGroupSuperMod permission to designate this group as a super-mod group.", w, r, user) - } - err = group.ChangeRank(false, true, false) - case "Banned": - err = group.ChangeRank(false, false, true) - case "Guest": - return common.LocalError("You can't designate a group as a guest group.", w, r, user) - case "Member": - err = group.ChangeRank(false, false, false) - default: - return common.LocalError("Invalid group type.", w, r, user) - } - if err != nil { - return common.InternalError(err, w, r) - } - } - - // TODO: Move this to *Group - _, err = stmts.updateGroup.Exec(gname, gtag, gid) - if err != nil { - return common.InternalError(err, w, r) - } - common.Groups.Reload(gid) - - http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) - return nil -} - -func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { - _, ferr := common.SimplePanelUserCheck(w, r, &user) - if ferr != nil { - return ferr - } - if !user.Perms.EditGroup { - return common.NoPermissions(w, r, user) - } - - gid, err := strconv.Atoi(sgid) - if err != nil { - return common.LocalError("The Group ID is not a valid integer.", w, r, user) - } - - group, err := common.Groups.Get(gid) - if err == ErrNoRows { - //log.Print("aaaaa monsters o.o") - return common.NotFound(w, r, nil) - } else if err != nil { - return common.InternalError(err, w, r) - } - - if group.IsAdmin && !user.Perms.EditGroupAdmin { - return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) - } - if group.IsMod && !user.Perms.EditGroupSuperMod { - return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) - } - - var pmap = make(map[string]bool) - if user.Perms.EditGroupLocalPerms { - for _, perm := range common.LocalPermList { - pvalue := r.PostFormValue("group-perm-" + perm) - pmap[perm] = (pvalue == "1") - } - } - - if user.Perms.EditGroupGlobalPerms { - for _, perm := range common.GlobalPermList { - pvalue := r.PostFormValue("group-perm-" + perm) - pmap[perm] = (pvalue == "1") - } - } - - // TODO: Abstract this - pjson, err := json.Marshal(pmap) - if err != nil { - return common.LocalError("Unable to marshal the data", w, r, user) - } - _, err = stmts.updateGroupPerms.Exec(pjson, gid) - if err != nil { - return common.InternalError(err, w, r) - } - err = common.RebuildGroupPermissions(gid) - if err != nil { - return common.InternalError(err, w, r) - } - - http.Redirect(w, r, "/panel/groups/edit/perms/"+strconv.Itoa(gid), http.StatusSeeOther) - return nil -} - -func routePanelGroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { - _, ferr := common.SimplePanelUserCheck(w, r, &user) - if ferr != nil { - return ferr - } - if !user.Perms.EditGroup { - return common.NoPermissions(w, r, user) - } - - groupName := r.PostFormValue("group-name") - if groupName == "" { - return common.LocalError("You need a name for this group!", w, r, user) - } - groupTag := r.PostFormValue("group-tag") - - var isAdmin, isMod, isBanned bool - if user.Perms.EditGroupGlobalPerms { - groupType := r.PostFormValue("group-type") - if groupType == "Admin" { - if !user.Perms.EditGroupAdmin { - return common.LocalError("You need the EditGroupAdmin permission to create admin groups", w, r, user) - } - isAdmin = true - isMod = true - } else if groupType == "Mod" { - if !user.Perms.EditGroupSuperMod { - return common.LocalError("You need the EditGroupSuperMod permission to create admin groups", w, r, user) - } - isMod = true - } else if groupType == "Banned" { - isBanned = true - } - } - - gid, err := common.Groups.Create(groupName, groupTag, isAdmin, isMod, isBanned) - if err != nil { - return common.InternalError(err, w, r) - } - http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) - return nil -} - func routePanelThemes(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { header, stats, ferr := common.PanelUserCheck(w, r, &user) if ferr != nil { diff --git a/query_gen/main.go b/query_gen/main.go index e28f0619..dbae7617 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -292,10 +292,6 @@ func writeUpdates(adapter qgen.Adapter) error { build.Update("updateTheme").Table("themes").Set("default = ?").Where("uname = ?").Parse() - build.Update("updateGroupPerms").Table("users_groups").Set("permissions = ?").Where("gid = ?").Parse() - - build.Update("updateGroup").Table("users_groups").Set("name = ?, tag = ?").Where("gid = ?").Parse() - build.Update("updateEmail").Table("emails").Set("email = ?, uid = ?, validated = ?, token = ?").Where("email = ?").Parse() build.Update("setTempGroup").Table("users").Set("temp_group = ?").Where("uid = ?").Parse() diff --git a/router_gen/routes.go b/router_gen/routes.go index c7103a08..b930f96a 100644 --- a/router_gen/routes.go +++ b/router_gen/routes.go @@ -204,12 +204,12 @@ func buildPanelRoutes() { View("panel.AnalyticsTopics", "/panel/analytics/topics/").Before("ParseForm"), View("panel.AnalyticsForums", "/panel/analytics/forums/").Before("ParseForm"), - View("routePanelGroups", "/panel/groups/"), - View("routePanelGroupsEdit", "/panel/groups/edit/", "extraData"), - View("routePanelGroupsEditPerms", "/panel/groups/edit/perms/", "extraData"), - Action("routePanelGroupsEditSubmit", "/panel/groups/edit/submit/", "extraData"), - Action("routePanelGroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extraData"), - Action("routePanelGroupsCreateSubmit", "/panel/groups/create/"), + View("panel.Groups", "/panel/groups/"), + View("panel.GroupsEdit", "/panel/groups/edit/", "extraData"), + View("panel.GroupsEditPerms", "/panel/groups/edit/perms/", "extraData"), + Action("panel.GroupsEditSubmit", "/panel/groups/edit/submit/", "extraData"), + Action("panel.GroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extraData"), + Action("panel.GroupsCreateSubmit", "/panel/groups/create/"), View("panel.Backups", "/panel/backups/", "extraData").Before("SuperAdminOnly").NoGzip(), // TODO: Tests for this View("panel.LogsRegs", "/panel/logs/regs/"), diff --git a/routes/panel/groups.go b/routes/panel/groups.go new file mode 100644 index 00000000..d358adfd --- /dev/null +++ b/routes/panel/groups.go @@ -0,0 +1,401 @@ +package panel + +import ( + "database/sql" + "net/http" + "strconv" + + "../../common" +) + +// routePanelGroups +func Groups(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { + header, stats, ferr := common.PanelUserCheck(w, r, &user) + if ferr != nil { + return ferr + } + header.Title = common.GetTitlePhrase("panel_groups") + + page, _ := strconv.Atoi(r.FormValue("page")) + perPage := 9 + offset, page, lastPage := common.PageOffset(stats.Groups, page, perPage) + + // Skip the 'Unknown' group + offset++ + + var count int + var groupList []common.GroupAdmin + groups, _ := common.Groups.GetRange(offset, 0) + for _, group := range groups { + if count == perPage { + break + } + + var rank string + var rankClass string + var canEdit bool + var canDelete = false + + // TODO: Use a switch for this + // TODO: Localise this + if group.IsAdmin { + rank = "Admin" + rankClass = "admin" + } else if group.IsMod { + rank = "Mod" + rankClass = "mod" + } else if group.IsBanned { + rank = "Banned" + rankClass = "banned" + } else if group.ID == 6 { + rank = "Guest" + rankClass = "guest" + } else { + rank = "Member" + rankClass = "member" + } + + canEdit = user.Perms.EditGroup && (!group.IsAdmin || user.Perms.EditGroupAdmin) && (!group.IsMod || user.Perms.EditGroupSuperMod) + groupList = append(groupList, common.GroupAdmin{group.ID, group.Name, rank, rankClass, canEdit, canDelete}) + count++ + } + //log.Printf("groupList: %+v\n", groupList) + + pageList := common.Paginate(stats.Groups, perPage, 5) + pi := common.PanelGroupPage{&common.BasePanelPage{header, stats, "groups", common.ReportForumID}, groupList, common.Paginator{pageList, page, lastPage}} + return panelRenderTemplate("panel_groups", w, r, user, &pi) +} + +//routePanelGroupsEdit +func GroupsEdit(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { + header, stats, ferr := common.PanelUserCheck(w, r, &user) + if ferr != nil { + return ferr + } + if !user.Perms.EditGroup { + return common.NoPermissions(w, r, user) + } + header.Title = common.GetTitlePhrase("panel_edit_group") + + gid, err := strconv.Atoi(sgid) + if err != nil { + return common.LocalError("You need to provide a whole number for the group ID", w, r, user) + } + + group, err := common.Groups.Get(gid) + if err == sql.ErrNoRows { + //log.Print("aaaaa monsters") + return common.NotFound(w, r, header) + } else if err != nil { + return common.InternalError(err, w, r) + } + + if group.IsAdmin && !user.Perms.EditGroupAdmin { + return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) + } + if group.IsMod && !user.Perms.EditGroupSuperMod { + return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) + } + + var rank string + switch { + case group.IsAdmin: + rank = "Admin" + case group.IsMod: + rank = "Mod" + case group.IsBanned: + rank = "Banned" + case group.ID == 6: + rank = "Guest" + default: + rank = "Member" + } + + disableRank := !user.Perms.EditGroupGlobalPerms || (group.ID == 6) + + pi := common.PanelEditGroupPage{&common.BasePanelPage{header, stats, "groups", common.ReportForumID}, group.ID, group.Name, group.Tag, rank, disableRank} + if common.RunPreRenderHook("pre_render_panel_edit_group", w, r, &user, &pi) { + return nil + } + err = common.Templates.ExecuteTemplate(w, "panel_group_edit.html", pi) + if err != nil { + return common.InternalError(err, w, r) + } + return nil +} + +//routePanelGroupsEditPerms +func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { + header, stats, ferr := common.PanelUserCheck(w, r, &user) + if ferr != nil { + return ferr + } + if !user.Perms.EditGroup { + return common.NoPermissions(w, r, user) + } + header.Title = common.GetTitlePhrase("panel_edit_group") + + gid, err := strconv.Atoi(sgid) + if err != nil { + return common.LocalError("The Group ID is not a valid integer.", w, r, user) + } + + group, err := common.Groups.Get(gid) + if err == sql.ErrNoRows { + //log.Print("aaaaa monsters") + return common.NotFound(w, r, header) + } else if err != nil { + return common.InternalError(err, w, r) + } + + if group.IsAdmin && !user.Perms.EditGroupAdmin { + return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) + } + if group.IsMod && !user.Perms.EditGroupSuperMod { + return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) + } + + // TODO: Load the phrases in bulk for efficiency? + var localPerms []common.NameLangToggle + + var addLocalPerm = func(permStr string, perm bool) { + localPerms = append(localPerms, common.NameLangToggle{permStr, common.GetLocalPermPhrase(permStr), perm}) + } + + addLocalPerm("ViewTopic", group.Perms.ViewTopic) + addLocalPerm("LikeItem", group.Perms.LikeItem) + addLocalPerm("CreateTopic", group.Perms.CreateTopic) + //<-- + addLocalPerm("EditTopic", group.Perms.EditTopic) + addLocalPerm("DeleteTopic", group.Perms.DeleteTopic) + addLocalPerm("CreateReply", group.Perms.CreateReply) + addLocalPerm("EditReply", group.Perms.EditReply) + addLocalPerm("DeleteReply", group.Perms.DeleteReply) + addLocalPerm("PinTopic", group.Perms.PinTopic) + addLocalPerm("CloseTopic", group.Perms.CloseTopic) + addLocalPerm("MoveTopic", group.Perms.MoveTopic) + + var globalPerms []common.NameLangToggle + var addGlobalPerm = func(permStr string, perm bool) { + globalPerms = append(globalPerms, common.NameLangToggle{permStr, common.GetGlobalPermPhrase(permStr), perm}) + } + + addGlobalPerm("BanUsers", group.Perms.BanUsers) + addGlobalPerm("ActivateUsers", group.Perms.ActivateUsers) + addGlobalPerm("EditUser", group.Perms.EditUser) + addGlobalPerm("EditUserEmail", group.Perms.EditUserEmail) + addGlobalPerm("EditUserPassword", group.Perms.EditUserPassword) + addGlobalPerm("EditUserGroup", group.Perms.EditUserGroup) + addGlobalPerm("EditUserGroupSuperMod", group.Perms.EditUserGroupSuperMod) + addGlobalPerm("EditUserGroupAdmin", group.Perms.EditUserGroupAdmin) + addGlobalPerm("EditGroup", group.Perms.EditGroup) + addGlobalPerm("EditGroupLocalPerms", group.Perms.EditGroupLocalPerms) + addGlobalPerm("EditGroupGlobalPerms", group.Perms.EditGroupGlobalPerms) + addGlobalPerm("EditGroupSuperMod", group.Perms.EditGroupSuperMod) + addGlobalPerm("EditGroupAdmin", group.Perms.EditGroupAdmin) + addGlobalPerm("ManageForums", group.Perms.ManageForums) + addGlobalPerm("EditSettings", group.Perms.EditSettings) + addGlobalPerm("ManageThemes", group.Perms.ManageThemes) + addGlobalPerm("ManagePlugins", group.Perms.ManagePlugins) + addGlobalPerm("ViewAdminLogs", group.Perms.ViewAdminLogs) + addGlobalPerm("ViewIPs", group.Perms.ViewIPs) + addGlobalPerm("UploadFiles", group.Perms.UploadFiles) + + pi := common.PanelEditGroupPermsPage{&common.BasePanelPage{header, stats, "groups", common.ReportForumID}, group.ID, group.Name, localPerms, globalPerms} + if common.RunPreRenderHook("pre_render_panel_edit_group_perms", w, r, &user, &pi) { + return nil + } + err = common.Templates.ExecuteTemplate(w, "panel_group_edit_perms.html", pi) + if err != nil { + return common.InternalError(err, w, r) + } + return nil +} + +//routePanelGroupsEditSubmit +func GroupsEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { + _, ferr := common.SimplePanelUserCheck(w, r, &user) + if ferr != nil { + return ferr + } + if !user.Perms.EditGroup { + return common.NoPermissions(w, r, user) + } + + gid, err := strconv.Atoi(sgid) + if err != nil { + return common.LocalError("You need to provide a whole number for the group ID", w, r, user) + } + + group, err := common.Groups.Get(gid) + if err == sql.ErrNoRows { + //log.Print("aaaaa monsters") + return common.NotFound(w, r, nil) + } else if err != nil { + return common.InternalError(err, w, r) + } + + if group.IsAdmin && !user.Perms.EditGroupAdmin { + return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) + } + if group.IsMod && !user.Perms.EditGroupSuperMod { + return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) + } + + gname := r.FormValue("group-name") + if gname == "" { + return common.LocalError("The group name can't be left blank.", w, r, user) + } + gtag := r.FormValue("group-tag") + rank := r.FormValue("group-type") + + var originalRank string + // TODO: Use a switch for this + if group.IsAdmin { + originalRank = "Admin" + } else if group.IsMod { + originalRank = "Mod" + } else if group.IsBanned { + originalRank = "Banned" + } else if group.ID == 6 { + originalRank = "Guest" + } else { + originalRank = "Member" + } + + if rank != originalRank { + if !user.Perms.EditGroupGlobalPerms { + return common.LocalError("You need the EditGroupGlobalPerms permission to change the group type.", w, r, user) + } + + switch rank { + case "Admin": + if !user.Perms.EditGroupAdmin { + return common.LocalError("You need the EditGroupAdmin permission to designate this group as an admin group.", w, r, user) + } + err = group.ChangeRank(true, true, false) + case "Mod": + if !user.Perms.EditGroupSuperMod { + return common.LocalError("You need the EditGroupSuperMod permission to designate this group as a super-mod group.", w, r, user) + } + err = group.ChangeRank(false, true, false) + case "Banned": + err = group.ChangeRank(false, false, true) + case "Guest": + return common.LocalError("You can't designate a group as a guest group.", w, r, user) + case "Member": + err = group.ChangeRank(false, false, false) + default: + return common.LocalError("Invalid group type.", w, r, user) + } + if err != nil { + return common.InternalError(err, w, r) + } + } + + err = group.Update(gname, gtag) + if err != nil { + return common.InternalError(err, w, r) + } + + http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) + return nil +} + +//routePanelGroupsEditPermsSubmit +func GroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user common.User, sgid string) common.RouteError { + _, ferr := common.SimplePanelUserCheck(w, r, &user) + if ferr != nil { + return ferr + } + if !user.Perms.EditGroup { + return common.NoPermissions(w, r, user) + } + + gid, err := strconv.Atoi(sgid) + if err != nil { + return common.LocalError("The Group ID is not a valid integer.", w, r, user) + } + + group, err := common.Groups.Get(gid) + if err == sql.ErrNoRows { + //log.Print("aaaaa monsters o.o") + return common.NotFound(w, r, nil) + } else if err != nil { + return common.InternalError(err, w, r) + } + + if group.IsAdmin && !user.Perms.EditGroupAdmin { + return common.LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) + } + if group.IsMod && !user.Perms.EditGroupSuperMod { + return common.LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) + } + + var pmap = make(map[string]bool) + + if user.Perms.EditGroupLocalPerms { + for _, perm := range common.LocalPermList { + pvalue := r.PostFormValue("group-perm-" + perm) + pmap[perm] = (pvalue == "1") + } + } + + if user.Perms.EditGroupGlobalPerms { + for _, perm := range common.GlobalPermList { + pvalue := r.PostFormValue("group-perm-" + perm) + pmap[perm] = (pvalue == "1") + } + } + + err = group.UpdatePerms(pmap) + if err != nil { + return common.InternalError(err, w, r) + } + + http.Redirect(w, r, "/panel/groups/edit/perms/"+strconv.Itoa(gid), http.StatusSeeOther) + return nil +} + +//routePanelGroupsCreateSubmit +func GroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { + _, ferr := common.SimplePanelUserCheck(w, r, &user) + if ferr != nil { + return ferr + } + if !user.Perms.EditGroup { + return common.NoPermissions(w, r, user) + } + + groupName := r.PostFormValue("group-name") + if groupName == "" { + return common.LocalError("You need a name for this group!", w, r, user) + } + groupTag := r.PostFormValue("group-tag") + + var isAdmin, isMod, isBanned bool + if user.Perms.EditGroupGlobalPerms { + groupType := r.PostFormValue("group-type") + if groupType == "Admin" { + if !user.Perms.EditGroupAdmin { + return common.LocalError("You need the EditGroupAdmin permission to create admin groups", w, r, user) + } + isAdmin = true + isMod = true + } else if groupType == "Mod" { + if !user.Perms.EditGroupSuperMod { + return common.LocalError("You need the EditGroupSuperMod permission to create admin groups", w, r, user) + } + isMod = true + } else if groupType == "Banned" { + isBanned = true + } + } + + gid, err := common.Groups.Create(groupName, groupTag, isAdmin, isMod, isBanned) + if err != nil { + return common.InternalError(err, w, r) + } + http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) + return nil +}