github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/forum_perms.go (about)

     1  package common
     2  
     3  import (
     4  	"database/sql"
     5  	"encoding/json"
     6  
     7  	"github.com/Azareal/Gosora/query_gen"
     8  )
     9  
    10  // ? - Can we avoid duplicating the items in this list in a bunch of places?
    11  
    12  var LocalPermList = []string{
    13  	"ViewTopic",
    14  	"LikeItem",
    15  	"CreateTopic",
    16  	"EditTopic",
    17  	"DeleteTopic",
    18  	"CreateReply",
    19  	"EditReply",
    20  	"DeleteReply",
    21  	"PinTopic",
    22  	"CloseTopic",
    23  	"MoveTopic",
    24  }
    25  
    26  // TODO: Rename this to ForumPermSet?
    27  /* Inherit from group permissions for ones we don't have */
    28  type ForumPerms struct {
    29  	ViewTopic bool
    30  	//ViewOwnTopic bool
    31  	LikeItem    bool
    32  	CreateTopic bool
    33  	EditTopic   bool
    34  	DeleteTopic bool
    35  	CreateReply bool
    36  	//CreateReplyToOwn bool
    37  	EditReply bool
    38  	//EditOwnReply bool
    39  	DeleteReply bool
    40  	PinTopic    bool
    41  	CloseTopic  bool
    42  	//CloseOwnTopic bool
    43  	MoveTopic bool
    44  
    45  	Overrides bool
    46  	ExtData   map[string]bool
    47  }
    48  
    49  func PresetToPermmap(preset string) (out map[string]*ForumPerms) {
    50  	out = make(map[string]*ForumPerms)
    51  	switch preset {
    52  	case "all":
    53  		out["guests"] = ReadForumPerms()
    54  		out["members"] = ReadWriteForumPerms()
    55  		out["staff"] = AllForumPerms()
    56  		out["admins"] = AllForumPerms()
    57  	case "announce":
    58  		out["guests"] = ReadForumPerms()
    59  		out["members"] = ReadReplyForumPerms()
    60  		out["staff"] = AllForumPerms()
    61  		out["admins"] = AllForumPerms()
    62  	case "members":
    63  		out["guests"] = BlankForumPerms()
    64  		out["members"] = ReadWriteForumPerms()
    65  		out["staff"] = AllForumPerms()
    66  		out["admins"] = AllForumPerms()
    67  	case "staff":
    68  		out["guests"] = BlankForumPerms()
    69  		out["members"] = BlankForumPerms()
    70  		out["staff"] = ReadWriteForumPerms()
    71  		out["admins"] = AllForumPerms()
    72  	case "admins":
    73  		out["guests"] = BlankForumPerms()
    74  		out["members"] = BlankForumPerms()
    75  		out["staff"] = BlankForumPerms()
    76  		out["admins"] = AllForumPerms()
    77  	case "archive":
    78  		out["guests"] = ReadForumPerms()
    79  		out["members"] = ReadForumPerms()
    80  		out["staff"] = ReadForumPerms()
    81  		out["admins"] = ReadForumPerms() //CurateForumPerms. Delete / Edit but no create?
    82  	default:
    83  		out["guests"] = BlankForumPerms()
    84  		out["members"] = BlankForumPerms()
    85  		out["staff"] = BlankForumPerms()
    86  		out["admins"] = BlankForumPerms()
    87  	}
    88  	return out
    89  }
    90  
    91  func PermmapToQuery(permmap map[string]*ForumPerms, fid int) error {
    92  	tx, err := qgen.Builder.Begin()
    93  	if err != nil {
    94  		return err
    95  	}
    96  	defer tx.Rollback()
    97  
    98  	deleteForumPermsByForumTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "fid = ?")
    99  	if err != nil {
   100  		return err
   101  	}
   102  	_, err = deleteForumPermsByForumTx.Exec(fid)
   103  	if err != nil {
   104  		return err
   105  	}
   106  
   107  	perms, err := json.Marshal(permmap["admins"])
   108  	if err != nil {
   109  		return err
   110  	}
   111  
   112  	addForumPermsToForumAdminsTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
   113  		qgen.DBInsert{"forums_permissions", "gid,fid,preset,permissions", ""},
   114  		qgen.DBSelect{"users_groups", "gid,?,'',?", "is_admin = 1", "", ""},
   115  	)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	_, err = addForumPermsToForumAdminsTx.Exec(fid, perms)
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	perms, err = json.Marshal(permmap["staff"])
   125  	if err != nil {
   126  		return err
   127  	}
   128  
   129  	addForumPermsToForumStaffTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
   130  		qgen.DBInsert{"forums_permissions", "gid,fid,preset,permissions", ""},
   131  		qgen.DBSelect{"users_groups", "gid,?,'',?", "is_admin = 0 AND is_mod = 1", "", ""},
   132  	)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	_, err = addForumPermsToForumStaffTx.Exec(fid, perms)
   137  	if err != nil {
   138  		return err
   139  	}
   140  
   141  	perms, err = json.Marshal(permmap["members"])
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	addForumPermsToForumMembersTx, err := qgen.Builder.SimpleInsertSelectTx(tx,
   147  		qgen.DBInsert{"forums_permissions", "gid,fid,preset,permissions", ""},
   148  		qgen.DBSelect{"users_groups", "gid,?,'',?", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""},
   149  	)
   150  	if err != nil {
   151  		return err
   152  	}
   153  	_, err = addForumPermsToForumMembersTx.Exec(fid, perms)
   154  	if err != nil {
   155  		return err
   156  	}
   157  
   158  	// TODO: The group ID is probably a variable somewhere. Find it and use it.
   159  	// Group 5 is the Awaiting Activation group
   160  	err = ReplaceForumPermsForGroupTx(tx, 5, map[int]string{fid: ""}, map[int]*ForumPerms{fid: permmap["guests"]})
   161  	if err != nil {
   162  		return err
   163  	}
   164  
   165  	// TODO: Consult a config setting instead of GuestUser?
   166  	err = ReplaceForumPermsForGroupTx(tx, GuestUser.Group, map[int]string{fid: ""}, map[int]*ForumPerms{fid: permmap["guests"]})
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	err = tx.Commit()
   172  	if err != nil {
   173  		return err
   174  	}
   175  	return FPStore.Reload(fid)
   176  	//return TopicList.RebuildPermTree()
   177  }
   178  
   179  // TODO: FPStore.Reload?
   180  func ReplaceForumPermsForGroup(gid int, presetSet map[int]string, permSets map[int]*ForumPerms) error {
   181  	tx, err := qgen.Builder.Begin()
   182  	if err != nil {
   183  		return err
   184  	}
   185  	defer tx.Rollback()
   186  
   187  	err = ReplaceForumPermsForGroupTx(tx, gid, presetSet, permSets)
   188  	if err != nil {
   189  		return err
   190  	}
   191  	return tx.Commit()
   192  	//return TopicList.RebuildPermTree()
   193  }
   194  
   195  func ReplaceForumPermsForGroupTx(tx *sql.Tx, gid int, presetSets map[int]string, permSets map[int]*ForumPerms) error {
   196  	deleteForumPermsForGroupTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "gid = ? AND fid = ?")
   197  	if err != nil {
   198  		return err
   199  	}
   200  
   201  	addForumPermsToGroupTx, err := qgen.Builder.SimpleInsertTx(tx, "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?")
   202  	if err != nil {
   203  		return err
   204  	}
   205  	for fid, permSet := range permSets {
   206  		permstr, err := json.Marshal(permSet)
   207  		if err != nil {
   208  			return err
   209  		}
   210  		_, err = deleteForumPermsForGroupTx.Exec(gid, fid)
   211  		if err != nil {
   212  			return err
   213  		}
   214  		_, err = addForumPermsToGroupTx.Exec(gid, fid, presetSets[fid], string(permstr))
   215  		if err != nil {
   216  			return err
   217  		}
   218  	}
   219  
   220  	return nil
   221  }
   222  
   223  // TODO: Refactor this and write tests for it
   224  // TODO: We really need to improve the thread safety of this
   225  func ForumPermsToGroupForumPreset(fp *ForumPerms) string {
   226  	if !fp.Overrides {
   227  		return "default"
   228  	}
   229  	if !fp.ViewTopic {
   230  		return "no_access"
   231  	}
   232  	canPost := (fp.LikeItem && fp.CreateTopic && fp.CreateReply)
   233  	canModerate := (canPost && fp.EditTopic && fp.DeleteTopic && fp.EditReply && fp.DeleteReply && fp.PinTopic && fp.CloseTopic && fp.MoveTopic)
   234  	if canModerate {
   235  		return "can_moderate"
   236  	}
   237  	if fp.EditTopic || fp.DeleteTopic || fp.EditReply || fp.DeleteReply || fp.PinTopic || fp.CloseTopic || fp.MoveTopic {
   238  		//if !canPost {
   239  		return "custom"
   240  		//}
   241  		//return "quasi_mod"
   242  	}
   243  
   244  	if canPost {
   245  		return "can_post"
   246  	}
   247  	if fp.ViewTopic && !fp.LikeItem && !fp.CreateTopic && !fp.CreateReply {
   248  		return "read_only"
   249  	}
   250  	return "custom"
   251  }
   252  
   253  func GroupForumPresetToForumPerms(preset string) (fperms *ForumPerms, changed bool) {
   254  	switch preset {
   255  	case "read_only":
   256  		return ReadForumPerms(), true
   257  	case "can_post":
   258  		return ReadWriteForumPerms(), true
   259  	case "can_moderate":
   260  		return AllForumPerms(), true
   261  	case "no_access":
   262  		return &ForumPerms{Overrides: true, ExtData: make(map[string]bool)}, true
   263  	case "default":
   264  		return BlankForumPerms(), true
   265  	}
   266  	return fperms, false
   267  }
   268  
   269  func BlankForumPerms() *ForumPerms {
   270  	return &ForumPerms{ViewTopic: false}
   271  }
   272  
   273  func ReadWriteForumPerms() *ForumPerms {
   274  	return &ForumPerms{
   275  		ViewTopic:   true,
   276  		LikeItem:    true,
   277  		CreateTopic: true,
   278  		CreateReply: true,
   279  		Overrides:   true,
   280  		ExtData:     make(map[string]bool),
   281  	}
   282  }
   283  
   284  func ReadReplyForumPerms() *ForumPerms {
   285  	return &ForumPerms{
   286  		ViewTopic:   true,
   287  		LikeItem:    true,
   288  		CreateReply: true,
   289  		Overrides:   true,
   290  		ExtData:     make(map[string]bool),
   291  	}
   292  }
   293  
   294  func ReadForumPerms() *ForumPerms {
   295  	return &ForumPerms{
   296  		ViewTopic: true,
   297  		Overrides: true,
   298  		ExtData:   make(map[string]bool),
   299  	}
   300  }
   301  
   302  // AllForumPerms is a set of forum local permissions with everything set to true
   303  func AllForumPerms() *ForumPerms {
   304  	return &ForumPerms{
   305  		ViewTopic:   true,
   306  		LikeItem:    true,
   307  		CreateTopic: true,
   308  		EditTopic:   true,
   309  		DeleteTopic: true,
   310  		CreateReply: true,
   311  		EditReply:   true,
   312  		DeleteReply: true,
   313  		PinTopic:    true,
   314  		CloseTopic:  true,
   315  		MoveTopic:   true,
   316  
   317  		Overrides: true,
   318  		ExtData:   make(map[string]bool),
   319  	}
   320  }