from datetime import datetime, timedelta from django.conf import settings from django.db.models import Q from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound, HttpResponseForbidden, Http404 from django.shortcuts import get_object_or_404 from django.core.urlresolvers import reverse from django.contrib import messages from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required from django.forms import ModelForm from django.forms.extras.widgets import SelectDateWidget from django.views.generic import TemplateView, DetailView, FormView, CreateView, ListView from django.views.generic.detail import BaseDetailView from django.conf import settings from gargoyle import gargoyle from utils import installed, blacklist_values, check_permissions, send_message from eve_api.models import EVEAccount, EVEPlayerCorporation, EVEPlayerCharacter from sso.tasks import update_user_access from hr.forms import RecommendationForm, ApplicationForm, NoteForm, BlacklistUserForm, AdminNoteForm from hr.models import Recommendation, Application, Audit, Blacklist, BlacklistSource from hr.app_defines import * ### General Views class HrIndexView(TemplateView): """ Gives the main HR index page, with various options displayed depending on their access level. """ template_name = 'hr/index.html' def get_context_data(self, **kwargs): context = super(HrIndexView, self).get_context_data(**kwargs) context['is_hr_staff'] = check_permissions(self.request.user) context['can_recommend'] = len(blacklist_values(self.request.user, BLACKLIST_LEVEL_ADVISORY)) == 0 return context ### Application Management class HrViewUserApplications(TemplateView): """ Shows a list of the user's applications in the system """ template_name = 'hr/applications/view_list.html' def get_context_data(self, **kwargs): context = super(HrViewUserApplications, self).get_context_data(**kwargs) context['applications'] = Application.objects.filter(user=self.request.user).order_by('id') return context class HrViewApplication(DetailView): """ View a individual application and related details """ template_name = 'hr/applications/view.html' context_object_name = "app" model = Application slug_field = 'id' def get_context_data(self, **kwargs): context = super(HrViewApplication, self).get_context_data(**kwargs) perm = check_permissions(self.request.user, self.object) if perm == HR_VIEWONLY: context['audit'] = self.object.audit_set.filter(event__in=[AUDIT_EVENT_STATUSCHANGE, AUDIT_EVENT_REJECTION, AUDIT_EVENT_ACCEPTED, AUDIT_EVENT_MESSAGE]) elif perm == HR_ADMIN: context['hrstaff'] = True context['audit'] = self.object.audit_set.all() else: raise Http404 return context class HrAddApplication(FormView): form_class = ApplicationForm def get_form_kwargs(self, **kwargs): kwargs = super(HrAddApplication, self).get_form_kwargs(**kwargs) kwargs['user'] = self.request.user return kwargs def form_valid(self, form): app = Application(user=self.request.user, character=form.cleaned_data['character'], corporation=form.cleaned_data['corporation']) app.save() messages.add_message(self.request, messages.INFO, "Your application to %s has been created." % app.corporation) return HttpResponseRedirect(reverse('hr-viewapplication', args=[app.id])) def get_template_names(self): if len(EVEPlayerCorporation.objects.filter(application_config__is_accepting=True)): return 'hr/applications/add.html' else: return 'hr/applications/noadd.html' ### Recommendation Management class HrViewRecommendations(TemplateView): """ Shows a list of the user's recommendations in the system """ template_name = 'hr/recommendations/view_list.html' def get_context_data(self, **kwargs): context = super(HrViewRecommendations, self).get_context_data(**kwargs) context['recommendations'] = Recommendation.objects.filter(user=self.request.user) return context class HrAddRecommendation(FormView): template_name = 'hr/recommendations/add.html' form_class = RecommendationForm def dispatch(self, request, *args, **kwargs): if len(blacklist_values(request.user, BLACKLIST_LEVEL_ADVISORY)): raise Http404 return super(HrAddRecommendation, self).dispatch(request, *args, **kwargs) def form_valid(self, form): rec = Recommendation(user=self.request.user) rec.user_character = form.cleaned_data['character'] rec.application = form.cleaned_data['application'] rec.save() messages.add_message(self.request, messages.INFO, "Recommendation added to %s's application" % rec.application ) return HttpResponseRedirect(reverse('hr-viewrecommendations')) def get_form_kwargs(self): kwargs = super(HrAddRecommendation, self).get_form_kwargs() kwargs['user'] = self.request.user return kwargs class HrAdminApplications(ListView): model = Application template_name = 'hr/applications/admin/view_list.html' context_object_name = 'apps' def get_queryset(self): if self.request.user.has_perm('hr.can_view_all'): apps = Application.objects.all() elif self.request.user.has_perm('hr.can_view_corp'): apps = Application.objects.filter(corporation__id__in=set(EVEPlayerCharacter.objects.filter(eveaccount__user=self.request.user).values_list('corporation__id', flat=True))) else: apps = Application.objects.none() query = self.request.GET.get('q', None) order = self.request.GET.get('o', 'id') # Filter by the query string if query: apps = apps.filter(character__name__icontains=query) else: apps = apps.filter(status__in=[APPLICATION_STATUS_AWAITINGREVIEW, APPLICATION_STATUS_ACCEPTED, APPLICATION_STATUS_QUERY, APPLICATION_STATUS_FLAGGED]) # If a invalid order as been passed, correct it if not order in ['id', 'corporation__name', 'character__name']: order = 'id' apps = apps.order_by(order) # If we've got a short search string, only get the first 50 if query and len(query) < 3: apps = apps[:50] return apps class HrUpdateApplication(BaseDetailView): """ Updates the status of a application if the workflow and permissions allow so. """ model = Application slug_field = 'id' def render_to_response(self, context): status = self.kwargs.get('status', None) if status and int(status) in APPLICATION_STATUS_ROUTES[self.object.status]: perm = check_permissions(self.request.user, self.object) if perm == HR_ADMIN or (perm == HR_VIEWONLY and int(status) <= 1): if not self.object.status == status: self.object.status = status self.object.save(user=self.request.user) self.object = self.model.objects.get(pk=self.object.pk) messages.add_message(self.request, messages.INFO, "Application %s has been changed to %s" % (self.object.id, self.object.get_status_display())) else: messages.add_message(self.request, messages.ERROR, "Invalid status change request") return HttpResponseRedirect(reverse('hr-viewapplication', args=[self.object.id])) class HrAddNote(CreateView): """ View to add a note to a application """ template_name = 'hr/applications/add_note.html' form_class = NoteForm model = Audit def dispatch(self, request, *args, **kwargs): if not check_permissions(request.user) == HR_ADMIN: return HttpResponseRedirect(reverse('hr-index')) self.application = Application.objects.get(pk=kwargs.get('applicationid')) return super(HrAddNote, self).dispatch(request, *args, **kwargs) def form_valid(self, form): if check_permissions(self.request.user, self.application) == HR_ADMIN: self.object = form.save(commit=False) self.object.event = AUDIT_EVENT_NOTE self.object.application = self.application self.object.user = self.request.user self.object.save() return HttpResponseRedirect(self.get_success_url()) def get_success_url(self): return reverse('hr-viewapplication', args=[self.application.id]) def get_context_data(self, **kwargs): context = super(HrAddNote, self).get_context_data(**kwargs) context['application'] = self.application return context class HrAddMessage(HrAddNote): template_name = 'hr/applications/add_message.html' def dispatch(self, request, *args, **kwargs): self.application = Application.objects.get(pk=kwargs.get('applicationid')) self.perm = check_permissions(request.user, self.application) if self.perm == HR_NONE: return HttpResponseRedirect(reverse('hr-index')) return CreateView.dispatch(self, request, *args, **kwargs) def get_form_class(self): if self.perm == HR_ADMIN: return AdminNoteForm else: return NoteForm def get_form_kwargs(self): kwargs = super(HrAddMessage, self).get_form_kwargs() if self.perm == HR_ADMIN: kwargs['application'] = self.application return kwargs def form_valid(self, form): self.object = form.save(commit=False) self.object.application = self.application self.object.event = AUDIT_EVENT_MESSAGE self.object.user = self.request.user self.object.save() if not self.application.user == self.request.user: try: send_message(self.application, 'message', note=self.object.text) except: pass return HttpResponseRedirect(self.get_success_url()) class HrRejectApplication(CreateView): template_name = 'hr/applications/reject.html' message_template_name = 'rejected' form_class = AdminNoteForm model = Audit application_change_status = APPLICATION_STATUS_REJECTED audit_event_type = AUDIT_EVENT_REJECTION def dispatch(self, request, *args, **kwargs): self.application = get_object_or_404(Application, pk=kwargs.get('applicationid')) if not (check_permissions(request.user) == HR_ADMIN and request.user.has_perm('hr.can_accept')): return HttpResponseRedirect(reverse('hr-index')) return super(HrRejectApplication, self).dispatch(request, *args, **kwargs) def get_form_kwargs(self): kwargs = super(HrRejectApplication, self).get_form_kwargs() kwargs['application'] = self.application return kwargs def get_context_data(self, **kwargs): context = super(HrRejectApplication, self).get_context_data(**kwargs) context['application'] = self.application return context def form_valid(self, form): self.object = form.save(commit=False) self.object.application = self.application self.object.user = self.request.user self.object.event = self.audit_event_type self.object.save() self.object.application.status = self.application_change_status self.object.application.save(user=self.request.user) try: send_message(self.object.application, self.message_template_name, note=self.object.text) except: pass return HttpResponseRedirect(self.get_success_url()) def get_success_url(self): return reverse('hr-viewapplication', args=[self.application.id]) class HrAcceptApplication(HrRejectApplication): template_name = 'hr/applications/accept.html' message_template_name = 'accepted' application_change_status = APPLICATION_STATUS_ACCEPTED audit_event_type = AUDIT_EVENT_ACCEPTED def dispatch(self, request, *args, **kwargs): app = get_object_or_404(Application, pk=kwargs.get('applicationid')) if app.blacklisted: messages.add_message(request, messages.INFO, "This application has one or more blacklist entries and cannot be accepted.") return HttpResponseRedirect(reverse('hr-viewapplication', args=[app.id])) return super(HrAcceptApplication, self).dispatch(request, *args, **kwargs) class HrBlacklistUser(FormView): template_name = 'hr/blacklist/blacklist.html' form_class = BlacklistUserForm def dispatch(self, request, *args, **kwargs): if request.user.has_perm('hr.add_blacklist'): self.blacklist_user = get_object_or_404(User, id=kwargs.get('userid')) return super(HrBlacklistUser, self).dispatch(request, *args, **kwargs) else: raise Http404 def get_context_data(self, **kwargs): context = super(HrBlacklistUser, self).get_context_data(**kwargs) context['blacklistuser'] = self.blacklist_user return context def blacklist_item(self, type, value): Blacklist(type=type, value=value, level=self.level, source=self.source, expiry_date=self.expiry, created_by=self.request.user, reason=self.reason).save() def form_valid(self, form): self.source = BlacklistSource.objects.get(id=1) self.expiry = form.cleaned_data.get('expiry_date', None) if not self.expiry: self.expiry = datetime.utcnow() + timedelta(days=50*365) # 50 year default self.level = form.cleaned_data.get('level', 0) self.reason = form.cleaned_data.get('reason', 'No reason provided') # Blacklist email address self.blacklist_item(BLACKLIST_TYPE_EMAIL, self.blacklist_user.email) # Blacklist API keys for account in self.blacklist_user.eveaccount_set.all(): self.blacklist_item(BLACKLIST_TYPE_APIUSERID, account.api_user_id) # Blacklist Characters for character in EVEPlayerCharacter.objects.filter(eveaccount__user=self.blacklist_user).distinct(): self.blacklist_item(BLACKLIST_TYPE_CHARACTER, character.name) # Blacklist Reddit accounts if installed('reddit'): for account in self.blacklist_user.redditaccount_set.all(): self.blacklist_item(BLACKLIST_TYPE_REDDIT, account.username) messages.add_message(self.request, messages.INFO, "User %s has been blacklisted" % self.blacklist_user.username ) # Disable the account if requested if form.cleaned_data.get('disable', None): self.blacklist_user.active = False self.blacklist_user.save() messages.add_message(self.request, messages.INFO, "User %s disabled" % self.blacklist_user.username) update_user_access.delay(user=self.blacklist_user.id) return HttpResponseRedirect(reverse('sso.views.user_view', args=[self.blacklist_user.username])) class HrBlacklistList(ListView): model = Blacklist allow_empty = True paginate_by = 25 def get_queryset(self): obj_list = self.model.objects.all() self.query = self.request.GET.get('q', None) self.order = self.request.GET.get('o', 'id') # Filter by the query string if self.query: obj_list = obj_list.filter(Q(value__icontains=self.query) | Q(reason__icontains=self.query)) # If a invalid order as been passed, correct it if not self.order in ['id', 'type', 'value', 'reason', 'expiry_date']: self.order = 'id' return obj_list.order_by(self.order) def get_context_data(self, **kwargs): context = super(HrBlacklistList, self).get_context_data(**kwargs) context['query'] = self.query context['order'] = self.order return context class HrAddBlacklist(CreateView): model = Blacklist template_name = 'hr/blacklist_add.html' def dispatch(self, request, *args, **kwargs): if not request.user.has_perm('hr.add_blacklist'): return HttpResponseForbidden() return super(HrAddBlacklist, self).dispatch(request, *args, **kwargs) def get_form_class(self): class AddBlacklistForm(ModelForm): class Meta: model = Blacklist exclude = ('source', 'created_by') widgets = {'expiry_date': SelectDateWidget()} return AddBlacklistForm def form_valid(self, form): obj = form.save(commit=False) obj.user = self.request.user obj.source, created = BlacklistSource.objects.get_or_create(id=getattr(settings, 'BLACKLIST_DEFAULT_SOURCE', 1)) obj.save() return HttpResponseRedirect(self.get_success_url()) def get_success_url(self): return reverse('hr-blacklist-list')