Skip to main content


Minimally Represented User 🥷🏿
Published onJun 29, 2022

There exist a certain user for PubPub that does not need to be represented to the full atomicity as a PubPub user. This user is typically created by the act of someone with manager permission. This user never exists as a scoped member either. For example, AttributableUser[1].

export type AttributableUser = {
	id: string;
	slug: string;
	initials: string;
	fullName: string;

Let’s consider Attributions

When we enter a user’s name into ‘Add new person’, under the hood a check is happening to see if the new person is a PubPub member. If they are huzzah, no need to do much. If not an AttributableUser will be created.

Hopefully, we can begin to see that AttributableUser belong to the class mentioned above. Fields on the User type are even derived from AttributalUser, hinting this kind of user is at least definitely a base type of User

export type User = AttributableUser & {
	slug: string;
	bio: string;
	publicEmail: string;

If not, let us consider what happens when the byline is rendered.

Since Alphonse Elric is only a AttributableUser they cannot log in and have no permission to do much of anything. But since qwelian is, he can. How do we reckon two different types of users? Notice list on byline is checked. To render the byline we pull a user from ensureUserForAttribution()[2]. This function will return a user object because none exists for the user. That user object is populated with information from the attribution if they do not exist. To render the list you see above we check if the user is a member or not using isShadowUser. The Attribution may or may not have a User object on it is the point of this. And whenever we interact with attributions we need to account for this.

New type MinUser = {}

To avoid this complexity we could try to represent an attribution or review user as this type. A MinUser can be extended to be any user type. I think the initial value is a clear inheritance pattern for User types. As for future development, it may be interesting to store JSON blobs of viewOnly objects that will be rendered in their views. But maybe not.

type MinUser = {
     id: string;
     email: string;
     accessTo?: (Attribution |...<T>)[];

With this, the Attribution only ever needs to be responsible for itself. Not some user type.

some of the relevant files

client/components/AttributionEditor/AttributionRow.tsx (row 38-45)


client/components/Byline/Byline.tsx (line 9 check for user is real)


No comments here
Why not start the discussion?