Skip to content
This repository has been archived by the owner on Jan 30, 2024. It is now read-only.

Commit

Permalink
Merge branch 'devel' of github.com:ForestAdmin/forest-rails into devel
Browse files Browse the repository at this point in the history
  • Loading branch information
raubineau committed Aug 1, 2018
2 parents c08a391 + f4befd2 commit 0082984
Show file tree
Hide file tree
Showing 41 changed files with 858 additions and 245 deletions.
86 changes: 86 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,92 @@

## [Unreleased]

## RELEASE 2.11.5 - 2018-07-31
### Fixed
- Search - Fix the broken search if the collection contains Array fields. [Regression introduced in 2.9.0]
- Search - Highlight the records id if it matches with the search value.

## RELEASE 2.11.4 - 2018-07-31
### Fixed
- Search - Fix the search while typing single quotes in the search value.

## RELEASE 2.11.3 - 2018-07-30
### Fixed
- Records Display - Fix collections display for project using Ruby version inferior to 2.3.0. [Regression introduced in 2.10.1]

## RELEASE 2.11.2 - 2018-07-30
### Fixed
- Smart BelongsTo - Fix the reference field values display in the records list of collections using Smart BelongsTo relationships.

## RELEASE 2.11.1 - 2018-07-30
### Fixed
- Records Count - Fix list display error if the collection name is different from the class name (routing issue to compute the count).

## RELEASE 2.11.0 - 2018-07-19
### Changed
- Performance - Improve the speed of listing the records by executing their count into another request.

## RELEASE 2.10.5 - 2018-07-11
### Fixed
- HasMany Relationships - Fix the performance of the related data retrieval if the collection has hidden belongsTo associations in the list.

## RELEASE 2.10.4 - 2018-07-11
### Fixed
- Mixpanel Integration - Only retrieve events that are less than 60 days old to be compliant with the Mixpanel's API.

## RELEASE 2.10.3 - 2018-07-10
### Fixed
- ActiveStorage - Support ActiveStorage without having to set eager_load property to true in development environments.

## RELEASE 2.10.2 - 2018-07-10
### Fixed
- Smart Views - Fix associated data retrieval from Smart Views (where the fields to retrieve are not specified in the query params).

## RELEASE 2.10.1 - 2018-07-10
### Fixed
- Stripe Integration - Improve the error handling if the customer Stripe Id is not found.
- Stripe Integration - Trial to prevent uninitialized constant errors with Stripe classes.

## RELEASE 2.10.0 - 2018-07-10
### Added
- Mixpanel Integration - Add the integration to display the last 100 Mixpanel events of a "user" record.

## RELEASE 2.9.2 - 2018-07-04
### Fixed
- Database Connection - If the database is not accessible on server start, the liana doesn't send an Apimap anymore (it was a "partial" Apimap in such case).

## RELEASE 2.9.1 - 2018-07-03
### Changed
- Technical - Use the "official" domain for the default server host.

### Fixed
- Record Creation - Fix the search of belongsTo associated records in record creation forms if the belongsTo foreign key is a UUID.

## RELEASE 2.9.0 - 2018-06-28
### Added
- Search - Display highlighted matches on table view when searching.

## RELEASE 2.8.6 - 2018-06-27
### Fixed
- Intercom Integration - Users can now access to the Intercom Details page.

## RELEASE 2.8.5 - 2018-06-26
### Fixed
- Namespacing - Prevent a potential error on server start if a ResourcesController class already exists in another lib of the client project.
- Filters - Filtering on 2 different belongsTo foreign keys referencing the same table now returns the expected records.

## RELEASE 2.8.4 - 2018-06-21
### Changed
- Onboarding - Improve the information message if the liana is properly setup and users run the "rails g forest_liana:install".

### Fixed
- Permissions - Fix automated permission for projects having multiple teams.

## RELEASE 2.8.3 - 2018-06-20
### Fixed
- Onboarding - If the liana is properly setup and users run the "rails g forest_liana:install" command again, the task will be skipped.
- Onboarding - The install generator now supports credentials.yml.enc file introduced in Rails 5.2.

