Massive reworking of HR to a class view based system.

This commit is contained in:
2011-09-08 14:42:12 +01:00
parent eaf1989fe9
commit 0b6d97e2f6
18 changed files with 411 additions and 355 deletions

View File

@@ -26,8 +26,8 @@ APPLICATION_STATUS_CHOICES = (
APPLICATION_STATUS_ROUTES = { APPLICATION_STATUS_ROUTES = {
APPLICATION_STATUS_NOTSUBMITTED: [APPLICATION_STATUS_AWAITINGREVIEW], APPLICATION_STATUS_NOTSUBMITTED: [APPLICATION_STATUS_AWAITINGREVIEW],
APPLICATION_STATUS_AWAITINGREVIEW: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_QUERY, APPLICATION_STATUS_FLAGGED], APPLICATION_STATUS_AWAITINGREVIEW: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_QUERY, APPLICATION_STATUS_FLAGGED],
APPLICATION_STATUS_REJECTED: [], APPLICATION_STATUS_REJECTED: [APPLICATION_STATUS_NOTSUBMITTED],
APPLICATION_STATUS_ACCEPTED: [APPLICATION_STATUS_COMPLETED], APPLICATION_STATUS_ACCEPTED: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_COMPLETED],
APPLICATION_STATUS_QUERY: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_FLAGGED], APPLICATION_STATUS_QUERY: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_FLAGGED],
APPLICATION_STATUS_COMPLETED: [], APPLICATION_STATUS_COMPLETED: [],
APPLICATION_STATUS_FLAGGED: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_QUERY], APPLICATION_STATUS_FLAGGED: [APPLICATION_STATUS_NOTSUBMITTED, APPLICATION_STATUS_QUERY],

View File

@@ -4,7 +4,7 @@
{% block content %} {% block content %}
<p>Fill in a note you want to send to the user.</p> <p>Fill in a note you want to send to the user.</p>
<form action="{% url hr.views.accept_application applicationid %}" method="post"> <form action="{% url hr-acceptapplication application.id %}" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
{% csrf_token %} {% csrf_token %}

View File

@@ -5,7 +5,7 @@
{% block content %} {% block content %}
<p>Select the character you wish to apply with, then the corporation you wish to apply for.</p> <p>Select the character you wish to apply with, then the corporation you wish to apply for.</p>
<form action="{% url hr.views.add_application %}" method="post"> <form action="{% url hr-addapplication %}" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
</table> </table>

View File

@@ -3,7 +3,7 @@
{% block title %}Send Message to Applicant{% endblock %} {% block title %}Send Message to Applicant{% endblock %}
{% block content %} {% block content %}
<form action="{% url hr.views.add_message applicationid %}" method="post"> <form action="{% url hr-addmessage application.id %}" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
</table> </table>

View File

@@ -3,7 +3,7 @@
{% block title %}Add Note to Application{% endblock %} {% block title %}Add Note to Application{% endblock %}
{% block content %} {% block content %}
<form action="{% url hr.views.add_note applicationid %}" method="post"> <form action="{% url hr-addnote application.id %}" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
</table> </table>

View File

@@ -5,21 +5,21 @@
{% block content %} {% block content %}
<h1>Search All Applications</h1> <h1>Search All Applications</h1>
<form method="GET" action="{% url hr.views.admin_applications %}"> <form method="GET" action="{% url hr-admin %}">
<input type="text" name="q" /> <input type="text" name="q" />
<input type="submit" value="Search" /> <input type="submit" value="Search" />
</form> </form>
{% if apps %} {% if apps %}
<table> <table>
<tr><th><a href="{% url hr.views.admin_applications %}?o=id">Application ID</a></th> <tr><th><a href="{% url hr-admin %}?o=id">Application ID</a></th>
<th><a href="{% url hr.views.admin_applications %}?o=character__name">Character</a></th> <th><a href="{% url hr-admin %}?o=character__name">Character</a></th>
<th><a href="{% url hr.views.admin_applications %}?o=corporation__name">Corporation</a></th> <th><a href="{% url hr-admin %}?o=corporation__name">Corporation</a></th>
<th>Application Status</th> <th>Application Status</th>
<th>Last Action Date</th> <th>Last Action Date</th>
<th>Last Action User</th></tr> <th>Last Action User</th></tr>
{% for app in apps %} {% for app in apps %}
<tr {% if app.alt_application %}id="alt-application"{% endif %}><td><a href="{% url hr.views.view_application app.id %}">{{ app.id }}</a></td> <tr {% if app.alt_application %}id="alt-application"{% endif %}><td><a href="{% url hr-viewapplication app.id %}">{{ app.id }}</a></td>
<td>{{ app.character }}</td> <td>{{ app.character }}</td>
<td>{{ app.corporation }}</td> <td>{{ app.corporation }}</td>
<td>{{ app.get_status_display }}</td> <td>{{ app.get_status_display }}</td>

View File

@@ -4,7 +4,7 @@
{% block content %} {% block content %}
<p>Fill in the rejection reason below, please note, this will be sent out to the user.</p> <p>Fill in the rejection reason below, please note, this will be sent out to the user.</p>
<form action="{% url hr.views.reject_application applicationid %}" method="post"> <form action="{% url hr-rejectapplication application.id %}" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
</table> </table>

