Register for InstructureCon25 • Passes include access to all sessions, the expo hall, entertainment and networking events, meals, and extraterrestrial encounters.
Found this content helpful? Log in or sign up to leave a like!
I have added the following JavaScript code to hide the navigation tab in courses for faculty. However, when I have impersonated a user assigned to a sub-account with one of the custom admin account roles I created, they are still able to see the navigation tab when they go into courses. How do I make it so only those users that are assigned the default account admin role can see the navigation tab in Courses?
//hides Navigation tab in course settings var navigationTab = document.getElementById('navigation_tab'); function isAdmin() { if (window.ENV && Array.isArray(window.ENV.current_user_roles)) { return window.ENV.current_user_roles.includes('admin') || window.ENV.current_user_roles.includes('root_admin'); } return false; } if (navigationTab && !isAdmin()) { navigationTab.style.display = 'none'; }
Solved! Go to Solution.
To refer to a specific type of admin user, you will want to use current_user_types instead of current_user_roles. You can then check that it includes "AccountAdmin" for the default account admin role.
ENV.current_user_types.includes("AccountAdmin")
Hi @casey_eubank,
This issue is definitely a frustrating one to deal with, as the ENV variables are not in-context (the array will have "admin" included even if the user is not an admin of the course being viewed, but some other subaccounts) nor does it include custom role info. I've been making an attempt to solve this recently, as documented at Get admin roles through API - Instructure Community. If you have access to Google Apps Script, you could try implementing my solution. The problem is that it involves quite a few API calls for admin roles (it's got to do one API call per subaccount), so it may take a second or two for that to complete. If you only care if the user is a root account full admin, you could strip my code down to just check for that with a single API call not using google API script (the API call may error out for some non-root-admins). I've been hoping others could review my code to see if there may be a more efficient way to code it, but so far there hasn't been much response. With that in mind, it might be better to use CSS to hide the tab by default and then have the javascript unhide it for root admin users.
I hope this helps a bit, and maybe it will get more eyes on my thread too to see if anyone has a better way to do this.
-Chris
That is correct about what I refer to at least as full root admin. You could also try the suggestions posted by @JamesSekcienski, if the subaccount admins (even out of context) could be allowed to see the navigation. The suggestions he gave are definitely simpler if they fit your needs. I have brought this situation up with our CSM, hoping one day Canvas will more easily expose exact and in-context role information in the ENV variable, but doesn't seem like that will be coming too soon.
-Chris
To refer to a specific type of admin user, you will want to use current_user_types instead of current_user_roles. You can then check that it includes "AccountAdmin" for the default account admin role.
ENV.current_user_types.includes("AccountAdmin")
You could also evaluate the admin role permissions that you have enabled on the custom roles. If you disable the "Manage Courses" permission or the more granular "Courses - manage/update" permission it should take away the ability to access the Navigation tab. However, there are other permissions tied to it that you would need to consider if they still need those permissions too or not.
So the code would look like this with changes in bold? Would this still also hide the navigation tab from faculty too?
//hides Navigation tab in course settings
var navigationTab = document.getElementById('navigation_tab');
function isAdmin() {
if (window.ENV && Array.isArray(window.ENV.current_user_types)) {
return window.ENV.current_user_types.includes('AccountAdmin') || window.ENV.current_user_types.includes('root_admin');
}
return false;
}
if (navigationTab && !isAdmin()) {
navigationTab.style.display = 'none';
}
Hi @casey_eubank,
I'm still a bit unsure about your overall goal, but the code you pasted is not quite right regardless. Are you trying to only show the navigation menu to users who are full admins in the root account, only show it to people who are full admins in any account/subaccount, or only to people who are any kind of admin (including custom roles) in the root account (I'm pretty sure it's one of these three you're trying to do, but please tell us if it's actually something else)?
If your code snippet, you're mixing up the user_roles and user_types, which is going to give the wrong results. AccountAdmin is found in current_user_types, while root_admin is found in current_user_roles. If you want to check for people who are *likely* to be full admins in a root account, you could try something like:
var navigationTab = document.getElementById('navigation_tab');
function isAdmin() {
return window.ENV && Array.isArray(window.ENV.current_user_types) && window.ENV.current_user_types.includes('AccountAdmin') && Array.isArray(window.ENV.current_user_roles) && window.ENV.current_user_roles.includes('root_admin');
}
if (navigationTab && !isAdmin())
navigationTab.style.display = 'none';
This still has a caveat that the ENV array isn't context aware, so it's possible that a user would be a custom admin role in the root account, but a full admin of a subaccount, and this code would still return true for the isAdmin because both things being checked would be there, just out of context. That's what my much fancier (and admittedly overkill for some things) code tries to fix. However, the above code would hide the navigation tab (if it exists when the code is run) from any user who is not both some kind of admin in the root account and a full admin in any account/subaccount in your Canvas instance.
The code above definitely works from the debug console, but I didn't try putting it in the theme JS.... There are situations where some page content is dynamically loaded and cusom javascript runs before the content is there, which could basically make the code inoperable. If that happens to be the case, you'd need to add additional code (perhaps a MutationObserver) to watch for elements to be loaded then take action. Even though I've gotten them to work in my code a couple times, I still have trouble wrapping my head around MutationObservers, so I definitely wouldn't be the best person to explain how to use them.
Hope this helps. If I got anything wrong here, I'm sure @JamesSekcienski will notice and correct me. I just figured I'd chime in since I got a notification about your reply.
-Chris
@chriscas Great points about the potential ways in which this may not still be a 100% accurate and the potential issue of needing a MutationObserver if the full rendering of the tab is delayed. I agree that the admin check does seem sufficiently accurate for this scenario.
@casey_eubank Another thing you may want to consider is hiding the tab by default with CSS and using JavaScript to unhide it for Account Admins. This can help avoid potential flickers/temporary visibility while the code is processing to change it from visible to hidden. It also makes sure it is hidden by default even if this script happens to run before the navigation tab is added. However, you would still need to learn to use Mutation Observers to unhide it for admin if the script is processing before the tab is added.
The custom class that is used below is 'abc-show-tab' but you could make it anything you want as long as it is likely to be unique from the classes generated by Canvas.
#navigation_tab {
display: none;
}
#navigation_tab.abc-show-tab {
display: list-item;
}
const navigationTab = document.getElementById('navigation_tab');
function isAdmin() {
return window.ENV && Array.isArray(window.ENV.current_user_types) && window.ENV.current_user_types.includes('AccountAdmin') && Array.isArray(window.ENV.current_user_roles) && window.ENV.current_user_roles.includes('root_admin');
}
if (navigationTab && isAdmin()) {
navigationTab.classList.add('abc-show-tab');
}
As a reminder, this approach is only to limit ease of access. As long as the users still have the permission to view and edit course navigation, someone with the technical knowledge could gain access and/or make changes.
Hi Chris
So if I only want to show the navigation tab to users who are full account admins only in the root subaccount, I would use this code?
var navigationTab = document.getElementById('navigation_tab');
function isAdmin() {
return window.ENV && Array.isArray(window.ENV.current_user_types) && window.ENV.current_user_types.includes('AccountAdmin') && Array.isArray(window.ENV.current_user_roles) && window.ENV.current_user_roles.includes('root_admin');
}
if (navigationTab && !isAdmin())
navigationTab.style.display = 'none';
Hi @casey_eubank,
Yes, I think that's the closest thing you can get with more simplicity (given the caveats we discussed above). If it doesn't work as part of your theme JavaScript, you'll probably need to figure out a MutationObserver to activate the code at the proper time.
-Chris
Hi @chris thanks to you and @JamesSekcienski for all your help!
That did not seem to work in my Beta environment, unfortunately.
I am not versed in JavaScript unfortunately but hope to learn it soon to fix issues like this in the future.
In the meantime, would you and/or @JamesSekcienski be willing to join a Zoom call with me to take a look?
Thanks so much for all your help with this issue!!!!
When you say it didn't work, what happened when you tested it? Did you act as a few different types of users to see what happened (root admin, non-root admin, custom role admin, teacher)?
You can also adjust the code some to include some console.log statements to help see where something may be going wrong.
var navigationTab = document.getElementById('navigation_tab');
function isAdmin() {
return window.ENV && Array.isArray(window.ENV.current_user_types) && window.ENV.current_user_types.includes('AccountAdmin') && Array.isArray(window.ENV.current_user_roles) && window.ENV.current_user_roles.includes('root_admin');
}
if (!navigationTab) {
console.log("No navigation tab found");
} else if (navigationTab && !isAdmin()) {
console.log("Not an admin. Need to hide navigation tab");
navigationTab.style.display = 'none';
} else {
console.log("User is an admin. Navigation tab should display.");
}
Can I recommend this also gets wrapped in a route specific condition.
if (/\/courses\/\d+\/settings/.test(window.location.pathname)) {
// keeps that code from running on all other routes, especially the login where ENV is not complete until the user is logged in.
}
Hi @casey_eubank,
This issue is definitely a frustrating one to deal with, as the ENV variables are not in-context (the array will have "admin" included even if the user is not an admin of the course being viewed, but some other subaccounts) nor does it include custom role info. I've been making an attempt to solve this recently, as documented at Get admin roles through API - Instructure Community. If you have access to Google Apps Script, you could try implementing my solution. The problem is that it involves quite a few API calls for admin roles (it's got to do one API call per subaccount), so it may take a second or two for that to complete. If you only care if the user is a root account full admin, you could strip my code down to just check for that with a single API call not using google API script (the API call may error out for some non-root-admins). I've been hoping others could review my code to see if there may be a more efficient way to code it, but so far there hasn't been much response. With that in mind, it might be better to use CSS to hide the tab by default and then have the javascript unhide it for root admin users.
I hope this helps a bit, and maybe it will get more eyes on my thread too to see if anyone has a better way to do this.
-Chris
Thank you, Chris! I am not that well versed in APIs but will try to see if I can follow your documentation.
Just to clarify what a root_admin is - that would be a person who has been assigned the default account admin role (no modifications) that is in the permission in the root account and not not any sub-accounts, correct?
That is correct about what I refer to at least as full root admin. You could also try the suggestions posted by @JamesSekcienski, if the subaccount admins (even out of context) could be allowed to see the navigation. The suggestions he gave are definitely simpler if they fit your needs. I have brought this situation up with our CSM, hoping one day Canvas will more easily expose exact and in-context role information in the ENV variable, but doesn't seem like that will be coming too soon.
-Chris
To interact with Panda Bot in the Instructure Community, you need to sign up or log in:
Sign In