Manage attachments on public record producer in Service Portal

gauravshurvir
Giga Contributor

Hi,

I have created a record producer to capture some information from the user who does not have any role on the instance. It is available for the public. I am rendering it through Service Portal. Have also created some widgets on the portal page. Everything is working fine except attachments. User with some role can easily add/remove attachments on the page but when user without any role  (public user) is trying to attach, nothing is happening. In the console i see an error

find_real_file.png

Has anyone encountered this error ? If yes, can you please advise some workaround.

 I am using attachment widget to manage attachments:

 

find_real_file.png

20 REPLIES 20

Hi @Zdravko Nedev 

I was to reproduce the error. It had something to do with a recent change I made to improve the Multipart Processing. It is fixed now - please sync your forks and then "Apply remote changes" in your ServiceNow instance.

 

While testing I saw that i was missing the rename support, so I quickly implemented this. Some notes however:

  • Because ACLs are checked for public attachments (!), you need to make sure that you have create, read, write (for rename) and delete ACLs on sys_attachment for the "public" role.
    You should configure them so that only access on the 'sc_cart_item' (and 'ZZ_YYsc_cart_item') table and only for attachments created by 'guest' is granted
  • As a general hint: Variables which appear on any public catalog item (or record producer) need to have Read = public (sufficient e.g. for container split/begin/...) and Create = public (for variables that need to be filled). Setting the Write field is *not* needed. (These fields can be found in the 'Permissions' section of a variable)
  • If you want the content-type icon to show (e.g. mini preview for uploaded images), you need to set the property 'glide.image_provider.security_enabled' to false (I do not recommend this - this is just FYI)

Hope this helps.

 

Best regards

Markus

Many thanks for the prompt response and fix.

 

I've added ACLs for create, read, write and delete on record and field level as follows (I've intentionally skipped the conditions for target table and user for now just to keep it simple)

ZdravkoNedev_1-1725010327513.png

 

 

Still I'm getting Unauthorized when I try to upload a file

ZdravkoNedev_0-1725009894384.png

 

 

Thanks.

Hm i remember this issue. There is a decent amount of caching involved with ACLs - for me this initially causing the 401 error.
Note: Im currently building a dedicated application for the ACLs. This also fixes the "cross guest" attachment issues (using plain ACLs only based on public-role will allow a hacker to hijack all attachments uploaded by guest users).

Here is the repo which adds the ACLs:

https://github.com/kr4uzi/ServiceNow-Guest-Attachments

I debugged this a bit and think I have another issue

 

If I change the PublicAttExt script include like so

PublicAttExt.prototype = {
	initialize: function() {
		const scriptGr = new GlideRecord('sys_rte_eb_script_operation');
		scriptGr.addQuery('sys_id', '36991d5593b74a10e02873718bba10b8');
		scriptGr.setLimit(1);
		scriptGr.query();
		if (scriptGr.next()) {
			gs.info('zdr PublicAttExt init')
			this.scriptGr = scriptGr;
		} else {
			throw new Error(`${this.type} requires injectable script record`);
		}
	},

	canCreateAttachment: function (recordTable, recordSysID, fileName, contentType) {
		this.scriptGr.sys_scope = 'global';
		this.scriptGr.script = `
			(function (recordTable, recordSysID, fileName, contentType) {
				var attGr = new GlideRecordSecure('sys_attachment');
				attGr.newRecord();
				attGr.table = recordTable;
				attGr.table_sys_id = recordSysID;
				attGr.setValue('file_name', fileName);
				attGr.content_type = contentType;
				var res = attGr.canCreate();
				gs.info('zdr res' + res)
				return res;
			})(recordTable, recordSysID, fileName, contentType);
		`;

		const gse = new GlideScopedEvaluator();
		var result =  gse.evaluateScript(this.scriptGr, 'script', {
			recordTable: recordTable,
			recordSysID: recordSysID,
			fileName: fileName,
			contentType: contentType
		});

		gs.info('zdr PubAtt result' + result)
		return result;
	},

 

then the result of the GlideScopedEvaluator is always null meaning that the script is not executed and "zdr res" is never logged.

 

I do have the following Cross scope defined

ZdravkoNedev_0-1725029712709.png

However even if I try to execute it in a background script I get this

ZdravkoNedev_1-1725029930557.png

 

 

@Zdravko Nedev Please Sync both the repositories, this should actually be fixed in the latest version of the Multipart / Service Catalog Public Attachment Repositories

 

EDIT: The reason it wasn't properly working is due to xanadu (which prevents a certain kind of dynamic script execution).