Skip to content

Commit

Permalink
Merge 28b7109 into ff4179c
Browse files Browse the repository at this point in the history
  • Loading branch information
quamilek committed Oct 17, 2014
2 parents ff4179c + 28b7109 commit e4b51d0
Show file tree
Hide file tree
Showing 9 changed files with 352 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
----------

DEV
~~~

* Added support for regions

2.1.0
~~~~~

Expand Down
76 changes: 74 additions & 2 deletions src/ralph/account/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@
from __future__ import print_function
from __future__ import unicode_literals

from django import forms
from django.contrib import admin
from django.forms.models import (
ModelForm,
BaseModelFormSet,
modelformset_factory,
)
from django.contrib.auth.admin import UserAdmin, GroupAdmin
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext_lazy as _

from lck.django.activitylog.admin import IPInline, UserAgentInline
from lck.django.common.admin import ForeignKeyAutocompleteTabularInline
from lck.django.common.admin import (
ForeignKeyAutocompleteTabularInline,
ModelAdmin,
)
from lck.django.profile.admin import ProfileInlineFormSet
from tastypie.models import ApiKey

from ralph.account.models import BoundPerm, Profile
from ralph.account.models import BoundPerm, Profile, Region


class ProfileInline(admin.StackedInline):
Expand Down Expand Up @@ -67,6 +76,60 @@ class ApiKeyInline(admin.StackedInline):
extra = 0


class RegionInlineFormSet(BaseModelFormSet):

def __init__(self, *args, **kwargs):
self.instance = kwargs.pop('instance')
super(RegionInlineFormSet, self).__init__(*args, **kwargs)

def _construct_form(self, *args, **kwargs):
return super(RegionInlineFormSet, self)._construct_form(
user_instance=self.instance, *args, **kwargs
)


class RegionForm(ModelForm):
assigned = forms.BooleanField(label=_('assigned'), required=False)

def __init__(self, *args, **kwargs):
self.user_instance = kwargs.pop('user_instance', None)
super(RegionForm, self).__init__(*args, **kwargs)
if self.user_instance:
self.fields['assigned'].initial = Region.profile.through.objects.filter( # noqa
region=self.instance,
profile=self.user_instance.profile
).exists()

def save(self, *args, **kwargs):
objects = Region.profile.through.objects
options = {
'profile': self.user_instance.profile,
'region': self.cleaned_data['id'],
}
if self.cleaned_data['assigned']:
objects.create(**options)
else:
objects.filter(**options).delete()


class RegionInline(admin.TabularInline):
formset = RegionInlineFormSet
form = RegionForm
model = Region
readonly_fields = ('name',)
fields = ('name', 'assigned')

def get_formset(self, *args, **kwargs):
return modelformset_factory(
self.model,
extra=0,
exclude=['profile', 'name'],
form=self.form,
formset=self.formset,
max_num=1,
)


class ProfileAdmin(UserAdmin):

def groups_show(self):
Expand All @@ -77,6 +140,7 @@ def groups_show(self):
inlines = [
ProfileInline,
ProfileBoundPermInline,
RegionInline,
ApiKeyInline,
ProfileIPInline,
ProfileUserAgentInline,
Expand Down Expand Up @@ -138,3 +202,11 @@ class CustomGroupAdmin(GroupAdmin):

admin.site.unregister(Group)
admin.site.register(Group, CustomGroupAdmin)


class RegionAdmin(ModelAdmin):
list_display = ('name',)
search_fields = ('name',)
exclude = ['profile']

admin.site.register(Region, RegionAdmin)
6 changes: 6 additions & 0 deletions src/ralph/account/fixtures/initial_data.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Initial regions

- model: account.Region
pk: 1
fields:
name: Default region
195 changes: 195 additions & 0 deletions src/ralph/account/migrations/0005_auto__add_region.py

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion src/ralph/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from dj.choices import Choices
from dj.choices.fields import ChoiceField
from lck.django.activitylog.models import MonitoredActivity
from lck.django.common.models import TimeTrackable, EditorTrackable
from lck.django.common.models import EditorTrackable, Named, TimeTrackable
from lck.django.profile.models import (
BasicInfo,
ActivationSupport,
Expand Down Expand Up @@ -82,6 +82,20 @@ class Perm(Choices):
has_scrooge_access = _("has_scrooge_access")


class Region(Named):
"""Used for distinguishing the origin of the object by region"""

profile = db.ManyToManyField('Profile')

@classmethod
def get_default_region(cls):
obj, created = cls.objects.get_or_create(name=settings.DEFAULT_REGION_NAME)
return obj

def __unicode__(self):
return self.name


class Profile(BasicInfo, ActivationSupport, GravatarSupport,
MonitoredActivity):

Expand All @@ -106,6 +120,14 @@ class Meta:
def __unicode__(self):
return self.nick

def get_regions(self):
regions = self.region_set.all()
if not regions:
regions = Region.objects.filter(
name=settings.DEFAULT_REGION_NAME,
)
return regions

def has_perm(self, perm, obj=None, role=None):
if not self.is_active:
return False
Expand Down Expand Up @@ -182,6 +204,9 @@ def filter_by_perm(self, query, perm):
venture__parent__parent__parent__boundperm__perm=perm.id)
).distinct()

