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
1 change: 1 addition & 0 deletions admin/institutions/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def get_context_data(self, *args, **kwargs):
institution_dict = model_to_dict(institution)
kwargs.setdefault('page_number', self.request.GET.get('page', '1'))
kwargs['institution'] = institution_dict
kwargs['cas_login_url'] = institution.cas_login_url
kwargs['logo_path'] = institution.logo_path
kwargs['banner_path'] = institution.banner_path
fields = institution_dict
Expand Down
70 changes: 69 additions & 1 deletion admin/templates/institutions/detail.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
{% extends "base.html" %}
{% load static %}
{% block top_includes %}
<link rel="stylesheet" type="text/css" href="/static/css/institutions.css" />
<link rel="stylesheet" type="text/css" href="/static/css/institutions.css" />
<style>
#copy-modal {
display: none; /* hidden by default */

position: fixed;
z-index: 2000;
inset: 0;
}
#copy-modal.show_modal {
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
#copy-modal .modal-content {
background: white;
width: 100%;
max-width: 600px;
max-height: 80vh;
padding: 20px;
border-radius: 10px;

display: flex;
flex-direction: column;
gap: 10px;
overflow: hidden;
}
</style>
{% endblock %}
{% load comment_extras %}
{% block title %}
Expand Down Expand Up @@ -33,6 +61,20 @@
{% if perms.osf.change_institution %}
<a class="btn btn-primary" href={% url 'institutions:list_and_add_admin' institution.id %}>Manage Admins</a>
{% endif %}

{% if cas_login_url %}
<button class="btn btn-primary" onclick="openCopyPopup('{{ cas_login_url|escapejs }}')">
Copy SSO URL
</button>

<div id="copy-modal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeCopyPopup()">&times;</span>
<p>Value copied. You can also copy manually:</p>
<textarea id="copy-input" readonly></textarea>
</div>
</div>
{% endif %}
</div>
</div>

Expand Down Expand Up @@ -168,5 +210,31 @@ <h3>Are you sure you want to run monthly report for this institution?</h3>
});
});
});

window.openCopyPopup = function(text) {
const modal = document.getElementById("copy-modal");
const input = document.getElementById("copy-input");

input.value = text;

modal.classList.add("show_modal");

navigator.clipboard.writeText(text).catch(() => {});

input.focus();
input.select();
};

window.closeCopyPopup = function() {
document.getElementById("copy-modal").classList.remove("show_modal");
};

// Close on outside click
window.onclick = function(event) {
const modal = document.getElementById("copy-modal");
if (event.target === modal) {
modal.classList.remove("show_modal");
}
};
</script>
{% endblock %}
13 changes: 13 additions & 0 deletions osf/models/institution.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from .validators import validate_email
from osf.utils.fields import NonNaiveDateTimeField, LowercaseEmailField
from website import settings as website_settings
from urllib.parse import quote

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -208,6 +209,18 @@ def banner_path(self):
except InstitutionAssetFile.DoesNotExist:
return '/static/img/institutions/banners/placeholder-banner.png'

@property
def cas_login_url(self):
if self.delegation_protocol == IntegrationType.NONE.value:
return None
if 'localhost' in website_settings.DOMAIN:
next_param = quote(website_settings.PROTOCOL + website_settings.LOCAL_ANGULAR_URL, safe='')
else:
next_param = quote(website_settings.DOMAIN, safe='')
service_url = quote(f'{website_settings.DOMAIN}login?next={next_param}', safe='')

return f'{website_settings.CAS_SERVER_URL}/login?campaign=institution&institutionId={self._id}&service={service_url}'

def update_search(self):
from website.search.search import update_institution
from website.search.exceptions import SearchUnavailableError
Expand Down
Loading