-
Notifications
You must be signed in to change notification settings - Fork 0
/
account.go
102 lines (88 loc) · 1.94 KB
/
account.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package rs
import (
"errors"
"fmt"
"sync"
"github.com/gregoryv/nugo"
)
var (
Anonymous = NewAccount("anonymous", 0)
Root = NewAccount("root", 1)
)
// NewAccount returns a new account with the given uid as both uid and
// group id.
func NewAccount(Name string, uid int) *Account {
return &Account{
Name: Name,
UID: uid,
Groups: []int{uid},
}
}
type Account struct {
Name string
UID int
mu sync.Mutex
Groups []int
}
// gid returns the first group id of the account
func (me *Account) gid() int { return me.Groups[0] }
// todo hide as command
func (me *Account) joinGroup(gid int) {
for _, id := range me.Groups {
if id == gid {
return
}
}
me.mu.Lock()
me.Groups = append(me.Groups, gid)
me.mu.Unlock()
}
// todo hide as command
func (me *Account) leaveGroup(gid int) {
for i, id := range me.Groups {
if id == gid {
me.mu.Lock()
me.Groups = append(me.Groups[:i], me.Groups[i+1:]...)
me.mu.Unlock()
return
}
}
}
// Use returns a Syscall struct for accessing the system.
func (me *Account) Use(sys *System) *Syscall {
return &Syscall{
sys: sys,
acc: me,
auditer: sys.auditer,
}
}
// owns returns true if the account uid mathes the given id
func (me *Account) owns(n *nugo.Node) bool {
return me.UID == n.UID
}
// permitted returns error if account does not have operation
// permission to the given seal.
func (me *Account) permitted(op operation, s *nugo.Node) error {
if me.UID == Root.UID {
return nil
}
n, u, g, o := op.Modes()
switch {
case me.UID == 0 && (s.Mode&n == n): // anonymous
case me.UID == s.UID && (s.Mode&u == u): // owner
case me.member(s.GID) && (s.Mode&g == g): // group
case me.UID > 0 && s.Mode&o == o: // other
default:
return fmt.Errorf("%v %v denied", s, op)
}
return nil
}
var ErrPermissionDenied = errors.New("permission denied")
func (me *Account) member(gid int) bool {
for _, id := range me.Groups {
if id == gid {
return true
}
}
return false
}