Detect if a user is Admin and do not send AuthUser
This is done by parsing users.mk with python, the users.mk will be watched by inotify for changes. Signed-off-by: René Jochum <rene@webmeisterei.com>master
parent
f1300b5c5f
commit
d62c1382ca
@ -0,0 +1,166 @@
|
|||||||
|
package lql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/fsnotify.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const usersExporterFile = `from __future__ import print_function
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
class MultiSiteUsers(object):
|
||||||
|
def update(self, data):
|
||||||
|
print(json.dumps(data));
|
||||||
|
|
||||||
|
multisite_users = MultiSiteUsers()
|
||||||
|
|
||||||
|
eval(open("%s").read())
|
||||||
|
`
|
||||||
|
|
||||||
|
type UserData struct {
|
||||||
|
ForceAuthUserWebservice bool `json:"force_authuser_webservice"`
|
||||||
|
Looked bool `json:"locked"`
|
||||||
|
Roles []string `json:"roles"`
|
||||||
|
ForceAuthUser bool `json:"force_authuser"`
|
||||||
|
Alias string `json:"alias"`
|
||||||
|
StartUrl string `json:"start_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UsersWatcher struct {
|
||||||
|
usersfile string
|
||||||
|
users map[string]UserData
|
||||||
|
lock *sync.RWMutex
|
||||||
|
logger *log.Logger
|
||||||
|
isWatching bool
|
||||||
|
watcher *fsnotify.Watcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUsersWatcher(usersfile string) (*UsersWatcher, error) {
|
||||||
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uw := &UsersWatcher{
|
||||||
|
usersfile: usersfile,
|
||||||
|
lock: &sync.RWMutex{},
|
||||||
|
isWatching: false,
|
||||||
|
watcher: watcher,
|
||||||
|
}
|
||||||
|
|
||||||
|
return uw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uw *UsersWatcher) Close() {
|
||||||
|
uw.watcher.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uw *UsersWatcher) SetLogger(logger *log.Logger) {
|
||||||
|
uw.logger = logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uw *UsersWatcher) StartWatching() {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event, ok := <-uw.watcher.Events:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
|
uw.FetchUsers()
|
||||||
|
}
|
||||||
|
case err, ok := <-uw.watcher.Errors:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uw.logger.WithField("error", err).Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
uw.lock.Lock()
|
||||||
|
uw.isWatching = true
|
||||||
|
uw.lock.Unlock()
|
||||||
|
|
||||||
|
err := uw.watcher.Add(uw.usersfile)
|
||||||
|
if err != nil {
|
||||||
|
uw.logger.WithField("error", err).Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uw *UsersWatcher) IsAdmin(userName string) bool {
|
||||||
|
uw.lock.RLock()
|
||||||
|
if uw.users == nil {
|
||||||
|
uw.lock.RUnlock()
|
||||||
|
|
||||||
|
if !uw.isWatching {
|
||||||
|
uw.StartWatching()
|
||||||
|
}
|
||||||
|
|
||||||
|
uw.FetchUsers()
|
||||||
|
uw.lock.RLock()
|
||||||
|
}
|
||||||
|
defer uw.lock.RUnlock()
|
||||||
|
|
||||||
|
userData, ok := uw.users[userName]
|
||||||
|
if !ok {
|
||||||
|
uw.logger.WithField("user_name", userName).Debug("Failed to fetch user from db")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, role := range userData.Roles {
|
||||||
|
if role == "admin" {
|
||||||
|
uw.logger.WithField("user_name", userName).Trace("User is admin")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uw.logger.WithField("user_name", userName).Trace("User is not admin")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uw *UsersWatcher) FetchUsers() error {
|
||||||
|
uw.logger.WithField("usersfile", uw.usersfile).Debug("Reading users")
|
||||||
|
|
||||||
|
dir, err := ioutil.TempDir("", "lql-api")
|
||||||
|
if err != nil {
|
||||||
|
uw.logger.WithField("error", err).Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpfn := filepath.Join(dir, "lql-api-user-reader.py")
|
||||||
|
if err := ioutil.WriteFile(tmpfn, []byte(fmt.Sprintf(usersExporterFile, uw.usersfile)), 0700); err != nil {
|
||||||
|
uw.logger.WithField("error", err).Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("python", tmpfn)
|
||||||
|
uw.logger.WithField("args", cmd.Args).Debug("Executing")
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
uw.logger.WithField("error", err).Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[string]UserData, 1)
|
||||||
|
if err = json.Unmarshal(out, &result); err != nil {
|
||||||
|
uw.logger.WithField("error", err).Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
uw.lock.Lock()
|
||||||
|
uw.users = result
|
||||||
|
uw.lock.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue