ixtlan 0.2.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/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
|