mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-15 07:20:17 +02:00
API SSO, Beautification of Tables, and more. (#562)
# One Thousandth Commit 🎉 🎈 🎆 🍾 * Allow requiring API ownership validation by SSO. Closes #163 * Add Discourse group name length restrictions. * Redirect after api addition/deletion of main character * Correct admin searching for removed discourse_username field in AuthServicesInfo * Correct admin function to sync user Discourse groups * Beautify tables by removing borders and hiding when empty. *Add buttons on dead-end pages to return to originating view.
This commit is contained in:
parent
4ea7fdeaf2
commit
e77c162fa0
@ -344,6 +344,8 @@ ALLIANCE_NAME = os.environ.get('AA_ALLIANCE_NAME', '')
|
||||
# BLUE_API_ACCOUNT - Require API to be for Account and not character restricted
|
||||
# REJECT_OLD_APIS - Require each submitted API be newer than the latest submitted API
|
||||
# REJECT_OLD_APIS_MARGIN - Margin from latest submitted API ID within which a newly submitted API is still accepted
|
||||
# API_SSO_VALIDATION - Require users to prove ownership of newly entered API keys via SSO
|
||||
# Requires SSO to be configured.
|
||||
#######################
|
||||
MEMBER_API_MASK = os.environ.get('AA_MEMBER_API_MASK', 268435455)
|
||||
MEMBER_API_ACCOUNT = 'True' == os.environ.get('AA_MEMBER_API_ACCOUNT', 'True')
|
||||
@ -351,6 +353,7 @@ BLUE_API_MASK = os.environ.get('AA_BLUE_API_MASK', 8388608)
|
||||
BLUE_API_ACCOUNT = 'True' == os.environ.get('AA_BLUE_API_ACCOUNT', 'False')
|
||||
REJECT_OLD_APIS = 'True' == os.environ.get('AA_REJECT_OLD_APIS', 'False')
|
||||
REJECT_OLD_APIS_MARGIN = os.environ.get('AA_REJECT_OLD_APIS_MARGIN', 50)
|
||||
API_SSO_VALIDATION = 'True' == os.environ.get('AA_API_SSO_VALIDATION', 'False')
|
||||
|
||||
#####################
|
||||
# Alliance Market
|
||||
|
@ -39,6 +39,7 @@ urlpatterns = [
|
||||
# Eve Online
|
||||
url(r'^main_character_change/(\w+)/$', eveonline.views.main_character_change,
|
||||
name='auth_main_character_change'),
|
||||
url(r'^api_verify_owner/(\w+)/$', eveonline.views.api_sso_validate, name='auth_api_sso'),
|
||||
|
||||
# Forum Service Control
|
||||
url(r'^activate_forum/$', services.views.activate_forum, name='auth_activate_forum'),
|
||||
|
@ -99,7 +99,7 @@ class AuthServicesInfoManager(admin.ModelAdmin):
|
||||
def sync_discourse(self, request, queryset):
|
||||
count = 0
|
||||
for a in queryset:
|
||||
if a.discourse_username != "":
|
||||
if a.discourse_enabled:
|
||||
update_discourse_groups.delay(a.user.pk)
|
||||
count += 1
|
||||
self.message_user(request, "%s discourse accounts queued for group sync." % count)
|
||||
@ -137,7 +137,6 @@ class AuthServicesInfoManager(admin.ModelAdmin):
|
||||
'mumble_username',
|
||||
'teamspeak3_uid',
|
||||
'discord_uid',
|
||||
'discourse_username',
|
||||
'ips4_username',
|
||||
'smf_username',
|
||||
'market_username',
|
||||
|
@ -4,6 +4,7 @@ from django.conf import settings
|
||||
|
||||
from services.managers.eve_api_manager import EveApiManager
|
||||
from eveonline.managers import EveManager
|
||||
from eveonline.models import EveApiKeyPair
|
||||
import evelink
|
||||
|
||||
import logging
|
||||
@ -31,6 +32,8 @@ class UpdateKeyForm(forms.Form):
|
||||
|
||||
if EveManager.check_if_api_key_pair_exist(self.cleaned_data['api_id']):
|
||||
logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id'])
|
||||
if EveApiKeyPair.objects.get(api_id=self.cleaned_data['api_id']).user:
|
||||
# allow orphaned APIs to proceed to SSO validation upon re-entry
|
||||
raise forms.ValidationError('API key already exist')
|
||||
if settings.REJECT_OLD_APIS and not EveManager.check_if_api_key_pair_is_new(
|
||||
self.cleaned_data['api_id'],
|
||||
|
27
eveonline/migrations/0003_auto_20161026_0149.py
Normal file
27
eveonline/migrations/0003_auto_20161026_0149.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.2 on 2016-10-26 01:49
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('eveonline', '0002_remove_eveapikeypair_error_count'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='eveapikeypair',
|
||||
name='user',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='evecharacter',
|
||||
name='user',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
@ -14,7 +14,7 @@ class EveCharacter(models.Model):
|
||||
alliance_id = models.CharField(max_length=254)
|
||||
alliance_name = models.CharField(max_length=254)
|
||||
api_id = models.CharField(max_length=254)
|
||||
user = models.ForeignKey(User)
|
||||
user = models.ForeignKey(User, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.character_name
|
||||
@ -24,10 +24,10 @@ class EveCharacter(models.Model):
|
||||
class EveApiKeyPair(models.Model):
|
||||
api_id = models.CharField(max_length=254)
|
||||
api_key = models.CharField(max_length=254)
|
||||
user = models.ForeignKey(User)
|
||||
user = models.ForeignKey(User, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username + " - ApiKeyPair"
|
||||
return self.api_id
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
|
@ -1,5 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
from django.shortcuts import render, redirect
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
|
||||
@ -7,11 +7,13 @@ from eveonline.forms import UpdateKeyForm
|
||||
from eveonline.managers import EveManager
|
||||
from authentication.managers import AuthServicesInfoManager
|
||||
from services.managers.eve_api_manager import EveApiManager
|
||||
from eveonline.models import EveApiKeyPair
|
||||
from eveonline.models import EveApiKeyPair, EveCharacter
|
||||
from authentication.models import AuthServicesInfo
|
||||
from authentication.tasks import set_state
|
||||
from eveonline.tasks import refresh_api
|
||||
|
||||
from eve_sso.decorators import token_required
|
||||
from django.conf import settings
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -24,20 +26,39 @@ def add_api_key(request):
|
||||
form = UpdateKeyForm(request.user, request.POST)
|
||||
logger.debug("Request type POST with form valid: %s" % form.is_valid())
|
||||
if form.is_valid():
|
||||
EveManager.create_api_keypair(form.cleaned_data['api_id'],
|
||||
form.cleaned_data['api_key'],
|
||||
request.user)
|
||||
|
||||
if EveApiKeyPair.objects.filter(api_id=form.cleaned_data['api_id'],
|
||||
api_key=form.cleaned_data['api_key']).exists():
|
||||
# allow orphaned keys to proceed to SSO validation upon re-entry
|
||||
api_key = EveApiKeyPair.objects.get(api_id=form.cleaned_data['api_id'],
|
||||
api_key=form.cleaned_data['api_key'])
|
||||
elif EveApiKeyPair.objects.filter(api_id=form.cleaned_data['api_id']).exists():
|
||||
logger.warn('API %s re-added with different vcode.' % form.cleaned_data['api_id'])
|
||||
EveApiKeyPair.objects.filter(api_id=form.cleaned_data['api_id']).delete()
|
||||
api_key = EveApiKeyPair.objects.create(api_id=form.cleaned_data['api_id'],
|
||||
api_key=form.cleaned_data['api_key'])
|
||||
else:
|
||||
api_key = EveApiKeyPair.objects.create(api_id=form.cleaned_data['api_id'],
|
||||
api_key=form.cleaned_data['api_key'])
|
||||
owner = None
|
||||
if not settings.API_SSO_VALIDATION:
|
||||
# set API and character owners if SSO validation not requested
|
||||
api_key.user = request.user
|
||||
api_key.save()
|
||||
owner = request.user
|
||||
# Grab characters associated with the key pair
|
||||
characters = EveApiManager.get_characters_from_api(form.cleaned_data['api_id'],
|
||||
form.cleaned_data['api_key'])
|
||||
EveManager.create_characters_from_list(characters, request.user, form.cleaned_data['api_id'])
|
||||
EveManager.create_characters_from_list(characters, owner, form.cleaned_data['api_id'])
|
||||
logger.info("Successfully processed api add form for user %s" % request.user)
|
||||
if not settings.API_SSO_VALIDATION:
|
||||
messages.success(request, 'Added API key %s to your account.' % form.cleaned_data['api_id'])
|
||||
auth = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
|
||||
if not auth.main_char_id:
|
||||
messages.warning(request, 'Please select a main character.')
|
||||
return redirect('auth_characters')
|
||||
return redirect("/api_key_management/")
|
||||
else:
|
||||
logger.debug('Requesting SSO validation of API %s by user %s' % (api_key.api_id, request.user))
|
||||
return render(request, 'registered/apisso.html', context={'api':api_key})
|
||||
else:
|
||||
logger.debug("Form invalid: returning to form.")
|
||||
else:
|
||||
@ -47,6 +68,32 @@ def add_api_key(request):
|
||||
return render(request, 'registered/addapikey.html', context=context)
|
||||
|
||||
|
||||
@login_required
|
||||
@token_required(new=True)
|
||||
def api_sso_validate(request, tokens, api_id):
|
||||
logger.debug('api_sso_validate called by user %s for api %s' % (request.user, api_id))
|
||||
api = get_object_or_404(EveApiKeyPair, api_id=api_id)
|
||||
if api.user:
|
||||
logger.warning('User %s attempting to take ownership of api %s from %s' % (request.user, api_id, api.user))
|
||||
messages.warning(request, 'API %s already claimed by user %s' % (api_id, api.user))
|
||||
return redirect('auth_api_key_management')
|
||||
token = tokens[0]
|
||||
logger.debug('API %s has no owner. Checking if token for %s matches.' % (api_id, token.character_name))
|
||||
characters = EveApiManager.get_characters_from_api(api.api_id, api.api_key).result
|
||||
if token.character_id in characters:
|
||||
api.user = request.user
|
||||
api.save()
|
||||
EveCharacter.objects.filter(character_id__in=characters).update(user=request.user, api_id=api_id)
|
||||
messages.success(request, 'Confirmed ownership of API %s' % api.api_id)
|
||||
auth, c = AuthServicesInfo.objects.get_or_create(user=request.user)
|
||||
if not auth.main_char_id:
|
||||
return redirect('auth_characters')
|
||||
return redirect('auth_api_key_management')
|
||||
else:
|
||||
messages.warning(request, '%s not found on API %s. Please SSO as a character on the API.' % (token.character_name, api.api_id))
|
||||
return render(request, 'registered/apisso.html', context={'api':api})
|
||||
|
||||
|
||||
@login_required
|
||||
def api_key_management_view(request):
|
||||
logger.debug("api_key_management_view called by user %s" % request.user)
|
||||
@ -59,21 +106,17 @@ def api_key_management_view(request):
|
||||
def api_key_removal(request, api_id):
|
||||
logger.debug("api_key_removal called by user %s for api id %s" % (request.user, api_id))
|
||||
authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
|
||||
# Check if our users main id is in the to be deleted characters
|
||||
characters = EveManager.get_characters_by_owner_id(request.user.id)
|
||||
if characters is not None:
|
||||
for character in characters:
|
||||
if character.character_id == authinfo.main_char_id:
|
||||
if character.api_id == api_id:
|
||||
messages.warning(request,
|
||||
'You have deleted your main character. Please select a new main character.')
|
||||
set_state(request.user)
|
||||
|
||||
EveManager.delete_api_key_pair(api_id, request.user.id)
|
||||
EveManager.delete_characters_by_api_id(api_id, request.user.id)
|
||||
messages.success(request, 'Deleted API key %s' % api_id)
|
||||
logger.info("Succesfully processed api delete request by user %s for api %s" % (request.user, api_id))
|
||||
if EveCharacter.objects.filter(character_id=authinfo.main_char_id).exists():
|
||||
return redirect("auth_api_key_management")
|
||||
else:
|
||||
authinfo.main_char_id = None
|
||||
authinfo.save()
|
||||
set_state(request.user)
|
||||
return redirect("auth_characters")
|
||||
|
||||
|
||||
@login_required
|
||||
@ -89,8 +132,8 @@ def main_character_change(request, char_id):
|
||||
logger.debug("main_character_change called by user %s for character id %s" % (request.user, char_id))
|
||||
if EveManager.check_if_character_owned_by_user(char_id, request.user):
|
||||
AuthServicesInfoManager.update_main_char_id(char_id, request.user)
|
||||
set_state(request.user)
|
||||
messages.success(request, 'Changed main character ID to %s' % char_id)
|
||||
set_state(request.user)
|
||||
return redirect("auth_characters")
|
||||
messages.error(request, 'Failed to change main character - selected character is not owned by your account.')
|
||||
return redirect("auth_characters")
|
||||
|
@ -343,7 +343,10 @@ class DiscourseManager:
|
||||
@staticmethod
|
||||
def _sanitize_groupname(name):
|
||||
name = name.strip(' _')
|
||||
return re.sub('[^\w]', '', name)
|
||||
name = re.sub('[^\w]', '', name)
|
||||
if len(name) < 3:
|
||||
name = name + "".join('_' for i in range(3-len(name)))
|
||||
return name[:20]
|
||||
|
||||
@staticmethod
|
||||
def update_groups(user):
|
||||
|
@ -9,27 +9,22 @@
|
||||
{% block extra_css %}{% endblock extra_css %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-lg-12">
|
||||
<div class="col-lg-6 col-lg-offset-3">
|
||||
<div class="row">
|
||||
{% if apikeypairs %}
|
||||
{% else %}
|
||||
<div class="alert alert-danger" role="alert">{% trans "No api keys found" %}</div>
|
||||
{% endif %}
|
||||
<h1 class="page-header text-center">{% trans "API Key Management" %}
|
||||
<div class="text-right">
|
||||
<a href="{% url 'auth_add_api_key' %}" class="btn btn-success">{% trans "Add Key" %}</a>
|
||||
</div>
|
||||
</h1>
|
||||
<table class="table table-bordered">
|
||||
{% if apikeypairs %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "API ID" %}</th>
|
||||
<th class="text-center">{% trans "API Key" %}</th>
|
||||
<th class="text-center">{% trans "Action" %}</th>
|
||||
</tr>
|
||||
{% for pair in apikeypairs %}
|
||||
<tr>
|
||||
<td class="text-center">{{ pair.api_id }}</td>
|
||||
<td class="text-center">{{ pair.api_key }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'auth_user_refresh_api' pair.api_id %}" class="btn btn-success">
|
||||
<span class="glyphicon glyphicon-refresh"></span>
|
||||
@ -41,6 +36,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-danger" role="alert">{% trans "No api keys found" %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
21
stock/templates/registered/apisso.html
Normal file
21
stock/templates/registered/apisso.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends 'public/base.html' %}
|
||||
{% load staticfiles %}
|
||||
{% block title %}Verify API Ownership{% endblock %}
|
||||
{% block page_title%}Verify API Ownership{% endblock %}
|
||||
{% block content %}
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header text-center">Verify API Ownership</div>
|
||||
<div class="col-xs-4 col-xs-offset-4">
|
||||
<div class="panel panel-default>
|
||||
<div class="panel-header">Please authenticate as a character on API {{ api.api_id }} to prove ownership.</div>
|
||||
<div class="panel-body">
|
||||
<div class="text-center">
|
||||
<a href="{% url 'auth_api_sso' api.api_id %}">
|
||||
<img class="img-responsive center-block" src="{% static 'img/sso/EVE_SSO_Login_Buttons_Large_Black.png' %}">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -17,7 +17,7 @@
|
||||
{% endif %}
|
||||
</h1>
|
||||
<h2>{% blocktrans %}{{ user }} has collected {{ n_fats }} links this month.{% endblocktrans %}</h2>
|
||||
<table class="table table-responsive table-bordered">
|
||||
<table class="table table-responsive">
|
||||
<tr>
|
||||
<th class="col-md-2 text-center">{% trans "Ship" %}</th>
|
||||
<th class="col-md-2 text-center">{% trans "Times used" %}</th>
|
||||
@ -31,7 +31,8 @@
|
||||
</table>
|
||||
{% if created_fats %}
|
||||
<h2>{% blocktrans %}{{ user }} has created {{ n_created_fats }} links this month.{% endblocktrans %}</h2>
|
||||
<table class="table table-bordered">
|
||||
{% if created_fats %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Name" %}</th>
|
||||
<th class="text-center">{% trans "Creator" %}</th>
|
||||
@ -58,6 +59,7 @@
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -16,7 +16,8 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</h1>
|
||||
<table class="table table-responsive table-bordered">
|
||||
<div class="col-lg-2 col-lg-offset-5">
|
||||
<table class="table table-responsive">
|
||||
<tr>
|
||||
<th class="col-md-2 text-center">{% trans "Month" %}</th>
|
||||
<th class="col-md-2 text-center">{% trans "Fats" %}</th>
|
||||
@ -33,6 +34,7 @@
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="/static/js/dateformat.js"></script>
|
||||
|
@ -16,7 +16,8 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</h1>
|
||||
<table class="table table-responsive table-bordered">
|
||||
{% if fatStats %}
|
||||
<table class="table table-responsive">
|
||||
<tr>
|
||||
<th class="col-md-1"></th>
|
||||
<th class="col-md-2 text-center">{% trans "Ticker" %}</th>
|
||||
@ -38,6 +39,7 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -22,7 +22,8 @@
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="table table-responsive table-bordered">
|
||||
{% if fats %}
|
||||
<table class="table table-responsive">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "fatname" %}</th>
|
||||
<th class="text-center">{% trans "Character" %}</th>
|
||||
@ -44,6 +45,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No fleet activity on record.</div>
|
||||
{% endif %}
|
||||
|
||||
{% if perms.auth.fleetactivitytracking%}
|
||||
<table class="table">
|
||||
@ -64,7 +68,8 @@
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="table table-bordered">
|
||||
{% if fatlinks %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Name" %}</th>
|
||||
<th class="text-center">{% trans "Creator" %}</th>
|
||||
@ -89,6 +94,9 @@
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No created fatlinks on record.</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -10,16 +10,21 @@
|
||||
{% block content %}
|
||||
<div class="col-lg-12">
|
||||
<h3 class="page-header text-center">{% trans "Group Management" %}</h3>
|
||||
<h4 class="page-header text-center">{% trans "Group Add Request" %}</h4>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-toggle="tab" href="#add">{% trans "Group Add Requests" %}</a></li>
|
||||
<li><a data-toggle="tab" href="#leave">{% trans "Group Leave Requests" %}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="add" class="tab-pane fade in active">
|
||||
<div class="panel-body">
|
||||
{% if acceptrequests %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "RequestID" %}</th>
|
||||
<th class="text-center">{% trans "CharacterName" %}</th>
|
||||
<th class="text-center">{% trans "GroupName" %}</th>
|
||||
<th class="text-center">{% trans "Action" %}</th>
|
||||
</tr>
|
||||
|
||||
{% for acceptrequest in acceptrequests %}
|
||||
<tr>
|
||||
<td class="text-center">{{ acceptrequest.id }}</td>
|
||||
@ -29,7 +34,6 @@
|
||||
<a href="{% url 'auth_group_accept_request' acceptrequest.id %}" class="btn btn-success">
|
||||
{% trans "Accept" %}
|
||||
</a>
|
||||
|
||||
<a href="{% url 'auth_group_reject_request' acceptrequest.id %}" class="btn btn-danger">
|
||||
{% trans "Reject" %}
|
||||
</a>
|
||||
@ -37,15 +41,21 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<h4 class="page-header text-center">{% trans "Group Leave Request" %}</h4>
|
||||
<table class="table table-bordered">
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No group add requests.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="leave" class="tab-pane fade">
|
||||
<div class="panel-body">
|
||||
{% if leaverequests %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "RequestID" %}</th>
|
||||
<th class="text-center">{% trans "CharacterName" %}</th>
|
||||
<th class="text-center">{% trans "GroupName" %}</th>
|
||||
<th class="text-center">{% trans "Action" %}</th>
|
||||
</tr>
|
||||
|
||||
{% for leaverequest in leaverequests %}
|
||||
<tr>
|
||||
<td class="text-center">{{ leaverequest.id }}</td>
|
||||
@ -55,7 +65,6 @@
|
||||
<a href="{% url 'auth_group_leave_accept_request' leaverequest.id %}" class="btn btn-success">
|
||||
{% trans "Accept" %}
|
||||
</a>
|
||||
|
||||
<a href="{% url 'auth_group_leave_reject_request' leaverequest.id %}" class="btn btn-danger">
|
||||
{% trans "Reject" %}
|
||||
</a>
|
||||
@ -63,6 +72,11 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No group leave requests.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
||||
|
@ -11,9 +11,9 @@
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header text-center">{% trans "Available Groups" %}</h1>
|
||||
{% if STATE == MEMBER_STATE or user.is_superuser %}
|
||||
<table class="table table-bordered">
|
||||
{% if pairs %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "GroupID" %}</th>
|
||||
<th class="text-center">{% trans "GroupName" %}</th>
|
||||
<th class="text-center">{% trans "GroupDesc" %}</th>
|
||||
<th class="text-center">{% trans "Action" %}</th>
|
||||
@ -21,7 +21,6 @@
|
||||
|
||||
{% for pair in pairs %}
|
||||
<tr>
|
||||
<td class="text-center">{{ pair.0.id }}</td>
|
||||
<td class="text-center">{{ pair.0.name }}</td>
|
||||
<td class="text-center">{{ pair.1.description }}</td>
|
||||
<td class="text-center">
|
||||
@ -48,6 +47,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No groups available.</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if IS_CORP %}
|
||||
<div class="alert alert-danger" role="alert">{% trans "You are not in the corporation." %}</div>
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="col-lg-12">
|
||||
{% if not STATE == MEMBER_STATE and not user.is_superuser %}
|
||||
{% if not STATE == MEMBER_STATE %}
|
||||
<h1 class="page-header text-center">{% trans "Personal Applications" %}
|
||||
<div class="text-right">
|
||||
{% if create %}
|
||||
@ -20,7 +20,8 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</h1>
|
||||
<table class="table table-bordered table-condensed">
|
||||
{% if personal_apps %}
|
||||
<table class="table table-condensed">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Username" %}</th>
|
||||
<th class="text-center">{% trans "Corporation" %}
|
||||
@ -55,6 +56,7 @@
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if perms.auth.human_resources %}
|
||||
<h1 class="page-header text-center">{% trans "Application Management" %}
|
||||
<div class="text-right">
|
||||
@ -71,6 +73,7 @@
|
||||
<div class="tab-content">
|
||||
<div id="pending" class="tab-pane fade in active">
|
||||
<div class="panel-body">
|
||||
{% if applications %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Date" %}</th>
|
||||
@ -107,10 +110,14 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No pending applications.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div id="reviewed" class="tab-pane fade">
|
||||
<div class="panel-body">
|
||||
{% if finished_applications %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Date" %}</th>
|
||||
@ -147,6 +154,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No reviewed applications.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,17 +11,17 @@
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header text-center">{% trans "View Application" %}</h1>
|
||||
<div class="container-fluid">
|
||||
<div class="col-md-4 col-md-offset-4">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="row">
|
||||
{% if app.approved %}
|
||||
<div class="alert alert-success">{% trans "Approved" %}</div>
|
||||
<div class="alert alert-success text-center">{% trans "Approved" %}</div>
|
||||
{% elif app.approved == False %}
|
||||
<div class="alert alert-danger">{% trans "Denied" %}</div>
|
||||
<div class="alert alert-danger text-center">{% trans "Denied" %}</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning">{% trans "Pending" %}</div>
|
||||
<div class="alert alert-warning text-center">{% trans "Pending" %}</div>
|
||||
{% endif %}
|
||||
{% if app.reviewer_str %}
|
||||
<div class="alert alert-info">{% trans "Reviewer:" %} {{ app.reviewer_str }}</div>
|
||||
<div class="alert alert-info text-center">{% trans "Reviewer:" %} {{ app.reviewer_str }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row">
|
||||
|
@ -22,6 +22,7 @@
|
||||
<div id="unread" class="tab-pane fade in active">
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
{% if unread %}
|
||||
<table class="table table-condensed table-hover table-striped">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Timestamp" %}</th>
|
||||
@ -43,12 +44,16 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No unread notifications.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="read" class="tab-pane fade">
|
||||
<div class="panel-body">
|
||||
<div class="table-responsive">
|
||||
{% if read %}
|
||||
<table class="table table-condensed table-hover table-striped">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Timestamp" %}</th>
|
||||
@ -70,6 +75,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No read notifications.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,7 +8,14 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header text-center">{% trans "View Notification" %}</h1>
|
||||
<h1 class="page-header text-center">
|
||||
{% trans "View Notification" %}
|
||||
<div class="text-right">
|
||||
<a href="{% url 'auth_notification_list' %}" class="btn btn-primary btn-lg">
|
||||
<span class="glyphicon glyphicon-arrow-left"></span>
|
||||
</a>
|
||||
</div>
|
||||
</h1>
|
||||
<div class="col-lg-12 container" id="example">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
|
@ -17,13 +17,14 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</h1>
|
||||
<div class="col-lg-12 text-center">
|
||||
<div class="col-lg-12 text-center row">
|
||||
<div class="label label-info text-left">
|
||||
<b>{% trans "Current Eve Time:" %} </b>
|
||||
</div><div class="label label-info text-left" id="current-time"></div>
|
||||
<br />
|
||||
</div>
|
||||
<table class="table table-responsive table-bordered">
|
||||
{% if optimer %}
|
||||
<table class="table table-responsive">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Operation Name" %}</th>
|
||||
<th class="text-center">{% trans "Doctrine" %}</th>
|
||||
@ -70,7 +71,9 @@
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% else %}
|
||||
<br /><div class="alert alert-warning text-center">No fleet operations found.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<script src="/static/js/dateformat.js"></script>
|
||||
|
@ -28,6 +28,9 @@
|
||||
<div class="alert alert-info" role="alert">{% blocktrans %}Give this link to the line members{% endblocktrans %}.</div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
http://{{ request.get_host }}{% url 'auth_srp_request_view' completed_srp_code %}</div>
|
||||
<div class="text-center">
|
||||
<a href="{% url 'auth_srp_management_view' %}" class="btn btn-primary btn-lg">{% trans "Continue" %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -34,7 +34,8 @@
|
||||
<b>{% trans "Total ISK Cost:" %} {{ totalcost | intcomma }}</b>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-bordered">
|
||||
{% if srpfleetrequests %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Pilot Name" %}</th>
|
||||
<th class="text-center">{% trans "Killboard Link" %}</th>
|
||||
@ -120,6 +121,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No SRP requests for this fleet.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="alert alert-success" role="alert">{% trans "SRP Request Successfully Submitted" %}</div>
|
||||
<div class="text-center">
|
||||
<a href="{% url 'auth_srp_management_view' %}" class="btn btn-primary btn-lg">{% trans 'Continue' %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -29,7 +29,8 @@
|
||||
<b>{% trans "Total ISK Cost:" %} {{ totalcost | intcomma }}</b>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-bordered">
|
||||
{% if srpfleets %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Fleet Name" %}</th>
|
||||
<th class="text-center">{% trans "Fleet Time" %}</th>
|
||||
@ -117,6 +118,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No SRP fleets created.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
{% if corp_timers %}
|
||||
<h4><b>{% trans "Corp Timers" %}</b></h4>
|
||||
<table class="table table-bordered">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th style="width:150px" class="text-center">{% trans "Details" %}</th>
|
||||
<th class="text-center">{% trans "Objective" %}</th>
|
||||
@ -124,7 +124,8 @@
|
||||
</table>
|
||||
{% endif %}
|
||||
<h4><b>{% trans "Next Timers" %}</b></h4>
|
||||
<table class="table table-bordered">
|
||||
{% if future_timers %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th style="width:150px" class="text-center">{% trans "Details" %}</th>
|
||||
<th class="text-center">{% trans "Objective" %}</th>
|
||||
@ -221,8 +222,12 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No upcoming timers.</div>
|
||||
{% endif %}
|
||||
<h4><b>{% trans "Past Timers" %}</b></h4>
|
||||
<table class="table table-bordered">
|
||||
{% if past_timers %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th style="width:150px" class="text-center">{% trans "Details" %}</th>
|
||||
<th class="text-center">{% trans "Objective" %}</th>
|
||||
@ -320,6 +325,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-warning text-center">No past timers.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user