diff --git a/.erdconfig b/.erdconfig
new file mode 100644
index 0000000000000000000000000000000000000000..6d077b17393fb5120fe8611219660aa374bb03c6
--- /dev/null
+++ b/.erdconfig
@@ -0,0 +1,19 @@
+attributes:
+  - content
+  - foreign_key
+  - inheritance
+disconnected: true
+filename: erd
+filetype: pdf
+indirect: true
+inheritance: true
+markup: true
+notation: bachman
+orientation: horizontal
+polymorphism: false
+sort: true
+warn: true
+title: PortalMEC
+exclude: null
+only: null
+prepend_primary: false
diff --git a/Gemfile b/Gemfile
index ffd65b8e5f621f29c5b21444b71092870e3fb79b..632fd727716b1196dda747eddaa922775551af5c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -47,7 +47,6 @@ gem 'stackprof'
 
 group :development do
   gem 'annotate'
-
   gem 'immigrant'
 
   # Generate ER Diagram from database (use: rake erd)
@@ -87,11 +86,17 @@ group :development do
 
   # JavaScript runtime
   gem 'execjs'
+
+  # local mailbox
+  gem 'mailcatcher'
 end
 
 group :test do
   gem 'shoulda'
   gem 'minitest-reporters'
+  gem 'rspec-rails'
+  gem 'faker'
+  gem 'factory_girl_rails'
 end
 
 gem 'streamio-ffmpeg', '~> 1.0.0'
@@ -147,3 +152,11 @@ gem 'rubyzip'
 
 # user activity
 gem 'public_activity'
+
+gem 'rails-observers'
+
+# soft-deleted for active record models
+gem 'paranoia', '~> 2.0'
+
+# models versioning
+gem 'paper_trail'
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index 1eb1ecace5941595657e420ba4b189364399dadc..8ec46499af5aff41d4fbd0224e3cfe1cdcc84ab0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -32,8 +32,10 @@ GEM
       erubis (~> 2.7.0)
       rails-dom-testing (~> 1.0, >= 1.0.5)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
-    active_model_serializers (0.9.5)
-      activemodel (>= 3.2)
+    active_model_serializers (0.10.0)
+      actionpack (>= 4.0)
+      activemodel (>= 4.0)
+      railties (>= 4.0)
     activejob (4.2.6)
       activesupport (= 4.2.6)
       globalid (>= 0.3.0)
@@ -58,7 +60,7 @@ GEM
       rake (>= 10.4, < 12.0)
     ansi (1.5.0)
     arel (6.0.3)
-    ast (2.2.0)
+    ast (2.3.0)
     axiom-types (0.1.1)
       descendants_tracker (~> 0.0.4)
       ice_nine (~> 0.11.0)
@@ -72,12 +74,12 @@ GEM
       rack (>= 0.9.0)
     binding_of_caller (0.7.2)
       debug_inspector (>= 0.0.1)
-    brakeman (3.3.0)
+    brakeman (3.3.1)
     builder (3.2.2)
-    bullet (5.0.0)
+    bullet (5.1.0)
       activesupport (>= 3.0.0)
-      uniform_notifier (~> 1.9.0)
-    byebug (8.2.5)
+      uniform_notifier (~> 1.10.0)
+    byebug (9.0.5)
     choice (0.2.0)
     chronic (0.10.2)
     climate_control (0.0.3)
@@ -94,6 +96,7 @@ GEM
     connection_pool (2.2.0)
     curb (0.8.8)
     cvss (0.99.0)
+    daemons (1.2.3)
     dalli (2.7.6)
     data_mapper (1.2.0)
       dm-aggregates (~> 1.2.0)
@@ -122,7 +125,7 @@ GEM
     debug_inspector (0.0.2)
     descendants_tracker (0.0.4)
       thread_safe (~> 0.3, >= 0.3.1)
-    devise (4.0.2)
+    devise (4.0.3)
       bcrypt (~> 3.0)
       orm_adapter (~> 0.1)
       railties (>= 4.1.0, < 5.1)
@@ -131,6 +134,7 @@ GEM
     devise_token_auth (0.1.37)
       devise (> 3.5.2, < 4.1)
       rails (< 6)
+    diff-lcs (1.2.5)
     dm-aggregates (1.2.0)
       dm-core (~> 1.2.0)
     dm-constraints (1.2.0)
@@ -183,15 +187,21 @@ GEM
       multi_json
     equalizer (0.0.11)
     erubis (2.7.0)
-    execjs (2.6.0)
+    eventmachine (1.0.9.1)
+    execjs (2.7.0)
+    factory_girl (4.7.0)
+      activesupport (>= 3.0.0)
+    factory_girl_rails (4.7.0)
+      factory_girl (~> 4.7.0)
+      railties (>= 3.0.0)
+    faker (1.6.3)
+      i18n (~> 0.5)
     faraday (0.9.2)
       multipart-post (>= 1.2, < 3)
-    fast_stack (0.2.0)
     fastercsv (1.5.5)
     feature (1.3.0)
     ffi (1.9.10)
-    flamegraph (0.1.0)
-      fast_stack
+    flamegraph (0.9.5)
     flay (2.7.0)
       erubis (~> 2.7.0)
       ruby_parser (~> 3.0)
@@ -227,26 +237,36 @@ GEM
       nokogiri (>= 1.5.9)
     mail (2.6.4)
       mime-types (>= 1.16, < 4)
-    mime-types (3.0)
+    mailcatcher (0.6.4)
+      activesupport (~> 4.0)
+      eventmachine (= 1.0.9.1)
+      mail (~> 2.3)
+      rack (~> 1.5)
+      sinatra (~> 1.2)
+      skinny (~> 0.2.3)
+      sqlite3 (~> 1.3)
+      thin (~> 1.5.0)
+    mime-types (3.1)
       mime-types-data (~> 3.2015)
-    mime-types-data (3.2016.0221)
+    mime-types-data (3.2016.0521)
     mimemagic (0.3.0)
     mina (0.3.8)
       open4 (~> 1.3.4)
       rake
-    mini_portile2 (2.0.0)
-    minitest (5.8.4)
+    mini_portile2 (2.1.0)
+    minitest (5.9.0)
     minitest-reporters (1.1.9)
       ansi
       builder
       minitest (>= 5.0)
       ruby-progressbar
-    multi_json (1.12.0)
+    multi_json (1.12.1)
     multi_xml (0.5.5)
     multipart-post (2.0.0)
     net-http-persistent (2.9.4)
-    nokogiri (1.6.7.2)
-      mini_portile2 (~> 2.0.0.rc2)
+    nokogiri (1.6.8)
+      mini_portile2 (~> 2.1.0)
+      pkg-config (~> 1.1.7)
     oauth (0.5.1)
     oauth2 (1.1.0)
       faraday (>= 0.8, < 0.10)
@@ -275,16 +295,23 @@ GEM
       omniauth-oauth (~> 1.1)
     open4 (1.3.4)
     orm_adapter (0.5.0)
+    paper_trail (5.1.1)
+      activerecord (>= 3.0, < 6.0)
+      activesupport (>= 3.0, < 6.0)
+      request_store (~> 1.1)
     paperclip (4.3.6)
       activemodel (>= 3.2.0)
       activesupport (>= 3.2.0)
       cocaine (~> 0.5.5)
       mime-types
       mimemagic (= 0.3.0)
-    parser (2.3.0.7)
+    paranoia (2.1.5)
+      activerecord (~> 4.0)
+    parser (2.3.1.0)
       ast (~> 2.2)
     pg (0.18.4)
     phantomjs (2.1.1.0)
+    pkg-config (1.1.7)
     powerpack (0.1.1)
     ptools (1.3.3)
     public_activity (1.5.0)
@@ -297,7 +324,7 @@ GEM
       activesupport (>= 3.0.0)
     rack (1.6.4)
     rack-cors (0.4.0)
-    rack-mini-profiler (0.9.9.2)
+    rack-mini-profiler (0.10.1)
       rack (>= 1.2.0)
     rack-protection (1.5.3)
       rack
@@ -332,6 +359,8 @@ GEM
       ruby-graphviz (~> 1.2)
     rails-html-sanitizer (1.0.3)
       loofah (~> 2.0)
+    rails-observers (0.1.2)
+      activemodel (~> 4.0)
     railties (4.2.6)
       actionpack (= 4.2.6)
       activesupport (= 4.2.6)
@@ -344,32 +373,50 @@ GEM
     redis (3.3.0)
     redis-namespace (1.5.2)
       redis (~> 3.0, >= 3.0.4)
-    reek (4.0.1)
+    reek (4.0.2)
       codeclimate-engine-rb (~> 0.3.1)
       parser (~> 2.3, >= 2.3.0.6)
       rainbow (~> 2.0)
+    request_store (1.3.1)
     resource_kit (0.1.5)
       addressable (~> 2.3.6)
     responders (2.2.0)
       railties (>= 4.2.0, < 5.1)
     rmagick (2.15.4)
-    rubocop (0.39.0)
-      parser (>= 2.3.0.7, < 3.0)
+    rspec-core (3.4.4)
+      rspec-support (~> 3.4.0)
+    rspec-expectations (3.4.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.4.0)
+    rspec-mocks (3.4.1)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.4.0)
+    rspec-rails (3.4.2)
+      actionpack (>= 3.0, < 4.3)
+      activesupport (>= 3.0, < 4.3)
+      railties (>= 3.0, < 4.3)
+      rspec-core (~> 3.4.0)
+      rspec-expectations (~> 3.4.0)
+      rspec-mocks (~> 3.4.0)
+      rspec-support (~> 3.4.0)
+    rspec-support (3.4.1)
+    rubocop (0.40.0)
+      parser (>= 2.3.1.0, < 3.0)
       powerpack (~> 0.1)
       rainbow (>= 1.99.1, < 3.0)
       ruby-progressbar (~> 1.7)
       unicode-display_width (~> 1.0, >= 1.0.1)
     ruby-graphviz (1.2.2)
-    ruby-progressbar (1.8.0)
+    ruby-progressbar (1.8.1)
     ruby_parser (3.8.2)
       sexp_processor (~> 4.1)
-    rubycritic (2.9.0)
+    rubycritic (2.9.1)
       colorize
       flay (= 2.7.0)
       flog (= 4.3.2)
       launchy (= 2.4.3)
-      parser (= 2.3.0.7)
-      reek (= 4.0.1)
+      parser (= 2.3.1.0)
+      reek (= 4.0.2)
       ruby_parser (~> 3.8)
       virtus (~> 1.0)
     rubyzip (1.2.0)
@@ -397,8 +444,11 @@ GEM
       rack (~> 1.5)
       rack-protection (~> 1.4)
       tilt (>= 1.3, < 3)
-    slim (3.0.6)
-      temple (~> 0.7.3)
+    skinny (0.2.4)
+      eventmachine (~> 1.0.0)
+      thin (>= 1.5, < 1.7)
+    slim (3.0.7)
+      temple (~> 0.7.6)
       tilt (>= 1.3.3, < 2.1)
     spring (1.7.1)
     sprockets (3.6.0)
@@ -414,15 +464,19 @@ GEM
     stringex (1.5.1)
     sys-uname (1.0.2)
       ffi (>= 1.0.0)
-    temple (0.7.6)
-    terminal-table (1.5.2)
+    temple (0.7.7)
+    terminal-table (1.6.0)
+    thin (1.5.1)
+      daemons (>= 1.0.9)
+      eventmachine (>= 0.12.6)
+      rack (>= 1.0.0)
     thor (0.19.1)
     thread_safe (0.3.5)
-    tilt (2.0.2)
+    tilt (2.0.5)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
     unicode-display_width (1.0.5)
-    uniform_notifier (1.9.0)
+    uniform_notifier (1.10.0)
     uuidtools (2.1.5)
     virtus (1.0.5)
       axiom-types (~> 0.1)
@@ -458,18 +512,23 @@ DEPENDENCIES
   devise_token_auth
   dspace_rest_client
   execjs
+  factory_girl_rails
+  faker
   feature
   flamegraph
   gitlab
   immigrant
   libarchive-static
+  mailcatcher
   mimemagic
   mina
   minitest-reporters
   omniauth-facebook
   omniauth-google-oauth2
   omniauth-twitter
+  paper_trail
   paperclip
+  paranoia (~> 2.0)
   pg
   public_activity
   puma
@@ -479,10 +538,12 @@ DEPENDENCIES
   rails (= 4.2.6)
   rails-api
   rails-erd
+  rails-observers
   rainbow
   rdoc
   redis-throttle!
   rmagick
+  rspec-rails
   rubocop
   rubycritic
   rubyzip
@@ -500,4 +561,4 @@ DEPENDENCIES
   whenever
 
 BUNDLED WITH
-   1.12.1
+   1.12.3
diff --git a/app/builders/learning_object/draft_builder.rb b/app/builders/learning_object/draft_builder.rb
index 3c4f318eb36ce0d09456d35e6f177809eaf912ad..cf7fe5b7c594738e8855906b3c3c282d01cb472b 100644
--- a/app/builders/learning_object/draft_builder.rb
+++ b/app/builders/learning_object/draft_builder.rb
@@ -2,35 +2,32 @@ class LearningObject::DraftBuilder
 
   def self.build(publisher, params={})
     @draft = LearningObject.new(sanitize_params(params))
-    @draft.draft
-
-
+    @draft.draft!
 
     #build language
     @draft.language = Language.find(params[:language]) if params[:language].to_i > 0
 
     # set publisher
     @draft.publisher = publisher
-
     @draft.save
+
     # build tags
     params[:tags].try(:each) do |t|
       tag = Tag.where(name: t['name']).first_or_create
       Tagging.where(tag: tag, taggable: @draft, tagger: publisher).first_or_create
     end
     @draft.save
+
     @draft
   end
 
-  private
-
   def self.sanitize_params(args={})
-    _args = args.clone
+    params = args.clone
     %w(tags language link).each do |arg|
-      _args.delete(arg)
+      params.delete(arg)
     end
-    metadata = [{'key' => 'dc.object.url', 'value' => args[:link]}]
-    _args.merge(metadata: metadata)
+    metadata = { 'dc.object.url' => args[:link] }
+    params.merge(metadata: metadata)
   end
 
 end
diff --git a/app/builders/learning_object_builder.rb b/app/builders/learning_object_builder.rb
index 9a48e71cef22b149da4ab554a1366738a7f6fe9f..e1839a9c2f5d2195f5ef360647d276191bf5ecc9 100644
--- a/app/builders/learning_object_builder.rb
+++ b/app/builders/learning_object_builder.rb
@@ -1,14 +1,13 @@
 class LearningObjectBuilder
-
   def self.build_from_dspace(item)
     lo = LearningObject.new(
-        name: item.name,
-        id_dspace: item.id,
-        thumbnail: nil,
-        metadata: item.metadata.map(&:to_h)
+      name: item.name,
+      id_dspace: item.id,
+      thumbnail: nil,
+      metadata: dspace_metadata_to_hash(item.metadata)
     )
 
-    institution = lo.get_metadata_values_of('dc.creator').first
+    institution = lo.get_metadata_value_of('dc.creator')
     institution = 'Desconhecido' if institution.blank?
     lo.publisher = Institution.where(name: institution).first_or_create
 
@@ -49,9 +48,13 @@ class LearningObjectBuilder
     _params
   end
 
- # private
+  def self.dspace_metadata_to_hash(metadata)
+    hash = Hash.new { |h, k| h[k] = Array.new(&h.default_proc) }
+    metadata.each { |m| hash[m.key] << m.value }
+    hash
+  end
 
-  #def self.sanitize_form_metadata(params={})
+  # def self.sanitize_form_metadata(params={})
   #  if !params[:link].blank?
   #    metadata = [{'key' => 'dc.object.url', 'value' => params[:link]}]
   #    _args.merge(metadata: metadata)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 03b7e34c95cce71bd52b0dde11b4cf639f7081fb..d904c81c1a0f597f8fa851b0364080ca2dd914bd 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -4,6 +4,12 @@ class ApplicationController < ActionController::API
   include Pundit
   include PublicActivity::StoreController
 
+  # tracking user in papertrail
+  before_action :set_paper_trail_whodunnit
+
+  # check if client application is allowed to consumes the API.
+  before_action :allow_client_application, if: -> { Feature.active?(:allow_client_application) }
+
   # Prevent CSRF attacks by raising an exception.
   # For APIs, you may want to use :null_session instead.
   # protect_from_forgery with: :null_session
@@ -17,23 +23,19 @@ class ApplicationController < ActionController::API
   protected
 
   def configure_permitted_parameters
-    registration_params = [:name, :email, :avatar, :password, :password_confirmation]
-
-    if params[:action] == 'update'
-      devise_parameter_sanitizer.for(:account_update) {
-          |u| u.permit(registration_params << :current_password)
-      }
-    elsif params[:action] == 'create'
-      devise_parameter_sanitizer.for(:sign_up) {
-          |u| u.permit(registration_params << :terms_of_service)
-      }
-    end
+    registration_params = [:name, :email, :avatar, :password, :password_confirmation, :current_password, :terms_of_service]
+    devise_parameter_sanitizer.permit :sign_up, keys: registration_params
+    devise_parameter_sanitizer.permit :account_update, keys: registration_params
   end
 
   private
 
+  def allow_client_application
+    app = Application.find_or_initialize_by(application_id: request.headers["PortalMEC-AppID"].to_s)
+    user_not_authorized if app.domain != request.domain
+  end
+
   def user_not_authorized
     render nothing: true, status: :unauthorized
   end
-
 end
diff --git a/app/controllers/concerns/deleted_objects_controller.rb b/app/controllers/concerns/deleted_objects_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2eeee836d94222119f9db2486516bb4ea3c1401b
--- /dev/null
+++ b/app/controllers/concerns/deleted_objects_controller.rb
@@ -0,0 +1,14 @@
+module DeletedObjectsController
+  extend ActiveSupport::Concern
+
+  def deleted
+    render json: deleted_resource.only_deleted
+  end
+
+  protected
+
+  def deleted_resource
+    raise NotImplementedError
+  end
+
+end
diff --git a/app/controllers/concerns/followable_controller.rb b/app/controllers/concerns/followable_controller.rb
index 33d81f3e0e408c0e6c522f5220bef1df20e93415..ba1aee20646739b28e44aeb34c8fbbf741f8ed60 100644
--- a/app/controllers/concerns/followable_controller.rb
+++ b/app/controllers/concerns/followable_controller.rb
@@ -28,5 +28,4 @@ module FollowableController
       render nothing: true, status: :forbidden
     end
   end
