diff options
author | maxbr <maxbr@mi.fu-berlin.de> | 2016-08-19 17:10:31 +0200 |
---|---|---|
committer | maxbr <maxbr@mi.fu-berlin.de> | 2016-08-19 17:10:31 +0200 |
commit | 79aec84973032e15ae9d36fcbd7d7d42af3283d1 (patch) | |
tree | c02fbd44cd53b0eed105bc648c743b10c62bfeb4 /pharos-dashboard/account | |
parent | 639cd5db77064c275253828780c17ae59551d95c (diff) |
Split the dashboard into different apps, add tests
JIRA: RELENG-12
Signed-off-by: maxbr <maxbr@mi.fu-berlin.de>
Diffstat (limited to 'pharos-dashboard/account')
18 files changed, 376 insertions, 0 deletions
diff --git a/pharos-dashboard/account/__init__.py b/pharos-dashboard/account/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pharos-dashboard/account/__init__.py diff --git a/pharos-dashboard/account/admin.py b/pharos-dashboard/account/admin.py new file mode 100644 index 0000000..7fab123 --- /dev/null +++ b/pharos-dashboard/account/admin.py @@ -0,0 +1,5 @@ +from django.contrib import admin + +from account.models import UserProfile + +admin.site.register(UserProfile)
\ No newline at end of file diff --git a/pharos-dashboard/account/apps.py b/pharos-dashboard/account/apps.py new file mode 100644 index 0000000..999566c --- /dev/null +++ b/pharos-dashboard/account/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class AccountsConfig(AppConfig): + name = 'account' diff --git a/pharos-dashboard/account/forms.py b/pharos-dashboard/account/forms.py new file mode 100644 index 0000000..7893867 --- /dev/null +++ b/pharos-dashboard/account/forms.py @@ -0,0 +1,17 @@ +import django.forms as forms +import pytz as pytz + +from registration.forms import RegistrationForm as BaseRegistrationForm + + +class AccountSettingsForm(forms.Form): + fields = ['first_name', 'last_name', 'email', 'company', 'ssh_public_key', 'pgp_public_key', + 'timezone'] + + first_name = forms.CharField(max_length=30) + last_name = forms.CharField(max_length=30) + email = forms.EmailField() + company = forms.CharField(max_length=30) + ssh_public_key = forms.CharField(max_length=2048, widget=forms.Textarea) + pgp_public_key = forms.CharField(max_length=2048, widget=forms.Textarea) + timezone = forms.ChoiceField(choices=[(x, x) for x in pytz.common_timezones], initial='UTC')
\ No newline at end of file diff --git a/pharos-dashboard/account/middleware.py b/pharos-dashboard/account/middleware.py new file mode 100644 index 0000000..f5170ba --- /dev/null +++ b/pharos-dashboard/account/middleware.py @@ -0,0 +1,15 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.utils import timezone +from django.utils.deprecation import MiddlewareMixin + + +class TimezoneMiddleware(MiddlewareMixin): + """ + Activate the timezone from request.user.userprofile if user is authenticated, + deactivate the timezone otherwise and use default (UTC) + """ + def process_request(self, request): + if request.user.is_authenticated: + timezone.activate(request.user.userprofile.timezone) + else: + timezone.deactivate() diff --git a/pharos-dashboard/account/migrations/0001_initial.py b/pharos-dashboard/account/migrations/0001_initial.py new file mode 100644 index 0000000..752d517 --- /dev/null +++ b/pharos-dashboard/account/migrations/0001_initial.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-12 09:51 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('dashboard', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('sshkey', models.CharField(max_length=1024)), + ('company', models.CharField(max_length=200)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'user_profile', + }, + ), + migrations.CreateModel( + name='UserResource', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dashboard.Resource')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'user_resource', + }, + ), + ] diff --git a/pharos-dashboard/account/migrations/0002_userprofile_timezone.py b/pharos-dashboard/account/migrations/0002_userprofile_timezone.py new file mode 100644 index 0000000..ea67598 --- /dev/null +++ b/pharos-dashboard/account/migrations/0002_userprofile_timezone.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-12 13:17 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='timezone', + field=models.CharField(default='UTC', max_length=100), + ), + ] diff --git a/pharos-dashboard/account/migrations/0003_userprofile_registration_complete.py b/pharos-dashboard/account/migrations/0003_userprofile_registration_complete.py new file mode 100644 index 0000000..d611443 --- /dev/null +++ b/pharos-dashboard/account/migrations/0003_userprofile_registration_complete.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-12 17:09 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0002_userprofile_timezone'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='registration_complete', + field=models.BooleanField(default=False), + ), + ] diff --git a/pharos-dashboard/account/migrations/0004_auto_20160812_1805.py b/pharos-dashboard/account/migrations/0004_auto_20160812_1805.py new file mode 100644 index 0000000..cb22855 --- /dev/null +++ b/pharos-dashboard/account/migrations/0004_auto_20160812_1805.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-12 18:05 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0003_userprofile_registration_complete'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='gpgkey', + field=models.CharField(default='a', max_length=2048), + preserve_default=False, + ), + migrations.AlterField( + model_name='userprofile', + name='sshkey', + field=models.CharField(max_length=2048), + ), + ] diff --git a/pharos-dashboard/account/migrations/0005_remove_userprofile_registration_complete.py b/pharos-dashboard/account/migrations/0005_remove_userprofile_registration_complete.py new file mode 100644 index 0000000..fa4bf72 --- /dev/null +++ b/pharos-dashboard/account/migrations/0005_remove_userprofile_registration_complete.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-13 10:49 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0004_auto_20160812_1805'), + ] + + operations = [ + migrations.RemoveField( + model_name='userprofile', + name='registration_complete', + ), + ] diff --git a/pharos-dashboard/account/migrations/0006_auto_20160813_1443.py b/pharos-dashboard/account/migrations/0006_auto_20160813_1443.py new file mode 100644 index 0000000..7d9cd58 --- /dev/null +++ b/pharos-dashboard/account/migrations/0006_auto_20160813_1443.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-13 14:43 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0005_remove_userprofile_registration_complete'), + ] + + operations = [ + migrations.RemoveField( + model_name='userresource', + name='resource', + ), + migrations.RemoveField( + model_name='userresource', + name='user', + ), + migrations.DeleteModel( + name='UserResource', + ), + ] diff --git a/pharos-dashboard/account/migrations/0007_auto_20160814_1056.py b/pharos-dashboard/account/migrations/0007_auto_20160814_1056.py new file mode 100644 index 0000000..2d1bbae --- /dev/null +++ b/pharos-dashboard/account/migrations/0007_auto_20160814_1056.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-08-14 10:56 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0006_auto_20160813_1443'), + ] + + operations = [ + migrations.RenameField( + model_name='userprofile', + old_name='gpgkey', + new_name='pgpkey', + ), + ] diff --git a/pharos-dashboard/account/migrations/__init__.py b/pharos-dashboard/account/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pharos-dashboard/account/migrations/__init__.py diff --git a/pharos-dashboard/account/models.py b/pharos-dashboard/account/models.py new file mode 100644 index 0000000..5181c71 --- /dev/null +++ b/pharos-dashboard/account/models.py @@ -0,0 +1,16 @@ +from django.db import models + +from django.contrib.auth.models import User + +from dashboard.models import Resource + + +class UserProfile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + timezone = models.CharField(max_length=100, blank=False, default='UTC') + sshkey = models.CharField(max_length=2048, blank=False) + pgpkey = models.CharField(max_length=2048, blank=False) + company = models.CharField(max_length=200, blank=False) + + class Meta: + db_table = 'user_profile' diff --git a/pharos-dashboard/account/tests/__init__.py b/pharos-dashboard/account/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pharos-dashboard/account/tests/__init__.py diff --git a/pharos-dashboard/account/tests/test_general.py b/pharos-dashboard/account/tests/test_general.py new file mode 100644 index 0000000..ba80b62 --- /dev/null +++ b/pharos-dashboard/account/tests/test_general.py @@ -0,0 +1,40 @@ +from django.contrib.auth.models import User +from django.test import Client +from django.test import TestCase +from django.urls import reverse +from django.utils import timezone + +from account.models import UserProfile + + +class AccountMiddlewareTestCase(TestCase): + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username='user1') + self.user1.set_password('user1') + self.user1profile = UserProfile.objects.create(user=self.user1) + self.user1.save() + + def test_timezone_middleware(self): + """ + The timezone should be UTC for anonymous users, for authenticated users it should be set + to user.userprofile.timezone + """ + #default + self.assertEqual(timezone.get_current_timezone_name(), 'UTC') + + url = reverse('account:settings') + # anonymous request + self.client.get(url) + self.assertEqual(timezone.get_current_timezone_name(), 'UTC') + + # authenticated user with UTC timezone (userprofile default) + self.client.login(username='user1', password='user1') + self.client.get(url) + self.assertEqual(timezone.get_current_timezone_name(), 'UTC') + + # authenticated user with custom timezone (userprofile default) + self.user1profile.timezone = 'Etc/Greenwich' + self.user1profile.save() + self.client.get(url) + self.assertEqual(timezone.get_current_timezone_name(), 'Etc/Greenwich') diff --git a/pharos-dashboard/account/urls.py b/pharos-dashboard/account/urls.py new file mode 100644 index 0000000..5d68135 --- /dev/null +++ b/pharos-dashboard/account/urls.py @@ -0,0 +1,26 @@ +"""pharos_dashboard URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.10/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url +from django.contrib.auth import views as auth_views + +from account.views import * + +urlpatterns = [ + url(r'^login/$', auth_views.login, name='login'), + url(r'^logout/$', auth_views.logout, name='logout'), + url(r'^register/', RegistrationView.as_view(), name='registration'), + url(r'^settings/', AccountSettingsView.as_view(), name='settings'), +] diff --git a/pharos-dashboard/account/views.py b/pharos-dashboard/account/views.py new file mode 100644 index 0000000..3432867 --- /dev/null +++ b/pharos-dashboard/account/views.py @@ -0,0 +1,78 @@ +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.core.exceptions import ObjectDoesNotExist +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.views.generic import FormView +from registration.backends.simple.views import RegistrationView as BaseRegistrationView + +from account.forms import AccountSettingsForm +from account.models import UserProfile + + +class RegistrationView(BaseRegistrationView): + template_name = 'registration/registration_form.html' + + def get_context_data(self, **kwargs): + context = super(RegistrationView, self).get_context_data(**kwargs) + context.update({'title': "Registration"}) + return context + + def register(self, form): + new_user = super(RegistrationView, self).register(form) + UserProfile.objects.create(user=new_user) + messages.add_message(self.request, messages.INFO, 'Please complete your user profile.') + return new_user + + def get_success_url(self, user): + return reverse('account:settings') + + +@method_decorator(login_required, name='dispatch') +class AccountSettingsView(FormView): + form_class = AccountSettingsForm + template_name = 'registration/registration_form.html' + success_url = '/' + + def dispatch(self, request, *args, **kwargs): + try: + request.user.userprofile + except ObjectDoesNotExist: + UserProfile.objects.create(user=request.user) + messages.add_message(self.request, messages.INFO, + 'Please complete your user profile to proceed.') + return super(AccountSettingsView, self).dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super(AccountSettingsView, self).get_context_data(**kwargs) + context.update({'title': "Settings"}) + return context + + def get_initial(self): + user = self.request.user + initial = super(AccountSettingsView, self).get_initial() + initial['first_name'] = user.first_name + initial['last_name'] = user.last_name + initial['email'] = user.email + initial['company'] = user.userprofile.company + initial['ssh_public_key'] = user.userprofile.sshkey + initial['pgp_public_key'] = user.userprofile.pgpkey + initial['timezone'] = user.userprofile.timezone + return initial + + def form_valid(self, form): + user = self.request.user + user.first_name = form.cleaned_data['first_name'] + user.last_name = form.cleaned_data['last_name'] + user.email = form.cleaned_data['email'] + user.userprofile.company = form.cleaned_data['company'] + user.userprofile.sshkey = form.cleaned_data['ssh_public_key'] + user.userprofile.pgpkey = form.cleaned_data['pgp_public_key'] + user.userprofile.timezone = form.cleaned_data['timezone'] + user.userprofile.save() + if not user.is_active: + user.is_active = True + user.save() + messages.add_message(self.request, messages.INFO, + 'Settings saved') + return super(AccountSettingsView, self).form_valid(form) |