cmis_server 1.2.1 → 1.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.
- checksums.yaml +4 -4
- data/app/controllers/cmis_server/atom_pub/entries_controller.rb +2 -1
- data/app/controllers/cmis_server/atom_pub/folder_collection_controller.rb +55 -11
- data/app/controllers/cmis_server/atom_pub/query_controller.rb +44 -16
- data/app/controllers/cmis_server/atom_pub/service_documents_controller.rb +1 -1
- data/app/services/cmis_server/discovery_service.rb +58 -9
- data/app/services/cmis_server/navigation_service.rb +62 -3
- data/app/services/cmis_server/object_service.rb +112 -13
- data/app/views/cmis_server/atom_pub/entries/_cmis_folder_links.atom_entry.builder +1 -1
- data/app/views/cmis_server/atom_pub/entries/_object_entry.atom_entry.builder +4 -3
- data/app/views/cmis_server/atom_pub/entries/type_entry.atom_entry.builder +1 -1
- data/app/views/cmis_server/atom_pub/feeds/feed.atom_feed.builder +3 -0
- data/app/views/cmis_server/atom_pub/query_results_feed.atom_feed.builder +59 -0
- data/app/views/cmis_server/atom_pub/queryable_types_feed.atom_feed.builder +35 -0
- data/app/views/cmis_server/atom_pub/service_documents/_workspace.atom_service.builder +1 -1
- data/config/initializers/cmis_core_configuration.rb +31 -8
- data/lib/cmis_server/atom_pub/entry_parser.rb +57 -22
- data/lib/cmis_server/cmis_object.rb +32 -2
- data/lib/cmis_server/configuration.rb +4 -3
- data/lib/cmis_server/connectors/CORE_CONNECTOR_QUERIES.md +180 -0
- data/lib/cmis_server/connectors/core_connector.rb +189 -69
- data/lib/cmis_server/constants.rb +3 -2
- data/lib/cmis_server/document_adapter.rb +135 -0
- data/lib/cmis_server/document_object.rb +1 -1
- data/lib/cmis_server/engine.rb +95 -0
- data/lib/cmis_server/exceptions.rb +19 -0
- data/lib/cmis_server/folder_adapter.rb +126 -0
- data/lib/cmis_server/property.rb +40 -4
- data/lib/cmis_server/query/parser.rb +11 -0
- data/lib/cmis_server/query/{parser.racc.rb → parser_racc.rb} +2 -2
- data/lib/cmis_server/query/{parser.rex.rb → parser_rex.rb} +6 -1
- data/lib/cmis_server/query/simple_parser.rb +276 -0
- data/lib/cmis_server/query/statement.rb +3 -389
- data/lib/cmis_server/query/statement.rb.bak +395 -0
- data/lib/cmis_server/query.rb +11 -2
- data/lib/cmis_server/renderable_collection.rb +23 -2
- data/lib/cmis_server/repository.rb +1 -1
- data/lib/cmis_server/version.rb +1 -1
- data/lib/cmis_server.rb +13 -0
- metadata +12 -4
@@ -6,18 +6,18 @@ module CmisServer
|
|
6
6
|
|
7
7
|
def find_documents(conditions = {})
|
8
8
|
return [] unless search_service_available?
|
9
|
+
return [] unless core_user # Pas de recherche sans utilisateur valide
|
9
10
|
|
10
11
|
begin
|
11
12
|
# Convertir les conditions CMIS en paramètres Core search
|
12
13
|
search_params = convert_cmis_to_docs_search_params(conditions)
|
13
14
|
|
14
|
-
# Créer le service de recherche avec les paramètres convertis et l'utilisateur
|
15
|
-
|
15
|
+
# Créer le service de recherche avec les paramètres convertis et l'utilisateur Core
|
16
|
+
search_service = docs_search_class.new(search_params, user: core_user)
|
16
17
|
|
17
|
-
# Exécuter la recherche et retourner les résultats paginés
|
18
|
-
documents = search
|
18
|
+
# Exécuter la recherche et retourner les résultats paginés (query Mongo)
|
19
|
+
documents = search_service.search
|
19
20
|
|
20
|
-
Rails.logger.info "CoreConnector: Found #{documents.count} documents with params: #{search_params}"
|
21
21
|
documents
|
22
22
|
rescue => e
|
23
23
|
Rails.logger.error "CoreConnector find_documents error: #{e.message}"
|
@@ -27,24 +27,31 @@ module CmisServer
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def find_folders(conditions = {})
|
30
|
-
|
30
|
+
|
31
|
+
return [] unless core_user # Pas de recherche sans utilisateur valide
|
31
32
|
|
32
33
|
begin
|
34
|
+
# Cas spécial : recherche des sous-espaces d'un parent
|
35
|
+
if conditions['parent_id'] && defined?(::Tagset)
|
36
|
+
parent_id = conditions['parent_id']
|
37
|
+
|
38
|
+
# Rechercher directement les Tagsets qui ont ce parent
|
39
|
+
tagsets = ::Tagset.where(parent_ids: parent_id, is_space: true)
|
40
|
+
return tagsets
|
41
|
+
end
|
42
|
+
|
43
|
+
# Pour les autres cas, utiliser SpacesSearch si disponible
|
44
|
+
return [] unless search_service_available?
|
45
|
+
|
33
46
|
# Convertir les conditions CMIS en paramètres Core search
|
34
47
|
search_params = convert_cmis_to_spaces_search_params(conditions)
|
35
48
|
|
36
|
-
#
|
37
|
-
|
38
|
-
search_params = { 'favorite' => true }
|
39
|
-
end
|
40
|
-
|
41
|
-
# Créer le service de recherche avec les paramètres convertis et l'utilisateur
|
42
|
-
search = spaces_search_class.new(search_params, user: user)
|
49
|
+
# Créer le service de recherche avec les paramètres convertis et l'utilisateur Core
|
50
|
+
search_service = spaces_search_class.new(search_params, user: core_user)
|
43
51
|
|
44
|
-
# Exécuter la recherche et retourner les résultats paginés
|
45
|
-
folders = search
|
52
|
+
# Exécuter la recherche et retourner les résultats paginés (query Mongo)
|
53
|
+
folders = search_service.search
|
46
54
|
|
47
|
-
Rails.logger.info "CoreConnector: Found #{folders.count} folders with params: #{search_params}"
|
48
55
|
folders
|
49
56
|
rescue => e
|
50
57
|
Rails.logger.error "CoreConnector find_folders error: #{e.message}"
|
@@ -54,39 +61,32 @@ module CmisServer
|
|
54
61
|
end
|
55
62
|
|
56
63
|
def find_object_by_id(id)
|
57
|
-
Rails.logger.info "CoreConnector: Searching for object with ID: #{id}"
|
58
64
|
|
59
|
-
# Cas spécial pour le dossier racine CMIS
|
60
|
-
if id == 'core_root'
|
61
|
-
Rails.logger.info "CoreConnector: Returning root folder for ID: #{id}"
|
65
|
+
# Cas spécial pour le dossier racine CMIS (accepter plusieurs variantes)
|
66
|
+
if id == 'core_root' || id == 'root_folder' || id == 'root' || id == 'root_folder_id'
|
62
67
|
return create_root_folder_object
|
63
68
|
end
|
64
69
|
|
65
70
|
# Essayer d'abord comme document
|
66
71
|
doc = find_document_by_id(id)
|
67
72
|
if doc
|
68
|
-
Rails.logger.info "CoreConnector: Found document with ID: #{id}"
|
69
73
|
return doc
|
70
74
|
end
|
71
75
|
|
72
76
|
# Puis essayer comme dossier/espace
|
73
77
|
folder = find_folder_by_id(id)
|
74
78
|
if folder
|
75
|
-
Rails.logger.info "CoreConnector: Found folder with ID: #{id}"
|
76
79
|
return folder
|
77
80
|
end
|
78
81
|
|
79
82
|
Rails.logger.warn "CoreConnector: No object found with ID: #{id}"
|
80
|
-
Rails.logger.info "CoreConnector: Available services - Doc: #{doc_class_available?}, Space: #{space_class_available?}, DocsSearch: #{docs_search_class}, SpacesSearch: #{spaces_search_class}"
|
81
83
|
nil
|
82
84
|
end
|
83
85
|
|
84
86
|
def find_object_by_path(path)
|
85
|
-
Rails.logger.info "CoreConnector: Searching for object with path: #{path}"
|
86
87
|
|
87
88
|
# Cas spécial pour le path racine
|
88
89
|
if path == '/' || path.blank?
|
89
|
-
Rails.logger.info "CoreConnector: Returning root folder for path: #{path}"
|
90
90
|
return create_root_folder_object
|
91
91
|
end
|
92
92
|
|
@@ -96,56 +96,164 @@ module CmisServer
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def find_root_folders
|
99
|
-
#
|
100
|
-
find_folders({})
|
99
|
+
# Retourner les espaces favoris comme enfants directs du root
|
100
|
+
find_folders({ 'favorite' => true })
|
101
101
|
end
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
def create_root_folder_object
|
106
|
-
# Créer un objet dossier racine virtuel avec l'interface CMIS attendue
|
107
|
-
root_object = OpenStruct.new(
|
108
|
-
id: 'core_root',
|
109
|
-
name: 'Core Repository Root',
|
110
|
-
path: '/',
|
111
|
-
description: 'Dossier racine du repository Core',
|
112
|
-
type: 'cmis:folder',
|
113
|
-
cmis_object_id: 'core_root'
|
114
|
-
)
|
103
|
+
def create_document(properties, folder_id: nil, content_stream: nil)
|
115
104
|
|
116
|
-
#
|
117
|
-
|
118
|
-
|
105
|
+
# Extraire les propriétés CMIS
|
106
|
+
# Les propriétés peuvent être soit des strings soit des objets Property
|
107
|
+
doc_name = properties['cmis:name']
|
108
|
+
doc_name = doc_name.respond_to?(:value) ? doc_name.value : doc_name
|
119
109
|
|
120
|
-
|
121
|
-
id: type_id,
|
122
|
-
base_id: base_id
|
123
|
-
)
|
110
|
+
doc_title = doc_name || 'Untitled'
|
124
111
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
112
|
+
doc_description = properties['cmis:description']
|
113
|
+
doc_description = doc_description.respond_to?(:value) ? doc_description.value : doc_description
|
114
|
+
doc_description ||= ''
|
115
|
+
|
116
|
+
# Déterminer l'espace parent
|
117
|
+
space_id = if folder_id && folder_id != 'root_folder'
|
118
|
+
folder_id
|
119
|
+
else
|
120
|
+
# Si pas de folder_id ou si c'est le root, utiliser le premier espace favori
|
121
|
+
favorite_spaces = find_folders({ 'favorite' => true })
|
122
|
+
if favorite_spaces.any?
|
123
|
+
favorite_spaces.first.id.to_s
|
124
|
+
else
|
125
|
+
raise "No favorite space found to create document"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# Créer le document dans Core
|
131
|
+
if doc_class
|
132
|
+
doc = doc_class.new
|
133
|
+
doc.title = doc_title
|
134
|
+
doc.description = doc_description if doc.respond_to?(:description=)
|
135
|
+
doc.tagset_ids = [BSON::ObjectId(space_id)] if doc.respond_to?(:tagset_ids=)
|
136
|
+
doc.user = core_user
|
137
|
+
|
138
|
+
# Gérer le contenu si présent
|
139
|
+
if content_stream && doc.respond_to?(:content=)
|
140
|
+
doc.content = content_stream.content
|
141
|
+
doc.content_type = content_stream.mime_type if doc.respond_to?(:content_type=)
|
142
|
+
end
|
143
|
+
|
144
|
+
if doc.save
|
145
|
+
doc.id.to_s
|
146
|
+
else
|
147
|
+
Rails.logger.error "CoreConnector: Failed to save document: #{doc.errors.full_messages.join(', ')}"
|
148
|
+
raise "Failed to create document: #{doc.errors.full_messages.join(', ')}"
|
149
|
+
end
|
150
|
+
else
|
151
|
+
raise "Doc class not available in Core"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def create_folder(properties, parent_folder_id: nil)
|
156
|
+
|
157
|
+
# Extraire les propriétés CMIS
|
158
|
+
folder_name = properties['cmis:name']
|
159
|
+
folder_name = folder_name.respond_to?(:value) ? folder_name.value : folder_name
|
160
|
+
folder_name ||= 'Untitled Folder'
|
131
161
|
|
132
|
-
|
133
|
-
|
162
|
+
folder_description = properties['cmis:description']
|
163
|
+
folder_description = folder_description.respond_to?(:value) ? folder_description.value : folder_description
|
164
|
+
folder_description ||= ''
|
134
165
|
|
135
|
-
#
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
166
|
+
# Créer un Tagset (espace) dans Core
|
167
|
+
if ::Tagset
|
168
|
+
tagset = ::Tagset.new
|
169
|
+
tagset.title = folder_name
|
170
|
+
tagset.description = folder_description if tagset.respond_to?(:description=)
|
171
|
+
tagset.is_space = true if tagset.respond_to?(:is_space=)
|
172
|
+
tagset.responsible = core_user.id.to_s if tagset.respond_to?(:responsible=) && core_user
|
173
|
+
|
174
|
+
# Gérer la hiérarchie si un parent est spécifié
|
175
|
+
if parent_folder_id && parent_folder_id != 'root_folder'
|
176
|
+
tagset.parent_ids = [BSON::ObjectId(parent_folder_id)] if tagset.respond_to?(:parent_ids=)
|
177
|
+
end
|
178
|
+
|
179
|
+
if tagset.save
|
180
|
+
tagset.id.to_s
|
181
|
+
else
|
182
|
+
Rails.logger.error "CoreConnector: Failed to save folder: #{tagset.errors.full_messages.join(', ')}"
|
183
|
+
raise "Failed to create folder: #{tagset.errors.full_messages.join(', ')}"
|
184
|
+
end
|
185
|
+
else
|
186
|
+
raise "Tagset class not available in Core"
|
146
187
|
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def delete_object(object_id)
|
147
191
|
|
148
|
-
|
192
|
+
# Essayer de trouver l'objet
|
193
|
+
object = find_object_by_id(object_id)
|
194
|
+
unless object
|
195
|
+
raise CmisServer::ObjectNotFound.new("Object '#{object_id}' not found")
|
196
|
+
end
|
197
|
+
|
198
|
+
# Supprimer selon le type
|
199
|
+
if doc_class && object.is_a?(doc_class)
|
200
|
+
# Définir l'utilisateur courant pour la traçabilité
|
201
|
+
object.current_user_id = core_user.id if object.respond_to?(:current_user_id=) && core_user
|
202
|
+
object.destroy
|
203
|
+
elsif object.respond_to?(:destroy) && object.class.name == 'Doc'
|
204
|
+
# Fallback si doc_class n'est pas trouvé mais que c'est bien un Doc
|
205
|
+
object.current_user_id = core_user.id if object.respond_to?(:current_user_id=) && core_user
|
206
|
+
object.destroy
|
207
|
+
elsif object.is_a?(::Tagset) || (object.respond_to?(:is_space) && object.is_space)
|
208
|
+
# Pour les espaces/tagsets aussi si nécessaire
|
209
|
+
object.current_user_id = core_user.id if object.respond_to?(:current_user_id=) && core_user
|
210
|
+
object.destroy
|
211
|
+
else
|
212
|
+
raise "Cannot delete object of type #{object.class}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
private
|
217
|
+
|
218
|
+
# Méthode pour obtenir un utilisateur Core à partir du user CMIS
|
219
|
+
def core_user
|
220
|
+
@core_user ||= begin
|
221
|
+
if @user.is_a?(::User)
|
222
|
+
# Déjà un utilisateur Core
|
223
|
+
@user
|
224
|
+
elsif @user.respond_to?(:id)
|
225
|
+
# Si on a un ID, essayer de charger l'utilisateur Core
|
226
|
+
begin
|
227
|
+
Rails.logger.debug "CoreConnector: Trying to find User with ID #{@user.id}"
|
228
|
+
user = ::User.find(@user.id)
|
229
|
+
Rails.logger.debug "CoreConnector: Found Core user: #{user.id}"
|
230
|
+
user
|
231
|
+
rescue => e
|
232
|
+
Rails.logger.error "CoreConnector: Cannot find Core user with ID #{@user.id}: #{e.message}"
|
233
|
+
# Pas de fallback - retourner nil pour des raisons de sécurité
|
234
|
+
nil
|
235
|
+
end
|
236
|
+
else
|
237
|
+
Rails.logger.error "CoreConnector: Invalid user object: #{@user.inspect}"
|
238
|
+
nil
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def create_root_folder_object
|
244
|
+
# Créer un objet racine virtuel qui représente la collection des espaces favoris
|
245
|
+
# Ce n'est pas un vrai dossier dans Core, mais un conteneur virtuel pour CMIS
|
246
|
+
OpenStruct.new(
|
247
|
+
id: 'root_folder',
|
248
|
+
title: 'Mes espaces favoris',
|
249
|
+
description: 'Collection des espaces favoris dans Core',
|
250
|
+
responsible: core_user&.name || 'Utilisateur Core',
|
251
|
+
parent_ids: [],
|
252
|
+
created_at: Time.now,
|
253
|
+
updated_at: Time.now,
|
254
|
+
is_space: true,
|
255
|
+
is_virtual: true # Marquer comme virtuel pour indiquer que ce n'est pas un vrai espace Core
|
256
|
+
)
|
149
257
|
end
|
150
258
|
|
151
259
|
def find_document_by_id(id)
|
@@ -160,10 +268,19 @@ module CmisServer
|
|
160
268
|
end
|
161
269
|
|
162
270
|
def find_folder_by_id(id)
|
163
|
-
return nil unless space_class_available?
|
164
|
-
|
165
271
|
begin
|
166
|
-
|
272
|
+
# Chercher d'abord dans les Tagsets (qui sont les espaces/dossiers)
|
273
|
+
if defined?(::Tagset)
|
274
|
+
tagset = ::Tagset.find_by(id: id)
|
275
|
+
return tagset if tagset
|
276
|
+
end
|
277
|
+
|
278
|
+
# Fallback sur space_class si disponible
|
279
|
+
if space_class_available?
|
280
|
+
space_class.find_by(id: id)
|
281
|
+
else
|
282
|
+
nil
|
283
|
+
end
|
167
284
|
rescue => e
|
168
285
|
Rails.logger.error "CoreConnector find_folder_by_id error: #{e.message}"
|
169
286
|
nil
|
@@ -226,6 +343,9 @@ module CmisServer
|
|
226
343
|
when 'cmis:parentId', 'parent_id', 'space_id'
|
227
344
|
# Filtrage par espace parent
|
228
345
|
params['space_id'] = value
|
346
|
+
when 'space_ids'
|
347
|
+
# Filtrage par espaces parents (array) - utiliser tagset_ids dans Core
|
348
|
+
params['tagset_ids'] = value
|
229
349
|
when 'cmis:objectTypeId', 'type_id', 'object_type'
|
230
350
|
# Filtrage par type d'objet (peut correspondre aux templates)
|
231
351
|
params['template_id'] = value
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module CmisServer
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# CMIS 1.1 namespaces
|
4
|
+
CMIS_NAMESPACE ="http://docs.oasis-open.org/ns/cmis/core/201103/"
|
5
|
+
CMIS_REST_ATOM_NAMESPACE="http://docs.oasis-open.org/ns/cmis/restatom/201103/"
|
5
6
|
CMIS_VERSION_SUPPORTED ="1.1"
|
6
7
|
|
7
8
|
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module CmisServer
|
2
|
+
class DocumentAdapter
|
3
|
+
attr_reader :object, :context
|
4
|
+
|
5
|
+
def initialize(object, context:)
|
6
|
+
@object = object
|
7
|
+
@context = context
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.class_adapter(context:)
|
11
|
+
new(nil, context: context)
|
12
|
+
end
|
13
|
+
|
14
|
+
def find(id)
|
15
|
+
connector = CmisServer::Connectors::ConnectorFactory.create_connector(
|
16
|
+
user: @context.is_a?(Hash) ? @context[:current_user] : @context.current_user
|
17
|
+
)
|
18
|
+
core_doc = connector.find_object_by_id(id)
|
19
|
+
|
20
|
+
# Convertir le document Core en objet CMIS
|
21
|
+
if core_doc
|
22
|
+
# Créer un DocumentObject CMIS à partir du Doc Core
|
23
|
+
doc_type = CmisServer::TypeRegistry.get_type('cmis:document')
|
24
|
+
properties = {
|
25
|
+
'cmis:objectId' => CmisServer::Property.new(id: 'cmis:objectId', value: core_doc.id.to_s),
|
26
|
+
'cmis:objectTypeId' => CmisServer::Property.new(id: 'cmis:objectTypeId', value: 'cmis:document'),
|
27
|
+
'cmis:name' => CmisServer::Property.new(id: 'cmis:name', value: core_doc.title),
|
28
|
+
'cmis:createdBy' => CmisServer::Property.new(id: 'cmis:createdBy', value: core_doc.user&.full_name || 'Unknown'),
|
29
|
+
'cmis:creationDate' => CmisServer::Property.new(id: 'cmis:creationDate', value: core_doc.created_at),
|
30
|
+
'cmis:lastModificationDate' => CmisServer::Property.new(id: 'cmis:lastModificationDate', value: core_doc.updated_at)
|
31
|
+
}
|
32
|
+
|
33
|
+
cmis_doc = CmisServer::DocumentObject.new(type: doc_type, properties: properties)
|
34
|
+
cmis_doc.cmis_object_id = core_doc.id.to_s
|
35
|
+
|
36
|
+
self.class.new(cmis_doc, context: @context)
|
37
|
+
else
|
38
|
+
raise CmisServer::ObjectNotFound.new("Document with ID #{id} not found")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_to_folder(folder)
|
43
|
+
# Store folder ID for when we save
|
44
|
+
@parent_folder_id = folder.respond_to?(:cmis_object_id) ? folder.cmis_object_id : folder
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_content_stream(content_stream)
|
48
|
+
@content_stream = content_stream
|
49
|
+
end
|
50
|
+
|
51
|
+
def save!
|
52
|
+
|
53
|
+
# Créer un document Core
|
54
|
+
doc = ::Doc.new
|
55
|
+
|
56
|
+
# Mapper les propriétés CMIS vers Core
|
57
|
+
if @object && @object.properties
|
58
|
+
# Extraire les valeurs des objets Property
|
59
|
+
name_value = @object.properties['cmis:name']
|
60
|
+
name_value = name_value.value if name_value.respond_to?(:value)
|
61
|
+
doc.title = name_value || 'Untitled'
|
62
|
+
doc.labels = ['cmis']
|
63
|
+
|
64
|
+
# Mapper les autres propriétés CMIS vers superfields
|
65
|
+
superfields = {}
|
66
|
+
@object.properties.each do |key, value|
|
67
|
+
unless ['cmis:name', 'cmis:objectTypeId'].include?(key)
|
68
|
+
# Extraire la valeur si c'est un objet Property
|
69
|
+
actual_value = value.respond_to?(:value) ? value.value : value
|
70
|
+
# Nettoyer la clé pour MongoDB (remplacer . et : par _)
|
71
|
+
clean_key = key.gsub(/[.:]/, '_')
|
72
|
+
# Convertir les IDs en string
|
73
|
+
if actual_value.respond_to?(:to_s)
|
74
|
+
superfields[clean_key] = actual_value.to_s
|
75
|
+
else
|
76
|
+
superfields[clean_key] = actual_value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
doc.superfields = superfields unless superfields.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
# Ajouter le contenu si présent
|
84
|
+
if @content_stream
|
85
|
+
require 'base64'
|
86
|
+
if @content_stream.base64
|
87
|
+
doc.blob = Base64.decode64(@content_stream.base64)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Définir le responsable (obligatoire)
|
92
|
+
if @context.current_user
|
93
|
+
# Si l'utilisateur est déjà un objet User de Core, l'utiliser directement
|
94
|
+
if @context.current_user.is_a?(::User)
|
95
|
+
doc.responsible = @context.current_user.id.to_s
|
96
|
+
Rails.logger.debug "Setting document responsible to Core user: #{doc.responsible}"
|
97
|
+
else
|
98
|
+
Rails.logger.error "Current user is not a Core User: #{@context.current_user.class.name}"
|
99
|
+
raise "Invalid user type for document creation"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
Rails.logger.warn "No current_user available in context!"
|
103
|
+
raise "No authenticated user for document creation"
|
104
|
+
end
|
105
|
+
|
106
|
+
# Ajouter aux espaces (folders)
|
107
|
+
if @parent_folder_id
|
108
|
+
# Si c'est root_folder, on ne fait rien
|
109
|
+
unless @parent_folder_id == 'root_folder'
|
110
|
+
# Sinon on ajoute le document à l'espace correspondant
|
111
|
+
doc.tagset_ids = [@parent_folder_id]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
# Sauvegarder le document
|
117
|
+
if doc.save
|
118
|
+
# Mettre à jour l'objet CMIS avec l'ID du document créé
|
119
|
+
@object.cmis_object_id = doc.id.to_s if @object
|
120
|
+
true
|
121
|
+
else
|
122
|
+
Rails.logger.error "DocumentAdapter#save! - Failed to save document: #{doc.errors.full_messages.join(', ')}"
|
123
|
+
raise "Failed to save document: #{doc.errors.full_messages.join(', ')}"
|
124
|
+
end
|
125
|
+
rescue => e
|
126
|
+
Rails.logger.error "DocumentAdapter#save! - Exception: #{e.class.name} - #{e.message}"
|
127
|
+
Rails.logger.error e.backtrace.first(5).join("\n")
|
128
|
+
raise e
|
129
|
+
end
|
130
|
+
|
131
|
+
def to_renderable_object
|
132
|
+
CmisServer::RenderableObject.new(base_object: @object)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/cmis_server/engine.rb
CHANGED
@@ -15,5 +15,100 @@ module CmisServer
|
|
15
15
|
Mime::Type.register "application/atom+xml;type=entry", :atom_entry unless Mime::Type.lookup_by_extension(:atom_entry)
|
16
16
|
Mime::Type.register "application/atomsvc+xml", :atom_service unless Mime::Type.lookup_by_extension(:atom_service)
|
17
17
|
end
|
18
|
+
|
19
|
+
# Load CMIS base types
|
20
|
+
initializer "cmis_server.load_base_types" do
|
21
|
+
config.after_initialize do
|
22
|
+
# Enregistrer les types CMIS de base seulement s'ils n'existent pas déjà
|
23
|
+
unless CmisServer::TypeRegistry.get_type('cmis:document')
|
24
|
+
# Type de base Document
|
25
|
+
document_type = CmisServer::DocumentType.new(
|
26
|
+
id: 'cmis:document',
|
27
|
+
local_name: 'document',
|
28
|
+
display_name: 'Document',
|
29
|
+
query_name: 'cmis:document',
|
30
|
+
description: 'Base type for all documents',
|
31
|
+
base_id: 'cmis:document',
|
32
|
+
parent_type: nil,
|
33
|
+
creatable: true,
|
34
|
+
fileable: true,
|
35
|
+
queryable: true,
|
36
|
+
controllable_policy: false,
|
37
|
+
controllable_acl: true,
|
38
|
+
fulltext_indexed: false,
|
39
|
+
included_in_supertype_query: true,
|
40
|
+
property_definitions: []
|
41
|
+
)
|
42
|
+
CmisServer::TypeRegistry.register_type('cmis:document', document_type)
|
43
|
+
end
|
44
|
+
|
45
|
+
unless CmisServer::TypeRegistry.get_type('cmis:folder')
|
46
|
+
# Type de base Folder
|
47
|
+
folder_type = CmisServer::FolderType.new(
|
48
|
+
id: 'cmis:folder',
|
49
|
+
local_name: 'folder',
|
50
|
+
display_name: 'Folder',
|
51
|
+
query_name: 'cmis:folder',
|
52
|
+
description: 'Base type for all folders',
|
53
|
+
base_id: 'cmis:folder',
|
54
|
+
parent_type: nil,
|
55
|
+
creatable: true,
|
56
|
+
fileable: true,
|
57
|
+
queryable: true,
|
58
|
+
controllable_policy: false,
|
59
|
+
controllable_acl: true,
|
60
|
+
fulltext_indexed: false,
|
61
|
+
included_in_supertype_query: true,
|
62
|
+
property_definitions: []
|
63
|
+
)
|
64
|
+
CmisServer::TypeRegistry.register_type('cmis:folder', folder_type)
|
65
|
+
end
|
66
|
+
|
67
|
+
unless CmisServer::TypeRegistry.get_type('cmis:item')
|
68
|
+
# Type de base Item (CMIS 1.1)
|
69
|
+
item_type = CmisServer::ItemType.new(
|
70
|
+
id: 'cmis:item',
|
71
|
+
local_name: 'item',
|
72
|
+
display_name: 'Item',
|
73
|
+
query_name: 'cmis:item',
|
74
|
+
description: 'Base type for all items',
|
75
|
+
base_id: 'cmis:item',
|
76
|
+
parent_type: nil,
|
77
|
+
creatable: true,
|
78
|
+
fileable: true,
|
79
|
+
queryable: true,
|
80
|
+
controllable_policy: false,
|
81
|
+
controllable_acl: true,
|
82
|
+
fulltext_indexed: false,
|
83
|
+
included_in_supertype_query: true,
|
84
|
+
property_definitions: []
|
85
|
+
)
|
86
|
+
CmisServer::TypeRegistry.register_type('cmis:item', item_type)
|
87
|
+
end
|
88
|
+
|
89
|
+
unless CmisServer::TypeRegistry.get_type('cmis:secondary')
|
90
|
+
# Type de base Secondary (CMIS 1.1)
|
91
|
+
secondary_type = CmisServer::SecondaryType.new(
|
92
|
+
id: 'cmis:secondary',
|
93
|
+
local_name: 'secondary',
|
94
|
+
display_name: 'Secondary Type',
|
95
|
+
query_name: 'cmis:secondary',
|
96
|
+
description: 'Base type for all secondary types',
|
97
|
+
base_id: 'cmis:secondary',
|
98
|
+
parent_type: nil,
|
99
|
+
creatable: false,
|
100
|
+
fileable: false,
|
101
|
+
queryable: true,
|
102
|
+
controllable_policy: false,
|
103
|
+
controllable_acl: false,
|
104
|
+
fulltext_indexed: false,
|
105
|
+
included_in_supertype_query: true,
|
106
|
+
property_definitions: []
|
107
|
+
)
|
108
|
+
CmisServer::TypeRegistry.register_type('cmis:secondary', secondary_type)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
18
113
|
end
|
19
114
|
end
|
@@ -182,4 +182,23 @@ module CmisServer
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
|
+
class InvalidArgument < CmisStandardError
|
186
|
+
def initialize(message = nil, attrs = {})
|
187
|
+
super(attrs)
|
188
|
+
@message = message
|
189
|
+
end
|
190
|
+
|
191
|
+
def title
|
192
|
+
"Invalid Argument"
|
193
|
+
end
|
194
|
+
|
195
|
+
def summary
|
196
|
+
@message || "One or more arguments are invalid."
|
197
|
+
end
|
198
|
+
|
199
|
+
def http_status_code
|
200
|
+
400
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
185
204
|
end
|