hackedteam/rcs-db

View on GitHub
lib/rcs-db/rest/entity.rb

Summary

Maintainability
C
1 day
Test Coverage
#
# Controller for Entity
#

require_relative '../link_manager'

module RCS
module DB

class EntityController < RESTController

  def index
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do
      fields = ["type", "level", "name", "desc", "path", "photos", 'position', 'position_attr', 'links', 'children', 'stand_for']
      filter = {'user_ids' => @session.user[:_id], 'level' => {'$ne' => :ghost}}
      fields = fields.inject({}) { |h, f| h[f] = 1; h }

      entities = ::Entity.collection.find(filter).select(fields).entries.map! do |ent|
        link_size = ent['links'] ? ent['links'].keep_if {|x| x['level'] != :ghost}.size : 0
        # don't send ghost links
        ent['links'].keep_if {|l| l['level'] != :ghost} if ent['links']
        ent['num_links'] = link_size
        ent['position'] = {longitude: ent['position'][0], latitude: ent['position'][1]} if ent['position'].is_a? Array
        ent
      end

      ok(entities)
    end
  end

  def flow
    require_auth_level :view

    mongoid_query do
      # Check the presence of the required params
      %w[ids from to].each do |param_name|
        return bad_request('INVALID_OPERATION') if @params[param_name].blank?
      end

      return ok Entity.flow(@params)
    end
  end

  def positions
    require_auth_level :view

    mongoid_query do
      ids = [@params['ids']].flatten
      from = @params['from'].to_i
      to = @params['to'].to_i

      if ids.blank? || from <= 0 || to <= 0 || to < from || to - from >= 1.year
        trace :error, "Cannot retreive positions flow of #{ids.size} entities from \"#{from.inspect}\" to \"#{to.inspect}\". Invalid parameters."
        return bad_request('INVALID_OPERATION')
      end

      options = {summary: @params['summary']}

      ok Entity.positions_flow(ids, from, to, options)
    end
  end

  def show
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do
      ent = ::Entity.where(_id: @params['_id']).in(user_ids: [@session.user[:_id]]).only(['type', 'level', 'name', 'desc', 'path', 'photos', 'position', 'position_attr', 'handles', 'links'])
      entity = ent.first
      return not_found if entity.nil?
      return not_found if entity.level == :ghost

      # convert position to hash {:latitude, :longitude}
      entity = entity.as_document
      entity['position'] = {longitude: entity['position'][0], latitude: entity['position'][1]} if entity['position'].is_a? Array

      # don't send ghost links
      entity['links'].keep_if {|l| l['level'] != :ghost} if entity['links']

      ok(entity)
    end
  end

  def create
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :intelligence

    mongoid_query do

      operation = ::Item.operations.find(@params['operation'])
      return bad_request('INVALID_OPERATION') if operation.nil?

      e = ::Entity.create! do |doc|
        doc[:path] = [operation._id]
        doc.users = operation.users
        doc[:name] = @params['name']
        doc[:type] = @params['type'].to_sym
        doc[:desc] = @params['desc']
        doc[:level] = :manual

        # when type is :position
        if @params['position'] and @params['position'].size > 0
          doc.position = [@params['position']['longitude'].to_f, @params['position']['latitude'].to_f]
          doc.position_attr[:accuracy] = @params['position_attr']['accuracy'].to_i
        end

        # when type is :group
        if @params['children']
          doc.children = @params['children'].map { |id| Moped::BSON::ObjectId(id) }
        end
      end

      Audit.log :actor => @session.user[:name], :action => 'entity.create', :_entity => e, :desc => "Created a new entity named #{e.name}"

      # convert position to hash {:latitude, :longitude}
      entity = e.as_document
      entity['position'] = {longitude: entity['position'][0], latitude: entity['position'][1]}  if entity['position'].is_a? Array
      entity.delete('analyzed')

      ok(entity)
    end
  end

  def update
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do
      entity = ::Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      @params.delete('_id')

      if @params['position'] and @params['position'].size > 0
        entity.position = [@params['position']['longitude'].to_f, @params['position']['latitude'].to_f]
        entity.position_attr[:accuracy] = @params['position_attr']['accuracy'].to_i
        entity.save
        @params.delete('position')
        @params.delete('position_attr')
      end

      @params.each_pair do |key, value|
        if key == 'path'
          value.collect! {|x| Moped::BSON::ObjectId(x)}
        end
        if entity[key.to_s] != value and not key['_ids']
          Audit.log :actor => @session.user[:name], :action => 'entity.update', :_entity => entity, :desc => "Updated '#{key}' to '#{value}' for entity #{entity.name}"
        end
      end

      entity.update_attributes(@params)

      return ok(entity)
    end
  end

  def destroy
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])

      # entity created by target cannot be deleted manually, they will disappear with their target
      return conflict('CANNOT_DELETE_TARGET_ENTITY') if e.type == :target

      Audit.log :actor => @session.user[:name], :action => 'entity.destroy', :_entity => e, :desc => "Deleted the entity #{e.name}"
      e.destroy

      return ok
    end
  end

  def add_photo
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@request[:content]['_id'])
      id = e.add_photo(@request[:content]['content'])

      Audit.log :actor => @session.user[:name], :action => 'entity.add_photo', :_entity => e, :desc => "Added a new photo to #{e.name}"

      return ok(id)
    end
  end

  def add_photo_from_grid
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      file = GridFS.get(@params['_grid'], @params['target_id'])
      id = e.add_photo(file.read)

      Audit.log :actor => @session.user[:name], :action => 'entity.add_photo', :_entity => e, :desc => "Added a new photo to #{e.name}"

      return ok(id)
    end
  end

  def del_photo
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      return not_found() unless e.del_photo(@params['photo_id'])

      Audit.log :actor => @session.user[:name], :action => 'entity.del_photo', :_entity => e, :desc => "Deleted a photo from #{e.name}"

      return ok
    end
  end

  def add_handle
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      e.handles.create!(level: :manual, type: @params['type'].downcase, name: @params['name'], handle: @params['handle'].downcase)

      Audit.log :actor => @session.user[:name], :action => 'entity.add_handle', :_entity => e, :desc => "Added a the handle '#{@params['handle'].downcase}' to #{e.name}"

      return ok
    end
  end

  def del_handle
    require_auth_level :view
    require_auth_level :view_profiles

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      e.handles.find(@params['handle_id']).destroy

      Audit.log :actor => @session.user[:name], :action => 'entity.del_handle', :_entity => e, :desc => "Deleted an handle from #{e.name}"

      return ok
    end
  end

  def promote_to_target
    require_auth_level :admin
    require_auth_level :admin_targets
    require_auth_level :view_profiles
    require_auth_level :view

    mongoid_query do
      entity = Entity.persons.any_in(user_ids: [@session.user[:_id]]).where(_id: @params['_id']).first
      return bad_request('INVALID_OPERATION') unless entity

      entity.promote_to_target

      operation = ::Item.operations.find(entity.path.first)

      Audit.log :actor => @session.user[:name],
                :action => "target.create",
                :operation_name => operation.name,
                :target_name => entity.name,
                :desc => "Created target '#{entity.name}' (person promoted to target)"

      return ok
    end
  end

  def most_contacted
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :correlation

    mongoid_query do
      entity = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      return conflict('NO_AGGREGATES_FOR_ENTITY') unless entity.type.eql? :target

      # extract the most contacted peers for this entity
      results = Aggregate.most_contacted(entity.path.last.to_s, @params)

      return ok(results)
    end
  end

  def most_visited_urls
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :correlation

    mongoid_query do
      entity = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      return conflict('NO_AGGREGATES_FOR_ENTITY') unless entity.type.eql? :target

      # extract the most contacted peers for this entity
      results = Aggregate.most_visited_urls(entity.path.last.to_s, @params)

      return ok(results)
    end
  end

  def most_visited_places
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :correlation

    mongoid_query do
      entity = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      return conflict('NO_AGGREGATES_FOR_ENTITY') unless entity.type.eql? :target

      # extract the most contacted peers for this entity
      results = Aggregate.most_visited_places(entity.path.last.to_s, @params)

      return ok(results)
    end
  end

  def add_link
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :intelligence

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      e2 = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['entity'])

      return not_found() if e.nil? or e2.nil?

      link = RCS::DB::LinkManager.instance.add_link(from: e, to: e2, level: :manual, type: @params['type'].to_sym, versus: @params['versus'].to_sym, rel: @params['rel'])

      Audit.log :actor => @session.user[:name], :action => 'entity.add_link', :_entity => e, :desc => "Added a new link between #{e.name} and #{e2.name}"
      Audit.log :actor => @session.user[:name], :action => 'entity.add_link', :_entity => e2, :desc => "Added a new link between #{e2.name} and #{e.name}"

      return ok(link)
    end
  end

  def edit_link
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :intelligence

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      e2 = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['entity'])

      return not_found() if e.nil? or e2.nil?

      link = RCS::DB::LinkManager.instance.edit_link(from: e, to: e2, type: @params['type'].to_sym, versus: @params['versus'].to_sym, rel: @params['rel'])

      Audit.log :actor => @session.user[:name], :action => 'entity.add_link', :_entity => e, :desc => "Edited link between #{e.name} and #{e2.name}"
      Audit.log :actor => @session.user[:name], :action => 'entity.add_link', :_entity => e2, :desc => "Edited link between #{e2.name} and #{e.name}"

      return ok(link)
    end
  end

  def del_link
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :intelligence

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      e2 = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['entity'])

      return not_found() if e.nil? or e2.nil?

      RCS::DB::LinkManager.instance.del_link(from: e, to: e2)

      Audit.log :actor => @session.user[:name], :action => 'entity.del_link', :_entity => e, :desc => "Deleted a link between #{e.name} and #{e2.name}"
      Audit.log :actor => @session.user[:name], :action => 'entity.del_link', :_entity => e2, :desc => "Deleted a link between #{e2.name} and #{e.name}"

      return ok
    end
  end

  def merge
    require_auth_level :view
    require_auth_level :view_profiles

    return conflict('LICENSE_LIMIT_REACHED') unless LicenseManager.instance.check :intelligence

    mongoid_query do

      e = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['_id'])
      e2 = Entity.any_in(user_ids: [@session.user[:_id]]).find(@params['entity'])

      return not_found() if e.nil? or e2.nil?

      e.merge(e2)

      Audit.log :actor => @session.user[:name], :action => 'entity.merge', :_entity => e, :desc => "Merged entity '#{e.name}' and '#{e2.name}'"
      Audit.log :actor => @session.user[:name], :action => 'entity.merge', :_entity => e2, :desc => "Merged entity '#{e2.name}' and '#{e.name}'"

      return ok(e)
    end
  end

end

end #DB::
end #RCS::