diff --git a/euscanwww/djeuscan/admin.py b/euscanwww/djeuscan/admin.py index 800fefc..5ecc512 100644 --- a/euscanwww/djeuscan/admin.py +++ b/euscanwww/djeuscan/admin.py @@ -1,6 +1,6 @@ from djeuscan.models import Package, Version, VersionLog, EuscanResult, \ Log, WorldLog, CategoryLog, HerdLog, MaintainerLog, Herd, Maintainer, \ - RefreshPackageQuery, Category, Overlay, ProblemReport, UserProfile + RefreshPackageQuery, Category, Overlay, ProblemReport from django.contrib import admin @@ -37,8 +37,6 @@ class ProblemReportAdmin(admin.ModelAdmin): ordering = ["-datetime"] -admin.site.register(UserProfile) - admin.site.register(Package, PackageAdmin) admin.site.register(Herd, HerdAdmin) diff --git a/euscanwww/djeuscan/feeds.py b/euscanwww/djeuscan/feeds.py index f1e2094..59b8e05 100644 --- a/euscanwww/djeuscan/feeds.py +++ b/euscanwww/djeuscan/feeds.py @@ -9,7 +9,8 @@ from django.db.models import Q from euscan.version import gentoo_unstable from djeuscan.models import Package, Herd, Maintainer, VersionLog -from djeuscan.helpers import get_profile, get_account_versionlogs + +from euscan_accounts.helpers import get_profile class BaseFeed(Feed): @@ -217,30 +218,6 @@ class CategoryFeed(BaseFeed): return VersionLog.objects.for_category(data["obj"]), 100 -class UserFeed(BaseFeed): - link = "/" - - def description(self, data): - return "%s - last euscan changes" % data["user"] - - def title(self, data): - return "%s - watched packages" % data["user"] - - def get_object(self, request): - return { - "user": request.user, - "options": request.GET, - } - - def _items(self, data): - user = data["user"] - - profile = get_profile(user) - vlogs = get_account_versionlogs(profile) - - return vlogs, 100 - - class WorldScanFeed(BaseFeed): link = "/" diff --git a/euscanwww/djeuscan/forms.py b/euscanwww/djeuscan/forms.py index 95f4717..a1c6f65 100644 --- a/euscanwww/djeuscan/forms.py +++ b/euscanwww/djeuscan/forms.py @@ -1,6 +1,5 @@ from django import forms - -from djeuscan.models import Version, ProblemReport, UserProfile +from djeuscan.models import Version, ProblemReport class WorldForm(forms.Form): @@ -27,39 +26,3 @@ class ProblemReportForm(forms.ModelForm): class Meta: model = ProblemReport fields = ('version', 'subject', 'message') - - -class PreferencesForm(forms.Form): - first_name = forms.CharField(max_length=30, required=False) - last_name = forms.CharField(max_length=30, required=False) - email = forms.EmailField() - - feed_upstream_info = forms.BooleanField(required=False, - label="Upstream info") - feed_portage_info = forms.BooleanField(required=False, - label="Portage info") - feed_show_adds = forms.BooleanField(required=False, - label="Show version bumps") - feed_show_removals = forms.BooleanField(required=False, - label="Show version removals") - feed_ignore_pre = forms.BooleanField(required=False, - label="Ignore unstable releases") - feed_ignore_pre_if_stable = forms.BooleanField( - required=False, - label="Ignore unstable releases if current version is stable" - ) - - email_activated = forms.BooleanField( - required=False, label="Receive euscan emails" - ) - email_every = forms.ChoiceField( - choices=UserProfile.EMAIL_OPTS, - label="Send email", - ) - email_ignore_pre = forms.BooleanField( - required=False, label="Ignore unstable releases" - ) - email_ignore_pre_if_stable = forms.BooleanField( - required=False, - label="Ignore unstable releases if current version is stable" - ) diff --git a/euscanwww/djeuscan/helpers.py b/euscanwww/djeuscan/helpers.py index d46fcaf..d5426eb 100644 --- a/euscanwww/djeuscan/helpers.py +++ b/euscanwww/djeuscan/helpers.py @@ -3,7 +3,7 @@ djeuscan.helpers """ from distutils.version import StrictVersion, LooseVersion -from django.db.models import Q +from django.shortcuts import get_object_or_404 def xint(i): @@ -77,81 +77,9 @@ class catch_and_return(object): return wrapper -def get_profile(user): - from djeuscan.models import UserProfile - try: - return user.get_profile() - except UserProfile.DoesNotExist: - UserProfile.objects.create(user=user) - return user.get_profile() - - -def get_account_categories(user): - from djeuscan.models import Package - # TODO: This is quite ugly - category_names = [obj.name for obj in get_profile(user).categories.all()] - return [c for c in Package.objects.categories() - if c["category"] in category_names] - - -def get_account_herds(user): - from djeuscan.models import Package - - ids = [herd.pk for herd in get_profile(user).herds.all()] - return Package.objects.herds(ids=ids) - - -def get_account_maintainers(user): - from djeuscan.models import Package - - ids = [obj.pk for obj in get_profile(user).maintainers.all()] - return Package.objects.maintainers(ids=ids) - - -def get_account_versionlogs(profile): - """ - Returns all watched packages - """ - from djeuscan.models import Package, VersionLog - - q_categories = Q(category__in=[ - category.name for category in profile.categories.all()]) - q_herds = Q(herds__in=profile.herds.all()) - q_maintainers = Q(maintainers__in=profile.maintainers.all()) - packages = list(profile.packages.all()) + list(Package.objects.filter( - q_categories | q_herds | q_maintainers)) - - overlays = [o.name for o in profile.overlays.all()] - - return VersionLog.objects.filter( - Q(package__in=packages) | Q(overlay__in=overlays) - ) - - -def get_user_fav_infos(user): - upstream_k = lambda c: c["n_versions"] - c["n_packaged"] - c["n_overlay"] - - categories = sorted(get_account_categories(user), - key=upstream_k, reverse=True) - c_upstream = sum([upstream_k(c) for c in categories]) - herds = sorted(get_account_herds(user), - key=upstream_k, reverse=True) - h_upstream = sum([upstream_k(c) for c in herds]) - maintainers = sorted(get_account_maintainers(user), - key=upstream_k, reverse=True) - m_upstream = sum([upstream_k(c) for c in maintainers]) - packages = sorted( - get_profile(user).packages.all(), - key=lambda p: p.n_versions - p.n_packaged - p.n_overlay, - reverse=True - ) - p_upstream = sum( - [c.n_versions - c.n_packaged - c.n_overlay for c in packages] - ) - - return { - "categories": categories, "categories_upstream": c_upstream, - "herds": herds, "herds_upstream": h_upstream, - "maintainers": maintainers, "maintainers_upstream": m_upstream, - "packages": packages, "packages_upstream": p_upstream, - } +def get_maintainer_or_404(id=None, email=None): + from djeuscan.models import Maintainer + if id: + return get_object_or_404(Maintainer, pk=id) + else: + return get_object_or_404(Maintainer, email=email) diff --git a/euscanwww/djeuscan/models.py b/euscanwww/djeuscan/models.py index a328522..a09c3e3 100644 --- a/euscanwww/djeuscan/models.py +++ b/euscanwww/djeuscan/models.py @@ -265,37 +265,6 @@ class Overlay(models.Model): return self.name -class UserProfile(models.Model): - EMAIL_SCAN = 1 - EMAIL_WEEKLY = 2 - EMAIL_MONTHLY = 3 - EMAIL_OPTS = ( - (EMAIL_SCAN, 'On updates'), - (EMAIL_WEEKLY, 'Weekly'), - (EMAIL_MONTHLY, 'Monthly') - ) - - user = models.OneToOneField(User) - herds = models.ManyToManyField(Herd) - maintainers = models.ManyToManyField(Maintainer) - packages = models.ManyToManyField(Package) - categories = models.ManyToManyField(Category) - overlays = models.ManyToManyField(Overlay) - - feed_upstream_info = models.BooleanField(default=True) - feed_portage_info = models.BooleanField(default=False) - feed_show_adds = models.BooleanField(default=True) - feed_show_removals = models.BooleanField(default=True) - feed_ignore_pre = models.BooleanField(default=False) - feed_ignore_pre_if_stable = models.BooleanField(default=False) - - email_activated = models.BooleanField(default=True) - email_every = models.IntegerField(choices=EMAIL_OPTS, default=EMAIL_SCAN) - email_ignore_pre = models.BooleanField(default=False) - email_ignore_pre_if_stable = models.BooleanField(default=False) - last_email = models.DateTimeField(auto_now_add=True) - - class Log(models.Model): """ Model used for keeping data for charts diff --git a/euscanwww/djeuscan/tasks.py b/euscanwww/djeuscan/tasks.py index 769e4af..b0b4413 100644 --- a/euscanwww/djeuscan/tasks.py +++ b/euscanwww/djeuscan/tasks.py @@ -15,10 +15,11 @@ from django.db.models import Q from euscan.version import gentoo_unstable -from djeuscan.models import Package, RefreshPackageQuery, UserProfile, \ - VersionLog +from djeuscan.models import Package, RefreshPackageQuery, VersionLog from djeuscan.processing import scan, misc -from djeuscan.helpers import get_account_versionlogs, get_user_fav_infos + +from euscan_accounts.helpers import get_account_versionlogs, get_user_fav_infos +from euscan_accounts.models import UserProfile class TaskFailedException(Exception): diff --git a/euscanwww/djeuscan/tests/test_views.py b/euscanwww/djeuscan/tests/test_views.py index 5cf55c2..4917d9d 100644 --- a/euscanwww/djeuscan/tests/test_views.py +++ b/euscanwww/djeuscan/tests/test_views.py @@ -5,7 +5,7 @@ try: except ImportError: from bs4 import BeautifulSoup -from djeuscan.helpers import get_profile +from euscan_accounts.helpers import get_profile from djeuscan.tests import SystemTestCase from djeuscan.tests.euscan_factory import PackageFactory, setup_maintainers, \ diff --git a/euscanwww/djeuscan/urls.py b/euscanwww/djeuscan/urls.py index a9add71..ded690f 100644 --- a/euscanwww/djeuscan/urls.py +++ b/euscanwww/djeuscan/urls.py @@ -1,14 +1,16 @@ from django.conf.urls.defaults import url, patterns, include from django.contrib.auth.decorators import user_passes_test -from django.contrib.auth.views import logout -from django.views.generic import RedirectView -from django.contrib.auth.decorators import login_required from djcelery.views import apply as apply_task from djeuscan.views import registered_tasks +from euscan_accounts.views import favourite_package, unfavourite_package, \ + favourite_category, unfavourite_category, favourite_herd, \ + unfavourite_herd, favourite_maintainer, unfavourite_maintainer, \ + favourite_overlay, unfavourite_overlay, favourite_world, unfavourite_world + from djeuscan.feeds import PackageFeed, CategoryFeed, HerdFeed, \ - MaintainerFeed, GlobalFeed, UserFeed, WorldScanFeed + MaintainerFeed, GlobalFeed, WorldScanFeed admin_required = user_passes_test(lambda u: u.is_superuser) @@ -17,8 +19,8 @@ admin_required = user_passes_test(lambda u: u.is_superuser) package_patterns = patterns('djeuscan.views', url(r'^$', 'package', name="package"), url(r'^feed/$', PackageFeed(), name='package_feed'), - url(r'^favourite/$', 'favourite_package', name="favourite_package"), - url(r'^unfavourite/$', 'unfavourite_package', name="unfavourite_package"), + url(r'^favourite/$', favourite_package, name="favourite_package"), + url(r'^unfavourite/$', unfavourite_package, name="unfavourite_package"), url(r'^refresh$', "refresh_package", name="refresh_package"), url(r'^problem$', 'problem', name="problem"), ) @@ -28,8 +30,8 @@ categories_patterns = patterns('djeuscan.views', url(r'^feed/$', CategoryFeed(), name='category_feed'), url(r'^charts/(?P[\w\-]+).png$', 'chart_category', name="chart_category"), - url(r'^favourite/$', 'favourite_category', name="favourite_category"), - url(r'^unfavourite/$', 'unfavourite_category', + url(r'^favourite/$', favourite_category, name="favourite_category"), + url(r'^unfavourite/$', unfavourite_category, name="unfavourite_category"), ) @@ -37,8 +39,8 @@ herds_patterns = patterns('djeuscan.views', url(r'^(?:view/)?$', 'herd', name="herd"), url(r'^feed/$', HerdFeed(), name='herd_feed'), url(r'^charts/(?P[\w\-]+).png$', 'chart_herd', name="chart_herd"), - url(r'^favourite/$', 'favourite_herd', name="favourite_herd"), - url(r'^unfavourite/$', 'unfavourite_herd', name="unfavourite_herd"), + url(r'^favourite/$', favourite_herd, name="favourite_herd"), + url(r'^unfavourite/$', unfavourite_herd, name="unfavourite_herd"), ) maintainers_patterns = patterns('djeuscan.views', @@ -46,15 +48,15 @@ maintainers_patterns = patterns('djeuscan.views', url(r'^feed/$', MaintainerFeed(), name='maintainer_feed'), url(r'^charts/(?P[\w\-]+).png$', 'chart_maintainer', name="chart_maintainer"), - url(r'^favourite/$', 'favourite_maintainer', name="favourite_maintainer"), - url(r'^unfavourite/$', 'unfavourite_maintainer', + url(r'^favourite/$', favourite_maintainer, name="favourite_maintainer"), + url(r'^unfavourite/$', unfavourite_maintainer, name="unfavourite_maintainer"), ) overlays_patterns = patterns('djeuscan.views', url(r'^(?:view/)?$', 'overlay', name="overlay"), - url(r'^favourite/$', 'favourite_overlay', name="favourite_overlay"), - url(r'^unfavourite/$', 'unfavourite_overlay', name="unfavourite_overlay"), + url(r'^favourite/$', favourite_overlay, name="favourite_overlay"), + url(r'^unfavourite/$', unfavourite_overlay, name="unfavourite_overlay"), ) tasks_patterns = patterns('djeuscan.views', @@ -64,25 +66,6 @@ tasks_patterns = patterns('djeuscan.views', name="apply_task"), ) -accounts_patterns = patterns('djeuscan.views', - url(r'^profile/$', 'accounts_index', name="accounts_index"), - url(r'^profile/preferences/$', 'accounts_preferences', - name="accounts_preferences"), - url(r'^categories/$', 'accounts_categories', name="accounts_categories"), - url(r'^herds/$', 'accounts_herds', name="accounts_herds"), - url(r'^maintainers/$', 'accounts_maintainers', - name="accounts_maintainers"), - url(r'^packages/$', 'accounts_packages', name="accounts_packages"), - url(r'^overlays/$', 'accounts_overlays', name="accounts_overlays"), - - url(r'^feed/$', login_required(UserFeed()), name='user_feed'), - - url(r'^logout/$', logout, {'next_page': '/'}), - - url(r'^password/change/done/$', - RedirectView.as_view(url="../../../profile/")), -) - urlpatterns = patterns('djeuscan.views', # Global stuff @@ -99,8 +82,8 @@ urlpatterns = patterns('djeuscan.views', url(r'^world/$', 'world', name="world"), url(r'^world/scan/$', 'world_scan', name="world_scan"), url(r'^world/scan/feed$', WorldScanFeed(), name="world_scan_feed"), - url(r'^world/favourite/$', 'favourite_world', name="favourite_world"), - url(r'^world/unfavourite/$', 'unfavourite_world', + url(r'^world/favourite/$', favourite_world, name="favourite_world"), + url(r'^world/unfavourite/$', unfavourite_world, name="unfavourite_world"), # Real data @@ -124,5 +107,4 @@ urlpatterns = patterns('djeuscan.views', include(package_patterns)), url(r'^tasks/', include(tasks_patterns)), - url(r'^accounts/', include(accounts_patterns)), ) diff --git a/euscanwww/djeuscan/views.py b/euscanwww/djeuscan/views.py index 05c8c21..3a7df88 100644 --- a/euscanwww/djeuscan/views.py +++ b/euscanwww/djeuscan/views.py @@ -8,17 +8,16 @@ from django.shortcuts import get_object_or_404 from django.contrib.auth.decorators import login_required from django.views.decorators.http import require_POST -from djeuscan.helpers import version_key, packages_from_names, get_profile, \ - get_account_categories, get_account_herds, get_account_maintainers, \ - get_user_fav_infos -from djeuscan.feeds import UserFeed +from djeuscan.helpers import version_key, packages_from_names, \ + get_maintainer_or_404 from djeuscan.models import Version, Package, Herd, Maintainer, EuscanResult, \ VersionLog, RefreshPackageQuery, ProblemReport, Category, Overlay -from djeuscan.forms import WorldForm, PackagesForm, ProblemReportForm, \ - PreferencesForm +from djeuscan.forms import WorldForm, PackagesForm, ProblemReportForm from djeuscan.tasks import admin_tasks from djeuscan import charts +from euscan_accounts.helpers import get_profile + @render_to('euscan/index.html') def index(request): @@ -122,13 +121,6 @@ def maintainers(request): return {'maintainers': maintainers, 'last_scan': last_scan} -def get_maintainer_or_404(id=None, email=None): - if id: - return get_object_or_404(Maintainer, pk=id) - else: - return get_object_or_404(Maintainer, email=email) - - @render_to('euscan/maintainer.html') def maintainer(request, maintainer_id=None, maintainer_email=None): maintainer = get_maintainer_or_404(maintainer_id, maintainer_email) @@ -422,211 +414,3 @@ def refresh_package(request, category, package): from djeuscan.tasks import consume_refresh_queue consume_refresh_queue.delay() return {"result": "success", "position": obj.position} - - -@login_required -@render_to('euscan/accounts/index.html') -def accounts_index(request): - user = request.user - - infos = get_user_fav_infos(user) - infos['vlog'] = UserFeed().items({'user': user, 'options': {}}) - - return infos - - -@login_required -@render_to('euscan/accounts/preferences.html') -def accounts_preferences(request): - user = request.user - prof = get_profile(user) - - updated = False - if request.method == "POST": - form = PreferencesForm(request.POST) - if form.is_valid(): - user.first_name = form.cleaned_data["first_name"] - user.last_name = form.cleaned_data["last_name"] - user.email = form.cleaned_data["email"] - user.save(force_update=True) - - prof.feed_upstream_info = form.cleaned_data["feed_upstream_info"] - prof.feed_portage_info = form.cleaned_data["feed_portage_info"] - prof.feed_show_adds = form.cleaned_data["feed_show_adds"] - prof.feed_show_removals = form.cleaned_data["feed_show_removals"] - prof.feed_ignore_pre = form.cleaned_data["feed_ignore_pre"] - prof.feed_ignore_pre_if_stable = \ - form.cleaned_data["feed_ignore_pre_if_stable"] - - prof.email_activated = form.cleaned_data["email_activated"] - prof.email_every = form.cleaned_data["email_every"] - prof.email_ignore_pre = form.cleaned_data["email_ignore_pre"] - prof.email_ignore_pre_if_stable = \ - form.cleaned_data["email_ignore_pre_if_stable"] - - prof.save(force_update=True) - - updated = True - else: - initial_data = { - "first_name": user.first_name, - "last_name": user.last_name, - "email": user.email, - "feed_upstream_info": prof.feed_upstream_info, - "feed_portage_info": prof.feed_portage_info, - "feed_show_adds": prof.feed_show_adds, - "feed_show_removals": prof.feed_show_removals, - "feed_ignore_pre": prof.feed_ignore_pre, - "feed_ignore_pre_if_stable": prof.feed_ignore_pre_if_stable, - "email_activated": prof.email_activated, - "email_every": prof.email_every, - "email_ignore_pre": prof.email_ignore_pre, - "email_ignore_pre_if_stable": prof.email_ignore_pre_if_stable, - } - form = PreferencesForm(initial_data) - return {"form": form, "updated": updated} - - -@login_required -@render_to('euscan/accounts/categories.html') -def accounts_categories(request): - return {"categories": get_account_categories(request.user)} - - -@login_required -@render_to('euscan/accounts/herds.html') -def accounts_herds(request): - return {"herds": get_account_herds(request.user)} - - -@login_required -@render_to('euscan/accounts/maintainers.html') -def accounts_maintainers(request): - return {"maintainers": get_account_maintainers(request.user)} - - -@login_required -@render_to('euscan/accounts/packages.html') -def accounts_packages(request): - return {"packages": get_profile(request.user).packages.all()} - - -@login_required -@render_to('euscan/accounts/overlays.html') -def accounts_overlays(request): - overlays = [obj.name for obj in get_profile(request.user).overlays.all()] - return {"overlays": overlays} - - -@login_required -@require_POST -@ajax_request -def favourite_package(request, category, package): - obj = get_object_or_404(Package, category=category, name=package) - get_profile(request.user).packages.add(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def unfavourite_package(request, category, package): - package = get_object_or_404(Package, category=category, name=package) - get_profile(request.user).packages.remove(package) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def favourite_herd(request, herd): - obj = get_object_or_404(Herd, herd=herd) - get_profile(request.user).herds.add(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def unfavourite_herd(request, herd): - herd = get_object_or_404(Herd, herd=herd) - get_profile(request.user).herds.remove(herd) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def favourite_maintainer(request, maintainer_id=None, maintainer_email=None): - obj = get_maintainer_or_404(maintainer_id, maintainer_email) - get_profile(request.user).maintainers.add(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def unfavourite_maintainer(request, maintainer_id=None, maintainer_email=None): - obj = get_maintainer_or_404(maintainer_id, maintainer_email) - get_profile(request.user).maintainers.remove(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def favourite_category(request, category): - obj = Category.objects.get(name=category) - get_profile(request.user).categories.add(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def unfavourite_category(request, category): - obj = Category.objects.get(name=category) - get_profile(request.user).categories.remove(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def favourite_overlay(request, overlay): - obj = Overlay.objects.get(name=overlay) - get_profile(request.user).overlays.add(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def unfavourite_overlay(request, overlay): - obj = Overlay.objects.get(name=overlay) - get_profile(request.user).overlays.remove(obj) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def favourite_world(request): - if not "packages[]" in request.POST: - return {"success": False} - packages = request.POST.getlist("packages[]") - objs = Package.objects.filter(id__in=packages) - get_profile(request.user).packages.add(*objs) - return {"success": True} - - -@login_required -@require_POST -@ajax_request -def unfavourite_world(request): - if not "packages[]" in request.POST: - return {"success": False} - packages = request.POST.getlist("packages[]") - objs = Package.objects.filter(id__in=packages) - get_profile(request.user).packages.remove(*objs) - return {"success": True} diff --git a/euscanwww/euscan_accounts/__init__.py b/euscanwww/euscan_accounts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/euscanwww/euscan_accounts/admin.py b/euscanwww/euscan_accounts/admin.py new file mode 100644 index 0000000..453650a --- /dev/null +++ b/euscanwww/euscan_accounts/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from euscan_accounts.models import UserProfile + +admin.site.register(UserProfile) diff --git a/euscanwww/euscan_accounts/feeds.py b/euscanwww/euscan_accounts/feeds.py new file mode 100644 index 0000000..9a70b80 --- /dev/null +++ b/euscanwww/euscan_accounts/feeds.py @@ -0,0 +1,26 @@ +from djeuscan.feeds import BaseFeed +from euscan_accounts.helpers import get_profile, get_account_versionlogs + + +class UserFeed(BaseFeed): + link = "/" + + def description(self, data): + return "%s - last euscan changes" % data["user"] + + def title(self, data): + return "%s - watched packages" % data["user"] + + def get_object(self, request): + return { + "user": request.user, + "options": request.GET, + } + + def _items(self, data): + user = data["user"] + + profile = get_profile(user) + vlogs = get_account_versionlogs(profile) + + return vlogs, 100 diff --git a/euscanwww/euscan_accounts/forms.py b/euscanwww/euscan_accounts/forms.py new file mode 100644 index 0000000..620448d --- /dev/null +++ b/euscanwww/euscan_accounts/forms.py @@ -0,0 +1,38 @@ +from django import forms +from euscan_accounts.models import UserProfile + + +class PreferencesForm(forms.Form): + first_name = forms.CharField(max_length=30, required=False) + last_name = forms.CharField(max_length=30, required=False) + email = forms.EmailField() + + feed_upstream_info = forms.BooleanField(required=False, + label="Upstream info") + feed_portage_info = forms.BooleanField(required=False, + label="Portage info") + feed_show_adds = forms.BooleanField(required=False, + label="Show version bumps") + feed_show_removals = forms.BooleanField(required=False, + label="Show version removals") + feed_ignore_pre = forms.BooleanField(required=False, + label="Ignore unstable releases") + feed_ignore_pre_if_stable = forms.BooleanField( + required=False, + label="Ignore unstable releases if current version is stable" + ) + + email_activated = forms.BooleanField( + required=False, label="Receive euscan emails" + ) + email_every = forms.ChoiceField( + choices=UserProfile.EMAIL_OPTS, + label="Send email", + ) + email_ignore_pre = forms.BooleanField( + required=False, label="Ignore unstable releases" + ) + email_ignore_pre_if_stable = forms.BooleanField( + required=False, + label="Ignore unstable releases if current version is stable" + ) diff --git a/euscanwww/euscan_accounts/helpers.py b/euscanwww/euscan_accounts/helpers.py new file mode 100644 index 0000000..7422ab9 --- /dev/null +++ b/euscanwww/euscan_accounts/helpers.py @@ -0,0 +1,81 @@ +from django.db.models import Q + + +def get_profile(user): + from euscan_accounts.models import UserProfile + try: + return user.get_profile() + except UserProfile.DoesNotExist: + UserProfile.objects.create(user=user) + return user.get_profile() + + +def get_account_categories(user): + from djeuscan.models import Package + # TODO: This is quite ugly + category_names = [obj.name for obj in get_profile(user).categories.all()] + return [c for c in Package.objects.categories() + if c["category"] in category_names] + + +def get_account_herds(user): + from djeuscan.models import Package + + ids = [herd.pk for herd in get_profile(user).herds.all()] + return Package.objects.herds(ids=ids) + + +def get_account_maintainers(user): + from djeuscan.models import Package + + ids = [obj.pk for obj in get_profile(user).maintainers.all()] + return Package.objects.maintainers(ids=ids) + + +def get_account_versionlogs(profile): + """ + Returns all watched packages + """ + from djeuscan.models import Package, VersionLog + + q_categories = Q(category__in=[ + category.name for category in profile.categories.all()]) + q_herds = Q(herds__in=profile.herds.all()) + q_maintainers = Q(maintainers__in=profile.maintainers.all()) + packages = list(profile.packages.all()) + list(Package.objects.filter( + q_categories | q_herds | q_maintainers)) + + overlays = [o.name for o in profile.overlays.all()] + + return VersionLog.objects.filter( + Q(package__in=packages) | Q(overlay__in=overlays) + ) + + +def get_user_fav_infos(user): + upstream_k = lambda c: c["n_versions"] - c["n_packaged"] - c["n_overlay"] + + categories = sorted(get_account_categories(user), + key=upstream_k, reverse=True) + c_upstream = sum([upstream_k(c) for c in categories]) + herds = sorted(get_account_herds(user), + key=upstream_k, reverse=True) + h_upstream = sum([upstream_k(c) for c in herds]) + maintainers = sorted(get_account_maintainers(user), + key=upstream_k, reverse=True) + m_upstream = sum([upstream_k(c) for c in maintainers]) + packages = sorted( + get_profile(user).packages.all(), + key=lambda p: p.n_versions - p.n_packaged - p.n_overlay, + reverse=True + ) + p_upstream = sum( + [c.n_versions - c.n_packaged - c.n_overlay for c in packages] + ) + + return { + "categories": categories, "categories_upstream": c_upstream, + "herds": herds, "herds_upstream": h_upstream, + "maintainers": maintainers, "maintainers_upstream": m_upstream, + "packages": packages, "packages_upstream": p_upstream, + } diff --git a/euscanwww/euscan_accounts/migrations/0001_initial.py b/euscanwww/euscan_accounts/migrations/0001_initial.py new file mode 100644 index 0000000..dd7ab8c --- /dev/null +++ b/euscanwww/euscan_accounts/migrations/0001_initial.py @@ -0,0 +1,204 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'UserProfile' + db.create_table('euscan_accounts_userprofile', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)), + ('feed_upstream_info', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('feed_portage_info', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('feed_show_adds', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('feed_show_removals', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('feed_ignore_pre', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('feed_ignore_pre_if_stable', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('email_activated', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('email_every', self.gf('django.db.models.fields.IntegerField')(default=1)), + ('email_ignore_pre', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('email_ignore_pre_if_stable', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('last_email', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + )) + db.send_create_signal('euscan_accounts', ['UserProfile']) + + # Adding M2M table for field herds on 'UserProfile' + db.create_table('euscan_accounts_userprofile_herds', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)), + ('herd', models.ForeignKey(orm['djeuscan.herd'], null=False)) + )) + db.create_unique('euscan_accounts_userprofile_herds', ['userprofile_id', 'herd_id']) + + # Adding M2M table for field maintainers on 'UserProfile' + db.create_table('euscan_accounts_userprofile_maintainers', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)), + ('maintainer', models.ForeignKey(orm['djeuscan.maintainer'], null=False)) + )) + db.create_unique('euscan_accounts_userprofile_maintainers', ['userprofile_id', 'maintainer_id']) + + # Adding M2M table for field packages on 'UserProfile' + db.create_table('euscan_accounts_userprofile_packages', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)), + ('package', models.ForeignKey(orm['djeuscan.package'], null=False)) + )) + db.create_unique('euscan_accounts_userprofile_packages', ['userprofile_id', 'package_id']) + + # Adding M2M table for field categories on 'UserProfile' + db.create_table('euscan_accounts_userprofile_categories', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)), + ('category', models.ForeignKey(orm['djeuscan.category'], null=False)) + )) + db.create_unique('euscan_accounts_userprofile_categories', ['userprofile_id', 'category_id']) + + # Adding M2M table for field overlays on 'UserProfile' + db.create_table('euscan_accounts_userprofile_overlays', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)), + ('overlay', models.ForeignKey(orm['djeuscan.overlay'], null=False)) + )) + db.create_unique('euscan_accounts_userprofile_overlays', ['userprofile_id', 'overlay_id']) + + def backwards(self, orm): + # Deleting model 'UserProfile' + db.delete_table('euscan_accounts_userprofile') + + # Removing M2M table for field herds on 'UserProfile' + db.delete_table('euscan_accounts_userprofile_herds') + + # Removing M2M table for field maintainers on 'UserProfile' + db.delete_table('euscan_accounts_userprofile_maintainers') + + # Removing M2M table for field packages on 'UserProfile' + db.delete_table('euscan_accounts_userprofile_packages') + + # Removing M2M table for field categories on 'UserProfile' + db.delete_table('euscan_accounts_userprofile_categories') + + # Removing M2M table for field overlays on 'UserProfile' + db.delete_table('euscan_accounts_userprofile_overlays') + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'djeuscan.category': { + 'Meta': {'object_name': 'Category'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}) + }, + 'djeuscan.herd': { + 'Meta': {'object_name': 'Herd'}, + 'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), + 'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Maintainer']", 'symmetrical': 'False'}) + }, + 'djeuscan.maintainer': { + 'Meta': {'object_name': 'Maintainer'}, + 'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'djeuscan.overlay': { + 'Meta': {'object_name': 'Overlay'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}) + }, + 'djeuscan.package': { + 'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'}, + 'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}), + 'homepage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_version_gentoo': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_version_gentoo'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['djeuscan.Version']"}), + 'last_version_overlay': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_version_overlay'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['djeuscan.Version']"}), + 'last_version_upstream': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_version_upstream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['djeuscan.Version']"}), + 'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}), + 'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'djeuscan.version': { + 'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'}, + 'alive': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'confidence': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'ebuild_path': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'handler': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'metadata_path': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128', 'db_index': 'True', 'blank': 'True'}), + 'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}), + 'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'slot': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), + 'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'vtype': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}) + }, + 'euscan_accounts.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Category']", 'symmetrical': 'False'}), + 'email_activated': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'email_every': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'email_ignore_pre': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_ignore_pre_if_stable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feed_ignore_pre': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feed_ignore_pre_if_stable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feed_portage_info': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feed_show_adds': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'feed_show_removals': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'feed_upstream_info': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Herd']", 'symmetrical': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_email': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Maintainer']", 'symmetrical': 'False'}), + 'overlays': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Overlay']", 'symmetrical': 'False'}), + 'packages': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Package']", 'symmetrical': 'False'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}) + } + } + + complete_apps = ['euscan_accounts'] \ No newline at end of file diff --git a/euscanwww/euscan_accounts/migrations/__init__.py b/euscanwww/euscan_accounts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/euscanwww/euscan_accounts/models.py b/euscanwww/euscan_accounts/models.py new file mode 100644 index 0000000..0d83e15 --- /dev/null +++ b/euscanwww/euscan_accounts/models.py @@ -0,0 +1,35 @@ +from django.db import models +from django.contrib.auth.models import User + +from djeuscan.models import Herd, Maintainer, Package, Category, Overlay + + +class UserProfile(models.Model): + EMAIL_SCAN = 1 + EMAIL_WEEKLY = 2 + EMAIL_MONTHLY = 3 + EMAIL_OPTS = ( + (EMAIL_SCAN, 'On updates'), + (EMAIL_WEEKLY, 'Weekly'), + (EMAIL_MONTHLY, 'Monthly') + ) + + user = models.OneToOneField(User) + herds = models.ManyToManyField(Herd) + maintainers = models.ManyToManyField(Maintainer) + packages = models.ManyToManyField(Package) + categories = models.ManyToManyField(Category) + overlays = models.ManyToManyField(Overlay) + + feed_upstream_info = models.BooleanField(default=True) + feed_portage_info = models.BooleanField(default=False) + feed_show_adds = models.BooleanField(default=True) + feed_show_removals = models.BooleanField(default=True) + feed_ignore_pre = models.BooleanField(default=False) + feed_ignore_pre_if_stable = models.BooleanField(default=False) + + email_activated = models.BooleanField(default=True) + email_every = models.IntegerField(choices=EMAIL_OPTS, default=EMAIL_SCAN) + email_ignore_pre = models.BooleanField(default=False) + email_ignore_pre_if_stable = models.BooleanField(default=False) + last_email = models.DateTimeField(auto_now_add=True) diff --git a/euscanwww/djeuscan/templates/euscan/accounts/categories.html b/euscanwww/euscan_accounts/templates/euscan/accounts/categories.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/categories.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/categories.html diff --git a/euscanwww/djeuscan/templates/euscan/accounts/euscan_email.txt b/euscanwww/euscan_accounts/templates/euscan/accounts/euscan_email.txt similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/euscan_email.txt rename to euscanwww/euscan_accounts/templates/euscan/accounts/euscan_email.txt diff --git a/euscanwww/djeuscan/templates/euscan/accounts/herds.html b/euscanwww/euscan_accounts/templates/euscan/accounts/herds.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/herds.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/herds.html diff --git a/euscanwww/djeuscan/templates/euscan/accounts/index.html b/euscanwww/euscan_accounts/templates/euscan/accounts/index.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/index.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/index.html diff --git a/euscanwww/djeuscan/templates/euscan/accounts/maintainers.html b/euscanwww/euscan_accounts/templates/euscan/accounts/maintainers.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/maintainers.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/maintainers.html diff --git a/euscanwww/djeuscan/templates/euscan/accounts/overlays.html b/euscanwww/euscan_accounts/templates/euscan/accounts/overlays.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/overlays.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/overlays.html diff --git a/euscanwww/djeuscan/templates/euscan/accounts/packages.html b/euscanwww/euscan_accounts/templates/euscan/accounts/packages.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/packages.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/packages.html diff --git a/euscanwww/djeuscan/templates/euscan/accounts/preferences.html b/euscanwww/euscan_accounts/templates/euscan/accounts/preferences.html similarity index 100% rename from euscanwww/djeuscan/templates/euscan/accounts/preferences.html rename to euscanwww/euscan_accounts/templates/euscan/accounts/preferences.html diff --git a/euscanwww/euscan_accounts/tests.py b/euscanwww/euscan_accounts/tests.py new file mode 100644 index 0000000..501deb7 --- /dev/null +++ b/euscanwww/euscan_accounts/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/euscanwww/euscan_accounts/urls.py b/euscanwww/euscan_accounts/urls.py new file mode 100644 index 0000000..0a798cb --- /dev/null +++ b/euscanwww/euscan_accounts/urls.py @@ -0,0 +1,26 @@ +from django.conf.urls import patterns, url +from django.contrib.auth.views import logout +from django.views.generic import RedirectView +from django.contrib.auth.decorators import login_required + +from euscan_accounts.feeds import UserFeed + + +urlpatterns = patterns('euscan_accounts.views', + url(r'^profile/$', 'accounts_index', name="accounts_index"), + url(r'^profile/preferences/$', 'accounts_preferences', + name="accounts_preferences"), + url(r'^categories/$', 'accounts_categories', name="accounts_categories"), + url(r'^herds/$', 'accounts_herds', name="accounts_herds"), + url(r'^maintainers/$', 'accounts_maintainers', + name="accounts_maintainers"), + url(r'^packages/$', 'accounts_packages', name="accounts_packages"), + url(r'^overlays/$', 'accounts_overlays', name="accounts_overlays"), + + url(r'^feed/$', login_required(UserFeed()), name='user_feed'), + + url(r'^logout/$', logout, {'next_page': '/'}), + + url(r'^password/change/done/$', + RedirectView.as_view(url="../../../profile/")), +) diff --git a/euscanwww/euscan_accounts/views.py b/euscanwww/euscan_accounts/views.py new file mode 100644 index 0000000..e80bc04 --- /dev/null +++ b/euscanwww/euscan_accounts/views.py @@ -0,0 +1,221 @@ +from annoying.decorators import render_to, ajax_request + +from django.shortcuts import get_object_or_404 +from django.contrib.auth.decorators import login_required +from django.views.decorators.http import require_POST + +from djeuscan.models import Package, Category, Herd, Overlay +from djeuscan.helpers import get_maintainer_or_404 + +from euscan_accounts.feeds import UserFeed +from euscan_accounts.forms import PreferencesForm +from euscan_accounts.helpers import get_user_fav_infos, get_profile, \ + get_account_categories, get_account_herds, get_account_maintainers + + +@login_required +@render_to('euscan/accounts/index.html') +def accounts_index(request): + user = request.user + + infos = get_user_fav_infos(user) + infos['vlog'] = UserFeed().items({'user': user, 'options': {}}) + + return infos + + +@login_required +@render_to('euscan/accounts/preferences.html') +def accounts_preferences(request): + user = request.user + prof = get_profile(user) + + updated = False + if request.method == "POST": + form = PreferencesForm(request.POST) + if form.is_valid(): + user.first_name = form.cleaned_data["first_name"] + user.last_name = form.cleaned_data["last_name"] + user.email = form.cleaned_data["email"] + user.save(force_update=True) + + prof.feed_upstream_info = form.cleaned_data["feed_upstream_info"] + prof.feed_portage_info = form.cleaned_data["feed_portage_info"] + prof.feed_show_adds = form.cleaned_data["feed_show_adds"] + prof.feed_show_removals = form.cleaned_data["feed_show_removals"] + prof.feed_ignore_pre = form.cleaned_data["feed_ignore_pre"] + prof.feed_ignore_pre_if_stable = \ + form.cleaned_data["feed_ignore_pre_if_stable"] + + prof.email_activated = form.cleaned_data["email_activated"] + prof.email_every = form.cleaned_data["email_every"] + prof.email_ignore_pre = form.cleaned_data["email_ignore_pre"] + prof.email_ignore_pre_if_stable = \ + form.cleaned_data["email_ignore_pre_if_stable"] + + prof.save(force_update=True) + + updated = True + else: + initial_data = { + "first_name": user.first_name, + "last_name": user.last_name, + "email": user.email, + "feed_upstream_info": prof.feed_upstream_info, + "feed_portage_info": prof.feed_portage_info, + "feed_show_adds": prof.feed_show_adds, + "feed_show_removals": prof.feed_show_removals, + "feed_ignore_pre": prof.feed_ignore_pre, + "feed_ignore_pre_if_stable": prof.feed_ignore_pre_if_stable, + "email_activated": prof.email_activated, + "email_every": prof.email_every, + "email_ignore_pre": prof.email_ignore_pre, + "email_ignore_pre_if_stable": prof.email_ignore_pre_if_stable, + } + form = PreferencesForm(initial_data) + return {"form": form, "updated": updated} + + +@login_required +@render_to('euscan/accounts/categories.html') +def accounts_categories(request): + return {"categories": get_account_categories(request.user)} + + +@login_required +@render_to('euscan/accounts/herds.html') +def accounts_herds(request): + return {"herds": get_account_herds(request.user)} + + +@login_required +@render_to('euscan/accounts/maintainers.html') +def accounts_maintainers(request): + return {"maintainers": get_account_maintainers(request.user)} + + +@login_required +@render_to('euscan/accounts/packages.html') +def accounts_packages(request): + return {"packages": get_profile(request.user).packages.all()} + + +@login_required +@render_to('euscan/accounts/overlays.html') +def accounts_overlays(request): + overlays = [obj.name for obj in get_profile(request.user).overlays.all()] + return {"overlays": overlays} + + +@login_required +@require_POST +@ajax_request +def favourite_package(request, category, package): + obj = get_object_or_404(Package, category=category, name=package) + get_profile(request.user).packages.add(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def unfavourite_package(request, category, package): + package = get_object_or_404(Package, category=category, name=package) + get_profile(request.user).packages.remove(package) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def favourite_herd(request, herd): + obj = get_object_or_404(Herd, herd=herd) + get_profile(request.user).herds.add(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def unfavourite_herd(request, herd): + herd = get_object_or_404(Herd, herd=herd) + get_profile(request.user).herds.remove(herd) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def favourite_maintainer(request, maintainer_id=None, maintainer_email=None): + obj = get_maintainer_or_404(maintainer_id, maintainer_email) + get_profile(request.user).maintainers.add(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def unfavourite_maintainer(request, maintainer_id=None, maintainer_email=None): + obj = get_maintainer_or_404(maintainer_id, maintainer_email) + get_profile(request.user).maintainers.remove(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def favourite_category(request, category): + obj = Category.objects.get(name=category) + get_profile(request.user).categories.add(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def unfavourite_category(request, category): + obj = Category.objects.get(name=category) + get_profile(request.user).categories.remove(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def favourite_overlay(request, overlay): + obj = Overlay.objects.get(name=overlay) + get_profile(request.user).overlays.add(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def unfavourite_overlay(request, overlay): + obj = Overlay.objects.get(name=overlay) + get_profile(request.user).overlays.remove(obj) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def favourite_world(request): + if not "packages[]" in request.POST: + return {"success": False} + packages = request.POST.getlist("packages[]") + objs = Package.objects.filter(id__in=packages) + get_profile(request.user).packages.add(*objs) + return {"success": True} + + +@login_required +@require_POST +@ajax_request +def unfavourite_world(request): + if not "packages[]" in request.POST: + return {"success": False} + packages = request.POST.getlist("packages[]") + objs = Package.objects.filter(id__in=packages) + get_profile(request.user).packages.remove(*objs) + return {"success": True} diff --git a/euscanwww/euscanwww/settings.py b/euscanwww/euscanwww/settings.py index 5705c3b..d14b968 100644 --- a/euscanwww/euscanwww/settings.py +++ b/euscanwww/euscanwww/settings.py @@ -159,6 +159,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( INSTALLED_APPS = ( 'euscanwww', 'djeuscan', + 'euscan_accounts', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', @@ -253,7 +254,7 @@ AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', ) -AUTH_PROFILE_MODULE = 'djeuscan.UserProfile' +AUTH_PROFILE_MODULE = 'euscan_accounts.UserProfile' try: from local_settings import * diff --git a/euscanwww/euscanwww/urls.py b/euscanwww/euscanwww/urls.py index a93c3e8..524fe5e 100644 --- a/euscanwww/euscanwww/urls.py +++ b/euscanwww/euscanwww/urls.py @@ -8,6 +8,7 @@ urlpatterns = patterns('', url(r'^', include('djeuscan.urls')), url(r'^admin/', include(admin.site.urls)), + url(r'^accounts/', include('euscan_accounts.urls')), url(r'^accounts/', include('euscan_captcha.urls')), url(r'^accounts/', include('registration.backends.default.urls')), ) diff --git a/euscanwww/runtests.py b/euscanwww/runtests.py index 417fd1d..b22d209 100644 --- a/euscanwww/runtests.py +++ b/euscanwww/runtests.py @@ -16,6 +16,8 @@ settings.configure( INSTALLED_APPS=[ 'euscanwww.euscanwww', 'djeuscan', + 'euscan_accounts', + 'euscan_captcha', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.admin', @@ -29,7 +31,7 @@ settings.configure( USE_TZ=True, TASKS_CONCURRENTLY=8, TASKS_SUBTASK_PACKAGES=32, - AUTH_PROFILE_MODULE="djeuscan.UserProfile", + AUTH_PROFILE_MODULE="euscan_accounts.UserProfile", RECAPTCHA_PUBLIC_KEY="", RECAPTCHA_PRIVATE_KEY="", )