-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC]: Harmonize and extend code completion hints on currentUser
-object on web & api side
#5866
Comments
currentUser
-object on web & api sidecurrentUser
-object on web & api side
With all the trouble we're going through in both #5856 and in this RFC I have a different idea: What about not including any of the I think I've heard the argument "But everyone is going to need RBAC sooner rather than later anyways, so might as well include it from the get-go". But I want to challenge that with personal experience. I have two RW apps I've been working on, on and off, for about two years now. Neither of them has any RBAC stuff yet. Another point is that So my suggestion is:
(This is just my personal thoughts that I just came up with. Not the view of the RW core team (yet 😜). Please do tell me about all the ways this is a horrible idea) |
Great writeup @Philzen 👏 This is my first post on Redwood, I'm super excited about this project and still learning the ropes, only on Chapter 4 so far. Nice to meet you all 👋 I stumbled upon this RFC tonight while running through tutorial
const { isAuthenticated, getCurrentUser, logOut } = useAuth<{
name?: string | null;
email: string;
hashedPassword: string;
salt: string;
resetToken?: string | null;
resetTokenExpiresAt?: Date | string | null;
}>(); ❌ Obviously this didn't work,
import { Prisma } from '.prisma/client/index';
...
// in the component:
const { isAuthenticated, logOut } = useAuth();
const currentUser = useAuth().currentUser as unknown as Prisma.UserCreateInput; I noted that the type for export interface AuthContextInterface {
loading: boolean;
isAuthenticated: boolean;
currentUser: null | CurrentUser; 🔴
userMetadata: null | SupportedUserMetadata;
logIn(options?: unknown): Promise<any>;
// ....and so on
} Total export interface AuthContextInterface {
loading: boolean;
isAuthenticated: boolean;
currentUser: null | Prisma.UserCreateInput; 🟢
userMetadata: null | SupportedUserMetadata;
logIn(options?: unknown): Promise<any>;
// ....and so on
} No idea if this is good/bad/smart/dumb but just asking the question. I am not sure if Prisma.UserCreateInput is static, or is auto-generated from the Thank you all for the work already put into this amazing project ☘️ |
Thanks for validating our efforts! @dac09 I'm keen to get your input here. Thanks! |
I don’t really want to engage on the other topics just yet - but happy that you guys are! But
This isn't a good idea I'm afraid, its too specific to your project perhaps - and also a bit odd that we'd use the CreateInput type here. Remember when writing these types in the framework: a) You cannot assume everyone uses dbAuth, and even returns a Prisma type
This is entirely the point of the types no? That if you change the shape of currentUser, and downstream something else expects the old shape, theres an error.
|
|
Summary
The basic idea here is to improve the DX revolving around auth.
As a developer working on my user model and writing tests for it I would like meaningful code completion on the
currentUser
-object and a flexible / resilient type system that meets the following requirements:api/src/lib/auth/getCurrentUser
in order to change it (including a JsDoc `{@link …} so I can go there in one click) – s.th. like this:getCurrentUser
, existing code must not become invalid (yarn rw type-check
will not show errors that were not there before the change)currentUser
as listed above is uniform in both api-sides' context and the object provided byuseAuth
on the web-sideAn additional bonus requirement what may be hinting towards a solution:
CurrentUser
thatgetCurrentIUser
is not returning yet. These fields map to my schema or my SDL (unsure yet which one, but I guess schema comes first) and are automatically updated when I update the specification of my user object there.Motivation
Regarding 1.
Obvious. Make it easier for newbies to navigate and customize the auth-handling. Basically auth on rails. 🚂 ;)
Regarding 2.
This is a currently a real pitfall (unfortunately not into the pit of success, but this RFC aims to change that):
When you add an – albeit optional – field to the result of
getCurrentUser
(e.g.name
), any parts of code involving aCurrentUser
-object become red in VSCode andyarn rw type-check
will suddenly start listing errors on each occurrence.For me, such a change invalidates dozens of service tests (potentially hundreds) – adding a field will make
yarn rw type-check
spit out:...for each of these occurrences. Now imagine you go ahead and change each and every one of these occurrences. At some point in the future, the decision is made to remove that field again (just from
getCurrentUser
– but it's still defined in the SDL and schema and thus a perfectly valid field!) and you'll get:I know there are may devs that would argue that the functionality of a project is unimpacted by these rather esoterical typescript errors, and that one should just learn to turn a blind eye on it and get on with their lives, but that's not how it works for many others.
TS-Newbies may be intimidated by these errors, seeing their code go red in various places just because they changed one line somewhere else, and I believe it's possible to come up with a more resilient type-system to avoid that. Also, there likely are projects that have the type-check as part of their CI/CD, so this has the potential to severely slow down time-to-market for RedwoodJS projects.
Regarding 3.
Currently, there seems to be a disjoint between api and the web side. On the API side,
CurrentUser
resolves to.redwood/types/includes/all-currentUser.d.ts
, while on the web side the type of the same name resolves tonode_modules/@redwoodjs/auth/dist/AuthProvider.d.ts
.The latter provides an additional
roles?: Array<string> | string
property and otherwise syncs withgetCurrentUser
(although I'm puzzled how it does that from looking at the implementation).The former now also will have an optional
roles
property when #5856 is merged, but at the end of the day from a devs perspective I don't see whycurrentUser
shouldn't be uniform on both sides.Regarding 4.
Functionally, there is of course no functional gain in this, but it may be a helpful guidance and an important heads up which fields are not yet available on the
currentUser
-object (but recognizing they are now part of the user model) and giving a hint, similar to requirement 1. , where you'll need to go make it available.Detailed proposal
(not very detailed though, additions welcome)
Regarding 1.
This is already implemented and will become available once #5856 is merged (also fixes the typescript errors and enables to go to
getCurrentUser
with a single click anywhere in the api side). It's included explicit requirement, however to ensure doesn't degrade or get lost during the refactorings required for the following requirements.Regarding 2.
Not sure yet. But there must be a way to make non-essential fields in
InferredCurrentUser
optional. Some typescript guru out there will know, request for comments welcome.Regarding 3.
Not exactly sure yet, but part of that already seems to be implemented, as outlined above. The
currentUser
returned from theuseAuth
-hook already is picking up the return values inferred from somewhere, it only needs to stop overwriting theroles
-definition.Regarding 4.
Basically we'd could look at something like
Omit<Prisma.UserUncheckedCreateInput, 'hashedPassword' | 'salt'>
and generate an interface with nice JSDoc from that (let's call thatHelpfulUnimplementedAndCommentedProps
for the sake of this explanation). Then have CurrentUser beOverwrite<HelpfulUnimplementedAndCommentedProps, InferredCurrentUser>
(see Overwrite method here).The text was updated successfully, but these errors were encountered: