Merge pull request #481 from metamaps/feature/api

quietly release a token based metamaps api just for maps, topics, synapses, and mappings
This commit is contained in:
Connor Turland 2016-03-13 02:29:44 +11:00
commit 7ff24fb3b6
28 changed files with 352 additions and 66 deletions

View file

@ -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'

View file

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

View file

@ -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'
) {

View file

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

View file

@ -0,0 +1,3 @@
class Api::MappingsController < API::RestfulController
end

View file

@ -0,0 +1,3 @@
class Api::MapsController < API::RestfulController
end

View file

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

View file

@ -0,0 +1,3 @@
class Api::SynapsesController < API::RestfulController
end

View file

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

View file

@ -0,0 +1,3 @@
class Api::TopicsController < API::RestfulController
end

View file

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

View file

@ -25,5 +25,5 @@ class Mapping < ActiveRecord::Base
def as_json(options={})
super(:methods =>[:user_name, :user_image])
end
end

View file

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

View file

@ -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 }

11
app/models/token.rb Normal file
View file

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

View file

@ -6,6 +6,7 @@ class User < ActiveRecord::Base
has_many :synapses
has_many :maps
has_many :mappings
has_many :tokens
after_create :generate_code

View file

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

View file

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

View file

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

View file

@ -0,0 +1,7 @@
class NewMetacodeSerializer < ActiveModel::Serializer
attributes :id,
:name,
:manual_icon,
:color,
:aws_icon
end

View file

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

View file

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

View file

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

View file

@ -0,0 +1,10 @@
class TokenSerializer < ActiveModel::Serializer
embed :ids, include: true
attributes :id,
:token,
:description,
:user_id,
:created_at,
:updated_at
end

View file

@ -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]

View file

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

View file

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

View file

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Token, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end