1
0
mirror of https://github.com/Yubico/yubiadmin.git synced 2024-12-11 09:24:18 +01:00

Writing/reading config files.

This commit is contained in:
Dain Nilsson 2013-04-25 14:48:24 +02:00
parent d690b94982
commit 86c45089ed
12 changed files with 230 additions and 113 deletions

View File

@ -79,7 +79,7 @@
{%- macro render_form(fieldsets, action) -%} {%- macro render_form(fieldsets, action) -%}
<form action="{{ action }}" method="post"> <form action="{{ action }}" method="post">
{% for fieldset in fieldsets %} {% for fieldset in fieldsets %}
{{ form_fieldset(fieldset) }} {{ form_fieldset(fieldset) }}
{% endfor %} {% endfor %}
<div class="form-actions"> <div class="form-actions">
<input type="submit" class="btn btn-primary" value="Save"> <input type="submit" class="btn btn-primary" value="Save">
@ -88,3 +88,5 @@
</div> </div>
</form> </form>
{%- endmacro -%} {%- endmacro -%}
{{ render_form(fieldsets, target) }}

View File

@ -1,3 +0,0 @@
<h2>Database settings</h2>
<p>This is where general settings go.</p>

View File

@ -1,3 +0,0 @@
<h2>General settings</h2>
<p>This is where general settings go.</p>

View File

@ -1,3 +0,0 @@
<h2>KSM settings</h2>
<p>This is where general settings go.</p>

View File

@ -1,3 +0,0 @@
{% from "forms.html" import render_form %}
{{ render_form(fieldsets, '/val/database') }}

View File

@ -1,3 +0,0 @@
{% from "forms.html" import render_form %}
{{ render_form(fieldsets, '/val/general') }}

View File

@ -1,3 +0,0 @@
<h2>KSM settings</h2>
<p>This is where general settings go.</p>

View File

@ -1,3 +0,0 @@
<h2>KSM settings</h2>
<p>This is where general settings go.</p>

View File

@ -1,8 +1,8 @@
import os import os
from wsgiref.simple_server import make_server from wsgiref.simple_server import make_server
from webob.dec import wsgify from webob.dec import wsgify
from jinja2 import Environment, FileSystemLoader
from yubiadmin.util import render
from yubiadmin.apps import apps from yubiadmin.apps import apps
@ -25,14 +25,8 @@ def inspect_app(app):
} }
def render_section(app, section, template, **kwargs):
data = app.__getattribute__(section)(**kwargs)
return template.render(**data)
class YubiAdmin(object): class YubiAdmin(object):
def __init__(self, env): def __init__(self):
self.env = env
self.apps = {} self.apps = {}
for app in apps: for app in apps:
app_data = inspect_app(app) app_data = inspect_app(app)
@ -45,38 +39,29 @@ class YubiAdmin(object):
section_name = request.path_info_pop() section_name = request.path_info_pop()
if not module_name: if not module_name:
tmpl = self.env.get_template('index.html') return render('index', modules=self.modules)
return tmpl.render(modules=self.modules)
app, module = self.apps[module_name] app, module = self.apps[module_name]
if not section_name: if not section_name:
section_name = module['sections'][0]['name'] section_name = module['sections'][0]['name']
tmpl = self.env.get_template('%s/%s.html' %
(module_name, section_name))
section = next(section for section in module['sections'] section = next(section for section in module['sections']
if section['name'] == section_name) if section['name'] == section_name)
data = app.__getattribute__(section_name)(request) return render(
page = tmpl.render(**data) 'app_base',
modules=self.modules,
data.update({ module=module,
'modules': self.modules, section=section,
'module': module, title='YubiAdmin - %s - %s' % (module_name, section_name),
'section': section, page=app.__getattribute__(section_name)(request)
'title': '%s - %s' % (module_name, section_name), )
'page': page
})
tmpl = env.get_template('app_base.html')
return tmpl.render(**data)
cwd = os.path.dirname(__file__) cwd = os.path.dirname(__file__)
base_dir = os.path.abspath(os.path.join(cwd, os.pardir)) base_dir = os.path.abspath(os.path.join(cwd, os.pardir))
static_dir = os.path.join(base_dir, 'static') static_dir = os.path.join(base_dir, 'static')
template_dir = os.path.join(base_dir, 'templates')
env = Environment(loader=FileSystemLoader(template_dir))
application = YubiAdmin(env) application = YubiAdmin()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -17,6 +17,6 @@ class YubikeyKsm(object):
""" """
Database Settings Database Settings
""" """
return {} return "Hello world"
app = YubikeyKsm() app = YubikeyKsm()

