Skip to content

Commit

Permalink
Added django-prometheus dependency and adjusted settings.py
Browse files Browse the repository at this point in the history
  • Loading branch information
Iso5786 committed Feb 24, 2025
1 parent fe7a6b2 commit edfac97
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 319 deletions.
102 changes: 46 additions & 56 deletions apps/badgrsocialauth/providers/surf_conext/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from mainsite.models import BadgrApp
from .provider import SurfConextProvider

logger = logging.getLogger("Badgr.Debug")
logger = logging.getLogger('Badgr.Debug')


def login(request):
Expand All @@ -42,35 +42,35 @@ def login(request):
# state contains the data required for the redirect after the login via SURFconext,
# it contains the user token, type of process and which badge_app

referer = request.headers["referer"].split("/")[3]
badgr_app_pk = request.session.get("badgr_app_pk", None)
referer = request.headers['referer'].split('/')[3]
badgr_app_pk = request.session.get('badgr_app_pk', None)
try:
badgr_app_pk = int(badgr_app_pk)
except:
badgr_app_pk = settings.BADGR_APP_ID
state = json.dumps(
[
request.GET.get("process", "login"),
request.GET.get('process', 'login'),
get_session_authcode(request),
badgr_app_pk,
referer,
]
)

params = {
"state": state,
"client_id": settings.SURF_CONEXT_CLIENT,
"response_type": "code",
"scope": "openid",
"redirect_uri": f"{settings.HTTP_ORIGIN}/account/openid/login/callback/",
"claims": '{"id_token":{"preferred_username":null,"given_name":null,'
'state': state,
'client_id': settings.SURF_CONEXT_CLIENT,
'response_type': 'code',
'scope': 'openid',
'redirect_uri': f'{settings.HTTP_ORIGIN}/account/openid/login/callback/',
'claims': '{"id_token":{"preferred_username":null,"given_name":null,'
'"family_name":null,"email":null,"schac_home_organization":null}}',
}
if request.GET.get("force_login") == "True":
params["prompt"] = "login"
if request.GET.get('force_login') == 'True':
params['prompt'] = 'login'
args = urllib.parse.urlencode(params)
# Redirect to eduID and enforce a linked SURFconext user with validated names
login_url = f"{settings.SURFCONEXT_DOMAIN_URL}/authorize?{args}"
login_url = f'{settings.SURFCONEXT_DOMAIN_URL}/authorize?{args}'
return redirect(login_url)


