This commit is contained in:
@@ -11,6 +11,8 @@ func AllPermissions() map[string]string {
|
||||
"channel.add": "Can add channels",
|
||||
"channel.edit": "Can edit channels",
|
||||
"channel.remove": "Can remove channels",
|
||||
"comment.edit": "Can edit non-owned comments",
|
||||
"comment.remove": "Can remove non-owned comments",
|
||||
"log.add": "Can add logs",
|
||||
"log.edit": "Can edit logs",
|
||||
"log.remove": "Can remove logs",
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// CheckPermission does some magic.
|
||||
func CheckPermission(ctx context.Context, op string, obj interface{}) error {
|
||||
token := TokenFromContext(ctx)
|
||||
if token == nil {
|
||||
return ErrUnauthenticated
|
||||
}
|
||||
|
||||
if reflect.TypeOf(obj).Kind() != reflect.Ptr {
|
||||
return CheckPermission(ctx, op, &obj)
|
||||
}
|
||||
|
||||
var authorized = false
|
||||
|
||||
switch v := obj.(type) {
|
||||
case *models.Channel:
|
||||
authorized = token.Permitted("channel." + op)
|
||||
case *models.Character:
|
||||
authorized = token.PermittedUser(v.Author, "member", "character."+op)
|
||||
case *models.Chapter:
|
||||
authorized = token.PermittedUser(v.Author, "member", "chapter."+op)
|
||||
case *models.Comment:
|
||||
if op == "add" && v.Author != token.UserID {
|
||||
return ErrInvalidOperation
|
||||
}
|
||||
|
||||
authorized = token.PermittedUser(v.Author, "member", "comment."+op)
|
||||
case *models.File:
|
||||
authorized = token.PermittedUser(v.Author, "member", "file."+op)
|
||||
case *models.Log:
|
||||
authorized = token.Permitted("log." + op)
|
||||
case *models.Post:
|
||||
authorized = token.Permitted("post." + op)
|
||||
case *models.Story:
|
||||
authorized = token.PermittedUser(v.Author, "member", "story."+op)
|
||||
case *models.User:
|
||||
authorized = token.Permitted("user." + op)
|
||||
}
|
||||
|
||||
if !authorized {
|
||||
return ErrUnauthorized
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -36,6 +36,15 @@ var ErrWrongPermissions = errors.New("User does not have these permissions")
|
||||
// ErrDeletedUser is returned by CheckToken if the key can represent this user, but the user doesn't exist.
|
||||
var ErrDeletedUser = errors.New("User was not found")
|
||||
|
||||
// ErrUnauthenticated is returned when the user is not authenticated
|
||||
var ErrUnauthenticated = errors.New("You are not authenticated")
|
||||
|
||||
// ErrUnauthorized is returned when the user doesn't have access to this resource
|
||||
var ErrUnauthorized = errors.New("You are not authorized to perform this action")
|
||||
|
||||
// ErrInvalidOperation is returned for operations that should never be allowed
|
||||
var ErrInvalidOperation = errors.New("No permission exists for this operation")
|
||||
|
||||
// TokenFromContext gets the token from context.
|
||||
func TokenFromContext(ctx context.Context) *models.Token {
|
||||
token, ok := ctx.Value(contextKey).(*models.Token)
|
||||
|
||||
+52
-26
@@ -5,56 +5,82 @@ import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var globalMutex sync.Mutex
|
||||
var global *Config
|
||||
|
||||
// Config is configuration
|
||||
// Config is configuration data
|
||||
type Config struct {
|
||||
Space struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Host string `json:"host"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
SecretKey string `json:"secretKey"`
|
||||
Bucket string `json:"bucket"`
|
||||
MaxSize int64 `json:"maxSize"`
|
||||
Root string `json:"root"`
|
||||
} `json:"space"`
|
||||
Space Space `json:"space" yaml:"space"`
|
||||
Database Database `json:"database" yaml:"database"`
|
||||
Wiki Wiki `json:"wiki" yaml:"wiki"`
|
||||
}
|
||||
|
||||
Database struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Db string `json:"db"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Mechanism string `json:"mechanism"`
|
||||
} `json:"database"`
|
||||
// Space is configuration for spaces.
|
||||
type Space struct {
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
Host string `json:"host" yaml:"host"`
|
||||
AccessKey string `json:"accessKey" yaml:"accessKey"`
|
||||
SecretKey string `json:"secretKey" yaml:"secretKey"`
|
||||
Bucket string `json:"bucket" yaml:"bucket"`
|
||||
MaxSize int64 `json:"maxSize" yaml:"maxSize"`
|
||||
Root string `json:"root" yaml:"root"`
|
||||
}
|
||||
|
||||
Wiki struct {
|
||||
URL string `json:"url"`
|
||||
} `json:"wiki"`
|
||||
// Database is configuration for spaces.
|
||||
type Database struct {
|
||||
Driver string `json:"driver" yaml:"driver"`
|
||||
Host string `json:"host" yaml:"host"`
|
||||
Port int `json:"port" yaml:"port"`
|
||||
Db string `json:"db" yaml:"db"`
|
||||
Username string `json:"username" yaml:"username"`
|
||||
Password string `json:"password" yaml:"password"`
|
||||
Mechanism string `json:"mechanism" yaml:"mechanism"`
|
||||
}
|
||||
|
||||
// Wiki is the wiki stuff.
|
||||
type Wiki struct {
|
||||
URL string `json:"url" yaml:"url"`
|
||||
}
|
||||
|
||||
// Load loads config stuff
|
||||
func (config *Config) Load(filename string) error {
|
||||
log.Println("Trying to load config from " + filename)
|
||||
|
||||
stat, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stat.Size() < 1 {
|
||||
return errors.New("File is empty")
|
||||
}
|
||||
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.NewDecoder(file).Decode(config)
|
||||
if strings.HasSuffix(filename, ".json") {
|
||||
return json.NewDecoder(file).Decode(config)
|
||||
}
|
||||
|
||||
return yaml.NewDecoder(file).Decode(config)
|
||||
}
|
||||
|
||||
// LoadAny loads the first of these files it can find
|
||||
func (config *Config) LoadAny(filenames ...string) error {
|
||||
for _, filename := range filenames {
|
||||
if err := config.Load(filename); err == nil {
|
||||
return nil
|
||||
if err := config.Load(filename); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
*config = Config{}
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("Failed to load configuration files")
|
||||
@@ -65,7 +91,7 @@ func Global() Config {
|
||||
globalMutex.Lock()
|
||||
if global == nil {
|
||||
global = &Config{}
|
||||
err := global.LoadAny("/etc/aiterp/rpdata.json", "./config.json")
|
||||
err := global.LoadAny("/etc/aiterp/rpdata.yaml", "/etc/aiterp/rpdata.json", "./config.yaml", "./config.json")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user