View File

@ -1,55 +1,107 @@
from wtforms import Form from wtforms.fields import StringField, IntegerField, PasswordField
from wtforms.fields import StringField, IntegerField from wtforms.validators import NumberRange, Optional
from wtforms.validators import NumberRange from wtforms.widgets import PasswordInput
from yubiadmin.util import App, ConfigForm, FileConfig, render
__all__ = [ __all__ = [
'app' 'app'
] ]
class MiscForm(Form): def yk_read_str(varname):
legend = 'Misc' return r'\$baseParams\[\'__YKVAL_%s__\'\] = [\'"](.*)[\'"];' % varname
default_timeout = IntegerField('Default Timeout', [NumberRange(0)],
default=1)
def load(self):
self.default_timeout.process_data(5)
def save(self):
pass
class SyncLevelsForm(Form): def yk_write_str(varname):
return lambda x: '$baseParams[\'__YKVAL_%s__\'] = "%s";' % (varname, x)
def yk_read_int(varname):
return r'\$baseParams\[\'__YKVAL_%s__\'\] = (\d+);' % varname
def yk_write_int(varname):
return lambda x: '$baseParams[\'__YKVAL_%s__\'] = %s;' % (varname, x)
def db_read(varname):
return r'\$db%s=\'(.*)\';' % varname
def db_write(varname):
return lambda x: '$db%s=\'%s\';' % (varname, x)
class SyncLevelsForm(ConfigForm):
legend = 'Sync Levels' legend = 'Sync Levels'
sync_default = IntegerField('Default', [NumberRange(1, 100)], default=60)
sync_secure = IntegerField('Secure', [NumberRange(1, 100)], default=40)
sync_fast = IntegerField('Fast', [NumberRange(1, 100)], default=1)
def load(self): sync_default = IntegerField('Default', [NumberRange(1, 100)])
# TODO: Read config file sync_secure = IntegerField('Secure', [NumberRange(1, 100)])
self.sync_default.process_data(40) sync_fast = IntegerField('Fast', [NumberRange(1, 100)])
self.sync_secure.process_data(51)
self.sync_fast.process_data(1)
def save(self): config = FileConfig(
# TODO: Save data t config file '/home/dain/yubico/yubiadmin/ykval-config.php',
pass [
(
'sync_default',
yk_read_int('SYNC_DEFAULT_LEVEL'),
yk_write_int('SYNC_DEFAULT_LEVEL'),
60
), (
'sync_secure',
yk_read_int('SYNC_SECURE_LEVEL'),
yk_write_int('SYNC_SECURE_LEVEL'),
40
), (
'sync_fast',
yk_read_int('SYNC_FAST_LEVEL'),
yk_write_int('SYNC_FAST_LEVEL'),
1
),
]
)
class DatabaseForm(Form): class MiscForm(ConfigForm):
legend = 'Misc'
default_timeout = IntegerField('Default Timeout', [NumberRange(0)])
config = FileConfig(
'/home/dain/yubico/yubiadmin/ykval-config.php',
[(
'default_timeout',
yk_read_int('SYNC_DEFAULT_TIMEOUT'),
yk_write_int('SYNC_DEFAULT_TIMEOUT'),
1
)]
)
class DatabaseForm(ConfigForm):
legend = 'Database' legend = 'Database'
connection_string = StringField('Connection String', default=1) dbtype = StringField('DB type')
attrs = {'connection_string': {'class': 'input-xxlarge'}} dbserver = StringField('Host')
dbport = IntegerField('Port', [Optional(), NumberRange(1, 65535)])
dbname = StringField('DB name')
dbuser = StringField('DB username')
dbpass = PasswordField('DB password',
widget=PasswordInput(hide_value=False))
def load(self): config = FileConfig(
self.connection_string.process_data( '/home/dain/yubico/yubiadmin/config-db.php',
'mysql:dbname=ykval;host=127.0.0.1') [
('dbtype', db_read('type'), db_write('type'), 'mysql'),
def save(self): ('dbserver', db_read('server'), db_write('server'), 'localhost'),
pass ('dbport', db_read('port'), db_write('port'), ''),
('dbname', db_read('name'), db_write('name'), 'ykval'),
('dbuser', db_read('user'), db_write('user'), 'ykval_verifier'),
('dbpass', db_read('pass'), db_write('pass'), ''),
]
)
class YubikeyVal(object): class YubikeyVal(App):
""" """
YubiKey Validation Server YubiKey Validation Server
@ -59,52 +111,28 @@ class YubikeyVal(object):
name = 'val' name = 'val'
sections = ['general', 'database', 'syncpool', 'ksms'] sections = ['general', 'database', 'syncpool', 'ksms']
def _populate_forms(self, forms, data):
if not data:
for form in forms:
form.load()
else:
errors = False
for form in forms:
form.process(data)
errors = form.validate() or errors
if not errors:
for form in forms:
form.save()
def general(self, request): def general(self, request):
""" """
General General
""" """
forms = [ return self.render_forms(request, [SyncLevelsForm(), MiscForm()])
SyncLevelsForm(),
MiscForm()
]
self._populate_forms(forms, request.params)
return {'fieldsets': forms}
def database(self, request): def database(self, request):
""" """
Database Settings Database Settings
""" """
forms = [DatabaseForm()] return self.render_forms(request, [DatabaseForm()])
self._populate_forms(forms, request.params)
return {'fieldsets': forms}
def syncpool(self, request): def syncpool(self, request):
""" """
Sync pool Sync pool
""" """
return {} return render('form', target=request.path)
def ksms(self, request): def ksms(self, request):
""" """
Key Store Modules Key Store Modules
""" """
return {} return render('form', target=request.path)
app = YubikeyVal() app = YubikeyVal()

