ixtlan 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +49 -0
- data/MIT-LICENSE +20 -0
- data/Manifest.txt +73 -48
- data/Rakefile +1 -1
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/gwt_ixtlan_datamapper_rspec_scaffold_generator.rb +3 -3
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/templates/AbstractApplicationResourceTestGwt.java +1 -1
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/templates/Fields.java +1 -1
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/templates/Model.java +2 -2
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/templates/ModelFactory.java +2 -2
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/templates/Screen.java +2 -2
- data/generators/gwt_ixtlan_datamapper_rspec_scaffold/templates/TestGwt.java +2 -2
- data/generators/ixtlan_datamapper_rspec_model/ixtlan_datamapper_rspec_model_generator.rb +1 -1
- data/generators/ixtlan_datamapper_rspec_scaffold/ixtlan_datamapper_rspec_scaffold_generator.rb +4 -4
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/guard.rb +7 -7
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/i18n.rb +1 -1
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/layout.html.erb +20 -0
- data/ixtlan_rails_templates.rb +537 -0
- data/lib/ixtlan/audit_config.rb +5 -5
- data/lib/ixtlan/child_path.rb +2 -2
- data/lib/ixtlan/cms_script.rb +4 -4
- data/lib/ixtlan/controllers/authentications_controller.rb +7 -2
- data/lib/ixtlan/controllers/configurations_controller.rb +15 -6
- data/lib/ixtlan/controllers/domains_controller.rb +99 -0
- data/lib/ixtlan/controllers/groups_controller.rb +105 -0
- data/lib/ixtlan/controllers/locales_controller.rb +99 -0
- data/lib/ixtlan/controllers/permissions_controller.rb +5 -0
- data/lib/ixtlan/controllers/phrases_controller.rb +26 -22
- data/lib/ixtlan/controllers/search_query.rb +24 -0
- data/lib/ixtlan/controllers/texts_controller.rb +5 -5
- data/lib/ixtlan/controllers/users_controller.rb +117 -0
- data/lib/ixtlan/controllers/word_bundles_controller.rb +13 -8
- data/lib/ixtlan/digest.rb +3 -3
- data/lib/ixtlan/guard.rb +11 -12
- data/lib/ixtlan/logger_config.rb +11 -11
- data/lib/ixtlan/mailer/error_notification.erb +1 -0
- data/lib/ixtlan/mailer/password.erb +1 -0
- data/lib/ixtlan/mailer.rb +27 -0
- data/lib/ixtlan/models/authentication.rb +9 -6
- data/lib/ixtlan/models/configuration.rb +21 -37
- data/lib/ixtlan/models/configuration_locale.rb +3 -3
- data/lib/ixtlan/models/domain.rb +44 -0
- data/lib/ixtlan/models/domain_group_user.rb +22 -0
- data/lib/ixtlan/models/group.rb +82 -16
- data/lib/ixtlan/models/group_locale_user.rb +4 -4
- data/lib/ixtlan/models/group_user.rb +7 -7
- data/lib/ixtlan/models/i18n_text.rb +26 -26
- data/lib/ixtlan/models/locale.rb +17 -5
- data/lib/ixtlan/models/permission.rb +3 -2
- data/lib/ixtlan/models/phrase.rb +15 -15
- data/lib/ixtlan/models/role.rb +5 -5
- data/lib/ixtlan/models/translation.rb +9 -9
- data/lib/ixtlan/models/update_children.rb +74 -0
- data/lib/ixtlan/models/user.rb +108 -16
- data/lib/ixtlan/models/word.rb +2 -1
- data/lib/ixtlan/models.rb +1 -0
- data/lib/ixtlan/modified_by.rb +9 -7
- data/lib/ixtlan/monkey_patches.rb +5 -5
- data/lib/ixtlan/optimistic_persistence.rb +2 -2
- data/lib/ixtlan/optimistic_persistence_module.rb +3 -3
- data/lib/ixtlan/optimistic_persistence_validation.rb +2 -2
- data/lib/ixtlan/passwords.rb +15 -13
- data/lib/ixtlan/rails/error_handling.rb +41 -40
- data/lib/ixtlan/rails/guard.rb +0 -1
- data/lib/ixtlan/rails/migrations.rb +75 -0
- data/lib/ixtlan/rails/session_timeout.rb +16 -14
- data/lib/ixtlan/rails/timestamps_modified_by_filter.rb +1 -1
- data/lib/ixtlan/rails/unrestful_authentication.rb +4 -4
- data/lib/ixtlan/rolling_file.rb +3 -3
- data/lib/ixtlan/session.rb +4 -3
- data/lib/ixtlan/user_logger.rb +13 -9
- data/lib/ixtlan/version.rb +1 -1
- data/spec/authentication_spec.rb +1 -1
- data/spec/guard_spec.rb +4 -4
- data/spec/guards/samples.rb +7 -7
- data/spec/modified_by_spec.rb +82 -0
- data/spec/optimistic_persistence_spec.rb +58 -0
- data/spec/phrase_spec.rb +119 -0
- data/spec/session_timeout_spec.rb +59 -0
- data/spec/spec_helper.rb +6 -5
- data/spec/text_collection_spec.rb +88 -0
- data/spec/text_spec.rb +105 -0
- data/spec/unrestful_authentication_spec.rb +142 -0
- data/spec/user_logger_spec.rb +105 -0
- data/spec/user_spec.rb +249 -0
- data/whitespace.rb +31 -0
- metadata +76 -50
- data/lib/ixtlan/error_notifier/error_notification.rhtml +0 -1
data/lib/ixtlan/models/locale.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'dm-serializer'
|
1
2
|
module Ixtlan
|
2
3
|
module Models
|
3
4
|
class Locale
|
@@ -12,10 +13,13 @@ module Ixtlan
|
|
12
13
|
ALL = "ALL"
|
13
14
|
end
|
14
15
|
|
15
|
-
property :
|
16
|
-
|
16
|
+
property :id, Serial
|
17
|
+
property :code, String, :required => true , :format => /^[a-z][a-z](_[A-Z][A-Z])?$|^#{DEFAULT}$|^#{ALL}$/, :length => 7, :unique_index => true
|
18
|
+
|
17
19
|
timestamps :created_at
|
18
20
|
|
21
|
+
modified_by Models::USER, :created_by
|
22
|
+
|
19
23
|
def parent
|
20
24
|
c = attribute_get(:code)
|
21
25
|
case c.size
|
@@ -29,17 +33,25 @@ module Ixtlan
|
|
29
33
|
end
|
30
34
|
|
31
35
|
def self.default
|
32
|
-
|
36
|
+
first(:code => DEFAULT)
|
33
37
|
end
|
34
38
|
|
35
39
|
def self.every
|
36
|
-
|
40
|
+
first(:code => ALL)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.first_or_get!(id_or_code)
|
44
|
+
first(:code => id_or_code) || get!(id_or_code)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.first_or_get(id_or_code)
|
48
|
+
first(:code => id_or_code) || get(id_or_code)
|
37
49
|
end
|
38
50
|
|
39
51
|
def hash
|
40
52
|
attribute_get(:code).hash
|
41
53
|
end
|
42
|
-
|
54
|
+
|
43
55
|
alias :eql? :==
|
44
56
|
def ==(other)
|
45
57
|
attribute_get(:code).eql?(other.attribute_get(:code))
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'dm-serializer'
|
1
2
|
module Ixtlan
|
2
3
|
module Models
|
3
4
|
class Permission
|
@@ -15,9 +16,9 @@ module Ixtlan
|
|
15
16
|
has n, :roles, :model => Models::ROLE
|
16
17
|
|
17
18
|
if protected_instance_methods.find {|m| m == 'to_x'}.nil?
|
18
|
-
|
19
|
+
|
19
20
|
protected
|
20
|
-
|
21
|
+
|
21
22
|
alias :to_x :to_xml_document
|
22
23
|
def to_xml_document(opts, doc = nil)
|
23
24
|
opts.merge!({:methods => [:roles]})
|
data/lib/ixtlan/models/phrase.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'dm-serializer'
|
1
2
|
module Ixtlan
|
2
3
|
module Models
|
3
4
|
class Phrase
|
@@ -9,25 +10,25 @@ module Ixtlan
|
|
9
10
|
|
10
11
|
property :id, Serial
|
11
12
|
|
12
|
-
property :code, String, :
|
13
|
-
|
14
|
-
property :text, String, :
|
15
|
-
|
16
|
-
property :current_text, String, :
|
17
|
-
|
18
|
-
property :updated_at, DateTime, :
|
19
|
-
|
13
|
+
property :code, String, :required => true, :length => 64
|
14
|
+
|
15
|
+
property :text, String, :required => true, :length => 256
|
16
|
+
|
17
|
+
property :current_text, String, :required => false, :length => 256
|
18
|
+
|
19
|
+
property :updated_at, DateTime, :required => true, :auto_validation => false
|
20
|
+
|
20
21
|
belongs_to :updated_by, :model => Models::USER
|
21
|
-
|
22
|
+
|
22
23
|
belongs_to :locale, :model => Models::LOCALE
|
23
|
-
|
24
|
-
belongs_to :default_translation, :model => Models::TRANSLATION, :nullable => true
|
25
24
|
|
26
|
-
belongs_to :
|
25
|
+
belongs_to :default_translation, :model => Models::TRANSLATION, :required => false
|
26
|
+
|
27
|
+
belongs_to :parent_translation, :model => Models::TRANSLATION, :required => false
|
27
28
|
|
28
29
|
alias :to_x :to_xml_document
|
29
30
|
def to_xml_document(opts = {}, doc = nil)
|
30
|
-
opts.merge!({:exclude => [:id, :parent_translation_id, :default_translation_id, :
|
31
|
+
opts.merge!({:exclude => [:id, :parent_translation_id, :default_translation_id, :locale_id], :element_name => 'phrase', :methods => [:default_translation, :parent_translation, :locale]})
|
31
32
|
to_x(opts, doc)
|
32
33
|
end
|
33
34
|
|
@@ -55,7 +56,7 @@ module Ixtlan
|
|
55
56
|
ph = map[code]
|
56
57
|
if(ph.nil?)
|
57
58
|
map[code] = Phrase.new(:code => code, :text => trans.text, :current_text => trans.text, :locale => locale, :updated_at => trans.approved_at, :updated_by => trans.approved_by, :default_translation => trans)
|
58
|
-
else
|
59
|
+
else
|
59
60
|
ph.default_translation = trans
|
60
61
|
end
|
61
62
|
end
|
@@ -68,4 +69,3 @@ module Ixtlan
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
end
|
71
|
-
|
data/lib/ixtlan/models/role.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
+
require 'dm-serializer'
|
1
2
|
module Ixtlan
|
2
3
|
module Models
|
3
4
|
class Role
|
4
5
|
|
5
6
|
include DataMapper::Resource
|
6
|
-
|
7
|
+
|
7
8
|
def self.default_storage_name
|
8
9
|
"Role"
|
9
10
|
end
|
10
11
|
|
11
|
-
property :name, String, :
|
12
|
+
property :name, String, :required => true , :format => /^[a-zA-Z0-9\-_.]*$/, :length => 32, :key => true
|
12
13
|
|
13
14
|
def hash
|
14
15
|
attribute_get(:name).hash
|
@@ -20,9 +21,9 @@ module Ixtlan
|
|
20
21
|
end
|
21
22
|
|
22
23
|
if protected_instance_methods.find {|m| m == 'to_x'}.nil?
|
23
|
-
|
24
|
+
|
24
25
|
protected
|
25
|
-
|
26
|
+
|
26
27
|
alias :to_x :to_xml_document
|
27
28
|
def to_xml_document(opts, doc = nil)
|
28
29
|
opts.merge!({:exclude => [:permission_resource,:permission_action]})
|
@@ -32,4 +33,3 @@ module Ixtlan
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
35
|
-
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'dm-serializer'
|
1
2
|
module Ixtlan
|
2
3
|
module Models
|
3
4
|
class Translation
|
@@ -6,17 +7,17 @@ module Ixtlan
|
|
6
7
|
def self.default_storage_name
|
7
8
|
"Translation"
|
8
9
|
end
|
9
|
-
|
10
|
+
|
10
11
|
property :id, Serial
|
11
12
|
|
12
|
-
property :text, String, :
|
13
|
-
|
14
|
-
property :previous_text, String, :
|
15
|
-
|
16
|
-
property :approved_at, DateTime, :
|
17
|
-
|
13
|
+
property :text, String, :required => true, :length => 256
|
14
|
+
|
15
|
+
property :previous_text, String, :required => false, :length => 256
|
16
|
+
|
17
|
+
property :approved_at, DateTime, :required => true, :auto_validation => false
|
18
|
+
|
18
19
|
belongs_to :approved_by, :model => Models::USER
|
19
|
-
|
20
|
+
|
20
21
|
def self.map_for(args = {})
|
21
22
|
map = {}
|
22
23
|
I18nText.latest_approved(args.dup).each do |text|
|
@@ -37,4 +38,3 @@ module Ixtlan
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
40
|
-
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
module Models
|
3
|
+
module UpdateChildren
|
4
|
+
|
5
|
+
def update_children(new_children, old_children_sym)
|
6
|
+
# get the dm-core/collection and its model
|
7
|
+
old_children = send(old_children_sym)
|
8
|
+
model = old_children.model
|
9
|
+
|
10
|
+
# make sure we have an array
|
11
|
+
if new_children.is_a?(Array)
|
12
|
+
# ids of new children
|
13
|
+
new_ids = new_children.collect { |v| v.to_i }
|
14
|
+
else
|
15
|
+
new_children = if new_children.nil?
|
16
|
+
[]
|
17
|
+
else
|
18
|
+
new_children[new_children.keys[0]]
|
19
|
+
end
|
20
|
+
new_children = [new_children] unless new_children.is_a? Array
|
21
|
+
|
22
|
+
# ids of new children
|
23
|
+
new_ids = new_children.collect { |v| v[:id].to_i }
|
24
|
+
end
|
25
|
+
|
26
|
+
# delete obsolete old children
|
27
|
+
old_children.select do |g|
|
28
|
+
!(new_ids.member? g.id)
|
29
|
+
end.each do |g|
|
30
|
+
old_children.delete(g)
|
31
|
+
end
|
32
|
+
|
33
|
+
# add missing new children
|
34
|
+
old_ids = old_children.collect { |g| g.id }
|
35
|
+
new_ids.each do |gid|
|
36
|
+
old_children << model.get!(gid) unless old_ids.member? gid
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_restricted_children(new_children, old_children_sym, allowed_children)
|
41
|
+
# get the dm-core/collection and its model
|
42
|
+
old_children = send(old_children_sym)
|
43
|
+
model = old_children.model
|
44
|
+
|
45
|
+
# make sure we have an array
|
46
|
+
new_children = if new_children.nil?
|
47
|
+
[]
|
48
|
+
else
|
49
|
+
new_children[new_children.keys[0]]
|
50
|
+
end
|
51
|
+
new_children = [new_children] unless new_children.is_a? Array
|
52
|
+
|
53
|
+
# ids of new children
|
54
|
+
new_ids = new_children.collect { |v| v[:id].to_i }
|
55
|
+
# ids of allowed children
|
56
|
+
allowed_ids = allowed_children.collect { |g| g.id }
|
57
|
+
|
58
|
+
# delete obsolete and allowed old children
|
59
|
+
set = old_children.select do |g|
|
60
|
+
!(new_ids.member? g.id) && (allowed_ids.member? g.id)
|
61
|
+
end
|
62
|
+
set.each do |g|
|
63
|
+
old_children.delete(g)
|
64
|
+
end
|
65
|
+
|
66
|
+
# add missing and allowed new children
|
67
|
+
old_ids = old_children.collect { |g| g.id }
|
68
|
+
new_ids.each do |gid|
|
69
|
+
old_children << model.get!(gid) if !old_ids.member?(gid) && allowed_ids.member?(gid)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/ixtlan/models/user.rb
CHANGED
@@ -2,10 +2,14 @@ require 'digest/sha1'
|
|
2
2
|
require 'base64'
|
3
3
|
require 'ixtlan/modified_by'
|
4
4
|
require 'dm-serializer'
|
5
|
+
require 'ixtlan/models/update_children'
|
5
6
|
module Ixtlan
|
6
7
|
module Models
|
7
8
|
class User
|
8
9
|
include DataMapper::Resource
|
10
|
+
include UpdateChildren
|
11
|
+
|
12
|
+
GROUP = Object.full_const_get(Models::GROUP)
|
9
13
|
|
10
14
|
def self.default_storage_name
|
11
15
|
"User"
|
@@ -13,15 +17,15 @@ module Ixtlan
|
|
13
17
|
|
14
18
|
property :id, Serial, :field => "uidnumber"
|
15
19
|
|
16
|
-
property :login, String, :
|
20
|
+
property :login, String, :required => true, :field => "uid", :length => 4..32, :unique_index => true, :format => /^[a-zA-Z0-9]*$/, :writer => :private
|
17
21
|
|
18
|
-
property :name, String, :
|
22
|
+
property :name, String, :required => true, :format => /^[^<">]*$/, :length => 2..64, :field => "cn"
|
19
23
|
|
20
|
-
property :email, String, :
|
24
|
+
property :email, String, :required => true, :format => :email_address, :required => true, :length => 8..64, :unique_index => true, :field => "mail"
|
21
25
|
|
22
|
-
property :language, String, :
|
26
|
+
property :language, String, :required => false, :format => /[a-z][a-z]/, :length => 2, :field => "preferredlanguage"
|
23
27
|
|
24
|
-
property :hashed_password, String, :
|
28
|
+
property :hashed_password, String, :required => false, :length => 128, :accessor => :private, :field => "userpassword"
|
25
29
|
|
26
30
|
timestamps :at
|
27
31
|
|
@@ -30,15 +34,15 @@ module Ixtlan
|
|
30
34
|
# Virtual attribute for the plaintext password
|
31
35
|
attr_reader :password
|
32
36
|
|
33
|
-
validates_is_unique :login
|
34
|
-
validates_is_unique :email
|
37
|
+
#validates_is_unique :login
|
38
|
+
#validates_is_unique :email
|
35
39
|
|
36
40
|
def reset_password(len = 12)
|
37
41
|
@password = Ixtlan::Passwords.generate(len)
|
38
42
|
attribute_set(:hashed_password, Ixtlan::Digest.ssha(@password, "--#{Time.now}--#{login}--"))
|
39
43
|
@password
|
40
44
|
end
|
41
|
-
|
45
|
+
|
42
46
|
def digest
|
43
47
|
::Base64.decode64(@hashed_password[6,200])
|
44
48
|
end
|
@@ -58,12 +62,20 @@ module Ixtlan
|
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
65
|
+
def self.first_or_get!(id_or_login)
|
66
|
+
first(:login => id_or_login) || get!(id_or_login)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.first_or_get(id_or_login)
|
70
|
+
first(:login => id_or_login) || get(id_or_login)
|
71
|
+
end
|
72
|
+
|
61
73
|
def groups
|
62
74
|
if @groups.nil?
|
63
75
|
# TODO spec the empty array to make sure new relations are stored
|
64
76
|
# in the database or the groups collection is empty before filling it
|
65
|
-
@groups = ::DataMapper::Collection.new(::DataMapper::Query.new(self.repository,
|
66
|
-
GroupUser.all(:memberuid => login).each do |gu|
|
77
|
+
@groups = ::DataMapper::Collection.new(::DataMapper::Query.new(self.repository, GROUP), [])
|
78
|
+
GroupUser.all(:memberuid => login).each do |gu|
|
67
79
|
@groups << gu.group
|
68
80
|
end
|
69
81
|
def @groups.user=(user)
|
@@ -72,22 +84,26 @@ module Ixtlan
|
|
72
84
|
@groups.user = self
|
73
85
|
def @groups.<<(group)
|
74
86
|
group.locales(@user)
|
87
|
+
group.domains(@user)
|
75
88
|
unless member? group
|
76
89
|
gu = GroupUser.create(:memberuid => @user.login, :gidnumber => group.id)
|
77
90
|
super
|
78
91
|
end
|
79
|
-
|
92
|
+
|
80
93
|
self
|
81
94
|
end
|
82
|
-
|
83
|
-
def @groups.delete(group)
|
95
|
+
|
96
|
+
def @groups.delete(group)
|
84
97
|
gu = GroupUser.first(:memberuid => @user.login, :gidnumber => group.id)
|
85
98
|
if gu
|
86
99
|
gu.destroy
|
87
100
|
end
|
88
101
|
super
|
89
102
|
end
|
90
|
-
@groups.each
|
103
|
+
@groups.each do |g|
|
104
|
+
g.locales(self)
|
105
|
+
g.domains(self)
|
106
|
+
end
|
91
107
|
end
|
92
108
|
@groups
|
93
109
|
end
|
@@ -97,13 +113,89 @@ module Ixtlan
|
|
97
113
|
attribute_set(:login, new_login) if login.nil?
|
98
114
|
end
|
99
115
|
|
116
|
+
def root?
|
117
|
+
groups.detect { |g| g.root? } || false
|
118
|
+
end
|
119
|
+
|
120
|
+
def locales_admin?
|
121
|
+
groups.detect { |g| g.locales_admin? } || false
|
122
|
+
end
|
123
|
+
|
124
|
+
def domains_admin?
|
125
|
+
groups.detect { |g| g.domains_admin? } || false
|
126
|
+
end
|
127
|
+
|
128
|
+
def update_all_children(new_groups)
|
129
|
+
if current_user.root?
|
130
|
+
# root has no restrictions
|
131
|
+
update_children(new_groups, :groups)
|
132
|
+
update_locales_domains(new_groups)
|
133
|
+
else
|
134
|
+
update_restricted_children(new_groups, :groups, current_user.groups)
|
135
|
+
if current_user.locales_admin? || current_user.domains_admin?
|
136
|
+
# locales/domains admin can use all locales/domains
|
137
|
+
update_locales_domains(new_groups)
|
138
|
+
end
|
139
|
+
if !current_user.locales_admin? || !current_user.domains_admin?
|
140
|
+
update_restricted_locales_domains(new_groups, current_user.groups)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def update_locales_domains(new_groups)
|
146
|
+
if(new_groups)
|
147
|
+
# make sure we have an array
|
148
|
+
new_groups = new_groups[:group]
|
149
|
+
new_groups = [new_groups] unless new_groups.is_a? Array
|
150
|
+
|
151
|
+
# create a map group_id => group
|
152
|
+
user_groups_map = {}
|
153
|
+
groups.each { |g| user_groups_map[g.id.to_s] = g }
|
154
|
+
|
155
|
+
# for each new groups update the locales/domains respectively
|
156
|
+
new_groups.each do |group|
|
157
|
+
if user_groups_map.key?(group[:id])
|
158
|
+
user_groups_map[group[:id]].update_children(group[:locales], :locales) if current_user.locales_admin? || current_user.root?
|
159
|
+
user_groups_map[group[:id]].update_children(group[:domains], :domains) if current_user.domains_admin? || current_user.root?
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def update_restricted_locales_domains(new_groups, ref_groups)
|
166
|
+
if(new_groups)
|
167
|
+
# make sure we have an array
|
168
|
+
new_groups = new_groups[:group]
|
169
|
+
new_groups = [new_groups] unless new_groups.is_a? Array
|
170
|
+
|
171
|
+
# create a map group_id => group
|
172
|
+
user_groups_map = {}
|
173
|
+
groups.each { |g| user_groups_map[g.id.to_s] = g }
|
174
|
+
# create a map group_id => group for the reference group
|
175
|
+
ref_group_locales = {}
|
176
|
+
ref_groups.each { |g| ref_group_locales[g.id.to_s] = g.locales }
|
177
|
+
ref_group_domains = {}
|
178
|
+
ref_groups.each { |g| ref_group_domains[g.id.to_s] = g.domains }
|
179
|
+
|
180
|
+
# for each new groups update the locales respectively
|
181
|
+
new_groups.each do |group|
|
182
|
+
if user_groups_map.key?(group[:id])
|
183
|
+
user_groups_map[group[:id]].update_restricted_children(group[:locales], :locales, ref_group_locales[group[:id]] || []) unless current_user.locales_admin?
|
184
|
+
user_groups_map[group[:id]].update_restricted_children(group[:domains], :domains, ref_group_domains[group[:id]] || []) unless current_user.domains_admin?
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
100
190
|
if protected_instance_methods.find {|m| m == 'to_x'}.nil?
|
101
|
-
alias :to_x :to_xml_document
|
191
|
+
alias :to_x :to_xml_document
|
102
192
|
|
103
193
|
protected
|
104
194
|
|
105
195
|
def to_xml_document(opts={}, doc = nil)
|
106
|
-
opts
|
196
|
+
unless(opts[:methods] || opts[:exclude])
|
197
|
+
opts.merge!({:exclude => [:hashed_password], :methods => [:groups]})
|
198
|
+
end
|
107
199
|
to_x(opts, doc)
|
108
200
|
end
|
109
201
|
end
|
data/lib/ixtlan/models/word.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
require 'dm-serializer'
|
1
2
|
module Ixtlan
|
2
3
|
module Models
|
3
4
|
class Word < Ixtlan::Models::I18nText
|
4
5
|
|
5
6
|
alias :to_x :to_xml_document
|
6
7
|
def to_xml_document(opts, doc = nil)
|
7
|
-
opts.merge!({:element_name => "word", :exclude => [:id, :
|
8
|
+
opts.merge!({:element_name => "word", :exclude => [:id, :locale_id, :current, :previous, :updated_at, :approved_at, :updated_by_id, :approved_by_id, :version]})
|
8
9
|
to_x(opts, doc)
|
9
10
|
end
|
10
11
|
end
|
data/lib/ixtlan/models.rb
CHANGED
@@ -6,6 +6,7 @@ module Ixtlan
|
|
6
6
|
ROLE = "::Ixtlan::Models::Role" unless const_defined? "ROLE"
|
7
7
|
PERMISSION = "::Ixtlan::Models::Permission" unless const_defined? "PERMISSION"
|
8
8
|
LOCALE = "::Ixtlan::Models::Locale" unless const_defined? "LOCALE"
|
9
|
+
DOMAIN = "::Ixtlan::Models::Domain" unless const_defined? "DOMAIN"
|
9
10
|
CONFIGURATION = "::Ixtlan::Models::Configuration" unless const_defined? "CONFIGURATION"
|
10
11
|
TRANSLATION = "::Ixtlan::Models::Translation" unless const_defined? "TRANSLATION"
|
11
12
|
TEXT = "::Ixtlan::Models::I18nText" unless const_defined? "TEXT"
|
data/lib/ixtlan/modified_by.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
#require 'dm-core'
|
2
2
|
module Ixtlan
|
3
3
|
|
4
|
-
module ModifiedBy
|
4
|
+
module ModifiedBy
|
5
5
|
extend ::DataMapper::Chainable
|
6
6
|
|
7
7
|
MODIFIED_BY_PROPERTIES = {
|
8
8
|
:updated_by => lambda {|r, u| r.updated_by = u},
|
9
|
-
:created_by => lambda {|r, u| r.created_by = u if r.new?
|
9
|
+
:created_by => lambda {|r, u| r.created_by = u #if r.new?
|
10
|
+
}
|
10
11
|
}.freeze
|
11
12
|
|
12
13
|
def self.included(model)
|
@@ -22,7 +23,7 @@ module Ixtlan
|
|
22
23
|
|
23
24
|
def current_user
|
24
25
|
raise ::DataMapper::MissingCurrentUserError.new("current_user not set. it can be set like any other property") unless @current_user
|
25
|
-
|
26
|
+
|
26
27
|
@current_user
|
27
28
|
end
|
28
29
|
|
@@ -56,14 +57,15 @@ module Ixtlan
|
|
56
57
|
end
|
57
58
|
|
58
59
|
module ClassMethods
|
59
|
-
def modified_by(type,
|
60
|
-
if(names.
|
61
|
-
modified_by(type, :created_by, :updated_by)
|
60
|
+
def modified_by(type, names = nil, options = {})
|
61
|
+
if(names.nil?)
|
62
|
+
modified_by(type, [:created_by, :updated_by])
|
62
63
|
else
|
64
|
+
names = [names] unless names.is_a?(Enumerable)
|
63
65
|
names.each do |name|
|
64
66
|
case name
|
65
67
|
when *MODIFIED_BY_PROPERTIES.keys
|
66
|
-
belongs_to name, :model => type.to_s
|
68
|
+
belongs_to name, options.merge!({:model => type.to_s})
|
67
69
|
else
|
68
70
|
raise ::DataMapper::InvalidModifiedByName, "Invalid 'modified by' name '#{name}'"
|
69
71
|
end
|
@@ -12,8 +12,8 @@ module Extlib
|
|
12
12
|
module Assertions
|
13
13
|
def assert_kind_of(name, value, *klasses)
|
14
14
|
# be less strict and allow matching class names to OK as well
|
15
|
-
klasses.each { |k| return if value.kind_of?(k) or value.class.name == k.name }
|
16
|
-
raise ArgumentError, "
|
15
|
+
klasses.each { |k| return if value.kind_of?(k) or value.class.name == k.name }
|
16
|
+
raise ArgumentError, "+#{name}+ should be #{klasses.map { |k| k.name } * ' or '}, but was #{value.class.name}", caller(2)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -21,15 +21,15 @@ if RUBY_PLATFORM =~ /java/
|
|
21
21
|
module DataMapper
|
22
22
|
module Validate
|
23
23
|
class NumericValidator
|
24
|
-
|
24
|
+
|
25
25
|
def validate_with_comparison(value, cmp, expected, error_message_name, errors, negated = false)
|
26
26
|
return if expected.nil?
|
27
|
-
if cmp == :=~
|
27
|
+
if cmp == :=~
|
28
28
|
return value =~ expected
|
29
29
|
end
|
30
30
|
comparison = value.send(cmp, expected)
|
31
31
|
return if negated ? !comparison : comparison
|
32
|
-
|
32
|
+
|
33
33
|
errors << ValidationErrors.default_error_message(error_message_name, field_name, expected)
|
34
34
|
end
|
35
35
|
end
|
@@ -6,10 +6,10 @@ module Ixtlan
|
|
6
6
|
qu = {}
|
7
7
|
c = model.key_conditions(repository, key)
|
8
8
|
c.each {|p,v| qu[p.name] = v}
|
9
|
-
|
9
|
+
|
10
10
|
s = self.model.first(qu)
|
11
|
-
if s.nil?
|
12
|
-
false
|
11
|
+
if s.nil?
|
12
|
+
false
|
13
13
|
else
|
14
14
|
# use to_s to get it to work in both MRI and JRuby
|
15
15
|
s.updated_at.to_s != updated_at.to_s
|
@@ -3,9 +3,9 @@ require 'ixtlan/optimistic_persistence_module'
|
|
3
3
|
module DataMapper
|
4
4
|
|
5
5
|
class StaleResource < StandardError; end
|
6
|
-
|
6
|
+
|
7
7
|
module OptimisticPersistenceValidation
|
8
|
-
|
8
|
+
|
9
9
|
def self.included(base)
|
10
10
|
base.send(:include, ::Ixtlan::OptimisticPersistenceModule)
|
11
11
|
base.validates_with_block :stale do
|
data/lib/ixtlan/passwords.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
module Ixtlan
|
2
2
|
class Passwords
|
3
3
|
def self.generate(length=64)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
if length > 0
|
5
|
+
# A-Z starting with 97 and having 26 characters
|
6
|
+
# a-z starting with 65 and having 26 characters
|
7
|
+
# 0-9 starting with 48 and lies inside range starting with 33 and having 26 characters
|
8
|
+
offset=[97, 65, 33]
|
9
|
+
|
10
|
+
# collect random characters from the either of the above ranges
|
11
|
+
begin
|
12
|
+
pwd = (0..(length - 1)).collect do
|
13
|
+
j = ActiveSupport::SecureRandom.random_number(78)
|
14
|
+
(offset[j / 26] + (j % 26)).chr
|
15
|
+
end.join
|
16
|
+
end while !((pwd =~ /[a-z]/) && (pwd =~ /[A-Z]/) && (pwd =~ /[!-;]/))
|
17
|
+
pwd
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|