Added the Group Permissions Editor.

Fixed a permission check.
This commit is contained in:
Azareal 2017-03-23 12:13:50 +00:00
parent c14a1e2100
commit bf19b66a94
9 changed files with 399 additions and 5 deletions

View File

@ -260,7 +260,9 @@ func main(){
router.HandleFunc("/panel/users/edit/submit/", route_panel_users_edit_submit)
router.HandleFunc("/panel/groups/", route_panel_groups)
router.HandleFunc("/panel/groups/edit/", route_panel_groups_edit)
router.HandleFunc("/panel/groups/edit/perms/", route_panel_groups_edit_perms)
router.HandleFunc("/panel/groups/edit/submit/", route_panel_groups_edit_submit)
router.HandleFunc("/panel/groups/edit/perms/submit/", route_panel_groups_edit_perms_submit)
router.HandleFunc("/api/", route_api)
//router.HandleFunc("/exit/", route_exit)

View File

@ -6,6 +6,7 @@ import "strings"
import "strconv"
import "net/http"
import "html"
import "encoding/json"
import "database/sql"
import _ "github.com/go-sql-driver/mysql"
@ -1457,7 +1458,7 @@ func route_panel_groups_edit(w http.ResponseWriter, r *http.Request){
return
}
if group.Is_Mod && !user.Perms.EditGroupSuperMod {
LocalError("You need the EditGroupSuperMod permission to edit an super-mod group.",w,r,user)
LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user)
return
}
@ -1486,6 +1487,78 @@ func route_panel_groups_edit(w http.ResponseWriter, r *http.Request){
}
}
func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request){
user, noticeList, ok := SessionCheck(w,r)
if !ok {
return
}
if !user.Is_Super_Mod || !user.Perms.EditGroup {
NoPermissions(w,r,user)
return
}
gid, err := strconv.Atoi(r.URL.Path[len("/panel/groups/edit/perms/"):])
if err != nil {
LocalError("The Group ID is not a valid integer.",w,r,user)
return
}
if !group_exists(gid) {
//fmt.Println("aaaaa monsters")
NotFound(w,r)
return
}
group := groups[gid]
if group.Is_Admin && !user.Perms.EditGroupAdmin {
LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user)
return
}
if group.Is_Mod && !user.Perms.EditGroupSuperMod {
LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user)
return
}
var localPerms []NameLangToggle
localPerms = append(localPerms, NameLangToggle{"ViewTopic",GetLocalPermPhrase("ViewTopic"),group.Perms.ViewTopic})
localPerms = append(localPerms, NameLangToggle{"LikeItem",GetLocalPermPhrase("LikeItem"),group.Perms.LikeItem})
localPerms = append(localPerms, NameLangToggle{"CreateTopic",GetLocalPermPhrase("CreateTopic"),group.Perms.CreateTopic})
//<--
localPerms = append(localPerms, NameLangToggle{"EditTopic",GetLocalPermPhrase("EditTopic"),group.Perms.EditTopic})
localPerms = append(localPerms, NameLangToggle{"DeleteTopic",GetLocalPermPhrase("DeleteTopic"),group.Perms.DeleteTopic})
localPerms = append(localPerms, NameLangToggle{"CreateReply",GetLocalPermPhrase("CreateReply"),group.Perms.CreateReply})
localPerms = append(localPerms, NameLangToggle{"EditReply",GetLocalPermPhrase("EditReply"),group.Perms.EditReply})
localPerms = append(localPerms, NameLangToggle{"DeleteReply",GetLocalPermPhrase("DeleteReply"),group.Perms.DeleteReply})
localPerms = append(localPerms, NameLangToggle{"PinTopic",GetLocalPermPhrase("PinTopic"),group.Perms.PinTopic})
localPerms = append(localPerms, NameLangToggle{"CloseTopic",GetLocalPermPhrase("CloseTopic"),group.Perms.CloseTopic})
var globalPerms []NameLangToggle
globalPerms = append(globalPerms, NameLangToggle{"BanUsers",GetGlobalPermPhrase("BanUsers"),group.Perms.BanUsers})
globalPerms = append(globalPerms, NameLangToggle{"ActivateUsers",GetGlobalPermPhrase("ActivateUsers"),group.Perms.ActivateUsers})
globalPerms = append(globalPerms, NameLangToggle{"EditUser",GetGlobalPermPhrase("EditUser"),group.Perms.EditUser})
globalPerms = append(globalPerms, NameLangToggle{"EditUserEmail",GetGlobalPermPhrase("EditUserEmail"),group.Perms.EditUserEmail})
globalPerms = append(globalPerms, NameLangToggle{"EditUserPassword",GetGlobalPermPhrase("EditUserPassword"),group.Perms.EditUserPassword})
globalPerms = append(globalPerms, NameLangToggle{"EditUserGroup",GetGlobalPermPhrase("EditUserGroup"),group.Perms.EditUserGroup})
globalPerms = append(globalPerms, NameLangToggle{"EditUserGroupSuperMod",GetGlobalPermPhrase("EditUserGroupSuperMod"),group.Perms.EditUserGroupSuperMod})
globalPerms = append(globalPerms, NameLangToggle{"EditUserGroupAdmin",GetGlobalPermPhrase("EditUserGroupAdmin"),group.Perms.EditUserGroupAdmin})
globalPerms = append(globalPerms, NameLangToggle{"EditGroup",GetGlobalPermPhrase("EditGroup"),group.Perms.EditGroup})
globalPerms = append(globalPerms, NameLangToggle{"EditGroupLocalPerms",GetGlobalPermPhrase("EditGroupLocalPerms"),group.Perms.EditGroupLocalPerms})
globalPerms = append(globalPerms, NameLangToggle{"EditGroupGlobalPerms",GetGlobalPermPhrase("EditGroupGlobalPerms"),group.Perms.EditGroupGlobalPerms})
globalPerms = append(globalPerms, NameLangToggle{"EditGroupSuperMod",GetGlobalPermPhrase("EditGroupSuperMod"),group.Perms.EditGroupSuperMod})
globalPerms = append(globalPerms, NameLangToggle{"EditGroupAdmin",GetGlobalPermPhrase("EditGroupAdmin"),group.Perms.EditGroupAdmin})
globalPerms = append(globalPerms, NameLangToggle{"ManageForums",GetGlobalPermPhrase("ManageForums"),group.Perms.ManageForums})
globalPerms = append(globalPerms, NameLangToggle{"EditSettings",GetGlobalPermPhrase("EditSettings"),group.Perms.EditSettings})
globalPerms = append(globalPerms, NameLangToggle{"ManageThemes",GetGlobalPermPhrase("ManageThemes"),group.Perms.ManageThemes})
globalPerms = append(globalPerms, NameLangToggle{"ManagePlugins",GetGlobalPermPhrase("ManagePlugins"),group.Perms.ManagePlugins})
globalPerms = append(globalPerms, NameLangToggle{"ViewIPs",GetGlobalPermPhrase("ViewIPs"),group.Perms.ViewIPs})
pi := EditGroupPermsPage{"Group Editor",user,noticeList,group.ID,group.Name,localPerms,globalPerms,nil}
err = templates.ExecuteTemplate(w,"panel-group-edit-perms.html",pi)
if err != nil {
InternalError(err,w,r)
}
}
func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request){
user, ok := SimpleSessionCheck(w,r)
if !ok {
@ -1518,7 +1591,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request){
return
}
if group.Is_Mod && !user.Perms.EditGroupSuperMod {
LocalError("You need the EditGroupSuperMod permission to edit an super-mod group.",w,r,user)
LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user)
return
}
@ -1568,7 +1641,7 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request){
groups[gid].Is_Banned = false
case "Mod":
if !user.Perms.EditGroupSuperMod {
LocalError("You need the EditGroupSuperMod permission to designate this group as an admin group.",w,r,user)
LocalError("You need the EditGroupSuperMod permission to designate this group as a super-mod group.",w,r,user)
return
}
@ -1618,6 +1691,90 @@ func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request){
http.Redirect(w,r,"/panel/groups/edit/" + strconv.Itoa(gid),http.StatusSeeOther)
}
func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request){
user, ok := SimpleSessionCheck(w,r)
if !ok {
return
}
if !user.Is_Super_Mod || !user.Perms.EditGroup {
NoPermissions(w,r,user)
return
}
if r.FormValue("session") != user.Session {
SecurityError(w,r,user)
return
}
gid, err := strconv.Atoi(r.URL.Path[len("/panel/groups/edit/perms/submit/"):])
if err != nil {
LocalError("The Group ID is not a valid integer.",w,r,user)
return
}
if !group_exists(gid) {
//fmt.Println("aaaaa monsters")
NotFound(w,r)
return
}
group := groups[gid]
if group.Is_Admin && !user.Perms.EditGroupAdmin {
LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user)
return
}
if group.Is_Mod && !user.Perms.EditGroupSuperMod {
LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user)
return
}
//var lpmap map[string]bool = make(map[string]bool)
var pmap map[string]bool = make(map[string]bool)
if user.Perms.EditGroupLocalPerms {
pplist := LocalPermList
for _, perm := range pplist {
pvalue := r.PostFormValue("group-perm-" + perm)
if pvalue == "1" {
pmap[perm] = true
} else {
pmap[perm] = false
}
}
}
//var gpmap map[string]bool = make(map[string]bool)
if user.Perms.EditGroupGlobalPerms {
gplist := GlobalPermList
for _, perm := range gplist {
pvalue := r.PostFormValue("group-perm-" + perm)
if pvalue == "1" {
pmap[perm] = true
} else {
pmap[perm] = false
}
}
}
pjson, err := json.Marshal(pmap)
if err != nil {
LocalError("Unable to marshal the data",w,r,user)
return
}
_, err = update_group_perms_stmt.Exec(pjson,gid)
if err != nil {
InternalError(err,w,r)
return
}
err = rebuild_group_permissions(gid)
if err != nil {
InternalError(err,w,r)
return
}
http.Redirect(w,r,"/panel/groups/edit/perms/" + strconv.Itoa(gid),http.StatusSeeOther)
}
func route_panel_themes(w http.ResponseWriter, r *http.Request){
user, noticeList, ok := SessionCheck(w,r)
if !ok {

View File

@ -83,6 +83,7 @@ var update_setting_stmt *sql.Stmt
var add_plugin_stmt *sql.Stmt
var update_plugin_stmt *sql.Stmt
var update_user_stmt *sql.Stmt
var update_group_perms_stmt *sql.Stmt
var update_group_rank_stmt *sql.Stmt
var update_group_stmt *sql.Stmt
var add_theme_stmt *sql.Stmt
@ -554,6 +555,12 @@ func init_database(err error) {
log.Fatal(err)
}
log.Print("Preparing update_group_rank statement.")
update_group_perms_stmt, err = db.Prepare("update `users_groups` set `permissions` = ? where `gid` = ?")
if err != nil {
log.Fatal(err)
}
log.Print("Preparing update_group_rank statement.")
update_group_rank_stmt, err = db.Prepare("update `users_groups` set `is_admin` = ?, `is_mod` = ?, `is_banned` = ? where `gid` = ?")
if err != nil {

View File

@ -99,6 +99,31 @@ type EditGroupPage struct
ExtData interface{}
}
type NameLangPair struct
{
Name string
LangStr string
}
type NameLangToggle struct
{
Name string
LangStr string
Toggle bool
}
type EditGroupPermsPage struct
{
Title string
CurrentUser User
NoticeList []string
ID int
Name string
LocalPerms []NameLangToggle
GlobalPerms []NameLangToggle
ExtData interface{}
}
type PageSimple struct
{
Title string

View File

@ -14,6 +14,46 @@ var ReadWriteForumPerms ForumPerms
var AllPerms Perms
var AllForumPerms ForumPerms
var LocalPermList []string = []string{
"ViewTopic",
"LikeItem",
"CreateTopic",
"EditTopic",
"DeleteTopic",
"CreateReply",
"EditReply",
"DeleteReply",
"PinTopic",
"CloseTopic",
}
var GlobalPermList []string = []string{
"BanUsers",
"ActivateUsers",
"EditUser",
"EditUserEmail",
"EditUserPassword",
"EditUserGroup",
"EditUserGroupSuperMod",
"EditUserGroupAdmin",
"EditGroup",
"EditGroupLocalPerms",
"EditGroupGlobalPerms",
"EditGroupSuperMod",
"EditGroupAdmin",
"ManageForums",
"EditSettings",
"ManageThemes",
"ManagePlugins",
"ViewIPs",
}
/*type PermMeta struct
{
Name string
Type int // 0: global, 1: local
}*/
// Permission Structure: ActionComponent[Subcomponent]Flag
type Perms struct
{
@ -350,3 +390,21 @@ func preset_to_emoji(preset string) string {
}
return ""
}
func rebuild_group_permissions(gid int) error {
var permstr []byte
log.Print("Reloading a group")
err := db.QueryRow("select permissions from users_groups where gid = ?",gid).Scan(&permstr)
if err != nil {
return err
}
tmp_perms := Perms{ExtData: make(map[string]bool)}
err = json.Unmarshal(permstr, &tmp_perms)
if err != nil {
return err
}
groups[gid].Perms = tmp_perms
return nil
}

82
phrases.go Normal file
View File

@ -0,0 +1,82 @@
package main
import "sync"
// I wish we had constant maps x.x
var phrase_mutex sync.RWMutex
var perm_phrase_mutex sync.RWMutex
var phrases map[string]string
var global_perm_phrases map[string]string = map[string]string{
"BanUsers": "Can ban users",
"ActivateUsers": "Can activate users",
"EditUser": "Can edit users",
"EditUserEmail": "Can change a user's email",
"EditUserPassword": "Can change a user's password",
"EditUserGroup": "Can change a user's group",
"EditUserGroupSuperMod": "Can edit super-mods",
"EditUserGroupAdmin": "Can edit admins",
"EditGroup": "Can edit groups",
"EditGroupLocalPerms": "Can edit a group's minor perms",
"EditGroupGlobalPerms": "Can edit a group's global perms",
"EditGroupSuperMod": "Can edit super-mod groups",
"EditGroupAdmin": "Can edit admin groups",
"ManageForums": "Can manage forums",
"EditSettings": "Can edit settings",
"ManageThemes": "Can manage themes",
"ManagePlugins": "Can manage plugins",
"ViewIPs": "Can view IP addresses",
}
var local_perm_phrases map[string]string = map[string]string{
"ViewTopic": "Can view topics",
"LikeItem": "Can like items",
"CreateTopic": "Can create topics",
"EditTopic": "Can edit topics",
"DeleteTopic": "Can delete topics",
"CreateReply": "Can create replies",
"EditReply": "Can edit replies",
"DeleteReply": "Can delete replies",
"PinTopic": "Can pin topics",
"CloseTopic": "Can lock topics",
}
// We might not need to use a mutex for this, we shouldn't need to change the phrases after start-up, and when we do we could overwrite the entire map
func GetPhrase(name string) (string,bool) {
phrase_mutex.RLock()
defer perm_phrase_mutex.RUnlock()
res, ok := phrases[name]
return res, ok
}
func GetPhraseUnsafe(name string) (string,bool) {
res, ok := phrases[name]
return res, ok
}
func GetGlobalPermPhrase(name string) string {
perm_phrase_mutex.RLock()
defer perm_phrase_mutex.RUnlock()
res, ok := global_perm_phrases[name]
if !ok {
return "{name}"
}
return res
}
func GetLocalPermPhrase(name string) string {
perm_phrase_mutex.RLock()
defer perm_phrase_mutex.RUnlock()
res, ok := local_perm_phrases[name]
if !ok {
return "{name}"
}
return res
}
func AddPhrase() {
}
func DeletePhrase() {
}

View File

@ -0,0 +1,63 @@
{{template "header.html" . }}
<div class="colstack_left">
<div class="colstack_item colstack_head">
<div class="rowitem rowhead"><a href="/panel/groups/edit/{{.ID}}">Group Editor</a></div>
</div>
<div class="colstack_item">
<div class="rowitem passive"><a href="/panel/groups/edit/{{.ID}}">General</a></div>
<div class="rowitem passive"><a>Promotions</a></div>
<div class="rowitem passive"><a href="/panel/groups/edit/perms/{{.ID}}">Permissions</a></div>
</div>
{{template "panel-inner-menu.html" . }}
</div>
<div class="colstack_right">
<div class="colstack_item colstack_head">
<div class="rowitem rowhead"><a>{{.Name}} Group</a></div>
</div>
<form action="/panel/groups/edit/perms/submit/{{.ID}}?session={{.CurrentUser.Session}}" method="post">
<div class="colstack_item">
{{if .CurrentUser.Perms.EditGroupLocalPerms}}
{{range .LocalPerms}}
<div class="formrow">
<div class="formitem">
<a>{{.LangStr}}</a>
<div style="float: right;">
<select name="group-perm-{{.Name}}">
<option{{if .Toggle}} selected{{end}} value=1>Yes</option>
<option{{if not .Toggle}} selected{{end}} value=0>No</option>
</select>
</div>
</div>
</div>
{{end}}
{{end}}
<div class="formrow">
<div class="formitem"><button name="panel-button" class="formbutton">Update Group</button></div>
</div>
</div>
<div class="colstack_item colstack_head">
<div class="rowitem rowhead"><a>Extended Permissions</a></div>
</div>
<div class="colstack_item">
{{if .CurrentUser.Perms.EditGroupGlobalPerms}}
{{range .GlobalPerms}}
<div class="formrow">
<div class="formitem">
<a>{{.LangStr}}</a>
<div style="float: right;">
<select name="group-perm-{{.Name}}">
<option{{if .Toggle}} selected{{end}} value=1>Yes</option>
<option{{if not .Toggle}} selected{{end}} value=0>No</option>
</select>
</div>
</div>
</div>
{{end}}
{{end}}
<div class="formrow">
<div class="formitem"><button name="panel-button" class="formbutton">Update Group</button></div>
</div>
</div>
</form>
</div>
{{template "footer.html" . }}

View File

@ -6,7 +6,7 @@
<div class="colstack_item">
<div class="rowitem passive"><a href="/panel/groups/edit/{{.ID}}">General</a></div>
<div class="rowitem passive"><a>Promotions</a></div>
<div class="rowitem passive"><a>Permissions</a></div>
<div class="rowitem passive"><a href="/panel/groups/edit/perms/{{.ID}}">Permissions</a></div>
</div>
{{template "panel-inner-menu.html" . }}
</div>
@ -20,7 +20,7 @@
<div class="formitem"><a>Name</a></div>
<div class="formitem"><input name="group-name" type="text" value="{{.Name}}" placeholder="General Forum" /></div>
</div>
{{if .CurrentUser.Perms.EditUserGroup}}
{{if .CurrentUser.Perms.EditGroup}}
<div class="formrow">
<div class="formitem"><a>Type</a></div>
<div class="formitem">

0
todo
View File