Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 0 additions & 37 deletions admin_login/azure_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,6 @@ def authenticate(self, request, username=None, password=None, **kwargs):
Authenticate user via Azure AD using username (email) and password.
"""
pass
# azure_details = get_azure_auth_details()
#
# # Initialize MSAL client
# msal_client = PublicClientApplication(
# client_id=azure_details['client_id'],
# authority=azure_details['authority'],
# )
#
# # Acquire token using username and password
# try:
# token_data = msal_client.acquire_token_by_username_password(
# username=username,
# password=password,
# scopes=azure_details['scope']
# )
#
# if 'access_token' in token_data:
# # Token is valid, retrieve or create the user
# user, created = User.objects.get_or_create(
# email=username, defaults={'username': username}
# )
# return user
# else:
# return None
# except Exception as e:
# # Log or handle error appropriately
# print(f"Error during Azure AD authentication: {e}")
# return None
#
# def get_user(self, user_id):
# """
# Retrieve user by their ID.
# """
# try:
# return User.objects.get(pk=user_id)
# except User.DoesNotExist:
# return None


class AzureADSignupService:
Expand Down
3 changes: 2 additions & 1 deletion admin_login/azure_utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ def payload_for_access_token(code):
'client_secret': azure_details['client_secret'],
}

return data
return data

10 changes: 5 additions & 5 deletions admin_login/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
from django.views import View
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied

from admin_login.azure_backend import AzureADSignupService, get_azure_auth_details

User = get_user_model()
# Create your views here.



class AzureADSignupView(View):
template_name = 'signup.html'

Expand Down Expand Up @@ -77,20 +79,18 @@ def _save_user_info(self, user_info):
name = user_info.get('name')
given_name = user_info.get('given_name')

if not User.objects.filter(email=email, is_active=True, is_superuser=True).exists():
raise PermissionDenied("Access Denied: You are not allowed to sign up.")
# Check if the user already exists
user, created = User.objects.get_or_create(
email=email,
defaults={
'username': name,
'username': email,
'first_name': given_name,
'is_staff': True, # Make the user an admin
'is_superuser': True, # Grant superuser permissions
},
)
if not created:
# Update user details if necessary
user.first_name = given_name
user.save()

user.is_superuser = True
user.is_staff = True
Expand Down
2 changes: 1 addition & 1 deletion iogt/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
},
}

SITE_VERSION = '2.13.7'
SITE_VERSION = '2.13.8'

try:
from .local import *
Expand Down
6 changes: 4 additions & 2 deletions iogt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,18 @@

