Browse Source

domain sharing, initial setup

pull/1/head
Nicolae Claudius 13 years ago
parent
commit
7e3f2a855d
  1. 2
      Gemfile
  2. 38
      Gemfile.lock
  3. 5
      app/assets/stylesheets/overrides.css.erb
  4. 11
      app/controllers/domains_controller.rb
  5. 12
      app/controllers/permissions_controller.rb
  6. 2
      app/helpers/permissions_helper.rb
  7. 6
      app/models/ability.rb
  8. 1
      app/models/domain.rb
  9. 30
      app/models/permission.rb
  10. 1
      app/models/user.rb
  11. 4
      app/views/domains/_list_record_columns.html.erb
  12. 73
      config/initializers/cancan.rb
  13. 12
      config/initializers/squeel.rb
  14. 4
      config/routes.rb
  15. 12
      db/migrate/20111129180907_create_permissions.rb
  16. 157
      spec/controllers/permissions_controller_spec.rb
  17. 3
      spec/factories.rb
  18. 15
      spec/helpers/permissions_helper_spec.rb
  19. 47
      spec/models/ability_spec.rb
  20. 5
      spec/models/permission_spec.rb
  21. 11
      spec/requests/permissions_spec.rb
  22. 35
      spec/routing/permissions_routing_spec.rb
  23. 3
      spec/support/shared_context/data.rb
  24. 15
      spec/views/permissions/edit.html.erb_spec.rb
  25. 14
      spec/views/permissions/index.html.erb_spec.rb
  26. 15
      spec/views/permissions/new.html.erb_spec.rb
  27. 11
      spec/views/permissions/show.html.erb_spec.rb

2
Gemfile

@ -9,7 +9,7 @@ gem 'rails', '3.1.1'
gem 'mysql2'
gem 'devise', '~> 1.4.5'
gem 'cancan', '~> 1.6.5'
# gem "meta_where", "~> 1.0" # squeel ?
gem "squeel", "~> 0.9.3"
gem 'sentient_user', '~> 0.3.2'
gem 'active_scaffold', '~> 3.1.0', :git => 'https://github.com/activescaffold/active_scaffold.git' # :path => '/home/clyfe/dev/active_scaffold'
gem 'pjax_rails', '~> 0.1.10'

38
Gemfile.lock

@ -6,9 +6,9 @@ GIT
GIT
remote: https://github.com/activescaffold/active_scaffold.git
revision: 75abf52219da6015e76a9bd9115f80134a384d69
revision: 7ece16b812891b155818ba466c4490b631bccffb
specs:
active_scaffold (3.1.11)
active_scaffold (3.1.13)
rails (~> 3.1.0)
GEM
@ -62,7 +62,7 @@ GEM
rack-test (>= 0.5.4)
selenium-webdriver (~> 2.0)
xpath (~> 0.1.4)
childprocess (0.2.3)
childprocess (0.2.4)
ffi (~> 1.0.6)
chunky_png (1.2.5)
coffee-rails (3.1.1)
@ -71,13 +71,13 @@ GEM
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.1.3)
compass (0.12.alpha.2)
coffee-script-source (1.2.0)
compass (0.12.alpha.3)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.1)
daemons (1.0.10)
dalli (1.1.3)
dalli (1.1.4)
database_cleaner (0.6.7)
devise (1.4.9)
bcrypt-ruby (~> 3.0)
@ -85,7 +85,7 @@ GEM
warden (~> 1.0.3)
diff-lcs (1.1.3)
erubis (2.7.0)
execjs (1.2.9)
execjs (1.2.13)
multi_json (~> 1.0)
factory_girl (2.3.2)
activesupport
@ -97,20 +97,21 @@ GEM
ffi (1.0.11)
fssm (0.2.7)
gem_plugin (0.2.3)
guard (0.8.8)
guard (0.9.4)
ffi (>= 0.5.0)
thor (~> 0.14.6)
guard-rspec (0.4.5)
guard (>= 0.4.0)
guard-spork (0.3.2)
guard (>= 0.8.4)
spork (>= 0.8.4)
highline (1.6.8)
highline (1.6.9)
hike (1.2.1)
i18n (0.6.0)
jquery-rails (1.0.19)
railties (~> 3.0)
thor (~> 0.14)
json (1.6.2)
json (1.6.4)
libnotify (0.5.9)
libv8 (3.3.10.4)
mail (2.3.0)
@ -123,7 +124,7 @@ GEM
daemons (~> 1.0.10)
gem_plugin (~> 0.2.3)
multi_json (1.0.4)
mysql2 (0.3.10)
mysql2 (0.3.11)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
net-sftp (2.0.5)
@ -138,6 +139,8 @@ GEM
orm_adapter (0.0.5)
pjax_rails (0.1.10)
jquery-rails
polyamorous (0.5.0)
activerecord (~> 3.0)
polyglot (0.3.3)
rack (1.3.5)
rack-cache (1.1)
@ -169,7 +172,7 @@ GEM
rb-fsevent (0.4.3.1)
rb-inotify (0.8.8)
ffi (>= 0.5.0)
rdoc (3.11)
rdoc (3.12)
json (~> 1.4)
rspec (2.6.0)
rspec-core (~> 2.6.0)
@ -185,13 +188,13 @@ GEM
railties (~> 3.0)
rspec (~> 2.6.0)
rubyzip (0.9.5)
sass (3.1.11)
sass (3.1.12)
sass-rails (3.1.5)
actionpack (~> 3.1.0)
railties (~> 3.1.0)
sass (~> 3.1.10)
tilt (~> 1.3.2)
selenium-webdriver (2.14.0)
selenium-webdriver (2.15.0)
childprocess (>= 0.2.1)
ffi (~> 1.0.9)
multi_json (~> 1.0.4)
@ -202,6 +205,10 @@ GEM
hike (~> 1.2)
rack (~> 1.0)
tilt (!= 1.3.0, ~> 1.1)
squeel (0.9.3)
activerecord (~> 3.0)
activesupport (~> 3.0)
polyamorous (~> 0.5.0)
therubyracer (0.9.9)
libv8 (~> 3.3.10)
thor (0.14.6)
@ -210,7 +217,7 @@ GEM
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.31)
uglifier (1.1.0)
uglifier (1.2.1)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
warden (1.0.6)
@ -251,6 +258,7 @@ DEPENDENCIES
sass-rails (~> 3.1.0)
sentient_user (~> 0.3.2)
spork (~> 0.9.0.rc)
squeel (~> 0.9.3)
therubyracer
uglifier
validates_hostname (~> 1.0.0)!