Expand All @@ -95,74 +95,69 @@ def callback(request):
"""
# extract the state of the redirect
if request.user.is_authenticated:
get_account_adapter(request).logout(
request
) # logging in while being authenticated breaks the login procedure
get_account_adapter(request).logout(request) # logging in while being authenticated breaks the login procedure

process, auth_token, badgr_app_pk, referer = json.loads(request.GET.get("state"))
process, auth_token, badgr_app_pk, referer = json.loads(request.GET.get('state'))

code = request.GET.get("code", None)
code = request.GET.get('code', None)
if code is None:
error = "Server error: No userToken found in callback"
error = 'Server error: No userToken found in callback'
return render_authentication_error(request, SurfConextProvider.id, error=error)

# 1. Exchange callback Token for id token
payload = {
"grant_type": "authorization_code",
"redirect_uri": f"{settings.HTTP_ORIGIN}/account/openid/login/callback/",
"code": code,
"scope": "openid",
"client_id": settings.SURF_CONEXT_CLIENT,
"client_secret": settings.SURF_CONEXT_SECRET,
'grant_type': 'authorization_code',
'redirect_uri': f'{settings.HTTP_ORIGIN}/account/openid/login/callback/',
'code': code,
'scope': 'openid',
'client_id': settings.SURF_CONEXT_CLIENT,
'client_secret': settings.SURF_CONEXT_SECRET,
}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Cache-Control": "no-cache",
'Content-Type': 'application/x-www-form-urlencoded',
'Cache-Control': 'no-cache',
}
response = requests.post(
f"{settings.SURFCONEXT_DOMAIN_URL}/token",
f'{settings.SURFCONEXT_DOMAIN_URL}/token',
data=urllib.parse.urlencode(payload),
headers=headers,
)

if response.status_code != 200:
error = (
"Server error: Token endpoint error (http %s) try alternative login methods"
% response.status_code
)
error = 'Server error: Token endpoint error (http %s) try alternative login methods' % response.status_code
return render_authentication_error(request, SurfConextProvider.id, error=error)

data = response.json()
id_token = data.get("id_token", None)
id_token = data.get('id_token', None)

if id_token is None:
error = "Server error: No id_token token, try alternative login methods."
error = 'Server error: No id_token token, try alternative login methods.'
return render_authentication_error(request, SurfConextProvider.id, error=error)

badgr_app = BadgrApp.objects.get(pk=badgr_app_pk)
set_session_badgr_app(request, BadgrApp.objects.get(pk=badgr_app.pk))

payload = jwt.get_unverified_claims(id_token)
for attr in ["sub", "email", "schac_home_organization"]:
for attr in ['sub', 'email', 'schac_home_organization']:
if attr not in payload:
error = f"Sorry, your account does not have a {attr} attribute. Login with SURFconext and then try again"
error = f'Sorry, your account does not have a {attr} attribute. Login with SURFconext and then try again'
logger.error(error)
return render_authentication_error(request, SurfConextProvider.id, error)

# 3. Complete social login and return to frontend
provider = SurfConextProvider(request)
login = provider.sociallogin_from_response(request, payload)
# connect process in which OpenID connects with, either login or connect, if you connect then login user with token
login.state = {"process": process}
login.state = {'process': process}
# login for connect because socialLogin can only connect to request.user
if process == "connect" and request.user.is_anonymous and auth_token:
if process == 'connect' and request.user.is_anonymous and auth_token:
request.user = get_verified_user(auth_token=auth_token)
ret = complete_social_login(request, login)
new_url = ret.url + "&role=teacher"
new_url = ret.url + '&role=teacher'
ret = HttpResponseRedirect(new_url)

if not request.user.is_anonymous: # the social login succeeded
institution_identifier = payload["schac_home_organization"]
institution_identifier = payload['schac_home_organization']
try:
institution = Institution.objects.get(identifier=institution_identifier)
# the institution exists
Expand All @@ -188,20 +183,17 @@ def callback(request):
): # there is no provisionment
extra_context = {}
if institution.email:
extra_context["admin_email"] = institution.email
extra_context['admin_email'] = institution.email
elif institution and institution.cached_staff():
cached_staff = institution.cached_staff()
admins = list(
filter(lambda u: u.may_administrate_users, cached_staff)
)
admins = list(filter(lambda u: u.may_administrate_users, cached_staff))
if len(admins) > 0:
extra_context["admin_email"] = admins[0].user.email
extra_context['admin_email'] = admins[0].user.email

error = "Sorry, you can not register without an invite."
extra_context["code"] = AuthErrorCode.REGISTER_WITHOUT_INVITE
error = 'Sorry, you can not register without an invite.'
extra_context['code'] = AuthErrorCode.REGISTER_WITHOUT_INVITE
if (
request.user.date_joined.today().date()
== datetime.datetime.today().date()
request.user.date_joined.today().date() == datetime.datetime.today().date()
): # extra protection before deletion
request.user.delete()
return render_authentication_error(
Expand All @@ -211,20 +203,18 @@ def callback(request):
extra_context=extra_context,
)

except (
Institution.DoesNotExist
): # no institution yet, and therefore also first login ever
error = "Sorry, your institution has not been created yet."
except Institution.DoesNotExist: # no institution yet, and therefore also first login ever
error = 'Sorry, your institution has not been created yet.'
return render_authentication_error(
request,
SurfConextProvider.id,
error,
extra_context={"code": AuthErrorCode.REGISTER_WITHOUT_INVITE},
extra_context={'code': AuthErrorCode.REGISTER_WITHOUT_INVITE},
)

request.user.accept_general_terms()

# override the response with a redirect to staff dashboard if the login came from there
if referer == "staff":
return HttpResponseRedirect(reverse("admin:index"))
if referer == 'staff':
return HttpResponseRedirect(reverse('admin:index'))
return ret
1 change: 0 additions & 1 deletion apps/badgrsocialauth/redirect_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
path('impersonate/<str:id>', ImpersonateUser.as_view(), name='impersonate_user'),
]


for provider in providers.registry.get_list():
try:
prov_mod = importlib.import_module(provider.get_package() + '.urls')
Expand Down
31 changes: 23 additions & 8 deletions apps/directaward/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,22 @@


class DirectAwardAdmin(admin.ModelAdmin):
list_display = ('id', 'recipient_email', 'eppn', 'created_at', admin_list_linkify('badgeclass', 'name'),
'institution_identifier', 'status')
list_display = (
'id',
'recipient_email',
'eppn',
'created_at',
admin_list_linkify('badgeclass', 'name'),
'institution_identifier',
'status',
)
list_display_links = ('recipient_email', 'eppn')
list_filter = ('created_at', 'badgeclass__name', 'badgeclass__issuer__faculty__institution__identifier')
search_fields = ('recipient_email', 'eppn', 'badgeclass__name',)
search_fields = (
'recipient_email',
'eppn',
'badgeclass__name',
)

@admin.display(
description='Institution',
Expand All @@ -21,12 +32,17 @@ def institution_identifier(self, obj):
return obj.badgeclass.issuer.faculty.institution.identifier



class DirectAwardBundleAdmin(admin.ModelAdmin):
list_display = (
'assertion_count', 'direct_award_count', 'direct_award_rejected_count',
'direct_award_scheduled_count','direct_award_revoked_count',
'created_at', admin_list_linkify('badgeclass', 'name'), 'institution_identifier')
'assertion_count',
'direct_award_count',
'direct_award_rejected_count',
'direct_award_scheduled_count',
'direct_award_revoked_count',
'created_at',
admin_list_linkify('badgeclass', 'name'),
'institution_identifier',
)

list_filter = ('created_at', 'badgeclass__issuer__faculty__institution__identifier')
search_fields = ('badgeclass__name',)
Expand All @@ -39,6 +55,5 @@ def institution_identifier(self, obj):
return obj.badgeclass.issuer.faculty.institution.identifier



badgr_admin.register(DirectAward, DirectAwardAdmin)
badgr_admin.register(DirectAwardBundle, DirectAwardBundleAdmin)
Loading

0 comments on commit edfac97

Please sign in to comment.