urlpatterns = api_url_patterns + [
path('django-admin/', admin.site.urls),
# path('admin/logout/', CustomLogoutView.as_view(), name='admin_logout'),
# path('admin/login/', AzureADSignupView.as_view(), name='azure_signup_view'), # Override Wagtail admin login
path('admin/logout/', CustomLogoutView.as_view(), name='admin_logout'),
path('admin/login/', AzureADSignupView.as_view(), name='azure_signup_view'), # Override Wagtail admin login
path('admin/', include(wagtailadmin_urls)),
path('documents/', include(wagtaildocs_urls)),
# path('admin-login/', include(admin_login_urls), name='admin_login_urls'),
*i18n_patterns(path('logout_hack_view', LogoutRedirectHackView.as_view(), name='logout_redirect')),
*i18n_patterns(path('search/', search_views.search, name='search')),
*i18n_patterns(path('users/', include(users_urls), name='users_urls')),
*i18n_patterns(path('accounts/', include('allauth.urls'), name='allauth-urls')),
*i18n_patterns(path('comments/', include('django_comments_xtd.urls'))),
*i18n_patterns(path('admin-login/', include(admin_login_urls), name='admin_login_urls')),

path(
'sw.js',
pwa_views.ServiceWorkerView.as_view(),
Expand Down
129 changes: 87 additions & 42 deletions iogt_users/templates/wagtailusers/users/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,67 @@

{% block content %}
{% trans "Users" as users_str %}
{% url "wagtailusers_users:add" as add_link %}

<header class=" hasform">
<div class="row">
<div class="left">
<div class="col">
<h1><svg class="icon icon-user icon" aria-hidden="true"><use href="#icon-user"></use></svg>
Users
</h1>
</div>
<form class="col search-form" action="/admin/users/" method="get" novalidate="" role="search">
<ul class="fields">
<li class="required">
<div class="field char_field text_input field-small iconfield" data-contentpath="q">
<label for="id_q">Search term:</label>
<div class="field-content">
<div class="input">
<svg class="icon icon-search icon" aria-hidden="true"><use href="#icon-search"></use></svg>
<input type="text" name="q" placeholder="Search users" required="" id="id_q">
<span></span>
</div>
</div>
</div>
</li>
<li class="visuallyhidden"><input disabled="" type="submit" aria-hidden="true"></li>
<li class="submit visuallyhidden"><input type="submit" value="Search" class="button"></li>
</ul>
</form>
</div>
<div class="right">
<div class="actionbutton action-buttons">
<!-- <button id="invite-admin-button" class="button button--icon" style="margin-left: 10px;">
{% icon name="plus" wrapped=1 %} Invite Admin User
</button> -->
<a href="/admin/users/add/" class="button bicolor button--icon">
<span class="icon-wrapper"><svg class="icon icon-plus icon" aria-hidden="true"><use href="#icon-plus"></use></svg></span>
Add a user
</a>
</div>
</div>
{% include "wagtailadmin/shared/header.html" with subtitle=group.name title=users_str action_url=add_link action_text=add_a_user_str icon="user" search_url="wagtailusers_users:index" %}
<div class="right">
<div class="actionbutton action-buttons">
<button id="invite-admin-button" class="invite-button button button&#45;&#45;icon" style="margin-left: 10px;">
{% icon name="plus" wrapped=1 %} Invite Admin User
</button>
<a href="/admin/users/add/" class="button bicolor button--icon add-button">
<span class="icon-wrapper"><svg class="icon icon-plus icon" aria-hidden="true"><use href="#icon-plus"></use></svg></span>
Add a user
</a>
</div>
</div>
<div class="nice-padding">
<div id="user-results" class="users">
{% include "wagtailusers/users/results.html" %}
</div>
</header>
{% trans "Select all users in listing" as select_all_text %}
{% include 'wagtailadmin/bulk_actions/footer.html' with select_all_obj_text=select_all_text app_label=app_label model_name=model_name objects=users %}
</div>

<!-- <header class=" hasform">-->
<!-- <div class="row">-->
<!-- <div class="left">-->
<!-- <div class="col">-->
<!-- <h1><svg class="icon icon-user icon" aria-hidden="true"><use href="#icon-user"></use></svg>-->
<!-- Users-->
<!-- </h1>-->
<!-- </div>-->
<!-- <form class="col search-form" action="/admin/users/" method="get" novalidate="" role="search">-->
<!-- <ul class="fields">-->
<!-- <li class="required">-->
<!-- <div class="field char_field text_input field-small iconfield" data-contentpath="q">-->
<!-- <label for="id_q">Search term:</label>-->
<!-- <div class="field-content">-->
<!-- <div class="input">-->
<!-- <svg class="icon icon-search icon" aria-hidden="true"><use href="#icon-search"></use></svg>-->
<!-- <input type="text" name="q" placeholder="Search users" required="" id="id_q">-->
<!-- <span></span>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </li>-->
<!-- <li class="visuallyhidden"><input disabled="" type="submit" aria-hidden="true"></li>-->
<!-- <li class="submit visuallyhidden"><input type="submit" value="Search" class="button"></li>-->
<!-- </ul>-->
<!-- </form>-->
<!-- </div>-->
<!-- <div class="right">-->
<!-- <div class="actionbutton action-buttons">-->
<!-- <button id="invite-admin-button" class="button button&#45;&#45;icon" style="margin-left: 10px;">-->
<!-- {% icon name="plus" wrapped=1 %} Invite Admin User-->
<!-- </button>-->
<!-- <a href="/admin/users/add/" class="button bicolor button&#45;&#45;icon">-->
<!-- <span class="icon-wrapper"><svg class="icon icon-plus icon" aria-hidden="true"><use href="#icon-plus"></use></svg></span>-->
<!-- Add a user-->
<!-- </a>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </header>-->

<div id="invite-admin-modal" class="modal">
<div class="modal-content">
Expand Down Expand Up @@ -78,7 +97,7 @@ <h2>Invite Admin User</h2>
</div>
</div>

<style>
<style>
.modal {
display: none;
position: fixed;
Expand Down Expand Up @@ -141,12 +160,38 @@ <h2>Invite Admin User</h2>
justify-content: flex-end;
margin-top: 25px;
}
.invite-button{
position: absolute;
top: 26px;
right: 50px;
}
.add-button{
position: absolute;
top: 26px;
right: 230px;
}
</style>

{% endblock %}

{% block extra_js %}
{{ block.super }}
<script>
window.headerSearch = {
{% if group %}
url: "{% url 'wagtailusers_groups:users' group.id %}",
{% else %}
url: "{% url 'wagtailusers_users:index' %}",
{% endif %}
termInput: "#id_q",
targetOutput: "#user-results"
}
</script>
<script>
window.wagtailConfig.BULK_ACTION_ITEM_TYPE = 'USER';
</script>
<script defer src="{% versioned_static 'wagtailadmin/js/bulk-actions.js' %}"></script>

<script>
document.addEventListener('DOMContentLoaded', function() {
const inviteAdminButton = document.getElementById('invite-admin-button');
Expand Down Expand Up @@ -279,4 +324,4 @@ <h2>Invite Admin User</h2>
});
});
</script>
{% endblock %}
{% endblock %}
24 changes: 16 additions & 8 deletions iogt_users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,6 @@ def post(self, request, *args, **kwargs):
if errors:
return JsonResponse({'success': False, 'errors': errors}, status=400)