-
-end
\ No newline at end of file
+end
diff --git a/app/controllers/concerns/highlights_controller.rb b/app/controllers/concerns/highlights_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8ff30cc9708b94f44b0708e49596fc406a3d6a37
--- /dev/null
+++ b/app/controllers/concerns/highlights_controller.rb
@@ -0,0 +1,16 @@
+module HighlightsController
+  extend ActiveSupport::Concern
+
+  # GET /v1/learning_objects/this_week
+  # GET /v1/learning_objects/this_week.json
+  def this_week
+    render json: highlights_resource.this_week
+  end
+
+  # GET /v1/learning_objects/this_month
+  # GET /v1/learning_objects/this_month.json
+  def this_month
+    render json: highlights_resource.this_month
+  end
+
+end
diff --git a/app/controllers/concerns/resource_model.rb b/app/controllers/concerns/resource_model.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e8763ac79c8b1c1f08717622076a4ce2686a2598
--- /dev/null
+++ b/app/controllers/concerns/resource_model.rb
@@ -0,0 +1,12 @@
+module ResourceModel
+  extend ActiveSupport::Concern
+
+  protected
+
+  def resource_model
+    resource, id = request.path.split('/')[2, 3]
+    resource_model = resource.singularize.classify.constantize
+    resource_model.find(id)
+  end
+
+end
diff --git a/app/controllers/concerns/sociable_controller.rb b/app/controllers/concerns/sociable_controller.rb
index 7ef79fed13f8681a39c0641f45a7d8070c8e1324..9ad2d5a95cda8e69cf70391411943abc6dad3b11 100644
--- a/app/controllers/concerns/sociable_controller.rb
+++ b/app/controllers/concerns/sociable_controller.rb
@@ -7,8 +7,8 @@ module SociableController
 
   included do
     before_action :authenticate_user!, only: [:like, :unlike]
+    before_action :authorize_sociable!, only: [:like, :unlike]
     before_action :view_object!, only: VIEWABLE_METHODS
-    before_action :sociable, only: [:like, :unlike]
   end
 
   # POST /v1/learning_objects/1/like
@@ -35,6 +35,14 @@ module SociableController
 
   protected
 
+  def authorize_sociable!
+    authorize sociable
+  end
+
+  def sociable
+    raise NotImplementedError
+  end
+
   def view_object!
     sociable.view current_user if user_signed_in?
   end
diff --git a/app/controllers/concerns/taggable_controller.rb b/app/controllers/concerns/taggable_controller.rb
index c01fccbad6f5e21c204743177c10e73ee3b62645..bfe6382eb41ec11b898128e5e2b296043ac96fbe 100644
--- a/app/controllers/concerns/taggable_controller.rb
+++ b/app/controllers/concerns/taggable_controller.rb
@@ -10,14 +10,14 @@ module TaggableController
   # POST /v1/learning_objects/1/tagging.json
   def tagging
     @owner.tag(taggable, with: [tag_params[:name]])
-    render json: ActiveModel::ArraySerializer.new(taggable.tags.to_a), status: :created
+    render json: taggable.tags, status: :created
   end
 
   # DELETE /v1/learning_objects/1/untagging
   # DELETE /v1/learning_objects/1/untagging.json
   def untagging
     @owner.untag(taggable, tag_params[:name])
-    render json: ActiveModel::ArraySerializer.new(taggable.tags.to_a), status: :ok
+    render json: taggable.tags, status: :ok
   end
 
   protected
diff --git a/app/controllers/old/about_controller.rb b/app/controllers/old/about_controller.rb
deleted file mode 100644
index a14c5285394b25132c61dc0562014403bc8ad507..0000000000000000000000000000000000000000
--- a/app/controllers/old/about_controller.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-class AboutController < ApplicationController
-  def index
-  end
-end
diff --git a/app/controllers/old/bookmarks_controller.rb b/app/controllers/old/bookmarks_controller.rb
deleted file mode 100644
index 0dccaf5650ce3f19e62f7958053fe880caca1741..0000000000000000000000000000000000000000
--- a/app/controllers/old/bookmarks_controller.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-class BookmarksController < ApplicationController
-  include Pundit
-
-  before_action :authenticate_user!
-  before_action :set_user
-  before_action :find_object, only: [:add_object, :remove_object]
-
-
-  # GET /bookmarks/1
-  # GET /bookmarks/1.json
-  def show
-    render partial: 'list' if params[:list] == 'true'
-  end
-
-  # POST /bookmarks/1/learning_object
-  def add_object
-    authorize @object
-    Bookmark.create(user: @user, bookmarkable: @object)
-
-    render json: { status: true } if request.xhr?
-  end
-
-  def list
-    render layout: false
-  end
-
-  # DELETE /bookmarks/1/learning_object
-  def remove_object
-    authorize @object
-    Bookmark.destroy Bookmark.where(user: @user, bookmarkable: @object)
-
-    render json: { status: true } if request.xhr?
-  end
-
-  private
-
-  def set_user
-    @user = current_user
-  end
-
-  def find_object
-    klass = params[:type].constantize
-    @object = klass.find params[:id]
-  end
-
-end
diff --git a/app/controllers/old/callbacks_controller.rb b/app/controllers/old/callbacks_controller.rb
deleted file mode 100644
index 56360cbdf6051b7efc7f63ef43d5512a7b08fa0e..0000000000000000000000000000000000000000
--- a/app/controllers/old/callbacks_controller.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-class CallbacksController < Devise::OmniauthCallbacksController
-
-  def facebook
-    request_data("Facebook","devise.facebook_data")
-  end
-
-  def twitter
-    request_data("Twitter","devise.twitter_data")
-  end
-
-  def google_oauth2
-    request_data("Google","devise.google_oauth2_data")
-  end
-
-  private
-
-  def request_data(provider,provider_session)
-    @user = User.from_omniauth(request.env["omniauth.auth"])
-
-      if @user.persisted?
-        sign_in_and_redirect @user, :event => :authentication
-        flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider
-      else
-        session[provider_session] = request.env["omniauth.auth"]
-        redirect_to new_user_registration_url
-      end
-
-      def failure
-        redirect_to root_path
-      end
-  end
-
-end
diff --git a/app/controllers/old/chunks_controller.rb b/app/controllers/old/chunks_controller.rb
deleted file mode 100644
index 460eee164e8ffd09737ccad7e0c45e3fc612a20a..0000000000000000000000000000000000000000
--- a/app/controllers/old/chunks_controller.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-class ChunksController < ApplicationController
-  layout nil
-
-  before_action :set_learning_object
-
-  #GET /chunk
-  def show
-    chunk = resumable_chunk chunk_number
-
-    unless valid_mime_type?
-      render :nothing => true, :status => 415
-    else
-      if File.exists?(chunk)
-        post_file_and_create_thumbnail @learning_object, resumable_filename if last_chunk?
-        #Let resumable.js know this chunk already exists
-        render :nothing => true, :status => 200
-      else
-        #Let resumable.js know this chunk doesnt exists and needs to be uploaded
-        render :nothing => true, :status => 404
-      end
-    end
-  end
-  #POST /chunk
-  def create
-
-    unless valid_mime_type?
-      return render :nothing => true, :status => 415
-    end
-
-    #chunk path based on the parameters
-    chunk = resumable_chunk chunk_number
-
-    #Create chunks directory when not present on system
-    if !File.directory?(dir)
-      FileUtils.mkdir(dir, :mode => 0700)
-    end
-
-    #Move the uploaded chunk to the directory
-    FileUtils.mv chunk_tmpfile, chunk
-
-    #Concatenate all the partial files into the original file
-    #When all chunks are uploaded
-    if last_chunk?
-      #Create a target file
-      File.open(resumable_filename, "a") do |target|
-        #Loop trough the chunks
-        for i in 1..chunk_number
-          #Select the chunk
-          chunk = File.open(resumable_chunk(i), 'r').read
-
-          #Write chunk into target file
-          chunk.each_line do |line|
-            target << line
-          end
-
-          #Deleting chunk
-          FileUtils.rm resumable_chunk(i), :force => true
-        end
-        puts "File saved to #{resumable_filename}"
-      end
-
-      post_file_and_create_thumbnail @learning_object, resumable_filename
-    end
-
-    render nothing: true, status: 200
-  end
-
-  private
-
-  def post_file_and_create_thumbnail(learning_object, filename)
-    publisher = LearningObjectPublisher.new(DspaceService.create_client)
-    publisher.post learning_object, filename
-  end
-
-  def chunk_tmpfile
-    chunks_params[:file].tempfile
-  end
-
-  def last_chunk?
-    chunk_number == total_chunks
-  end
-
-  def chunk_size
-    chunks_params[:resumableChunkSize].to_i
-  end
-
-  def total_chunks
-    chunks_params[:resumableTotalChunks].to_i
-  end
-
-  def chunk_number
-    chunks_params[:resumableChunkNumber].to_i
-  end
-
-  def resumable_chunk(part)
-    "#{resumable_filename}.part#{part}"
-  end
-
-  def resumable_filename
-    "#{dir}/#{chunks_params[:resumableFilename]}"
-  end
-
-  def dir
-    "/tmp/#{chunks_params[:resumableIdentifier]}"
-  end
-
-  def set_learning_object
-    @learning_object = LearningObject.find chunks_params[:learning_object_id]
-  end
-
-  def resumable_file_extension
-    File.extname(chunks_params[:resumableFilename])[1..-1]
-  end
-
-  def valid_mime_type?
-    mime_types = @learning_object.object_type.mime_types.map(&:extension)
-    return true if mime_types.empty?
-    mime_types.include? resumable_file_extension
-  end
-  # Never trust parameters from the scary internet, only allow the white list through.
-  def chunks_params
-    params.permit(:file, :learning_object_id, :resumableIdentifier, :resumableFilename, :resumableChunkNumber, :resumableTotalChunks, :resumableChunkSize)
-  end
-end
diff --git a/app/controllers/old/collections_controller.rb b/app/controllers/old/collections_controller.rb
deleted file mode 100644
index 9ae2446a9aa477e56850fa01966487fb738f66b1..0000000000000000000000000000000000000000
--- a/app/controllers/old/collections_controller.rb
+++ /dev/null
@@ -1,229 +0,0 @@
-class CollectionsController < ApplicationController
-  include Pundit
-
-  before_action :set_collection, only: [:show, :update, :destroy, :like, :change_privacy]
-  before_action :set_collections, only: [:list, :add_learning_object, :remove_learning_object]
-  before_action :authenticate_user!, only: [:update, :destroy, :like, :list, :me, :add_learning_object, :remove_learning_object, :change_privacy]
-  before_action :authorize_action, only: [:show, :create, :update, :destroy, :add_learning_object, :remove_learning_object, :change]
-
-  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
-
-
-  # GET /collections
-  # GET /collections.json
-  def index
-    respond_to do |format|
-      # for HTML page, returns institutional collections
-      format.html do
-        @collections = Collection.all.where(owner: Institution.all)
-      end
-
-      # returns all collection of logged user as JSON for UI actions
-      if user_signed_in?
-        format.json do
-          @collections = current_user.collections
-        end
-      end
-    end
-  end
-
-  # GET /collections/1
-  # GET /collections/1.json
-  def show
-    if @collection.class == User
-      # bookmark
-      @user = @collection
-      @collection = collection_repository.bookmarks(@user)
-      @own = true
-    else
-      check_collection_privacy! @collection
-
-      @user = @collection.owner
-      @own = user_signed_in? ? @collection.user_own?(current_user) : false
-    end
-
-    @reviews = Review.includes(:user).where(reviewable: @collection)
-
-    render partial: 'list' if params[:list] == 'true'
-  end
-
-  # POST /collections/1/like
-  def like
-    Collection.like @collection
-  end
-
-  # POST /collections
-  # POST /collections.json
-  def create
-    @collection = Collection.new(collection_params)
-    @collection.owner = params[:collection][:owner].blank? ? current_user : Institution.find(params[:collection][:owner])
-
-    respond_to do |format|
-      if @collection.save
-        format.html { redirect_to :back, notice: t('activerecord.attributes.collection.create.notice.successfully_created') }
-      else
-        format.html { render :new }
-      end
-    end
-  end
-
-  # PATCH/PUT /collections/1
-  # PATCH/PUT /collections/1.json
-  def update
-    respond_to do |format|
-      if Collection.update(collection_params)
-        format.html { redirect_to @collection, notice: t('activerecord.attributes.collection.update.notice.successfully_updated') }
-      else
-        format.html { render :edit }
-      end
-    end
-  end
-
-  # DELETE /collections/1
-  # DELETE /collections/1.json
-  def destroy
-    Collection.destroy @collection
-
-    respond_to do |format|
-      format.html { redirect_to user_path(current_user), notice: t('activerecord.attributes.collection.destroy.notice.successfully_destroy') }
-    end
-  end
-
-  def list
-    @collection = @collections.first
-
-    # list all
-    @collection = nil if @collection == 'all'
-
-    @collections = current_user.associated_collections
-    @collections.select! do |c|
-      (!@collection.blank? && c.id != @collection.id) || !include_learning_objects?(c)
-    end
-    @type = params[:type]
-
-    unless @type.blank?
-      @send = case @type
-                when 'add' then
-                  'Adicionar'
-                when 'copy' then
-                  'Copiar'
-                when 'move' then
-                  'Mover'
-                else
-                  'Enviar'
-              end
-
-      @title = (@send == 'Enviar') ? 'Coleções' : @send + '  objeto(s) às coleções'
-    end
-
-    render layout: false
-  end
-
-  def me
-    @new_collection = Collection.new
-
-    @publishers = current_user.institutions
-    @bookmark = (current_user.bookmarks.nil? || current_user.bookmarks.first.nil?) ? [] : [current_user.bookmarks.first]
-
-    @groups = [
-        CollectionsGroup.new(title: 'Coleções Automáticas',
-                             collections: @bookmark),
-        CollectionsGroup.new(title: 'Coleções Adicionadas',
-                             collections: current_user.associated_collections)
-    ]
-
-  end
-
-  # POST /collections/1/learning_object
-  def add_learning_object
-    @collections.each do |collection|
-      next unless collection.user_own?(current_user)
-
-      @learning_objects.each do |learning_object|
-        collection.learning_objects << learning_object unless collection.learning_objects.include? learning_object
-      end
-      collection.save
-    end
-
-    render json: {status: true} if request.xhr?
-  end
-
-  # DELETE /collections/1/learning_object
-  def remove_learning_object
-    @collections.each do |collection|
-      next unless collection.user_own?(current_user)
-
-      @learning_objects.each do |learning_object|
-        collection.learning_objects.destroy(learning_object)
-      end
-      collection.save
-    end
-
-    render json: {status: true} if request.xhr?
-  end
-
-  # change collection privacy
-  def change_privacy
-    @collection.privacy = params[:privacy]
-
-    response = @collection.save
-
-    render json: {status: response} if request.xhr?
-  end
-
-  private
-
-  def include_learning_objects?(collection)
-    @learning_objects.each do |lo|
-      return true if collection.learning_objects.include? lo
-    end
-    false
-  end
-
-  def check_collection_privacy!(collection)
-    if collection.private? && !collection.user_own?(current_user)
-      redirect_to :root, notice: 'Está é uma coleção privada.'
-    end
-  end
-
-  def set_collection
-    @collection = Collection.find params[:id]
-  end
-
-  def set_collections
-    if params[:id] == 'all' || params[:id].blank?
-      @collections = ['all']
-    else
-      @collections = (params[:id].class == String) ? [Collection.find(params[:id])] : params[:id].map { |id| Collection.find id }
-    end
-
-    unless params[:learning_objects_ids].blank?
-      @learning_objects = []
-
-      params[:learning_objects_ids].split(',').each do |id|
-        object = LearningObject.find id
-        @learning_objects << object unless object.blank?
-      end
-    end
-  end
-
-  # Never trust parameters from the scary internet, only allow the white list through.
-  def collection_params
-    params.require(:collection).permit(:name, :description, learning_objects: [])
-  end
-
-  def user_not_authorized
-    flash[:notice] = "Esta coleção é privada!"
-    redirect_to (root_path)
-  end
-
-  def authorize_action
-    if !@collections.nil?
-      @collections.each { |c| authorize c }
-    else
-      @collection ||= Collection.new
-      authorize @collection
-    end
-  end
-
-end
diff --git a/app/controllers/old/complaints_controller.rb b/app/controllers/old/complaints_controller.rb
deleted file mode 100644
index 0766279742594ccac197ebb57f097158e3b562a8..0000000000000000000000000000000000000000
--- a/app/controllers/old/complaints_controller.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-class ComplaintsController < ApplicationController
-  include Pundit
-
-  before_action :authorize_action
-  before_action :authenticate_user!
-
-  def create
-    complaint = Complaint.new(complaint_params)
-    complaint.user = current_user
-
-    respond_to do |format|
-      if complaint.save
-        format.html { redirect_to :back, notice: t('activerecord.attributes.complaint.create.notice.sucess') }
-      else
-        format.html { redirect_to :back, alert: t('activerecord.attributes.complaint.create.alert.failure') }
-      end
-    end
-  end
-
-  private
-
-  # Never trust parameters from the scary internet, only allow the white list through.
-  def complaint_params
-    params.require(:complaint).permit(:complaintable_id, :complaintable_type, :complaint_reason_id, :description)
-  end
-
-  def authorize_action
-    @complaint ||= Complaint.new(complaint_params)
-    authorize @complaint
-  end
-
-end
diff --git a/app/controllers/old/feedbacks_controller.rb b/app/controllers/old/feedbacks_controller.rb
deleted file mode 100644
index bf391b700c3b8f13aff4b4a7ec5228b46c51c575..0000000000000000000000000000000000000000
--- a/app/controllers/old/feedbacks_controller.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-class FeedbacksController < ApplicationController
-  before_filter :authenticate_user!
-
-  # GET /feedbacks/new
-  def new
-  #  @feedbacks = Feedback.new
-
-#    render layout: false
- end
-
-  # GET /feedbacks/new_bug
-  def new_bug
-    @bug = Bug.new
-
-    render layout: false
-  end
-
-  # POST /feedbacks
-  def create
-   # @feedbacks = Feedback.new(feedback_params)
-
-   # respond_to do |format|
-   #   if feedback_service.send_feedback @feedbacks
-   #     format.html { redirect_to :back, notice: 'Obrigado pela sua avaliação!' }
-  #    end
-  #  end
-  end
-
-  # POST /feedbacks/report_bug
-  def report_bug
-    @bug = Bug.new(bug_params)
-
-    respond_to do |format|
-      if feedback_service.report_bug @bug
-        format.html { redirect_to :back, notice: t('activerecord.attributes.feedback.report_bug.notice.success') }
-      end
-    end
-  end
-
-  private
-
-  def feedback_service
-    FeedbackService.new(GitlabBugreporterService.new(Gitlab))
-  end
-
-  def bug_params
-    params.require(:bug).permit(:title, :description)
-  end
-
-  def feedback_params
-    params.require(:feedbacks).permit(:object, :message, :description)
-  end
-
-end
diff --git a/app/controllers/old/institutions_controller.rb b/app/controllers/old/institutions_controller.rb
deleted file mode 100644
index 0f89f86b0a5bf486916863ece16809455b1162d8..0000000000000000000000000000000000000000
--- a/app/controllers/old/institutions_controller.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-class InstitutionsController < ApplicationController
-  include Pundit
-
-  before_action :set_institution, only: [:show, :edit, :update, :destroy, :like, :users]
-  before_action :authorize_action
-
-  # GET /institutions
-  # GET /institutions.json
-  def index
-    @institutions = Institution.all
-  end
-
-  # GET /institutions/1
-  # GET /institutions/1.json
-  def show
-  end
-
-  # GET /institutions/new
-  def new
-    @institution = Institution.new
-  end
-
-  # GET /institutions/1/edit
-  def edit
-  end
-
-  # POST /institutions
-  # POST /institutions.json
-  def create
-    @institution = Institution.new(institution_params)
-
-    respond_to do |format|
-      if Institution.save @institution
-        format.html { redirect_to @institution, notice: t('activerecord.attributes.institution.create.notice.successfully_created') }
-      else
-        format.html { render :new }
-      end
-    end
-  end
-
-  # PATCH/PUT /institutions/1
-  # PATCH/PUT /institutions/1.json
-  def update
-    respond_to do |format|
-      if Institution.update(institution_params)
-        format.html { redirect_to @learning_object, notice: t('activerecord.attributes.institution.update.notice.successfully_updated') }
-      else
-        format.html { render :edit }
-      end
-    end
-  end
-
-  # DELETE /institutions/1
-  # DELETE /institutions/1.json
-  def destroy
-    Institution.destroy @institution
-
-    respond_to do |format|
-      format.html { redirect_to institutions_url, notice: t('activerecord.attributes.institution.destroy.notice.successfully_destroy') }
-    end
-  end
-
-  def users
-    @users = @institution.users
-  end
-
-  private
-
-  def set_institution
-    @institution = Institution.find(params[:id])
-  end
-
-  # Never trust parameters from the scary internet, only allow the white list through.
-  def institution_params
-    params[:institution_object]
-  end
-
-  def authorize_action
-    @institution ||= Institution.new
-    authorize @institution
-  end
-
-end
diff --git a/app/controllers/old/learning_objects/build_controller.rb b/app/controllers/old/learning_objects/build_controller.rb
deleted file mode 100644
index 2463a66685c0241c5156e13c8fde94b17acab926..0000000000000000000000000000000000000000
--- a/app/controllers/old/learning_objects/build_controller.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-class LearningObjects::BuildController < ::ApplicationController
-  layout 'learning_object_studio'
-
-  include Wicked::Wizard
-  before_action :set_learning_object, only: [:show, :update]
-
-  steps :upload_attachments, :select_thumbnail
-
-  def show
-    render_wizard
-  end
-
-  def update
-    @learning_object.update_attributes(learning_object_params)
-    publish @learning_object if step == steps.last
-    render_wizard @learning_object, notice: update_message
-  end
-
-  private
-
-  def set_learning_object
-    @learning_object = LearningObject.unscoped.find(params[:learning_object_id])
-  end
-
-  def publish(learning_object)
-    learning_object.publish
-    learning_object.save
-  end
-
-  def learning_object_params
-    params[:learning_object].permit(:thumbnail, :name, :object_type_id, :description, :school_level, :language, :link, topics: [])
-  end
-
-  def update_message
-    case step
-      when :upload_attachments
-        "Seus arquivos foram enviados com sucesso! Agora atualize a imagem do seu conteúdo para finalizar o processo de criação."
-      when :select_thumbnail
-        "Parabéns, a imagem foi atualizada e seu conteúdo foi criado com sucesso! Acesse seu perfil e veja todos os objetos criados."
-    end
-  end
-end
\ No newline at end of file
diff --git a/app/controllers/old/learning_objects_controller.rb b/app/controllers/old/learning_objects_controller.rb
deleted file mode 100644
index 99915a21e11d573e7eb275d82d5281481727b4b2..0000000000000000000000000000000000000000
--- a/app/controllers/old/learning_objects_controller.rb
+++ /dev/null
@@ -1,174 +0,0 @@
-require 'uri'
-
-class LearningObjectsController < ApplicationController
-  include Reportable
-  layout :resolve_layout
-
-  before_action :authenticate_user!, except: [:index, :show]
-  before_action :set_learning_object, only: [:show, :edit, :update,
-                                             :destroy, :destroy_attachment, :remove_thumbnail, :like, :bookmarks,
-                                             :collections, :upload, :upload_link, :download,
-                                             :user_not_authorized]
-  after_action :increment_learning_object_views, only: [:show]
-  before_action :set_form_objects, only: [:new, :edit, :create]
-  before_action :authorize_action
-  before_action :set_preview_notice, only: :show
-
-  # GET /learning_objects/1
-  # GET /learning_objects/1.json
-  def show
-    @liked = @learning_object.liked?(current_user) if user_signed_in?
-    @reviews = Review.where(reviewable: @learning_object)
-  end
-
-  # GET /learning_objects/new
-  def new
-    @learning_object = LearningObject.new
-  end
-
-  # GET /learning_objects/1/edit
-  def edit
-  end
-
-  # POST /learning_objects
-  # POST /learning_objects.json
-  def create
-    @learning_object = ::LearningObject::DraftBuilder.build current_user, learning_object_params
-    publisher = LearningObjectPublisher.new(DspaceService.create_client)
-
-    respond_to do |format|
-      if publisher.create_draft @learning_object
-        # go to file submission page
-        format.html { success_redirect @learning_object }
-      else
-        format.html { render :new, notice:  t('activerecord.attributes.learning_object.create.notice.failure') }
-      end
-    end
-
-  end
-
-  # PATCH/PUT /learning_objects/1
-  # PATCH/PUT /learning_objects/1.json
-  def update
-    respond_to do |format|
-      if @learning_object.update(LearningObjectBuilder.build_form_params(learning_object_params))
-        format.html { redirect_to learning_object_build_path(learning_object_id: @learning_object.id, id: :upload_attachments), notice: 'Os metadados do seu conteúdo educacional foram atualizados com sucesso!' }
-      else
-        format.html { render :edit }
-      end
-    end
-  end
-
-  # DELETE /learning_objects/1
-  # DELETE /learning_objects/1.json
-  def destroy
-    LearningObject.destroy @learning_object
-
-    respond_to do |format|
-      format.html { redirect_to user_path(current_user), notice: t('activerecord.attributes.learning_object.destroy.notice.successfully_destroy') }
-    end
-  end
-
-  # POST /learning_objects/1/like
-  def like
-    if @learning_object.liked? current_user
-      @learning_object.dislike current_user
-    else
-      @learning_object.like current_user
-    end
-
-    if request.xhr?
-      render json: {count: @learning_object.likes.count, id: params[:id]}
-    end
-  end
-
-  def destroy_attachment
-    attachment = LearningObject::Attachment.find(params[:attachment_id])
-    @learning_object.update(attachment: nil) if @learning_object.attachment == attachment
-    attachment.destroy
-    render :nothing => true, :status => 204
-  end
-
-  def remove_thumbnail
-    @learning_object.thumbnail = nil
-    @learning_object.save
-    render :nothing => true, :status => 204
-  end
-
-  def download
-    @learning_object.download current_user
-
-    redirect_to @learning_object.retrieve_link
-  end
-
-  # POST /learning_objects/1/bookmarks
-  def bookmarks
-    bookmarks = current_user.bookmarks
-    bookmarks.add @learning_object
-    Collection.save_learning_objects bookmarks
-
-    if request.xhr?
-      render json: {id: params[:id]}
-    end
-  end
-
-  # GET /learning_objects/1/collections.json
-  def collections
-    @collections = @learning_object.collections
-  end
-
-  private
-
-  def set_preview_notice
-    if params[:preview_object]
-      flash[:notice] = %Q[Você está pré-visualizando o objeto. <a href='javascript:history.back()'>Clique aqui para voltar ao estúdio de criação</a>.]
-    end
-  end
-
-  # Use callbacks to share common setup or constraints between actions.
-  def set_learning_object
-    @learning_object = LearningObject.unscoped.find(params[:id])
-  end
-
-  # Never trust parameters from the scary internet, only allow the white list through.
-  def learning_object_params
-    params[:learning_object].permit(:author, :name, :object_type_id, :description, :school_level, :language, :link, topics: [])
-  end
-
-  def increment_learning_object_views
-    View.create(viewable: @learning_object, user: current_user) if user_signed_in? && @learning_object.publisher != current_user
-  end
-
-  def success_redirect(learning_object)
-    #if 'Website externo' == learning_object.object_type.name
-    redirect_to learning_object_build_path(learning_object, :upload_attachments), notice: t('activerecord.attributes.learning_object.success_redirect.notice.successfully_created')
-  end
-
-  def set_form_objects
-    @school_levels = ['Educação Infantil', 'Ensino Fundamental', 'Ensino Médio']
-    @topics = Topic.defaults
-    @types = ObjectType.all
-    @languages = Language.all
-  end
-
-  def user_not_authorized
-    flash[:notice] = "Este objeto está suspenso!"
-    flash[:alert] = "Razões: #{Complaint.where(complaintable_id: @learning_object.id).map(&:reason).join(',').to_s}"
-    redirect_to (root_path)
-  end
-
-  def resolve_layout
-    case action_name
-      when 'new', 'edit', 'create', 'update'
-        'learning_object_studio'
-      else
-        'application'
-    end
-  end
-
-  def authorize_action
-    @learning_object ||= LearningObject.new
-    authorize @learning_object
-  end
-
-end
diff --git a/app/controllers/old/links_controller.rb b/app/controllers/old/links_controller.rb
deleted file mode 100644
index 78529c149a984880a0270f5ad9baadca0de4106b..0000000000000000000000000000000000000000
--- a/app/controllers/old/links_controller.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-class LinksController < ApplicationController
-end
diff --git a/app/controllers/old/reviews_controller.rb b/app/controllers/old/reviews_controller.rb
deleted file mode 100644
index 75e783ee450532e96a7aaff7e66dabd8a4481321..0000000000000000000000000000000000000000
--- a/app/controllers/old/reviews_controller.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-class ReviewsController < ApplicationController
-  include Pundit
-
-  before_action :authenticate_user!, except: [:show, :list]
-  before_action :set_review, only: [:show, :destroy]
-  before_action :authorize_action
-
-
-  def list
-    if !params[:learning_object_id].blank?
-      reviewable = LearningObject.find params[:learning_object_id]
-    elsif !params[:collection_id].blank?
-      reviewable = Collection.find params[:collection_id]
-    end
-
-    @reviews = Review.where(reviewable: reviewable) unless reviewable.blank?
-  end
-
-  # Global variables to show page
-  def show
-  end
-
-  def new
-    @review = Review.new
-    @rates = Rating.all
-
-    @reviewable_id = params[:reviewable_id]
-    @reviewable_type = params[:reviewable_type]
-  end
-
-  def create
-    review = Review.where(user: current_user, reviewable_id: params[:reviewable_id], reviewable_type: params[:reviewable_type]).new(review_params)
-
-    respond_to do |format|
-      if review.save && !params[:rates].blank? && params[:rates].is_a?(Hash) && params[:rates].size == Rating.count
-        ratings = []
-        params[:rates].each { |id, value| ratings << ReviewRating.new(review: review, rating_id: id.to_i, value: value.to_i) }
-        ReviewRating.import ratings
-
-        format.html { redirect_to params[:reviewable_type].constantize.find(params[:reviewable_id]), notice: t('activerecord.attributes.review.create.notice.successfully_created') }
-      else
-        review.destroy
-        format.html { redirect_to new_review_path, alert: t('activerecord.attributes.review.create.alert.there_was_an_error')}
-      end
-    end
-  end
-
-  def destroy
-    redirect = @review.reviewable
-
-    @review.destroy
-
-    respond_to do |format|
-      format.html { redirect_to redirect, notice: t('activerecord.attributes.review.destroy.notice.successfully_destroy') }
-    end
-  end
-
-  # User approve or not, the review
-  def rate
-    review = Review.find(params[:id])
-    user = current_user
-    approves = approves_param
-
-    rate = Rate.where(user: user, review: review).first_or_initialize
-
-    if rate.approves == approves
-      rate.destroy
-    else
-      rate.update(approves: approves)
-    end
-
-    render json: { approves: approves } if request.xhr?
-  end
-
-  private
-
-  def set_review
-    @review = Review.find params[:id]
-  end
-
-  # Never trust parameters from the scary internet, only allow the white list through.
-  def review_params
-    params.require(:review).permit(:name, :description, :pros, :cons)
-  end
-
-  def approves_param
-    case params[:approves]
-    when 'true' then true
-    when 'false' then false
-    end
-  end
-
-  def authorize_action
-    @review||= Review.new
-    authorize @review
-  end
-
-end
diff --git a/app/controllers/old/search_controller.rb b/app/controllers/old/search_controller.rb
deleted file mode 100644
index dc7d2368f4456c1a5387cde2ce22b284694fab18..0000000000000000000000000000000000000000
--- a/app/controllers/old/search_controller.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-class SearchController < ApplicationController
-
-  include LearningObjectsHelper
-  include Pundit
-
-  def index
-    @types = ObjectType.all.map(&:name)
-
-    @topics = Topic.defaults
-
-    @school_levels = ['Educação Infantil', 'Ensino Fundamental', 'Ensino Médio'].map { |o| Topic.find_by_name(o) }
-
-    @sources = Institution.all
-  end
-
-  def fetch
-
-    params[:query] = "*" if params[:query].blank?
-
-    case params[:search_class]
-    when "LearningObject"
-      @result = LearningObject.search params[:query], where: where_hash(params), order: lo_order_hash(params), page: params[:page] || 1, per_page: 10
-    when "Collection"
-      @result = Collection.search params[:query], where: {privacy: "public"}, order: col_order_hash(params), page: params[:page] || 1, per_page: 10
-    when "User"
-      @result = User.search params[:query], order: user_order_hash(params), page: params[:page] || 1, per_page: 10
-    else
-      raise "Wrong search class parameter"
-    end
-
-    render partial: 'search/fetch'
-  end
-
-  def autocomplete
-    params_hash = {}
-    get_thumbnail = nil
-    case params[:search_class]
-    when "LearningObject"
-      params_hash = { fields: ['name^10', 'description', 'author'] }
-      get_thumbnail = Proc.new { |obj| image_tag(learning_object_thumbnail(obj)) }
-    when "Collection"
-      params_hash = { where: {privacy: "public"},
-        fields: ['name^10', 'description', 'owner'] }
-      get_thumbnail = Proc.new { |obj| image_tag("/assets/icons/collection") }
-    when "User"
-      params_hash = { fields: ['name'] }
-      get_thumbnail = Proc.new { |obj| image_tag(obj.avatar.url(:thumb), 32) }
-    else
-      raise "Wrong search class parameter"
-    end
-    render json: autocomplete_search(Object.const_get(params[:search_class]), params_hash, get_thumbnail)
-  end
-
-  def get_class_size
-    className = params[:class]
-    render json: { number: Object.const_get(className).count }
-  end
-
-  private
-
-  def autocomplete_search(search_class, params_hash={}, get_thumbnail)
-    response = []
-    search_params = { limit: 10, misspellings: { below: 5 }, where: {state: validate_object} }
-    objs = search_class.search(params[:query], search_params.merge(params_hash))
-    objs.each do |obj|
-      hash = {}
-      hash["name"] = obj.name
-      hash["thumbnail"] = get_thumbnail.call(obj)
-      hash["url"] = url_for([obj, :only_path => false])
-      response <<  hash
-    end
-    response
-  end
-
-  def image_tag(image, width=56, height=32)
-    ActionController::Base.helpers.image_tag image, width: width, height: height, class: "autocomplete"
-  end
-
-  def where_hash(params)
-    hash = {}
-
-    topics = params[:topic] unless params[:topic].blank?
-    topics += ", " unless topics.nil?
-    topics = topics.to_s + params[:school_level] unless params[:school_level].blank?
-
-    # build hash
-    hash[:topics_name] = topics.split(', ') unless topics.nil?
-    hash[:object_type] = params[:type].split(', ') unless params[:type].blank?
-    hash[:publisher] = params[:source].split("-s- ") unless params[:source].blank?
-    hash[:state] = validate_object
-    # year = params[:year].blank? ? nil : params[:year].split('-').take(2)
-
-    hash.blank? ? nil : hash
-  end
-
-  def lo_order_hash(params)
-    case params[:order]
-    when 'author'
-      { author: {order: :asc, unmapped_type: :string} }
-    when 'publicationasc'
-      { published_at: {order: :asc, unmapped_type: :timestamp} }
-    when 'publicationdesc'
-      { published_at: {order: :desc, unmapped_type: :timestamp} }
-    when 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def col_order_hash(params)
-    case params[:order]
-    when 'author'
-      { owner: {order: :asc, unmapped_type: :string} }
-    when 'publicationasc'
-      { created_at: {order: :asc, unmapped_type: :timestamp} }
-    when 'publicationdesc'
-      { created_at: {order: :desc, unmapped_type: :timestamp} }
-    when 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def user_order_hash(params)
-    if params[:order] == 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-
-  private
-
-  def validate_object
-    return 'published' if current_user.nil? || !current_user.is_admin?
-    return ['published', 'suspended', 'draft']
-  end
-
-end
diff --git a/app/controllers/old/users_controller.rb b/app/controllers/old/users_controller.rb
deleted file mode 100644
index b4f75c7d0bcc31ab5e0827cfe74cd06072b5250d..0000000000000000000000000000000000000000
--- a/app/controllers/old/users_controller.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-class UsersController < ApplicationController
-
-  include Pundit
-
-  before_action :authenticate_user!, only: [:follow, :unfollow]
-  before_action :check_current_user_page, only: :show
-  before_action :set_user, only: [:show]
-  before_action :set_institutions, only: :me
-  before_action :set_empty_collection, only: [:show, :me]
-  before_action :set_followable, only: [:follow, :unfollow]
-
-  def show
-    @objects = @user.learning_objects
-    @institutions = @user.institutions
-    @groups = [CollectionsGroup.new(title: 'Coleções Adicionadas', collections: [ CollectionPolicy::Scope.new(current_user, @user.id, @user.collections).resolve.includes(:owner)])]
-
-    if @user == current_user
-      @publishers = @user.institutions
-      @bookmarks = (@user.bookmarks.nil? || @user.bookmarks.first.nil?) ? [] : [@user.bookmarks.first]
-      @groups.unshift(CollectionsGroup.new(title: 'Coleções Automáticas', collections: @bookmarks))
-    end
-  end
-
-  def list
-    @users = User.all
-  end
-
-  def follow
-    Follow.create(user: current_user, followable: @followable) unless @followable.nil?
-
-    redirect_to user_path(@followable)
-  end
-
-  def unfollow
-    Follow.where(user: current_user, followable: @followable).destroy_all unless @followable.nil?
-
-    redirect_to user_path(@followable)
-  end
-
-  def verify_email
-    exists = User.find_by_email(params[:email])
-    render json: { valid: exists.nil? && !params[:email].match(Devise.email_regexp).nil? }
-  end
-
-  private
-
-  def set_empty_collection
-    @new_collection = Collection.new
-  end
-
-  def set_institutions
-    @institutions = current_user.institutions
-  end
-
-  def set_user
-    @user = User.find params[:id]
-  end
-
-  def set_followable
-    @followable = params[:followable_type].constantize.find(params[:followable_id]) if %w(Collection User).include? params[:followable_type]
-  end
-
-  def check_current_user_page
-    if user_signed_in?
-      if current_user.id == params[:id]
-        redirect_to action: :me
-      end
-    end
-  end
-
-  def publishers_for(user)
-    publishers = []
-    user_publisher = user
-    user_publisher.id = user.rid
-
-    publishers << user_publisher
-    publishers + user.institutions
-  end
-
-end
diff --git a/app/controllers/old/welcome_controller.rb b/app/controllers/old/welcome_controller.rb
deleted file mode 100644
index 9b7681179d235026580b07df755e55af4fcb68d8..0000000000000000000000000000000000000000
--- a/app/controllers/old/welcome_controller.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-class WelcomeController < ApplicationController
-  include Pundit
-
-  def index
-    @carousel = Carousel.all || []
-    @highlights = policy_scope(LearningObject).limit(8).includes(:publisher, :language, :topics)
-  end
-
-  def faq
-  end
-
-  def contact
-  end
-
-  def terms_of_service
-  end
-
-end
diff --git a/app/controllers/v1/activities_controller.rb b/app/controllers/v1/activities_controller.rb
index 8edf1d8aa7ea4ac3246158a4b3a4147d377899b8..3de2c8634d1eb13849a314c25e2b5eb7de823377 100644
--- a/app/controllers/v1/activities_controller.rb
+++ b/app/controllers/v1/activities_controller.rb
@@ -1,17 +1,22 @@
 class V1::ActivitiesController < ApplicationController
