Use properties in config for pass-through compat vars

Strings are immutable, so when one variable changes the other will not,
as such there is variance on config load between variables that should
be the the value of another variable.

To solve that I've moved the config into a class and made those values
read-only properties to the loaded values.

Closes: #137 #138
This commit is contained in:
Sachi King 2016-06-02 17:39:12 +10:00
parent 9fd2661405
commit 695dba98f9
4 changed files with 179 additions and 165 deletions

View file

@ -164,7 +164,7 @@ def error_handler(e):
def create_app(config=None): def create_app(config=None):
app = Application(__name__) app = Application(__name__)
app.config.from_object('realms.config') app.config.from_object('realms.config.conf')
app.url_map.converters['regex'] = RegexConverter app.url_map.converters['regex'] = RegexConverter
app.url_map.strict_slashes = False app.url_map.strict_slashes = False

View file

@ -10,6 +10,8 @@ import pip
import time import time
import subprocess import subprocess
config = config.conf
# called to discover commands in modules # called to discover commands in modules
app = create_app() app = create_app()

View file

@ -1,208 +1,218 @@
import os
import json import json
import os
import sys
from urlparse import urlparse from urlparse import urlparse
from realms.lib.util import in_vagrant from realms.lib.util import in_vagrant
def update(data): class Config(object):
conf = read()
conf.update(data)
return save(data)
urlparse = urlparse
def read(): APP_PATH = os.path.abspath(os.path.dirname(__file__) + "/../..")
conf = dict() USER_HOME = os.path.abspath(os.path.expanduser("~"))
for k, v in os.environ.items(): # Best to change to /var/run
if k.startswith('REALMS_'): PIDFILE = "/tmp/realms-wiki.pid"
conf[k[7:]] = v
loc = get_path() ENV = 'DEV'
if loc: HOST = "0.0.0.0"
with open(loc) as f: PORT = 5000
conf.update(json.load(f)) BASE_URL = 'http://localhost'
SITE_TITLE = "Realms"
for k in ['APP_PATH', 'USER_HOME']: # https://pythonhosted.org/Flask-SQLAlchemy/config.html#connection-uri-format
if k in conf: DB_URI = 'sqlite:////tmp/wiki.db'
del conf[k] # DB_URI = 'mysql://scott:tiger@localhost/mydatabase'
# DB_URI = 'postgresql://scott:tiger@localhost/mydatabase'
# DB_URI = 'oracle://scott:tiger@127.0.0.1:1521/sidname'
# DB_URI = 'crate://'
return conf # LDAP = {
# 'URI': '',
#
# # This BIND_DN/BIND_PASSWORD default to '', this is shown here for demonstrative purposes
# # The values '' perform an anonymous bind so we may use search/bind method
# 'BIND_DN': '',
# 'BIND_AUTH': '',
#
# # Adding the USER_SEARCH field tells the flask-ldap-login that we are using
# # the search/bind method
# 'USER_SEARCH': {'base': 'dc=example,dc=com', 'filter': 'uid=%(username)s'},
#
# # Map ldap keys into application specific keys
# 'KEY_MAP': {
# 'name': 'cn',
# 'company': 'o',
# 'location': 'l',
# 'email': 'mail',
# }
# }
# OAUTH = {
# 'twitter': {
# 'key': '',
# 'secret': ''
# },
# 'github': {
# 'key': '',
# 'secret': ''
# }
# }
def save(conf): # Valid options: simple, redis, memcached
loc = get_path(check_write=True) CACHE_TYPE = 'simple'
with open(loc, 'w') as f:
f.write(json.dumps(conf, sort_keys=True, indent=4, separators=(',', ': ')).strip() + '\n')
return loc
CACHE_REDIS_HOST = '127.0.0.1'
CACHE_REDIS_PORT = 6379
CACHE_REDIS_DB = '0'
def get_path(check_write=False): CACHE_MEMCACHED_SERVERS = ['127.0.0.1:11211']
"""Find config path
"""
for loc in os.curdir, os.path.expanduser("~"), "/etc/realms-wiki":
if not loc:
continue
path = os.path.join(loc, "realms-wiki.json")
if os.path.isfile(path):
# file exists
if not check_write:
# Don't care if I can write
return path
if os.access(path, os.W_OK): # Valid options: simple, elasticsearch, woosh
# Has write access, ok! SEARCH_TYPE = 'simple'
return path
elif os.path.isdir(loc) and check_write:
# dir exists file doesn't
if os.access(loc, os.W_OK):
# can write file
return path
return None
ELASTICSEARCH_URL = 'http://127.0.0.1:9200'
ELASTICSEARCH_FIELDS = ["name"]
APP_PATH = os.path.abspath(os.path.dirname(__file__) + "/../..") WHOOSH_INDEX = '/tmp/whoosh'
USER_HOME = os.path.abspath(os.path.expanduser("~")) WHOOSH_LANGUAGE = 'en'
# Best to change to /var/run # Get ReCaptcha Keys for your domain here:
PIDFILE = "/tmp/realms-wiki.pid" # https://www.google.com/recaptcha/admin#whyrecaptcha
RECAPTCHA_ENABLE = False
RECAPTCHA_USE_SSL = False
RECAPTCHA_PUBLIC_KEY = "6LfYbPkSAAAAAB4a2lG2Y_Yjik7MG9l4TDzyKUao"
RECAPTCHA_PRIVATE_KEY = "6LfYbPkSAAAAAG-KlkwjZ8JLWgwc9T0ytkN7lWRE"
RECAPTCHA_OPTIONS = {}
ENV = 'DEV' SECRET_KEY = 'CHANGE_ME'
DEBUG = True # Path on file system where wiki data will reside
ASSETS_DEBUG = True WIKI_PATH = '/tmp/wiki'
SQLALCHEMY_ECHO = False
HOST = "0.0.0.0" # Name of page that will act as home
PORT = 5000 WIKI_HOME = 'home'
BASE_URL = 'http://localhost'
SITE_TITLE = "Realms"
# https://pythonhosted.org/Flask-SQLAlchemy/config.html#connection-uri-format AUTH_LOCAL_ENABLE = True
DB_URI = 'sqlite:////tmp/wiki.db' ALLOW_ANON = True
# DB_URI = 'mysql://scott:tiger@localhost/mydatabase' REGISTRATION_ENABLED = True
# DB_URI = 'postgresql://scott:tiger@localhost/mydatabase' PRIVATE_WIKI = False
# DB_URI = 'oracle://scott:tiger@127.0.0.1:1521/sidname'
# DB_URI = 'crate://'
# LDAP = { # None, firepad, and/or togetherjs
# 'URI': '', COLLABORATION = 'togetherjs'
#
# # This BIND_DN/BIND_PASSWORD default to '', this is shown here for demonstrative purposes
# # The values '' perform an anonymous bind so we may use search/bind method
# 'BIND_DN': '',
# 'BIND_AUTH': '',
#
# # Adding the USER_SEARCH field tells the flask-ldap-login that we are using
# # the search/bind method
# 'USER_SEARCH': {'base': 'dc=example,dc=com', 'filter': 'uid=%(username)s'},
#
# # Map ldap keys into application specific keys
# 'KEY_MAP': {
# 'name': 'cn',
# 'company': 'o',
# 'location': 'l',
# 'email': 'mail',
# }
# }
# OAUTH = { # Required for firepad
# 'twitter': { FIREBASE_HOSTNAME = None
# 'key': '',
# 'secret': ''
# },
# 'github': {
# 'key': '',
# 'secret': ''
# }
# }
CACHE_TYPE = 'simple' # Page names that can't be modified
WIKI_LOCKED_PAGES = []
# Redis ROOT_ENDPOINT = 'wiki.page'
# CACHE_TYPE = 'redis'
CACHE_REDIS_HOST = '127.0.0.1'
CACHE_REDIS_PORT = 6379
CACHE_REDIS_DB = '0'
# Memcached # Used by Flask-Login
# CACHE_TYPE = 'memcached' @property
CACHE_MEMCACHED_SERVERS = ['127.0.0.1:11211'] def LOGIN_DISABLED(self):
return self.ALLOW_ANON
SEARCH_TYPE = 'simple' # simple is not good for large wikis # Depreciated variable name
@property
def LOCKED(self):
return self.WIKI_LOCKED_PAGES[:]
# SEARCH_TYPE = 'elasticsearch' @property
ELASTICSEARCH_URL = 'http://127.0.0.1:9200' def SQLALCHEMY_DATABASE_URI(self):
ELASTICSEARCH_FIELDS = ["name"] return self.DB_URI
# SEARCH_TYPE = 'whoosh' @property
WHOOSH_INDEX = '/tmp/whoosh' def _url(self):
WHOOSH_LANGUAGE = 'en' return urlparse(self.BASE_URL)
# Get ReCaptcha Keys for your domain here: @property
# https://www.google.com/recaptcha/admin#whyrecaptcha def RELATIVE_PATH(self):
RECAPTCHA_ENABLE = False return self._url.path
RECAPTCHA_USE_SSL = False
RECAPTCHA_PUBLIC_KEY = "6LfYbPkSAAAAAB4a2lG2Y_Yjik7MG9l4TDzyKUao"
RECAPTCHA_PRIVATE_KEY = "6LfYbPkSAAAAAG-KlkwjZ8JLWgwc9T0ytkN7lWRE"
RECAPTCHA_OPTIONS = {}
SECRET_KEY = 'CHANGE_ME'
# Path on file system where wiki data will reside
WIKI_PATH = '/tmp/wiki'
# Name of page that will act as home
WIKI_HOME = 'home'
AUTH_LOCAL_ENABLE = True
ALLOW_ANON = True
REGISTRATION_ENABLED = True
PRIVATE_WIKI = False
# None, firepad, and/or togetherjs
COLLABORATION = 'togetherjs'
# Required for firepad
FIREBASE_HOSTNAME = None
# Page names that can't be modified
WIKI_LOCKED_PAGES = []
ROOT_ENDPOINT = 'wiki.page'
# Used by Flask-Login
LOGIN_DISABLED = ALLOW_ANON
# Depreciated variable name
LOCKED = WIKI_LOCKED_PAGES[:]
if BASE_URL.endswith('/'):
BASE_URL = BASE_URL[:-1]
SQLALCHEMY_DATABASE_URI = DB_URI
_url = urlparse(BASE_URL)
RELATIVE_PATH = _url.path
if in_vagrant():
# sendfile doesn't work well with Virtualbox shared folders
USE_X_SENDFILE = False USE_X_SENDFILE = False
if ENV != "DEV":
DEBUG = False DEBUG = False
ASSETS_DEBUG = False ASSETS_DEBUG = False
SQLALCHEMY_ECHO = False SQLALCHEMY_ECHO = False
MODULES = ['wiki', 'search', 'auth'] MODULES = ['wiki', 'search', 'auth']
globals().update(read()) def __init__(self):
for k, v in self.read().iteritems():
setattr(self, k, v)
if hasattr(self, 'AUTH_LOCAL_ENABLE'):
self.MODULES.append('auth.local')
if hasattr(self, 'OAUTH'):
self.MODULES.append('auth.oauth')
if hasattr(self, 'LDAP'):
self.MODULES.append('auth.ldap')
if in_vagrant():
self.USE_X_SENDFILE = False
if self.ENV == "DEV":
self.DEBUG = True
self.ASSETS_DEBUG = True
self.SQLALCHEMY_ECHO = True
self.USE_X_SENDFILE = False
if globals().get('AUTH_LOCAL_ENABLE'): def update(self, data):
MODULES.append('auth.local') conf = self.read()
conf.update(data)
return self.save(data)
if globals().get('OAUTH'): def read(self):
MODULES.append('auth.oauth') conf = dict()
if globals().get('LDAP'): for k, v in os.environ.items():
MODULES.append('auth.ldap') if k.startswith('REALMS_'):
conf[k[7:]] = v
loc = self.get_path()
if loc:
with open(loc) as f:
conf.update(json.load(f))
if 'BASE_URL' in conf and conf['BASE_URL'].endswith('/'):
conf['BASE_URL'] = conf['BASE_URL'][:-1]
for k in ['APP_PATH', 'USER_HOME']:
if k in conf:
del conf[k]
return conf
def save(self, conf):
loc = self.get_path(check_write=True)
with open(loc, 'w') as f:
f.write(json.dumps(conf, sort_keys=True, indent=4, separators=(',', ': ')).strip() + '\n')
return loc
def get_path(self, check_write=False):
"""Find config path
"""
for loc in os.curdir, os.path.expanduser("~"), "/etc/realms-wiki":
if not loc:
continue
path = os.path.join(loc, "realms-wiki.json")
if os.path.isfile(path):
# file exists
if not check_write:
# Don't care if I can write
return path
if os.access(path, os.W_OK):
# Has write access, ok!
return path
elif os.path.isdir(loc) and check_write:
# dir exists file doesn't
if os.access(loc, os.W_OK):
# can write file
return path
return None
conf = Config()

View file

@ -5,6 +5,8 @@ from flask_oauthlib.client import OAuth
from realms import config from realms import config
from ..models import BaseUser from ..models import BaseUser
config = config.conf
oauth = OAuth() oauth = OAuth()
users = {} users = {}