-
Notifications
You must be signed in to change notification settings - Fork 43
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
[MNOE-428] Migrate mno-enterprise to MnoHub API V2 #281
Conversation
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.
1st review didn't go to the end as mentioned.
Something to be careful of is the check on organization role.
There was some logic to improve perfs: filter the Org array if loaded and otherwise load the single organization
We need to make sure we don't introduce major slow down on this part
else | ||
status_scope = { status: 'accepted' } | ||
end | ||
organization.org_invites.where(status_scope.merge(user_id: user.id)).first | ||
Mno::Organization.includes(:user).where(status_scope.merge(user_id: user.id, organization_id: organization.id)).first |
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.
Shouldn't it be the Mno::OrgInvite
?
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.
Well spotted.
@parent_organization ||= begin | ||
id_or_uid = params[:organization_id] | ||
field = is_integer?(id_or_uid)? :id : :uid | ||
Mno::Organization.includes(:orga_relations, :users).find(field => id_or_uid).first |
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 is no longer scoped to the current_user
?
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.
True, needs to find a way to do it.
json.role member.role | ||
elsif member.is_a?(MnoEnterprise::OrgInvite) | ||
json.role organization.role(member) | ||
elsif member.is_a?(Mno::OrgaInvite) |
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.
MnoEnterprise::OrgInvite
-> Mno::OrgaInvite
?
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.
yes. It is OrgaInvite in MnoHub. Let's have consistency :)
@@ -13,31 +13,34 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::AppInstancesController | |||
#================================================================== | |||
# Instance methods | |||
#================================================================== | |||
# GET /mnoe/jpi/v1/organization/1/apps.json?timestamp=151452452345 | |||
# GET /mnoe/jpi/v1/organization/1/apps.json?tg=151452452345 |
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 we can deprecate the timestamp filtering.
This was used in old versions of the frontend when we were displaying the status of hosted apps.
There was a poller that was sending the current TS and it was used to change the status from starting to running.
This has been removed a while back.
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.
ok. will do
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. But you should update the comment :)
end | ||
|
||
# DELETE /mnoe/jpi/v1/app_instances/1 | ||
def destroy | ||
app_instance = MnoEnterprise::AppInstance.find(params[:id]) | ||
app_instance = Mno::AppInstance.find(params[:id])[0] |
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.
find
is always returning an array? Unlike AR/Her which distinguish find
from find_all
?
In this case, I'd prefer first
than [0]
Or should we use find_one
?
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.
yes, everything is a query for him, and therefore find return an array (I am not totally agains the approach, if you consider that everything is a collection, you can factorise code)
It is explained here: JsonApiClient/json_api_client#75
we should indeed use my lovely find_one
@@ -95,6 +95,7 @@ def dashboard_params | |||
whitelisted[:settings] = params[:dashboard][:metadata] || {} | |||
end | |||
.except(:metadata) | |||
.merge(owner_type: "User", owner_id: current_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.
This will cause backward compatibility issues with some customer projects where the owner is an Org.
They've extended the dashboards
method.
I can share the code customisation with you as I believe it's quite flexible.
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.
Not to much of an issue as we'll tag a major release for this
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.
That'll likely be a problem in the feature so it'd be good to address it.
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.
Is that something that could be fixed easily?
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.
we could change the api to accept an owner_type externally, that could be User or Organization
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.
but the current code was using UserDashboard, and therefore was already creating a dashboard for which the owner was a user.
There is no backward compatibility issue.
return render_not_found('widget') unless widget | ||
MnoEnterprise::EventLogger.info('widget_delete', current_user.id, 'Widget Deletion', widget) | ||
widget.destroy | ||
if widget.errors.empty? |
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 have the logger in this block? Or do you put it before to avoid issue with its being deleted?
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.
You got it right. widget.id is empty after you call destroy. Quite annoying actually.
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.
Ok
organization.users.to_a.find { |u| u.email == email } || | ||
organization.org_invites.active.where(user_email: email).first | ||
organization.users.find { |u| u.email == email } || | ||
organization.orga_invites.find { |u| u.status == 'pending' && u.user_email = email} |
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.
u.user_email == email
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.
thanks !
29559a2
to
6e422a4
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.
Few general notes:
- Change the
Mno
namespace toMnoEnterprise
- Few TODO left
- Perf improvements? Do you see any improvements in the amount and size of request to MnoHub?
- stub_audit_events globally
- I'm dropping support to ruby < 2.3 in the 4.0 branch so feel free to leverage Hash#dig and & (don't go overboard ;))
json.created_at app_instance.created_at | ||
|
||
json.per_user_licence app_instance.per_user_licence |
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.
fields removed?
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.
Yes, it did not appear to be used in mno-enterprise-angular.
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.
Yes but this is because the PR is still in review/revision: maestrano/mno-enterprise-angular#82
@@ -2,31 +2,23 @@ | |||
|
|||
module MnoEnterprise | |||
class AuditEventsListener | |||
include HTTParty | |||
base_uri "#{MnoEnterprise.mno_api_private_host || MnoEnterprise.mno_api_host}/api/mnoe/v1/audit_events" | |||
read_timeout 0.1 |
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 still have a short read timeout here? As we don't care about the response.
Not a biggie as the event logging is done through ActiveJob anyway.
@@ -68,9 +68,9 @@ def freeze_account | |||
# Check that the deletion_request has the right status | |||
if @deletion_request.status == 'pending' | |||
@deletion_request.freeze_account! | |||
format.html { redirect_to @deletion_request, notice: 'Your account has been frozen' } | |||
format.html { redirect_to({action: :show, id: @deletion_request.id}, notice: 'Your account has been frozen') } |
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.
Interesting, the previous code is no longer working?
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.
No, but only because of the difference of namespace between the controller and the model. This should be fixed if I put everything on the same namespace.
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.
Which namespace? The Mno
one? That should be working now ;)
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.
Corrected.
@@ -13,31 +13,34 @@ module MnoEnterprise::Concerns::Controllers::Jpi::V1::AppInstancesController | |||
#================================================================== | |||
# Instance methods | |||
#================================================================== | |||
# GET /mnoe/jpi/v1/organization/1/apps.json?timestamp=151452452345 | |||
# GET /mnoe/jpi/v1/organization/1/apps.json?tg=151452452345 |
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. But you should update the comment :)
if app_instance.errors.any? | ||
render json: app_instance.errors, status: :bad_request | ||
else | ||
MnoEnterprise::EventLogger.info('app_add', current_user.id, 'App added', app_instance.first) |
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.
app_instance.first
?
It's not super intuitive to have provision_app_instance
return an array
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 agree, but this is the way of working of json_api_client, everything returned is always an array.
core/app/models/mno/user.rb
Outdated
# Validation | ||
#================================ | ||
# | ||
# if Devise.password_regex |
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.
Validation?
return Time.iso8601(res) | ||
else | ||
return res | ||
when res.kind_of?(Array) |
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.
Indent when
as deep as case
👮♂️
Given that's Her related stuff, I'm sure it's Rubymine :)
# @see OrmAdapter::Bax`` | ||
def get(id) | ||
res = klass.includes(:deletion_requests, :organizations, :orga_relations, :dashboards).find(wrap_key(id)) | ||
if(res.errors && res.errors.first && res.errors.first.code != "404") |
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.
See my ruby 2.3 comment, &
ftw!
core/lib/mno_enterprise/core.rb
Outdated
@@mno_api_v2_root_path = "/api/mnoe/v2" | ||
|
||
mattr_reader :mnoe_api_v2 | ||
@@mnoe_api_v2 = nil |
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.
What is this one used for?
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.
Nothing, good spot.
core/mno-enterprise-core.gemspec
Outdated
@@ -47,6 +47,8 @@ Gem::Specification.new do |s| | |||
# Config files per environment | |||
s.add_dependency 'config', '~> 1.0', '< 1.3' | |||
|
|||
s.add_dependency 'json_api_client', '~> 1.3' |
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.
Add it next to her and faraday
05193b8
to
3b59dc8
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.
Another review.
Please do a separate commit for this so it's easier to review and it won't crash the github diff ;)
general comments:
- still lots of TODO left
- not a big fan of the let!(stub) is there a particular reason?
- remove her dependency (and all helpers files)?
- AppReview/AppComment => Needed for Opal project
question:
- Schema information in model is quite useful?
- attributes to property is not 1 => 1 (eg: a big list is replaced by created_at/updated_at)
- the assocations are no longer explicit?
I'll merge it soon (ie tomorrow) in a v4
branch and we can do more PR to iterate
json.created_at app_instance.created_at | ||
|
||
json.per_user_licence app_instance.per_user_licence |
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.
Yes but this is because the PR is still in review/revision: maestrano/mno-enterprise-angular#82
@@ -1,4 +1,6 @@ | |||
json.audit_events do | |||
json.array! @audit_events, partial: 'audit_event', as: :audit_event | |||
end | |||
json.metadata @audit_events.metadata | |||
# TODO: Port previous pagination metadata information ? | |||
# json.metadata @audit_events.metadata |
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.
Is this used somewhere? I couldn't find it in the frontend
Seems that the pagination is done through headers
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.
Ok. Removing it.
@@ -2,4 +2,4 @@ json.id user.id | |||
json.name user.name | |||
json.surname user.surname | |||
json.email user.email | |||
json.role organization.members.to_a.find { |e| e.id == user.id }.role | |||
json.role user.role(organization) |
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 are a couple calls like this. What is the effect in terms of performance?
This was introduced for sme-platform release to improve performance by avoiding extra calls to MnoHub.
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 no performance issue, as the user is already loaded with it's organization.
@@ -68,9 +68,9 @@ def freeze_account | |||
# Check that the deletion_request has the right status | |||
if @deletion_request.status == 'pending' | |||
@deletion_request.freeze_account! | |||
format.html { redirect_to @deletion_request, notice: 'Your account has been frozen' } | |||
format.html { redirect_to({action: :show, id: @deletion_request.id}, notice: 'Your account has been frozen') } |
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.
Which namespace? The Mno
one? That should be working now ;)
@@ -95,6 +95,7 @@ def dashboard_params | |||
whitelisted[:settings] = params[:dashboard][:metadata] || {} | |||
end | |||
.except(:metadata) | |||
.merge(owner_type: "User", owner_id: current_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.
Is that something that could be fixed easily?
module Validations | ||
class RemoteUniquenessValidator < ::ActiveModel::EachValidator | ||
def validate_each(record, attribute, value) | ||
list = record.class.where({attribute => value}).paginate(page: 1, per_page: 1).to_a |
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.
can you do record.class.find_first({attribute => value}).to_a
?
and list.any? { |e| e && e.id != record.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.
I am not sure find_first
exists. I will have a look.
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.
find_first does not exist in json api client. :(
|
||
# Return true if the instance can be considered active | ||
# Route53 DNS propagation may take up to a minute, so we force a minimum of 60 seconds before considering the application online | ||
def 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.
Shouldn't we keep all those instances methods (this and the one below)
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.
If they are not called. (and they are not), why should we ?
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.
@@ -42,26 +23,4 @@ module ClassMethods | |||
#================================================================== | |||
# Instance methods | |||
#================================================================== | |||
# Add a user to the team | |||
# TODO: specs | |||
def add_user(user) |
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 is no longer needed?
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.
Needs to check, good spot.
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.
It is used in organization_controller.
@@ -22,8 +22,10 @@ | |||
require "her_extension/middleware/mnoe_raise_error" |
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.
Let's get rid of this!
@@ -21,6 +21,7 @@ Gem::Specification.new do |s| | |||
s.add_dependency "her", "~> 0.7.3" |
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.
Let's remove it!
Some of the TODO were already here, (for example the Ability on the Impac model)
To be able to replace the stub for some particular case.
Yep, I should do that in a separate commit indeed.
question:
True, however I am not a big fan as it is not always up to date. I think I would prefer to use the attributes as a way to document the fields and their types. What do you think ?
Yes, because they are not needed explicitly to work. I will add them (Maybe using MnoHub)
Unfortunately no, it is documented in MnoHub, but not visible in MnoE, |
# Admin cannot edit Super Admin | ||
raise CanCan::AccessDenied if (member.is_a?(MnoEnterprise::User) && organization.role(member) == 'Super Admin') || (member.is_a?(MnoEnterprise::OrgaInvite) && member.user_role == 'Super Admin') | ||
elsif member.id == current_user.id && attributes[:role] != 'Super Admin' && organization.orga_relations.count {|u| u.role == 'Super Admin'} <= 1 | ||
if member_current_role == 'Super Admin' |
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 can now be done in one line with if
as a modifier instead of a statement
@@ -58,14 +58,13 @@ def main_app | |||
|
|||
context 'when the request is pending' do | |||
it 'freezes the account' do | |||
expect(controller.current_user).to receive(:current_deletion_request).and_return(deletion_req) | |||
expect(deletion_req).to receive(:freeze_account!) | |||
expect_any_instance_of(MnoEnterprise::DeletionRequest).to receive(:freeze_account!) |
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 rubocop prefers the previous code :)
Because you're testing you're freezing the correct deletion 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.
but it won't be the same object, as the one passed is a one created from the parsing of the api result...
- Add missing methods on user and organization - User -- Add create_api_credentials - Organization -- add role -- add payment_restriction -- add orga_relation - KPI and Alert - Implement Invite and Delete Organization Members - Implement Create Organization - Implement Update member - Implement Team management - Add star_ready? connec_ready? and responsive - Implement app instance provisioning - Implement Team Update - Implement Dashboard management - Implement widget controller - Update Dashboard - Correct issues with Dashboard's widgets not being sorted - Implement App Synchronisation - Apply Code Review Remark - Implement Audit Logging - Start Spec Writing - Adapt organization_spec.rb - Adapt Team Controller - Adapt Specs - Update Remote Authenticable - Remove Her Specifics Specs - Adapt App Specs - Adapt Model Specs - Adapt Confirmation Controller - Adapt DeletionRequestController KpisController - Adapt Marketplace Controller Spec and IntercomEventsListern - Adapt Current User Controller Spec - Apply Code review remarks - Add to_audit_event - Adapt Toto
- add per_user_licence back - extract custom_parser to a file - removed or corrected comments - simplified code
- Manage App Shared Entities - Manage Widget KPIS - Fix issue with user's role - Fix App instance querying - Fix error while deleting Teams - Fix error when an metadata containing a time was sent to the EventLogger - Remove logging when not in dev
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.
Quick question. Why create AppSharedEntity
and not reuse SharedEntity
?
json.array! app.shared_entities do |shared_entity| | ||
json.extract! shared_entity, :shared_entity_nid, :shared_entity_name, :write, :read | ||
if app.app_shared_entities.any? | ||
json.app_shared_entities do |
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.
The response is changing from shared_entities
to app_shared_entities
?
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.
The app contains a list of app_shared_entities in the v2 api.
if app.app_shared_entities.any? | ||
json.app_shared_entities do | ||
json.array! app.app_shared_entities do |shared_entity| | ||
json.shared_entity_nid shared_entity.shared_entity.nid |
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.
Why not use json.extract!
? It's a bit more concise?
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.
because it's not taking the fields name by name, it is mapping
shared_entity_nid to shared_entity.nid.
because in the MnoHub model, an app contains AppSharedEntities, that contains SharedEntity |
No description provided.