5
app/assets/stylesheets/overrides.css.erb

@ -14,6 +14,11 @@
text-shadow: none;
}
#main .block .content .active-scaffold th p {
font: bold 11px arial, sans-serif;
text-shadow: none;
}
body.errors #main .inner {
margin-top: 15px;
}

11
app/controllers/domains_controller.rb

@ -2,15 +2,16 @@ class DomainsController < ApplicationController
active_scaffold :domain do |conf|
conf.columns = [:name, :ip, :records, :soa_record, :ns_records]
conf.list.columns = [:name, :records]
conf.list.columns = [:name, :records, :permissions]
conf.create.columns = [:name, :ip, :soa_record, :ns_records]
conf.update.columns = [:name, :soa_record]
conf.columns[:name].description = 'Ex. "domain.com"'
conf.columns[:ip].description = 'Ex. "10.10.5.12", optional IP to associate your domain with'
conf.columns[:ns_records].show_blank_record = false
conf.columns[:permissions].label = 'Sharing'
conf.actions.exclude :show
conf.list.sorting = {:name => :asc}
conf.create.link.label = "Add Domain"
conf.create.link.label = 'Add Domain'
# conf.columns[:records].label = 'All Records'
end
@ -22,6 +23,12 @@ class DomainsController < ApplicationController
@record.setup(current_user.email)
end
def new_model
record = super
record.user_id = current_user.id
record
end
def before_create_save(record)
record.type = 'NATIVE'
end

12
app/controllers/permissions_controller.rb

@ -0,0 +1,12 @@
class PermissionsController < ApplicationController
active_scaffold :permission do |conf|
conf.actions.exclude :show
conf.columns = [:domain, :user, :user_email]
conf.list.columns = [:domain, :user, :user_email]
conf.create.columns = [:domain, :user_email]
conf.update.columns = [:domain, :user_email]
conf.columns[:user_email].form_ui = :virtual
conf.columns[:user_email].description = 'user\'s email address, to share with. Ex. jhon.doe@domain.com'
end
before_filter :ensure_nested_under_domain
end

2
app/helpers/permissions_helper.rb

@ -0,0 +1,2 @@
module PermissionsHelper
end

6
app/models/ability.rb

@ -17,6 +17,12 @@ class Ability
# can manage his hosts
can :manage, A, :user_id => user.id #, :domain => {:name => Settings.host_domains}
# can manage permissions for his domains
can :manage, Permission, :domain => {:user_id => user.id}
# can manage shared domains and records
can :manage, Domain, :permissions.outer => {:user_id => user.id}
can :manage, Record, :domain => {:permissions.outer => {:user_id => user.id}}
end
# See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities

1
app/models/domain.rb

@ -9,6 +9,7 @@ class Domain < ActiveRecord::Base
belongs_to :user, :inverse_of => :domain
has_many :records, :inverse_of => :domain, :dependent => :destroy
has_many :permissions, :inverse_of => :domain, :dependent => :destroy
cattr_reader :types
@@types = ['NATIVE', 'MASTER', 'SLAVE', 'SUPERSLAVE']

30
app/models/permission.rb

@ -0,0 +1,30 @@
class Permission < ActiveRecord::Base
belongs_to :domain, :inverse_of => :permissions
belongs_to :user, :inverse_of => :permissions
validates :domain_id, :presence => true
validates :user_id, :presence => true, :uniqueness => {
:scope => :domain_id,
:message => "already is permitted"
}
validates :user, :presence => {
:if => lambda {@user_email.present?},
:message => "with given email was not found"
}
validate do
errors[:user] = 'cannot be yourself' if user_id == domain.user_id
end
def user_email
@user_email || user.try(:email)
end
def user_email=(email)
@user_email = email
self.user = User.find_by_email(email)
end
def to_label
user.try(:email) || @user_email || '-'
end
end

1
app/models/user.rb

@ -18,6 +18,7 @@ class User < ActiveRecord::Base
has_many :domains, :inverse_of => :user, :dependent => :destroy
has_many :records, :inverse_of => :user, :dependent => :destroy
has_many :permissions, :inverse_of => :user, :dependent => :destroy
def name
"#{first_name} #{last_name}"

4
app/views/domains/_list_record_columns.html.erb

@ -9,9 +9,9 @@
<% column_value = 'Manage All Records (0)' if column_value == '-' %>
<%= authorized ? render_list_column(column_value, column, record) : column_value %>
</td>
<% elsif column.name == :ns_records %>
<% elsif column.name == :permissions %>
<td class="<%= column_class(column, column_value, record) %>" >
<% column_value = 'Manage NS Records (0)' if column_value == '-' %>
<% column_value = 'Permissions (0)' if column_value == '-' %>
<%= authorized ? render_list_column(column_value, column, record) : column_value %>
</td>
<% else %>

73
config/initializers/cancan.rb

@ -0,0 +1,73 @@
# tweaks to allow Squeel Join
module CanCan
module ModelAdapters
class ActiveRecordAdapter < AbstractAdapter
def tableized_conditions(conditions, model_class = @model_class)
return conditions unless conditions.kind_of? Hash
conditions.inject({}) do |result_hash, (name, value)|
reflection_name = name.kind_of?(Symbol) ? name : name._name # Squeel compatibility
if value.kind_of? Hash
reflection = model_class.reflect_on_association(reflection_name)
association_class = reflection.class_name.constantize
name = reflection.table_name.to_sym
value = tableized_conditions(value, association_class)
end
result_hash[name] = value
result_hash
end
end
private
# override to fix overwrites
# do not write existing hashes using empty hashes
def merge_joins(base, add)
add.each do |name, nested|
if base[name].is_a?(Hash) && nested.present?
merge_joins(base[name], nested)
elsif !base[name].is_a?(Hash) || nested.present?
base[name] = nested
end
end
end
end
end
class Rule
# allow Squeel Join
def matches_conditions_hash?(subject, conditions = @conditions)
if conditions.empty?
true
else
if model_adapter(subject).override_conditions_hash_matching? subject, conditions
model_adapter(subject).matches_conditions_hash? subject, conditions
else
conditions.all? do |name, value|
if model_adapter(subject).override_condition_matching? subject, name, value
model_adapter(subject).matches_condition? subject, name, value
else
method_name = name.kind_of?(Symbol) ? name : name._name # Squeel compatibility
attribute = subject.send(method_name)
if value.kind_of?(Hash)
if attribute.kind_of? Array
attribute.any? { |element| matches_conditions_hash? element, value }
else
!attribute.nil? && matches_conditions_hash?(attribute, value)
end
elsif value.kind_of?(Array) || value.kind_of?(Range)
value.include? attribute
else
attribute == value
end
end
end
end
end
end
end
end

12
config/initializers/squeel.rb

@ -0,0 +1,12 @@
Squeel.configure do |config|
# To load hash extensions (to allow for AND (&), OR (|), and NOT (-) against
# hashes of conditions)
config.load_core_extensions :hash
# To load symbol extensions (for a subset of the old MetaWhere functionality,
# via ARel predicate methods on Symbols: :name.matches, etc)
# config.load_core_extensions :symbol
# To load both hash and symbol extensions
config.load_core_extensions :hash, :symbol
end