View File

@@ -27,29 +27,29 @@
<div class="skill_controls"> <div class="skill_controls">
<p> <p>
{% if app.status < 1 %} {% if app.status < 1 %}
<a href="{% url hr.views.update_application app.id 1 %}">Submit Application</a> <a href="{% url hr-updateapplication app.id 1 %}">Submit Application</a>
{% else %} {% else %}
<a href="{% url hr.views.update_application app.id 0 %}">Withdraw Application</a> <a href="{% url hr-updateapplication app.id 0 %}">Withdraw Application</a>
{% endif %} {% endif %}
<a href="{% url hr.views.add_message app.id %}">Add Message</a> <a href="{% url hr-addmessage app.id %}">Add Message</a>
{% if hrstaff %} {% if hrstaff %}
<a href="{% url hr.views.add_note app.id %}">Add Staff Note</a> <a href="{% url hr-addnote app.id %}">Add Staff Note</a>
{% if app.status < 2 or app.status = 4 or app.status = 6 %} {% if app.status < 2 or app.status = 4 or app.status = 6 %}
{% if perms.hr.can_accept %} {% if perms.hr.can_accept %}
<a href="{% url hr.views.reject_application app.id %}">Reject Application</a> <a href="{% url hr-rejectapplication app.id %}">Reject Application</a>
{% ifequal app.blacklisted 0 %} {% ifequal app.blacklisted 0 %}
<a href="{% url hr.views.accept_application app.id %}">Accept Application</a> <a href="{% url hr-acceptapplication app.id %}">Accept Application</a>
{% endifequal %} {% endifequal %}
{% endif %} {% endif %}
{% ifnotequal app.status 4 %} {% ifnotequal app.status 4 %}
<a href="{% url hr.views.update_application app.id 4 %}">Mark as In Query</a> <a href="{% url hr-updateapplication app.id 4 %}">Mark as In Query</a>
{% endifnotequal %} {% endifnotequal %}
{% ifnotequal app.status 6 %} {% ifnotequal app.status 6 %}
<a href="{% url hr.views.update_application app.id 6 %}">Flag for Review</a> <a href="{% url hr-updateapplication app.id 6 %}">Flag for Review</a>
{% endifnotequal %} {% endifnotequal %}
{% endif %} {% endif %}
{% ifequal app.status 3 %} {% ifequal app.status 3 %}
<a href="{% url hr.views.update_application app.id 5 %}">Mark as Complete</a> <a href="{% url hr-updateapplication app.id 5 %}">Mark as Complete</a>
{% endifequal %} {% endifequal %}
{% endif %} {% endif %}
</p> </p>
@@ -166,7 +166,7 @@ function createRequestObject() {
var http = createRequestObject(); var http = createRequestObject();
function redditposts(action) { function redditposts(action) {
http.open('get', '{% url hr.views.view_application app.id %}?redditxhr'); http.open('get', '{% url reddit-commentsjson %}?userid={{ app.user.id }}');
http.onreadystatechange = handleResponse; http.onreadystatechange = handleResponse;
http.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); http.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
http.send(null); http.send(null);
@@ -180,11 +180,11 @@ function handleResponse() {
document.getElementById('loadlink').style.display = 'none'; document.getElementById('loadlink').style.display = 'none';
var out = ''; var out = '';
for (var obj in response) { for (var obj in response['posts']) {
if (response[obj]['kind'] == 2) { if (response['posts'][obj]['kind'] == 2) {
var out = out + "<p><b><a href=\"http://reddit.com" + response[obj]['permalink'] + "\">" + response[obj]['title'] + "</a></b> - (/r/" + response[obj]['subreddit']+ ")</p>"; var out = out + "<p><b><a href=\"http://reddit.com" + response['posts'][obj]['permalink'] + "\">" + response['posts'][obj]['title'] + "</a></b> - (/r/" + response['posts'][obj]['subreddit']+ ")</p>";
} else { } else {
var out = out + "<p>" + response[obj]['body'] + "<br/><b>/r/" + response[obj]['subreddit'] + "</b> <a href=\"" + response[obj]['permalink'] + "\">Permalink</a></p>"; var out = out + "<p>" + response['posts'][obj]['body'] + "<br/><b>/r/" + response['posts'][obj]['subreddit'] + "</b> <a href=\"" + response['posts'][obj]['permalink'] + "\">Permalink</a></p>";
} }
} }
document.getElementById('redditposts').innerHTML = out; document.getElementById('redditposts').innerHTML = out;

View File

@@ -8,7 +8,7 @@
<table> <table>
<tr><th>Application ID</th><th>Character</th><th>Corporation</th><th>Application Status</th></tr> <tr><th>Application ID</th><th>Character</th><th>Corporation</th><th>Application Status</th></tr>
{% for app in apps %} {% for app in apps %}
<tr><td><a href="{% url hr.views.view_application app.id %}">{{ app.id }}</a></td> <tr><td><a href="{% url hr-viewapplication app.id %}">{{ app.id }}</a></td>
<td>{{ app.character }}</td> <td>{{ app.character }}</td>
<td>{{ app.corporation }}</td> <td>{{ app.corporation }}</td>
<td>{{ app.get_status_display }}</td> <td>{{ app.get_status_display }}</td>

View File

@@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load installed %}
{% block title %}Blacklist User{% endblock %} {% block title %}Blacklist User{% endblock %}
{% block content %} {% block content %}
@@ -10,12 +10,14 @@
<li>EVE API Keys</li> <li>EVE API Keys</li>
<li>Characters</li> <li>Characters</li>
<li>Email Addresses</li> <li>Email Addresses</li>
{% if "reddit"|installed %}
<li>Reddit Accounts</li> <li>Reddit Accounts</li>
{% endif %}
</ul> </ul>
<form action="{% url hr.views.blacklist_user u.id %}" method="post"> <form action="{% url hr-blacklistuser blacklistuser.id %}" method="post">
<table> <table>
<tr><th><label>User:</label></th><td>{{ u.username }}</td></tr> <tr><th><label>User:</label></th><td>{{ blacklistuser.username }}</td></tr>
{{ form.as_table }} {{ form.as_table }}
</table> </table>
{% csrf_token %} {% csrf_token %}

View File

@@ -6,20 +6,21 @@
<H1>HR</H1> <H1>HR</H1>
<h3>Applications</h3> <h3>Applications</h3>
<p><a href="{% url hr.views.view_applications %}">View your current open applications</a><br/> <p><a href="{% url hr-userapplications %}">View your current open applications</a><br/>
<a href="{% url hr.views.add_application %}">Create a application</a><br/></p> <a href="{% url hr-addapplication %}">Create a application</a><br/></p>
{% if can_recommend %} {% if can_recommend %}
<h3>Recommendations</h3> <h3>Recommendations</h3>
<p> <p>
<a href="{% url hr.views.view_recommendations %}">View your current open recommendations</a><br/> <a href="{% url hr-viewrecommendations %}">View your current open recommendations</a><br/>
<a href="{% url hr.views.add_recommendation %}">Add a recommendation</a><br/> <a href="{% url hr-addrecommendation %}">Add a recommendation</a><br/>
</p> </p>
{% endif %} {% endif %}
{% if hrstaff %} {% if hrstaff %}
<h3>HR Admin</h3> <h3>HR Admin</h3>
<p> <p>
<a href="{% url hr.views.admin_applications %}">View applications</a><br/> <a href="{% url hr-admin %}">View applications</a><br/>
</p> </p>
{% endif %} {% endif %}

View File

@@ -7,7 +7,7 @@
The person you are recommending needs to have created their application before you can add a recommendation.</p> The person you are recommending needs to have created their application before you can add a recommendation.</p>
<form action="{% url hr.views.add_recommendation %}" method="post"> <form action="{% url hr-addrecommendation %}" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
</table> </table>

View File

@@ -5,13 +5,13 @@
{% block content %} {% block content %}
<p>This list shows your current open recommendations that are yet to be submitted, as <p>This list shows your current open recommendations that are yet to be submitted, as
soon as the recommended user submits their application your recommendation will be removed from this list.</p> soon as the recommended user submits their application your recommendation will be removed from this list.</p>
{% if recs %} {% if recommendations %}
<table> <table>
<thead> <thead>
<tr><th>Recommender</th><th>Recommended Application</th><th>Application Status</th></tr> <tr><th>Recommender</th><th>Recommended Application</th><th>Application Status</th></tr>
</thead> </thead>
<tbody> <tbody>
{% for rec in recs %} {% for rec in recommendations %}
<tr><td>{{ rec.user_character }}</td> <tr><td>{{ rec.user_character }}</td>
<td>{{ rec.application }}</td> <td>{{ rec.application }}</td>
<td>{{ rec.application.get_status_display }}</td> <td>{{ rec.application.get_status_display }}</td>

View File

@@ -1,22 +1,23 @@
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from django.contrib.auth.decorators import login_required
from hr import views from hr import views
urlpatterns = patterns('', urlpatterns = patterns('',
('^$', views.index), url('^$', login_required(views.HrIndexView.as_view()), name='hr-index'),
(r'^recommendation/$', views.view_recommendations),
(r'^application/$', views.view_applications),
(r'^application/(?P<applicationid>\d+)/$', views.view_application),
(r'^application/(?P<applicationid>\d+)/update/(?P<status>\d+)/$', views.update_application),
(r'^application/(?P<applicationid>\d+)/note/$', views.add_note),
(r'^application/(?P<applicationid>\d+)/message/$', views.add_message),
(r'^application/(?P<applicationid>\d+)/reject/$', views.reject_application),
(r'^application/(?P<applicationid>\d+)/accept/$', views.accept_application),
(r'^application/add/$', views.add_application), url(r'^application/$', login_required(views.HrViewUserApplications.as_view()), name='hr-userapplications'),
(r'^recommendation/add/$', views.add_recommendation), url(r'^application/(?P<slug>\d+)/$', login_required(views.HrViewApplication.as_view()), name='hr-viewapplication'),
url(r'^application/(?P<slug>\d+)/update/(?P<status>\d+)/$', login_required(views.HrUpdateApplication.as_view()), name='hr-updateapplication'),
url(r'^application/(?P<applicationid>\d+)/note/$', login_required(views.HrAddNote.as_view()), name='hr-addnote'),
url(r'^application/(?P<applicationid>\d+)/message/$', login_required(views.HrAddMessage.as_view()), name='hr-addmessage'),
url(r'^application/(?P<applicationid>\d+)/reject/$', login_required(views.HrRejectApplication.as_view()), name='hr-rejectapplication'),
url(r'^application/(?P<applicationid>\d+)/accept/$', login_required(views.HrAcceptApplication.as_view()), name='hr-acceptapplication'),
url(r'^application/add/$', login_required(views.HrAddApplication.as_view()), name='hr-addapplication'),
url(r'^application/admin/$', login_required(views.HrAdminApplications.as_view()), name='hr-admin'),
(r'^application/admin$', views.admin_applications), url(r'^recommendation/$', login_required(views.HrViewRecommendations.as_view()), name='hr-viewrecommendations'),
url(r'^recommendation/add/$', login_required(views.HrAddRecommendation.as_view()), name='hr-addrecommendation'),
(r'^blacklist/user/(?P<userid>\d+)/$', views.blacklist_user), url(r'^blacklist/user/(?P<userid>\d+)/$', login_required(views.HrBlacklistUser.as_view()), name='hr-blacklistuser'),
) )

View File

@@ -1,10 +1,12 @@
import re import re
from datetime import datetime from datetime import datetime
from django.db import models
from django.template.loader import render_to_string
from eve_api.models import EVEPlayerCharacter
from hr.app_defines import * from hr.app_defines import *
from hr.models import Blacklist, Application from hr.models import Blacklist, Application
from django.db import models
from eve_api.models import EVEPlayerCharacter
def installed(value): def installed(value):
from django.conf import settings from django.conf import settings
@@ -42,7 +44,7 @@ def blacklist_values(user, level=BLACKLIST_LEVEL_NOTE):
blacklist.extend(bl_items.filter(type=BLACKLIST_TYPE_AUTH, value=user.username.lower())) blacklist.extend(bl_items.filter(type=BLACKLIST_TYPE_AUTH, value=user.username.lower()))
# Check EVE Related blacklists # Check EVE Related blacklists
evechars = EVEPlayerCharacter.objects.filter(eveaccount__user=user).select_related('corporation', 'corporation__alliance') evechars = EVEPlayerCharacter.objects.filter(eveaccount__user=user).distinct().select_related('corporation', 'corporation__alliance')
# Check Character blacklists # Check Character blacklists
characters = [re.escape(x) for x in evechars.values_list('name', flat=True) if x] characters = [re.escape(x) for x in evechars.values_list('name', flat=True) if x]
@@ -80,3 +82,42 @@ def recommendation_chain(application, first=True):
if first: if first:
return {name: output} return {name: output}
return output return output
def check_permissions(user, application=None):
""" Check if the user has permissions to view or admin the application """
corplist = EVEPlayerCharacter.objects.select_related('roles').filter(eveaccount__user=user)
if not application:
if user.has_perm('hr.can_view_all') or user.has_perm('hr.can_view_corp') or corplist.filter(roles__name='roleDirector').count():
return HR_ADMIN
else:
if application.user == user:
return HR_VIEWONLY
if user.has_perm('hr.can_view_all'):
return HR_ADMIN
else:
# Give admin access to directors of the corp
if application.corporation.id in corplist.filter(roles__name='roleDirector').values_list('corporation__id', flat=True):
return HR_ADMIN
# Give access to none director HR people access
if application.corporation.id in corplist.values_list('corporation__id', flat=True) and user.has_perm('hr.can_view_corp'):
return HR_ADMIN
return HR_NONE
def send_message(application, message_type, note=None):
from django.core.mail import send_mail
subject = render_to_string('hr/emails/%s_subject.txt' % message_type, { 'app': application })
subject = ''.join(subject.splitlines())
message = render_to_string('hr/emails/%s.txt' % message_type, { 'app': application, 'note': note })
try:
send_mail(subject, message, getattr(settings, 'DEFAULT_FROM_EMAIL', 'auth@nowhere.com'), [application.user.email])
except:
pass
if installed('reddit') and len(application.user.redditaccount_set.all()) > 0:
from reddit.tasks import send_reddit_message
for account in application.user.redditaccount_set.all():
send_reddit_message.delay(to=account.username, subject=subject, message=message)

View File

@@ -1,359 +1,370 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.utils import simplejson
from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404, redirect from django.shortcuts import get_object_or_404
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.template import RequestContext from django.views.generic import TemplateView, DetailView, FormView, CreateView, ListView
from django.template.loader import render_to_string from django.views.generic.detail import BaseDetailView
from django.conf import settings from django.conf import settings
from gargoyle import gargoyle from gargoyle import gargoyle
from utils import installed, blacklist_values from utils import installed, blacklist_values, check_permissions, send_message
from eve_api.models import EVEAccount, EVEPlayerCorporation, EVEPlayerCharacter 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.forms import RecommendationForm, ApplicationForm, NoteForm, BlacklistUserForm, AdminNoteForm
from hr.models import Recommendation, Application, Audit, Blacklist, BlacklistSource from hr.models import Recommendation, Application, Audit, Blacklist, BlacklistSource
from app_defines import * from hr.app_defines import *
### Shared Functions
def send_message(application, message_type, note=None):
from django.core.mail import send_mail
subject = render_to_string('hr/emails/%s_subject.txt' % message_type, { 'app': application })
subject = ''.join(subject.splitlines())
message = render_to_string('hr/emails/%s.txt' % message_type, { 'app': application, 'note': note })
try:
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [application.user.email])
except:
pass
if installed('reddit') and len(application.user.redditaccount_set.all()) > 0:
from reddit.tasks import send_reddit_message
for account in application.user.redditaccount_set.all():
send_reddit_message.delay(to=account.username, subject=subject, message=message)
def check_permissions(user, application=None):
""" Check if the user has permissions to view or admin the application """
corplist = EVEPlayerCharacter.objects.select_related('roles').filter(eveaccount__user=user)
if not application:
if user.has_perm('hr.can_view_all') or user.has_perm('hr.can_view_corp') or corplist.filter(roles__name='roleDirector').count():
return HR_ADMIN
else:
if application.user == user:
return HR_VIEWONLY
if user.has_perm('hr.can_view_all'):
return HR_ADMIN
else:
# Give admin access to directors of the corp
if application.corporation.id in corplist.filter(roles__name='roleDirector').values_list('corporation__id', flat=True):
return HR_ADMIN
# Give access to none director HR people access
if application.corporation.id in corplist.values_list('corporation__id', flat=True) and user.has_perm('hr.can_view_corp'):
return HR_ADMIN
return HR_NONE
### General Views ### General Views
@login_required class HrIndexView(TemplateView):
def index(request): """
hrstaff = check_permissions(request.user) Gives the main HR index page, with various options displayed depending on their
can_recommend = False access level.
if len(blacklist_values(request.user, BLACKLIST_LEVEL_ADVISORY)) == 0: """
can_recommend = True
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request)) template_name = 'hr/index.html'
def get_context_data(self, **kwargs):
context = super(HrIndexView, self).get_context_data(**kwargs)
context['hrstaff'] = check_permissions(self.request.user)
context['can_recommend'] = len(blacklist_values(self.request.user, BLACKLIST_LEVEL_ADVISORY)) == 0
return context
### Application Management ### Application Management
@login_required class HrViewUserApplications(TemplateView):
def view_applications(request): """
""" Shows a list of the user's applications """ Shows a list of the user's applications in the system
"""
apps = Application.objects.filter(user=request.user).order_by('id') template_name = 'hr/applications/view_list.html'
return render_to_response('hr/applications/view_list.html', locals(), context_instance=RequestContext(request))
@login_required def get_context_data(self, **kwargs):
def view_application(request, applicationid): context = super(HrViewUserApplications, self).get_context_data(**kwargs)
""" View a individual application """ context['applications'] = Application.objects.filter(user=self.request.user).order_by('id')
return context
app = get_object_or_404(Application, id=applicationid)
perm = check_permissions(request.user, app) 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: if perm == HR_VIEWONLY:
audit = app.audit_set.filter(event__in=[AUDIT_EVENT_STATUSCHANGE, AUDIT_EVENT_REJECTION, AUDIT_EVENT_ACCEPTED, AUDIT_EVENT_MESSAGE]) 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: elif perm == HR_ADMIN:
hrstaff = True context['hrstaff'] = True
audit = app.audit_set.all() context['audit'] = self.object.audit_set.all()
else: return context
return HttpResponseRedirect(reverse('hr.views.index'))
# Respond to Reddit Comment Load
# TODO: Move to reddit app?
if installed('reddit') and gargoyle.is_active('reddit', request) and request.GET.has_key('redditxhr') and request.is_ajax():
posts = []
for acc in app.user.redditaccount_set.all():
try:
accposts = acc.recent_posts()
except:
accposts = []
posts.extend(accposts)
return HttpResponse(simplejson.dumps(accposts), mimetype='application/javascript')
return render_to_response('hr/applications/view.html', locals(), context_instance=RequestContext(request)) class HrAddApplication(FormView):
@login_required form_class = ApplicationForm
def add_application(request):
""" Create a new application to a corporation """
if request.method == 'POST': def get_form_kwargs(self, **kwargs):
form = ApplicationForm(request.POST, user=request.user) kwargs = super(HrAddApplication, self).get_form_kwargs(**kwargs)
if form.is_valid(): kwargs['user'] = self.request.user
app = Application(user=request.user, character=form.cleaned_data['character'], corporation=form.cleaned_data['corporation']) 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() app.save()
messages.add_message(request, messages.INFO, "Your application to %s has been created." % app.corporation) messages.add_message(self.request, messages.INFO, "Your application to %s has been created." % app.corporation)
return HttpResponseRedirect(reverse('hr.views.view_application', args=[app.id])) return HttpResponseRedirect(reverse('hr-viewapplication', args=[app.id]))
else:
form = ApplicationForm(user=request.user)
def get_template_names(self):
if len(EVEPlayerCorporation.objects.filter(application_config__is_accepting=True)): if len(EVEPlayerCorporation.objects.filter(application_config__is_accepting=True)):
return render_to_response('hr/applications/add.html', locals(), context_instance=RequestContext(request)) return 'hr/applications/add.html'
else: else:
return render_to_response('hr/applications/noadd.html', locals(), context_instance=RequestContext(request)) return 'hr/applications/noadd.html'
### Recommendation Management ### Recommendation Management
@login_required class HrViewRecommendations(TemplateView):
def view_recommendations(request): """
""" View a list of recommendations the user has made """ Shows a list of the user's recommendations in the system
"""
recs = Recommendation.objects.filter(user=request.user) template_name = 'hr/recommendations/view_list.html'
return render_to_response('hr/recommendations/view_list.html', locals(), context_instance=RequestContext(request))
@login_required def get_context_data(self, **kwargs):
def add_recommendation(request): context = super(HrViewRecommendations, self).get_context_data(**kwargs)
""" Add a recommendation to a user's application """ context['recommendations'] = Recommendation.objects.filter(user=self.request.user)
return context
# If the person has a blacklist, stop recommendations
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)): if len(blacklist_values(request.user, BLACKLIST_LEVEL_ADVISORY)):
raise Http404 raise Http404
return super(HrAddRecommendation, self).dispatch(request, *args, **kwargs)
if request.method == 'POST': def form_valid(self, form):
form = RecommendationForm(request.POST, user=request.user) rec = Recommendation(user=self.request.user)
if form.is_valid():
rec = Recommendation(user=request.user)
rec.user_character = form.cleaned_data['character'] rec.user_character = form.cleaned_data['character']
rec.application = form.cleaned_data['application'] rec.application = form.cleaned_data['application']
rec.save() rec.save()
messages.add_message(request, messages.INFO, "Recommendation added to %s's application" % rec.application ) messages.add_message(self.request, messages.INFO, "Recommendation added to %s's application" % rec.application )
return HttpResponseRedirect(reverse('hr.views.view_recommendations')) return HttpResponseRedirect(reverse('hr-viewrecommendations'))
else:
form = RecommendationForm(user=request.user) # An unbound form
return render_to_response('hr/recommendations/add.html', locals(), context_instance=RequestContext(request)) def get_form_kwargs(self):
kwargs = super(HrAddRecommendation, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
@login_required
def admin_applications(request):
# Get the list of viewable applications by the admin
corplist = EVEPlayerCharacter.objects.filter(eveaccount__user=request.user).values_list('corporation', flat=True)
view_status = [APPLICATION_STATUS_AWAITINGREVIEW, APPLICATION_STATUS_ACCEPTED, APPLICATION_STATUS_QUERY, APPLICATION_STATUS_FLAGGED]
if request.user.has_perm('hr.can_view_all'): 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() apps = Application.objects.all()
elif request.user.has_perm('hr.can_view_corp'): elif self.request.user.has_perm('hr.can_view_corp'):
apps = Application.objects.filter(corporation__id__in=list(corplist)) apps = Application.objects.filter(corporation__id__in=EVEPlayerCharacter.objects.filter(eveaccount__user=self.request.user))
else:
return HttpResponseRedirect(reverse('hr.views.index'))
if 'q' in request.GET: query = self.request.GET.get('q', None)
query = request.GET['q'] order = self.request.GET.get('o', 'id')
# Filter by the query string
if query:
apps = apps.filter(character__name__icontains=query) apps = apps.filter(character__name__icontains=query)
else: else:
apps = apps.filter(status__in=view_status) apps = apps.filter(status__in=[APPLICATION_STATUS_AWAITINGREVIEW, APPLICATION_STATUS_ACCEPTED, APPLICATION_STATUS_QUERY, APPLICATION_STATUS_FLAGGED])
if 'o' in request.GET: # If a invalid order as been passed, correct it
order = request.GET['o'] if not order in ['id', 'corporation__name', 'character__name']:
if order in ['id', 'corporation__name', 'character__name']: order = 'id'
apps = apps.order_by(order)
if 'l' in request.GET: # If we've got a short search string, only get the first 50
limit = request.GET['l'] if query and len(query) < 3:
apps = apps[:limit] apps = apps[:50]
return render_to_response('hr/applications/admin/view_list.html', locals(), context_instance=RequestContext(request)) return apps
@login_required
def update_application(request, applicationid, status):
""" Update a application's status """
app = get_object_or_404(Application, id=applicationid) class HrUpdateApplication(BaseDetailView):
"""
Updates the status of a application if the workflow and permissions allow so.
"""
model = Application
slug_field = 'id'
if int(status) in APPLICATION_STATUS_ROUTES[app.status]: def render_to_response(self, context):
perm = check_permissions(request.user, app) 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 perm == HR_ADMIN or (perm == HR_VIEWONLY and int(status) <= 1):
if not app.status == status: if not self.object.status == status:
app.status = status self.object.status = status
app.save(user=request.user) 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: else:
messages.add_message(request, messages.ERROR, "Invalid status change request") messages.add_message(self.request, messages.ERROR, "Invalid status change request")
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid])) return HttpResponseRedirect(reverse('hr-viewapplication', args=[self.object.id]))
@login_required
def add_note(request, applicationid):
""" Add a note to a application """
if check_permissions(request.user) == HR_ADMIN:
if request.method == 'POST':
app = Application.objects.get(id=applicationid)
if check_permissions(request.user, app) == HR_ADMIN:
obj = Audit(application=app, user=request.user, event=AUDIT_EVENT_NOTE)
form = NoteForm(request.POST, instance=obj)
if form.is_valid():
obj = form.save()
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid]))
form = NoteForm()
return render_to_response('hr/applications/add_note.html', locals(), context_instance=RequestContext(request))
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request))
@login_required class HrAddNote(CreateView):
def add_message(request, applicationid): """
""" Send a message to the end user and note it on the application """ View to add a note to a application
"""
app = Application.objects.get(id=applicationid) template_name = 'hr/applications/add_note.html'
perm = check_permissions(request.user, app) form_class = NoteForm
if perm: model = Audit
if request.method == 'POST':
obj = Audit(application=app, user=request.user, event=AUDIT_EVENT_MESSAGE) def dispatch(self, request, *args, **kwargs):
if perm == HR_ADMIN: if not check_permissions(request.user) == HR_ADMIN:
form = AdminNoteForm(request.POST, instance=obj, application=app) return HttpResponseRedirect(reverse('hr.views.HrIndexView'))
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 not self.perm:
return HttpResponseRedirect(reverse('hr.views.HrIndexView'))
return super(HrAddMessage, self).dispatch(request, *args, **kwargs)
def get_form_class(self):
if self.perm == HR_ADMIN:
return AdminNoteForm
else: else:
form = NoteForm(request.POST, instance=obj) return NoteForm
if form.is_valid():
obj = form.save()
if not app.user == request.user:
send_message(obj.application, 'message', note=obj.text)
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid]))
if perm == HR_ADMIN: def get_form_kwargs(self):
form = AdminNoteForm(application=app) kwargs = super(HrAddMessage, self).get_form_kwargs()
else: if self.perm == HR_ADMIN:
form = NoteForm() kwargs['application'] = self.application
return render_to_response('hr/applications/add_message.html', locals(), context_instance=RequestContext(request)) return kwargs
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request)) 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())
@login_required class HrRejectApplication(CreateView):
def reject_application(request, applicationid):
""" Reject the application and notify the user """
if check_permissions(request.user) == HR_ADMIN and request.user.has_perm('hr.can_accept'): template_name = 'hr/applications/reject.html'
app = Application.objects.get(id=applicationid) message_template_name = 'rejected'
if request.method == 'POST': form_class = AdminNoteForm
if check_permissions(request.user, app) == HR_ADMIN: model = Audit
obj = Audit(application=app, user=request.user, event=AUDIT_EVENT_REJECTION) application_change_status = APPLICATION_STATUS_REJECTED
form = AdminNoteForm(request.POST, instance=obj, application=app) audit_event_type = AUDIT_EVENT_REJECTION
if form.is_valid():
obj = form.save()
obj.application.status = APPLICATION_STATUS_REJECTED
obj.application.save(user=request.user)
send_message(obj.application, 'rejected', note=obj.text)
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid]))
form = AdminNoteForm(application=app) def dispatch(self, request, *args, **kwargs):
return render_to_response('hr/applications/reject.html', locals(), context_instance=RequestContext(request)) 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)
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request)) def get_form_kwargs(self):
kwargs = super(HrRejectApplication, self).get_form_kwargs()
kwargs['application'] = self.application
return kwargs
@login_required def get_context_data(self, **kwargs):
def accept_application(request, applicationid): context = super(HrRejectApplication, self).get_context_data(**kwargs)
""" Accept the application and notify the user """ context['application'] = self.application
return context
if check_permissions(request.user) == HR_ADMIN and request.user.has_perm('hr.can_accept'): def form_valid(self, form):
app = Application.objects.get(id=applicationid) 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: if app.blacklisted:
messages.add_message(request, messages.INFO, "This application has one or more blacklist entries and cannot be accepted.") messages.add_message(request, messages.INFO, "This application has one or more blacklist entries and cannot be accepted.")
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid])) return HttpResponseRedirect(reverse('hr-viewapplication', args=[app.id]))
return super(HrAcceptApplication, self).dispatch(request, *args, **kwargs)
if request.method == 'POST':
if check_permissions(request.user, app) == HR_ADMIN:
obj = Audit(application=app, user=request.user, event=AUDIT_EVENT_ACCEPTED)
form = AdminNoteForm(request.POST, instance=obj, application=app)
if form.is_valid():
obj = form.save()
obj.application.status = APPLICATION_STATUS_ACCEPTED
obj.application.save(user=request.user)
send_message(obj.application, 'accepted', note=obj.text)
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid]))
form = AdminNoteForm(application=app)
return render_to_response('hr/applications/accept.html', locals(), context_instance=RequestContext(request))
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request))
def blacklist_user(request, userid): class HrBlacklistUser(FormView):
if request.user.has_perm('hr.add_blacklist'): template_name = 'hr/blacklist/blacklist.html'
form_class = BlacklistUserForm
u = get_object_or_404(User, id=userid) def dispatch(self, request, *args, **kwargs):
self.blacklist_user = get_object_or_404(User, id=kwargs.get('userid'))
return super(HrBlacklistUser, self).dispatch(request, *args, **kwargs)
if request.method == 'POST': def get_context_data(self, **kwargs):
form = BlacklistUserForm(request.POST) context = super(HrBlacklistUser, self).get_context_data(**kwargs)
if form.is_valid(): context['blacklistuser'] = self.blacklist_user
source = BlacklistSource.objects.get(id=1) return context
if not form.cleaned_data.get('expiry_date', None):
expiry = datetime.utcnow() + timedelta(days=50*365)
else:
expiry = form.cleaned_data['expiry_date']
level = form.cleaned_data.get('level', 0)
def blacklist_item(type, value): def blacklist_item(type, value):
o = Blacklist(type=type, value=value, level=level, source=source, expiry_date=expiry, created_by=request.user, reason=form.cleaned_data['reason']) Blacklist(type=self.type, value=self.value, level=self.level, source=self.source, expiry_date=self.expiry, created_by=self.request.user, reason=self.reason).save()
o.save()
for ea in u.eveaccount_set.all(): def form_valid(self, form):
blacklist_item(BLACKLIST_TYPE_APIUSERID, ea.api_user_id) 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'): if installed('reddit'):
for ra in u.redditaccount_set.all(): for account in u.redditaccount_set.all():
blacklist_item(BLACKLIST_TYPE_REDDIT, ra.username) self.blacklist_item(BLACKLIST_TYPE_REDDIT, account.username)
for char in EVEPlayerCharacter.objects.filter(eveaccount__user=u):
blacklist_item(BLACKLIST_TYPE_CHARACTER, char.name)
blacklist_item(BLACKLIST_TYPE_EMAIL, u.email)
messages.add_message(request, messages.INFO, "User %s has been blacklisted" % u.username ) messages.add_message(request, messages.INFO, "User %s has been blacklisted" % u.username )
# Disable the account if requested
if form.cleaned_data.get('disable', None): if form.cleaned_data.get('disable', None):
# Disable the account self.blacklist_user.active = False
u.active = False self.blacklist_user.save()
u.save()
for acc in u.serviceaccount_set.all(): update_user_access.delay(user=self.blacklist_user.id)
acc.delete()
messages.add_message(request, messages.INFO, "User %s disabled" % u.username ) messages.add_message(request, messages.INFO, "User %s disabled" % u.username )
return redirect('sso.views.user_view', username=u.username) return redirect('sso.views.user_view', username=self.blacklist_user.username)
else:
messages.add_message(request, messages.ERROR, "Error while processing the form")
form = BlacklistUserForm()
return render_to_response('hr/blacklist/blacklist.html', locals(), context_instance=RequestContext(request))
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request))

View File

@@ -23,7 +23,7 @@
<a href="{% url sso.views.refresh_access user.id %}">Update Access</a> <a href="{% url sso.views.refresh_access user.id %}">Update Access</a>
{% if "hr"|installed %} {% if "hr"|installed %}
{% if perms.hr.add_blacklist %} {% if perms.hr.add_blacklist %}
<a href="{% url hr.views.blacklist_user user.id %}">Blacklist User</a> <a href="{% url hr-blacklistuser user.id %}">Blacklist User</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
@@ -49,7 +49,7 @@
<table> <table>
<tr><th>ID</th><th>Character</th><th>Applied To</th><th>Status</th></tr> <tr><th>ID</th><th>Character</th><th>Applied To</th><th>Status</th></tr>
{% for app in user.application_set.all %} {% for app in user.application_set.all %}
<tr><td><a href="{% url hr.views.view_application app.id %}">{{ app.id }}</a></td> <tr><td><a href="{% url hr-viewapplication app.id %}">{{ app.id }}</a></td>
<td>{{ app.character }}</td> <td>{{ app.character }}</td>
<td>{{ app.corporation }}</td> <td>{{ app.corporation }}</td>
<td>{{ app.get_status_display }}</td></tr> <td>{{ app.get_status_display }}</td></tr>
@@ -63,7 +63,7 @@
<table> <table>
<tr><th>Recommended Application</th><th>Recommendation Character</th><th>Recommendation Date</th></tr> <tr><th>Recommended Application</th><th>Recommendation Character</th><th>Recommendation Date</th></tr>
{% for rec in user.recommendation_set.all %} {% for rec in user.recommendation_set.all %}
<tr><td><a href="{% url hr.views.view_application rec.application.id %}">{{ rec.application.character.name }}</a></td> <tr><td><a href="{% url hr-viewapplication rec.application.id %}">{{ rec.application.character.name }}</a></td>
<td>{{ rec.user_character }}</td> <td>{{ rec.user_character }}</td>
<td>{{ rec.recommendation_date }}</td></tr> <td>{{ rec.recommendation_date }}</td></tr>
{% endfor %} {% endfor %}

View File

@@ -23,7 +23,7 @@
<li><a href="{% url oauth-list-tokens %}">Application Access</a></li> <li><a href="{% url oauth-list-tokens %}">Application Access</a></li>
{% endif %} {% endif %}
{% if "hr"|installed %} {% if "hr"|installed %}
<li><a href="{% url hr.views.index %}">HR</a></li> <li><a href="{% url hr-index %}">HR</a></li>
{% endif %} {% endif %}
<li><a href="{% url eve_api.views.eveapi_character %}">Characters</a></li> <li><a href="{% url eve_api.views.eveapi_character %}">Characters</a></li>
{% if perms.sso.can_search_users %} {% if perms.sso.can_search_users %}