diff --git a/Gemfile b/Gemfile index eec31832..b7ea08e9 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,8 @@ gem 'devise' gem 'redis' gem 'pg' gem 'pundit' +gem 'cancan' +gem 'pundit_extra' gem 'formula' gem 'formtastic' gem 'json' @@ -15,6 +17,8 @@ gem 'best_in_place' #in-place editing gem 'kaminari' # pagination gem 'uservoice-ruby' gem 'dotenv' +gem 'snorlax', '~> 0.1.3' +gem 'active_model_serializers', '~> 0.8.1' gem 'paperclip' gem 'aws-sdk', '< 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 2f10214a..a2a3b031 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -20,6 +20,8 @@ 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.8.3) + activemodel (>= 3.0) activejob (4.2.4) activesupport (= 4.2.4) globalid (>= 0.3.0) @@ -43,8 +45,8 @@ GEM aws-sdk-v1 (1.66.0) json (~> 1.4) nokogiri (>= 1.4.4) - bcrypt (3.1.10) - best_in_place (3.0.3) + bcrypt (3.1.11) + best_in_place (3.1.0) actionpack (>= 3.2) railties (>= 3.2) better_errors (2.1.1) @@ -54,23 +56,24 @@ GEM binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) - byebug (5.0.0) - columnize (= 0.9.0) + byebug (8.2.2) + cancan (1.6.10) + cancancan (1.10.1) climate_control (0.0.3) activesupport (>= 3.0) - cocaine (0.5.7) + cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) - coderay (1.1.0) - coffee-rails (4.1.0) + coderay (1.1.1) + coffee-rails (4.1.1) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.0) + railties (>= 4.0.0, < 5.1.x) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1.1) - columnize (0.9.0) + coffee-script-source (1.10.0) + concurrent-ruby (1.0.1) debug_inspector (0.0.2) - devise (3.5.2) + devise (3.5.6) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 3.2.6, < 5) @@ -79,13 +82,13 @@ GEM warden (~> 1.2.3) diff-lcs (1.2.5) docile (1.1.5) - dotenv (2.0.2) + dotenv (2.1.0) erubis (2.7.0) execjs (2.6.0) ezcrypto (0.7.2) factory_girl (4.5.0) activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) + factory_girl_rails (4.6.0) factory_girl (~> 4.5.0) railties (>= 3.0.0) formtastic (3.1.3) @@ -95,17 +98,17 @@ GEM globalid (0.3.6) activesupport (>= 4.1.0) i18n (0.7.0) - jbuilder (2.3.2) - activesupport (>= 3.0.0, < 5) + jbuilder (2.4.1) + activesupport (>= 3.0.0, < 5.1) multi_json (~> 1.2) - jquery-rails (4.0.5) - rails-dom-testing (~> 1.0) + jquery-rails (4.1.1) + rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) jquery-ui-rails (5.0.5) railties (>= 3.2.16) json (1.8.3) - json-schema (2.6.0) + json-schema (2.6.1) addressable (~> 2.3.8) kaminari (0.16.3) actionpack (>= 3.0.0) @@ -115,33 +118,34 @@ GEM mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (2.6.2) + mime-types (2.99.1) mimemagic (0.3.0) - mini_portile (0.6.2) - minitest (5.8.2) + mini_portile2 (2.0.0) + minitest (5.8.4) multi_json (1.11.2) - nokogiri (1.6.6.2) - mini_portile (~> 0.6.0) - oauth (0.4.7) + nokogiri (1.6.7.2) + mini_portile2 (~> 2.0.0.rc2) + oauth (0.5.1) orm_adapter (0.5.0) - paperclip (4.3.1) + paperclip (4.3.5) activemodel (>= 3.2.0) activesupport (>= 3.2.0) cocaine (~> 0.5.5) mime-types mimemagic (= 0.3.0) - pg (0.18.3) + pg (0.18.4) pry (0.10.3) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - pry-byebug (3.2.0) - byebug (~> 5.0) + pry-byebug (3.3.0) + byebug (~> 8.0) pry (~> 0.10) pry-rails (0.3.4) pry (>= 0.9.10) pundit (1.1.0) activesupport (>= 3.0.0) + pundit_extra (0.1.1) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) rack (1.6.4) @@ -164,66 +168,70 @@ GEM activesupport (>= 4.2.0.beta, < 5.0) nokogiri (~> 1.6.0) rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.2) + rails-html-sanitizer (1.0.3) loofah (~> 2.0) rails3-jquery-autocomplete (1.0.15) rails (>= 3.2) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging - rails_serve_static_assets (0.0.4) + rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.4) railties (4.2.4) actionpack (= 4.2.4) activesupport (= 4.2.4) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (10.4.2) - redis (3.2.1) - responders (2.1.0) - railties (>= 4.2.0, < 5) - rspec-core (3.3.2) - rspec-support (~> 3.3.0) - rspec-expectations (3.3.1) + rake (11.1.0) + redis (3.2.2) + responders (2.1.1) + railties (>= 4.2.0, < 5.1) + 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.3.0) - rspec-mocks (3.3.2) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.3.0) - rspec-rails (3.3.3) + 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.3.0) - rspec-expectations (~> 3.3.0) - rspec-mocks (~> 3.3.0) - rspec-support (~> 3.3.0) - rspec-support (3.3.0) - sass (3.4.19) + 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) + sass (3.4.21) sass-rails (5.0.4) railties (>= 4.0.0, < 5.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - shoulda-matchers (3.0.1) + shoulda-matchers (3.1.1) activesupport (>= 4.0.0) - simplecov (0.11.1) + simplecov (0.11.2) docile (~> 1.1.0) json (~> 1.8) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) - sprockets (3.4.0) + snorlax (0.1.4) + cancancan (~> 1.10.1) + rails (> 4.1) + sprockets (3.5.2) + concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (2.3.3) - actionpack (>= 3.0) - activesupport (>= 3.0) - sprockets (>= 2.8, < 4.0) + sprockets-rails (3.0.4) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) thor (0.19.1) thread_safe (0.3.5) - tilt (2.0.1) - tunemygc (1.0.61) + tilt (2.0.2) + tunemygc (1.0.65) tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.2) @@ -233,17 +241,19 @@ GEM ezcrypto (>= 0.7.2) json (>= 1.7.5) oauth (>= 0.4.7) - warden (1.2.3) + warden (1.2.6) rack (>= 1.0) PLATFORMS ruby DEPENDENCIES + active_model_serializers (~> 0.8.1) aws-sdk (< 2.0) best_in_place better_errors binding_of_caller + cancan coffee-rails devise dotenv @@ -261,6 +271,7 @@ DEPENDENCIES pry-byebug pry-rails pundit + pundit_extra quiet_assets rails (= 4.2.4) rails3-jquery-autocomplete @@ -270,6 +281,10 @@ DEPENDENCIES sass-rails shoulda-matchers simplecov + snorlax (~> 0.1.3) tunemygc uglifier uservoice-ruby + +BUNDLED WITH + 1.11.2 diff --git a/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb b/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb index 27812c57..00460ad4 100644 --- a/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb +++ b/app/assets/javascripts/src/Metamaps.GlobalUI.js.erb @@ -48,6 +48,7 @@ $(document).ready(function () { // this runs the init function within each sub-object on the Metamaps one if (Metamaps.hasOwnProperty(prop) && + Metamaps[prop] != null && Metamaps[prop].hasOwnProperty('init') && typeof (Metamaps[prop].init) == 'function' ) { diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/app/assets/javascripts/src/Metamaps.js.erb index 5a6c5955..ff6d57e6 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/app/assets/javascripts/src/Metamaps.js.erb @@ -17,12 +17,10 @@ var labelType, useGradients, nativeTextSupport, animate; })(); // TODO eliminate these 4 top-level variables -Metamaps = { - panningInt: null, - tempNode: null, - tempInit: false, - tempNode2: null -} +Metamaps.panningInt = null; +Metamaps.tempNode = null; +Metamaps.tempInit = false; +Metamaps.tempNode2 = null; Metamaps.Settings = { embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages diff --git a/app/controllers/api/mappings_controller.rb b/app/controllers/api/mappings_controller.rb new file mode 100644 index 00000000..426c9dbe --- /dev/null +++ b/app/controllers/api/mappings_controller.rb @@ -0,0 +1,3 @@ +class Api::MappingsController < API::RestfulController + +end diff --git a/app/controllers/api/maps_controller.rb b/app/controllers/api/maps_controller.rb new file mode 100644 index 00000000..7b805280 --- /dev/null +++ b/app/controllers/api/maps_controller.rb @@ -0,0 +1,3 @@ +class Api::MapsController < API::RestfulController + +end diff --git a/app/controllers/api/restful_controller.rb b/app/controllers/api/restful_controller.rb new file mode 100644 index 00000000..06396e3d --- /dev/null +++ b/app/controllers/api/restful_controller.rb @@ -0,0 +1,49 @@ +class API::RestfulController < ActionController::Base + include Pundit + include PunditExtra + + snorlax_used_rest! + + rescue_from(Pundit::NotAuthorizedError) { |e| respond_with_standard_error e, 403 } + load_and_authorize_resource only: [:show, :update, :destroy] + + def create + authorize resource_class + instantiate_resouce + resource.user = current_user + create_action + respond_with_resource + end + + private + + def resource_serializer + "new_#{resource_name}_serializer".camelize.constantize + end + + def accessible_records + if current_user + visible_records + else + public_records + end + end + + def current_user + super || token_user || nil + end + + def token_user + authenticate_with_http_token do |token, options| + access_token = Token.find_by_token(token) + if access_token + @token_user ||= access_token.user + end + end + end + + def permitted_params + @permitted_params ||= PermittedParams.new(params) + end + +end diff --git a/app/controllers/api/synapses_controller.rb b/app/controllers/api/synapses_controller.rb new file mode 100644 index 00000000..f133ffd0 --- /dev/null +++ b/app/controllers/api/synapses_controller.rb @@ -0,0 +1,3 @@ +class Api::SynapsesController < API::RestfulController + +end diff --git a/app/controllers/api/tokens_controller.rb b/app/controllers/api/tokens_controller.rb new file mode 100644 index 00000000..3fcca370 --- /dev/null +++ b/app/controllers/api/tokens_controller.rb @@ -0,0 +1,19 @@ +class Api::TokensController < API::RestfulController + + def my_tokens + raise Pundit::NotAuthorizedError.new unless current_user + instantiate_collection page_collection: false, timeframe_collection: false + respond_with_collection + end + + private + + def resource_serializer + "#{resource_name}_serializer".camelize.constantize + end + + def visible_records + current_user.tokens + end + +end diff --git a/app/controllers/api/topics_controller.rb b/app/controllers/api/topics_controller.rb new file mode 100644 index 00000000..f3633544 --- /dev/null +++ b/app/controllers/api/topics_controller.rb @@ -0,0 +1,3 @@ +class Api::TopicsController < API::RestfulController + +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d030c6e6..4388337e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,6 +7,10 @@ class ApplicationController < ActionController::Base before_action :get_invite_link after_action :allow_embedding + def default_serializer_options + { root: false } + end + # this is for global login include ContentHelper diff --git a/app/models/mapping.rb b/app/models/mapping.rb index d034de1c..1a37f490 100644 --- a/app/models/mapping.rb +++ b/app/models/mapping.rb @@ -25,5 +25,5 @@ class Mapping < ActiveRecord::Base def as_json(options={}) super(:methods =>[:user_name, :user_image]) end - + end diff --git a/app/models/permitted_params.rb b/app/models/permitted_params.rb new file mode 100644 index 00000000..a49ed648 --- /dev/null +++ b/app/models/permitted_params.rb @@ -0,0 +1,33 @@ +class PermittedParams < Struct.new(:params) + + %w[map synapse topic mapping token].each do |kind| + define_method(kind) do + permitted_attributes = self.send("#{kind}_attributes") + params.require(kind).permit(*permitted_attributes) + end + alias_method :"api_#{kind}", kind.to_sym + end + + alias :read_attribute_for_serialization :send + + def token_attributes + [:description] + end + + def map_attributes + [:name, :desc, :permission, :arranged] + end + + def synapse_attributes + [:desc, :category, :weight, :permission, :node1_id, :node2_id] + end + + def topic_attributes + [:name, :desc, :link, :permission, :metacode_id] + end + + def mapping_attributes + [:xloc, :yloc, :map_id, :mappable_type, :mappable_id] + end + +end diff --git a/app/models/synapse.rb b/app/models/synapse.rb index 4807d7ab..540376bb 100644 --- a/app/models/synapse.rb +++ b/app/models/synapse.rb @@ -10,6 +10,8 @@ class Synapse < ActiveRecord::Base validates :desc, length: { minimum: 0, allow_nil: false } validates :permission, presence: true + validates :node1_id, presence: true + validates :node2_id, presence: true validates :permission, inclusion: { in: Perm::ISSIONS.map(&:to_s) } validates :category, inclusion: { in: ['from-to', 'both'], allow_nil: true } diff --git a/app/models/token.rb b/app/models/token.rb new file mode 100644 index 00000000..15bdca79 --- /dev/null +++ b/app/models/token.rb @@ -0,0 +1,11 @@ +class Token < ActiveRecord::Base + belongs_to :user + + before_create :generate_token + + private + def generate_token + self.token = SecureRandom.uuid.gsub(/\-/,'') + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index bd3bf477..50493a55 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,6 +6,7 @@ class User < ActiveRecord::Base has_many :synapses has_many :maps has_many :mappings + has_many :tokens after_create :generate_code diff --git a/app/policies/map_policy.rb b/app/policies/map_policy.rb index 50123877..1594e6d9 100644 --- a/app/policies/map_policy.rb +++ b/app/policies/map_policy.rb @@ -1,7 +1,11 @@ class MapPolicy < ApplicationPolicy class Scope < Scope def resolve - scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) + if user + scope.where('maps.permission IN (?) OR maps.user_id = ?', ["public", "commons"], user.id) + else + scope.where('maps.permission IN (?)', ["public", "commons"]) + end end end diff --git a/app/serializers/new_map_serializer.rb b/app/serializers/new_map_serializer.rb new file mode 100644 index 00000000..9b2ff400 --- /dev/null +++ b/app/serializers/new_map_serializer.rb @@ -0,0 +1,16 @@ +class NewMapSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :name, + :desc, + :permission, + :screenshot, + :created_at, + :updated_at + + has_many :topics, serializer: NewTopicSerializer + has_many :synapses, serializer: NewSynapseSerializer + has_many :mappings, serializer: NewMappingSerializer + has_many :contributors, root: :users, serializer: NewUserSerializer + +end diff --git a/app/serializers/new_mapping_serializer.rb b/app/serializers/new_mapping_serializer.rb new file mode 100644 index 00000000..4e65e161 --- /dev/null +++ b/app/serializers/new_mapping_serializer.rb @@ -0,0 +1,19 @@ +class NewMappingSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :xloc, + :yloc, + :created_at, + :updated_at, + :mappable_id, + :mappable_type + + has_one :user, serializer: NewUserSerializer + has_one :map, serializer: NewMapSerializer + + def filter(keys) + keys.delete(:xloc) unless object.mappable_type == "Topic" + keys.delete(:yloc) unless object.mappable_type == "Topic" + keys + end +end diff --git a/app/serializers/new_metacode_serializer.rb b/app/serializers/new_metacode_serializer.rb new file mode 100644 index 00000000..e664e7ea --- /dev/null +++ b/app/serializers/new_metacode_serializer.rb @@ -0,0 +1,7 @@ +class NewMetacodeSerializer < ActiveModel::Serializer + attributes :id, + :name, + :manual_icon, + :color, + :aws_icon +end diff --git a/app/serializers/new_synapse_serializer.rb b/app/serializers/new_synapse_serializer.rb new file mode 100644 index 00000000..b145d605 --- /dev/null +++ b/app/serializers/new_synapse_serializer.rb @@ -0,0 +1,15 @@ +class NewSynapseSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :desc, + :category, + :weight, + :permission, + :created_at, + :updated_at + + has_one :topic1, root: :topics, serializer: NewTopicSerializer + has_one :topic2, root: :topics, serializer: NewTopicSerializer + has_one :user, serializer: NewUserSerializer + +end diff --git a/app/serializers/new_topic_serializer.rb b/app/serializers/new_topic_serializer.rb new file mode 100644 index 00000000..cdbbedf9 --- /dev/null +++ b/app/serializers/new_topic_serializer.rb @@ -0,0 +1,14 @@ +class NewTopicSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :name, + :desc, + :link, + :permission, + :created_at, + :updated_at + + has_one :user, serializer: NewUserSerializer + has_one :metacode, serializer: NewMetacodeSerializer + +end diff --git a/app/serializers/new_user_serializer.rb b/app/serializers/new_user_serializer.rb new file mode 100644 index 00000000..45be36b0 --- /dev/null +++ b/app/serializers/new_user_serializer.rb @@ -0,0 +1,15 @@ +class NewUserSerializer < ActiveModel::Serializer + attributes :id, + :name, + :avatar, + :is_admin, + :generation + + def avatar + object.image.url(:sixtyfour) + end + + def is_admin + object.admin + end +end diff --git a/app/serializers/token_serializer.rb b/app/serializers/token_serializer.rb new file mode 100644 index 00000000..8eed535a --- /dev/null +++ b/app/serializers/token_serializer.rb @@ -0,0 +1,10 @@ +class TokenSerializer < ActiveModel::Serializer + embed :ids, include: true + attributes :id, + :token, + :description, + :user_id, + :created_at, + :updated_at + +end diff --git a/config/routes.rb b/config/routes.rb index 76d281ce..b9be5288 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,16 @@ Metamaps::Application.routes.draw do get 'search/mappers', to: 'main#searchmappers', as: :searchmappers get 'search/synapses', to: 'main#searchsynapses', as: :searchsynapses + namespace :api, path: '/api/v1', defaults: {format: :json} do + resources :maps, only: [:create, :show, :update, :destroy] + resources :synapses, only: [:create, :show, :update, :destroy] + resources :topics, only: [:create, :show, :update, :destroy] + resources :mappings, only: [:create, :show, :update, :destroy] + resources :tokens, only: [ :create, :destroy] do + get :my_tokens, on: :collection + end + end + resources :mappings, except: [:index, :new, :edit] resources :metacode_sets, :except => [:show] resources :metacodes, :except => [:show, :destroy] diff --git a/db/migrate/20160310200131_create_tokens.rb b/db/migrate/20160310200131_create_tokens.rb new file mode 100644 index 00000000..7b9272a5 --- /dev/null +++ b/db/migrate/20160310200131_create_tokens.rb @@ -0,0 +1,11 @@ +class CreateTokens < ActiveRecord::Migration + def change + create_table :tokens do |t| + t.string :token + t.string :description + t.references :user, index: true, foreign_key: true + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e6a9bd11..334fd4ad 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160223061711) do +ActiveRecord::Schema.define(version: 20160310200131) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -117,6 +117,16 @@ ActiveRecord::Schema.define(version: 20160223061711) do add_index "synapses", ["node2_id"], name: "index_synapses_on_node2_id", using: :btree add_index "synapses", ["user_id"], name: "index_synapses_on_user_id", using: :btree + create_table "tokens", force: :cascade do |t| + t.string "token" + t.string "description" + t.integer "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "tokens", ["user_id"], name: "index_tokens_on_user_id", using: :btree + create_table "topics", force: :cascade do |t| t.text "name" t.text "desc" @@ -171,4 +181,5 @@ ActiveRecord::Schema.define(version: 20160223061711) do add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + add_foreign_key "tokens", "users" end diff --git a/spec/models/token_spec.rb b/spec/models/token_spec.rb new file mode 100644 index 00000000..18bba17d --- /dev/null +++ b/spec/models/token_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Token, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end