Finishing Impersonation
Tags: programming, opensource, webdev
Published: 2023-04-10 14:45:48

## Finishing impersonation

This past week my issue of choice when working on [the Starchart (My.Custom.Domain) opensource web site](https://github.com/DevelopingSpace/starchart) was the following to broadly "make impersonation work" [#508](https://github.com/DevelopingSpace/starchart/issues/508). The week before last I had gotten the logic I wanted to use for this issue landed in terms of how it would work on the session/root loader side of things and I replaced every place I could see at the time that was using the useUser hook to take a user out of the root loader with my new useEffectiveUser hook which would do the same but would allow for admins to impersonate other users and act in their stead.

## Reconciling code differences

For the majority of this week's work I ended up working as is often the case in another developer's code, and saw some things that I have not seen before. I had already seen the way that this dev had written simple button posts using [useFetcher](https://remix.run/docs/en/1.15.0/hooks/use-fetcher#usefetcher) from [Remix](https://remix.run/docs/en/1.15.0) and thought that was cool, I tried using it before myself although I don't remember if it ended up in any of my PRs, and after taking a while to remember how our components, routes, actions and loaders worked together I dove into the code in our admin pages.

When writing my own code this time I stood true to what I had done before and kept what I knew worked moving forward so when I was writing the logic for the buttons on the admin table that should impersonate a user I used the same kind of logic I had done before where I wrapped the buttons in a form with an invisible input and made them of submit type. 

Once the buttons to submit were clicked the action for the admin route would be reached with my payload and there was already code on this route using something I had never seen before.

The dev I had mentioned created this cool bit of code that would search through users as you entered characters into a search box, and on the "back end" (the action) they used a typed approach to their response using a library that is new to me called [Zod](https://zod.dev/). I tried to use Zod for quite a while and parse the payload as I was seeing, I added a new attribute to his parseFormSafe call and tried to make it conditional/optional seeing as my newEffectiveUser would not always be in the payload to the action but it didn't work the way I had hoped and was taking a bit longer than I was comfortable with at the time with the other obligations I have at the end of the semester. It turned out the best way I could think of doing it was to actually make the search logic and the impersonation logic mutually exclusive. First I would write the cave man way I have been writing the actions where I just try to extract something from the request's formData with a .get and if what I expect is there then I redirect to index with the effective user cookie populated with the new value from the button press and if not then we must have arrived here from the search box and so ensue the previous logic.

## Tying up loose ends

In this PR I also added requireAdmin to the admin route, I changed another one of pages from useUser to useEffectiveUser and I also did some changes to the way the header looks whenever an admin is impersonating someone so that it would show a theater mask and allow you to stop with the press of a newly added button in the header that worked similarly to how the impersonation button worked, that is to say a form submit that results in a redirect with a new cookie.

The full PR is here [#547](https://github.com/DevelopingSpace/starchart/pull/547)