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):
if perm == HR_VIEWONLY: """
audit = app.audit_set.filter(event__in=[AUDIT_EVENT_STATUSCHANGE, AUDIT_EVENT_REJECTION, AUDIT_EVENT_ACCEPTED, AUDIT_EVENT_MESSAGE]) View a individual application and related details
elif perm == HR_ADMIN: """
hrstaff = True
audit = app.audit_set.all()
else:
return HttpResponseRedirect(reverse('hr.views.index'))
# Respond to Reddit Comment Load template_name = 'hr/applications/view.html'
# TODO: Move to reddit app? context_object_name = "app"
if installed('reddit') and gargoyle.is_active('reddit', request) and request.GET.has_key('redditxhr') and request.is_ajax(): model = Application
posts = [] slug_field = 'id'
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)) 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()
return context
@login_required
def add_application(request):
""" Create a new application to a corporation """
if request.method == 'POST': class HrAddApplication(FormView):
form = ApplicationForm(request.POST, user=request.user)
if form.is_valid():
app = Application(user=request.user, character=form.cleaned_data['character'], corporation=form.cleaned_data['corporation'])
app.save()
messages.add_message(request, messages.INFO, "Your application to %s has been created." % app.corporation)
return HttpResponseRedirect(reverse('hr.views.view_application', args=[app.id]))
else:
form = ApplicationForm(user=request.user)
if len(EVEPlayerCorporation.objects.filter(application_config__is_accepting=True)): form_class = ApplicationForm
return render_to_response('hr/applications/add.html', locals(), context_instance=RequestContext(request))
else: def get_form_kwargs(self, **kwargs):
return render_to_response('hr/applications/noadd.html', locals(), context_instance=RequestContext(request)) 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 ### 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
if len(blacklist_values(request.user, BLACKLIST_LEVEL_ADVISORY)):
raise Http404
if request.method == 'POST':
form = RecommendationForm(request.POST, user=request.user)
if form.is_valid():
rec = Recommendation(user=request.user)
rec.user_character = form.cleaned_data['character']
rec.application = form.cleaned_data['application']
rec.save()
messages.add_message(request, messages.INFO, "Recommendation added to %s's application" % rec.application )
return HttpResponseRedirect(reverse('hr.views.view_recommendations'))
else:
form = RecommendationForm(user=request.user) # An unbound form
return render_to_response('hr/recommendations/add.html', locals(), context_instance=RequestContext(request))
@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'):
apps = Application.objects.all()
elif request.user.has_perm('hr.can_view_corp'):
apps = Application.objects.filter(corporation__id__in=list(corplist))
else:
return HttpResponseRedirect(reverse('hr.views.index'))
if 'q' in request.GET:
query = request.GET['q']
apps = apps.filter(character__name__icontains=query)
else:
apps = apps.filter(status__in=view_status)
if 'o' in request.GET:
order = request.GET['o']
if order in ['id', 'corporation__name', 'character__name']:
apps = apps.order_by(order)
if 'l' in request.GET:
limit = request.GET['l']
apps = apps[:limit]
return render_to_response('hr/applications/admin/view_list.html', locals(), context_instance=RequestContext(request))
@login_required
def update_application(request, applicationid, status):
""" Update a application's status """
app = get_object_or_404(Application, id=applicationid)
if int(status) in APPLICATION_STATUS_ROUTES[app.status]:
perm = check_permissions(request.user, app)
if perm == HR_ADMIN or (perm == HR_VIEWONLY and int(status) <= 1):
if not app.status == status:
app.status = status
app.save(user=request.user)
else:
messages.add_message(request, messages.ERROR, "Invalid status change request")
return HttpResponseRedirect(reverse('hr.views.view_application', args=[applicationid]))
@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 HrAddRecommendation(FormView):
def add_message(request, applicationid):
""" Send a message to the end user and note it on the application """
app = Application.objects.get(id=applicationid) template_name = 'hr/recommendations/add.html'
perm = check_permissions(request.user, app) form_class = RecommendationForm
if perm:
if request.method == 'POST':
obj = Audit(application=app, user=request.user, event=AUDIT_EVENT_MESSAGE)
if perm == HR_ADMIN:
form = AdminNoteForm(request.POST, instance=obj, application=app)
else:
form = NoteForm(request.POST, instance=obj)
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 dispatch(self, request, *args, **kwargs):
form = AdminNoteForm(application=app) 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=EVEPlayerCharacter.objects.filter(eveaccount__user=self.request.user))
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: else:
form = NoteForm() apps = apps.filter(status__in=[APPLICATION_STATUS_AWAITINGREVIEW, APPLICATION_STATUS_ACCEPTED, APPLICATION_STATUS_QUERY, APPLICATION_STATUS_FLAGGED])
return render_to_response('hr/applications/add_message.html', locals(), context_instance=RequestContext(request))
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request)) # If a invalid order as been passed, correct it
if not order in ['id', 'corporation__name', 'character__name']:
order = 'id'
@login_required # If we've got a short search string, only get the first 50
def reject_application(request, applicationid): if query and len(query) < 3:
""" Reject the application and notify the user """ apps = apps[:50]
if check_permissions(request.user) == HR_ADMIN and request.user.has_perm('hr.can_accept'): return apps
app = Application.objects.get(id=applicationid)
if request.method == 'POST':
if check_permissions(request.user, app) == HR_ADMIN:
obj = Audit(application=app, user=request.user, event=AUDIT_EVENT_REJECTION)
form = AdminNoteForm(request.POST, instance=obj, application=app)
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)
return render_to_response('hr/applications/reject.html', locals(), context_instance=RequestContext(request))
return render_to_response('hr/index.html', locals(), context_instance=RequestContext(request)) class HrUpdateApplication(BaseDetailView):
"""
Updates the status of a application if the workflow and permissions allow so.
"""
model = Application
slug_field = 'id'
@login_required def render_to_response(self, context):
def accept_application(request, applicationid): status = self.kwargs.get('status', None)
""" Accept the application and notify the user """ 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]))
if check_permissions(request.user) == HR_ADMIN and request.user.has_perm('hr.can_accept'):
app = Application.objects.get(id=applicationid)
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.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:
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: 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): def blacklist_item(type, value):
expiry = datetime.utcnow() + timedelta(days=50*365) 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()
else:
expiry = form.cleaned_data['expiry_date']
level = form.cleaned_data.get('level', 0) 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')
def blacklist_item(type, value): # Blacklist email address
o = Blacklist(type=type, value=value, level=level, source=source, expiry_date=expiry, created_by=request.user, reason=form.cleaned_data['reason']) self.blacklist_item(BLACKLIST_TYPE_EMAIL, self.blacklist_user.email)
o.save()
for ea in u.eveaccount_set.all(): # Blacklist API keys
blacklist_item(BLACKLIST_TYPE_APIUSERID, ea.api_user_id) for account in self.blacklist_user.eveaccount_set.all():
self.blacklist_item(BLACKLIST_TYPE_APIUSERID, account.api_user_id)
if installed('reddit'): # Blacklist Characters
for ra in u.redditaccount_set.all(): for character in EVEPlayerCharacter.objects.filter(eveaccount__user=self.blacklist_user).distinct():
blacklist_item(BLACKLIST_TYPE_REDDIT, ra.username) self.blacklist_item(BLACKLIST_TYPE_CHARACTER, character.name)
for char in EVEPlayerCharacter.objects.filter(eveaccount__user=u): # Blacklist Reddit accounts
blacklist_item(BLACKLIST_TYPE_CHARACTER, char.name) if installed('reddit'):
for account in u.redditaccount_set.all():
self.blacklist_item(BLACKLIST_TYPE_REDDIT, account.username)
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):
self.blacklist_user.active = False
self.blacklist_user.save()
if form.cleaned_data.get('disable', None): update_user_access.delay(user=self.blacklist_user.id)
# Disable the account
u.active = False
u.save()
for acc in u.serviceaccount_set.all(): messages.add_message(request, messages.INFO, "User %s disabled" % u.username )
acc.delete()
messages.add_message(request, messages.INFO, "User %s disabled" % u.username )
return redirect('sso.views.user_view', username=u.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))
return redirect('sso.views.user_view', username=self.blacklist_user.username)

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 %}