Package xypriv supports to central manage and control privileges that protect resources from illegal access.
Resources are objects that need to be protected from illegal actions.
Actions are activities which are performed on resources.
Subjects are entities who want to perform actions on resources.
There are some Subjects are considered as the owner of Resources.
The accessible ability of a subject on resource is based on:
- The relation between subject and owner. It defines a privilege number.
The higher the privilege, the more easily the subject can access on the owner's resources.
- The permission set of resource, it contains many elements, each element is a tuple of an owner and an access level.
The higher the access level, the more difficult a subject can access on the owner's resources.
Assuming that:
- The resource has the owner, called
O
. - The resource defines the access level to read is
AC
. - The subject has the privilege over
O
isP
.
The subject can read the resource if P >= AC
.
After you read the following guide, please visit tutorials.
First, you need to define all subjects, resources, contexts, and relations in each context. For example, see tutorials.
Then, give prefered names to the privileges and access levels in each context. Below items are recommended privileges and access levels for the normal context.
Privilege | Relation |
---|---|
10 | Self |
8-9 | Admin |
6-7 | Moderator, Supporter |
2-5 | Familiars |
1 | Anyone |
0 | Bad relation |
Permission | Level |
---|---|
10 | Top secret |
8-9 | Secret |
6-7 | Confidential |
2-5 | Private |
1 | Public |
After you read the all sections, please visit tutorials.
Subject
interface requires only one method called Relation
.
It receives another Subject
as parameter and the context. It expects to return the privilege number of the current Subject
over the parameter Subject
.
The latter parameter helps to find relations depending on the context. The context can be seen as the namespace of relations.
For example, assuming that user A joined in group G, user B is the admin of group G, user C is a friend of user A:
- In the normal context, user B has no relation with user A, user C is the friend of user A.
- In the context of group G, user B is the group admin of user A, user C has no relation with user A.
The context will be determined by the Resource. The normal context should be represented by nil
.
type Subject interface {
Relation(s Subject, ctx any) Privilege
}
For example:
// User implements Subject interface.
type User struct {
id string
}
func (u User) Relation(s Subject, ctx any) xypriv.Privilege {
switch t := s.(type) {
case User:
if u.id == t.id {
return xypriv.Self
}
}
switch c := ctx.(type) {
case nil:
// handle context-dependent privileges.
}
return xypriv.Anyone
}
After you read the all sections, please visit tutorials.
For a resource, you need to define Context
and Owner
methods which returns the context and owner of resource, respectively.
You also need to define Permission
method, it returns the AccessLevel
to perform the action on the resource. The parameter of this method depends on which problem you are solving.
type Resource interface {
Context() any
Owner() Subject
}
type SimpleResource interface {
Resource
Permission(action ...string) AccessLevel
}
type EnhancedResource interface {
Resource
Permission(s Subject, action ...string) AccessLevel
}
For example:
// Avatar implements SimpleResource.
type Avatar struct {
user User
}
func (a Avatar) Context() any {
return nil
}
fuunc (a Avatar) Owner() xypriv.Subject {
return a.user
}
func (a Avatar) Permission(action ...string) xypriv.AccessLevel {
if len(action) != 1 {
return xypriv.NotSupport
}
switch action[0] {
case "update":
return xypriv.LowPrivate
}
return xypriv.NotSupport
}
We also provides a built-in Resource called AbstractResource
. See the 3rd tutorial.
After you read the all sections, please visit tutorials.
var userA = User{name: "A"}
var userB = User{name: "B"}
var avtA = Avatar{user: userA}
xypriv.Check(userA).Perform("update").On(avtA) // nil
xypriv.Check(userB).Perform("update").On(avtA) // XyprivError