Group creation triggered from editor

pull/5200/head
Juan Ignacio Sánchez Lara 9 years ago
parent 10d7bc6b73
commit 228f6ff9e1

@ -1,6 +1,7 @@
# encoding: utf-8
require_relative 'paged_searcher'
require_dependency 'cartodb/errors'
module Carto
module Api
@ -20,6 +21,17 @@ module Carto
}, 200)
end
def create
group = @organization.create_group(params['display_name'])
render_jsonp(Carto::Api::GroupPresenter.new(group).to_poro, 200)
rescue CartoDB::ModelAlreadyExistsError => e
CartoDB.notify_debug('Group already exists', { params: params })
render json: { errors: "A group with that data already exists" }, status: 409
rescue => e
CartoDB.notify_exception(e, { params: params , group: (group ? group : 'not created') })
render json: { errors: e.message }, status: 500
end
private
def load_organization

@ -16,6 +16,7 @@ module Carto
validates :name, :database_role, :organization_id, :presence => true
# Constructor for groups already existing in the database
def self.new_instance(database_name, name, database_role, display_name = name)
organization = Organization.find_by_database_name(database_name)
@ -26,6 +27,19 @@ module Carto
new(name: name, database_role: database_role, display_name: display_name, organization: organization)
end
# Creation of brand-new group with the extension
def self.create_group(organization, display_name)
name = valid_group_name(display_name)
organization.owner.in_database(:as => :superuser) do |conn|
create_group_with_extension(conn, name)
end
# Extension triggers a request to the editor databases endpoint which actually creates the group
group = Carto::Group.find_by_organization_id_and_name(organization.id, name)
group.display_name = display_name
group.save
group
end
def rename(new_name, new_database_role)
self.name = new_name
self.database_role = new_database_role
@ -55,5 +69,18 @@ module Carto
organization.database_name
end
private
# TODO: PG Format("%I", strvar); ?
def self.valid_group_name(display_name)
name = display_name.squish
name = "g_#{name}" unless name[/^[a-z_]{1}/]
name.gsub(/[^a-z0-9_]/,'_').gsub(/_{2,}/, '_')
end
def self.create_group_with_extension(conn, name)
conn.execute(%Q{ select cartodb.CDB_Group_CreateGroup('#{name}') })
end
end
end

@ -39,6 +39,12 @@ module Carto
owner ? owner.database_name : nil
end
def create_group(display_name)
Carto::Group.create_group(self, display_name)
end
private
end
end

@ -44,6 +44,7 @@ CartoDB::Application.configure do
# config.action_mailer.delivery_method = :smtp
# Enable threaded mode
# In order to run supporting concurrent requests, uncomment next line and run with `bundle exec thin start --threaded -p 3000`
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to

@ -352,6 +352,7 @@ CartoDB::Application.routes.draw do
# Groups
get '(/user/:user_domain)(/u/:user_domain)/api/v1/organization/:organization_id/groups' => 'groups#index', as: :api_v1_organization_groups, constraints: { organization_id: /[^\/]+/ }
post '(/user/:user_domain)(/u/:user_domain)/api/v1/organization/:organization_id/groups' => 'groups#create', as: :api_v1_organization_groups_create, constraints: { organization_id: /[^\/]+/ }
# Databases (organization) groups
# Note: url doesn't contain org_id because this needs to be triggered from the SQL API

@ -8,10 +8,13 @@ FactoryGirl.define do
database_role 'database_role'
end
factory :random_group, :class => Carto::Group do |g|
factory :new_random_group, :class => Carto::Group do |g|
name { "g_#{String.random(4)}" }
display_name { "Group #{g.name}" }
database_role { "database_role_#{g.name}" }
factory :random_group do
database_role { "database_role_#{g.name}" }
end
end
end

@ -2,6 +2,7 @@
require_relative '../../../spec_helper'
require_relative '../../../../app/controllers/carto/api/database_groups_controller'
require 'rspec/mocks'
describe Carto::Api::GroupsController do
include_context 'organization with users helper'
@ -16,7 +17,7 @@ describe Carto::Api::GroupsController do
@group_2_json = { 'id' => @group_2.id, 'organization_id' => @group_2.organization_id, 'name' => @group_2.name, 'display_name' => @group_2.display_name }
@group_3 = FactoryGirl.create(:random_group, display_name: 'g_3', organization: @carto_organization)
@group_3_json = { 'id' => @group_3.id, 'organization_id' => @group_3.organization_id, 'name' => @group_3.name, 'display_name' => @group_3.display_name }
@no_auth_headers = {'CONTENT_TYPE' => 'application/json', :format => "json" }
@headers = {'CONTENT_TYPE' => 'application/json', :format => "json" }
end
after(:all) do
@ -26,13 +27,13 @@ describe Carto::Api::GroupsController do
end
it '#index returns 401 without authentication' do
get_json api_v1_organization_groups_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id), {}, @no_auth_headers do |response|
get_json api_v1_organization_groups_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id), {}, @headers do |response|
response.status.should == 401
end
end
it '#index returns groups with pagination metadata' do
get_json api_v1_organization_groups_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id, api_key: @org_user_owner.api_key), {}, @no_auth_headers do |response|
get_json api_v1_organization_groups_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id, api_key: @org_user_owner.api_key), {}, @headers do |response|
response.status.should == 200
expected_response = {
groups: [ @group_1_json, @group_2_json, @group_3_json ],
@ -44,7 +45,7 @@ describe Carto::Api::GroupsController do
end
it '#index returns paginated groups with pagination metadata' do
get_json api_v1_organization_groups_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id, api_key: @org_user_owner.api_key), { page: 2, per_page: 1, order: 'display_name' }, @no_auth_headers do |response|
get_json api_v1_organization_groups_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id, api_key: @org_user_owner.api_key), { page: 2, per_page: 1, order: 'display_name' }, @headers do |response|
response.status.should == 200
expected_response = {
groups: [ @group_2_json ],
@ -55,6 +56,34 @@ describe Carto::Api::GroupsController do
end
end
it '#create new groups' do
display_name = 'a new group'
name = 'a_new_group'
# Replacement for extension interaction
fake_database_role = 'fake_database_role'
fake_group_creation = Carto::Group.new_instance(@carto_organization.database_name, name, fake_database_role)
fake_group_creation.save
Carto::Group.expects(:create_group_with_extension).with(anything, name).returns(fake_group_creation)
post_json api_v1_organization_groups_create_url(user_domain: @org_user_owner.username, organization_id: @carto_organization.id, api_key: @org_user_owner.api_key), { display_name: display_name }, @headers do |response|
response.status.should == 200
response.body[:id].should_not be_nil
response.body[:organization_id].should == @carto_organization.id
response.body[:name].should == name
response.body[:display_name].should == display_name
# Also check database data because Group changes something after extension interaction
new_group = Carto::Group.find(response.body[:id])
new_group.organization_id.should == @carto_organization.id
new_group.name.should == name
new_group.display_name.should == display_name
new_group.database_role.should_not be_nil
end
end
# TODO: check only owner can
end
end

Loading…
Cancel
Save