-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[PM-18876] Refine PolicyRequirements API #5445
base: main
Are you sure you want to change the base?
Conversation
New Issues (13)Checkmarx found the following issues in this Pull Request
Fixed Issues (30)Great job! The following issues were fixed in this Pull Request
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5445 +/- ##
=======================================
Coverage 44.48% 44.49%
=======================================
Files 1533 1535 +2
Lines 71073 71079 +6
Branches 6379 6379
=======================================
+ Hits 31619 31624 +5
- Misses 38087 38089 +2
+ Partials 1367 1366 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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.
Looks great! I have left some initial thoughts
/// </remarks> | ||
public delegate T RequirementFactory<out T>(IEnumerable<PolicyDetails> policyDetails) | ||
where T : IPolicyRequirement; | ||
public interface IRequirementFactory<out T> where T : IPolicyRequirement |
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.
This interface could use a separate file
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.
Done
/// <typeparam name="T"></typeparam> | ||
public abstract class SimpleRequirementFactory<T> : IRequirementFactory<T> where T : IPolicyRequirement | ||
{ | ||
protected abstract IEnumerable<OrganizationUserType> ExemptRoles { get; } |
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 think most policies will have these roles exempt so we could make it virtual to be overridden if necessary
protected abstract IEnumerable<OrganizationUserType> ExemptRoles { get; } | |
protected virtual IEnumerable<OrganizationUserType> ExemptRoles { get; } = | |
[OrganizationUserType.Owner, OrganizationUserType.Admin]; |
We could do the same thing for the exempt statuses
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.
This was also Matt Gibson's feedback. I've done this for roles, statuses and exempting providers, all with sensible defaults.
/// <summary> | ||
/// Policy requirements for the Disable Send and Send Options policies. | ||
/// </summary> | ||
public class DisableSendRequirement : IPolicyRequirement |
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.
This name would be very specific
public class DisableSendRequirement : IPolicyRequirement | |
public class DisableSendPolicyRequirement : IPolicyRequirement |
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've brought all the names into line so that the PolicyRequirement wording is more consistent.
src/Core/AdminConsole/OrganizationFeatures/Policies/Implementations/PolicyRequirementQuery.cs
Outdated
Show resolved
Hide resolved
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.
Great work!
|
🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-18876
📔 Objective
@MGibson1 provided feedback that the static factory methods for policy requirements had too many responsibilities to be a clear interface for other teams. When implementing it, the developer needs to know to:
It would be easy to only implement the last item, which would be wrong.
This PR replaces that with an
IPolicyRequirementFactory
interface instead, which requires that you handle those 3 business requirements explicitly when implementing it. This way, the interface describes the questions you need to answer. This will be accompanied with documentation (maybe a deep dive) once merged.I've also provided a default base implementation, which makes the
Enforce
predicate fully declarative (i.e. configurable just by listing who you want to exempt), and has sensible defaults so that you don't miss something important. This should work in 99% of cases. (To the point where I almost made this the interface, but I wanted to maintain a distinction between the required interface vs. a default implementation.)Lastly, I've updated the Send requirement I'd already implemented to use the new api.
There are a few flow-on effects worth noting:
IPolicyRequirementFactory
implementations can be registered as scoped dependencies in the usual fashion, instead of the more flexible but weirder currying of static factory methods to inject any dependencies (if you're wondering "huh what does he mean by that" - exactly). While most factories won't require additional dependencies, some do (mostly GlobalSettings and feature flags) and we need to facilitate that.BasePolicyRequirementFactory
don't need as many tests, because they can rely on the base class to have implemented - and therefore in my view, tested - theEnforce
method. They only really need to test theirCreate
method. Given that we're going to have a lot of factories, this should result in way fewer tests.IPolicyRequirementFactory
also makes your tests more granular, and therefore easier to arrange.📸 Screenshots
⏰ Reminders before review
🦮 Reviewer guidelines
:+1:
) or similar for great changes:memo:
) or ℹ️ (:information_source:
) for notes or general info:question:
) for questions:thinking:
) or 💭 (:thought_balloon:
) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion:art:
) for suggestions / improvements:x:
) or:warning:
) for more significant problems or concerns needing attention:seedling:
) or ♻️ (:recycle:
) for future improvements or indications of technical debt:pick:
) for minor or nitpick changes