-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
feat(staff): Create initial staff class for _admin mode #61653
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #61653 +/- ##
==========================================
+ Coverage 80.35% 81.22% +0.86%
==========================================
Files 5187 5188 +1
Lines 228691 228847 +156
Branches 38396 38428 +32
==========================================
+ Hits 183770 185885 +2115
+ Misses 39050 37294 -1756
+ Partials 5871 5668 -203
|
25f422c
to
2743786
Compare
8b7317e
to
a5a300e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i still need to look at tests
d027250
to
439733b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm but this is also an ever evolving project
439733b
to
008b4e6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know I'm a little late to this PR, sorry! But happy to go over the comments more if you want. Let me know if I've misunderstood something, or don't have the right context.
def is_active_staff(request: Request) -> bool: | ||
if is_system_auth(getattr(request, "auth", None)): | ||
return True | ||
stf = getattr(request, "staff", None) or Staff(request) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
considering that Staff
initializer can throw errors, would it be more prudent to have this around a try/except so that we don't have unintended behaviors or errors? Something along the lines of:
try:
stf = getattr(request, "staff", None) or Staff(request)
except Exception as err:
logger.error(f"unexpected error trying to determine active staff user, defaulting to False", exc_info=err)
return False
return stf.is_active
# if the user has changed | ||
if str(self.request.user.id) != self.uid: | ||
return False | ||
return self._is_active |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading the code all the way, I now know _populate
is at the end supposed to help establish this value before being referenced, but if that's the case, it would be better in the __init__
to establish this value first as a default for safer code. Reading this code from top to bottom, it's not clear that the value gets dynamically added to the instance; I thought "Oh no, we're referencing a value that doesn't exist!" haha
We have to go 2 levels deep (from populate -> set_logged_in/out) to know this is a class variable we can use in this class, and if something happens in that chain, we could be blowing up here/throwing an error.
) | ||
return | ||
|
||
session_token = data.get("tok") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: do we have constants for these keys/references?
return False, "invalid-ip" | ||
return True, None | ||
|
||
def get_session_data(self, current_datetime=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a lot of checks and calculations happening in this function. Can we break those apart? I think the code would be much easier to read, and the flow/logic much more feasible to follow in the mind!
We also seem to be populating some keys and not others if a condition fails. For example, if idl
is less than current, we will return early and not populate the rest of the keys (exp
). Is that what we expect? Should the rest of the keys still be defaulted so they exist? Could we pull the populating/checking of those keys out to another function so that we could handle that decision more easily?
|
||
return data | ||
|
||
def _populate(self, current_datetime=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we name this function to something else? Populate is very generic, I'm not sure what it's supposed to be populating, and if it's okay to rerun this function or add to another private function.
If this is only meant to be run once, could we add some guard rails/checks for that? Or restructure this function so that it returns the values we want to populate and the __init__
can be responsible for adding them to the class?
if not self.is_active: | ||
if self._inactive_reason: | ||
logger.warning( | ||
"staff.%s", | ||
self._inactive_reason, | ||
extra={ | ||
"ip_address": request.META["REMOTE_ADDR"], | ||
"user_id": request.user.id, | ||
}, | ||
) | ||
else: | ||
logger.warning( | ||
"staff.inactive-unknown-reason", | ||
extra={ | ||
"ip_address": request.META["REMOTE_ADDR"], | ||
"user_id": request.user.id, | ||
}, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to do this logic in this function at this level? Right now, is_activate
property needs _populate
to finish first so that _is_active
gets added to the class, now _populate
needs is_active
to function correctly. It's creating this cyclic dependency effect, and it would be best to pull that out.
Super exciting work here Seiji!! |
Create staff middleware and tests. The code has been copied and adjusted over from the superuser middleware. Requires #61653 Closes https://github.com/getsentry/team-enterprise/issues/6
In future PRs, I will create + test the staff middleware and index endpoint
Summary
This PR creates a new staff class that is modeled off of the existing
Superuser
class. I removed all the code that was added to support the superuser modal because_admin
will not require that, only 2FA.Similarities
is_active_staff
is not a class method but a helper function, that checks for staff the same way asis_active_superuser
checks for superuserget_session_data
is identicalset_logged_out
and_set_logged_out
are identicalon_response
is identicalDifferences
set_logged_in
for Staff vs Superuser_needs_validation
functionis_active
class property does not check for an expiry time depending on in you switched orgs b/c staff mode is not tied to any org_check_expired_on_org_change
STAFF_ORG_ID
, instead of setting this is init, we know keep it as a file constant because it should never changeCloses https://github.com/getsentry/team-enterprise/issues/5