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

[MNOE-428] Migrate mno-enterprise to MnoHub API V2 #281

Merged
merged 5 commits into from
Jun 22, 2017

Conversation

x4d3
Copy link
Contributor

@x4d3 x4d3 commented Apr 27, 2017

No description provided.

Copy link
Contributor

@ouranos ouranos left a 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
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 it be the Mno::OrgInvite?

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

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)
Copy link
Contributor

Choose a reason for hiding this comment

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

MnoEnterprise::OrgInvite -> Mno::OrgaInvite?

Copy link
Contributor Author

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
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 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok. will do

Copy link
Contributor

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]
Copy link
Contributor

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?

Copy link
Contributor Author

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)
Copy link
Contributor

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.

Copy link
Contributor

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

Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor Author

@x4d3 x4d3 Jun 19, 2017

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?
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 have the logger in this block? Or do you put it before to avoid issue with its being deleted?

Copy link
Contributor Author

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.

Copy link
Contributor

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}
Copy link
Contributor

Choose a reason for hiding this comment

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

u.user_email == email

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks !

@x4d3 x4d3 force-pushed the feature/api-v2 branch 2 times, most recently from 29559a2 to 6e422a4 Compare May 24, 2017 16:44
@ouranos ouranos added this to the v4.0 milestone Jun 7, 2017
@x4d3 x4d3 force-pushed the feature/api-v2 branch from 7fdb566 to 094bbb3 Compare June 7, 2017 13:38
Copy link
Contributor

@ouranos ouranos left a 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 to MnoEnterprise
  • 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
Copy link
Contributor

Choose a reason for hiding this comment

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

fields removed?

Copy link
Contributor Author

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.

Copy link
Contributor

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
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 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') }
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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 ;)

Copy link
Contributor Author

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
Copy link
Contributor

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)
Copy link
Contributor

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

Copy link
Contributor Author

@x4d3 x4d3 Jun 14, 2017

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.

# Validation
#================================
#
# if Devise.password_regex
Copy link
Contributor

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)
Copy link
Contributor

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")
Copy link
Contributor

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!

@@mno_api_v2_root_path = "/api/mnoe/v2"

mattr_reader :mnoe_api_v2
@@mnoe_api_v2 = nil
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nothing, good spot.

@@ -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'
Copy link
Contributor

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

@x4d3 x4d3 force-pushed the feature/api-v2 branch 3 times, most recently from 05193b8 to 3b59dc8 Compare June 14, 2017 16:46
@x4d3 x4d3 changed the title [WIP] Mnoe App V2 Development [MNOE-428] Migrate mno-enterprise to MnoHub API V2 Jun 14, 2017
@x4d3 x4d3 closed this Jun 19, 2017
@x4d3 x4d3 deleted the feature/api-v2 branch June 19, 2017 07:07
@x4d3 x4d3 restored the feature/api-v2 branch June 19, 2017 07:09
@x4d3 x4d3 reopened this Jun 19, 2017
Copy link
Contributor

@ouranos ouranos left a 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
Copy link
Contributor

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
Copy link
Contributor

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

Copy link
Contributor Author

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)
Copy link
Contributor

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.

Copy link
Contributor Author

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') }
Copy link
Contributor

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)
Copy link
Contributor

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
Copy link
Contributor

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 }

Copy link
Contributor Author

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.

Copy link
Contributor Author

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?
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 we keep all those instances methods (this and the one below)

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 they are not called. (and they are not), why should we ?

Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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"
Copy link
Contributor

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"
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's remove it!

@x4d3
Copy link
Contributor Author

x4d3 commented Jun 19, 2017

Some of the TODO were already here, (for example the Ability on the Impac model)

not a big fan of the let!(stub) is there a particular reason?

To be able to replace the stub for some particular case.

remove her dependency (and all helpers files)?

Yep, I should do that in a separate commit indeed.
AppReview/AppComment => Needed for Opal project

Yes, I had issue with polymorphism.

question:

Schema information in model is quite useful?

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 ?

attributes to property is not 1 => 1 (eg: a big list is replaced by created_at/updated_at)

Yes, because they are not needed explicitly to work. I will add them (Maybe using MnoHub)

the assocations are no longer explicit?

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'
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 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!)
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 rubocop prefers the previous code :)
Because you're testing you're freezing the correct deletion request

Copy link
Contributor Author

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...

@ouranos ouranos changed the base branch from master to 4.0 June 20, 2017 08:29
x4d3 added 3 commits June 20, 2017 10:25
- 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
@x4d3 x4d3 force-pushed the feature/api-v2 branch from 8f2c83e to 81c447b Compare June 20, 2017 09:26
x4d3 added 2 commits June 20, 2017 12:03
- 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
Copy link
Contributor

@ouranos ouranos left a 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
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@x4d3
Copy link
Contributor Author

x4d3 commented Jun 22, 2017

because in the MnoHub model, an app contains AppSharedEntities, that contains SharedEntity

@ouranos ouranos merged commit eb2546f into maestrano:4.0 Jun 22, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants