fix bug with user perms not being applied independantly
This commit is contained in:
parent
2b52b21176
commit
b7e0086816
|
@ -485,7 +485,9 @@ func handleNAMES(c *Client, e Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't append modes, overwrite them.
|
// Don't append modes, overwrite them.
|
||||||
user.Perms.set(modes, false)
|
perms, _ := user.Perms.Lookup(channel.Name)
|
||||||
|
perms.set(modes, false)
|
||||||
|
user.Perms.set(channel.Name, perms)
|
||||||
}
|
}
|
||||||
c.state.Unlock()
|
c.state.Unlock()
|
||||||
c.state.notify(c, UPDATE_STATE)
|
c.state.notify(c, UPDATE_STATE)
|
||||||
|
|
87
modes.go
87
modes.go
|
@ -4,7 +4,11 @@
|
||||||
|
|
||||||
package girc
|
package girc
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
// CMode represents a single step of a given mode change.
|
// CMode represents a single step of a given mode change.
|
||||||
type CMode struct {
|
type CMode struct {
|
||||||
|
@ -353,7 +357,9 @@ func handleMODE(c *Client, e Event) {
|
||||||
|
|
||||||
user := c.state.lookupUser(modes[i].args)
|
user := c.state.lookupUser(modes[i].args)
|
||||||
if user != nil {
|
if user != nil {
|
||||||
user.Perms.setFromMode(modes[i])
|
perms, _ := user.Perms.Lookup(channel.Name)
|
||||||
|
perms.setFromMode(modes[i])
|
||||||
|
user.Perms.set(channel.Name, perms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,30 +388,83 @@ func (s *state) userPrefixes() string {
|
||||||
return DefaultPrefixes
|
return DefaultPrefixes
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserPerms contains all channel-based user permissions. The minimum op, and
|
// UserPerms contains all of the permissions for each channel the user is
|
||||||
|
// in.
|
||||||
|
type UserPerms struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
channels map[string]Perms
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy returns a deep copy of the channel permissions.
|
||||||
|
func (p *UserPerms) Copy() (perms *UserPerms) {
|
||||||
|
np := &UserPerms{
|
||||||
|
channels: make(map[string]Perms),
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mu.RLock()
|
||||||
|
for key := range p.channels {
|
||||||
|
np.channels[key] = p.channels[key]
|
||||||
|
}
|
||||||
|
p.mu.RUnlock()
|
||||||
|
|
||||||
|
return np
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler.
|
||||||
|
func (p *UserPerms) MarshalJSON() ([]byte, error) {
|
||||||
|
p.mu.Lock()
|
||||||
|
out, err := json.Marshal(&p.channels)
|
||||||
|
p.mu.Unlock()
|
||||||
|
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup looks up the users permissions for a given channel. ok is false
|
||||||
|
// if the user is not in the given channel.
|
||||||
|
func (p *UserPerms) Lookup(channel string) (perms Perms, ok bool) {
|
||||||
|
p.mu.RLock()
|
||||||
|
perms, ok = p.channels[ToRFC1459(channel)]
|
||||||
|
p.mu.RUnlock()
|
||||||
|
|
||||||
|
return perms, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *UserPerms) set(channel string, perms Perms) {
|
||||||
|
p.mu.Lock()
|
||||||
|
p.channels[ToRFC1459(channel)] = perms
|
||||||
|
p.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *UserPerms) remove(channel string) {
|
||||||
|
p.mu.Lock()
|
||||||
|
delete(p.channels, ToRFC1459(channel))
|
||||||
|
p.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perms contains all channel-based user permissions. The minimum op, and
|
||||||
// voice should be supported on all networks. This also supports non-rfc
|
// voice should be supported on all networks. This also supports non-rfc
|
||||||
// Owner, Admin, and HalfOp, if the network has support for it.
|
// Owner, Admin, and HalfOp, if the network has support for it.
|
||||||
type UserPerms struct {
|
type Perms struct {
|
||||||
// Owner (non-rfc) indicates that the user has full permissions to the
|
// Owner (non-rfc) indicates that the user has full permissions to the
|
||||||
// channel. More than one user can have owner permission.
|
// channel. More than one user can have owner permission.
|
||||||
Owner bool
|
Owner bool `json:"owner"`
|
||||||
// Admin (non-rfc) is commonly given to users that are trusted enough
|
// Admin (non-rfc) is commonly given to users that are trusted enough
|
||||||
// to manage channel permissions, as well as higher level service settings.
|
// to manage channel permissions, as well as higher level service settings.
|
||||||
Admin bool
|
Admin bool `json:"admin"`
|
||||||
// Op is commonly given to trusted users who can manage a given channel
|
// Op is commonly given to trusted users who can manage a given channel
|
||||||
// by kicking, and banning users.
|
// by kicking, and banning users.
|
||||||
Op bool
|
Op bool `json:"op"`
|
||||||
// HalfOp (non-rfc) is commonly used to give users permissions like the
|
// HalfOp (non-rfc) is commonly used to give users permissions like the
|
||||||
// ability to kick, without giving them greater abilities to ban all users.
|
// ability to kick, without giving them greater abilities to ban all users.
|
||||||
HalfOp bool
|
HalfOp bool `json:"half_op"`
|
||||||
// Voice indicates the user has voice permissions, commonly given to known
|
// Voice indicates the user has voice permissions, commonly given to known
|
||||||
// users, with very light trust, or to indicate a user is active.
|
// users, with very light trust, or to indicate a user is active.
|
||||||
Voice bool
|
Voice bool `json:"voice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAdmin indicates that the user has banning abilities, and are likely a
|
// IsAdmin indicates that the user has banning abilities, and are likely a
|
||||||
// very trustable user (e.g. op+).
|
// very trustable user (e.g. op+).
|
||||||
func (m UserPerms) IsAdmin() bool {
|
func (m Perms) IsAdmin() bool {
|
||||||
if m.Owner || m.Admin || m.Op {
|
if m.Owner || m.Admin || m.Op {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -415,7 +474,7 @@ func (m UserPerms) IsAdmin() bool {
|
||||||
|
|
||||||
// IsTrusted indicates that the user at least has modes set upon them, higher
|
// IsTrusted indicates that the user at least has modes set upon them, higher
|
||||||
// than a regular joining user.
|
// than a regular joining user.
|
||||||
func (m UserPerms) IsTrusted() bool {
|
func (m Perms) IsTrusted() bool {
|
||||||
if m.IsAdmin() || m.HalfOp || m.Voice {
|
if m.IsAdmin() || m.HalfOp || m.Voice {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -424,7 +483,7 @@ func (m UserPerms) IsTrusted() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset resets the modes of a user.
|
// reset resets the modes of a user.
|
||||||
func (m *UserPerms) reset() {
|
func (m *Perms) reset() {
|
||||||
m.Owner = false
|
m.Owner = false
|
||||||
m.Admin = false
|
m.Admin = false
|
||||||
m.Op = false
|
m.Op = false
|
||||||
|
@ -434,7 +493,7 @@ func (m *UserPerms) reset() {
|
||||||
|
|
||||||
// set translates raw prefix characters into proper permissions. Only
|
// set translates raw prefix characters into proper permissions. Only
|
||||||
// use this function when you have a session lock.
|
// use this function when you have a session lock.
|
||||||
func (m *UserPerms) set(prefix string, append bool) {
|
func (m *Perms) set(prefix string, append bool) {
|
||||||
if !append {
|
if !append {
|
||||||
m.reset()
|
m.reset()
|
||||||
}
|
}
|
||||||
|
@ -457,7 +516,7 @@ func (m *UserPerms) set(prefix string, append bool) {
|
||||||
|
|
||||||
// setFromMode sets user-permissions based on channel user mode chars. E.g.
|
// setFromMode sets user-permissions based on channel user mode chars. E.g.
|
||||||
// "o" being oper, "v" being voice, etc.
|
// "o" being oper, "v" being voice, etc.
|
||||||
func (m *UserPerms) setFromMode(mode CMode) {
|
func (m *Perms) setFromMode(mode CMode) {
|
||||||
switch string(mode.name) {
|
switch string(mode.name) {
|
||||||
case ModeOwner:
|
case ModeOwner:
|
||||||
m.Owner = mode.add
|
m.Owner = mode.add
|
||||||
|
|
10
state.go
10
state.go
|
@ -83,9 +83,7 @@ type User struct {
|
||||||
|
|
||||||
// Perms are the user permissions applied to this user that affect the given
|
// Perms are the user permissions applied to this user that affect the given
|
||||||
// channel. This supports non-rfc style modes like Admin, Owner, and HalfOp.
|
// channel. This supports non-rfc style modes like Admin, Owner, and HalfOp.
|
||||||
// If you want to easily check if a user has permissions equal or greater
|
Perms *UserPerms
|
||||||
// than OP, use Perms.IsAdmin().
|
|
||||||
Perms UserPerms
|
|
||||||
|
|
||||||
// Extras are things added on by additional tracking methods, which may
|
// Extras are things added on by additional tracking methods, which may
|
||||||
// or may not work on the IRC server in mention.
|
// or may not work on the IRC server in mention.
|
||||||
|
@ -113,6 +111,7 @@ func (u *User) Copy() *User {
|
||||||
nu := &User{}
|
nu := &User{}
|
||||||
*nu = *u
|
*nu = *u
|
||||||
|
|
||||||
|
nu.Perms = u.Perms.Copy()
|
||||||
_ = copy(nu.Channels, u.Channels)
|
_ = copy(nu.Channels, u.Channels)
|
||||||
|
|
||||||
return nu
|
return nu
|
||||||
|
@ -122,6 +121,8 @@ func (u *User) Copy() *User {
|
||||||
func (u *User) addChannel(name string) {
|
func (u *User) addChannel(name string) {
|
||||||
u.Channels = append(u.Channels, ToRFC1459(name))
|
u.Channels = append(u.Channels, ToRFC1459(name))
|
||||||
sort.StringsAreSorted(u.Channels)
|
sort.StringsAreSorted(u.Channels)
|
||||||
|
|
||||||
|
u.Perms.set(name, Perms{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteChannel removes an existing channel from the users channel list.
|
// deleteChannel removes an existing channel from the users channel list.
|
||||||
|
@ -139,6 +140,8 @@ func (u *User) deleteChannel(name string) {
|
||||||
if j != -1 {
|
if j != -1 {
|
||||||
u.Channels = append(u.Channels[:j], u.Channels[j+1:]...)
|
u.Channels = append(u.Channels[:j], u.Channels[j+1:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u.Perms.remove(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InChannel checks to see if a user is in the given channel.
|
// InChannel checks to see if a user is in the given channel.
|
||||||
|
@ -312,6 +315,7 @@ func (s *state) createUser(nick string) (ok bool) {
|
||||||
Nick: nick,
|
Nick: nick,
|
||||||
FirstSeen: time.Now(),
|
FirstSeen: time.Now(),
|
||||||
LastActive: time.Now(),
|
LastActive: time.Now(),
|
||||||
|
Perms: &UserPerms{channels: make(map[string]Perms)},
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in New Issue