-  before_action :authenticate_user!, only: [:my_activities]
+  include ::ResourceModel
+  before_action :authenticate_user!
 
   # GET v1/activities
   # GET v1/activities.json
+  # Render all activities that logged user can see
   def index
-    render json: PublicActivity::Activity.includes(:owner).order("created_at DESC").all
+    authorize :activity, :index?
+    render json: ActivitiyPolicy::Scope.new(current_user, PublicActivity::Activity).resolve
   end
 
-  # GET v1/activities/my_activities
-  # GET v1/activities/my_activities.json
-  def my_activities
-    activities = PublicActivity::Activity.order("created_at DESC").where(owner_type: "User", owner_id: current_user).all
-    render json: activities
+  # GET v1/users/1/activities
+  # GET v1/users/1/activities.json
+  # Render specific user activities
+  # Only followers can see user activities
+  def user_activities
+    raise Pundit::NotAuthorizedError unless ActivitiyPolicy.new(current_user, resource_model).user_activities?
+    render json: resource_model.activities
   end
 
 end
diff --git a/app/controllers/v1/collections_controller.rb b/app/controllers/v1/collections_controller.rb
index 7ef5414ed980d4e007a4b836abbae5eeecd3e9a5..2deb8b8d2adfa62f66afa2d048d188874fe38124 100644
--- a/app/controllers/v1/collections_controller.rb
+++ b/app/controllers/v1/collections_controller.rb
@@ -2,6 +2,8 @@ class V1::CollectionsController < ApplicationController
   include ::SociableController
   include ::FollowableController
   include ::TaggableController
+  include ::DeletedObjectsController
+  include ::HighlightsController
 
   before_action :set_collection, only: [:show, :update, :destroy]
   before_action :authenticate_user!, only: [:create, :update, :destroy]
@@ -9,7 +11,9 @@ class V1::CollectionsController < ApplicationController
   # GET /v1/collections
   # GET /v1/collections.json
   def index
-    render json: Collection.all
+    limit = params[:limit] || 10
+    offset = params[:offset] || 0
+    render json: Collection.limit(limit).offset(offset)
   end
 
   # GET /v1/collections/1
@@ -49,18 +53,13 @@ class V1::CollectionsController < ApplicationController
 
   private
 
-  # social concerns methods
-  def followable
-    set_collection
-  end
-
-  def taggable
-    set_collection
-  end
+  def deleted_resource; Collection; end
+  def highlights_resource; Collection; end
 
-  def sociable
-    set_collection
-  end
+  # social concerns methods
+  def followable; set_collection; end
+  def taggable; set_collection; end
+  def sociable; set_collection; end
 
   def set_collection
     @collection ||= Collection.find(params[:id])
diff --git a/app/controllers/v1/complaints_controller.rb b/app/controllers/v1/complaints_controller.rb
index f8c68a2811c9b167d8680b376c73669819e223a6..b54b8b2f587e53a5c1f59de4e21e6f88ad82752a 100644
--- a/app/controllers/v1/complaints_controller.rb
+++ b/app/controllers/v1/complaints_controller.rb
@@ -1,4 +1,6 @@
 class V1::ComplaintsController < ApplicationController
+  include ::DeletedObjectsController
+
   before_action :authenticate_user!, only: [:create]
 
   # GET v1/complaint
@@ -21,6 +23,10 @@ class V1::ComplaintsController < ApplicationController
 
   private
 
+  def deleted_resource
+    Complaint
+  end
+
   def complaint_params
     params.require(:complaint).permit(:user_id, :description,:complaintable_id, :complaint_reason_id, :complaintable_type)
   end
diff --git a/app/controllers/v1/institutions_controller.rb b/app/controllers/v1/institutions_controller.rb
index 56021ea278777c2844e19a87e314d49fc253277c..bdc27523965dc29bec8b4e71ee6a67aa6d32218a 100644
--- a/app/controllers/v1/institutions_controller.rb
+++ b/app/controllers/v1/institutions_controller.rb
@@ -1,4 +1,5 @@
 class V1::InstitutionsController < ApplicationController
+  include ::DeletedObjectsController
 
   before_action :set_institution, only: [:show, :update, :destroy, :users]
   before_action :authenticate_user!, only: [:create, :update, :destroy]
@@ -51,6 +52,10 @@ class V1::InstitutionsController < ApplicationController
 
   private
 
+  def deleted_resource
+    Institution
+  end
+
   def set_institution
     @institution = Institution.find(params[:id])
   end
diff --git a/app/controllers/v1/learning_objects_controller.rb b/app/controllers/v1/learning_objects_controller.rb
index ff124dc4c4a707fd52bd3876dbe0ca442732c81a..19588ceb19cb620fb43dda41fddd0f3f389478f2 100644
--- a/app/controllers/v1/learning_objects_controller.rb
+++ b/app/controllers/v1/learning_objects_controller.rb
@@ -4,19 +4,24 @@ class V1::LearningObjectsController < ApplicationController
   include ::SociableController
   include ::TaggableController
   include ::Paginator
+  include ::DeletedObjectsController
+  include ::HighlightsController
 
   before_action :authenticate_user!, except: [:index, :show]
   before_action :set_learning_object, only: [:show, :update, :destroy]
   before_action :authorize!, only: [:show, :update, :destroy]
 
   def index
-    render json: ActiveModel::ArraySerializer.new(LearningObject.limit(limit).offset(offset).all)
+    limit = params[:limit] || 10
+    offset = params[:offset] || 0
+    serializer = params[:obaa].nil? ? LearningObjectSerializer : LearningObjectObaaSerializer
+    render json: LearningObject.includes(:tags, :publisher, :language, :license).limit(limit).offset(offset), each_serializer: serializer
   end
 
   # GET /learning_objects/1
   # GET /learning_objects/1.json
   def show
-    render json: @learning_object
+    render json: params[:obaa].nil? ? @learning_object : LearningObjectObaaSerializer.new(@learning_object)
   end
 
   # POST /learning_objects
@@ -51,13 +56,10 @@ class V1::LearningObjectsController < ApplicationController
 
   private
 
-  def sociable
-    set_learning_object
-  end
-
-  def taggable
-    set_learning_object
-  end
+  def deleted_resource; LearningObject; end
+  def highlights_resource; LearningObject; end
+  def sociable; set_learning_object; end
+  def taggable; set_learning_object; end
 
   # Use callbacks to share common setup or constraints between actions.
   def set_learning_object
diff --git a/app/controllers/v1/licenses_controller.rb b/app/controllers/v1/licenses_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a9bd87aa97cea7b4f0ae950fab257b702f35db7c
--- /dev/null
+++ b/app/controllers/v1/licenses_controller.rb
@@ -0,0 +1,58 @@
+class V1::LicensesController < ApplicationController
+  before_action :authenticate_user!, only: [:create, :update, :destroy]
+  before_action :set_license, only: [:show, :update, :destroy]
+
+  # GET /licenses
+  # GET /licenses.json
+  def index
+    render json: License.all, each_serializer: LicenseSerializer
+  end
+
+  # GET /licenses/1
+  # GET /licenses/1.json
+  def show
+    render json: @license
+  end
+
+  # POST /licenses
+  # POST /licenses.json
+  def create
+    @license = License.new(license_params)
+
+    if @license.save
+      render json: @license, status: :created
+    else
+      render json: @license.errors, status: :unprocessable_entity
+    end
+  end
+
+  # PATCH/PUT /licenses/1
+  # PATCH/PUT /licenses/1.json
+  def update
+    @license = License.find(params[:id])
+
+    if @license.update(license_params)
+      head :no_content
+    else
+      render json: @license.errors, status: :unprocessable_entity
+    end
+  end
+
+  # DELETE /licenses/1
+  # DELETE /licenses/1.json
+  def destroy
+    @license.destroy
+
+    head :no_content
+  end
+
+  private
+
+  def set_license
+    @license = License.find(params[:id])
+  end
+
+  def license_params
+    params.require(:license).permit(:name, :description, :url, :image_url)
+  end
+end
diff --git a/app/controllers/v1/reviews_controller.rb b/app/controllers/v1/reviews_controller.rb
index 0eb054edebb38ace3fcbf954f52676b706eb35d3..0a83f1248d07ab75ed8968f94b6aa558852fe76e 100644
--- a/app/controllers/v1/reviews_controller.rb
+++ b/app/controllers/v1/reviews_controller.rb
@@ -1,12 +1,13 @@
 class V1::ReviewsController < ApplicationController
+  include ::DeletedObjectsController
+  include ::ResourceModel
+
   before_action :set_review, only: [:show, :destroy, :rate]
   before_action :authenticate_user!, only: [:create, :rate, :destroy]
 
   # GET /v1/collections/1/reviews
   def index
-    render json: ActiveModel::ArraySerializer.new(
-      reviewable.reviews,
-      each_serializer: ReviewSerializer)
+    render json: reviewable.reviews, each_serializer: ReviewSerializer
   end
 
   # GET /v1/collections/1/reviews/1
@@ -72,10 +73,12 @@ class V1::ReviewsController < ApplicationController
 
   private
 
+  def deleted_resource
+    Review
+  end
+
   def reviewable
-    resource, id = request.path.split('/')[2, 3]
-    reviewable_model = resource.singularize.classify.constantize
-    @reviewable = reviewable_model.find(id)
+    @reviewable = resource_model
   end
 
   # Never trust parameters from the scary internet, only allow the white list through.
diff --git a/app/controllers/v1/search_controller.rb b/app/controllers/v1/search_controller.rb
index 2a1aabec64446e46cff50a1ce33c079d53976372..98563378a3b2b1cd254a72e6c27ad1d36ed66c1c 100644
--- a/app/controllers/v1/search_controller.rb
+++ b/app/controllers/v1/search_controller.rb
@@ -1,47 +1,30 @@
 class V1::SearchController < ApplicationController
-
   before_action :set_search
 
   # GET v1/search
   # GET v1/search.json
   def index
-    begin
-      render json: ActiveModel::ArraySerializer.new(search_service.fetch), status: :ok
-    rescue => e
-      if e.message == "Invalid search"
-        render json: @search.errors, status: :bad_request
-      else
-        render nothing: true, status: :internal_server_error
-        puts e.message
-        puts e.backtrace
-      end
-    end
+    render json: SearchService.search(@search, current_user), status: :ok
+  rescue SearchService::InvalidSearchError
+    render json: @search.errors, status: :bad_request
   end
 
   # GET v1/search/autocomplete
   # GET v1/search/autocomplete.json
   def autocomplete
-    begin
-      render json: ActiveModel::ArraySerializer.new(search_service.autocomplete), status: :ok
-    rescue => e
-      if e.message == "Invalid search"
-        render json: @search.errors, status: :bad_request
-      else
-        render nothing: true, status: :internal_server_error
-        puts e.message
-        puts e.backtrace
-      end
-    end
+    render json: SearchService.autocomplete(@search, current_user), status: :ok
+  rescue SearchService::InvalidSearchError
+    render json: @search.errors, status: :bad_request
   end
 
   private
 
   def set_search
-    @search = Search.new(params)
+    @search = Search.new(search_params)
   end
 
-  def search_service
-    @search_service ||= SearchService.new(@search, current_user)
+  # Never trust parameters from the scary internet, only allow the white list through.
+  def search_params
+    params.permit(:page, :results_per_page, :order, :query, :search_class)
   end
-
-end
\ No newline at end of file
+end
diff --git a/app/controllers/v1/users_controller.rb b/app/controllers/v1/users_controller.rb
index 67eccc9d00fead4293d00662eeec264346162176..d24e649cb34111b2afca7e2030268af7df9992f0 100644
--- a/app/controllers/v1/users_controller.rb
+++ b/app/controllers/v1/users_controller.rb
@@ -1,8 +1,9 @@
 class V1::UsersController < ApplicationController
   include ::FollowableController
+  include ::DeletedObjectsController
 
-  before_action :set_user, only: [:show, :update, :destroy]
-  before_action :authenticate_user!, only: [:create, :update, :destroy]
+  before_action :set_user, only: [:show, :update, :destroy, :watching]
+  before_action :authenticate_user!, only: [:create, :update, :destroy, :watching]
 
   # GET /v1/users
   # GET /v1/users.json
@@ -50,8 +51,20 @@ class V1::UsersController < ApplicationController
     end
   end
 
+  def watching
+    type = params[:object_type]
+    is_current = (@user.id == current_user.id) unless current_user.nil?
+    return render nothing: true, status: :bad_request unless type.in? %w(User Collection)
+    w = @user.watching(type, is_current)
+    render json: w, root: 'follows', status: :ok
+  end
+
   private
 
+  def deleted_resource
+    User
+  end
+
   def followable
     set_user
   end
@@ -64,5 +77,4 @@ class V1::UsersController < ApplicationController
   def user_params
     params.require(:user).permit(:name, :email, :password, :password_confirmation, :terms_of_service, role_ids: [])
   end
-
 end
diff --git a/app/controllers/v1/versions_controller.rb b/app/controllers/v1/versions_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b6861247329657849a5c7dea82914983daab1ff8
--- /dev/null
+++ b/app/controllers/v1/versions_controller.rb
@@ -0,0 +1,27 @@
+class V1::VersionsController < ApplicationController
+  include ::ResourceModel
+
+  # GET v1/learning_objects/1/versions
+  # GET v1/learning_objects/1/versions.json
+  def index
+    render json: resource_model.versions
+  end
+
+  # GET v1/learning_objects/1/versions/123
+  # GET v1/learning_objects/1/versions/123.json
+  def show
+    resource = PaperTrail::Version.find(params[:id])
+    render json: resource
+  end
+
+  # POST /learning_objects/1/versions/234/checkout
+  def checkout
+    resource = PaperTrail::Version.find(params[:id]).reify
+    if resource.save
+      render json: resource
+    else
+      render nothing: true, status: :unprocessable_entity
+    end
+  end
+
+end
diff --git a/app/models/application.rb b/app/models/application.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1485a35a47669e2229a076f027dac3eef4ee6959
--- /dev/null
+++ b/app/models/application.rb
@@ -0,0 +1,14 @@
+class Application < ActiveRecord::Base
+  belongs_to :user
+
+  validates :domain, presence: true, uniqueness: true
+  validates :application_id, presence: true, uniqueness: true
+  before_create :generate_application_id
+
+  private
+
+  def generate_application_id
+    @application_id = SecureRandom.uuid.to_s
+    generate_application_id if self.class.find_by_application_id(@application_id)
+  end
+end
diff --git a/app/models/bookmark.rb b/app/models/bookmark.rb
index 99344a15ef3e0c5828a57232ec360d74fa30c775..d49ca0269e01b952814ce0c8de0df78dbac95c4a 100644
--- a/app/models/bookmark.rb
+++ b/app/models/bookmark.rb
@@ -11,6 +11,8 @@
 #
 
 class Bookmark < ActiveRecord::Base
+  # Example of Trackable:
+  # *current_user* create bookmark *bookmarkable*
   include Trackable
 
   belongs_to :user, counter_cache: true
diff --git a/app/models/collection.rb b/app/models/collection.rb
index 0121b15d79c47c2726a02b73d70a2c7602ef7150..ae5893b540b25d6c94757bf55d2290c92ff0f126 100644
--- a/app/models/collection.rb
+++ b/app/models/collection.rb
@@ -30,6 +30,7 @@ class Collection < ActiveRecord::Base
   include Thumbnailable
   include Taggable
   include Trackable
+  include Highlights
 
   has_many :collection_items, as: :collectionable, dependent: :destroy
   has_many :collections, through: :collection_items, source: :collectionable, source_type: 'Collection'
@@ -45,6 +46,9 @@ class Collection < ActiveRecord::Base
 
   searchkick language: 'brazilian', match: :word_start, searchable: [:name, :description, :author], callbacks: :async
 
