Skip to content
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

refactor(backend): context hook #1684

Merged
merged 1 commit into from
Aug 15, 2024
Merged

refactor(backend): context hook #1684

merged 1 commit into from
Aug 15, 2024

Conversation

roschaefer
Copy link
Contributor

Motivation

This fixes #1503.

This is necessary before I can properly implement role based authorization (for the admins).

How to test

  1. CI should be green

@roschaefer roschaefer requested review from Mogge, mahula and trinity2701 and removed request for Mogge and mahula August 7, 2024 23:49
where: {
id: user.id,
},
data,
})

if (data.introduction === undefined) delete data.introduction
if (data.availability === undefined) delete data.availability
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something I don't understand: Why was the updatedUser not returned?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I wrote this code I was confused as well. Check if the false positive is workuing

@roschaefer roschaefer changed the title refactor: context hook refactor(backend): context hook Aug 8, 2024
@roschaefer roschaefer force-pushed the refactor-context-hook branch 2 times, most recently from fbaaa28 to c402711 Compare August 12, 2024 11:40
Copy link
Contributor

@Mogge Mogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice refactor. Much better structured, and I like the context function. Please check for the false positive.
How do you want to realize the admin authorization? So far the single source of truth is authentik and therefore the token. When you touch the authChecker function, the token is already `out of scope.

backend/src/auth/authChecker.spec.ts Outdated Show resolved Hide resolved
)
}

it('deletes introduction and availability', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a false positive as introduction and availability are already null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will have a look into this, but is this a blocker for this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mogge it's addressed and certainly not a false negative anymore - I consider a failing test as positive (like a HIV-test) and a false positive a false alert. A false negative for me would be a test that does not fail but a bug is present.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you change something? There is only one force pushed commit and I cannot see the changes done by the last commit. Was I wrong? Now the code looks fine

where: {
id: user.id,
},
data,
})

if (data.introduction === undefined) delete data.introduction
if (data.availability === undefined) delete data.availability
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I wrote this code I was confused as well. Check if the false positive is workuing

@@ -15,7 +15,7 @@
"coverageThreshold": {
"global": {
"statements": 95,
"branches": 80,
"branches": 79,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to avoid the

    const { user } = context
    if (!user) throw new Error('User not found!')

construction in all resolvers that require a user. Can we somehow force the type UserWithProfile for calls that require authorization?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will also have a look but this is out of scope of this PR, isn't it?

Maybe there is a typescript solution for this. Ideally Authorized() would mark the context.user as not null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mogge I think we're out of luck here: microsoft/TypeScript#49229

I would suggest we use a simple helper method:

const { user } = requireUser(context)

with:

const requireUser = (context: Context) => {
  const { user } = context
  if (!user) throw new Error('context.user must be present after authorization!')
  return context
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would not raise the coverage of our branches

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have a dummy unauthenticated user that is set if there is no authentication?

@roschaefer
Copy link
Contributor Author

Nice refactor. Much better structured, and I like the context function. Please check for the false positive. How do you want to realize the admin authorization? So far the single source of truth is authentik and therefore the token. When you touch the authChecker function, the token is already `out of scope.

Role based-authorization can be done with this: https://github.com/dreammall-earth/dreammall.earth/pull/1686/files#diff-ab0ffeecd111988f9570b4645447f2cf50e1aecc99eef4cc4d45fbfbe3314dcbR65 and we would create an admin group with { roles: ['admin'] } attributes. Every member of this group will have the deep-merged roles in the JWT payload. Authentik has a concept of "roles" as well, but I could not find a documented way to encode that in the payload. I guess, group attributes are the way to go.

Also, I vote to decode the JWT in the backend and return the currentUser.roles to the frontend without a database call if not necessary. We can store the roles in the database, too, why not. But I would like to avoid a findOrCreateBy database call in the context hook unless we need to update/save the currentUser in our database.

@roschaefer roschaefer force-pushed the refactor-context-hook branch 2 times, most recently from a2a71f7 to d3ffd1d Compare August 14, 2024 21:10
@roschaefer roschaefer requested a review from Mogge August 15, 2024 07:21
Copy link
Contributor

@Mogge Mogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can merge this for now.

@ulfgebhardt
Copy link
Member

@roschaefer pls do your thing

Motivation
----------
This fixes #1503.

This is necessary before I can properly implement role based authorization (for the admins).

How to test
-----------
1. CI should be green
@roschaefer roschaefer force-pushed the refactor-context-hook branch from d3ffd1d to a4d6a40 Compare August 15, 2024 09:16
@roschaefer roschaefer enabled auto-merge (squash) August 15, 2024 09:16
@roschaefer roschaefer merged commit 4f027b6 into master Aug 15, 2024
34 checks passed
@ulfgebhardt ulfgebhardt deleted the refactor-context-hook branch September 12, 2024 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

🔧 [Refactor] authChecker and global module mocks
3 participants