## RELEASE 2.8.2 - 2018-06-18
### Fixed
- Development Autoreload - Prevent "A copy of ForestLiana::ResourcesController has been removed from the module tree but is still active!" in development mode.
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
forest_liana (2.8.2)
forest_liana (2.11.5)
arel-helpers
bcrypt
groupdate
Expand Down Expand Up @@ -154,4 +154,4 @@ DEPENDENCIES
useragent

BUNDLED WITH
1.16.1
1.16.2
27 changes: 17 additions & 10 deletions app/controllers/forest_liana/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,17 @@ def serialize_model(record, options = {})
force_utf8_encoding(json)
end

def serialize_models(records, options = {})
def serialize_models(records, options = {}, fields_searched = [])
options[:is_collection] = true
json = JSONAPI::Serializer.serialize(records, options)

if options[:count]
json[:meta] = {} unless json[:meta]
json[:meta][:count] = options[:count]
end

if !options[:has_more].nil?
json[:meta] = {} unless json[:meta]
json[:meta][:has_more] = options[:has_more]
if options[:params] && options[:params][:search]
# NOTICE: Add the Smart Fields with a 'String' type.
fields_searched.concat(get_collection.string_smart_fields_names).uniq!
json['meta'] = {
decorators: ForestLiana::DecorationHelper
.decorate_for_search(json, fields_searched, options[:params][:search])
}
end

force_utf8_encoding(json)
Expand All @@ -68,6 +67,7 @@ def authenticate_user_from_jwt

@jwt_decoded_token = JWT.decode(token, ForestLiana.auth_secret, true,
{ algorithm: 'HS256', leeway: 30 }).try(:first)
@rendering_id = @jwt_decoded_token['data']['relationships']['renderings']['data'][0]['id']
else
head :unauthorized
end
Expand Down Expand Up @@ -150,7 +150,14 @@ def fields_per_model(params_fields, model)
if model_association
model_name = model_association.class_name
# NOTICE: Join fields in case of model with self-references.
fields[model_name] = [fields[model_name], relation_fields].join(',')
if fields[model_name]
fields[model_name] = [
fields[model_name],
relation_fields
].join(',').split(',').uniq.join(',')
else
fields[model_name] = relation_fields
end
end
end
fields
Expand Down
30 changes: 25 additions & 5 deletions app/controllers/forest_liana/associations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ def index
end
end

def count
begin
getter = HasManyGetter.new(@resource, @association, params)
getter.count

render serializer: nil, json: { count: getter.records_count }
rescue => error
FOREST_LOGGER.error "Association Index Count error: #{error}\n#{format_stacktrace(error)}"
internal_server_error
end
end

def update
begin
updater = BelongsToUpdater.new(@resource, @association, params)
Expand Down Expand Up @@ -105,20 +117,28 @@ def render_jsonapi getter
records = getter.records.map { |record| get_record(record) }

includes = getter.includes_for_serialization
if includes.length > 0
if fields_to_serialize && includes.length > 0
association_name = ForestLiana.name_for(@association.klass)
fields_to_serialize[association_name] += ",#{includes.join(',')}"
end

json = serialize_models(
records,
include: includes,
fields: fields_to_serialize,
count: getter.count,
params: params
{
include: includes,
fields: fields_to_serialize,
params: params
},
getter.search_query_builder.fields_searched
)

render serializer: nil, json: json
end

def get_collection
model_association = @resource.reflect_on_association(params[:association_name].to_sym).klass
collection_name = ForestLiana.name_for(model_association)
@collection ||= ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
end
end
end
2 changes: 1 addition & 1 deletion app/controllers/forest_liana/intercom_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def conversations

render serializer: nil, json: serialize_models(getter.records, {
context: { type: get_serializer_type('intercom_conversations') },
count: getter.count
meta: { count: getter.count }
})
end

Expand Down
27 changes: 27 additions & 0 deletions app/controllers/forest_liana/mixpanel_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module ForestLiana
class MixpanelController < ForestLiana::ApplicationController
def last_events
collection_name = params[:collection]
mapping = ForestLiana.integrations[:mixpanel][:mapping]
mapping_for_current_collection = mapping.find { |item| item.start_with?(collection_name) }
field_name = mapping_for_current_collection.split('.')[1]
id = params[:id]
field_value = collection_name.constantize.find_by('id': id)[field_name]

