ixtlan 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +64 -0
- data/README.txt +86 -0
- data/Rakefile +38 -0
- data/generators/ixtlan_datamapper_model/ixtlan_datamapper_model_generator.rb +20 -0
- data/generators/ixtlan_datamapper_model/templates/model.rb +17 -0
- data/generators/ixtlan_datamapper_rspec_model/ixtlan_datamapper_rspec_model_generator.rb +20 -0
- data/generators/ixtlan_datamapper_rspec_model/templates/model_spec.rb +58 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/ixtlan_datamapper_rspec_scaffold_generator.rb +37 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/controller.rb +99 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/controller_spec.rb +206 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/guard.rb +8 -0
- data/generators/ixtlan_datamapper_rspec_scaffold/templates/i18n.rb +11 -0
- data/lib/dm-serializer/common.rb +28 -0
- data/lib/dm-serializer/to_xml.rb +99 -0
- data/lib/dm-serializer/xml_serializers/libxml.rb +42 -0
- data/lib/dm-serializer/xml_serializers/nokogiri.rb +36 -0
- data/lib/dm-serializer/xml_serializers/rexml.rb +30 -0
- data/lib/dm-serializer/xml_serializers.rb +17 -0
- data/lib/dm-serializer.rb +1 -0
- data/lib/ixtlan/audit_config.rb +35 -0
- data/lib/ixtlan/cms_script.rb +29 -0
- data/lib/ixtlan/controllers/texts_controller.rb +65 -0
- data/lib/ixtlan/digest.rb +15 -0
- data/lib/ixtlan/error_notifier/error_notification.rhtml +1 -0
- data/lib/ixtlan/guard.rb +125 -0
- data/lib/ixtlan/logger_config.rb +65 -0
- data/lib/ixtlan/models/authentication.rb +30 -0
- data/lib/ixtlan/models/configuration.rb +74 -0
- data/lib/ixtlan/models/configuration_locale.rb +19 -0
- data/lib/ixtlan/models/group.rb +69 -0
- data/lib/ixtlan/models/group_locale_user.rb +22 -0
- data/lib/ixtlan/models/group_user.rb +39 -0
- data/lib/ixtlan/models/locale.rb +37 -0
- data/lib/ixtlan/models/permission.rb +29 -0
- data/lib/ixtlan/models/phrase.rb +71 -0
- data/lib/ixtlan/models/role.rb +35 -0
- data/lib/ixtlan/models/text.rb +140 -0
- data/lib/ixtlan/models/translation.rb +40 -0
- data/lib/ixtlan/models/user.rb +112 -0
- data/lib/ixtlan/models/word.rb +12 -0
- data/lib/ixtlan/models.rb +13 -0
- data/lib/ixtlan/modified_by.rb +80 -0
- data/lib/ixtlan/monkey_patches.rb +38 -0
- data/lib/ixtlan/optimistic_persistence.rb +20 -0
- data/lib/ixtlan/optimistic_persistence_module.rb +22 -0
- data/lib/ixtlan/optimistic_persistence_validation.rb +21 -0
- data/lib/ixtlan/passwords.rb +19 -0
- data/lib/ixtlan/rails/audit.rb +22 -0
- data/lib/ixtlan/rails/error_handling.rb +130 -0
- data/lib/ixtlan/rails/guard.rb +11 -0
- data/lib/ixtlan/rails/session_timeout.rb +93 -0
- data/lib/ixtlan/rails/timestamps_modified_by_filter.rb +33 -0
- data/lib/ixtlan/rails/unrestful_authentication.rb +137 -0
- data/lib/ixtlan/rolling_file.rb +61 -0
- data/lib/ixtlan/session.rb +18 -0
- data/lib/ixtlan/user_logger.rb +49 -0
- data/lib/ixtlan/version.rb +3 -0
- data/lib/ixtlan.rb +2 -0
- data/lib/models.rb +14 -0
- data/spec/authentication_spec.rb +30 -0
- data/spec/guard_spec.rb +125 -0
- data/spec/guards/samples.rb +12 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +170 -0
- metadata +210 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Serialize
|
3
|
+
# Returns propreties to serialize based on :only or :exclude arrays, if provided
|
4
|
+
# :only takes precendence over :exclude
|
5
|
+
#
|
6
|
+
# @return <Array> properties that need to be serialized
|
7
|
+
def properties_to_serialize(options)
|
8
|
+
only_properties = Array(options[:only])
|
9
|
+
excluded_properties = Array(options[:exclude])
|
10
|
+
|
11
|
+
model.properties(repository.name).reject do |p|
|
12
|
+
if only_properties.include? p.name
|
13
|
+
false
|
14
|
+
else
|
15
|
+
excluded_properties.include?(p.name) || !(only_properties.empty? || only_properties.include?(p.name))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Model.append_inclusions self
|
21
|
+
|
22
|
+
class Support
|
23
|
+
def self.dm_validations_loaded?
|
24
|
+
DataMapper.const_defined?("Validate")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'dm-serializer/common'
|
2
|
+
require 'dm-serializer/xml_serializers'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
module DataMapper
|
6
|
+
module Serialize
|
7
|
+
# Serialize a Resource to XML
|
8
|
+
#
|
9
|
+
# @return <REXML::Document> an XML representation of this Resource
|
10
|
+
def to_xml(opts = {})
|
11
|
+
xml = XMLSerializers::SERIALIZER
|
12
|
+
xml.output(to_xml_document(opts)).to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
# This method requires certain methods to be implemented in the individual
|
17
|
+
# serializer library subclasses:
|
18
|
+
# new_document
|
19
|
+
# root_node
|
20
|
+
# add_property_node
|
21
|
+
# add_node
|
22
|
+
def to_xml_document(opts={}, doc = nil)
|
23
|
+
xml = XMLSerializers::SERIALIZER
|
24
|
+
doc ||= xml.new_document
|
25
|
+
default_xml_element_name = lambda { Extlib::Inflection.underscore(model.storage_name.singular).tr("/", "-") }
|
26
|
+
root = xml.root_node(doc, opts[:element_name] || default_xml_element_name[])
|
27
|
+
properties_to_serialize(opts).each do |property|
|
28
|
+
value = __send__(property.name)
|
29
|
+
attrs = (property.type == String) ? {} : {'type' => property.type.to_s.downcase}
|
30
|
+
value = value.to_s(:xml) if property.type == DateTime rescue value
|
31
|
+
xml.add_node(root, property.name.to_s, value.frozen? ? value.to_s.dup: value, attrs)
|
32
|
+
end
|
33
|
+
|
34
|
+
(opts[:methods] || []).each do |meth|
|
35
|
+
if self.respond_to?(meth)
|
36
|
+
xml_name = meth.to_s.gsub(/[^a-z0-9_]/, '')
|
37
|
+
value = __send__(meth)
|
38
|
+
unless value.nil?
|
39
|
+
if value.respond_to?(:to_xml_document)
|
40
|
+
xml.add_xml(root, value.__send__(:to_xml_document, value.is_a?(DataMapper::Collection) ? {:collection_element_name => xml_name} : {:element_name => xml_name}))
|
41
|
+
else
|
42
|
+
xml.add_node(root, xml_name, value.to_s)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
doc
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Collection
|
52
|
+
def to_xml(opts = {})
|
53
|
+
to_xml_document(opts).to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def to_xml_document(opts = {})
|
59
|
+
xml = DataMapper::Serialize::XMLSerializers::SERIALIZER
|
60
|
+
doc = xml.new_document
|
61
|
+
default_collection_element_name = lambda {Extlib::Inflection.underscore(self.model.storage_name).tr("/", "-")}
|
62
|
+
root = xml.root_node(doc, opts[:collection_element_name] || default_collection_element_name[], {'type' => 'array'})
|
63
|
+
self.each do |item|
|
64
|
+
item.__send__(:to_xml_document, opts, doc)
|
65
|
+
end
|
66
|
+
doc
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if Serialize::Support.dm_validations_loaded?
|
71
|
+
|
72
|
+
module Validate
|
73
|
+
class ValidationErrors
|
74
|
+
def to_xml(opts = {})
|
75
|
+
to_xml_document(opts).to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def to_xml_document(opts = {})
|
81
|
+
xml = DataMapper::Serialize::XMLSerializers::SERIALIZER
|
82
|
+
doc = xml.new_document
|
83
|
+
root = xml.root_node(doc, "errors", {'type' => 'hash'})
|
84
|
+
|
85
|
+
errors.each do |key, value|
|
86
|
+
property = xml.add_node(root, key.to_s, nil, {'type' => 'array'})
|
87
|
+
property.attributes["type"] = 'array'
|
88
|
+
value.each do |error|
|
89
|
+
xml.add_node(property, "error", error)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
doc
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Serialize
|
3
|
+
module XMLSerializers
|
4
|
+
module LibXML
|
5
|
+
def self.new_document
|
6
|
+
::LibXML::XML::Document.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.root_node(doc, name, attrs = {})
|
10
|
+
root = ::LibXML::XML::Node.new(name)
|
11
|
+
attrs.each do |attr_name, attr_val|
|
12
|
+
root[attr_name] = attr_val
|
13
|
+
end
|
14
|
+
doc.root.nil? ? doc.root = root : doc.root << root
|
15
|
+
root
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.add_node(parent, name, value, attrs = {})
|
19
|
+
value_str = value.to_s unless value.nil?
|
20
|
+
node = ::LibXML::XML::Node.new(name, value_str)
|
21
|
+
attrs.each do |attr_name, attr_val|
|
22
|
+
node[attr_name] = attr_val
|
23
|
+
end
|
24
|
+
parent << node
|
25
|
+
node
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.add_xml(parent, xml)
|
29
|
+
parent << xml.root.copy(true)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.add_xml(parent, xml)
|
33
|
+
parent << xml.root.copy(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.output(doc)
|
37
|
+
doc.root.to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Serialize
|
3
|
+
module XMLSerializers
|
4
|
+
module Nokogiri
|
5
|
+
def self.new_document
|
6
|
+
::Nokogiri::XML::Document.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.root_node(doc, name, attrs = {})
|
10
|
+
root = ::Nokogiri::XML::Node.new(name, doc)
|
11
|
+
attrs.each do |attr_name, attr_val|
|
12
|
+
root[attr_name] = attr_val
|
13
|
+
end
|
14
|
+
doc.root.nil? ? doc.root = root : doc.root << root
|
15
|
+
root
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.add_node(parent, name, value, attrs = {})
|
19
|
+
node = ::Nokogiri::XML::Node.new(name, parent.document)
|
20
|
+
node << ::Nokogiri::XML::Text.new(value.to_s, parent.document) unless value.nil?
|
21
|
+
attrs.each {|attr_name, attr_val| node[attr_name] = attr_val }
|
22
|
+
parent << node
|
23
|
+
node
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.add_xml(parent, xml)
|
27
|
+
parent << xml.root
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.output(doc)
|
31
|
+
doc.root.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Serialize
|
3
|
+
module XMLSerializers
|
4
|
+
module REXML
|
5
|
+
def self.new_document
|
6
|
+
::REXML::Document.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.root_node(document, name, attrs = {})
|
10
|
+
add_node(document.root || document, name, nil, attrs)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.add_node(parent, name, value, attrs = {})
|
14
|
+
node = parent.add_element(name)
|
15
|
+
attrs.each {|attr_name, attr_val| node.attributes[attr_name] = attr_val}
|
16
|
+
node << ::REXML::Text.new(value.to_s) unless value.nil?
|
17
|
+
node
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.add_xml(parent, xml)
|
21
|
+
parent.add(xml)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.output(doc)
|
25
|
+
doc.to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'dm-serializer/xml_serializers/rexml'
|
2
|
+
require 'dm-serializer/xml_serializers/nokogiri'
|
3
|
+
require 'dm-serializer/xml_serializers/libxml'
|
4
|
+
|
5
|
+
module DataMapper
|
6
|
+
module Serialize
|
7
|
+
module XMLSerializers
|
8
|
+
SERIALIZER = if defined?(::LibXML)
|
9
|
+
LibXML
|
10
|
+
elsif defined?(::Nokogiri)
|
11
|
+
Nokogiri
|
12
|
+
else
|
13
|
+
REXML
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'dm-serializer/to_xml'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'ixtlan/audit'
|
2
|
+
|
3
|
+
Logging.init :debug, :info, :warn, :error, :fatal unless Logging.const_defined? 'MAX_LEVEL_LENGTH'
|
4
|
+
|
5
|
+
module Ixtlan
|
6
|
+
class AuditConfig
|
7
|
+
|
8
|
+
@logger = Logging::Logger[self]
|
9
|
+
|
10
|
+
def self.configure(keep, file, categories)
|
11
|
+
@@categories = categories
|
12
|
+
reconfigure(keep, file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.reconfigure(keep, file)
|
16
|
+
audit_appender =
|
17
|
+
RollingFile.new('audit',
|
18
|
+
{ :filename_base => file,
|
19
|
+
:keep => keep,
|
20
|
+
:safe => true,
|
21
|
+
:layout => Logging::Layouts::Pattern.new(:pattern => "%d %m\n") }
|
22
|
+
)
|
23
|
+
|
24
|
+
@@categories.each do |category|
|
25
|
+
logger = Logging::Logger[category]
|
26
|
+
logger.remove_appenders('audit')
|
27
|
+
logger.add_appenders(audit_appender)
|
28
|
+
@logger.debug("setup logger for #{category}")
|
29
|
+
end
|
30
|
+
@logger.info("initialized audit log . . .")
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
class CmsScript
|
3
|
+
def initialize(app, rootpath = "/ixtlan")
|
4
|
+
@app = app
|
5
|
+
@rootpath = rootpath
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
dup._call(env)
|
10
|
+
end
|
11
|
+
|
12
|
+
def _call(env)
|
13
|
+
if(env['REQUEST_PATH'] =~ /^#{@rootpath}\//)
|
14
|
+
|
15
|
+
file = Rails.public_path.to_s + env['REQUEST_PATH'].sub(/^#{@rootpath}/, '')
|
16
|
+
@file = File.open(file)
|
17
|
+
[@status, {}, self]
|
18
|
+
else
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def each(&block)
|
24
|
+
@file.each do |line|
|
25
|
+
block.call(line.sub(/<\/head>/, "<link type='text/css' rel='stylesheet' href='#{@rootpath}/embed.css'></link><script type='text/javascript' language='javascript' src='#{@rootpath}/embed.nocache.js'></script></head>"))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
module Controllers
|
3
|
+
module TextsController
|
4
|
+
|
5
|
+
LOCALE = Object.full_const_get(::Ixtlan::Models::LOCALE)
|
6
|
+
TEXT = Object.full_const_get(::Ixtlan::Models::TEXT)
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def locale_guard
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
public
|
15
|
+
|
16
|
+
def index
|
17
|
+
version = params[:version]
|
18
|
+
|
19
|
+
@texts = TEXT.all(:locale => LOCALE.get!(params[:locale]))
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
phrase = params[:phrase]
|
24
|
+
|
25
|
+
locale = LOCALE.get!(phrase.delete(:locale))
|
26
|
+
|
27
|
+
if(TEXT.count(:version => nil, :code => phrase[:code], :locale => locale) == 1)
|
28
|
+
raise "TODO precondition failed"
|
29
|
+
end
|
30
|
+
|
31
|
+
phrase[:text] ||= phrase.delete(:current_text)
|
32
|
+
phrase[:locale] = locale
|
33
|
+
|
34
|
+
@text = TEXT.new(phrase)
|
35
|
+
|
36
|
+
respond_to do |format|
|
37
|
+
if @text.save
|
38
|
+
flash[:notice] = 'Text was successfully created.'
|
39
|
+
format.html { redirect_to(text_url(@text.id)) }
|
40
|
+
format.xml { render :xml => @text, :status => :created }
|
41
|
+
else
|
42
|
+
format.html { render :action => "new" }
|
43
|
+
format.xml { render :xml => @text.errors, :status => :unprocessable_entity }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def update
|
49
|
+
phrase = params[:phrase]
|
50
|
+
phrase[:text] ||= phrase.delete(:current_text)
|
51
|
+
|
52
|
+
respond_to do |format|
|
53
|
+
if @text.update(phrase)
|
54
|
+
flash[:notice] = phrase[:text].nil? ? 'Text was successfully approved.' : 'Text was successfully updated.'
|
55
|
+
format.html { redirect_to(text_url(@text.id)) }
|
56
|
+
format.xml { render :xml => @text, :status => :ok }
|
57
|
+
else
|
58
|
+
format.html { render :action => "edit" }
|
59
|
+
format.xml { render :xml => @text.errors, :status => :unprocessable_entity }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
class Digest
|
3
|
+
# method from openldap faq which produces the userPassword attribute
|
4
|
+
# for the ldap
|
5
|
+
# @param secret String the password
|
6
|
+
# @param salt String the salt for the password digester
|
7
|
+
# @return the encoded password/salt
|
8
|
+
def self.ssha(secret, salt)
|
9
|
+
require 'sha1'
|
10
|
+
require 'base64'
|
11
|
+
(salt.empty? ? "{SHA}": "{SSHA}") +
|
12
|
+
Base64.encode64(::Digest::SHA1.digest(secret + salt) + salt).gsub(/\n/, '')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @text %>
|
data/lib/ixtlan/guard.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
module ActionController #:nodoc:
|
3
|
+
module Guard #:nodoc:
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
end
|
7
|
+
module InstanceMethods #:nodoc:
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def guard(locale = nil)
|
12
|
+
guard!(params[:controller], params[:action], locale)
|
13
|
+
end
|
14
|
+
|
15
|
+
def guard!(resource, action, locale = nil)
|
16
|
+
unless ::Ixtlan::Guard.check(self, resource, action, locale)
|
17
|
+
raise ::Ixtlan::PermissionDenied.new("permission denied for '#{resource}##{action}'")
|
18
|
+
end
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Allowed #:nodoc:
|
26
|
+
# Inclusion hook to make #allowed available as method
|
27
|
+
def self.included(base)
|
28
|
+
base.send(:include, InstanceMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
module InstanceMethods #:nodoc:
|
32
|
+
def allowed(resource, action, locale = nil)
|
33
|
+
::Ixtlan::Guard.check(helpers.controller, resource, action, locale)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Guard
|
39
|
+
|
40
|
+
@@map = {}
|
41
|
+
|
42
|
+
def self.load(logger = Logger.new(STDOUT), superuser = :root, guard_dir = "#{RAILS_ROOT}/app/guards", &block)
|
43
|
+
@@block =
|
44
|
+
if block
|
45
|
+
block
|
46
|
+
else
|
47
|
+
Proc.new do |controller|
|
48
|
+
user = controller.send :current_user
|
49
|
+
user.groups if user
|
50
|
+
end
|
51
|
+
end
|
52
|
+
DataMapper.setup(:guard_memory, :adapter => :in_memory)
|
53
|
+
@@logger = logger
|
54
|
+
@@superuser = superuser
|
55
|
+
if File.exists?(guard_dir)
|
56
|
+
Dir.new(guard_dir).to_a.each do |f|
|
57
|
+
if f.match(".rb$")
|
58
|
+
require(File.join(guard_dir, f))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
logger.debug("initialized guard . . .")
|
62
|
+
else
|
63
|
+
logger.warn("guard directory #{guard_dir} not found, skip loading")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.initialize(controller, map)
|
68
|
+
msg = map.collect{ |k,v| "\n\t#{k} => [#{v.join(',')}]"}
|
69
|
+
@@logger.debug("#{controller} guard: #{msg}")
|
70
|
+
@@map[controller] = map
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.export_xml
|
74
|
+
repository(:guard_memory) do
|
75
|
+
role_const = Object.full_const_get(Models::ROLE)
|
76
|
+
permission_const = Object.full_const_get(Models::PERMISSION)
|
77
|
+
root = role_const.create(:name => @@superuser)
|
78
|
+
@@map.each do |controller, actions|
|
79
|
+
actions.each do |action, roles|
|
80
|
+
permission = permission_const.create(:resource => controller, :action => action)
|
81
|
+
permission.roles << root
|
82
|
+
roles.each do |role|
|
83
|
+
r = role_const.create(:name => role)
|
84
|
+
permission.roles << r unless permission.roles.member? r
|
85
|
+
end
|
86
|
+
permission.save
|
87
|
+
end
|
88
|
+
end
|
89
|
+
xml = permission_const.all.to_xml
|
90
|
+
permission_const.all.destroy!
|
91
|
+
role_const.all.destroy!
|
92
|
+
xml
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.check(controller, resource, action, locale = nil)
|
97
|
+
groups = @@block.call(controller)
|
98
|
+
return true if groups.nil?
|
99
|
+
resource = resource.to_sym
|
100
|
+
if (@@map.key? resource)
|
101
|
+
action = action.to_sym
|
102
|
+
allowed = @@map[resource][action]
|
103
|
+
if (allowed.nil?)
|
104
|
+
@@logger.warn("unknown action '#{action}' for controller '#{resource}'")
|
105
|
+
raise ::Ixtlan::GuardException.new("unknown action '#{action}' for controller '#{resource}'")
|
106
|
+
else
|
107
|
+
allowed << @@superuser unless allowed.member? @@superuser
|
108
|
+
for group in groups
|
109
|
+
if allowed.member? group.name.to_sym
|
110
|
+
return locale.nil? ? true : (group.locales.member? locale)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
else
|
116
|
+
@@logger.warn("unknown controller '#{resource}'")
|
117
|
+
raise ::Ixtlan::GuardException.new("unknown controller '#{resource}'")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class GuardException < Exception; end
|
123
|
+
class PermissionDenied < GuardException; end
|
124
|
+
end
|
125
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# use logging logger for slf4r logger facade
|
2
|
+
require 'slf4r/logging_logger'
|
3
|
+
|
4
|
+
require 'ixtlan/rolling_file'
|
5
|
+
|
6
|
+
module Ixtlan
|
7
|
+
class LoggerConfig
|
8
|
+
def self.rolling_appender(name)
|
9
|
+
appender = Ixtlan::RollingFile.new(name,
|
10
|
+
:filename_base => log_filebase(name),
|
11
|
+
:keep => 2,
|
12
|
+
:date_pattern => '%Y-%m')
|
13
|
+
appender.layout = Logging::Layouts::Pattern.new(:pattern => "%d [%-l] (%c) %m\n")
|
14
|
+
appender
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.logger(appender, category, level = :warn)
|
18
|
+
logger = Logging::Logger.new(category)
|
19
|
+
logger.add_appenders(appender)
|
20
|
+
logger.level = log_level(level)
|
21
|
+
logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.log_filebase(name)
|
25
|
+
::Rails.root.join('log', name).to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.log_level(level = :warn)
|
29
|
+
ENV['RAILS_ENV'] == 'production' ? level : :debug
|
30
|
+
end
|
31
|
+
|
32
|
+
Logging.init :debug, :info, :warn, :error, :fatal unless Logging.const_defined? 'MAX_LEVEL_LENGTH'
|
33
|
+
|
34
|
+
# setup rails logger
|
35
|
+
rails_appender = Logging::Appenders::File.new('rails',
|
36
|
+
:filename => log_filebase(RAILS_ENV) + ".log")
|
37
|
+
rails_appender.layout = Logging::Layouts::Pattern.new(:pattern => "%-20c\t- %m\n")
|
38
|
+
|
39
|
+
logger = logger(rails_appender, Rails)
|
40
|
+
logger.info "initialized logger ..."
|
41
|
+
|
42
|
+
# datamapper + dataobject logger
|
43
|
+
appender = rolling_appender('sql')
|
44
|
+
|
45
|
+
DataMapper.logger = logger([appender,rails_appender], DataMapper)
|
46
|
+
|
47
|
+
#TODO better find out which database !!!
|
48
|
+
DataObjects::Sqlite3.logger = logger([appender,rails_appender], DataObjects)
|
49
|
+
|
50
|
+
# configure audit logger
|
51
|
+
Ixtlan::AuditConfig.configure(Ixtlan::Models::Configuration.instance.keep_audit_logs,
|
52
|
+
log_filebase('audit'),
|
53
|
+
[
|
54
|
+
Ixtlan::Models::User,
|
55
|
+
Ixtlan::Rails::Audit,
|
56
|
+
Ixtlan::Rails::SessionTimeout,
|
57
|
+
Ixtlan::Rails::UnrestfulAuthentication,
|
58
|
+
Ixtlan::Rails::ErrorHandling
|
59
|
+
] )
|
60
|
+
|
61
|
+
# keep the guard messages in a separate file as well
|
62
|
+
logger(rolling_appender('guard'), Ixtlan::Guard, :info)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
module Models
|
3
|
+
class Authentication
|
4
|
+
include DataMapper::Resource
|
5
|
+
|
6
|
+
def self.name
|
7
|
+
"Authentication"
|
8
|
+
end
|
9
|
+
|
10
|
+
property :login, String,:format => /^[a-zA-Z0-9\-!=+$%^&*\(\){}|\[\]<>_.]*$/, :key => true
|
11
|
+
|
12
|
+
property :password, String,:format => /^[a-zA-Z0-9_.]*$/
|
13
|
+
|
14
|
+
attr_accessor :token
|
15
|
+
|
16
|
+
belongs_to :user, :model => ::Ixtlan::Models::USER
|
17
|
+
|
18
|
+
if protected_instance_methods.find {|m| m == 'to_x'}.nil?
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
alias :to_x :to_xml_document
|
23
|
+
def to_xml_document(opts, doc = nil)
|
24
|
+
opts.merge!({:exclude => [:password,:user_id], :methods => [:token, :user]})
|
25
|
+
to_x(opts, doc)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|