cmis_server 1.0.3
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +51 -0
- data/app/assets/javascripts/cmis_server/application.js +13 -0
- data/app/assets/stylesheets/cmis_server/application.css +15 -0
- data/app/controllers/cmis_server/application_controller.rb +19 -0
- data/app/controllers/cmis_server/atom_pub/base_controller.rb +23 -0
- data/app/controllers/cmis_server/atom_pub/bulk_controller.rb +302 -0
- data/app/controllers/cmis_server/atom_pub/content_controller.rb +178 -0
- data/app/controllers/cmis_server/atom_pub/entries_controller.rb +41 -0
- data/app/controllers/cmis_server/atom_pub/folder_collection_controller.rb +70 -0
- data/app/controllers/cmis_server/atom_pub/query_controller.rb +138 -0
- data/app/controllers/cmis_server/atom_pub/repository_controller.rb +75 -0
- data/app/controllers/cmis_server/atom_pub/secondary_types_controller.rb +149 -0
- data/app/controllers/cmis_server/atom_pub/service_documents_controller.rb +34 -0
- data/app/controllers/cmis_server/atom_pub/types_controller.rb +229 -0
- data/app/controllers/cmis_server/atom_pub/uri_templates_controller.rb +58 -0
- data/app/controllers/concerns/cmis_server/atom_pub/repository_scopable.rb +18 -0
- data/app/helpers/cmis_server/application_helper.rb +31 -0
- data/app/models/cmis_server/application_record.rb +5 -0
- data/app/services/cmis_server/bulk_update_service.rb +69 -0
- data/app/services/cmis_server/content_stream_service.rb +75 -0
- data/app/services/cmis_server/discovery_service.rb +31 -0
- data/app/services/cmis_server/navigation_service.rb +43 -0
- data/app/services/cmis_server/object_service.rb +176 -0
- data/app/services/cmis_server/repository_service.rb +40 -0
- data/app/services/cmis_server/secondary_type_service.rb +120 -0
- data/app/services/cmis_server/type_management_service.rb +117 -0
- data/app/views/cmis_server/atom_pub/bulk_update_feed.atom.builder +47 -0
- data/app/views/cmis_server/atom_pub/entries/_cmis_document_links.atom_entry.builder +0 -0
- data/app/views/cmis_server/atom_pub/entries/_cmis_folder_links.atom_entry.builder +3 -0
- data/app/views/cmis_server/atom_pub/entries/_object_entry.atom_entry.builder +64 -0
- data/app/views/cmis_server/atom_pub/entries/_property.atom_entry.builder +8 -0
- data/app/views/cmis_server/atom_pub/entries/object_entry.atom_entry.builder +1 -0
- data/app/views/cmis_server/atom_pub/entries/type_entry.atom_entry.builder +59 -0
- data/app/views/cmis_server/atom_pub/feeds/_feed_entry.atom_feed.builder +1 -0
- data/app/views/cmis_server/atom_pub/feeds/feed.atom_feed.builder +30 -0
- data/app/views/cmis_server/atom_pub/service_documents/_uri_template.atom_service.builder +5 -0
- data/app/views/cmis_server/atom_pub/service_documents/_workspace.atom_service.builder +89 -0
- data/app/views/cmis_server/atom_pub/service_documents/service_document.atom_service.builder +1 -0
- data/app/views/cmis_server/atom_pub/shared/_collection.xml.builder +7 -0
- data/app/views/cmis_server/atom_pub/shared/atom_entry_layout.atom_entry.builder +0 -0
- data/app/views/cmis_server/atom_pub/type_entry.atom.builder +69 -0
- data/app/views/cmis_server/atom_pub/types_feed.atom.builder +91 -0
- data/app/views/layouts/cmis_server/application.atom_entry.builder +2 -0
- data/app/views/layouts/cmis_server/application.atom_feed.builder +3 -0
- data/app/views/layouts/cmis_server/application.atom_service.builder +10 -0
- data/app/views/layouts/cmis_server/application.html.erb +14 -0
- data/config/routes.rb +49 -0
- data/lib/cmis_server/atom_pub/entry_parser.rb +72 -0
- data/lib/cmis_server/base_objects/base_type.rb +128 -0
- data/lib/cmis_server/base_objects/document.rb +68 -0
- data/lib/cmis_server/base_objects/folder.rb +104 -0
- data/lib/cmis_server/base_objects/item.rb +25 -0
- data/lib/cmis_server/base_types.rb +123 -0
- data/lib/cmis_server/cmis_object.rb +190 -0
- data/lib/cmis_server/configuration.rb +43 -0
- data/lib/cmis_server/constants.rb +8 -0
- data/lib/cmis_server/content_stream.rb +52 -0
- data/lib/cmis_server/context.rb +11 -0
- data/lib/cmis_server/document_object.rb +12 -0
- data/lib/cmis_server/document_type.rb +67 -0
- data/lib/cmis_server/engine.rb +60 -0
- data/lib/cmis_server/exceptions.rb +185 -0
- data/lib/cmis_server/folder_object.rb +18 -0
- data/lib/cmis_server/folder_type.rb +34 -0
- data/lib/cmis_server/id.rb +18 -0
- data/lib/cmis_server/item_adapter.rb +26 -0
- data/lib/cmis_server/item_object.rb +15 -0
- data/lib/cmis_server/item_type.rb +7 -0
- data/lib/cmis_server/object_adapter.rb +79 -0
- data/lib/cmis_server/property.rb +29 -0
- data/lib/cmis_server/property_definition.rb +118 -0
- data/lib/cmis_server/query/parser.output +2250 -0
- data/lib/cmis_server/query/parser.racc +222 -0
- data/lib/cmis_server/query/parser.racc.rb +1039 -0
- data/lib/cmis_server/query/parser.rex +114 -0
- data/lib/cmis_server/query/parser.rex.rb +238 -0
- data/lib/cmis_server/query/statement.rb +395 -0
- data/lib/cmis_server/query.rb +2 -0
- data/lib/cmis_server/renderable_collection.rb +45 -0
- data/lib/cmis_server/renderable_object.rb +49 -0
- data/lib/cmis_server/repository.rb +91 -0
- data/lib/cmis_server/secondary_type.rb +11 -0
- data/lib/cmis_server/type.rb +62 -0
- data/lib/cmis_server/type_registry.rb +115 -0
- data/lib/cmis_server/version.rb +4 -0
- data/lib/cmis_server.rb +22 -0
- data/lib/tasks/cmis_server_tasks.rake +4 -0
- data/test/cmis_server_test.rb +7 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/integration/navigation_test.rb +8 -0
- data/test/services/bulk_update_service_test.rb +121 -0
- data/test/services/content_stream_service_test.rb +176 -0
- data/test/services/secondary_type_service_test.rb +174 -0
- data/test/services/type_management_service_test.rb +146 -0
- data/test/test_helper.rb +16 -0
- metadata +326 -0
@@ -0,0 +1,190 @@
|
|
1
|
+
module CmisServer
|
2
|
+
|
3
|
+
class CmisObject
|
4
|
+
|
5
|
+
attr_reader :type
|
6
|
+
attr_reader :properties
|
7
|
+
attr_reader :secondary_types
|
8
|
+
|
9
|
+
class InvalidType < StandardError; end
|
10
|
+
|
11
|
+
def initialize(type:, properties: {}, secondary_types: [])
|
12
|
+
self.type = type
|
13
|
+
@secondary_types = []
|
14
|
+
initialize_properties
|
15
|
+
|
16
|
+
# Ajouter les types secondaires s'ils sont fournis
|
17
|
+
secondary_types.each do |secondary_type|
|
18
|
+
add_secondary_type(secondary_type)
|
19
|
+
end
|
20
|
+
|
21
|
+
properties.to_h.each do |property, value|
|
22
|
+
self.send(property.to_s.gsub(/[^0-9a-z]/i, '_').underscore+"=", value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_renderable_object
|
27
|
+
CmisServer::RenderableObject.new(base_object: self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy_properties_values_of object
|
31
|
+
self.properties.each{|_k,property| property.value=object.send(property.property_definition.getter_method_name)}
|
32
|
+
end
|
33
|
+
|
34
|
+
# CMIS 1.1: Méthodes pour gérer les types secondaires
|
35
|
+
def add_secondary_type(secondary_type)
|
36
|
+
# Vérifier que le type est bien un type secondaire
|
37
|
+
unless secondary_type.base_id == 'cmis:secondary'
|
38
|
+
raise InvalidType.new("#{secondary_type.id} is not a secondary type")
|
39
|
+
end
|
40
|
+
|
41
|
+
# Vérifier que le type n'est pas déjà ajouté
|
42
|
+
if has_secondary_type?(secondary_type.id)
|
43
|
+
raise InvalidType.new("#{secondary_type.id} is already added")
|
44
|
+
end
|
45
|
+
|
46
|
+
# Ajouter le type secondaire
|
47
|
+
@secondary_types << secondary_type
|
48
|
+
|
49
|
+
# Ajouter les propriétés du type secondaire
|
50
|
+
add_secondary_type_properties(secondary_type)
|
51
|
+
|
52
|
+
# Mettre à jour la propriété cmis:secondaryObjectTypeIds
|
53
|
+
update_secondary_type_ids
|
54
|
+
|
55
|
+
secondary_type
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_secondary_type(type_id)
|
59
|
+
# Trouver le type secondaire
|
60
|
+
secondary_type = @secondary_types.find { |st| st.id == type_id }
|
61
|
+
unless secondary_type
|
62
|
+
raise InvalidType.new("#{type_id} is not a secondary type of this object")
|
63
|
+
end
|
64
|
+
|
65
|
+
# Supprimer le type secondaire
|
66
|
+
@secondary_types.delete(secondary_type)
|
67
|
+
|
68
|
+
# Supprimer les propriétés associées à ce type secondaire
|
69
|
+
remove_secondary_type_properties(secondary_type)
|
70
|
+
|
71
|
+
# Mettre à jour la propriété cmis:secondaryObjectTypeIds
|
72
|
+
update_secondary_type_ids
|
73
|
+
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def has_secondary_type?(type_id)
|
78
|
+
@secondary_types.any? { |st| st.id == type_id }
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_properties(properties_hash)
|
82
|
+
properties_hash.each do |prop_id, value|
|
83
|
+
if @properties.key?(prop_id)
|
84
|
+
@properties[prop_id].value = value
|
85
|
+
else
|
86
|
+
# Vérifier si cette propriété appartient à un type secondaire que nous n'avons pas encore
|
87
|
+
property_def = find_property_definition(prop_id)
|
88
|
+
if property_def && property_def.owning_type && property_def.owning_type.base_id == 'cmis:secondary'
|
89
|
+
# Ajouter automatiquement le type secondaire
|
90
|
+
add_secondary_type(property_def.owning_type)
|
91
|
+
# Puis définir la valeur
|
92
|
+
@properties[prop_id].value = value
|
93
|
+
else
|
94
|
+
raise ArgumentError, "Property #{prop_id} does not exist for this object"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def save
|
101
|
+
# À implémenter selon votre système de stockage
|
102
|
+
# Cette méthode devrait sauvegarder l'objet avec toutes ses propriétés
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def all_property_definitions
|
107
|
+
# Combine les définitions de propriétés du type principal et des types secondaires
|
108
|
+
all_defs = type.property_definitions.to_a
|
109
|
+
|
110
|
+
@secondary_types.each do |secondary_type|
|
111
|
+
all_defs.concat(secondary_type.property_definitions.to_a)
|
112
|
+
end
|
113
|
+
|
114
|
+
all_defs
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def find_property_definition(prop_id)
|
120
|
+
# Chercher dans les types secondaires disponibles
|
121
|
+
CmisServer::TypeRegistry.types.values.each do |available_type|
|
122
|
+
if available_type.base_id == 'cmis:secondary'
|
123
|
+
prop_def = available_type.property_definitions.find { |pd| pd.id == prop_id }
|
124
|
+
return prop_def if prop_def
|
125
|
+
end
|
126
|
+
end
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
def add_secondary_type_properties(secondary_type)
|
131
|
+
secondary_type.property_definitions.each do |pd|
|
132
|
+
# Ajouter la propriété si elle n'existe pas déjà
|
133
|
+
unless @properties.key?(pd.id)
|
134
|
+
@properties[pd.id] = Property.new(pd, pd.default_value, self)
|
135
|
+
|
136
|
+
# Ajouter les méthodes getter et setter
|
137
|
+
define_singleton_method(pd.getter_method_name) { @properties[pd.id].value }
|
138
|
+
define_singleton_method(pd.setter_method_name) { |v| @properties[pd.id].value = v }
|
139
|
+
define_singleton_method(pd.property_method_name) { @properties[pd.id] }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def remove_secondary_type_properties(secondary_type)
|
145
|
+
secondary_type.self_property_definitions.each do |pd|
|
146
|
+
# Vérifier que la propriété n'est pas également définie par le type principal ou un autre type secondaire
|
147
|
+
unless property_defined_elsewhere?(pd.id, secondary_type.id)
|
148
|
+
@properties.delete(pd.id)
|
149
|
+
|
150
|
+
# Supprimer les méthodes associées
|
151
|
+
singleton_class.send(:remove_method, pd.getter_method_name) if respond_to?(pd.getter_method_name)
|
152
|
+
singleton_class.send(:remove_method, pd.setter_method_name) if respond_to?(pd.setter_method_name)
|
153
|
+
singleton_class.send(:remove_method, pd.property_method_name) if respond_to?(pd.property_method_name)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def property_defined_elsewhere?(prop_id, excluding_type_id)
|
159
|
+
# Vérifier si la propriété est définie par le type principal
|
160
|
+
return true if type.property_definitions.any? { |pd| pd.id == prop_id }
|
161
|
+
|
162
|
+
# Vérifier si la propriété est définie par un autre type secondaire
|
163
|
+
@secondary_types.any? do |st|
|
164
|
+
st.id != excluding_type_id && st.property_definitions.any? { |pd| pd.id == prop_id }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def update_secondary_type_ids
|
169
|
+
# Mettre à jour la propriété cmis:secondaryObjectTypeIds avec les IDs des types secondaires
|
170
|
+
if @properties.key?('cmis:secondaryObjectTypeIds')
|
171
|
+
@properties['cmis:secondaryObjectTypeIds'].value = @secondary_types.map(&:id)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def type=(type)
|
176
|
+
@type=type
|
177
|
+
type.property_definitions.each do |pd|
|
178
|
+
define_singleton_method(pd.getter_method_name) { @properties[pd.id].value }
|
179
|
+
define_singleton_method(pd.setter_method_name) { |v| @properties[pd.id].value=v }
|
180
|
+
define_singleton_method(pd.property_method_name) { @properties[pd.id] }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def initialize_properties
|
185
|
+
@properties=type.property_definitions.map do |pd|
|
186
|
+
[pd.id, Property.new(pd, pd.value, self)]
|
187
|
+
end.to_h
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module CmisServer
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
attr_accessor :http_basic_auth_procedure
|
5
|
+
attr_accessor :arguments_for_root_folder
|
6
|
+
attr_accessor :default_page_size
|
7
|
+
attr_accessor :debug
|
8
|
+
attr_accessor :repository_info
|
9
|
+
attr_accessor :optimizations
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
|
13
|
+
#defines default values
|
14
|
+
|
15
|
+
@http_basic_auth_procedure = Proc.new do |user, password|
|
16
|
+
puts "Set your identification procedure in the CmisServer gem configuration with key http_basic_auth_procedure."
|
17
|
+
puts "example : config.http_basic_auth_procedure = Proc.new{|user,password| User.find_by(username: user)&.valid_password?(password)}"
|
18
|
+
raise "http_basic_auth_procedure configuration not set"
|
19
|
+
end
|
20
|
+
|
21
|
+
@arguments_for_root_folder={
|
22
|
+
type: FolderType.base,
|
23
|
+
properties:{
|
24
|
+
cmis_object_id: 'cmis:root_folder',
|
25
|
+
cmis_name: "Root Folder",
|
26
|
+
cmis_last_modification_date: DateTime.now,
|
27
|
+
cmis_creation_date: DateTime.now,
|
28
|
+
cmis_created_by: 'unknown'
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
@default_page_size = 10
|
33
|
+
|
34
|
+
@debug=false
|
35
|
+
|
36
|
+
@repository_info = {}
|
37
|
+
|
38
|
+
@optimizations = {}
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module CmisServer
|
6
|
+
class ContentStream
|
7
|
+
|
8
|
+
attr_accessor :media_type
|
9
|
+
attr_accessor :base64
|
10
|
+
attr_accessor :filename
|
11
|
+
attr_accessor :id
|
12
|
+
|
13
|
+
def initialize(id: nil, base64: nil, media_type: nil, filename: nil)
|
14
|
+
@media_type=media_type
|
15
|
+
@base64 =base64
|
16
|
+
@id =id
|
17
|
+
@filename =filename
|
18
|
+
end
|
19
|
+
|
20
|
+
def length
|
21
|
+
content.bytesize
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_extensions
|
25
|
+
MIME::Types[self.media_type].first&.extensions&.first||'txt'
|
26
|
+
end
|
27
|
+
|
28
|
+
def content
|
29
|
+
Base64.decode64(self.base64)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tempfile(name='tempfile')
|
33
|
+
t=Tempfile.new([name, ".#{default_extensions}"])
|
34
|
+
t.binmode
|
35
|
+
t.write(self.content)
|
36
|
+
t.close
|
37
|
+
t.open
|
38
|
+
t
|
39
|
+
end
|
40
|
+
|
41
|
+
def with_tempfile(&block)
|
42
|
+
temp_file=self.tempfile
|
43
|
+
begin
|
44
|
+
block.call(temp_file)
|
45
|
+
ensure
|
46
|
+
temp_file.close
|
47
|
+
temp_file.unlink
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module CmisServer
|
2
|
+
class DocumentType < Type
|
3
|
+
|
4
|
+
attr_accessor :versionable,
|
5
|
+
:content_stream_allowed
|
6
|
+
# notallowed
|
7
|
+
# A content stream MUST NOT be included.
|
8
|
+
# allowed
|
9
|
+
# A content stream MAY be included.
|
10
|
+
# required
|
11
|
+
# A content stream MUST be included (i.e. MUST be included when the object is created, and MUST NOT be deleted).
|
12
|
+
|
13
|
+
def initialize(attrs={})
|
14
|
+
@versionable = attrs.fetch(:versionable, false)
|
15
|
+
@content_stream_allowed = attrs.fetch(:content_stream_allowed, :allowed)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def adapter_class
|
20
|
+
DocumentAdapter
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def self.base
|
25
|
+
@base||=new(id: 'cmis:document',
|
26
|
+
parent_type: nil,
|
27
|
+
description: "A CMIS document",
|
28
|
+
display_name: 'Document',
|
29
|
+
creatable: true,
|
30
|
+
fileable: true,
|
31
|
+
queryable: true,
|
32
|
+
property_definitions: [
|
33
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:name'.freeze, type: String, required: true, updatability: :readwrite}),
|
34
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:description'.freeze, type: String, required: false, updatability: :readwrite}),
|
35
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:objectId'.freeze, type: CmisServer::Id, required: true, updatability: :readonly}),
|
36
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:baseTypeId'.freeze, type: CmisServer::Id, required: true, updatability: :readonly, value: ->(obj) { obj.type.base_id }}),
|
37
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:objectTypeId'.freeze, type: CmisServer::Id, required: true, updatability: :oncreate, value: ->(obj) { obj.type.id }}),
|
38
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:createdBy'.freeze, type: String, required: false, updatability: :readonly, queryable: true, orderable: true}),
|
39
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:creationDate'.freeze, type: DateTime, required: false, updatability: :readonly, queryable: true, orderable: true}),
|
40
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:lastModifiedBy'.freeze, type: String, required: false, updatability: :readonly, queryable: true, orderable: true}),
|
41
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:lastModificationDate'.freeze, type: DateTime, required: false, updatability: :readonly, queryable: true, orderable: true}),
|
42
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:changeToken'.freeze, type: String, required: false, updatability: :readonly}),
|
43
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:isImmutable'.freeze, type: Boolean, required: false, updatability: :readonly, default: false}),
|
44
|
+
|
45
|
+
# Versionning properties
|
46
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:isLatestVersion'.freeze, type: Boolean, required: false, updatability: :readonly}),
|
47
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:isMajorVersion'.freeze, type: Boolean, required: false, updatability: :readonly}),
|
48
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:isLatestMajorVersion'.freeze, type: Boolean, required: false, updatability: :readonly}),
|
49
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:isPrivateWorkingCopy'.freeze, type: Boolean, required: false, updatability: :readonly}),
|
50
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:versionLabel'.freeze, type: String, required: false, cardinality: :single, updatability: :readonly}),
|
51
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:versionSeriesId'.freeze, type: CmisServer::Id, required: false, cardinality: :single, updatability: :readonly}),
|
52
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:isVersionSeriesCheckedOut'.freeze, type: Boolean, required: false, cardinality: :single, updatability: :readonly}),
|
53
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:versionSeriesCheckedOutBy'.freeze, type: String, required: false, cardinality: :single, updatability: :readonly}),
|
54
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:versionSeriesCheckedOutId'.freeze, type: Id, required: false, cardinality: :single, updatability: :readonly}),
|
55
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:checkinComment'.freeze, type: String, required: false, cardinality: :single, updatability: :readonly}),
|
56
|
+
|
57
|
+
# ContentStream properties
|
58
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:contentStreamLength'.freeze, type: Integer, required: false, cardinality: :single, updatability: :readonly, value: ->(obj) { obj.content_stream&.length }}),
|
59
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:contentStreamMimeType'.freeze, type: String, required: false, cardinality: :single, updatability: :readonly, value: ->(obj) { obj.content_stream&.media_type }}),
|
60
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:contentStreamFileName'.freeze, type: String, required: false, cardinality: :single, updatability: :readonly, value: ->(obj) { obj.content_stream&.filename }}),
|
61
|
+
CmisServer::PropertyDefinition.register_property_definition({id: 'cmis:contentStreamId'.freeze, type: String, required: false, cardinality: :single, updatability: :readonly, value: ->(obj) { obj.content_stream&.id }}),
|
62
|
+
])
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module CmisServer
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
config.autoload_paths << File.expand_path("../../app/services", __FILE__)
|
4
|
+
isolate_namespace CmisServer
|
5
|
+
|
6
|
+
# Enregistrement des types MIME selon les conventions de Rails 7+
|
7
|
+
initializer "cmis_server.register_mime_types" do
|
8
|
+
Mime::Type.register "application/atom+xml", :atom_xml
|
9
|
+
Mime::Type.register "application/atom+xml;type=feed", :atom_feed
|
10
|
+
Mime::Type.register "application/atom+xml;type=entry", :atom_entry
|
11
|
+
Mime::Type.register "application/atomsvc+xml", :atom_service
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'cmis_server/version'
|
17
|
+
require 'cmis_server/constants'
|
18
|
+
require 'cmis_server/configuration'
|
19
|
+
|
20
|
+
require 'cmis_server/exceptions'
|
21
|
+
|
22
|
+
#CMIS special types
|
23
|
+
require 'cmis_server/id'
|
24
|
+
require 'cmis_server/content_stream'
|
25
|
+
|
26
|
+
require 'cmis_server/repository'
|
27
|
+
require 'cmis_server/property_definition'
|
28
|
+
require 'cmis_server/property'
|
29
|
+
|
30
|
+
# Charger BaseType en premier
|
31
|
+
require 'cmis_server/base_objects/base_type'
|
32
|
+
|
33
|
+
require 'cmis_server/type'
|
34
|
+
require 'cmis_server/base_types'
|
35
|
+
require 'cmis_server/type_registry'
|
36
|
+
require 'cmis_server/cmis_object'
|
37
|
+
require 'cmis_server/document_type'
|
38
|
+
require 'cmis_server/document_object'
|
39
|
+
require 'cmis_server/folder_type'
|
40
|
+
require 'cmis_server/folder_object'
|
41
|
+
require 'cmis_server/item_type'
|
42
|
+
require 'cmis_server/item_object'
|
43
|
+
require 'cmis_server/secondary_type'
|
44
|
+
# require 'cmis_server/type_registry'
|
45
|
+
|
46
|
+
|
47
|
+
require 'cmis_server/object_adapter'
|
48
|
+
require 'cmis_server/item_adapter'
|
49
|
+
require 'cmis_server/base_objects/base_type'
|
50
|
+
require 'cmis_server/base_objects/document'
|
51
|
+
require 'cmis_server/base_objects/folder'
|
52
|
+
require 'cmis_server/base_objects/item'
|
53
|
+
|
54
|
+
require 'cmis_server/atom_pub/entry_parser'
|
55
|
+
|
56
|
+
require 'cmis_server/context'
|
57
|
+
|
58
|
+
require 'cmis_server/query'
|
59
|
+
require 'cmis_server/renderable_object'
|
60
|
+
require 'cmis_server/renderable_collection'
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module CmisServer
|
2
|
+
|
3
|
+
class CmisStandardError < StandardError
|
4
|
+
|
5
|
+
attr_reader :http_status_code, :debug_data, :trigger, :title
|
6
|
+
|
7
|
+
def initialize(attrs= {})
|
8
|
+
self.http_status_code = attrs.fetch(:http_status, 500)
|
9
|
+
@debug_data = attrs.fetch(:debug_data, nil)
|
10
|
+
@trigger = attrs.fetch(:trigger, nil)
|
11
|
+
@title = attrs.fetch(:title, nil)
|
12
|
+
end
|
13
|
+
|
14
|
+
def http_status
|
15
|
+
Rack::Utils::HTTP_STATUS_CODES[self.http_status_code]
|
16
|
+
end
|
17
|
+
|
18
|
+
def title
|
19
|
+
@title||self.class.name
|
20
|
+
end
|
21
|
+
|
22
|
+
def summary
|
23
|
+
"A #{self.title} error occured."
|
24
|
+
end
|
25
|
+
|
26
|
+
def message(debug: CmisServer.configuration.debug)
|
27
|
+
message=self.summary
|
28
|
+
message+= " It was initially triggered by : #{@trigger}" if @trigger&&debug
|
29
|
+
message
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_h(debug: CmisServer.configuration.debug)
|
33
|
+
h={
|
34
|
+
title: self.title,
|
35
|
+
summary: self.summary,
|
36
|
+
http_status_code: self.http_status_code,
|
37
|
+
http_status: self.http_status,
|
38
|
+
}
|
39
|
+
if debug
|
40
|
+
h[:debug_data]= self.debug_data.to_h
|
41
|
+
h[:backtrace] =self.backtrace&.join("\n")
|
42
|
+
h[:trigger] ={
|
43
|
+
name: self.trigger,
|
44
|
+
backtrace: self.trigger&.backtrace&.join("\n")
|
45
|
+
}
|
46
|
+
end
|
47
|
+
h
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_xml(debug: CmisServer.configuration.debug)
|
51
|
+
formated_hash=self.to_h(debug: debug).map { |k, v| [k.to_s.camelcase(:lower), v] }.to_h
|
52
|
+
formated_hash.to_xml(:root => 'error', :skip_instruct => true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def log(logger)
|
56
|
+
logger.error "#{self.class.to_s} (#{self.summary})"
|
57
|
+
logger.info self.backtrace.join("\n") if self.backtrace
|
58
|
+
if self.trigger
|
59
|
+
logger.error "Initialy triggered by : #{self.trigger.class.to_s} (#{self.trigger.message})"
|
60
|
+
logger.info self.trigger.backtrace.join("\n") if self.trigger.backtrace
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def http_status_code=(value)
|
67
|
+
if value.is_a? Integer
|
68
|
+
@http_status_code=value
|
69
|
+
else
|
70
|
+
@http_status_code=Rack::Utils::SYMBOL_TO_STATUS_CODE[value]||value.to_i
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class RuntimeError < CmisStandardError
|
76
|
+
def title
|
77
|
+
"Runtime Error"
|
78
|
+
end
|
79
|
+
|
80
|
+
def summary
|
81
|
+
"An unhandled error occurred on the CMIS server."
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class ObjectNotFound < CmisStandardError
|
86
|
+
def title
|
87
|
+
"Object Not Found"
|
88
|
+
end
|
89
|
+
|
90
|
+
def summary
|
91
|
+
"The requested object could not be found in this CMIS repository or you don't have permissions to access it"
|
92
|
+
end
|
93
|
+
|
94
|
+
def http_status_code
|
95
|
+
404
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Exceptions pour CMIS 1.1
|
100
|
+
class InvalidType < CmisStandardError
|
101
|
+
def title
|
102
|
+
"Invalid Type"
|
103
|
+
end
|
104
|
+
|
105
|
+
def summary
|
106
|
+
"The specified type is invalid or does not exist."
|
107
|
+
end
|
108
|
+
|
109
|
+
def http_status_code
|
110
|
+
400
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class InvalidTypeDefinition < CmisStandardError
|
115
|
+
def initialize(message = nil, attrs = {})
|
116
|
+
super(attrs)
|
117
|
+
@message = message
|
118
|
+
end
|
119
|
+
|
120
|
+
def title
|
121
|
+
"Invalid Type Definition"
|
122
|
+
end
|
123
|
+
|
124
|
+
def summary
|
125
|
+
@message || "The type definition is invalid."
|
126
|
+
end
|
127
|
+
|
128
|
+
def http_status_code
|
129
|
+
400
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class InvalidOperation < CmisStandardError
|
134
|
+
def initialize(message = nil, attrs = {})
|
135
|
+
super(attrs)
|
136
|
+
@message = message
|
137
|
+
end
|
138
|
+
|
139
|
+
def title
|
140
|
+
"Invalid Operation"
|
141
|
+
end
|
142
|
+
|
143
|
+
def summary
|
144
|
+
@message || "The requested operation cannot be performed."
|
145
|
+
end
|
146
|
+
|
147
|
+
def http_status_code
|
148
|
+
400
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class NotSupported < CmisStandardError
|
153
|
+
def title
|
154
|
+
"Not Supported"
|
155
|
+
end
|
156
|
+
|
157
|
+
def summary
|
158
|
+
"The requested operation is not supported by this CMIS repository."
|
159
|
+
end
|
160
|
+
|
161
|
+
def http_status_code
|
162
|
+
405
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class ConstraintViolation < CmisStandardError
|
167
|
+
def initialize(message = nil, attrs = {})
|
168
|
+
super(attrs)
|
169
|
+
@message = message
|
170
|
+
end
|
171
|
+
|
172
|
+
def title
|
173
|
+
"Constraint Violation"
|
174
|
+
end
|
175
|
+
|
176
|
+
def summary
|
177
|
+
@message || "A constraint has been violated."
|
178
|
+
end
|
179
|
+
|
180
|
+
def http_status_code
|
181
|
+
409
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CmisServer
|
2
|
+
class FolderObject < CmisServer::CmisObject
|
3
|
+
|
4
|
+
def self.root_folder
|
5
|
+
unless @root
|
6
|
+
@root=new(CmisServer.configuration.arguments_for_root_folder)
|
7
|
+
@root.define_singleton_method :is_root?,(lambda { true })
|
8
|
+
end
|
9
|
+
@root
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(type:, properties: {})
|
13
|
+
raise InvalidType unless type.base_id == 'cmis:folder'
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|