+  acts_as_paranoid
+  has_paper_trail
+
   def search_data
     {
         name: name,
diff --git a/app/models/collection_item.rb b/app/models/collection_item.rb
index aa4659532dd1ae8cf63b4b06148565f088bfebf5..02eedcbe136a7ebce9f84bec02936ab12979d384 100644
--- a/app/models/collection_item.rb
+++ b/app/models/collection_item.rb
@@ -12,8 +12,10 @@
 #
 
 class CollectionItem < ActiveRecord::Base
-  belongs_to :collection
+  # *current_user* add item *collectionable* to *collection*
+  include Trackable
 
+  belongs_to :collection
   belongs_to :collectionable, polymorphic: true
 
   validates_presence_of :collection, :collectionable
diff --git a/app/models/complaint.rb b/app/models/complaint.rb
index a965eac3b87e8c5f86294a802cd8f99ffebd39ab..abe53017eedeb87cb3bbdcbf2539d3c4dc441727 100644
--- a/app/models/complaint.rb
+++ b/app/models/complaint.rb
@@ -13,6 +13,7 @@
 #
 
 class Complaint < ActiveRecord::Base
+  # *current_user* create complaint about *complaint_reason* for *complaintable*
   include Trackable
 
   belongs_to :complaint_reason
@@ -22,6 +23,9 @@ class Complaint < ActiveRecord::Base
   validates_presence_of :user, :complaintable, :description, :complaint_reason
   validates :user_id, uniqueness: { scope: [:complaintable_id, :complaintable_type] }
 
+  acts_as_paranoid
+  has_paper_trail
+
   def reason
     complaint_reason.reason
   end
diff --git a/app/models/complaint_reason.rb b/app/models/complaint_reason.rb
index 26ee8777f0c3631591f4d29ba5a7b34da7cd51e4..468f59d301d629ba342ff9b1678b7717b2a6549b 100644
--- a/app/models/complaint_reason.rb
+++ b/app/models/complaint_reason.rb
@@ -9,8 +9,12 @@
 #
 
 class ComplaintReason < ActiveRecord::Base
+  # *current_user* create complaint reason
+  # Only admins can create complaint reasons
+  include Trackable
+
   has_many :complaints
 
   validates_presence_of :reason
-
+  has_paper_trail
 end
diff --git a/app/models/concerns/highlights.rb b/app/models/concerns/highlights.rb
new file mode 100644
index 0000000000000000000000000000000000000000..62a3d5480644ae26a88a5289f44140e583a80930
--- /dev/null
+++ b/app/models/concerns/highlights.rb
@@ -0,0 +1,9 @@
+module Highlights
+  extend ActiveSupport::Concern
+
+  included do
+    scope :this_week, -> (limit = 1000) { where('created_at >= ?', 1.week.ago).order(score: :desc).limit(limit) }
+    scope :this_month, -> (limit = 1000) { where('created_at >= ?', 1.month.ago).order(score: :desc).limit(limit) }
+  end
+
+end
\ No newline at end of file
diff --git a/app/models/concerns/metadatable.rb b/app/models/concerns/metadatable.rb
index 07bd3ac398f424e522a0c2ab3a0f9b7b1a1b17a3..28ba9409496a851fb81de6a3edc39b1b77c60ecf 100644
--- a/app/models/concerns/metadatable.rb
+++ b/app/models/concerns/metadatable.rb
@@ -7,19 +7,11 @@ module Metadatable
     serialize :metadata, ArraySerializer
   end
 
-  def get_metadata_value_of key
+  def get_metadata_value_of(key)
     get_metadata_values_of(key).first
   end
 
-  def get_metadata_values_of key
-    values = []
-    unless metadata.blank?
-      metadata.each do |m|
-        m = m.with_indifferent_access
-        values << m["value"] if m["key"] == key
-      end
-    end
-    values
+  def get_metadata_values_of(key)
+    metadata[key].blank? ? [] : metadata[key]
   end
-
 end
diff --git a/app/models/concerns/reputationable.rb b/app/models/concerns/reputationable.rb
index 59f8a4da614b28dad688ca6336de23b421cb8129..13697eb0598d3d444a80c563fbda111c29bb1412 100644
--- a/app/models/concerns/reputationable.rb
+++ b/app/models/concerns/reputationable.rb
@@ -1,6 +1,10 @@
 module Reputationable
   extend ActiveSupport::Concern
 
+  included do
+    delegate :count, to: :followers, prefix: true
+  end
+
   def submitted_objects
     learning_objects.count
   end
@@ -8,7 +12,7 @@ module Reputationable
   def reviews_score_average
     scores = learning_objects.map(&:review_ratings_average)
 
-    return 0.0 if scores.size == 0
+    return 0.0 if scores.empty?
 
     scores.inject(0.0) { |a, e| a + e }.to_f / scores.size.to_f
   end
@@ -35,14 +39,10 @@ module Reputationable
     array.inject(0.0) { |a, e| a + e } / array.size
   end
 
-  def followers_count
-    followers.count
-  end
-
   def learning_objects_recently_submitted
     return 0.0 if learning_objects.nil?
 
-    learning_objects.where('created_at >= ?', (Time.now - 2.months)).count
+    learning_objects.where('created_at >= ?', (Time.current - 2.months)).count
   end
 
   def collections_score_average
diff --git a/app/models/concerns/stateful.rb b/app/models/concerns/stateful.rb
index 5ea87856d68674a4b660a9e58f1d2fa225f5f875..7ca2f074779ec9894ee4f4b2166a637ff92daf41 100644
--- a/app/models/concerns/stateful.rb
+++ b/app/models/concerns/stateful.rb
@@ -2,32 +2,6 @@ module Stateful
   extend ActiveSupport::Concern
 
   included do
-    # validates with accepted states
-    validates :state, inclusion: { in: %w(draft published suspended) }
+    enum state: { draft: 0, published: 1, suspended: 2 }
   end
-
-  def is_published?
-    'published' == state
-  end
-
-  def is_draft?
-    'draft' == state
-  end
-
-  def publish
-    self.state = 'published'
-  end
-
-  def draft
-    self.state = 'draft'
-  end
-
-  def suspend
-    self.state = 'suspended'
-  end
-
-  def is_suspended?
-    'suspended' == state
-  end
-
 end
diff --git a/app/models/concerns/taggable.rb b/app/models/concerns/taggable.rb
index aedd68087056700b9847f28715fedbb422146d50..bf62302ea155c014411a4d7467e819e39b6b12fa 100644
--- a/app/models/concerns/taggable.rb
+++ b/app/models/concerns/taggable.rb
@@ -5,6 +5,4 @@ module Taggable
     has_many :taggings, as: :taggable, dependent: :destroy
     has_many :tags, through: :taggings, dependent: :destroy
   end
-
-
 end
diff --git a/app/models/concerns/thumbnailable.rb b/app/models/concerns/thumbnailable.rb
index e22d871bfba9593fbd6f1790d20410631cef7d0c..123ffb7de4f048ba8e712fe8e04d1e6f39899613 100644
--- a/app/models/concerns/thumbnailable.rb
+++ b/app/models/concerns/thumbnailable.rb
@@ -2,7 +2,7 @@ module Thumbnailable
   extend ActiveSupport::Concern
 
   included do
-    has_attached_file :thumbnail, styles: { medium: '530x300', small: '250x140' }, default_url: 'learning-object-preview.png'
+    has_attached_file :thumbnail, styles: { medium: '530x300', small: '250x140' }, default_url: ''
     validates_attachment_content_type :thumbnail, content_type: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
   end
 
diff --git a/app/models/concerns/trackable.rb b/app/models/concerns/trackable.rb
index 7d8455f3f63d0ffe1022b6a7338f0fcb3acc5f30..c0b2c747e084b47917e7cdbe140ad5829f25f807 100644
--- a/app/models/concerns/trackable.rb
+++ b/app/models/concerns/trackable.rb
@@ -3,7 +3,7 @@ module Trackable
   include PublicActivity::Model
 
   included do
-    tracked owner: Proc.new{ |controller, model| controller.current_user }
+    tracked owner: proc { |controller, model|
+      model.try(:user) || model.try(:owner) || controller.try(:current_user) }
   end
-
 end
diff --git a/app/models/download.rb b/app/models/download.rb
index 53c6d05f0d54809affe850328880a5c76e73471f..3435d9bcf3182bf23530c60549dbd0e8c29cbaa7 100644
--- a/app/models/download.rb
+++ b/app/models/download.rb
@@ -11,6 +11,7 @@
 #
 
 class Download < ActiveRecord::Base
+  # *current_user* download *downloadable*
   include Trackable
 
   belongs_to :downloadable, polymorphic: true, counter_cache: true
diff --git a/app/models/follow.rb b/app/models/follow.rb
index 464d4508b2d9dba87b322150c12a46cd313eba93..7c32adc1ba5ba1a449d0e355de90b901e356613e 100644
--- a/app/models/follow.rb
+++ b/app/models/follow.rb
@@ -11,6 +11,7 @@
 #
 
 class Follow < ActiveRecord::Base
+  # *current_user* follows *followable*
   include Trackable
 
   belongs_to :followable, polymorphic: true, counter_cache: true
diff --git a/app/models/institution.rb b/app/models/institution.rb
index f0e06793bdbb6995a1a79b301ce8cbd9b6879736..5c380822a1db59c0c7f5603403b1581425ceef45 100644
--- a/app/models/institution.rb
+++ b/app/models/institution.rb
@@ -14,12 +14,19 @@
 
 class Institution < ActiveRecord::Base
   include Tagger
+
+  # *current_user* add member for instituion *name*
+  # *current_user* create instituion
+  # *current_user* destroy instituion
+  # *current_user* update instituion
   include Trackable
 
   has_and_belongs_to_many :users
-
   has_many :learning_objects, as: :publisher
   has_many :collections, as: :owner
 
   validates_presence_of :name
+
+  acts_as_paranoid
+  has_paper_trail
 end
diff --git a/app/models/learning_object.rb b/app/models/learning_object.rb
index 63f5dc60e7989235c95b89a56f4be1c76e0244b6..985dd42465d49e8ac33373d92cb465ffe1d844c9 100644
--- a/app/models/learning_object.rb
+++ b/app/models/learning_object.rb
@@ -1,4 +1,4 @@
-# == Schema Information
+ # == Schema Information
 #
 # Table name: learning_objects
 #
@@ -38,6 +38,11 @@ class LearningObject < ActiveRecord::Base
   include Scoreable
   include Thumbnailable
   include Taggable
+  include Highlights
+
+  # *current_user* create learning object
+  # *current_user* update learning object
+  # *current_user* destroy learning object
   include Trackable
 
   has_many :collection_items, as: :collectionable
@@ -47,17 +52,20 @@ class LearningObject < ActiveRecord::Base
 
   belongs_to :publisher, polymorphic: true
   belongs_to :language
+  belongs_to :license
   belongs_to :object_type
   belongs_to :attachment, class_name: 'LearningObject::Attachment'
 
   validates_presence_of :name, :publisher, :object_type, :language, :author
-  validates :id_dspace, presence: true, uniqueness: true, unless: :is_draft?
+  validates :id_dspace, presence: true, uniqueness: true, unless: :draft?
 
   default_scope { includes(:object_type, :attachment, :attachments).order(score: :desc) }
   scope :missing_thumbnail, ->() { where(thumbnail_file_name: nil) }
 
   searchkick language: 'brazilian', match: :word_start, searchable: [:name, :description, :author, :object_type], callbacks: :async
 
+  acts_as_paranoid
+
   def search_data
     source = (!publisher.nil? && publisher.is_a?(Institution)) ? publisher.name : nil
     type = object_type.try(:name)
@@ -129,4 +137,5 @@ class LearningObject < ActiveRecord::Base
   def user_category
     publisher.try('user_category')
   end
+
 end
diff --git a/app/models/license.rb b/app/models/license.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5bc15243c08c0d622808a74920fa68bba4ca0776
--- /dev/null
+++ b/app/models/license.rb
@@ -0,0 +1,3 @@
+class License < ActiveRecord::Base
+  validates :name, presence: true
+end
diff --git a/app/models/like.rb b/app/models/like.rb
index 58d242d5184f386d7b7388939e37cc1329fff159..d9e98d20d3b90bf2faff5c0a566ada4d20a90684 100644
--- a/app/models/like.rb
+++ b/app/models/like.rb
@@ -11,6 +11,8 @@
 #
 
 class Like < ActiveRecord::Base
+  # *current_user* likes *likeable*
+  # *current_user* unlikes *likeable*
   include Trackable
 
   belongs_to :likeable, polymorphic: true, counter_cache: true
diff --git a/app/models/rate.rb b/app/models/rate.rb
index f18629a957419fb1588a65e500be8c8f228d2cad..5b7a27e6372608dd1d3124d3f8e5adf989fe04c8 100644
--- a/app/models/rate.rb
+++ b/app/models/rate.rb
@@ -9,6 +9,7 @@
 #  created_at :datetime         not null
 #  updated_at :datetime         not null
 class Rate < ActiveRecord::Base
+  # *current_user* rate a review *review*
   include Trackable
 
   belongs_to :user
diff --git a/app/models/review.rb b/app/models/review.rb
index fd840a94b87e990647bc5ff014f546fe282c824e..cb8cdb03aa96a1b7f9cab31041cf63cdcce4ba53 100644
--- a/app/models/review.rb
+++ b/app/models/review.rb
@@ -16,6 +16,7 @@
 #
 
 class Review < ActiveRecord::Base
+  # *current_user* review *reviewable*
   include Trackable
 
   belongs_to :reviewable, polymorphic: true
@@ -34,6 +35,9 @@ class Review < ActiveRecord::Base
 
   default_scope { includes(:user) }
 
+  acts_as_paranoid
+  has_paper_trail
+
   def rating_values
     review_ratings.includes(:rating).map { |r| {rating: r.rating, value: r.value} }
   end
diff --git a/app/models/score.rb b/app/models/score.rb
index d4d2ab4bb58baed039a1ffda4fa5791ba9dd4a74..d7e98121091fa868e3ce6b0fb9b39441dc63bb48 100644
--- a/app/models/score.rb
+++ b/app/models/score.rb
@@ -21,6 +21,7 @@ class Score < ActiveRecord::Base
   validates_numericality_of :weight
 
   scope :object_type, ->(name) { where('? = ANY (score_type)', name) }
+  has_paper_trail
 
   def max_value
     score_user_categories.maximum(:value)
diff --git a/app/models/search.rb b/app/models/search.rb
index f0e0f1bf38e30933398e3112cfa4ea380619ada3..4f99e8fe47dd2abbb70513f4b1a1100026a3ffe6 100644
--- a/app/models/search.rb
+++ b/app/models/search.rb
@@ -1,26 +1,25 @@
 class Search
   include ActiveModel::Model
-
   attr_accessor :page, :results_per_page, :order, :query, :search_class, :tags, :types, :sources
 
   validates_presence_of :query, :results_per_page, :order, :search_class
   validates_numericality_of :results_per_page, greater_than: 0
-  validates :search_class, inclusion: {in: %w(LearningObject Collection User)}
+  validates :search_class, inclusion: { in: ::SearchService::SEARCH_CLASSES }
 
-  def initialize(params={})
-    super(defaults.merge(params.select { |key,value| self.respond_to? key }))
+  def initialize(params = {})
+    super(defaults.merge(params.select { |key, _value| respond_to? key }))
   end
 
   def learning_object?
-    @search_class == "LearningObject"
+    search_class == 'LearningObject'
   end
 
   def collection?
-    @search_class == "Collection"
+    search_class == 'Collection'
   end
 
   def user?
-    @search_class == "User"
+    search_class == 'User'
   end
 
   private
@@ -33,5 +32,4 @@ class Search
       results_per_page: 10
     }
   end
-
-end
\ No newline at end of file
+end
diff --git a/app/models/share.rb b/app/models/share.rb
index 7be91509ed1d5a6536775753d0859484b23fe887..4816f94a60291f7f2d42166a8ce70c8bd0a08221 100644
--- a/app/models/share.rb
+++ b/app/models/share.rb
@@ -11,6 +11,7 @@
 #
 
 class Share < ActiveRecord::Base
+  # *current_user* shares *shareable*
   include Trackable
 
   belongs_to :shareable, polymorphic: true, counter_cache: true
diff --git a/app/models/tagging.rb b/app/models/tagging.rb
index ed698885ac0e5353a4039b1211cc8ac367dcb0e6..d926c6db5500dfe223cf7643c3b13915166c0d25 100644
--- a/app/models/tagging.rb
+++ b/app/models/tagging.rb
@@ -1,4 +1,5 @@
 class Tagging < ActiveRecord::Base
+  # *current_user* tag *taggable* with *tag*
   include Trackable
 
   belongs_to :tagger, polymorphic: true
diff --git a/app/models/user.rb b/app/models/user.rb
index 0f03e7aeafbc903c6d15c625ade7ee184def7b5f..ecfd182636edbbb67ccb4da6b24f65aa3a6e85f7 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -53,18 +53,15 @@ class User < ActiveRecord::Base
   has_many :bookmark_collections, through: :bookmarks, source: :bookmarkable, source_type: 'Collection'
   has_many :bookmark_learning_objects, through: :bookmarks, source: :bookmarkable, source_type: 'LearningObject'
   has_many :bookmarks
-
   has_many :collections, as: :owner
-
   has_many :learning_objects, as: :publisher
-
   has_many :views
   has_many :downloads
   has_many :likes
   has_many :shares
   has_many :follows
-
   has_many :reviews
+  has_many :applications
 
   after_create :default_role
 
@@ -74,6 +71,9 @@ class User < ActiveRecord::Base
 
   searchkick language: 'brazilian', match: :word_start, searchable: [:name], callbacks: :async
 
