diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..abceb94
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,16 @@
+FROM python:3.6
+
+VOLUME /opt/cbmi
+
+RUN apt-get update && apt-get install -y libsasl2-dev python-dev libldap2-dev libssl-dev
+
+ADD requirements.txt /requirements.txt
+RUN pip install --upgrade -r /requirements.txt
+
+RUN ls /opt/cbmi
+
+EXPOSE 8000
+ENTRYPOINT ["/opt/cbmi/start"]
+
+
+
diff --git a/account/cbase_members.py b/account/cbase_members.py
index b9ef86e..a9d0039 100644
--- a/account/cbase_members.py
+++ b/account/cbase_members.py
@@ -5,7 +5,7 @@ import ldap
import copy
from django.conf import settings
-from password_encryption import get_ldap_password
+from account.password_encryption import get_ldap_password
"""
Example configuration:
@@ -14,11 +14,12 @@ CBASE_LDAP_URL = 'ldap://lea.cbrp3.c-base.org:389/'
CBASE_BASE_DN = 'ou=crew,dc=c-base,dc=org'
"""
+
def retrieve_member(request):
ldap_password = get_ldap_password(request)
session = dict(request.session)
- print "session:", session
- print "cookies:", request.COOKIES
+ print("session:", session)
+ print("cookies:", request.COOKIES)
return MemberValues(request.user.username, ldap_password)
@@ -26,6 +27,7 @@ class MemberValues(object):
"""
Dictionary-like abstraction of the c-base member attributes.
"""
+
def __init__(self, username, password):
self._username = username
self._password = password
@@ -42,6 +44,9 @@ class MemberValues(object):
else:
value = default
+ if value is not None:
+ value = value.decode()
+
# Decode
if value == 'TRUE':
return True
@@ -79,7 +84,7 @@ class MemberValues(object):
action = ldap.MOD_REPLACE
if new_key not in self._old.keys():
action = ldap.MOD_ADD
- mod_attrs.append((action, '%s' % new_key, new_value ))
+ mod_attrs.append((action, '%s' % new_key, new_value))
continue
if self._old[new_key][0] != None and new_value == [None]:
action = ldap.MOD_DELETE
@@ -88,14 +93,13 @@ class MemberValues(object):
# Set the attribute and wait for the LDAP server to complete.
if self._old[new_key][0] != new_value[0]:
action = ldap.MOD_REPLACE
- mod_attrs.append((action, '%s' % new_key, new_value ))
+ mod_attrs.append((action, '%s' % new_key, new_value))
continue
-
- print "modattrs: ",mod_attrs
+ print("modattrs: ", mod_attrs)
result = l.modify_s(dn, mod_attrs)
#
- # print "result is: ", result
+ # print("result is: ", result)
l.unbind_s()
def change_password(self, new_password):
@@ -142,9 +146,10 @@ class MemberValues(object):
searchFilter = "uid=%s" % self._username
dn = settings.CBASE_BASE_DN
- result = session.search_s(dn, searchScope, searchFilter, retrieveAttributes)
+ result = session.search_s(
+ dn, searchScope, searchFilter, retrieveAttributes)
# TODO: latin1
- print "result is: ", result
+ print("result is: ", result)
# TODO: if len(result)==0
session.unbind_s()
return result[0][1]
@@ -176,7 +181,7 @@ class MemberValues(object):
l.simple_bind_s(user_dn, self._password)
try:
result_id = l.search(settings.CBASE_BASE_DN, ldap.SCOPE_SUBTREE,
- "memberOf=cn=crew,ou=groups,dc=c-base,dc=org", None)
+ "memberOf=cn=crew,ou=groups,dc=c-base,dc=org", None)
result_set = []
while True:
result_type, result_data = l.result(result_id, 0)
@@ -187,7 +192,14 @@ class MemberValues(object):
result_set.append(result_data)
# list comprehension to get a list of user tupels in the format ("nickname", "nickname (real name)")
- userlist = [(x[0][1]['uid'][0], '%s (%s, %s)' % (x[0][1]['uid'][0], x[0][1]['cn'][0], x[0][1]['uidNumber'][0])) for x in result_set]
+ userlist = [(
+ x[0][1]['uid'][0].decode(),
+ '%s (%s, %s)' % (
+ x[0][1]['uid'][0].decode(),
+ x[0][1]['cn'][0].decode(),
+ x[0][1]['uidNumber'][0].decode()
+ )
+ ) for x in result_set]
return sorted(userlist)
- except:
+ except Exception:
return []
diff --git a/account/models.py b/account/models.py
index 72984e0..9db847a 100644
--- a/account/models.py
+++ b/account/models.py
@@ -4,7 +4,7 @@ from django.db.models import signals
from account.signals import create_profile, delete_profile
class UserProfile(models.Model):
- user = models.OneToOneField(User, editable=False)
+ user = models.OneToOneField(User, editable=False, on_delete=models.CASCADE)
uid = models.CharField(verbose_name="User-ID",
max_length=8,
null=True,
diff --git a/account/password_encryption.py b/account/password_encryption.py
index 0c4138c..d18938e 100644
--- a/account/password_encryption.py
+++ b/account/password_encryption.py
@@ -26,7 +26,7 @@ def encrypt_ldap_password(cleartext_pw):
# do the encryption
aes = AES.new(key, AES.MODE_CFB, iv)
message = iv + aes.encrypt(cleartext_pw)
- return base64.b64encode(message), base64.b64encode(key)
+ return base64.b64encode(message).decode(), base64.b64encode(key).decode()
def decrypt_ldap_password(message, key):
"""
diff --git a/account/templates/base.html b/account/templates/base.html
index e80b77e..393bc84 100644
--- a/account/templates/base.html
+++ b/account/templates/base.html
@@ -1,5 +1,6 @@
{% load i18n %}
{% load crispy_forms_tags %}
+{% load static from staticfiles %}
@@ -66,7 +67,7 @@
+ src="{% static 'img/logo.gif' %}" />
{% trans "member interface" %}
diff --git a/account/templates/hammertime.html b/account/templates/hammertime.html
index 190b5e0..cc1b2a8 100644
--- a/account/templates/hammertime.html
+++ b/account/templates/hammertime.html
@@ -11,7 +11,8 @@
-

+

+
diff --git a/account/tests.py b/account/tests.py
index 078a96a..ac863db 100644
--- a/account/tests.py
+++ b/account/tests.py
@@ -19,8 +19,8 @@ class PasswordEncryptionTest(TestCase):
def test_encrypt_ldap_password(self):
message, key = self.encrypt_it()
- print 'key:', key
- print 'message:', message
+ print('key:', key)
+ print('message:', message)
def test_decrypt_ldap_password(self):
diff --git a/account/urls.py b/account/urls.py
index 52882ae..a5f919e 100644
--- a/account/urls.py
+++ b/account/urls.py
@@ -1,20 +1,21 @@
-from django.conf.urls import patterns, url
+from account.views import (admin, auth_login, auth_logout, clabpin, gastropin,
+ groups_list, home, memberstatus, nrf24, password,
+ preferred_email, rfid, sippin, wlan_presence)
+from django.conf.urls import url
-
-urlpatterns = patterns(
- '',
- url(r'^login/$', 'account.views.auth_login', name="cbase_auth_login"),
- url(r'^logout/$', 'account.views.auth_logout', name="auth_logout"),
- url(r'^gastropin/$', 'account.views.gastropin', name='gastropin'),
- url(r'^wlan_presence/$', 'account.views.wlan_presence', name='wlan_presence'),
- url(r'^rfid/$', 'account.views.rfid', name='rfid'),
- url(r'^nrf24/$', 'account.views.nrf24', name='nrf24'),
- url(r'^password/$', 'account.views.password', name='password'),
- url(r'^sippin/$', 'account.views.sippin', name='sippin'),
- url(r'^clabpin/$', 'account.views.clabpin', name='clabpin'),
- url(r'^preferred_email/$', 'account.views.preferred_email', name='preferred_email'),
- url(r'^admin/$', 'account.views.admin', name='admin'),
- url(r'^memberstatus/$', 'account.views.memberstatus', name='memberstatus'),
- url(r'^$', 'account.views.home', name="home"),
- url(r'^groups/(?P[^/]+)/', 'account.views.groups_list'),
-)
+urlpatterns = [
+ url(r'^login/$', auth_login, name="cbase_auth_login"),
+ url(r'^logout/$', auth_logout, name="auth_logout"),
+ url(r'^gastropin/$', gastropin, name='gastropin'),
+ url(r'^wlan_presence/$', wlan_presence, name='wlan_presence'),
+ url(r'^rfid/$', rfid, name='rfid'),
+ url(r'^nrf24/$', nrf24, name='nrf24'),
+ url(r'^password/$', password, name='password'),
+ url(r'^sippin/$', sippin, name='sippin'),
+ url(r'^clabpin/$', clabpin, name='clabpin'),
+ url(r'^preferred_email/$', preferred_email, name='preferred_email'),
+ url(r'^admin/$', admin, name='admin'),
+ url(r'^memberstatus/$', memberstatus, name='memberstatus'),
+ url(r'^$', home, name="home"),
+ url(r'^groups/(?P[^/]+)/', groups_list),
+]
diff --git a/account/views.py b/account/views.py
index 3b610e5..065fa06 100644
--- a/account/views.py
+++ b/account/views.py
@@ -19,13 +19,13 @@ from django.contrib.auth.models import Group
from django.shortcuts import render
from django.utils.translation import ugettext as _
-from forms import GastroPinForm, WlanPresenceForm, LoginForm, PasswordForm, \
+from account.forms import GastroPinForm, WlanPresenceForm, LoginForm, PasswordForm, \
RFIDForm, NRF24Form, SIPPinForm, CLabPinForm, AdminForm, PreferredEmailForm
-from cbase_members import retrieve_member, MemberValues
-from password_encryption import *
+from account.cbase_members import retrieve_member, MemberValues
+from account.password_encryption import *
def landingpage(request):
- if request.user.is_authenticated():
+ if request.user.is_authenticated:
return HttpResponseRedirect('/account')
login_form = LoginForm()
try:
@@ -77,8 +77,7 @@ def auth_login(request):
else:
form = LoginForm()
- return render_to_response('login.html',
- RequestContext(request, locals()))
+ return render_to_response('login.html', locals())
@login_required
def home(request):
@@ -88,13 +87,13 @@ def home(request):
username = request.user.username
url = "https://vorstand.c-base.org/cteward-api/legacy/member/%s" % username
cteward = None
- #try:
- #r = requests.get(url, verify=False, auth=(username, password))
- #cteward = r.json()
- #except:
- #pass
+ try:
+ r = requests.get(url, verify=False, auth=(username, password))
+ cteward = r.json()
+ except Exception:
+ pass
context = {'member': member.to_dict(),
- 'groups': sorted(list(request.user.groups.all())),
+ 'groups': list(request.user.groups.all().order_by('name')),
'number_of_members': number_of_members,
'cteward': cteward,
}
@@ -137,7 +136,7 @@ def set_hash_field(request, form_type, in_field, out_field, hash_func,
form = form_type(request.POST)
if form.is_valid():
hashed_value = hash_func(form.cleaned_data[in_field])
- print 'hashed value: ', hashed_value
+ print('hashed value: ', hashed_value)
member.set(out_field, hashed_value)
member.save()
new_form = form_type(initial=initial)
diff --git a/cbapi_ldap/urls.py b/cbapi_ldap/urls.py
index bb83b0b..478f5b8 100644
--- a/cbapi_ldap/urls.py
+++ b/cbapi_ldap/urls.py
@@ -1,9 +1,10 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
from jsonrpc import jsonrpc_site
+from jsonrpc.views import browse
from cbapi_ldap import views
-urlpatterns = patterns(
- '',
- url(r'^ldap/browse/$', 'jsonrpc.views.browse', name='jsonrpc_browser'),
+
+urlpatterns = [
+ url(r'^ldap/browse/$', browse, name='jsonrpc_browser'),
url(r'^ldap/$', jsonrpc_site.dispatch, name='jsonrpc_mountpoint'),
-)
+]
diff --git a/cbmi/cbmi.db b/cbmi/cbmi.db
new file mode 100644
index 0000000..7f2b0cd
Binary files /dev/null and b/cbmi/cbmi.db differ
diff --git a/cbmi/settings.py b/cbmi/settings.py
index 4334f4f..6ee3e9d 100644
--- a/cbmi/settings.py
+++ b/cbmi/settings.py
@@ -1,4 +1,5 @@
# Django settings for cbmi project.
+import os
DEBUG = True
TEMPLATE_DEBUG = DEBUG
@@ -10,14 +11,17 @@ ADMINS = (
MANAGERS = ADMINS
+PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'cbmi',
- 'USER': 'cbmi',
- 'PASSWORD': 'cbmi',
- 'HOST': '',
- 'PORT': '',
+ # 'ENGINE': 'django.db.backends.mysql',
+ # 'NAME': 'cbmi',
+ # 'USER': 'cbmi',
+ # 'PASSWORD': 'cbmi',
+ # 'HOST': '',
+ # 'PORT': '',
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(PROJECT_DIR, 'cbmi.db'),
}
}
@@ -69,6 +73,7 @@ STATICFILES_DIRS = (
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
'/home/cbmi/cbmi/static',
+ '/opt/cbmi/static',
)
# List of finder classes that know how to find static files in
@@ -99,15 +104,14 @@ TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.request"
)
-MIDDLEWARE_CLASSES = (
+MIDDLEWARE = [
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
- # Uncomment the next line for simple clickjacking protection:
- # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-)
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
ROOT_URLCONF = 'cbmi.urls'
@@ -120,6 +124,23 @@ TEMPLATE_DIRS = (
# Don't forget to use absolute paths, not relative paths.
)
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'builtins': [],
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
@@ -230,5 +251,5 @@ LOGIN_URL = '/account/login/'
try:
from local_settings import *
-except ImportError, e:
- print 'Unable to load local_settings.py:', e
+except ImportError as e:
+ print('Unable to load local_settings.py:', e)
diff --git a/cbmi/urls.py b/cbmi/urls.py
index 418b1ed..d0b2516 100644
--- a/cbmi/urls.py
+++ b/cbmi/urls.py
@@ -1,17 +1,18 @@
-from django.conf.urls import patterns, include, url
+from django.conf.urls import include, url
from django.contrib import admin
+from account.views import hammertime, landingpage
admin.autodiscover()
-urlpatterns = patterns('',
- url(r'^stop/hammertime/$', 'account.views.hammertime', name="hammertime"),
- url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
- url(r'^admin/', include(admin.site.urls)),
+urlpatterns = [
+ url(r'^stop/hammertime/$', hammertime, name="hammertime"),
+ url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+ url(r'^admin/', admin.site.urls),
url(r'^cbapi/', include("cbapi_ldap.urls")),
url(r'account/', include('account.urls')),
- url(r'^$', 'account.views.landingpage', name="landingpage"),
+ url(r'^$', landingpage, name="landingpage"),
-)
+]
diff --git a/pop_members.py b/pop_members.py
index 0c4748a..32e29d8 100644
--- a/pop_members.py
+++ b/pop_members.py
@@ -57,6 +57,6 @@ def populate_members():
for m in sorted(all_members()):
member = LDAPBackend().populate_user(m)
if member:
- print 'Populated: %s' % member
+ print('Populated: %s' % member)
else:
- print 'Not found: %s' % m
+ print('Not found: %s' % m)
diff --git a/requirements.txt b/requirements.txt
index 968eef6..6a95cfd 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,9 @@
-Django==1.8.4
+Django>=1.11.16
#MySQL-python==1.2.5
-django-auth-ldap==1.2.6
-django-json-rpc
-django-crispy-forms==1.5.2
-pycrypto==2.6.1
-smbpasswd==1.0.2
-requests==2.8.0
+django-auth-ldap>=1.7.0
+django-json-rpc>=0.7.2
+django-crispy-forms>=1.7.2
+gunicorn>=19.9.0
+pycrypto>=2.6.1
+passlib
+requests>=2.19.1
diff --git a/smbpasswd.py b/smbpasswd.py
new file mode 100644
index 0000000..41f0d6f
--- /dev/null
+++ b/smbpasswd.py
@@ -0,0 +1,7 @@
+import passlib.hash
+
+def lmhash(s):
+ return passlib.hash.lmhash.encrypt(s).upper()
+
+def nthash(s):
+ return passlib.hash.nthash.encrypt(s).upper()
diff --git a/start b/start
new file mode 100755
index 0000000..9179ec5
--- /dev/null
+++ b/start
@@ -0,0 +1,10 @@
+#! /bin/bash
+
+cd /opt/cbmi
+
+python /opt/cbmi/manage.py makemigrations
+python /opt/cbmi/manage.py migrate
+
+echo "from django.contrib.auth.models import User; User.objects.filter(email='admin@example.com').delete(); User.objects.create_superuser('admin', 'admin@example.com', 'fooderbar23')" | python /opt/cbmi/manage.py shell
+
+python /opt/cbmi/manage.py runserver 0.0.0.0:8000