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

Add support for Get Profile Status By ID in Cli and Api #5100

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

navnitms
Copy link
Contributor

Summary

Added support to get profile status by Profile Id in CLI
Reformatted GetProfileStatusByNameAndProject code to accommodate GetProfileStatusByIdAndProject
Reformatted GetProfileStatusByNameAndProject to reduce complexity to a permissible level (<15)

Fixes (#4999 )

Change Type

Mark the type of change your PR introduces:

  • Bug fix (resolves an issue without affecting existing features)
  • Feature (adds new functionality without breaking changes)
  • Breaking change (may impact existing functionalities or require documentation updates)
  • Documentation (updates or additions to documentation)
  • Refactoring or test improvements (no bug fixes or new functionality)

Testing

Outline how the changes were tested, including steps to reproduce and any relevant configurations.
Attach screenshots if helpful.

Review Checklist:

  • Reviewed my own code for quality and clarity.
  • Added comments to complex or tricky code sections.
  • Updated any affected documentation.
  • Included tests that validate the fix or feature.
  • Checked that related changes are merged.

Fixed the issue where retrieving profile status by ID was not possible due to the missing CLI flag.
Also added a function to get profile status by ID and project.
	Reduced Complexity From 23 to 12
@navnitms navnitms requested a review from a team as a code owner November 29, 2024 22:40
@navnitms navnitms marked this pull request as draft November 29, 2024 22:52
@navnitms navnitms changed the title Add support for Get Profile Status By ID in Cli and Api WIP:Add support for Get Profile Status By ID in Cli and Api Nov 29, 2024
@coveralls
Copy link

coveralls commented Nov 30, 2024

Coverage Status

coverage: 55.318% (+0.2%) from 55.135%
when pulling 74dea5a on navnitms:Add-get_Profile_Status_By_Id
into a02f754 on mindersec:main.

@navnitms navnitms marked this pull request as ready for review November 30, 2024 19:59
@navnitms navnitms changed the title WIP:Add support for Get Profile Status By ID in Cli and Api Add support for Get Profile Status By ID in Cli and Api Nov 30, 2024
Copy link
Contributor

@eleftherias eleftherias left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution @navnitms!
I've left a few comments inline.

cmd/cli/app/profile/status/status_get.go Show resolved Hide resolved
@@ -606,6 +606,17 @@ service ProfileService {
};
}