def is_region_granted(self, region):
return self.regions.filter(pk=region.id).exists()


class BoundPerm(TimeTrackable, EditorTrackable):
profile = db.ForeignKey(
Expand Down
32 changes: 32 additions & 0 deletions src/ralph/middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from threading import current_thread

from django.conf import settings

from ralph.account.models import Region


_requests = {}


def get_actual_regions():
thread_name = current_thread().name
if thread_name not in _requests:
return Region.objects.filter(
name=settings.DEFAULT_REGION_NAME,
)
return _requests[thread_name]['regions']


class RegionMiddleware(object):
def process_request(self, request):
if hasattr(request, 'user') and not request.user.is_anonymous():
data = {
'user_id': request.user.id,
'regions': request.user.profile.get_regions(),
}
_requests[current_thread().name] = data

def process_response(self, request, response):
if hasattr(request, 'user') and not request.user.is_anonymous():
_requests.pop(current_thread().name, None)
return response
2 changes: 2 additions & 0 deletions src/ralph/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
'django.contrib.messages.middleware.MessageMiddleware',
'lck.django.activitylog.middleware.ActivityMiddleware',
'lck.django.common.middleware.ForceLanguageCodeMiddleware',
'ralph.middleware.RegionMiddleware',
)
ROOT_URLCONF = 'ralph.urls'
TEMPLATE_DIRS = (CURRENT_DIR + "templates",)
Expand Down Expand Up @@ -754,3 +755,4 @@

# url to page where user requests permission to module (eg. assets)
# REQUEST_PERM_URL = 'http://tickets.office/request/ralph_module/permission'
DEFAULT_REGION_NAME = 'Default region'
3 changes: 3 additions & 0 deletions src/ralph/util/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
from django.views.generic.base import View
from django.http import HttpResponse, HttpResponseBadRequest

from ralph.middleware import RegionMiddleware


class PicklableRequest(object):

Expand Down Expand Up @@ -60,6 +62,7 @@ def get_result(request):
request = copy.deepcopy(request)
SessionMiddleware().process_request(request)
AuthenticationMiddleware().process_request(request)
RegionMiddleware().process_request(request)
view.request = request
return view.get_result(
request, *url_match.args, **url_match.kwargs
Expand Down
10 changes: 9 additions & 1 deletion src/ralph/util/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
from factory.django import DjangoModelFactory
from django.contrib.auth.models import User

from ralph.account.models import Profile
from ralph.account.models import (
Profile,
Region,
)
from ralph.cmdb import models_ci
from ralph.cmdb.tests.utils import CIFactory

Expand Down Expand Up @@ -78,3 +81,8 @@ class ServiceProfitCenterRelationFactory(DjangoModelFactory):
child = factory.SubFactory(ServiceFactory)
type = models_ci.CI_RELATION_TYPES.CONTAINS
readonly = False


class RegionFactory(DjangoModelFactory):
FACTORY_FOR = Region
name = factory.Sequence(lambda n: 'Region #{}'.format(n))

0 comments on commit e4b51d0

Please sign in to comment.