Compare commits

...

17 Commits

Author SHA1 Message Date
Ariel Rin
10bd77d761 Version Bump v2.9.0a2 2021-05-13 21:43:24 +10:00
Ariel Rin
192d286cf2 Merge branch 'master' of https://gitlab.com/allianceauth/allianceauth into v2.9.x 2021-05-13 21:38:22 +10:00
Ariel Rin
8ab9d2d5ad Merge branch 'revert-to-autofield' into 'v2.9.x'
revert migrations & set DEFAULT_AUTO_FIELD to django.db.models.AutoField

See merge request allianceauth/allianceauth!1312
2021-05-10 11:53:47 +00:00
Peter Pfeufer
3630812b92 revert migrations & set DEFAULT_AUTO_FIELD to django.db.models.AutoField 2021-05-10 13:35:40 +02:00
Ariel Rin
2f320bc256 Version Bump 2.9.0a1 2021-05-09 06:45:17 +00:00
Ariel Rin
45b8d42b8e Merge branch 'javascript-modernization' into 'v2.9.x'
Cleanup and modernize JS

See merge request allianceauth/allianceauth!1305
2021-05-09 06:43:58 +00:00
Peter Pfeufer
bd2d19f867 Cleanup and modernize JS 2021-05-09 06:43:58 +00:00
Ariel Rin
0be404baca Merge branch 'py36remove' into 'v2.9.x'
Remove Python36 Testing and Support

See merge request allianceauth/allianceauth!1301
2021-05-09 06:42:56 +00:00
Ariel Rin
e6cee9ac83 Remove Python36 Testing and Support 2021-05-09 06:42:56 +00:00
Ariel Rin
d173a59441 Merge branch 'add-robots-txt' into 'v2.9.x'
Adding robots.txt to fix random 404 message