4
config/routes.rb

@ -50,6 +50,10 @@ Entrydns::Application.routes.draw do
as_routes
end
resources :permissions do
as_routes
end
get '/dashboard', :to => 'dashboard#index', :as => :dashboard
resources :pages, :only => :show

12
db/migrate/20111129180907_create_permissions.rb

@ -0,0 +1,12 @@
class CreatePermissions < ActiveRecord::Migration
def change
create_table :permissions do |t|
t.references :domain # the domain to whom permission is being given
t.references :user # the user permitted to manage
t.timestamps
end
add_index :permissions, :domain_id
add_index :permissions, :user_id
end
end

157
spec/controllers/permissions_controller_spec.rb

@ -0,0 +1,157 @@
require 'spec_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
describe PermissionsController do
# This should return the minimal set of attributes required to create a valid
# Permission. As you add validations to Permission, be sure to
# update the return value of this method accordingly.
def valid_attributes
{}
end
describe "GET index" do
it "assigns all permissions as @permissions" do
permission = Permission.create! valid_attributes
get :index
assigns(:permissions).should eq([permission])
end
end
describe "GET show" do
it "assigns the requested permission as @permission" do
permission = Permission.create! valid_attributes
get :show, :id => permission.id.to_s
assigns(:permission).should eq(permission)
end
end
describe "GET new" do
it "assigns a new permission as @permission" do
get :new
assigns(:permission).should be_a_new(Permission)
end
end
describe "GET edit" do
it "assigns the requested permission as @permission" do
permission = Permission.create! valid_attributes
get :edit, :id => permission.id.to_s
assigns(:permission).should eq(permission)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Permission" do
expect {
post :create, :permission => valid_attributes
}.to change(Permission, :count).by(1)
end
it "assigns a newly created permission as @permission" do
post :create, :permission => valid_attributes
assigns(:permission).should be_a(Permission)
assigns(:permission).should be_persisted
end
it "redirects to the created permission" do
post :create, :permission => valid_attributes
response.should redirect_to(Permission.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved permission as @permission" do
# Trigger the behavior that occurs when invalid params are submitted
Permission.any_instance.stub(:save).and_return(false)
post :create, :permission => {}
assigns(:permission).should be_a_new(Permission)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Permission.any_instance.stub(:save).and_return(false)
post :create, :permission => {}
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested permission" do
permission = Permission.create! valid_attributes
# Assuming there are no other permissions in the database, this
# specifies that the Permission created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Permission.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
put :update, :id => permission.id, :permission => {'these' => 'params'}
end
it "assigns the requested permission as @permission" do
permission = Permission.create! valid_attributes
put :update, :id => permission.id, :permission => valid_attributes
assigns(:permission).should eq(permission)
end
it "redirects to the permission" do
permission = Permission.create! valid_attributes
put :update, :id => permission.id, :permission => valid_attributes
response.should redirect_to(permission)
end
end
describe "with invalid params" do
it "assigns the permission as @permission" do
permission = Permission.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Permission.any_instance.stub(:save).and_return(false)
put :update, :id => permission.id.to_s, :permission => {}
assigns(:permission).should eq(permission)
end
it "re-renders the 'edit' template" do
permission = Permission.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Permission.any_instance.stub(:save).and_return(false)
put :update, :id => permission.id.to_s, :permission => {}
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested permission" do
permission = Permission.create! valid_attributes
expect {
delete :destroy, :id => permission.id.to_s
}.to change(Permission, :count).by(-1)
end
it "redirects to the permissions list" do
permission = Permission.create! valid_attributes
delete :destroy, :id => permission.id.to_s
response.should redirect_to(permissions_url)
end
end
end

3
spec/factories.rb

@ -33,4 +33,7 @@ FactoryGirl.define do
content {Faker::Internet.ip_v4_address}
end
factory :permission do
end
end

15
spec/helpers/permissions_helper_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the PermissionsHelper. For example:
#
# describe PermissionsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe PermissionsHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

47
spec/models/ability_spec.rb

@ -5,23 +5,42 @@ require 'spec_helper'
describe Ability do
include_context "data"
it "allows me to manage my domains and their records, and my hosts" do
ability.should be_able_to(:manage, domain)
ability.should be_able_to(:manage, a_record)
ability.should be_able_to(:manage, soa_record)
ability.should_not be_able_to(:delete, soa_record) # SOA deleted only via parent
ability.should be_able_to(:manage, host_a_record)
end
context "basic" do
it "allows me to manage my domains and their records, and my hosts" do
ability.should be_able_to(:manage, domain)
ability.should be_able_to(:manage, a_record)
ability.should be_able_to(:manage, soa_record)
ability.should_not be_able_to(:delete, soa_record) # SOA deleted only via parent
ability.should be_able_to(:manage, host_a_record)
end
it "denies other user to manage my domains and their records, and my hosts" do
other_user_ability.should_not be_able_to(:manage, domain)
other_user_ability.should_not be_able_to(:manage, a_record)
other_user_ability.should_not be_able_to(:manage, soa_record)
other_user_ability.should_not be_able_to(:manage, host_a_record)
end
it "denies other user to manage my domains and their records" do
other_user_ability.should_not be_able_to(:manage, domain)
other_user_ability.should_not be_able_to(:manage, a_record)
other_user_ability.should_not be_able_to(:manage, soa_record)
other_user_ability.should_not be_able_to(:manage, host_a_record)
it "allows admin to manage other user's hosts" do
admin_ability.should be_able_to(:manage, host_a_record)
end
end
it "allows admin to manage other user's hosts" do
admin_ability.should be_able_to(:manage, host_a_record)
context "permission" do
it "allows other user to manage user's domains and records, if permitted" do
permission # ensure permission to domain
other_user_ability.should be_able_to(:manage, domain)
other_user_ability.should be_able_to(:manage, a_record)
other_user_ability.should be_able_to(:manage, soa_record)
end
it "allows me to manage my domain's permissions" do
ability.should be_able_to(:manage, permission)
end
it "denies other user to manage my domain's permissions" do
other_user_ability.should_not be_able_to(:manage, permission)
end
end
end

5
spec/models/permission_spec.rb

@ -0,0 +1,5 @@
require 'spec_helper'
describe Permission do
pending "add some examples to (or delete) #{__FILE__}"
end

11
spec/requests/permissions_spec.rb

@ -0,0 +1,11 @@
require 'spec_helper'
describe "Permissions" do
describe "GET /permissions" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get permissions_path
response.status.should be(200)
end
end
end

35
spec/routing/permissions_routing_spec.rb

@ -0,0 +1,35 @@
require "spec_helper"
describe PermissionsController do
describe "routing" do
it "routes to #index" do
get("/permissions").should route_to("permissions#index")
end
it "routes to #new" do
get("/permissions/new").should route_to("permissions#new")
end
it "routes to #show" do
get("/permissions/1").should route_to("permissions#show", :id => "1")
end
it "routes to #edit" do
get("/permissions/1/edit").should route_to("permissions#edit", :id => "1")
end
it "routes to #create" do
post("/permissions").should route_to("permissions#create")
end
it "routes to #update" do
put("/permissions/1").should route_to("permissions#update", :id => "1")
end
it "routes to #destroy" do
delete("/permissions/1").should route_to("permissions#destroy", :id => "1")
end
end
end

3
spec/support/shared_context/data.rb

@ -2,6 +2,7 @@ shared_context "data" do
let(:user){create(:user)}
let(:ability){Ability.new(:user => user)}
let(:other_user){create(:user)}
let(:other_user_ability){Ability.new(:user => other_user)}
@ -37,4 +38,6 @@ shared_context "data" do
}
let(:host_a_record){create(:a, :content => '127.0.0.1', :domain => host_domain, :user => user)}
let(:permission) {create(:permission, :domain => domain, :user => other_user)}
end

15
spec/views/permissions/edit.html.erb_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
describe "permissions/edit.html.erb" do
before(:each) do
@permission = assign(:permission, stub_model(Permission))
end
it "renders the edit permission form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => permissions_path(@permission), :method => "post" do
end
end
end

14
spec/views/permissions/index.html.erb_spec.rb

@ -0,0 +1,14 @@
require 'spec_helper'
describe "permissions/index.html.erb" do
before(:each) do
assign(:permissions, [
stub_model(Permission),
stub_model(Permission)
])
end
it "renders a list of permissions" do
render
end
end

15
spec/views/permissions/new.html.erb_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
describe "permissions/new.html.erb" do
before(:each) do
assign(:permission, stub_model(Permission).as_new_record)
end
it "renders new permission form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => permissions_path, :method => "post" do
end
end
end

11
spec/views/permissions/show.html.erb_spec.rb

@ -0,0 +1,11 @@
require 'spec_helper'
describe "permissions/show.html.erb" do
before(:each) do
@permission = assign(:permission, stub_model(Permission))
end
it "renders attributes in <p>" do
render
end
end
Loading…
Cancel
Save