member_grouping_options.gno
1.93 Kb · 49 lines
1package commondao
2
3// MemberGroupingOption configures member groupings.
4type MemberGroupingOption func(MemberGrouping)
5
6// SECURITY XXX: UseStorageFactory captures a caller-supplied factory
7// that returns the MemberStorage used to track who is a DAO member.
8// A malicious factory can return a MemberStorage impl that lies about
9// membership — always-true (everyone is a member, votes pass trivially)
10// or always-false (legitimate members are locked out). This isn't a
11// cur-leak; it's a behavior-substitution risk on the data layer the
12// DAO's voting and proposal logic depends on.
13// Fix: document that the factory must come from trusted code (a
14// hardcoded constructor in the DAO realm itself), and never accept
15// a UseStorageFactory option from external-realm input. Or restrict
16// to a canonical-impl allowlist (type-switch on known MemberStorage
17// types) in commondao itself.
18//
19// UseStorageFactory assigns a custom member storage creation function to the grouping.
20// Creation function is called each time a member group is added, with the name of the
21// group as the only argument, to create a storage where the new group stores its members.
22func UseStorageFactory(fn func(group string) MemberStorage) MemberGroupingOption {
23 if fn == nil {
24 panic("storage factory function must not be nil")
25 }
26
27 return func(g MemberGrouping) {
28 grouping, ok := g.(*memberGrouping)
29 if !ok {
30 panic("storage factory not supported by member grouping")
31 }
32
33 grouping.createStorage = fn
34 }
35}
36
37// WithGroups creates multiple members groups.
38// To use a custom member storage factory to create the groups make sure that this option
39// comes after the `UseStorageFactory()` option, otherwise groups are created using the
40// default factory which is `commondao.NewMemberStorage()`.
41func WithGroups(names ...string) MemberGroupingOption {
42 return func(g MemberGrouping) {
43 for _, name := range names {
44 if _, err := g.Add(name); err != nil {
45 panic(err)
46 }
47 }
48 }
49}