getter = ForestLiana::MixpanelLastEventsGetter.new(params)
getter.perform(field_name, field_value)

custom_properties = ForestLiana.integrations[:mixpanel][:custom_properties]
MixpanelEventSerializer.attributes(*custom_properties)

render serializer: nil, json: serialize_models(getter.records, {
context: { type: get_serializer_type('mixpanel_events') },
count: getter.count,
})
end

def get_serializer_type(suffix)
"#{params[:collection]}_#{suffix}"
end
end
end
55 changes: 44 additions & 11 deletions app/controllers/forest_liana/resources_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ class ResourcesController < ForestLiana::ApplicationController
def index
begin
if request.format == 'csv'
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'export').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'export', @rendering_id)
return head :forbidden unless checker.is_authorized?
elsif params.has_key?(:searchToEdit)
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'searchToEdit').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'searchToEdit', @rendering_id)
return head :forbidden unless checker.is_authorized?
else
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'list').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'list', @rendering_id)
return head :forbidden unless checker.is_authorized?
end

getter = ForestLiana::ResourcesGetter.new(@resource, params)
Expand All @@ -39,9 +42,29 @@ def index
end
end

def count
begin
checker = ForestLiana::PermissionsChecker.new(@resource, 'list', @rendering_id)
return head :forbidden unless checker.is_authorized?

getter = ForestLiana::ResourcesGetter.new(@resource, params)
getter.count

render serializer: nil, json: { count: getter.records_count }

rescue ForestLiana::Errors::LiveQueryError => error
render json: { errors: [{ status: 422, detail: error.message }] },
status: :unprocessable_entity, serializer: nil
rescue => error
FOREST_LOGGER.error "Records Index Count error: #{error}\n#{format_stacktrace(error)}"
internal_server_error
end
end

def show
begin
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'show').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'show', @rendering_id)
return head :forbidden unless checker.is_authorized?

getter = ForestLiana::ResourceGetter.new(@resource, params)
getter.perform
Expand All @@ -56,7 +79,8 @@ def show

def create
begin
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'create').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'create', @rendering_id)
return head :forbidden unless checker.is_authorized?

creator = ForestLiana::ResourceCreator.new(@resource, params)
creator.perform
Expand All @@ -79,7 +103,8 @@ def create

def update
begin
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'update').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'update', @rendering_id)
return head :forbidden unless checker.is_authorized?

updater = ForestLiana::ResourceUpdater.new(@resource, params)
updater.perform
Expand All @@ -102,7 +127,8 @@ def update

def destroy
begin
return head :forbidden unless ForestLiana::PermissionsChecker.new(@resource, 'delete').is_authorized?
checker = ForestLiana::PermissionsChecker.new(@resource, 'delete', @rendering_id)
return head :forbidden unless checker.is_authorized?

@resource.destroy(params[:id])
head :no_content
Expand Down Expand Up @@ -152,13 +178,20 @@ def render_jsonapi getter

json = serialize_models(
records,
include: includes(getter),
fields: fields_to_serialize,
count: getter.count,
params: params
{
include: includes(getter),
fields: fields_to_serialize,
params: params
},
getter.search_query_builder.fields_searched
)

render serializer: nil, json: json
end

def get_collection
collection_name = ForestLiana.name_for(@resource)
@collection ||= ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
end
end
end
5 changes: 4 additions & 1 deletion app/controllers/forest_liana/router.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
class ForestLiana::Router
def call(env)
params = env['action_dispatch.request.path_parameters']
resource = ForestLiana::SchemaUtils.find_model_from_collection_name(params[:collection])
collection_name = params[:collection]
resource = ForestLiana::SchemaUtils.find_model_from_collection_name(collection_name)

begin
component_prefix = ForestLiana.component_prefix(resource)
Expand All @@ -14,6 +15,8 @@ def call(env)
when 'GET'
if params[:id]
action = 'show'
elsif env['PATH_INFO'] == "/#{collection_name}/count"
action = 'count'
else
action = 'index'
end
Expand Down
Loading

0 comments on commit 0082984

Please sign in to comment.