First public import

pull/1/head
q3k 2016-02-15 20:30:53 +00:00
commit d03f876670
1024 changed files with 2400 additions and 0 deletions

2
runserver.py Normal file
View File

@ -0,0 +1,2 @@
from webapp import app
app.run('0.0.0.0', 20007, debug=True)

69
webapp/__init__.py Normal file
View File

@ -0,0 +1,69 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import flask
import flask.ext.wtf
import wtforms
app = flask.Flask(__name__)
app.secret_key = "foobarbaz"
#app.add_url_rule('/login', views.login_form, methods=["GET"])
#app.add_url_rule('/login', views.login_action, methods=["POST"])
#app.add_url_rule('/logout', views.login_action)
#app.add_url_rule('/passwd', views.passwd_form, methods=["GET"])
#app.add_url_rule('/passwd', views.passwd_action, methods=["POST"])
# import views to route them
import webapp.views
from webapp import validation, pools, config
@app.context_processor
def inject_readable():
return dict(readable_names=config.readable_names)
@app.context_processor
def inject_static():
return dict(STATIC_PATH=config.STATIC_PATH)
@app.template_filter('first')
def ldap_first(v):
return v and v[0]
@app.template_filter('readable')
def readable_tf(n):
return config.readable_names.get(n, n)
class LPKForm(flask.ext.wtf.Form):
value = wtforms.fields.TextAreaField('Klucz Publiczny')
def initialize_forms():
forms = {}
for f in reduce(lambda a,b: a | b, config.can.values()):
cls, attrs = config.fields.get(f, config.default_field)
class AddForm(flask.ext.wtf.Form):
value = cls(label=config.readable_names.get(f), **attrs)
AddForm.__name__ == 'Add' + f
forms[f] = AddForm
print f, forms[f]
forms[validation.sanitize_ldap(config.lpk_attr)] = LPKForm
return forms
@app.before_first_request
def start(*a, **kw):
validation.sanitize_perms()
validation.sanitize_readable()
config.lpk_attr = validation.sanitize_ldap(config.lpk_attr)
app.connections = pools.ConnectionPool(config.ldap_url, timeout=300.0)
def drop_profile(dn):
if dn != config.admin_dn:
del app.profiles[dn]
app.connections.register_callback('drop', drop_profile)
app.connections.start()
app.tokens = pools.TokenPool(timeout=600.0)
app.tokens.start()
app.profiles = {}
app.forms = initialize_forms()

64
webapp/config.py Normal file
View File

@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
import flask.ext.wtf
import wtforms
ldap_url = 'ldap://ldap.hackerspace.pl'
lpk_attr = 'sshPublicKey'
irc_attr = 'ircnick'
dn_format = "uid=%s,ou=people,dc=hackerspace,dc=pl"
admin_dn = 'cn=ldapweb,ou=Services,dc=hackerspace,dc=pl'
admin_pw = 'foobarbaz'
api_allowed = [
"/C=PL/ST=Mazowieckie/L=Warsaw/O=Hackerspace Warsaw/OU=API/CN=ood-web/name=ood-web/emailAddress=bofh@hackerspace.pl",
"/C=PL/ST=Mazowieckie/L=Warsaw/O=Hackerspace Warsaw/OU=API/CN=patologia-new/name=itanic/emailAddress=bofh@hackerspace.pl",
]
readable_names = {
'givenname': u'Imię',
'surname': 'Nazwisko',
'loginshell': u'Powłoka',
'telephonenumber': 'Nr tel.',
'mobiletelephonenumber': 'Tel. kom.',
lpk_attr: 'Klucz publiczny',
irc_attr: 'IRC Nick',
}
full_name = {
'cn': 'commonname',
'sn': 'surname',
'mobile': 'mobiletelephonenumber',
'l': 'locality',
}
can_add = set([
'telephonenumber',
'mobiletelephonenumber',
lpk_attr,
])
perm_errors = {
'add': 'You cannot add this attribute!',
'mod': 'You cannot change this attribute!',
'del': 'You cannot delete this attribute!',
}
std_templates = {
'add': 'ops/add.html',
'mod': 'ops/mod.html',
'del': 'ops/del.html',
}
admin_required = set(['ircnick'])
can_delete = can_add | set(['ircnick'])
can_modify = can_add
can = { 'add':can_add, 'mod':can_modify, 'del':can_delete }
default_field = (wtforms.fields.StringField, {})
fields = { 'telephonenumber': (wtforms.fields.StringField, {'validators': [wtforms.validators.Regexp(r'[+0-9 ]+')]})}
STATIC_PATH = 'https://static.hackerspace.pl/staging/'
TOKEN_LENGTH = 32

60
webapp/context.py Normal file
View File

@ -0,0 +1,60 @@
import random
import string
import hashlib
import flask
import ldap
from webapp import app, config, validation
class Attr(object):
def __init__(self, name, value):
name = validation.sanitize_ldap(name)
self.name = name
self.readable_name = config.readable_names.get(name, name)
self.value = value
self.uid = hashlib.sha1(name + value).hexdigest()
def __unicode__(self):
return self.value.decode('utf-8')
def get_dn():
return flask.session.get('dn')
def get_connection(dn = None):
dn = dn or get_dn()
return app.connections[dn]
def get_admin_connection():
conn = app.connections[config.admin_dn]
if not conn:
conn = app.connections.bind(config.admin_dn, config.admin_pw)
return conn
def get_profile():
return app.profiles[get_dn()]
def refresh_profile(dn=None):
dn = dn or get_dn()
conn = get_connection(dn)
if not conn:
return # no session, nothing to refresh i guess
res = conn.search_s(dn, ldap.SCOPE_SUBTREE)
assert(len(res) == 1)
profile = {}
for attr, vs in res[0][1].iteritems():
for v in vs:
a = Attr(attr, v)
profile[a.uid] = a
app.profiles[dn] = profile
return profile
def generate_token():
dn = get_dn()
token = ''.join(random.choice(string.letters) for i in xrange(config.TOKEN_LENGTH))
app.tokens.insert(dn, token)
def get_token():
dn = get_dn()
return app.tokens[dn]

58
webapp/lru.py Normal file
View File

@ -0,0 +1,58 @@
import sys
import functools
import threading
import time
def locked(f):
@functools.wraps(f)
def func(self, *a, **kw):
self.lock.acquire()
try:
return f(self, *a, **kw)
finally:
self.lock.release()
return func
class LRUPool(threading.Thread):
def __init__(self, timeout=60.0, **kw):
threading.Thread.__init__(self, **kw)
self.setDaemon(True)
self.pool = {}
self.timeout = timeout
self.lock = threading.Lock()
self.callbacks = {}
def run(self):
print >> sys.stderr, "pool starting"
while True:
time.sleep(self.timeout / 2)
self.lock.acquire()
now = time.time()
for k, [c, atime] in self.pool.items():
if now - atime > self.timeout:
print 'popping', k, now, atime
self._drop(k)
self.lock.release()
def register_callback(self, action, cb):
self.callbacks.setdefault(action, []).append(cb)
@locked
def __getitem__(self, key):
item = self.pool.get(key)
if not item:
return
item[1] = time.time()
return item[0]
def _insert(self, key, item):
self.pool[key] = [item, time.time()]
return item
@locked
def insert(self, key, item):
return self._insert(key, item)
def _drop(self, key):
for f in self.callbacks.get('drop',[]):
f(key)
return self.pool.pop(key, None)
@locked
def drop(self, key):
return self._drop(key)

30
webapp/pools.py Normal file
View File

@ -0,0 +1,30 @@
import ldap
from webapp import lru, config
class ConnectionPool(lru.LRUPool):
def __init__(self, url, use_tls=True, **kw):
lru.LRUPool.__init__(self, **kw)
self.use_tls = use_tls
self.url = url
self.admin_dn = config.admin_dn
self.admin_pw = config.admin_pw
@lru.locked
def bind(self, dn, password):
conn = ldap.initialize(self.url)
if(self.use_tls):
conn.start_tls_s()
conn.simple_bind_s(dn, password)
return self._insert(dn, conn)
def unbind(self, dn):
return self.drop(dn)
class TokenPool(lru.LRUPool):
@lru.locked
def find_owner(self, token):
for k, v in self.pool.items():
if v[0] == token:
return k
return None

76
webapp/static/basic.css Normal file
View File

@ -0,0 +1,76 @@
td.key {
font-size: 7pt;
max-width: 300pt;
word-break: break-all;
word-wrap: break-word;
}
td.token {
font-weight: bold;
}
h2 {
padding-left: 40px;
}
.login {
position: relative;
top: 100%;
margin-top: -30px;
float: right;
background-color: rgb(50, 50, 50);
padding: 5px;
padding-left: 15px;
padding-right: 15px;
border-radius: 5px 5px 0 0;
font-size: 14px;
color: rgb(200, 200, 200);
}
.login img {
margin-right: 8px;
}
.login a {
color: rgb(238, 238, 238);
}
#content {
clear: both;
}
a {
text-decoration: none;
color: rgb(34, 34, 34);
}
#actions a {
font-family: verdana, sans-serif;
font-size: 13px;
}
#actions a img {
position: relative;
top: -2px;
margin-right: 6px;
}
#actions li {
list-style: none;
}
#headerimg {
width: 1024px;
height: 100px;
background-image: url("/static/servers.jpg");
}
footer {
font-size: 10px;
color: rgb(100, 100, 100);
}
footer a {
color: rgb(120, 120, 120);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

BIN
webapp/static/icons/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

BIN
webapp/static/icons/bin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 793 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Some files were not shown because too many files have changed in this diff Show More