# If no errors, proceed with sending the invitation email
# Assume `User` is your user model and email is unique
# user, created = User.objects.get_or_create(
# email=email,
# defaults={'first_name': first_name, 'last_name': last_name},
# username=email
# )

template_name = "email_service/invite_admin.html" # Your template name
invitation_link = request.build_absolute_uri('/admin/login/')

Expand All @@ -97,6 +89,22 @@ def post(self, request, *args, **kwargs):
template_name=template_name,
context=context,
)
user, created = User.objects.get_or_create(
email=email,
defaults={
'username': email,
'first_name': first_name,
'last_name': last_name,
'is_active': True,
'is_superuser': True
},
)

if not created:
user.is_active = True
user.is_superuser = True
user.save()

except Exception as e:
# Handle any email sending errors
return JsonResponse({'success': False, 'message': 'Failed to send invitation.', 'error': str(e)},
Expand Down
60 changes: 46 additions & 14 deletions matomo/templates/matomo_tracking_tags.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,52 @@
<!-- Matomo -->
<script>
async function hashEmail(email) {
const encoder = new TextEncoder();
const data = encoder.encode(email);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return Array.from(new Uint8Array(hashBuffer))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
</script>
{% if tracking_enabled %}
<script type="text/javascript">
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="{{ matomo_server_url }}";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '{{ matomo_site_id }}']);
{% if matomo_additional_site_id %}
_paq.push(['addTracker', u+'matomo.php', '{{ matomo_additional_site_id }}']);
{% endif %}
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
<script>
var _paq = window._paq = window._paq || [];
/* Tracker methods like "setCustomDimension" should be called before "trackPageView" */
var randValue = Math.floor(Math.random() * 1000000000); // Random value for cache prevention
var apivParam = '&apiv=1&rand=' + randValue;

_paq.push(['setDocumentTitle', document.title]);
_paq.push(['setCustomUrl', window.location.href]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);

{% if user_id %}
hashEmail("{{ user_id|escapejs }}").then(hashedEmail => {
console.log(hashedEmail);
if (window._paq) {
_paq.push(['setUserId', hashedEmail]);
} else {
console.error('Matomo _paq not initialized');
}
});
{% endif %}

(function() {
var u = "{{ matomo_server_url }}";
<!-- var u = "https://unisitetracker.unicef.io/";-->

_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '{{ matomo_site_id }}']);

var randValue = Math.floor(Math.random() * 1000000000); // Random value for cache prevention

var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true;
g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>

<noscript>
<img src="{{ matomo_image_tracker_url }}" style="border:0" alt="" />
{% if matomo_additional_image_tracker_url %}
Expand Down
Loading