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

[#152] save user metrics preferences in database #166

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

MathildeDuboille
Copy link
Contributor

@MathildeDuboille MathildeDuboille commented Mar 31, 2020

PR Checklist

Please check if your PR fulfills the following requirements:

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting)
  • Refactoring (no functional changes)
  • Documentation content changes

Other information

Closes: #152

@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm March 31, 2020 15:44 Inactive
@@ -143,6 +145,20 @@ def _has_siblings(self, obj) -> bool:
> 1
)

def _user_metrics(self, obj):
metrics = list(
MetricsPreferences.objects.filter(project=obj).filter(
Copy link
Contributor

@fargito fargito Mar 31, 2020

Choose a reason for hiding this comment

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

You can put both arguments in the same filter, with

MetricsPreferences.objects.filter(
    project=obj,
    user_id=self.context.get("user_id")
)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that here you would not get the unique MetricsPreference object that corresponds to user and project, but rather the list of MetricPreferences right ?

backend/projects/models.py Outdated Show resolved Hide resolved
@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 1, 2020 14:01 Inactive
@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 1, 2020 14:17 Inactive
@MathildeDuboille MathildeDuboille force-pushed the feature/152-save-user-metrics-preferences branch from 7dc3e17 to 099fad0 Compare April 1, 2020 14:20
@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 1, 2020 14:20 Inactive
@MathildeDuboille MathildeDuboille changed the title [WIP] save user metrics preferences in database [#152] save user metrics preferences in database Apr 1, 2020
data = JSONParser().parse(request)
project_id = data["project"]
new_metrics = data["metrics"]
metrics = MetricsPreferences.objects.filter(
Copy link
Contributor

Choose a reason for hiding this comment

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

@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 2, 2020 09:57 Inactive
user_id=self.context.get("user_id")
)
)
if len(metrics) == 0:
Copy link
Contributor

Choose a reason for hiding this comment

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

Are that the default metrics? Shouldn’t we set that as a default in the DB migration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we set these metrics as default in the DB migration, we need to insert a line for each user and for each of his/her project in the table. So I don't think this is ideal, what do you think ?

Copy link
Contributor

Choose a reason for hiding this comment

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

I second @MathildeDuboille, this will save a lot of space in the database

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm I see your point. However I think that the typical Falco instance has few users and few projects. Even for Theodo’s Falco (which I think would be one of the biggest one), we have 43 projects and ~130 user, and every user averages 1-2 projects. So that would mean <300 lines in DB, which I think is definitely manageable.

I might be mistaken, but wouldn’t using the DB default to store the three defaults simplify the mechanism for creating / updating the metrics ? For one, creation would be already taken care of. Also, there’s something “weird” about asking for an object in an API, receiving one, and not being able to tell if 1) that’s the state of the DB 2) the DB’s empty and we’re receiving default.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also I should note that I do not consider this topic as blocking, and we can totally merge this and have this discussion in a later issue. Just think it’s an interesting discussion!

Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, the free DB instance in Heroku is capped at 10,000 lines, and the cheapest one (the one we have at Theodo) is capped at 10,000,000 lines.
So either you do not pay and will likely have only a few number of projects (otherwise you’ll reach the max pretty quickly), or you do pay and a few hundred lines are quite insignificant.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok that's convincing, we should put these default metrics in the database


@swagger_auto_schema(
methods=["post"],
responses={200: openapi.Response("Updates a metric preference.")},
Copy link
Contributor

Choose a reason for hiding this comment

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

Updates a user’s metric preferences for a given project

def metrics(request):
data = JSONParser().parse(request)
project_id = data["project"]
new_metrics = data["metrics"]
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens if a metric is not recognized here (either because of a bug or because someone is trying to attack this endpoint)? Do we reply with a 400 or a 500?

I think we should reply with a 400, meaning that we might have to check here whether the metrics sent by the users all belong to the list of “accepted” metrics.

new_metric_preferences.save()
else:
metrics.update(metrics=new_metrics)
return JsonResponse({})
Copy link
Contributor

Choose a reason for hiding this comment

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

You could reply with the metrics object that was created or updated

Copy link
Contributor

Choose a reason for hiding this comment

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

(I consider it good practice when POSTing or PATCHing an object to reply with the created or updated object in the response body)

case getType(updateAllDisplayedMetrics):
return {
...state,
displayedMetrics: {
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 rename this to currentDisplayedMetrics to be consistent with the naming of the other parameters in this Redux state?

@@ -157,6 +166,14 @@ function* fetchProjects(action: ActionType<typeof fetchProjectsRequest>) {
true,
null,
);
const displayedMetrics = projects.reduce(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is is necessary to have the displayedMetrics for all projects, even though we only show projects one at a time? It looks like the page ID, parameters, etc… are scoped as the current page.

I’ll have a deeper look into the Redux structure and try to figure out a solution more in line with the rest of the Redux mechanics.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I see in the network tab in the console, we don't call /projects/<id> every time we switch to another project, so it may be a problem if we don't store all the metrics when we fetch all projects :/

Copy link
Contributor

Choose a reason for hiding this comment

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

OK got it! You could maybe rename displayedMetrics into displayedMetricsByProjectId so that it becomes obvious what the id in the object stands for.

Copy link
Contributor

@phacks phacks Apr 2, 2020

Choose a reason for hiding this comment

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

Another solution would be to send the displayed_metrics with the GET /projects/first and GET /projects and store that info inside each project’s information. That would however require a number of changes in this PR. @fargito what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, the metrics should be handled at project level

@@ -22,4 +22,5 @@
),
path("<uuid:project_uuid>/scripts", views.project_scripts),
path("<uuid:project_uuid>/scripts/<uuid:script_uuid>", views.project_script_detail),
path("metrics", views.metrics),
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't the url be set by project ?

@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 3, 2020 10:03 Inactive
@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 3, 2020 15:02 Inactive
@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 3, 2020 15:13 Inactive
@phacks phacks temporarily deployed to falco-feature-152-save--u5lzlm April 3, 2020 16:23 Inactive
@sonarcloud
Copy link

sonarcloud bot commented Apr 3, 2020

SonarCloud Quality Gate failed.

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 6 Code Smells

No Coverage information No Coverage information
6.1% 6.1% Duplication

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.

Save Metrics preferences on user profile
3 participants