123
yubiadmin/util.py Normal file
View File

@ -0,0 +1,123 @@
import os
import re
from UserDict import DictMixin
from wtforms import Form
from jinja2 import Environment, FileSystemLoader
__all__ = [
'App',
'FileConfig',
'ConfigForm',
'render',
'populate_forms',
]
cwd = os.path.dirname(__file__)
base_dir = os.path.abspath(os.path.join(cwd, os.pardir))
template_dir = os.path.join(base_dir, 'templates')
env = Environment(loader=FileSystemLoader(template_dir))
def render(tmpl, **kwargs):
template = env.get_template('%s.html' % tmpl)
return template.render(**kwargs)
def populate_forms(forms, data):
if not data:
for form in forms:
form.load()
else:
errors = False
for form in forms:
form.process(data)
errors = not form.validate() or errors
if not errors:
for form in forms:
form.save()
else:
print 'Errors!'
class App(object):
name = None
sections = []
def render_forms(self, request, forms):
populate_forms(forms, request.params)
return render('form', target=request.path, fieldsets=forms)
class ValueHandler(object):
def __init__(self, pattern, writer, default=None, group=1):
self.pattern = re.compile(pattern)
self.writer = writer
self.default = default
self.group = group
def read(self, content):
match = self.pattern.search(content)
if match:
return match.group(self.group)
return self.default
def write(self, content, value):
if value is None:
value = ''
if self.pattern.search(content):
content = self.pattern.sub(self.writer(value), content, 1)
else:
content += os.linesep + self.writer(value)
return content
class FileConfig(DictMixin):
def __init__(self, filename, params=[]):
self.filename = filename
self.params = {}
for param in params:
self.add_param(*param)
def read(self):
try:
with open(self.filename, 'r') as file:
self.content = file.read()
except IOError as e:
print e
self.content = ''
def commit(self):
with open(self.filename, 'w+') as file:
file.write(self.content)
def add_param(self, key, pattern, writer, default=None, group=1):
self.params[key] = ValueHandler(pattern, writer, default, group)
def __getitem__(self, key):
return self.params[key].read(self.content)
def __setitem__(self, key, value):
self.content = self.params[key].write(self.content, value)
def keys(self):
return self.params.keys()
def __delitem__(self, key):
del self.params[key]
class ConfigForm(Form):
config = None
def load(self):
self.config.read()
for field in self:
if field.id in self.config:
field.process_data(self.config[field.id])
def save(self):
self.config.read()
for field in self:
if field.id in self.config:
self.config[field.id] = field.data
self.config.commit()