+  acts_as_paranoid
+  has_paper_trail
+
   def search_data
     {
         name: name,
@@ -117,8 +117,34 @@ class User < ActiveRecord::Base
     !follows.where(followable_id: followable.id, followable_type: followable.class.name).blank?
   end
 
+  # This function permits see what person is following.
+  # For current user, list all users and all collections. But,
+  # if, isn't current user, list only users, and public collections which this person follows.
+  def watching(followable_type, is_current_user = true)
+    f = Follow.where(user_id: id, followable_type: followable_type).all
+
+    # If type collection, and isn't current_user, so should list only public collections
+    if followable_type.to_s == 'Collection' && !is_current_user
+      f = Follow.joins('INNER JOIN collections ON follows.followable_id = collections.id').where(
+        "follows.user_id = #{id} " \
+        'AND follows.followable_type = \'Collection\' ' \
+        'AND collections.id = follows.followable_id ' \
+        'AND collections.privacy = \'public\''
+      )
+    end
+
+    f
+  end
+
   # ~~~~ end followable actions ~~~~ #
 
+  ## get all activities from user
+  # return an array of PublicActivity::Activity
+  def activities
+    condition = '(owner_type = :type AND owner_id = :id) OR (recipient_type = :type AND recipient_id = :id)'
+    PublicActivity::Activity.order('created_at DESC').where(condition, {type: object.class.to_s, id: object.id}).all
+  end
+
   private
 
   def default_role
diff --git a/app/models/view.rb b/app/models/view.rb
index 72579609f1fc97f0a61283772ed71c0789c9ee46..94f27f19e255fa086dc2f5ade9e92f851e2d7ec2 100644
--- a/app/models/view.rb
+++ b/app/models/view.rb
@@ -11,6 +11,9 @@
 #
 
 class View < ActiveRecord::Base
+  # *current_user* views *viewable*
+  include Trackable
+
   belongs_to :viewable, polymorphic: true, counter_cache: true
   belongs_to :user
 
diff --git a/app/policies/activity_policy.rb b/app/policies/activity_policy.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4a047168e4dbf5763ad93eaa763cc9f06d7e4d0c
--- /dev/null
+++ b/app/policies/activity_policy.rb
@@ -0,0 +1,28 @@
+class ActivityPolicy < ApplicationPolicy
+  class Scope < Scope
+    attr_reader :user, :scope
+
+    def initialize(user, scope)
+      @user  = user
+      @scope = scope
+    end
+
+    def resolve
+      raise StandardError, 'The user must be set.' if user.blank?
+      if user.is_admin?
+        scope.includes(:owner).order('created_at DESC').all
+      else
+        user.activities
+      end
+    end
+  end
+
+  def index?
+    true
+  end
+
+  ## only user followers can see your activities
+  def user_activities?
+    record if user.following? record
+  end
+end
diff --git a/app/policies/collection_policy.rb b/app/policies/collection_policy.rb
index fab8a33a5bcc8c8955e18c4f30939748010215d4..7af04bed7faf340bf08f766264e4d2f783cfcc02 100644
--- a/app/policies/collection_policy.rb
+++ b/app/policies/collection_policy.rb
@@ -3,7 +3,6 @@ class CollectionPolicy < ApplicationPolicy
   include FollowablePolicy
   include TaggablePolicy
 
-
   class Scope < Scope
     def initialize (user, user_id, scope)
       @user = user
@@ -24,10 +23,6 @@ class CollectionPolicy < ApplicationPolicy
     record if user_exists?
   end
 
-  def edit?
-    record if owns?
-  end
-
   def show?
     unless record.private?
       record
diff --git a/app/policies/license_policy.rb b/app/policies/license_policy.rb
new file mode 100644
index 0000000000000000000000000000000000000000..adb7750ca3bdd3402ead90e2f67e32907d7b7e76
--- /dev/null
+++ b/app/policies/license_policy.rb
@@ -0,0 +1,21 @@
+class LicensePolicy < ApplicationPolicy
+  def index?
+    record
+  end
+
+  def show?
+    record
+  end
+
+  def create?
+    record if user.is_admin?
+  end
+
+  def update?
+    record if user.is_admin?
+  end
+
+  def destroy?
+    record if user.is_admin?
+  end
+end
diff --git a/app/serializers/follow_serializer.rb b/app/serializers/follow_serializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..507f2d9830c7c5c079ee7cbeb44b776a0e76c0d5
--- /dev/null
+++ b/app/serializers/follow_serializer.rb
@@ -0,0 +1,5 @@
+class FollowSerializer < ActiveModel::Serializer
+  has_one :followable
+
+  attributes :id, :user_id
+end
diff --git a/app/serializers/learning_object/attachment_serializer.rb b/app/serializers/learning_object/attachment_serializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2e5b87370fa97dceb34f82dd50de6d4d6cdee67b
--- /dev/null
+++ b/app/serializers/learning_object/attachment_serializer.rb
@@ -0,0 +1,3 @@
+class LearningObject::AttachmentSerializer < ActiveModel::Serializer
+  attributes :id, :name, :retrieve_link, :description, :format, :mime_type, :size, :bundle_name, :learning_object_id, :created_at, :updated_at, :id_dspace, :thumbnail, :cache_link
+end
diff --git a/app/serializers/learning_object_obaa_serializer.rb b/app/serializers/learning_object_obaa_serializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f6d520e433eb10aeef1007f3b4efe5c66c2dc060
--- /dev/null
+++ b/app/serializers/learning_object_obaa_serializer.rb
@@ -0,0 +1,67 @@
+class LearningObjectObaaSerializer < ActiveModel::Serializer
+#   "educational": {
+#     "description": "? não existe no PortalMecHomologa"
+#   },
+
+  def general
+    {
+      title: object.name,
+      description: object.description,
+      keywords: object.tags.map(&:name).join(','),
+      created_at: object.created_at,
+      updated_at: object.updated_at,
+      thumbnail: object.default_thumbnail,
+      score: object.score,
+      likes_count: object.likes_count,
+      shares_count: object.shares_count,
+      acessibility: ''
+    }
+  end
+
+  def identifier
+    {
+      catalog: 'PortalMec',
+      entry: object.id,
+      language: object.language.try(:code)
+    }
+  end
+
+  def technical
+    {
+      location: object.default_attachment.try(:retrieve_url),
+      format: object.default_attachment.try(:mime_type)
+    }
+  end
+
+  def rights
+    {
+      copyrightAndOhterRestrictions: 'true',
+      cost: 'false',
+      description: object.license.try(:name)
+    }
+  end
+
+  def metametadata
+    {
+      identifier: {
+        catalog: 'PortalMec',
+        name: object.publisher.try(:name),
+        entry_type: object.publisher.class.name,
+        entry: object.publisher.try(:id)
+      },
+      contribute: {
+        role: 'Criador',
+        entity: object.author,
+        date: object.created_at
+      },
+      metadataSchema: 'OBAAv1.0',
+      language: object.language.try(:name)
+    }
+  end
+
+  # attributes :id , :name, :created_at, :updated_at, :description, :author, :score, :likes_count
+  attributes :id, :general, :identifier, :technical, :rights, :metametadata
+
+  # has_many :tags
+  # has_many :attachments
+end
diff --git a/app/serializers/learning_object_serializer.rb b/app/serializers/learning_object_serializer.rb
index 58e096c5623fb8a9d5f8bbc1215d858c45001077..5d51578f8c2bd95d96560a9e620b8a0cf6b179c1 100644
--- a/app/serializers/learning_object_serializer.rb
+++ b/app/serializers/learning_object_serializer.rb
@@ -1,5 +1,22 @@
 class LearningObjectSerializer < ActiveModel::Serializer
-  attributes :id , :name, :created_at, :updated_at, :description, :author, :score, :likes_count
+  def default_location
+    object.default_attachment.try(:retrieve_url)
+  end
+
+  def default_mime_type
+    object.default_attachment.try(:mime_type)
+  end
+
+  def default_attachment_id
+    object.default_attachment.try(:id)
+  end
+
+  def thumbnail
+    object.default_thumbnail
+  end
+
+  attributes :id, :name, :description, :author, :thumbnail, :publisher, :language, :default_attachment_id, :default_location, :default_mime_type, :score, :license, :likes_count, :shares_count, :created_at, :updated_at
+
   has_many :tags
   has_many :attachments
 end
diff --git a/app/serializers/license_serializer.rb b/app/serializers/license_serializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..52cc601b822ac7fad57128b4b42e49524482fd77
--- /dev/null
+++ b/app/serializers/license_serializer.rb
@@ -0,0 +1,3 @@
+class LicenseSerializer < ActiveModel::Serializer
+  attributes :id, :name, :description, :url, :image_url
+end
diff --git a/app/serializers/paper_trail/version_serializer.rb b/app/serializers/paper_trail/version_serializer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..039afe83b8104237e207266d7bb48db7695c6579
--- /dev/null
+++ b/app/serializers/paper_trail/version_serializer.rb
@@ -0,0 +1,3 @@
+class PaperTrail::VersionSerializer < ActiveModel::Serializer
+  attributes :id, :item, :event, :whodunnit, :created_at, :object
+end
diff --git a/app/serializers/public_activity/activity_serializer.rb b/app/serializers/public_activity/activity_serializer.rb
index 42a4b063a1b61594b109a30c0367137da1282a9e..fc1439de5de8fa1eeb23f826d067c56fdbddc48a 100644
--- a/app/serializers/public_activity/activity_serializer.rb
+++ b/app/serializers/public_activity/activity_serializer.rb
@@ -1,3 +1,3 @@
 class PublicActivity::ActivitySerializer < ActiveModel::Serializer
-  attributes :id, :owner
+  attributes :id, :owner, :trackable, :recipient, :parameters, :created_at
 end
diff --git a/app/services/learning_object_publisher.rb b/app/services/learning_object_publisher.rb
index d2f99a4e0949f2f61b8be41dde16611779651041..1508c31b71bd4372f06f6e5fa951ce3ea742a995 100644
--- a/app/services/learning_object_publisher.rb
+++ b/app/services/learning_object_publisher.rb
@@ -15,7 +15,7 @@ class LearningObjectPublisher
       draft.id_dspace = item.id
       draft.save
 
-      publish! draft if draft.has_url_reference?
+      publish draft if draft.has_url_reference?
       return draft
     end
     false
@@ -28,9 +28,9 @@ class LearningObjectPublisher
 
   ## publish *learning_object*
   # this method will create thumbnails, change state to published and will save it.
-  def publish!(learning_object)
-    if learning_object.is_draft?
-      learning_object.publish
+  def publish(learning_object)
+    if learning_object.draft?
+      learning_object.published!
       ThumbnailGenerateWorker.perform_async learning_object.id, learning_object.url_reference if learning_object.has_url_reference?
     end
     learning_object.save
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 7a472ab7ee7c429ff6afee2f4bab7b2a438efc37..c8883fcea7c33a44f98a823040b1fca12feecc03 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -1,129 +1,20 @@
-class SearchService
+module SearchService
+  SEARCH_CLASSES = %w(LearningObject Collection User)
 
-  attr_accessor :search
+  class InvalidSearchError < StandardError; end
 
-  def initialize(search, user)
-    @search = search
-    @user = user
+  def self.search(search, user)
+    model = instance(search, user)
+    model.search.results
   end
 
-  def fetch
-    validate
-    return search_learning_object if @search.learning_object?
-    return search_collection if @search.collection?
-    return search_user if @search.user?
+  def self.autocomplete(search, user)
+    model = instance(search, user)
+    model.autocomplete
   end
 
-  def autocomplete
-    validate
-
-    params_hash = {}
-    get_thumbnail = nil
-    get_type = nil
-    if @search.learning_object?
-      params_hash = { where: {state: validate_object},
-        fields: ['name^10', 'description', 'author'] }
-      get_thumbnail = Proc.new { |obj| obj.default_thumbnail }
-      get_type = Proc.new { |obj| obj.object_type.try(:name) }
-
-    elsif @search.collection?
-      params_hash = { where: {privacy: "public"},
-        fields: ['name^10', 'description', 'owner'] }
-      get_thumbnail = Proc.new { |obj| "/assets/icons/collection" }
-      get_type = Proc.new { |obj| "Collection"}
-
-    else #User
-      params_hash = { fields: ['name'] }
-      get_thumbnail = Proc.new { |obj| obj.avatar.url(:thumb) }
-      get_type = Proc.new { |obj| "User" }
-    end
-
-    autocomplete_search(Object.const_get(@search.search_class), @search.query, params_hash, get_type, get_thumbnail)
-  end
-
-  private
-
-  def validate
-    raise "Invalid search" unless @search.valid?
+  def self.instance(search, user)
+    raise InvalidSearchError unless search.valid?
+    "SearchService::#{search.search_class}".constantize.new(search, user)
   end
-
-  def search_learning_object
-    LearningObject.search(@search.query, where: lo_where_hash, order: lo_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
-  end
-  
-  def search_collection
-    Collection.search(@search.query, where: {privacy: "public"}, order: col_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
-  end
-
-  def search_user
-    User.search(@search.query, order: user_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
-  end
-
-  def autocomplete_search(search_class, query, params_hash={}, get_type, get_thumbnail)
-    response = []
-    search_params = { limit: 10, misspellings: { below: 5 } }
-    objs = search_class.search(query, search_params.merge(params_hash))    
-    objs.each do |obj|
-      hash = {}
-      hash["id"] = obj.id
-      hash["name"] = obj.name
-      hash["type"] = get_type.call(obj)
-      hash["thumbnail"] = get_thumbnail.call(obj)
-      response << hash
-    end
-    response
-  end
-
-  def lo_where_hash
-    hash = {}
-    hash[:tags] = @search.tags unless @search.tags.blank?
-    hash[:object_type] = @search.types unless @search.types.blank?
-    hash[:source] = @search.sources unless @search.sources.blank?
-    hash[:state] = validate_object
-    hash.blank? ? nil : hash
-  end
-
-  def lo_order_hash(order)
-    case order
-    when 'author'
-      { author: {order: :asc, unmapped_type: :string} }
-    when 'publicationasc'
-      { published_at: {order: :asc, unmapped_type: :timestamp} }
-    when 'publicationdesc'
-      { published_at: {order: :desc, unmapped_type: :timestamp} }
-    when 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def col_order_hash(order)
-    case order
-    when 'author'
-      { owner: {order: :asc, unmapped_type: :string} }
-    when 'publicationasc'
-      { created_at: {order: :asc, unmapped_type: :timestamp} }
-    when 'publicationdesc'
-      { created_at: {order: :desc, unmapped_type: :timestamp} }
-    when 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def user_order_hash(order)
-    if order == 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def validate_object
-    return 'published' unless !@user.nil? && @user.is_admin?
-    return ['published', 'suspended', 'draft']
-  end
-
-end
\ No newline at end of file
+end
diff --git a/app/services/search_service/collection.rb b/app/services/search_service/collection.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b5c17c3a36d1a4117b8939ae7347dec075c18c20
--- /dev/null
+++ b/app/services/search_service/collection.rb
@@ -0,0 +1,29 @@
+module SearchService
+  class Collection < Model
+    def search
+      ::Collection.search(@search.query, where: { privacy: 'public' }, order: order_hash, page: @search.page, per_page: @search.results_per_page)
+    end
+
+    def autocomplete
+      params = {  where: { privacy: 'public' },
+                  fields: ['name^10', 'description', 'owner'] }
+      result = ::Collection.search(@search.query, autocomplete_params.merge(params))
+
+      thumbnail = proc { |_obj| '/assets/icons/collection' }
+      type = proc { |_obj| 'Collection' }
+      autocomplete_render(result, type, thumbnail)
+    end
+
+    private
+
+    def order_hash
+      case @search.order
+      when 'author' then { owner: { order: :asc, unmapped_type: :string } }
+      when 'publicationasc' then { created_at: { order: :asc, unmapped_type: :timestamp } }
+      when 'publicationdesc' then { created_at: { order: :desc, unmapped_type: :timestamp } }
+      when 'title' then { name: { order: :asc, unmapped_type: :string } }
+      else { score: { order: :desc, unmapped_type: :integer } }
+      end
+    end
+  end
+end
diff --git a/app/services/search_service/learning_object.rb b/app/services/search_service/learning_object.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c53a300febdfb77160bf5eca942d6c0ccd4b7d58
--- /dev/null
+++ b/app/services/search_service/learning_object.rb
@@ -0,0 +1,43 @@
+module SearchService
+  class LearningObject < Model
+    def search
+      ::LearningObject.search(@search.query, where: where_hash, order: order_hash, page: @search.page, per_page: @search.results_per_page)
+    end
+
+    def autocomplete
+      params = {  where: { state: validate_object },
+                  fields: ['name^10', 'description', 'author'] }
+      result = ::LearningObject.search(@search.query, autocomplete_params.merge(params))
+
+      thumbnail = proc { |obj| obj.default_thumbnail }
+      type = proc { |obj| obj.object_type.try(:name) }
+      autocomplete_render(result, type, thumbnail)
+    end
+
+    private
+
+    def where_hash
+      hash = {}
+      hash[:tags] = @search.tags unless @search.tags.blank?
+      hash[:object_type] = @search.types unless @search.types.blank?
+      hash[:source] = @search.sources unless @search.sources.blank?
+      hash[:state] = validate_object
+      hash.blank? ? nil : hash
+    end
+
+    def order_hash
+      case @search.order
+      when 'author' then { author: { order: :asc, unmapped_type: :string } }
+      when 'publicationasc' then { published_at: { order: :asc, unmapped_type: :timestamp } }
+      when 'publicationdesc' then { published_at: { order: :desc, unmapped_type: :timestamp } }
+      when 'title' then { name: { order: :asc, unmapped_type: :string } }
+      else { score: { order: :desc, unmapped_type: :integer } }
+      end
+    end
+
+    def validate_object
+      return 'published' unless !@user.nil? && @user.is_admin?
+      %w(published suspended draft)
+    end
+  end
+end
diff --git a/app/services/search_service/model.rb b/app/services/search_service/model.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e1a0bbb6bf43da38383cbee5c0cbe577db8b0b7f
--- /dev/null
+++ b/app/services/search_service/model.rb
@@ -0,0 +1,35 @@
+module SearchService
+  class Model
+    def initialize(search, user)
+      raise 'Invalid search' unless search.valid?
+
+      @search = search
+      @user = user
+    end
+
+    def search
+      raise 'Must implement!'
+    end
+
+    def autocomplete
+      raise 'Must implement!'
+    end
+
+    private
+
+    def autocomplete_params
+      { limit: 10, misspellings: { below: 5 } }
+    end
+
+    def autocomplete_render(result, type, thumbnail)
+      result.map do |obj|
+        {
+          id: obj.id,
+          name: obj.name,
+          type: type.call(obj),
+          thumbnail: thumbnail.call(obj)
+        }
+      end
+    end
+  end
+end
diff --git a/app/services/search_service/user.rb b/app/services/search_service/user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c7ffef549acbdcc0fd80dfebaee0d5f14a2dff72
--- /dev/null
+++ b/app/services/search_service/user.rb
@@ -0,0 +1,22 @@
+module SearchService
+  class User < Model
+    def search
+      ::User.search(@search.query, order: order_hash, page: @search.page, per_page: @search.results_per_page)
+    end
+
+    def autocomplete
+      result = ::User.search(@search.query, autocomplete_params.merge(fields: ['name']))
+
+      thumbnail = proc { |obj| obj.avatar.url(:thumb) }
+      type = proc { |_obj| 'User' }
+      autocomplete_render(result, type, thumbnail)
+    end
+
+    private
+
+    def order_hash
+      return { name: { order: :asc, unmapped_type: :string } } if @search.order == 'title'
+      { score: { order: :desc, unmapped_type: :integer } }
+    end
+  end
+end
diff --git a/app/workers/dspace_upload_worker.rb b/app/workers/dspace_upload_worker.rb
index 4bd64788af10fa0c15b3ca8bb7eb18e3437e68df..463943e242b95a14a91f8539a475faa91c8f3739 100644
--- a/app/workers/dspace_upload_worker.rb
+++ b/app/workers/dspace_upload_worker.rb
@@ -13,7 +13,7 @@ class DspaceUploadWorker
     #find learning object
     learning_object = LearningObject.find learning_object_id
     attachment = learning_object.attachments.create map_bitstream2attachment(bitstream)
-    publisher.publish! learning_object
+    publisher.publish learning_object
 
     ThumbnailGenerateWorker.perform_async attachment.id, media_path
   end
diff --git a/config/environments/development.rb b/config/environments/development.rb
index eb3772c3a0867beabd00a672cf5c425b64731fa7..987efaf25f29e895293756ea1e7bc3c1703b2bad 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -51,5 +51,9 @@ Rails.application.configure do
   # Raises error for missing translations
   # config.action_view.raise_on_missing_translations = true
 
+  #config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
+  # Lets define mailcatcher configs
+  config.action_mailer.delivery_method = :smtp
+  config.action_mailer.smtp_settings = { address: 'localhost', port: 1025 }
   config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
 end
diff --git a/config/feature.yml b/config/feature.yml
index 078483a61535eabf09ad0ed4037353244f30f274..b5aa6837a4ad98cc4ae3b1a32159f660f77f09ba 100644
--- a/config/feature.yml
+++ b/config/feature.yml
@@ -1,11 +1,11 @@
 development:
   features:
-    barra_brasil: false
+    allow_client_application: false
 
 test:
   features:
-    barra_brasil: true
+    allow_client_application: true
 
 production:
   features:
-    barra_brasil: true
\ No newline at end of file
+    allow_client_application: false
diff --git a/config/initializers/paper_trail.rb b/config/initializers/paper_trail.rb
new file mode 100644
index 0000000000000000000000000000000000000000..442b5f789ce70fcc93ffac5ab211d24668919884
--- /dev/null
+++ b/config/initializers/paper_trail.rb
@@ -0,0 +1 @@
+PaperTrail.config.track_associations = false
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 0c9b6275987f925de1a01609a78803b8bc3f7461..4b045a9eb95bb5f4d2c8d84a188b34fb7ff89cd8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,12 @@ Rails.application.routes.draw do
   require 'sidekiq/web'
   mount Sidekiq::Web, at: '/sidekiq'
 
+  concern :deletable do
+    collection do
+      get :deleted
+    end
+  end
+
   concern :followable do
     member do
       post 'follow', as: :follow, action: :follow
@@ -24,46 +30,74 @@ Rails.application.routes.draw do
   end
 
   concern :reviewable do
-    resources :reviews, except: :update do
+    resources :reviews, only: [:index, :create, :show, :destroy], concerns: :deletable do
       member do
         post :rate
       end
     end
   end
 
+  concern :highlights do
+    collection do
+      get :this_week
+      get :this_month
+    end
+  end
+
+  # GET /learning_objects/1/versions/123
+  # GET /learning_objects/1/versions
+  # POST /learning_objects/1/versions/234/checkout
+  concern :versionable do
+    resources :versions, only: [:show, :index] do
+      member do
+        post :checkout
+      end
+    end
+  end
+
   scope :v1 do
     mount_devise_token_auth_for 'User', skip: [:omniauth_callbacks], at: :auth
   end
 
   namespace :v1 do
-    #activities
-    get :activities, to: 'activities#index'
+    resources :activities, only: :index
 
-    resources :users, concerns: :followable do
+    resources :users, concerns: [:followable, :deletable] do
       member do
         resources :bookmarks, module: 'users', only: [:index, :create, :destroy]
+        get 'watching/:object_type', to: 'users#watching'
+        get 'activities', to: 'activities#user_activities'
       end
     end
-    get :search, to: 'search#index'
-    get 'search/autocomplete', to: 'search#autocomplete'
-    resources :collections, concerns: [:followable, :sociable, :reviewable, :taggable]
-    resources :learning_objects, concerns: [:sociable, :reviewable, :taggable] do
+
+    # search routes
+    resources :search, only: :index do
+      collection do
+        get :autocomplete
+      end
+    end
+
+    resources :collections, concerns: [:followable, :sociable, :reviewable, :taggable, :versionable, :deletable, :highlights]
+    resources :learning_objects, concerns: [:sociable, :reviewable, :taggable, :versionable, :deletable, :highlights] do
       member do
         resource :chunk, module: 'learning_objects', only: [:create, :show]
         resource :upload, module: 'learning_objects', only: :create
       end
     end
-    resources :institutions do
+
+    resources :institutions, concerns: :deletable do
       member do
         get :users, to: 'institutions#users'
       end
     end
-    resources :scores, only: [:index, :update]
-    resources :object_types, except: [:new, :edit]
-    resources :mime_types, except: [:new, :edit]
+
+    resources :complaints, only: [:index, :create], concerns: :deletable
     resources :languages, except: [:new, :edit]
-    resources :complaints, only: [:index, :create]
+    resources :licenses, except: [:new, :edit]
+    resources :mime_types, except: [:new, :edit]
+    resources :object_types, except: [:new, :edit]
     resources :roles, except: [:new, :edit]
+    resources :scores, only: [:index, :update]
 
     post '/package', to: 'packages#link'
   end
diff --git a/db/migrate/20160512135942_add_deleted_at_to_learning_objects.rb b/db/migrate/20160512135942_add_deleted_at_to_learning_objects.rb
new file mode 100644
index 0000000000000000000000000000000000000000..30a6ed6f0bb5262ae8fbef1960ddf0b698833bf8
--- /dev/null
+++ b/db/migrate/20160512135942_add_deleted_at_to_learning_objects.rb
@@ -0,0 +1,6 @@
+class AddDeletedAtToLearningObjects < ActiveRecord::Migration
+  def change
+    add_column :learning_objects, :deleted_at, :datetime
+    add_index :learning_objects, :deleted_at
+  end
+end
diff --git a/db/migrate/20160512140101_add_deleted_at_to_collections.rb b/db/migrate/20160512140101_add_deleted_at_to_collections.rb
new file mode 100644
index 0000000000000000000000000000000000000000..820a98d6daafdd9410f271a297e4123a0db723c8
--- /dev/null
+++ b/db/migrate/20160512140101_add_deleted_at_to_collections.rb
@@ -0,0 +1,6 @@
+class AddDeletedAtToCollections < ActiveRecord::Migration
+  def change
+    add_column :collections, :deleted_at, :datetime
+    add_index :collections, :deleted_at
+  end
+end
diff --git a/db/migrate/20160512140142_add_deleted_at_to_complaints.rb b/db/migrate/20160512140142_add_deleted_at_to_complaints.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c34d7384c8619d85a96e7d9c257596b7be05c235
--- /dev/null
+++ b/db/migrate/20160512140142_add_deleted_at_to_complaints.rb
@@ -0,0 +1,6 @@
+class AddDeletedAtToComplaints < ActiveRecord::Migration
+  def change
+    add_column :complaints, :deleted_at, :datetime
+    add_index :complaints, :deleted_at
+  end
+end
diff --git a/db/migrate/20160512140201_add_deleted_at_to_institutions.rb b/db/migrate/20160512140201_add_deleted_at_to_institutions.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1ea68ab23c78cbaf77e21d98f78fd3b5a2a3e1ba
--- /dev/null
+++ b/db/migrate/20160512140201_add_deleted_at_to_institutions.rb
@@ -0,0 +1,6 @@
+class AddDeletedAtToInstitutions < ActiveRecord::Migration
+  def change
+    add_column :institutions, :deleted_at, :datetime
+    add_index :institutions, :deleted_at
+  end
+end
diff --git a/db/migrate/20160512140234_add_deleted_at_to_reviews.rb b/db/migrate/20160512140234_add_deleted_at_to_reviews.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0794fe290ffc63fb810ff7d49cc8d4335825f254
--- /dev/null
+++ b/db/migrate/20160512140234_add_deleted_at_to_reviews.rb
@@ -0,0 +1,6 @@
+class AddDeletedAtToReviews < ActiveRecord::Migration
+  def change
+    add_column :reviews, :deleted_at, :datetime
+    add_index :reviews, :deleted_at
+  end
+end
diff --git a/db/migrate/20160512140321_add_deleted_at_to_users.rb b/db/migrate/20160512140321_add_deleted_at_to_users.rb
new file mode 100644
index 0000000000000000000000000000000000000000..29ba1647ecaf78d5943413ce995a87ee8fe38973
--- /dev/null
+++ b/db/migrate/20160512140321_add_deleted_at_to_users.rb
@@ -0,0 +1,6 @@
+class AddDeletedAtToUsers < ActiveRecord::Migration
+  def change
+    add_column :users, :deleted_at, :datetime
+    add_index :users, :deleted_at
+  end
+end
diff --git a/db/migrate/20160512140322_ensure_versions_table_is_deleted.rb b/db/migrate/20160512140322_ensure_versions_table_is_deleted.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d79b2e5a181a0e0be5b5c429ae1eb93be5069ef3
--- /dev/null
+++ b/db/migrate/20160512140322_ensure_versions_table_is_deleted.rb
@@ -0,0 +1,6 @@
+class EnsureVersionsTableIsDeleted < ActiveRecord::Migration
+  def change
+    table = :versions
+    drop_table table if table_exists? table
+  end
+end
diff --git a/db/migrate/20160512143532_create_versions.rb b/db/migrate/20160512143532_create_versions.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dbe8ec81bbbf5332a0a037f7696d654c17f94e74
--- /dev/null
+++ b/db/migrate/20160512143532_create_versions.rb
@@ -0,0 +1,68 @@
+# This migration creates the `versions` table, the only schema PT requires.
+# All other migrations PT provides are optional.
+class CreateVersions < ActiveRecord::Migration
+  # Class names of MySQL adapters.
+  # - `MysqlAdapter` - Used by gems: `mysql`, `activerecord-jdbcmysql-adapter`.
+  # - `Mysql2Adapter` - Used by `mysql2` gem.
+  MYSQL_ADAPTERS = [
+    "ActiveRecord::ConnectionAdapters::MysqlAdapter",
+    "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
+  ].freeze
+
+  # The largest text column available in all supported RDBMS is
+  # 1024^3 - 1 bytes, roughly one gibibyte.  We specify a size
+  # so that MySQL will use `longtext` instead of `text`.  Otherwise,
+  # when serializing very large objects, `text` might not be big enough.
+  TEXT_BYTES = 1_073_741_823
+
+  def change
+    create_table :versions, versions_table_options do |t|
+      t.string   :item_type, null: false
+      t.integer  :item_id,   null: false
+      t.string   :event,     null: false
+      t.string   :whodunnit
+      t.text     :object, limit: TEXT_BYTES
+
+      # Known issue in MySQL: fractional second precision
+      # -------------------------------------------------
+      #
+      # MySQL timestamp columns do not support fractional seconds unless
+      # defined with "fractional seconds precision". MySQL users should manually
+      # add fractional seconds precision to this migration, specifically, to
+      # the `created_at` column.
+      # (https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html)
+      #
+      # MySQL users should also upgrade to rails 4.2, which is the first
+      # version of ActiveRecord with support for fractional seconds in MySQL.
+      # (https://github.com/rails/rails/pull/14359)
+      #
+      t.datetime :created_at
+    end
+    add_index :versions, [:item_type, :item_id]
+  end
+
+  private
+
+  # Even modern versions of MySQL still use `latin1` as the default character
+  # encoding. Many users are not aware of this, and run into trouble when they
+  # try to use PaperTrail in apps that otherwise tend to use UTF-8. Postgres, by
+  # comparison, uses UTF-8 except in the unusual case where the OS is configured
+  # with a custom locale.
+  #
+  # - https://dev.mysql.com/doc/refman/5.7/en/charset-applications.html
+  # - http://www.postgresql.org/docs/9.4/static/multibyte.html
+  #
+  # Furthermore, MySQL's original implementation of UTF-8 was flawed, and had
+  # to be fixed later by introducing a new charset, `utf8mb4`.
+  #
+  # - https://mathiasbynens.be/notes/mysql-utf8mb4
+  # - https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
+  #
+  def versions_table_options
+    if MYSQL_ADAPTERS.include?(connection.class.name)
+      { options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" }
+    else
+      {}
+    end
+  end
+end
diff --git a/db/migrate/20160516125724_create_licenses.rb b/db/migrate/20160516125724_create_licenses.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dd447797a2598788e75f7ec9bb89296fa7522691
--- /dev/null
+++ b/db/migrate/20160516125724_create_licenses.rb
@@ -0,0 +1,12 @@
+class CreateLicenses < ActiveRecord::Migration
+  def change
+    create_table :licenses do |t|
+      t.string :name, index: true
+      t.text :description
+      t.string :image_url
+      t.string :url
+
+      t.timestamps null: false
+    end
+  end
+end
diff --git a/db/migrate/20160516125800_add_license_to_learning_objects.rb b/db/migrate/20160516125800_add_license_to_learning_objects.rb
new file mode 100644
index 0000000000000000000000000000000000000000..283adeecb97a22884a57837fdea4211d7e8e1e9f
--- /dev/null
+++ b/db/migrate/20160516125800_add_license_to_learning_objects.rb
@@ -0,0 +1,5 @@
+class AddLicenseToLearningObjects < ActiveRecord::Migration
+  def change
+    add_reference :learning_objects, :license, index: true
+  end
+end
diff --git a/db/migrate/20160517140326_create_applications.rb b/db/migrate/20160517140326_create_applications.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a13de010952b216b7b3dfd626a9a47e03f4aa110
--- /dev/null
+++ b/db/migrate/20160517140326_create_applications.rb
@@ -0,0 +1,14 @@
+class CreateApplications < ActiveRecord::Migration
+  def change
+    create_table :applications do |t|
+      t.string :name
+      t.string :domain
+      t.string :application_id
+      t.belongs_to :user, index: true, foreign_key: true
+
+      t.timestamps null: false
+    end
+    add_index :applications, :domain, unique: true
+    add_index :applications, :application_id, unique: true
+  end
+end
diff --git a/db/migrate/20160519122525_change_state_type_in_learning_objects.rb b/db/migrate/20160519122525_change_state_type_in_learning_objects.rb
new file mode 100644
index 0000000000000000000000000000000000000000..134afa90ce9a000c4b9e7b37d5b02ab2a48b2aaa
--- /dev/null
+++ b/db/migrate/20160519122525_change_state_type_in_learning_objects.rb
@@ -0,0 +1,11 @@
+class ChangeStateTypeInLearningObjects < ActiveRecord::Migration
+  def change
+    add_column :learning_objects, :statenew, :integer, default: 0
+    execute <<-SQL
+          UPDATE learning_objects set statenew = 1 WHERE state = 'published';
+          UPDATE learning_objects set statenew = 2 WHERE state = 'suspended';
+        SQL
+    remove_column :learning_objects, :state
+    rename_column :learning_objects, :statenew, :state
+  end
+end
diff --git a/db/seeds.rb b/db/seeds.rb
index 8259284babccce34d2a3b8b63af9301683277774..0cc0d52f1cfe1fb6431d0d6a224dd5cbcd6cc298 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -22,6 +22,7 @@ User.create(
 require_relative 'seeds/complaints'
 require_relative 'seeds/institutions'
 require_relative 'seeds/languages'
+require_relative 'seeds/licenses'
 require_relative 'seeds/object_types'
 require_relative 'seeds/ratings'
 require_relative 'seeds/scores'
diff --git a/db/seeds/licenses.rb b/db/seeds/licenses.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b670e4583944e2a1f170138b1a45a4130d492ec5
--- /dev/null
+++ b/db/seeds/licenses.rb
@@ -0,0 +1,10 @@
+License.create(name: 'CC BY', description: 'Creative Commons Atribuição', url: 'https://creativecommons.org/licenses/by/4.0/deed.pt_BR', image_url: 'https://licensebuttons.net/l/by/3.0/88x31.png')
+License.create(name: 'CC BY-SA', description: 'Creative Commons Atribuição-CompartilhaIgual', url: 'https://creativecommons.org/licenses/by-sa/4.0/deed.pt_BR', image_url: 'https://licensebuttons.net/l/by-sa/3.0/88x31.png')
+License.create(name: 'CC BY-ND', description: 'Creative Commons Atribuição-SemDerivações', url: 'https://creativecommons.org/licenses/by-nd/4.0/deed.pt_BR', image_url: 'https://licensebuttons.net/l/by-nd/3.0/88x31.png')
+License.create(name: 'CC BY-NC', description: 'Creative Commons Atribuição-NãoComercial', url: 'https://creativecommons.org/licenses/by-nc/4.0/deed.pt_BR', image_url: 'https://licensebuttons.net/l/by-nc/3.0/88x31.png')
+License.create(name: 'CC BY-NC-SA', description: 'Creative Commons Atribuição-NãoComercial-CompartilhaIgual', url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/deed.pt_BR', image_url: 'https://licensebuttons.net/l/by-nc-sa/3.0/88x31.png')
+License.create(name: 'CC BY-NC-ND', description: 'Creative Commons Atribuição-SemDerivações-SemDerivados', url: 'https://creativecommons.org/licenses/by-nc-nd/4.0/deed.pt_BR', image_url: 'https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png')
+License.create(name: 'MIT', description: 'MIT', url: 'https://opensource.org/licenses/MIT', image_url: '')
+License.create(name: 'GPL-2.0', description: 'GNU General Public License v2', url: 'https://opensource.org/licenses/GPL-2.0', image_url: '')
+License.create(name: 'GPL-3.0', description: 'GNU General Public License v3', url: 'https://opensource.org/licenses/GPL-3.0', image_url: '')
+License.create(name: 'Apache', description: 'Apache v2', url: 'https://www.apache.org/licenses/LICENSE-2.0', image_url: '')
diff --git a/spec/auth_helper.rb b/spec/auth_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7a763c45af393eb438620e80d081c1ce2710609a
--- /dev/null
+++ b/spec/auth_helper.rb
@@ -0,0 +1,4 @@
+# authenticate the test application
+def auth_app(app, request)
+  request.headers['PortalMEC-AppID'] = app.application_id
+end
\ No newline at end of file
diff --git a/spec/controllers/v1/collections_controller_spec.rb b/spec/controllers/v1/collections_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d5621cd6e5cff9f368b01e9667624c7dae5ce27b
--- /dev/null
+++ b/spec/controllers/v1/collections_controller_spec.rb
@@ -0,0 +1,45 @@
+require 'rails_helper'
+
+RSpec.describe V1::CollectionsController, type: :controller do
+  fixtures :all
+
+  it { should use_before_action(:authenticate_user!) }
+  it { should use_before_action(:set_collection) }
+  it { should route(:get, '/v1/collections').to(action: :index) }
+
+  describe 'sociable actions' do
+    it { should use_before_action(:authorize_sociable!) }
+    it { should use_before_action(:view_object!) }
+    it { should route(:post, '/v1/collections/1/like').to(action: :like, id: 1) }
+    it { should route(:delete, '/v1/collections/1/like').to(action: :unlike, id: 1) }
+
+    describe 'POST #like' do
+      before do
+        auth_app applications(:test_app), @request
+        post :like, id: collections(:ufpr).id
+      end
+
+      context 'when user is authenticated' do
+        it do
+          #user = applications(:test_app).user
+          expect(response).to have_http_status(:created)
+        end
+      end
+
+      context 'when user is not authenticated' do
+        it { expect(response).to have_http_status(:unauthorized) }
+      end
+    end
+  end
+
+  describe 'GET #index' do
+      before do
+        auth_app applications(:test_app), @request
+        get :index
+      end
+
+      it { expect(response.content_type).to eq('application/json') }
+      it { expect(response).to have_http_status(:ok) }
+  end
+
+end
\ No newline at end of file
diff --git a/spec/factories/applications.rb b/spec/factories/applications.rb
new file mode 100644
index 0000000000000000000000000000000000000000..badcbdbec12f586ed5ddc0dadbe7e7b733ee6f8d
--- /dev/null
+++ b/spec/factories/applications.rb
@@ -0,0 +1,9 @@
+FactoryGirl.define do
+
+  factory :application do |f|
+    user
+    f.name { 'test app' }
+    f.domain { 'test.host' }
+  end
+
+end
\ No newline at end of file
diff --git a/spec/factories/collections.rb b/spec/factories/collections.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8b7761ccbaf537062a6a53b8b116a49e99ec451f
--- /dev/null
+++ b/spec/factories/collections.rb
@@ -0,0 +1,9 @@
+FactoryGirl.define do
+
+  factory :collection do |f|
+    owner
+    f.name { Faker::University.name }
+    f.privacy { 'public' }
+  end
+
+end
\ No newline at end of file
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
new file mode 100644
index 0000000000000000000000000000000000000000..09510c84e714612e680422705622ac5a55b8a16b
--- /dev/null
+++ b/spec/factories/users.rb
@@ -0,0 +1,9 @@
+FactoryGirl.define do
+
+  factory :user, aliases: [:owner] do |f|
+    f.name { Faker::Name.name }
+    f.email { Faker::Internet.email }
+    f.confirmed_at { '2015-10-10 15:30:22' }
+  end
+
+end
\ No newline at end of file
diff --git a/spec/models/application_spec.rb b/spec/models/application_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..004603d65dc7a0f1497017872bd5b5b9f9b98ec8
--- /dev/null
+++ b/spec/models/application_spec.rb
@@ -0,0 +1,11 @@
+require 'rails_helper'
+
+RSpec.describe Application, type: :model do
+
+  describe 'validate model' do
+    it { should belong_to :user }
+    it { should validate_presence_of(:domain) }
+    it { should validate_presence_of(:application_id) }
+  end
+
+end
\ No newline at end of file
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..258bbf11d75ef86fed2789992c2f51b5ca6f0d39
--- /dev/null
+++ b/spec/rails_helper.rb
@@ -0,0 +1,58 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+ENV['RAILS_ENV'] ||= 'test'
+require File.expand_path('../../config/environment', __FILE__)
+# Prevent database truncation if the environment is production
+abort("The Rails environment is running in production mode!") if Rails.env.production?
+require 'spec_helper'
+require 'auth_helper'
+require 'rspec/rails'
+# Add additional requires below this line. Rails is not loaded until this point!
+
+# Requires supporting ruby files with custom matchers and macros, etc, in
+# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
+# run as spec files by default. This means that files in spec/support that end
+# in _spec.rb will both be required and run as specs, causing the specs to be
+# run twice. It is recommended that you do not name files matching this glob to
+# end with _spec.rb. You can configure this pattern with the --pattern
+# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
+#
+# The following line is provided for convenience purposes. It has the downside
+# of increasing the boot-up time by auto-requiring all files in the support
+# directory. Alternatively, in the individual `*_spec.rb` files, manually
+# require only the support files necessary.
+#
+# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
+
+# Checks for pending migration and applies them before tests are run.
+# If you are not using ActiveRecord, you can remove this line.
+ActiveRecord::Migration.maintain_test_schema!
+
+RSpec.configure do |config|
+  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+  config.fixture_path = "#{::Rails.root}/test/fixtures"
+
+  # If you're not using ActiveRecord, or you'd prefer not to run each of your
+  # examples within a transaction, remove the following line or assign false
+  # instead of true.
+  config.use_transactional_fixtures = true
+
+  # RSpec Rails can automatically mix in different behaviours to your tests
+  # based on their file location, for example enabling you to call `get` and
+  # `post` in specs under `spec/controllers`.
+  #
+  # You can disable this behaviour by removing the line below, and instead
+  # explicitly tag your specs with their type, e.g.:
+  #
+  #     RSpec.describe UsersController, :type => :controller do
+  #       # ...
+  #     end
+  #
+  # The different available types are documented in the features, such as in
+  # https://relishapp.com/rspec/rspec-rails/docs
+  config.infer_spec_type_from_file_location!
+
+  # Filter lines from Rails gems in backtraces.
+  config.filter_rails_from_backtrace!
+  # arbitrary gems may also be filtered via:
+  # config.filter_gems_from_backtrace("gem name")
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..61e27385c3ed6390048ef9df5ae4434c1afc92a7
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,92 @@
+# This file was generated by the `rails generate rspec:install` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# The `.rspec` file also contains a few flags that are not defaults but that
+# users commonly want.
+#
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+  # rspec-expectations config goes here. You can use an alternate
+  # assertion/expectation library such as wrong or the stdlib/minitest
+  # assertions if you prefer.
+  config.expect_with :rspec do |expectations|
+    # This option will default to `true` in RSpec 4. It makes the `description`
+    # and `failure_message` of custom matchers include text for helper methods
+    # defined using `chain`, e.g.:
+    #     be_bigger_than(2).and_smaller_than(4).description
+    #     # => "be bigger than 2 and smaller than 4"
+    # ...rather than:
+    #     # => "be bigger than 2"
+    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+  end
+
+  # rspec-mocks config goes here. You can use an alternate test double
+  # library (such as bogus or mocha) by changing the `mock_with` option here.
+  config.mock_with :rspec do |mocks|
+    # Prevents you from mocking or stubbing a method that does not exist on
+    # a real object. This is generally recommended, and will default to
+    # `true` in RSpec 4.
+    mocks.verify_partial_doubles = true
+  end
+
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+  # These two settings work together to allow you to limit a spec run
+  # to individual examples or groups you care about by tagging them with
+  # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+  # get run.
+  config.filter_run :focus
+  config.run_all_when_everything_filtered = true
+
+  # Allows RSpec to persist some state between runs in order to support
+  # the `--only-failures` and `--next-failure` CLI options. We recommend
+  # you configure your source control system to ignore this file.
+  config.example_status_persistence_file_path = "spec/examples.txt"
+
+  # Limits the available syntax to the non-monkey patched syntax that is
+  # recommended. For more details, see:
+  #   - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
+  #   - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+  #   - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
+  config.disable_monkey_patching!
+
+  # Many RSpec users commonly either run the entire suite or an individual
+  # file, and it's useful to allow more verbose output when running an
+  # individual spec file.
+  if config.files_to_run.one?
+    # Use the documentation formatter for detailed output,
+    # unless a formatter has already been configured
+    # (e.g. via a command-line flag).
+    config.default_formatter = 'doc'
+  end
+
+  # Print the 10 slowest examples and example groups at the
+  # end of the spec run, to help surface which specs are running
+  # particularly slow.
+  config.profile_examples = 10
+
+  # Run specs in random order to surface order dependencies. If you find an
+  # order dependency and want to debug it, you can fix the order by providing
+  # the seed, which is printed after each run.
+  #     --seed 1234
+  config.order = :random
+
+  # Seed global randomization in this process using the `--seed` CLI option.
+  # Setting this allows you to use `--seed` to deterministically reproduce
+  # test failures related to randomization by passing the same `--seed` value
+  # as the one that triggered the failure.
+  Kernel.srand config.seed
+=end
+end
diff --git a/test/controllers/v1/institutions_controller_test.rb b/test/controllers/v1/institutions_controller_test.rb
index ba90ef5db6a83ec69f82c9c089401f0c5b55116f..be23eca891c65e89be0a3ae1cd7d7bd2cf631b86 100644
--- a/test/controllers/v1/institutions_controller_test.rb
+++ b/test/controllers/v1/institutions_controller_test.rb
@@ -9,6 +9,7 @@ class V1::InstitutionControllerTest < ActionController::TestCase
   end
 
   test 'should user show institution' do
+    auth_application
     ufpr = institutions(:ufpr)
     get :show, id: ufpr.id
     assert_response :ok
diff --git a/test/controllers/v1/licenses_controller_test.rb b/test/controllers/v1/licenses_controller_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6cd9d7a9347e87286ac40d67f80852d06311e095
--- /dev/null
+++ b/test/controllers/v1/licenses_controller_test.rb
@@ -0,0 +1,50 @@
+require 'test_helper'
+
+class V1::LicensesControllerTest < ActionController::TestCase
+  tests V1::LicensesController
+  include Devise::TestHelpers
+
+  setup do
+    @license = licenses(:one)
+  end
+
+  test "should get index" do
+    skip
+    get :index
+    assert_response :success
+    assert_not_nil assigns(:licenses)
+  end
+
+  test "should create license" do
+    auth_request users(:admin)
+
+    assert_difference('License.count') do
+      post :create, license: { description: @license.description, name: @license.name, url: @license.url, image_url: @license.image_url }
+    end
+
+    assert_response 201
+  end
+
+  test "should show license" do
+    skip
+    get :show, id: @license
+    assert_response :success
+  end
+
+  test "should update license" do
+    auth_request users(:admin)
+
+    put :update, id: @license, license: { description: @license.description, name: @license.name, url: @license.url, image_url: @license.image_url }
+    assert_response 204
+  end
+
+  test "should destroy license" do
+    auth_request users(:admin)
+
+    assert_difference('License.count', -1) do
+      delete :destroy, id: @license
+    end
+
+    assert_response 204
+  end
+end
diff --git a/test/controllers/v1/search_controller_test.rb b/test/controllers/v1/search_controller_test.rb
index f01d4994278c109a7c8cea7a55839ea822ee07b3..8fc542c7b351e365377ca11e4277d5322e640a3c 100644
--- a/test/controllers/v1/search_controller_test.rb
+++ b/test/controllers/v1/search_controller_test.rb
@@ -1,28 +1,35 @@
+require 'test_helper'
+
 class V1::SearchControllerTest < ActionController::TestCase
+  tests V1::SearchController
 
   setup do
-    LearningObject.reindex
-    LearningObject.searchkick_index.refresh
+    SearchService::SEARCH_CLASSES.each { |search_class| reindex search_class.constantize }
+    auth_application
   end
 
-  test 'should get index and return :ok' do
-    get :index, search_class: 'LearningObject'
-    assert_response :ok
+  test 'should search return :ok' do
+    SearchService::SEARCH_CLASSES.each do |search_class|
+      get :index, search_class: search_class
+      assert_response :ok
+    end
   end
 
-  test 'should get index and return :bad_request' do
-    get :index
+  test 'should search with invalid class and return :bad_request' do
+    get :index, search_class: 'invalid'
     assert_response :bad_request
   end
 
-  test 'should get autocomplete and return :ok' do
-    get :autocomplete, search_class: 'LearningObject'
-    assert_response :ok
+  test 'should autocomplete with invalid class and return :bad_request' do
+    get :autocomplete, search_class: 'invalid'
+    assert_response :bad_request
   end
 
-  test 'should get autocomplete and return :bad_request' do
-    get :autocomplete
-    assert_response :bad_request
+  private
+
+  def reindex(klass)
+    klass.reindex
+    klass.searchkick_index.refresh
   end
 
 end
diff --git a/test/fixtures/applications.yml b/test/fixtures/applications.yml
new file mode 100644
index 0000000000000000000000000000000000000000..190a8c980878489cff21c8824be220f25859eced
--- /dev/null
+++ b/test/fixtures/applications.yml
@@ -0,0 +1,5 @@
+test_app:
+  name: 'test app'
+  domain: 'test.host'
+  application_id: 'ffcb31a0-bacc-4f37-925c-656b3805095a'
+  user_id: john (User)
\ No newline at end of file
diff --git a/test/fixtures/learning_objects.yml b/test/fixtures/learning_objects.yml
index 531fe909669c2a7c973b137617425bf559256dfe..1dec107ce313f68f7044532a0448021d84d1c475 100644
--- a/test/fixtures/learning_objects.yml
+++ b/test/fixtures/learning_objects.yml
@@ -61,7 +61,7 @@ lo_metadata:
   id_dspace: '2'
   object_type: image
   language: portuguese
-  metadata:  '[{"key": "dc.creator", "value": "ufpr", "language": "nil"}]'
+  metadata:  '{"dc.creator": "ufpr"}'
 
 lo_metadata2:
   name: 'Institution Object 2'
@@ -70,7 +70,7 @@ lo_metadata2:
   id_dspace: '3'
   object_type: image
   language: portuguese
-  metadata:  '[{"key": "dc.creator", "value": "ufpr", "language": "nil"}]'
+  metadata:  '{"dc.creator": "ufpr"}'
 
 search:
   name: 'Teste'
diff --git a/test/fixtures/licenses.yml b/test/fixtures/licenses.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0d9a9e4790f4c916eb726c85610dbc31950bed49
--- /dev/null
+++ b/test/fixtures/licenses.yml
@@ -0,0 +1,13 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+  name: MyString
+  description: MyText
+  url: MyString
+  image_url: MyString
+
+two:
+  name: MyString
+  description: MyText
+  url: MyString
+  image_url: MyString
diff --git a/test/models/application_test.rb b/test/models/application_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f959b7a8b0f457cc11eedd3b6f1e3e0639c85ef5
--- /dev/null
+++ b/test/models/application_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class ApplicationTest < ActiveSupport::TestCase
+  should belong_to :user
+  should validate_presence_of(:domain)
+  should validate_presence_of(:application_id)
+end
diff --git a/test/models/collection_test.rb b/test/models/collection_test.rb
index 758411c545ad260d9420ec262d722139922ee98b..242f37dbf6ab6b9861e98ca460fce83feb480b72 100644
--- a/test/models/collection_test.rb
+++ b/test/models/collection_test.rb
@@ -47,6 +47,14 @@ class CollectionTest < ActiveSupport::TestCase
 
   include ::Portalmec::SociableTests
 
+  test 'should get all collections created this week' do
+    Collection.this_week.each {|o| assert_instance_of Collection, o}
+  end
+
+  test 'should get all collections created this month' do
+    Collection.this_month.each {|o| assert_instance_of Collection, o}
+  end
+
   protected
 
   def sociable_object
diff --git a/test/models/learning_object_test.rb b/test/models/learning_object_test.rb
index abbf05d0474e49485602b83634260826630ed21e..f2924dc9b678914b0cae67e95fa510379aaef648 100644
--- a/test/models/learning_object_test.rb
+++ b/test/models/learning_object_test.rb
@@ -56,6 +56,29 @@ class LearningObjectTest < ActiveSupport::TestCase
 
   include ::Portalmec::SociableTests
 
+  test 'should search data return a hash' do
+    learning_object = learning_objects(:lo_complete)
+    assert_equal learning_object.search_data, {
+        name: 'Institution Object 1',
+        description: 'Testing',
+        author: 'Mauricio',
+        object_type: 'Imagem',
+        score: learning_object.score,
+        published_at: learning_object.published_at,
+        tags: learning_object.tags.map(&:name),
+        source: nil,
+        state: learning_object.state
+    }
+  end
+
+  test 'should get all learning objects created this week' do
+    LearningObject.this_week.each {|o| assert_instance_of LearningObject, o}
+  end
+
+  test 'should get all learning objects created this month' do
+    LearningObject.this_month.each {|o| assert_instance_of LearningObject, o}
+  end
+
   protected
 
   def sociable_object
diff --git a/test/models/license_test.rb b/test/models/license_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c56bac9d45cc94bcd2506e20ffad3061998c4f41
--- /dev/null
+++ b/test/models/license_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class LicenseTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
index bcf2ab2b5f92ecd06ccc124726256615508991d2..86e0c5ce438ad0e45dbb687c3fe9e4350ce7b1cf 100644
--- a/test/models/user_test.rb
+++ b/test/models/user_test.rb
@@ -51,6 +51,7 @@ class UserTest < ActiveSupport::TestCase
   should have_many :shares
   should have_many :follows
   should have_many :reviews
+  should have_many :applications
 
   test 'an user can follow another user' do
     john = users(:john)
diff --git a/test/services/search_service_test.rb b/test/services/search_service_test.rb
index 3733c0418a7ca9acda375eff3cdd99e07d1af071..35c7a30fba49cd3fda4b10335831adb76fcf2d17 100644
--- a/test/services/search_service_test.rb
+++ b/test/services/search_service_test.rb
@@ -1,69 +1,66 @@
 require 'test_helper'
 
 class SearchServiceTest < ActiveSupport::TestCase
-
   test 'fetch learning object with all search params' do
     reindex LearningObject
 
-    service = SearchService.new(Search.new(los_complete_search), users(:john))
-    assert_equal [learning_objects(:search)], service.fetch
+    search = SearchService.search(Search.new(los_complete_search), users(:john))
+    search.each {|o| assert_instance_of LearningObject, o}
   end
 
   test 'fetch all public collections' do
     reindex Collection
 
-    service = SearchService.new(Search.new(collections_search), users(:john))
-    assert_equal [collections(:ufpr)], service.fetch
+    search = SearchService.search(Search.new(collections_search), users(:john))
+    search.each {|o| assert_instance_of Collection, o}
   end
 
   test 'fetch users named john' do
     reindex User
 
-    service = SearchService.new(Search.new(users_john_search), users(:john))
-    assert_equal [users(:john), users(:one)], service.fetch
+    search = SearchService.search(Search.new(users_john_search), users(:john))
+    assert_equal [users(:john), users(:one)], search
   end
 
   test 'autocomplete users named john' do
     reindex User
 
-    service = SearchService.new(Search.new(users_john), users(:john))
-    assert_equal users_autocomplete_hashes([users(:john),users(:one)]), service.autocomplete
+    search = SearchService.autocomplete(Search.new(users_john), users(:john))
+    assert_equal users_autocomplete_hashes([users(:john), users(:one)]), search
   end
 
   private
 
   def los_complete_search
-    default_params.merge({
-      :query => 'teste', 
-      :search_class => 'LearningObject', 
-      :tags => ['Matemática'],
-      :types => ['Imagem'], 
-      :sources => ['UFPR institution']
-    })
+    default_params.merge(
+      query: 'teste',
+      search_class: 'LearningObject',
+      tags: ['Matemática'],
+      types: ['Imagem'],
+      sources: ['UFPR institution']
+    )
   end
 
   def collections_search
-    default_params.merge({
-      :search_class => 'Collection'
-    })
+    default_params.merge(search_class: 'Collection')
   end
 
   def users_john_search
     default_params.merge(users_john)
   end
-  
+
   def users_john
     {
-      :query => 'John',
-      :search_class => 'User'
+      query: 'John',
+      search_class: 'User'
     }
   end
 
   def default_params
     {
-      :page => 1,
-      :results_per_page => 10,
-      :order => 'score'
+      page: 1,
+      results_per_page: 10,
+      order: 'score'
     }
   end
 
@@ -72,17 +69,14 @@ class SearchServiceTest < ActiveSupport::TestCase
     klass.searchkick_index.refresh
   end
 
-  def users_autocomplete_hashes(users=[])
-    hashes = []
-    users.each do |user|
-      hash = {}
-      hash["id"] = user.id
-      hash["name"] = user.name
-      hash["type"] = "User"
-      hash["thumbnail"] = user.avatar.url(:thumb)
-      hashes << hash
+  def users_autocomplete_hashes(users = [])
+    users.map do |user|
+      {
+        id: user.id,
+        name: user.name,
+        type: 'User',
+        thumbnail: user.avatar.url(:thumb)
+      }
     end
-    hashes
   end
-
-end
\ No newline at end of file
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index dfe4b91c2b026a7d121538f11343b7efe9a425de..0e357f9b2cd176faa6ddcdff218c592c8e9a0b5d 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -23,10 +23,15 @@ class ActiveSupport::TestCase
 
   # authenticate requests using devise_token_auth
   def auth_request(user)
+    auth_application
     sign_in user
     request.headers.merge!(user.create_new_auth_token)
   end
 
+  def auth_application
+    @request.headers['PortalMEC-AppID'] = applications(:test_app).application_id
+  end
+
   def mock
     MiniTest::Mock.new
   end