- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-11-2018 08:03 PM
Hi all,
I'm looking at setting up a processor that allows shorter URL's to KB articles. I was wondering if there's a good way to allow external access (Via ACL?) to a specific processor?
Background
Links to our KB articles currently look like:
https://instancename.service-now.com/csm?id=kb_article&sys_id=7abc123odadoiwagbdwaiohvsuicpoe6
I've got a processor which shortens the links to:
https://instancename.service-now.com/help?article=KB00001
The marketing department will be much happier pasting this into their social media links!
The Processor
It's a relatively simple thing that executes the following:
(function process(g_request, g_response, g_processor) {
var article = g_request.getParameter("article");
//Query table for Knowledge article
var kb = new GlideRecord('kb_knowledge');
kb.addQuery('number', article); //Key, query value
kb.query();
//Default url if not found
var url = 'https://devinstance.service-now.com/csm';
//While we have results
while (kb.next()) {
if (kb.number.toString() == article.toString()){
url = url + '?id=kb_article&sys_id=' + kb.sys_id.toString();
}
}
//Redrect to base csm addr or found kb article
g_processor.redirect(url);
})(g_request, g_response, g_processor);
The CSM endpoint is accessible by external users, they don't need to be logged in to navigate the service portal and read KB and News articles.
However, this processor is set up in the global namespace with the previously mentioned /help endpoint.
Navigating to <instance.com>/help requires a user to log in.
Is there a safe way to enable access to this specific endpoint for external users?
Any comments are appreciated!
Regards,
David
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-13-2018 06:23 AM
Got it.
to make the processor public you need to do 1 or 2 things. If you don't have CSM or any other application that might activate the snc_internal/snc_external roles then you just need step 1.
1. Create the processor, go to sys_public.list and add the path there. Then in the url use <path>.do and it will work.
2. if you have the snc-roles thingie. Then you also need to edit the roles field on the processor. Now this isn't visible from start and ServiceNow has been kind to add the role snc_internal there by default which of course the none loggedin user doesn't have. Here you need to remove that and then add the role public instead.
Then it should work :). I think I'll make a video of this 🙂 and steal your idea about it 😉
//Göran
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-15-2018 12:35 AM
For fun, if you just try to redirect to /csm and not anything with knowledge etc. does it still redirect to SSO. Just to verify it isn't something else with the portal.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-15-2018 02:18 PM
Good call, I just realised that I don't believe I've tried accessing /help.do as my admin account. I previously just attempted it with the public user (Not snc_external as I now know! Ironically it's an internal role for accounts to mark that they're external from the business, as opposed to external from the system, which is public)
I noticed that I'd forgotten to add the public page, so I've activated that module and added an active record in Global for "help" (I dont believe the public page entry requires a .do)
Now a public user can access the endpoint without having to log in!
But the result is a "page not found" for help.do
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-15-2018 02:24 PM
Ah, forgive me again, it seems that all references to the "help.do" endpoint need to be named "help" and then just referenced as .do when accessing it outside, it's now working and avoiding the SSO!
Thank you so much for your help, I'll be sure to poke around for hidden records when trying to tweak the instance next time, as mentioned before, if you do make the video please share it with me, would be great to see!
Thanks again,
David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-25-2018 04:16 AM
Btw. here is the video 😃
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-26-2018 12:25 PM
Nice video! I'll keep an eye out for more of them on your channel 🙂
As a small extension of this processor (The marketing team demanded more than just the KB Article number, ho hum) I've added a custom field to the KB Article table called "Friendly name", which allows the marketing team to 'add their own urls'.
Plus a small sanity check for internal / external articles. If a non logged in user tries to view an internal article then the ACL's will restrict their access, however it's a little bit neater to redirect them to the /csm page instead of a "Article not found" page.
The code now looks a little like this:
//g_response.setContentType('text/html;charset=UTF-8'); // Not necessary here, but may serve use in future
(function process(g_request, g_response, g_processor) {
//
// Be aware, debugging with writeOutput will nullify the effects of a redirect
// Remember to comment them out when done debugging
//
//Hard coded example
//g_processor.redirect('https://instancename.service-now.com/csm?id=kb_article&sys_id=7070431f4f9f5b009417d6ef0310c726');
// Parameters
var article = g_request.getParameter("article");
var friendly_name = g_request.getParameter("help");
//Find external knowledge base id
var kb = new GlideRecord('kb_knowledge_base');
kb.addQuery('title', 'External Knowledge Base');
kb.query();
var knowledge_base_id;
while (kb.next()){
if (kb.title.toString() == 'External Knowledge Base'){
knowledge_base_id = kb.sys_id;
}
}
//Catches 404's -- Shouldn't occur, but good practice
var url = 'https://instancename.service-now.com/csm';
if (!knowledge_base_id){
g_processor.redirect(url);
}
var kba;
if (article) {
//Query table for Knowledge article
kba = new GlideRecord('kb_knowledge');
kba.addQuery('number', article); //Key, query value
kba.query();
// Make sure attributes match
while (kba.next()) {
if (kba.number.toString() == article.toString()){
if(kba.kb_knowledge_base.toString() == knowledge_base_id.toString()) {
url = url + '?id=kb_article&sys_id=' + kba.sys_id.toString();
g_processor.redirect(url);
}
}
}
}
if (friendly_name) {
// For friendly urls
//Query table for Knowledge article
kba = new GlideRecord('kb_knowledge');
kba.addQuery('u_friendly_url', friendly_name); //Key, query value
kba.query();
// Make sure attributes match
while (kba.next()) {
if (kba.u_friendly_url.toString() == friendly_name.toString()){
if(kba.kb_knowledge_base.toString() == knowledge_base_id.toString()) {
url = url + '?id=kb_article&sys_id=' + kba.sys_id.toString();
g_processor.redirect(url);
}
}
}
}
//Redrect to base csm addr or found kb article
g_processor.redirect(url);
})(g_request, g_response, g_processor);
There's alot of duplicate code there, but it was a quick and easy copy and paste job that ended up working, I had tried playing with extracting the GlideRecord queries to a separate function called findRow() but the results when passing back a GlideRecord object were a little interesting, it returned null rows even when calling GlideRecord.next() in the function
Maybe I'll tidy it up on day, but this seems to be a good functional start! (Not fully tested, that's today's job 😉 )
Thanks again for your help!