rpc GetProfileStatusById (GetProfileStatusByIdRequest) returns (GetProfileStatusByIdResponse) {
option (google.api.http) = {
get: "/api/v1/profile/id/{id=**}/status"
Copy link
Contributor

Choose a reason for hiding this comment

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

Following the convention set by the other API endpoints, this should be

Suggested change
get: "/api/v1/profile/id/{id=**}/status"
get: "/api/v1/profile/{id}/status"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have updated the api , to follow the convention

var getProfileErr error

switch id := profileIdentifier.(type) {
case string:
Copy link
Contributor

Choose a reason for hiding this comment

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

I worry that the switch statement here is fragile and makes it harder to follow the codepath.
Do you see a way to call GetProfileStatusByNameAndProjectParams or GetProfileStatusByIdAndProjectParams respectively in their corresponding top level functions and then pass the results to the helper?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have refactored the code , to make the flow more simple to follow

@navnitms
Copy link
Contributor Author

navnitms commented Dec 3, 2024

@eleftherias Thanks for the review

Copy link
Contributor

@eleftherias eleftherias left a comment

Choose a reason for hiding this comment

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

Thanks for the quick updates @navnitms!
I've left a few more comments inline.

bool all = 4;

// rule is the type of the rule. Deprecated in favor of rule_type
string rule = 5 [deprecated=true];
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is a new API, we shouldn't add deprecated fields

if selector != nil || isAllRequested(ctx) {
dbRuleEvaluationStatuses, err := s.store.ListRuleEvaluationsByProfileId(ctx, db.ListRuleEvaluationsByProfileIdParams{
ProfileID: profileID,
EntityID: *selector,
Copy link
Contributor

Choose a reason for hiding this comment

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

selector could be nil here which would result in a panic

err error) {

switch ps := dbProfileStatus.(type) {
case db.GetProfileStatusByNameAndProjectRow:
Copy link
Contributor

Choose a reason for hiding this comment

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

The isn't much benefit in having a common helper function if it has switch statements which separate the code paths.
In this case, we can change the signature of processProfileStatus to processProfileStatus(ctx context.Context, profileName string, profileID uuid.UUID, lastUpdated *timestamppb.Timestamp, profileStatus string) and then just pass the fields that we need:

	resp, err := s.processProfileStatus(
		ctx,
		dbProfileStatus.Name,
		dbProfileStatus.ID,
		timestamppb.New(dbProfileStatus.LastUpdated),
		string(dbProfileStatus.ProfileStatus),
	)

var ruleName *sql.NullString

switch r := req.(type) {
case *minderv1.GetProfileStatusByNameRequest:
Copy link
Contributor

Choose a reason for hiding this comment

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

Once we remove rule from the GetProfileStatusByIdRequest then the logic will be different between getting the status by name and ID.
It would make sense to have 2 separate helpers instead of a common helper with switch statements.

@eleftherias
Copy link
Contributor

Hey @navnitms, happy new year!
Do you think you'll have time to continue working on this enhancement?

@navnitms
Copy link
Contributor Author

navnitms commented Jan 2, 2025

Hey @eleftherias , Sorry for the delay
I was caught up in some work for a while
Sure i would love to complete this
Also looking forward to contribute more

@eleftherias
Copy link
Contributor

No problem @navnitms and thank you for your work so far. Feel free to reach out if you have any questions.

@navnitms
Copy link
Contributor Author

navnitms commented Jan 4, 2025

Hey @eleftherias, Thanks for the support,
I have made the necessary updates

Copy link
Contributor

@eleftherias eleftherias left a comment

Choose a reason for hiding this comment

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

Thanks for the updates! I've left one comment inline.
There is also a change that needs to be made to the validators. Currently, the validator still requires a profile name. We should update it to require either a name or an ID:

func (p *Profile) Validate() error {
if p.getTypeWithDefault() != ProfileType {
return fmt.Errorf("%w: profile type is invalid: %s. Did you parse the wrong file?",
ErrValidationFailed, p.Type)
}
if p.getVersionWithDefault() != ProfileTypeVersion {
return fmt.Errorf("%w: profile version is invalid: %s", ErrValidationFailed, p.Version)
}
if p.GetName() == "" {
return fmt.Errorf("%w: profile name cannot be empty", ErrValidationFailed)
}

logger.BusinessRecord(ctx).Project = entityCtx.Project.ID
logger.BusinessRecord(ctx).Profile = logger.Profile{Name: profileName, ID: profileID}

return &minderv1.GetProfileStatusResponse{
Copy link
Contributor

Choose a reason for hiding this comment

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

This can return minderv1.GetProfileStatusByNameResponse and then we can remove GetProfileStatusResponse from the proto file.

logger.BusinessRecord(ctx).Project = entityCtx.Project.ID
logger.BusinessRecord(ctx).Profile = logger.Profile{Name: profileName, ID: profileID}

return &minderv1.GetProfileStatusResponse{
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to the the comment above, This can return minderv1.GetProfileStatusByIdResponse so we can remove GetProfileStatusResponse from the proto file.

@navnitms
Copy link
Contributor Author

navnitms commented Jan 6, 2025

Hi @eleftherias

There is also a change that needs to be made to the validators. Currently, the validator still requires a profile name. We should update it to require either a name or an ID:

I have some concerns about this proposed change.
Are we planning for the validation to pass if only one of the ID or name is provided? Isn't the profile name supposed to be mandatory? Additionally, I couldn't find any instance where the validate function is called in relation to GetProfileStatus. Could you please clarify?

Additionally, I noticed that the check for whether profileId or profileName is passed is happening in the minder/cmd/cli/app/profile/get.go

Apologies for the multiple iterations of review required for this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants