diff --git a/sso/admin.py b/sso/admin.py index 550415d..eaace52 100644 --- a/sso/admin.py +++ b/sso/admin.py @@ -3,37 +3,37 @@ from django.contrib.auth.models import User from django.contrib.auth.admin import UserAdmin from sso.models import Service, ServiceAccount, SSOUser, SSOUserNote + class ServiceAdmin(admin.ModelAdmin): list_display = ('name', 'url', 'api', 'active') search_fields = ['name'] list_filter = ('active',) -admin.site.register(Service, ServiceAdmin) class ServiceAccountAdmin(admin.ModelAdmin): list_display = ('service', 'service_uid', 'user', 'active') search_fields = ['service_uid', 'user__username'] list_filter = ('service', 'active') -admin.site.register(ServiceAccount, ServiceAccountAdmin) - class SSOUserProfileInline(admin.StackedInline): model = SSOUser fk_name = 'user' max_num = 1 + # Define a new UserAdmin class class SSOUserAdmin(UserAdmin): inlines = [SSOUserProfileInline, ] -# Re-register UserAdmin -admin.site.unregister(User) -admin.site.register(User, SSOUserAdmin) class SSOUserNoteAdmin(admin.ModelAdmin): list_display = ('user', 'note', 'date_created', 'created_by') search_fields = ['user__username'] -admin.site.register(SSOUserNote, SSOUserNoteAdmin) +admin.site.register(Service, ServiceAdmin) +admin.site.register(ServiceAccount, ServiceAccountAdmin) +admin.site.unregister(User) +admin.site.register(User, SSOUserAdmin) +admin.site.register(SSOUserNote, SSOUserNoteAdmin) diff --git a/sso/backends.py b/sso/backends.py index 5fb04f1..796c058 100644 --- a/sso/backends.py +++ b/sso/backends.py @@ -21,4 +21,3 @@ class SimpleHashModelBackend(ModelBackend): return user return None - diff --git a/sso/forms.py b/sso/forms.py index 1e6ba3b..de93d83 100644 --- a/sso/forms.py +++ b/sso/forms.py @@ -10,10 +10,11 @@ from eve_api.models import EVEAccount, EVEPlayerCharacter, EVEPlayerCorporation from sso.models import ServiceAccount, Service from registration.forms import RegistrationForm + class RegistrationFormUniqueEmailBlocked(RegistrationForm): """ - Subclass of ``RegistrationForm`` which disallows registration from certain domains - and also makes sure that the email address is unique in the DB + Subclass of ``RegistrationForm`` which disallows registration from certain + domains and also makes sure that the email address is unique in the DB """ def clean_email(self): @@ -35,8 +36,8 @@ class RegistrationFormUniqueEmailBlocked(RegistrationForm): class EveAPIForm(forms.Form): """ EVE API input form """ - user_id = forms.IntegerField(label = u'User ID') - api_key = forms.CharField(label = u'API Key', max_length=64) + user_id = forms.IntegerField(label=u'User ID') + api_key = forms.CharField(label=u'API Key', max_length=64) description = forms.CharField(max_length=100, required=False) def clean(self): @@ -58,7 +59,7 @@ class EveAPIForm(forms.Form): def UserServiceAccountForm(user): """ Generate a Service Account form based on the user's permissions """ - services = Service.objects.filter(groups__in=user.groups.all(),active=1).exclude(id__in=ServiceAccount.objects.filter(user=user).values('service')).distinct() + services = Service.objects.filter(groups__in=user.groups.all(), active=1).exclude(id__in=ServiceAccount.objects.filter(user=user).values('service')).distinct() chars = EVEPlayerCharacter.objects.filter(eveaccount__user=user) class ServiceAccountForm(forms.Form): @@ -70,7 +71,7 @@ def UserServiceAccountForm(user): def __init__(self, *args, **kwargs): super(ServiceAccountForm, self).__init__(*args, **kwargs) if not settings.GENERATE_SERVICE_PASSWORD: - self.password = forms.CharField(widget=forms.PasswordInput, label="Password" ) + self.password = forms.CharField(widget=forms.PasswordInput, label="Password") self.fields['password'] = self.password def clean(self): @@ -101,32 +102,35 @@ def UserServiceAccountForm(user): class ServiceAccountResetForm(forms.Form): + """ Password reset form for Services """ + def __init__(self, *args, **kwargs): super(ServiceAccountResetForm, self).__init__(*args, **kwargs) if not settings.GENERATE_SERVICE_PASSWORD: - self.password = forms.CharField(widget=forms.PasswordInput, label="Password" ) + self.password = forms.CharField(widget=forms.PasswordInput, label="Password") self.fields['password'] = self.password class UserLookupForm(forms.Form): """ User Lookup Form """ - choices = [ (1, "Auth Username"), - (2, "Character"), - (4, "Email Address"), ] + choices = [(1, "Auth Username"), + (2, "Character"), + (4, "Email Address"), ] def __init__(self, *args, **kwargs): super(UserLookupForm, self).__init__(*args, **kwargs) - choices = [ (1, "Auth Username"), - (2, "Character"), - (4, "Email Address"), ] + choices = [(1, "Auth Username"), + (2, "Character"), + (4, "Email Address"), ] if installed('reddit'): choices.append((3, "Reddit ID")) self.fields['type'] = forms.ChoiceField(label=u'Search type', choices=choices) - self.fields['username'] = forms.CharField(label = u'User ID', max_length=64) + self.fields['username'] = forms.CharField(label=u'User ID', max_length=64) + class APIPasswordForm(forms.Form): + """ API Password reset form """ - password = forms.CharField(widget=forms.PasswordInput, label="Password" ) - + password = forms.CharField(widget=forms.PasswordInput, label="Password") diff --git a/sso/models.py b/sso/models.py index 3ef53c9..39205a8 100644 --- a/sso/models.py +++ b/sso/models.py @@ -15,16 +15,18 @@ from services import get_api ## Exceptions + class CorporateOnlyService(Exception): pass + class ExistingUser(Exception): pass + class ServiceError(Exception): pass -## Models class SSOUser(models.Model): """ Extended SSO User Profile options """ @@ -37,12 +39,13 @@ class SSOUser(models.Model): return self.user.__unicode__() @staticmethod - def create_user_profile(sender, instance, created, **kwargs): - if created: - profile, created = SSOUser.objects.get_or_create(user=instance) + def create_user_profile(sender, instance, created, **kwargs): + if created: + profile, created = SSOUser.objects.get_or_create(user=instance) signals.post_save.connect(SSOUser.create_user_profile, sender=User) + class SSOUserNote(models.Model): """ Notes bound to a user's account. Used to store information regarding the user """ @@ -154,7 +157,7 @@ class ServiceAccount(models.Model): models.Model.save(self) @staticmethod - def pre_delete_listener( **kwargs ): + def pre_delete_listener(**kwargs): if not kwargs['instance'].service.api_class.delete_user(kwargs['instance'].service_uid): raise ServiceError('Unable to delete account on related service') diff --git a/sso/tasks.py b/sso/tasks.py index 3da4bb1..7bb123a 100644 --- a/sso/tasks.py +++ b/sso/tasks.py @@ -4,6 +4,7 @@ from sso.models import ServiceAccount from django.contrib.auth.models import User from django.db.models import signals + # Signals that the tasks need to listen for def eveapi_deleted(sender, instance, **kwargs): if instance.user: @@ -14,7 +15,10 @@ signals.post_delete.connect(eveapi_deleted, sender=EVEAccount) @task() def update_user_access(user, **kwargs): - """ Process all corporate and alliance entries and correct access groups """ + """ + Process all corporate and alliance entries and correct + access groups. + """ user = User.objects.get(id=user) @@ -30,7 +34,7 @@ def update_user_access(user, **kwargs): # Create a list of Char groups chargroups = [] for eacc in EVEAccount.objects.filter(user=user): - if eacc.api_status in [1,3]: + if eacc.api_status in [1, 3]: for char in eacc.characters.all(): if char.corporation.group: chargroups.append(char.corporation.group) @@ -71,6 +75,7 @@ def update_user_access(user, **kwargs): update_service_groups.delay(user_id=user.id) + @task(ignore_result=True) def update_service_groups(user_id): for service in ServiceAccount.objects.filter(user=user_id, active=True).select_related('service__api'): diff --git a/sso/views.py b/sso/views.py index 3f52744..7ec9f8c 100644 --- a/sso/views.py +++ b/sso/views.py @@ -31,6 +31,7 @@ def index(request): else: return render_to_response('sso/index.html', context_instance=RequestContext(request)) + @login_required def profile(request): """ Displays the user's profile page """ @@ -44,6 +45,7 @@ def profile(request): return render_to_response('sso/profile.html', locals(), context_instance=RequestContext(request)) + @login_required def characters(request, charid=0): """ Provide a list of characters, or a indivdual character sheet """ @@ -56,12 +58,13 @@ def characters(request, charid=0): characters = EVEPlayerCharacter.objects.select_related('corporation', 'corporation__alliance').filter(eveaccount__user=request.user).only('id', 'name', 'corporation__name', 'corporation__alliance__name') return render_to_response('sso/characterlist.html', locals(), context_instance=RequestContext(request)) + @login_required def eveapi_add(request): """ Add a EVE API key to a user's account """ - if request.method == 'POST': - form = EveAPIForm(request.POST) + if request.method == 'POST': + form = EveAPIForm(request.POST) if form.is_valid(): task = import_apikey.delay(api_key=form.cleaned_data['api_key'], api_userid=form.cleaned_data['user_id'], user=request.user.id) @@ -69,7 +72,7 @@ def eveapi_add(request): task.wait(5) except celery.exceptions.TimeoutError: messages.add_message(request, messages.INFO, "The addition of your API key is still processing, please check back in a minute or so") - pass + pass else: messages.add_message(request, messages.INFO, "EVE API successfully added.") @@ -79,11 +82,12 @@ def eveapi_add(request): return render_to_response('sso/eveapi.html', locals(), context_instance=RequestContext(request)) + @login_required def eveapi_del(request, userid=0): """ Delete a EVE API key from a account """ - if userid > 0 : + if userid > 0: try: acc = EVEAccount.objects.get(id=userid) except EVEAccount.DoesNotExist: @@ -94,11 +98,12 @@ def eveapi_del(request, userid=0): return redirect('sso.views.profile') + @login_required def eveapi_refresh(request, userid=0): """ Force refresh a EVE API key """ - if userid > 0 : + if userid > 0: try: acc = EVEAccount.objects.get(id=userid) except EVEAccount.DoesNotExist: @@ -114,14 +119,15 @@ def eveapi_refresh(request, userid=0): acc = EVEAccount.objects.get(id=userid) return HttpResponse(serializers.serialize('json', [acc]), mimetype='application/javascript') else: - messages.add_message(request, messages.INFO,"Key %s has been queued to be refreshed from the API" % acc.api_user_id) + messages.add_message(request, messages.INFO, "Key %s has been queued to be refreshed from the API" % acc.api_user_id) return redirect('sso.views.profile') + @login_required def eveapi_log(request, userid=0): """ Provides a list of access logs for a specific EVE API key """ - if userid > 0 : + if userid > 0: try: acc = EVEAccount.objects.get(id=userid) except: @@ -133,14 +139,15 @@ def eveapi_log(request, userid=0): return redirect('sso.views.profile') + @login_required def service_add(request): """ Add a service to a user's account """ clsform = UserServiceAccountForm(request.user) - if request.method == 'POST': - form = clsform(request.POST) + if request.method == 'POST': + form = clsform(request.POST) if form.is_valid(): acc = ServiceAccount(user=request.user, service=form.cleaned_data['service']) @@ -174,16 +181,17 @@ def service_add(request): availserv = Service.objects.filter(groups__in=request.user.groups.all()).exclude(id__in=ServiceAccount.objects.filter(user=request.user).values('service')) if len(availserv) == 0: return render_to_response('sso/serviceaccount/noneavailable.html', locals(), context_instance=RequestContext(request)) - else: + else: form = clsform() # An unbound form return render_to_response('sso/serviceaccount/index.html', locals()) + @login_required def service_del(request, serviceid=0): """ Delete a service from a user's account """ - if serviceid > 0 : + if serviceid > 0: try: acc = ServiceAccount.objects.get(id=serviceid) except ServiceAccount.DoesNotExist: @@ -205,11 +213,12 @@ def service_del(request, serviceid=0): return redirect('sso.views.profile') + @login_required def service_reset(request, serviceid=0): """ Reset a user's password on a service """ - if serviceid > 0 : + if serviceid > 0: try: acc = ServiceAccount.objects.get(id=serviceid) except ServiceAccount.DoesNotExist: @@ -240,17 +249,18 @@ def service_reset(request, serviceid=0): return redirect('sso.views.profile') + @login_required def user_view(request, username=None): """ View a user's profile as a admin """ if username: - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - return redirect('sso.views.user_lookup') + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + return redirect('sso.views.user_lookup') else: - return redirect('sso.views.user_lookup') + return redirect('sso.views.user_lookup') profile = user.get_profile() is_admin = request.user.is_staff @@ -260,6 +270,7 @@ def user_view(request, username=None): return render_to_response('sso/lookup/user.html', locals(), context_instance=RequestContext(request)) + @login_required def user_lookup(request): """ Lookup a user's account by providing a matching criteria """ @@ -275,12 +286,14 @@ def user_lookup(request): users = User.objects.filter(username__icontains=form.cleaned_data['username']).only('username') elif form.cleaned_data['type'] == '2': uid = EVEAccount.objects.filter(characters__name__icontains=form.cleaned_data['username']).values('user') - for u in uid: uids.append(u['user']) + for u in uid: + uids.append(u['user']) users = User.objects.filter(id__in=uids).only('username') elif installed('reddit') and form.cleaned_data['type'] == '3': from reddit.models import RedditAccount uid = RedditAccount.objects.filter(username__icontains=form.cleaned_data['username']).values('user') - for u in uid: uids.append(u['user']) + for u in uid: + uids.append(u['user']) users = User.objects.filter(id__in=uids).only('username') elif form.cleaned_data['type'] == '4': users = User.objects.filter(email__icontains=form.cleaned_data['username']).only('username') @@ -295,7 +308,7 @@ def user_lookup(request): else: messages.add_message(request, messages.INFO, "No results found") return redirect('sso.views.user_lookup') - + return render_to_response('sso/lookup/userlookup.html', locals(), context_instance=RequestContext(request)) @@ -315,4 +328,3 @@ def set_apipasswd(request): form = APIPasswordForm() # An unbound form return render_to_response('sso/apipassword.html', locals(), context_instance=RequestContext(request)) -