See merge request allianceauth/allianceauth!1302
2021-04-27 14:11:14 +00:00
Peter Pfeufer
8f59f2549a robots.txt added
This fixes the randomly appearing 404 error in Auth  (issue #1232)
2021-04-15 20:59:25 +02:00
Ariel Rin
630400fee4 Merge branch 'django-3-2-update' into 'v2.9.x'
Django 3.2 compatibility update

See merge request allianceauth/allianceauth!1300
2021-04-08 05:07:01 +00:00
Ariel Rin
1ec6929e91 Merge branch 'python39' into 'v2.9.x'
Add  Python3.9 Testing

See merge request allianceauth/allianceauth!1284
2021-04-08 04:49:15 +00:00
Ariel Rin
8c6bdd8ae2 Add Python3.9 Testing 2021-04-08 04:49:15 +00:00
Peter Pfeufer
e04138bced migrations 2021-04-07 18:40:39 +02:00
Peter Pfeufer
db5ad85811 add new default for PKs 2021-04-07 18:16:33 +02:00
Peter Pfeufer
5b44fd376d revert version cap on Django, so we get 3.2 again 2021-04-07 18:11:01 +02:00
23 changed files with 344 additions and 298 deletions

View File

@@ -25,15 +25,6 @@ dependency_scanning:
- python -V - python -V
- pip install wheel tox - pip install wheel tox
test-3.6-core:
image: python:3.6-buster
script:
- tox -e py36-core
artifacts:
when: always
reports:
cobertura: coverage.xml
test-3.7-core: test-3.7-core:
image: python:3.7-buster image: python:3.7-buster
script: script:
@@ -52,10 +43,10 @@ test-3.8-core:
reports: reports:
cobertura: coverage.xml cobertura: coverage.xml
test-3.6-all: test-3.9-core:
image: python:3.6-buster image: python:3.9-buster
script: script:
- tox -e py36-all - tox -e py39-core
artifacts: artifacts:
when: always when: always
reports: reports:
@@ -79,9 +70,18 @@ test-3.8-all:
reports: reports:
cobertura: coverage.xml cobertura: coverage.xml
test-3.9-all:
image: python:3.9-buster
script:
- tox -e py39-all
artifacts:
when: always
reports:
cobertura: coverage.xml
deploy_production: deploy_production:
stage: deploy stage: deploy
image: python:3.8-buster image: python:3.9-buster
before_script: before_script:
- pip install twine wheel - pip install twine wheel

View File

@@ -1,7 +1,7 @@
# This will make sure the app is always imported when # This will make sure the app is always imported when
# Django starts so that shared_task will use this app. # Django starts so that shared_task will use this app.
__version__ = '2.8.4' __version__ = '2.9.0a2'
__title__ = 'Alliance Auth' __title__ = 'Alliance Auth'
__url__ = 'https://gitlab.com/allianceauth/allianceauth' __url__ = 'https://gitlab.com/allianceauth/allianceauth'
NAME = '%s v%s' % (__title__, __version__) NAME = '%s v%s' % (__title__, __version__)

View File

@@ -42,6 +42,7 @@
</div> </div>
{% endblock content %} {% endblock content %}
{% block extra_script %} {% block extra_script %}
$(document).ready(function(){ $(document).ready(function () {
$("[rel=tooltip]").tooltip(); $("[rel=tooltip]").tooltip();
});
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -44,6 +44,7 @@
</div> </div>
{% endblock content %} {% endblock content %}
{% block extra_script %} {% block extra_script %}
$(document).ready(function(){ $(document).ready(function () {
$("[rel=tooltip]").tooltip(); $("[rel=tooltip]").tooltip();
});
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -83,7 +83,7 @@
{% block extra_script %} {% block extra_script %}
$.fn.dataTable.moment = function(format, locale) { $.fn.dataTable.moment = function(format, locale) {
var types = $.fn.dataTable.ext.type; let types = $.fn.dataTable.ext.type;
// Add type detection // Add type detection
types.detect.unshift(function(d) { types.detect.unshift(function(d) {

View File

@@ -34,17 +34,15 @@
{% endblock %} {% endblock %}
{% block extra_script %} {% block extra_script %}
$('#id_start').datetimepicker({ $('#id_start').datetimepicker({
setlocale: '{{ LANGUAGE_CODE }}', setlocale: '{{ LANGUAGE_CODE }}',
{% if NIGHT_MODE %} {% if NIGHT_MODE %}
theme: 'dark', theme: 'dark',
{% else %} {% else %}
theme: 'default', theme: 'default',
{% endif %} {% endif %}
mask: true, mask: true,
format: 'Y-m-d H:i', format: 'Y-m-d H:i',
minDate: 0 minDate: 0
}); });
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -41,9 +41,10 @@
{% include 'bundles/moment-js.html' with locale=True %} {% include 'bundles/moment-js.html' with locale=True %}
<script src="{% static 'js/timers.js' %}"></script> <script src="{% static 'js/timers.js' %}"></script>
<script type="application/javascript"> <script type="application/javascript">
// Data // Data
var timers = [ let timers = [
{% for op in optimer %} {% for op in optimer %}
{ {
'id': {{ op.id }}, 'id': {{ op.id }},
@@ -52,67 +53,66 @@
}, },
{% endfor %} {% endfor %}
]; ];
</script>
<script type="application/javascript">
timedUpdate();
setAllLocalTimes();
// Start timed updates
setInterval(timedUpdate, 1000);
function timedUpdate() {
updateClock();
updateAllTimers();
}
function updateAllTimers () {
var l = timers.length;
for (var i=0; i < l; ++i) {
if (timers[i].expired) continue;
updateTimer(timers[i]);
}
}
/** /**
* Update a timer * Update a timer
* @param timer Timer information * @param timer Timer information
* @param timer.start Date of the timer
* @param timer.id Id number of the timer
* @param timer.expired
*/ */
function updateTimer(timer) { let updateTimer = function (timer) {
if (timer.start.isAfter(Date.now())) { if (timer.start.isAfter(Date.now())) {
var duration = moment.duration(timer.start - moment(), 'milliseconds'); let duration = moment.duration(timer.start - moment(), 'milliseconds');
document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration); document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration);
} else { } else {
timer.expired = true; timer.expired = true;
document.getElementById("countdown" + timer.id).innerHTML = ""; document.getElementById("countdown" + timer.id).innerHTML = "";
} }
} };
let updateAllTimers = function () {
let l = timers.length;
/**
* Set all local time fields
*/
function setAllLocalTimes() {
var l = timers.length;
for (var i=0; i < l; ++i) { for (var i=0; i < l; ++i) {
setLocalTime(timers[i]); if (timers[i].expired) continue;
updateTimer(timers[i]);
} }
} };
/** /**
* Set the local time info for the timer * Set the local time info for the timer
* @param timer Timer information * @param timer Timer information
* @param timer.start Date of the timer
* @param timer.id Id number of the timer
*/ */
function setLocalTime(timer) { let setLocalTime = function (timer) {
document.getElementById("localtime" + timer.id).innerHTML = timer.start.format("ddd @ LT"); document.getElementById("localtime" + timer.id).innerHTML = timer.start.format("ddd @ LT");
} };
function updateClock() { /**
* Set all local time fields
*/
let setAllLocalTimes = function () {
let l = timers.length;
for (var i=0; i < l; ++i) {
setLocalTime(timers[i]);
}
};
let updateClock = function () {
document.getElementById("current-time").innerHTML = getCurrentEveTimeString(); document.getElementById("current-time").innerHTML = getCurrentEveTimeString();
} };
let timedUpdate = function () {
updateClock();
updateAllTimers();
};
// Set initial values
setAllLocalTimes();
timedUpdate();
// Start timed updates
setInterval(timedUpdate, 1000);
</script> </script>
{% endblock content %} {% endblock content %}

View File

@@ -56,8 +56,9 @@
{% block extra_script %} {% block extra_script %}
$(document).ready(function() { $(document).ready(function() {
var groupColumn = 0; let groupColumn = 0;
var table = $('#tab_permissions_audit').DataTable({
$('#tab_permissions_audit').DataTable({
columnDefs: [ columnDefs: [
{ "visible": false, "targets": groupColumn } { "visible": false, "targets": groupColumn }
], ],
@@ -73,9 +74,9 @@
bootstrap: true bootstrap: true
}, },
drawCallback: function ( settings ) { drawCallback: function ( settings ) {
var api = this.api(); let api = this.api();
var rows = api.rows( {page:'current'} ).nodes(); let rows = api.rows( {page:'current'} ).nodes();
var last=null; let last = null;
api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) { api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) {
if ( last !== group ) { if ( last !== group ) {

View File

@@ -89,8 +89,9 @@
{% block extra_script %} {% block extra_script %}
$(document).ready(function() { $(document).ready(function() {
var groupColumn = 0; let groupColumn = 0;
var table = $('#tab_permissions_overview').DataTable({
$('#tab_permissions_overview').DataTable({
columnDefs: [ columnDefs: [
{ "visible": false, "targets": groupColumn } { "visible": false, "targets": groupColumn }
], ],
@@ -108,9 +109,9 @@
bootstrap: true bootstrap: true
}, },
drawCallback: function ( settings ) { drawCallback: function ( settings ) {
var api = this.api(); let api = this.api();
var rows = api.rows( {page:'current'} ).nodes(); let rows = api.rows( {page:'current'} ).nodes();
var last=null; let last = null;
api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) { api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) {
if ( last !== group ) { if ( last !== group ) {

View File

@@ -262,3 +262,5 @@ LOGGING = {
}, },
} }
} }
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

View File

@@ -12,20 +12,12 @@ import base64
import hmac import hmac
import hashlib import hashlib
try: from urllib.parse import unquote, urlencode, parse_qs
from urllib import unquote, urlencode
except ImportError: #py3
from urllib.parse import unquote, urlencode
try:
from urlparse import parse_qs
except ImportError: #py3
from urllib.parse import parse_qs
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
ACCESS_PERM = 'discourse.access_discourse' ACCESS_PERM = 'discourse.access_discourse'
@@ -55,7 +47,7 @@ def discourse_sso(request):
# Validate the payload # Validate the payload
try: try:
payload = unquote(payload).encode('utf-8') payload = unquote(payload).encode('utf-8')
decoded = base64.decodestring(payload).decode('utf-8') decoded = base64.decodebytes(payload).decode('utf-8')
assert 'nonce' in decoded assert 'nonce' in decoded
assert len(payload) > 0 assert len(payload) > 0
except AssertionError: except AssertionError:
@@ -86,7 +78,7 @@ def discourse_sso(request):
if main_char: if main_char:
params['avatar_url'] = main_char.portrait_url(256) params['avatar_url'] = main_char.portrait_url(256)
return_payload = base64.encodestring(urlencode(params).encode('utf-8')) return_payload = base64.encodebytes(urlencode(params).encode('utf-8'))
h = hmac.new(key, return_payload, digestmod=hashlib.sha256) h = hmac.new(key, return_payload, digestmod=hashlib.sha256)
query_string = urlencode({'sso': return_payload, 'sig': h.hexdigest()}) query_string = urlencode({'sso': return_payload, 'sig': h.hexdigest()})

View File

@@ -43,17 +43,15 @@
{% endblock %} {% endblock %}
{% block extra_script %} {% block extra_script %}
$('#id_fleet_time').datetimepicker({ $('#id_fleet_time').datetimepicker({
setlocale: '{{ LANGUAGE_CODE }}', setlocale: '{{ LANGUAGE_CODE }}',
{% if NIGHT_MODE %} {% if NIGHT_MODE %}
theme: 'dark', theme: 'dark',
{% else %} {% else %}
theme: 'default', theme: 'default',
{% endif %} {% endif %}
mask: true, mask: true,
format: 'Y-m-d H:i', format: 'Y-m-d H:i',
minDate: 0 minDate: 0
}); });
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -206,73 +206,71 @@ ESC to cancel{% endblocktrans %}"id="blah"></i></th>
{% endblock extra_javascript %} {% endblock extra_javascript %}
{% block extra_script %} {% block extra_script %}
$(document).ready(function() { $(document).ready(function() {
$.fn.editable.defaults.mode = 'inline'; $.fn.editable.defaults.mode = 'inline';
$.fn.editable.defaults.showbuttons = false; $.fn.editable.defaults.showbuttons = false;
$.fn.editable.defaults.highlight = "#AAFF80"; $.fn.editable.defaults.highlight = "#AAFF80";
$.fn.dataTable.moment = function(format, locale) {
let types = $.fn.dataTable.ext.type;
$('.srp').editable({ // Add type detection
display: function(value, response) { types.detect.unshift(function(d) {
return false; return moment(d, format, locale, true).isValid() ?
}, 'moment-' + format :
success: function(response, newValue) { null;
newValue = parseInt(newValue); });
newvalue = newValue.toLocaleString() + " ISK";
$(this).html(newvalue.bold());
},
validate: function(value) {
if (value === null || value === '') {
return 'Empty values not allowed';
}
}
});
$('.srp').on('hidden', function(e, reason){
if(reason === 'save' || reason === 'nochange') {
var $next = $(this).closest('tr').next().find('.editable');
setTimeout(function() {
$next.editable('show');
}, 400);
}
});
});
$(document).ready(function(){ // Add sorting method - use an integer for the sorting
$("[rel=tooltip]").tooltip({ placement: 'top'}); types.order[ 'moment-' + format+'-pre' ] = function(d) {
}); return moment(d, format, locale, true).unix();
};
};
$.fn.dataTable.moment('YYYY-MMM-D, HH:mm');
$.fn.dataTable.moment = function(format, locale) { $('.srp').editable({
var types = $.fn.dataTable.ext.type; display: function(value, response) {
return false;
},
success: function(response, newValue) {
newValue = parseInt(newValue);
let newValueOutput = newValue.toLocaleString() + " ISK";
// Add type detection $(this).html(newValueOutput.bold());
types.detect.unshift(function(d) { },
return moment(d, format, locale, true).isValid() ? validate: function(value) {
'moment-'+format : if (value === null || value === '') {
null; return 'Empty values not allowed';
} ); }
}
});
// Add sorting method - use an integer for the sorting $('.srp').on('hidden', function(e, reason){
types.order[ 'moment-'+format+'-pre' ] = function(d) { if(reason === 'save' || reason === 'nochange') {
return moment(d, format, locale, true).unix(); let $next = $(this).closest('tr').next().find('.editable');
};
};
$(document).ready( function(){ setTimeout(function() {
$.fn.dataTable.moment('YYYY-MMM-D, HH:mm'); $next.editable('show');
}, 400);
}
});
$('table.srplist').DataTable({ $('table.srplist').DataTable({
"order": [[ 6, "asc" ]], "order": [[ 6, "asc" ]],
"paging": false, "paging": false,
"columnDefs": [{ "columnDefs": [
"targets": [1, 8], {
"orderable": false "targets": [1, 8],
}, "orderable": false
{ },
"targets": [4, 5], {
"type": "num" "targets": [4, 5],
}] "type": "num"
}
]
});
// tooltip
$("[rel=tooltip]").tooltip({ placement: 'top'});
}); });
});
{% endblock extra_script %} {% endblock extra_script %}

View File

@@ -1,3 +1,5 @@
/* global notificationUPdateSettings */
/* /*
This script refreshed the unread notification count in the top menu This script refreshed the unread notification count in the top menu
on a regular basis so to keep the user apprised about newly arrived on a regular basis so to keep the user apprised about newly arrived
@@ -6,70 +8,67 @@
The refresh rate can be changes via the Django setting NOTIFICATIONS_REFRESH_TIME. The refresh rate can be changes via the Django setting NOTIFICATIONS_REFRESH_TIME.
See documentation for details. See documentation for details.
*/ */
$(function () { $(function () {
var elem = document.getElementById("dataExport"); 'use strict';
var notificationsListViewUrl = elem.getAttribute("data-notificationsListViewUrl");
var notificationsRefreshTime = elem.getAttribute("data-notificationsRefreshTime"); let notificationsListViewUrl = notificationUPdateSettings.notificationsListViewUrl;
var userNotificationsCountViewUrl = elem.getAttribute( let notificationsRefreshTime = notificationUPdateSettings.notificationsRefreshTime;
"data-userNotificationsCountViewUrl" let userNotificationsCountViewUrl = notificationUPdateSettings.userNotificationsCountViewUrl;
);
// update the notification unread count in the top menu // update the notification unread count in the top menu
function update_notifications() { let updateNotifications = function () {
$.getJSON(userNotificationsCountViewUrl, function (data, status) { $.getJSON(userNotificationsCountViewUrl, function (data, status) {
if (status == 'success') { if (status === 'success') {
var innerHtml = ""; let innerHtml = '';
var unread_count = data.unread_count; let unreadCount = data.unread_count;
if (unread_count > 0) {
if (unreadCount > 0) {
innerHtml = ( innerHtml = (
`Notifications <span class="badge">${unread_count}</span>` `Notifications <span class="badge">${unreadCount}</span>`
) );
} else {
innerHtml = '<i class="far fa-bell"></i>';
} }
else {
innerHtml = '<i class="far fa-bell"></i>' $('#menu_item_notifications').html(
}
$("#menu_item_notifications").html(
`<a href="${notificationsListViewUrl}">${innerHtml}</a>` `<a href="${notificationsListViewUrl}">${innerHtml}</a>`
); );
} } else {
else {
console.error( console.error(
`Failed to load HTMl to render notifications item. Error: ` `Failed to load HTMl to render notifications item. Error: ${xhr.status}': '${xhr.statusText}`
`${xhr.status}': '${xhr.statusText}`
); );
} }
}); });
} };
var myInterval; let myInterval;
// activate automatic refreshing every x seconds // activate automatic refreshing every x seconds
function activate_refreshing() { let activateRefreshing = function () {
if (notificationsRefreshTime > 0) { if (notificationsRefreshTime > 0) {
myInterval = setInterval( myInterval = setInterval(
update_notifications, notificationsRefreshTime * 1000 updateNotifications, notificationsRefreshTime * 1000
); );
} }
} };
// deactivate automatic refreshing // deactivate automatic refreshing
function deactivate_refreshing() { let deactivateRefreshing = function () {
if ((notificationsRefreshTime > 0) && (typeof myInterval !== 'undefined')) { if ((notificationsRefreshTime > 0) && (typeof myInterval !== 'undefined')) {
clearInterval(myInterval) clearInterval(myInterval);
} }
} };
// refreshing only happens on active browser tab // refreshing only happens on active browser tab
$(document).on({ $(document).on({
'show': function () { 'show': function () {
activate_refreshing() activateRefreshing();
}, },
'hide': function () { 'hide': function () {
deactivate_refreshing() deactivateRefreshing();
} }
}); });
// Initial start of refreshing on script loading // Initial start of refreshing on script loading
activate_refreshing() activateRefreshing();
}); });

View File

@@ -1,23 +1,49 @@
/* global moment */
/** /**
* Get a duration string like countdown.js * Get a duration string like countdown.js
* e.g. "1y 2d 3h 4m 5s" * e.g. "1y 2d 3h 4m 5s"
* @param duration moment.duration *
*/ * @param duration
function getDurationString(duration) { * @returns {string}
var out = ""; */
let getDurationString = function (duration) {
'use strict';
let out = '';
if (duration.years()) { if (duration.years()) {
out += duration.years() + 'y '; out += duration.years() + 'y ';
} }
if (duration.months()) { if (duration.months()) {
out += duration.months() + 'm '; out += duration.months() + 'm ';
} }
if (duration.days()) { if (duration.days()) {
out += duration.days() + 'd '; out += duration.days() + 'd ';
} }
return out + duration.hours() + "h " + duration.minutes() + "m " + duration.seconds() + "s";
}
return out + duration.hours() + 'h ' + duration.minutes() + 'm ' + duration.seconds() + 's';
};
function getCurrentEveTimeString() { /**
return moment().utc().format('dddd LL HH:mm:ss') * returns the current eve time as a formatted string
} *
* condition:
* only if moment.js is loaded before,
* if not this function returns an empty string to avoid JS errors from happening.
*
* @returns {string}
*/
let getCurrentEveTimeString = function () {
'use strict';
let returnValue = '';
if (window.moment) {
returnValue = moment().utc().format('dddd LL HH:mm:ss');
}
return returnValue;
};

View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow: /

View File

@@ -46,16 +46,17 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<!-- share data with JS part -->
<div
id="dataExport"
data-notificationsListViewUrl="{% url 'notifications:list' %}"
data-notificationsRefreshTime="{% notifications_refresh_time %}"
data-userNotificationsCountViewUrl="{% url 'notifications:user_notifications_count' request.user.pk %}"
>
</div>
{% include 'bundles/bootstrap-js.html' %} {% include 'bundles/bootstrap-js.html' %}
{% include 'bundles/jquery-visibility-js.html' %} {% include 'bundles/jquery-visibility-js.html' %}
<script type="application/javascript">
let notificationUPdateSettings = {
notificationsListViewUrl: "{% url 'notifications:list' %}",
notificationsRefreshTime: "{% notifications_refresh_time %}",
userNotificationsCountViewUrl: "{% url 'notifications:user_notifications_count' request.user.pk %}"
};
</script>
<script src="{% static 'js/refresh_notifications.js' %}"></script> <script src="{% static 'js/refresh_notifications.js' %}"></script>
{% block extra_javascript %} {% block extra_javascript %}

View File

@@ -526,9 +526,7 @@
{% include 'bundles/moment-js.html' with locale=True %} {% include 'bundles/moment-js.html' with locale=True %}
<script src="{% static 'js/timers.js' %}"></script> <script src="{% static 'js/timers.js' %}"></script>
<script type="application/javascript"> <script type="application/javascript">
var locale = "{{ LANGUAGE_CODE }}"; let timers = [
var timers = [
{% for timer in timers %} {% for timer in timers %}
{ {
'id': {{ timer.id }}, 'id': {{ timer.id }},
@@ -545,67 +543,64 @@
{% endfor %} {% endfor %}
]; ];
moment.locale(locale); /**
* Update a timer
* @param timer Timer information
*/
let updateTimer = function (timer) {
if (timer.targetDate.isAfter(Date.now())) {
let duration = moment.duration(timer.targetDate - moment(), 'milliseconds');
// Set initial values document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration);
setAllLocalTimes(); } else {
timedUpdate(); timer.expired = true;
// Start timed updates document.getElementById("countdown" + timer.id).innerHTML = "";
setInterval(timedUpdate, 1000); }
};
let updateAllTimers = function () {
let l = timers.length;
for (var i=0; i < l; ++i) {
if (timers[i].expired) continue;
updateTimer(timers[i]);
}
};
function timedUpdate() { function timedUpdate() {
updateClock(); updateClock();
updateAllTimers(); updateAllTimers();
} }
function updateAllTimers () {
var l = timers.length;
for (var i=0; i < l; ++i) {
if (timers[i].expired) continue;
updateTimer(timers[i]);
}
}
/** /**
* Update a timer * Set the local time info for the timer
* @param timer Timer information * @param timer Timer information
* @param timer.targetDate Date of the timer
* @param timer.id Id number of the timer
* @param timer.expired
*/ */
function updateTimer(timer) { let setLocalTime = function (timer) {
if (timer.targetDate.isAfter(Date.now())) { document.getElementById("localtime" + timer.id).innerHTML = timer.targetDate.format("ddd @ LT");
duration = moment.duration(timer.targetDate - moment(), 'milliseconds'); };
document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration);
} else {
timer.expired = true;
document.getElementById("countdown" + timer.id).innerHTML = "";
}
}
/** /**
* Set all local time fields * Set all local time fields
*/ */
function setAllLocalTimes() { let setAllLocalTimes = function () {
var l = timers.length; let l = timers.length;
for (var i=0; i < l; ++i) { for (var i=0; i < l; ++i) {
setLocalTime(timers[i]); setLocalTime(timers[i]);
} }
} };
/** let updateClock = function () {
* Set the local time info for the timer
* @param timer Timer information
* @param timer.targetDate Date of the timer
* @param timer.id Id number of the timer
*/
function setLocalTime(timer) {
document.getElementById("localtime" + timer.id).innerHTML = timer.targetDate.format("ddd @ LT");
}
function updateClock() {
document.getElementById("current-time").innerHTML = getCurrentEveTimeString(); document.getElementById("current-time").innerHTML = getCurrentEveTimeString();
} };
// Set initial values
setAllLocalTimes();
timedUpdate();
// Start timed updates
setInterval(timedUpdate, 1000);
</script> </script>
{% endblock content %} {% endblock content %}

View File

@@ -47,15 +47,23 @@ Place your virtual host configuration in the appropriate section within `/etc/ht
ServerName auth.example.com ServerName auth.example.com
ProxyPassMatch ^/static ! ProxyPassMatch ^/static !
ProxyPassMatch ^/robots.txt !
ProxyPass / http://127.0.0.1:8000/ ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/ ProxyPassReverse / http://127.0.0.1:8000/
ProxyPreserveHost On ProxyPreserveHost On
Alias "/static" "/var/www/myauth/static" Alias "/static" "/var/www/myauth/static"
Alias "/robots.txt" "/var/www/myauth/static/robots.txt"
<Directory "/var/www/myauth/static"> <Directory "/var/www/myauth/static">
Require all granted Require all granted
</Directory> </Directory>
<Location "/robots.txt">
SetHandler None
Require all granted
</Location>
</VirtualHost> </VirtualHost>
``` ```

View File

@@ -69,6 +69,10 @@ server {
autoindex off; autoindex off;
} }
location /robots.txt {
alias /var/www/myauth/static/robots.txt;
}
# Gunicorn config goes below # Gunicorn config goes below
location / { location / {
include proxy_params; include proxy_params;

View File

@@ -18,12 +18,17 @@ To run AA with a newer Python 3 version than your system's default you need to i
```eval_rst ```eval_rst
.. note:: .. note::
For stability and performance we currently recommend to run AA with Python 3.7. Since at the time of writing Python 3.7 was not available for CentOS through yum install this guide will upgrade to Python 3.6. For Ubuntu one can just replace "3.6" with "3.7" in the installation commands to get Python 3.7. For stability and performance we currently recommend to run AA with Python 3.7. It has proven to be the fastest and most stable version in use currently.
``` ```
To install other Python versions than come with your distro you need to add a new installation repository. Then you can install the specific Python 3 to your system. To install other Python versions than those included with your distribution, you need to add a new installation repository. Then you can install the specific Python 3 to your system.
Ubuntu: Ubuntu 1604 1804:
```eval_rst
.. note::
Ubuntu 2004 ships with Python 3.8, No updates required.
```
```bash ```bash
add-apt-repository ppa:deadsnakes/ppa add-apt-repository ppa:deadsnakes/ppa
@@ -34,23 +39,38 @@ apt-get update
``` ```
```bash ```bash
apt-get install python3.6 python3.6-dev python3.6-venv apt-get install python3.7 python3.7-dev python3.7-venv
``` ```
CentOS: CentOS 7/8:
```bash ```bash
yum install https://centos7.iuscommunity.org/ius-release.rpm cd ~
``` ```
```bash ```bash
yum update sudo yum install gcc openssl-devel bzip2-devel libffi-devel wget
``` ```
```bash ```bash
yum install python36u python36u-pip python36u-devel wget https://www.python.org/ftp/python/3.7.10/Python-3.7.10.tgz
``` ```
```bash
tar xvf Python-3.7.10.tgz
```
```bash
cd Python-3.7.10/
```
```bash
./configure --enable-optimizations --enable-shared
```
```bash
make altinstall
```
## Preparing your venv ## Preparing your venv
Before updating your venv it is important to make sure that your current installation is stable. Otherwise your new venv might not be consistent with your data, which might create problems. Before updating your venv it is important to make sure that your current installation is stable. Otherwise your new venv might not be consistent with your data, which might create problems.
@@ -97,12 +117,6 @@ If you unsure which apps you have installed from repos check `INSTALLED_APPS` in
pip list pip list
``` ```
Some AA installations might still be running an older version of django-celery-beat. We would recommend to upgrade to the current version before doing the Python update:
```bash
pip install -U 'django-celery-beat<2.00'
```
```bash ```bash
python manage.py migrate python manage.py migrate
``` ```
@@ -171,7 +185,7 @@ mv /home/allianceserver/venv/auth /home/allianceserver/venv/auth_old
Now let's create our new venv with Python 3.6 and activate it: Now let's create our new venv with Python 3.6 and activate it:
```bash ```bash
python3.6 -m venv /home/allianceserver/venv/auth python3.7 -m venv /home/allianceserver/venv/auth
``` ```
```bash ```bash

View File

@@ -22,7 +22,7 @@ install_requires = [
'celery>=4.3.0,<5.0.0,!=4.4.4', # 4.4.4 is missing a dependency 'celery>=4.3.0,<5.0.0,!=4.4.4', # 4.4.4 is missing a dependency
'celery_once>=2.0.1', 'celery_once>=2.0.1',
'django>=3.1.1,<3.2.0', 'django>=3.1.1,<4.0.0',
'django-bootstrap-form', 'django-bootstrap-form',
'django-registration>=3.1', 'django-registration>=3.1',
'django-sortedm2m', 'django-sortedm2m',
@@ -58,7 +58,7 @@ setup(
extras_require={ extras_require={
'testing': testing_extras 'testing': testing_extras
}, },
python_requires='~=3.6', python_requires='~=3.7',
license='GPLv2', license='GPLv2',
packages=['allianceauth'], packages=['allianceauth'],
url=allianceauth.__url__, url=allianceauth.__url__,
@@ -72,15 +72,20 @@ setup(
'Environment :: Web Environment', 'Environment :: Web Environment',
'Framework :: Django', 'Framework :: Django',
'Framework :: Django :: 3.1', 'Framework :: Django :: 3.1',
'Framework :: Django :: 3.2',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Linux',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
], ],
project_urls={
'Documentation': 'https://allianceauth.readthedocs.io/',
},
) )

View File

@@ -1,16 +1,16 @@
[tox] [tox]
skipsdist = true skipsdist = true
usedevelop = true usedevelop = true
envlist = py{36,37,38}-{all} envlist = py{37,38,39}-{all}
[testenv] [testenv]
setenv = setenv =
all: DJANGO_SETTINGS_MODULE = tests.settings_all all: DJANGO_SETTINGS_MODULE = tests.settings_all
core: DJANGO_SETTINGS_MODULE = tests.settings_core core: DJANGO_SETTINGS_MODULE = tests.settings_core
basepython = basepython =
py36: python3.6
py37: python3.7 py37: python3.7
py38: python3.8 py38: python3.8
py39: python3.9
deps= deps=
coverage coverage
install_command = pip install -e ".[testing]" -U {opts} {packages} install_command = pip install -e ".[testing]" -U {opts} {packages}