✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now

Discussion on creating a unique identifier for payment tickets using the document's _id in a slug field.

6 replies
Last updated: Aug 14, 2022
I’m stuck at trying to write a slugifier that adds the current document’s
_id
value to a slug field. My intention is to have a slug that is created based on a couple of values from the same document but I can only have a single source, correct? I’m seeing that a function can also be used as the source, but I’m kinda lost . What would be the best approach? Is there a way to add the
_id
(also slicing the first 7 characters to remove ‘drafts.’)
Aug 13, 2022, 8:57 PM
Hi Guillermo. When you write a function for your slug source, it can include conditional logic or multiple sources. With a few more details on what you’re after, we could elaborate.
To use the
_id
as you asked, you could do something like:

{
	name: 'slug',
	title: 'Slug',
	type: 'slug',
	options: {
		source: (doc) => {
			return doc?._id ? doc._id.replace(/^drafts./,'') : ''
		}
	}
}
A brand new document won’t have an
_id
set, so you may want to handle that situation better. In the code above, you’d have to press the “Generate” button twice (once to give the document an
_id
, and again to generate the slug).
Aug 13, 2022, 9:13 PM
Hi
user A
. That’s exactly what I was trying to achieve. I’ll give a bit more background. I’m creating payment tickets, for which the schema generates a slug field that can be copied and then emailed to our clients. The current slug takes in
orderId
as an input, and creates a slug in the following fashion:
<http://mydomain.com/store/ticket?orderId=768766|mydomain.com/store/ticket?orderId=768766>
where ‘768766’ is the value used as an identifier.
However, this presents a problem as anyone with the link can simply try different numbers and see other active tickets (which show client’s name and details) and obviously I don’t want that.

Sooo, the solution I came up with was to have a unique identifier in the URL to use as a challenge. Since the
_id
is unique for every document, I thought about adding that to the URL, like so:

<http://mydomain.com/store/ticket?orderId=768766&challenge=72117b40-b0b8-4c9f|mydomain.com/store/ticket?orderId=768766&challenge=72117b40-b0b8-4c9f>

This way I can capture both URL params and pass them to my query . If they match, I show the ticket details. There’s no way anyone will be able to guess that pair of values. Does it make any sense?
Aug 13, 2022, 9:24 PM
Thanks for that extra detail. I’m not too sure about best practices around slugs and query parameters like that, but I’m sure someone else will pick that question up. Have a good weekend!
Aug 13, 2022, 9:59 PM
Thank you! I think that having an extra url param to check if it matches other values is standard, at least it sound logical to me.
Aug 13, 2022, 10:04 PM
I guess I can just use the
_id
instead of trying to match two values. Might be easier.
Aug 13, 2022, 10:35 PM
user N
I can't vouch for best practices either, but in some versions of Woocommerce the order page's URL param is a similar approach to yours with just a single param derived from the order ID while not citing it directly.
If you know the secret sauce in the Studio and in the front end (perhaps salted by an environment variable) you could generate something so elaborate that nobody is realistically going to arrive at it randomly, but you can descramble it as necessary to pull up the actual decent and normal ID.

Like my

<http://domain.com/store/ticket?orderId=puX6xKvKjKVDrdOxdyIrgHHrb9imw1Vza|domain.com/store/ticket?orderId=puX6xKvKjKVDrdOxdyIrgHHrb9imw1Vza>
where you ran the order ID through a cryptographic function using a specific a single secret word of phrase to inform the scrambling as a separate parameter.

The Studio would ideally just be you and your colleagues so it's less of an issue if the secret phrase is known if hunted for in the source, and then in the front end the formula could be in the source but the phrase stored in an environment variable.

So the Studio would have the encrypt function using it, and the front end could have the decrypt where it's descrambling with the most important bit that nobody can see.

I used to use a version of that approach to secure documents in PHP, but what I would do is the code would reference the true details (like a doc ID or a filename) and stick that as a data attribute in the markup, then if someone clicked the resulting markup it would attempt a fetch for another function (which also knew the secret) and attempt to validate it.
Aug 14, 2022, 7:16 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?