Mosaic products documentation: Concepts, API Reference, Technical articles, How-to, Downloads and tools

Manage User Profiles

Introduction

@axinom/mosaic-user-auth is a react library provided to be used by the frontend application to make end-user related authentication and other end-user related operations easier.

This article describes the use case where the methods exposed by this library can be used to manage user profiles in an end-user application.

Working with User Profiles

In addition to user authentication, the user service and @axinom/mosaic-user-auth library provides functionality related to user profile management.

Every user is assigned a user profile by default. The end-user application developer have the choice to decide if they want multiple user profiles per user or there will be no concept of user profiles. In case of the former, the developers can make use of the following methods exposed by the @axinom/mosaic-user-auth library to manage user profiles.

Either way, the user access token that is generated by the user service will contain the User Profile ID in addition to the User ID, which will be subsequently be used in the Personalization service. (For applications that do not implement a user profile concept, the default user profile created for the user will be used.)

Retrieving all available profiles for a user

When a user has multiple profiles, the first thing after the authentication process would be to display a list of user profiles on screen for the signed in user to proceed. The below code example shows how we can retrieve the user profiles for a user.

const {
  getUserProfiles
} = useUserService();

const userProfiles = await getUserProfiles();

Setting the Active Profile for the session

The active profile for the session can then be set by passing the required profile ID to the setActiveProfile method.

const {
  setActiveProfile
} = useUserService();

await setActiveProfile(profileId);

Create new User Profile

A new user profile for a user can be created using the createUserProfile method. It only takes the Display Name as the argument.

const {
  createUserProfile
} = useUserService();

await createUserProfile(displayName);

Delete a User Profile

A user profile can be deleted using the deleteUserProfile method. The ID of the user profile to be deleted must be passed.

const {
  deleteUserProfile
} = useUserService();

await deleteUserProfile(profileId);

Edit a User Profile

A user profile has properties defined by the UserProfile interface. The updateUserProfile takes a UserProfile object as the argument and updates the properties against its profile ID.

const {
  updateUserProfile
} = useUserService();

const profileToUpdate: UserProfile = {
  id: '3ee944b7-8fc4-47f2-9590-e0a400e44400',
  displayName: 'Thorin',
  profilePictureUrl: 'https://avatars.dicebear.com/api/bottts/thorin.svg',
};

await updateUserProfile(profileToUpdate);

The complete source for an example Profile Selector React component would look like below.

import {
  TokenResponse,
  UserProfile,
  useUserService,
} from '@axinom/mosaic-user-auth';


const ProfileSelector: React.FC = () => {
  const history = useHistory();
  const {
    getToken,
    getUserProfiles,
    setActiveProfile,
    updateUserProfile,
    deleteUserProfile,
    addTokenChangedHandler,
    removeTokenChangedHandler,
  } = useUserService();

  const [userProfiles, setUserProfiles] = useState<UserProfile[] | undefined>(
    undefined,
  );
  const [tokenResponse, setTokenResponse] = useState<TokenResponse | null>(
    null,
  );

  useEffect(() => {
    (async () => {
      const token = await getToken();
      if (token.code === 'ERROR') {
        history.push('/login');
      } else {
        setTokenResponse(token);
        const userProfiles = await getUserProfiles();
        setUserProfiles(userProfiles);
      }
    })();
  }, [
    addTokenChangedHandler,
    getToken,
    getUserProfiles,
    history,
    removeTokenChangedHandler,
  ]);

  const handleSelectProfileClick = async (profileId: string) => {
    await setActiveProfile(profileId);
    history.replace('/');
  };

  const handleEditProfileClick = async (userProfileToUpdate: UserProfile) => {
    const profileIndex = userProfiles?.findIndex(
      (profile) => profile.id === userProfileToUpdate.id,
    );

    if (profileIndex !== undefined) {
      const updatedUserProfiles = [...(userProfiles ?? [])];
      updatedUserProfiles[profileIndex] = {
        ...updatedUserProfiles[profileIndex],
        ...userProfileToUpdate,
        profilePictureUrl: `https://avatars.dicebear.com/api/bottts/${tokenResponse?.userToken?.userId}-${userProfileToUpdate.displayName}.svg`,
      };

      setUserProfiles(updatedUserProfiles);
    }

    await updateUserProfile(userProfileToUpdate);
  };

  const handleDeleteProfileClick = async (profileIdToDelete: string) => {
    setUserProfiles(
      userProfiles?.filter((profile) => profile.id !== profileIdToDelete),
    );

    await deleteUserProfile(profileIdToDelete);
  };

  return userProfiles === undefined ? (
    <LoadingPlaceholder />
  ) : userProfiles === null ? (
    <div>ERROR</div>
  ) : (
    <Container>
      <NavBar />

      <Segment style={{ marginTop: '50px' }} textAlign="center">
        <Card.Group itemsPerRow={3} stackable>
          {userProfiles.map((profile) => (
            <ProfileCard
              key={profile.id}
              id={profile.id}
              displayName={profile.displayName}
              defaultProfile={profile.defaultProfile}
              profileData={profile.profileData}
              profilePictureUrl={`https://avatars.dicebear.com/api/bottts/${tokenResponse?.userToken?.userId}-${profile.displayName}.svg`}
              active={tokenResponse?.userToken?.profileId === profile.id}
              onClick={async () => await handleSelectProfileClick(profile.id)}
              onDeleteClicked={handleDeleteProfileClick}
              onEditClicked={handleEditProfileClick}
            />
          ))}

          <AddProfileCard />
        </Card.Group>
      </Segment>
    </Container>
  );
};
all profiles
Figure 1. All Profiles