How to create unique codes for private groups in Firebase

Published on Jul 21, 2022
~6 min read

If you search Google with terms like "firestore unique 6 digit code", "firestore ensure usernames are unique" or "firestore unique field" you'll quickly find that it is not supported natively by Firebase. People will suggest doing things like slicing the document ID to get a unique code or even using the unique uuid, but that isn't great for users. Users need something more human readable.

So I have come up with a hacky little solution that will allow you to create unique ids or codes that are human readable in firestore.

Firestore data model

Let's say our application is a photo sharing application where users can share photos with private groups. Our data model will look like the below.

JS
Collection: groups
Doc: group
name: 'group-1'
groupCode: 'LVGHYE'
members: [],
Collection: groupCodes
doc: 'LVGHYE'
group: group
collection: photos
doc: photo
group: group
photoURL: 'some bucket address'

This data modal is going to allow us to check if a randomly generated code already exists in the groupCodes collection, if that code is unique we will add it as a doc to our groupCodes collection and link it to a group doc in our groups collection.

So how do we do that? Let's look first at a quick random code generator function.

Generate unique code for Firestore

To generate a unique code we need to do the client side, Firestore currently doesn't have a solution for this. However, the benefit of this is that we can make it human readable which is better for user experience than someone having to enter 4y5mJ*.

JS
export const randomCode = () => {
let code = '';
const alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const codeLength = 6;
for (let i = 0; i < codeLength; i++) {
code += alpha.charAt(Math.floor(Math.random() * alpha.length));
}
return code;
};

The above function will generate a unique 6 digit capitalised code. We are going to use this function to generate a unqiue code at the time the user needs it.

So let's look at how we can ensure this code is unique in Firestore.

Ensuring unique field in firestore

The chances of the code we generate in the randomCode() function not being unique are quiet low since 26^6 generates 300+ million unique codes. However, we want to be 100% sure that a user will get a unique code. Could you imagine if a user got access to someones private photo's, that would be a very bad experience for those involved.

To ensure the code is unique we will run a checkCodeUnique function at the time a user goes to create a new group.

JSX
import { db, auth } from '../../firebase';
import { collection, getDocs } from 'firebase/firestore';
let groupCode = randomCode();
const checkCode = async () => {
const docRef = doc(db, 'groupCodes', groupCode);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
console.log('Document data already exists');
groupCode = randomCode();
} else {
console.log('No such document! with ', groupCode);
await setDoc(doc(db, 'groupCodes', groupCode), {
group: '',
});
}
};

Let's go through what is happening above. First, we call our randomCode() function to set a groupCode, this happens as soon as the user access this component.

Next we setup our checkCodeUnique function. The first thing we do in this function look for a doc with the randomly generated groupCode in our groupCodes collection (that sentence is a monthful). Then we conditionally conditionally check if it exists. If it does exist we will regenerate the random code. If it doesn't exist we will then create a new doc in our groupsCode collection and set the id to be the randomly generated groupCode so no one else can use it again in the future.

So we have a way for ensuring our codes are unique, now we need to link the code to group and vice-versa.

Creating private groups

Now we have a unique code as the id of our groupCode doc in our groupCodes collection, we need to assign that group code to a group. This is a one-to-one relationships, as one groupCode can only have one group.

Below is the code to do this, have a look over it and I'll explain what is happening below.

JSX
import { collection, getDoc, doc, addDoc, setDoc } from 'firebase/firestore';
const writeNewGroup = async () => {
await checkCode();
try {
let groupRef = await addDoc(collection(db, 'groups'), {
name: groupName,
owner: user.uid,
groupCode: groupCode,
members: [user.uid],
});
await setDoc(doc(db, 'groupCodes', groupCode), {
group: groupRef.id,
});
} catch (e) {
console.error('Error adding document: ', e);
}
};

So the first thing we do in this function is we call our checkCode() function to ensure we have a unique code for the group. The next thing we do is we create a new group doc. In this group doc we set the field groupCode to the unique code we just created. Next, we set the group field in the groupCode doc to the id of the group doc we just created which sets up our one-to-one relationship.

That is all there is to it, you now have a nice little hacky way to create unique, private, human readable codes for your application.

//TODO: // I might want to add some images of what the firestore setup looks like // change the setDoc method to and update doc method

Picture of author

Peter Lynch

Web Developer & Bootcamp grad who wants to learn as much as he can check me out on twitter.

Starting from the bottom newsletter

This newsletter is a record of my journey as an indie hacker, developer, entrepreneur, and human. Delivered straight to your inbox each Sunday.