collection_api.rb 11.5 KB
Newer Older
1
2
3
module Chemotion
  class CollectionAPI < Grape::API
    resource :collections do
4
5
6
7
8
9
10
11
12
13
14

      desc "Return collection by id"
      params do
        requires :id, type: Integer, desc: "Collection id"
      end
      route_param :id, requirements: { id: /[0-9]*/ } do
        get do
          Collection.find(params[:id])
        end
      end

15
16
17
18
19
20
21
22
23
24
25
      namespace :take_ownership do
        desc "Take ownership of collection with specified id"
        params do
          requires :id, type: Integer, desc: "Collection id"
        end
        route_param :id do
          before do
            error!('401 Unauthorized', 401) unless CollectionPolicy.new(@current_user, Collection.find(params[:id])).take_ownership?
          end

          post do
26
            Usecases::Sharing::TakeOwnership.new(params.merge(current_user_id: current_user.id)).execute!
27
28
29
30
          end
        end
      end

31
      desc "Return all unshared serialized collection roots of current user"
32
      get :roots do
33
        current_user.collections.ordered.unshared.roots
34
      end
35

36
      desc "Return all shared serialized collections"
37
      get :shared_roots do
38
        Collection.shared(current_user.id)
39
40
      end

41
      desc "Return all remote serialized collections"
42
      get :remote_roots, each_serializer: RemoteCollectionSerializer do
43
        current_user.collections.remote(current_user.id)
44
45
      end

46
47
48
49
50
      desc "Bulk update and/or create new collections"
      patch '/' do
        Collection.bulk_update(current_user.id, params[:collections].as_json(except: :descendant_ids), params[:deleted_ids])
      end

51
      namespace :shared do
52
53
54
55
56
57
58
        desc "Update shared collection"
        params do
          requires :id, type: Integer
          requires :permission_level, type: Integer
          requires :sample_detail_level, type: Integer
          requires :reaction_detail_level, type: Integer
          requires :wellplate_detail_level, type: Integer
59
          requires :screen_detail_level, type: Integer
60
61
62
63
64
65
        end
        put ':id' do
          Collection.find(params[:id]).update({
            permission_level: params[:permission_level],
            sample_detail_level: params[:sample_detail_level],
            reaction_detail_level: params[:reaction_detail_level],
66
67
            wellplate_detail_level: params[:wellplate_detail_level],
            screen_detail_level: params[:screen_detail_level]
68
69
70
          })
        end

71
72
        desc "Create shared collections"
        params do
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
          requires :elements_filter, type: Hash do
            optional :sample, type: Hash do
              optional :all, type: Boolean
              optional :included_ids, type: Array
              optional :excluded_ids, type: Array
            end

            optional :reaction, type: Hash do
              optional :all, type: Boolean
              optional :included_ids, type: Array
              optional :excluded_ids, type: Array
            end

            optional :wellplate, type: Hash do
              optional :all, type: Boolean
              optional :included_ids, type: Array
              optional :excluded_ids, type: Array
            end
91
92
93
94
95
96

            optional :screen, type: Hash do
              optional :all, type: Boolean
              optional :included_ids, type: Array
              optional :excluded_ids, type: Array
            end
97
          end
98
99
100
101
102
103
104
          requires :collection_attributes, type: Hash do
            requires :permission_level, type: Integer
            requires :sample_detail_level, type: Integer
            requires :reaction_detail_level, type: Integer
            requires :wellplate_detail_level, type: Integer
          end
          requires :user_ids, type: Array
105
          optional :current_collection_id, type: Integer
106
        end
107
108

        before do
109
110
111
112
          samples = Sample.for_user(current_user.id).for_ui_state(params[:elements_filter][:sample])
          reactions = Reaction.for_user(current_user.id).for_ui_state(params[:elements_filter][:reaction])
          wellplates = Wellplate.for_user(current_user.id).for_ui_state(params[:elements_filter][:wellplate])
          screens = Screen.for_user(current_user.id).for_ui_state(params[:elements_filter][:screen])
113
114
115
116
117

          top_secret_sample = samples.pluck(:is_top_secret).any?
          top_secret_reaction = reactions.flat_map(&:samples).map(&:is_top_secret).any?
          top_secret_wellplate = wellplates.flat_map(&:samples).map(&:is_top_secret).any?
          top_secret_screen = screens.flat_map(&:wellplates).flat_map(&:samples).map(&:is_top_secret).any?
118

119
          is_top_secret = top_secret_sample || top_secret_wellplate || top_secret_reaction || top_secret_screen
120

121
122
123
124
          share_samples = ElementsPolicy.new(current_user, samples).share?
          share_reactions = ElementsPolicy.new(current_user, reactions).share?
          share_wellplates = ElementsPolicy.new(current_user, wellplates).share?
          share_screens = ElementsPolicy.new(current_user, screens).share?
125

126
          sharing_allowed = share_samples && share_reactions && share_wellplates && share_screens
127

128
          error!('401 Unauthorized', 401) if (!sharing_allowed || is_top_secret)
129
130
        end

131
132
133
134
135
        post do
          # TODO better way to do this?
          params[:collection_attributes][:shared_by_id] = current_user.id
          Usecases::Sharing::ShareWithUsers.new(params).execute!
        end
136
137
138
139
      end

      # TODO add authorization/authentication, e.g. is current_user allowed
      # to fetch this samples?
140
141
142
143
144
145
146
147
148
149
      desc "Return serialized samples for given collection id"
      params do
        requires :id, type: Integer, desc: "Collection id"
      end

      route_param :id do
        get :samples do
          Collection.find(params[:id]).samples
        end
      end
Marco Sehrer's avatar
Marco Sehrer committed
150

151
152
153
154
155
156
      namespace :elements do
        desc "Update the collection of a set of elements by UI state"
        params do
          requires :ui_state, type: Hash, desc: "Selected elements from the UI"
          requires :collection_id, type: Integer, desc: "Destination collection id"
        end
157
        put do
158

159
160
          ui_state = params[:ui_state]
          current_collection_id = ui_state[:currentCollectionId]
161
          collection_id = params[:collection_id]
Fernando D'Agostino's avatar
Fernando D'Agostino committed
162

163
          sample_ids = Sample.for_user(current_user.id).for_ui_state_with_collection(
164
165
            ui_state[:sample],
            CollectionsSample,
166
167
168
            current_collection_id
          )

169
          CollectionsSample.where(
170
            sample_id: sample_ids,
171
172
173
            collection_id: current_collection_id
          ).delete_all

174
          sample_ids.map { |id|
Fernando D'Agostino's avatar
Fernando D'Agostino committed
175
            CollectionsSample.find_or_create_by(sample_id: id, collection_id: collection_id)
176
          }
177

178
          reaction_ids = Reaction.for_user(current_user.id).for_ui_state_with_collection(
179
180
            ui_state[:reaction],
            CollectionsReaction,
181
182
183
            current_collection_id
          )

184
          CollectionsReaction.where(
185
            reaction_id: reaction_ids,
186
187
188
            collection_id: current_collection_id
          ).delete_all

189
          reaction_ids.map { |id|
Fernando D'Agostino's avatar
Fernando D'Agostino committed
190
            CollectionsReaction.find_or_create_by(reaction_id: id, collection_id: collection_id)
191
          }
192

193
          wellplate_ids = Wellplate.for_user(current_user.id).for_ui_state_with_collection(
194
195
            ui_state[:wellplate],
            CollectionsWellplate,
196
197
198
            current_collection_id
          )

199
          CollectionsWellplate.where(
200
            wellplate_id: wellplate_ids,
201
202
203
            collection_id: current_collection_id
          ).delete_all

204
          wellplate_ids.map { |id|
Fernando D'Agostino's avatar
Fernando D'Agostino committed
205
            CollectionsWellplate.find_or_create_by(wellplate_id: id, collection_id: collection_id)
206
          }
Fernando D'Agostino's avatar
Fernando D'Agostino committed
207

208
          screen_ids = Screen.for_user(current_user.id).for_ui_state_with_collection(
209
210
211
212
            ui_state[:screen],
            CollectionsScreen,
            current_collection_id
          )
213

214
          CollectionsScreen.where(
215
            screen_id: screen_ids,
216
217
218
            collection_id: current_collection_id
          ).delete_all

219
220
          screen_ids.map { |id|
            CollectionsScreen.find_or_create_by(screen_id: id, collection_id: collection_id)
221
          }
222
        end
223

224
225
226
227
228
229
230
231
        desc "Assign a collection to a set of elements by UI state"
        params do
          requires :ui_state, type: Hash, desc: "Selected elements from the UI"
          requires :collection_id, type: Integer, desc: "Destination collection id"
        end
        post do
          ui_state = params[:ui_state]
          collection_id = params[:collection_id]
232
233
          current_collection_id = ui_state[:currentCollectionId]

234
          Sample.for_user(current_user.id).for_ui_state_with_collection(
235
236
            ui_state[:sample],
            CollectionsSample,
237
238
            current_collection_id
          ).each do |id|
239
240
            CollectionsSample.find_or_create_by(sample_id: id, collection_id: collection_id)
          end
241

242
          Reaction.for_user(current_user.id).for_ui_state_with_collection(
243
244
            ui_state[:reaction],
            CollectionsReaction,
245
246
            current_collection_id
          ).each do |id|
247
248
249
            CollectionsReaction.find_or_create_by(reaction_id: id, collection_id: collection_id)
          end

250
          Wellplate.for_user(current_user.id).for_ui_state_with_collection(
251
252
            ui_state[:wellplate],
            CollectionsWellplate,
253
254
            current_collection_id
          ).each do |id|
255
256
            CollectionsWellplate.find_or_create_by(wellplate_id: id, collection_id: collection_id)
          end
257

258
          Screen.for_user(current_user.id).for_ui_state_with_collection(
259
260
261
262
263
264
            ui_state[:screen],
            CollectionsScreen,
            current_collection_id
          ).each do |id|
            CollectionsScreen.find_or_create_by(screen_id: id, collection_id: collection_id)
          end
265
        end
266
267
268
269
270
271
272
273
274

        desc "Remove from a collection a set of elements by UI state"
        params do
          requires :ui_state, type: Hash, desc: "Selected elements from the UI"
        end
        delete do
          ui_state = params[:ui_state]
          current_collection_id = ui_state[:currentCollectionId]

275
          sample_ids = Sample.for_ui_state_with_collection(
276
277
            ui_state[:sample],
            CollectionsSample,
278
279
280
281
            current_collection_id
          )

          CollectionsSample.where(
282
            sample_id: sample_ids,
283
284
285
286
            collection_id: current_collection_id
          ).delete_all

          reaction_ids = Reaction.for_ui_state_with_collection(
287
288
            ui_state[:reaction],
            CollectionsReaction,
289
290
291
292
            current_collection_id
          )

          CollectionsReaction.where(
293
            reaction_id: reaction_ids,
294
295
296
297
            collection_id: current_collection_id
          ).delete_all

          wellplate_ids = Wellplate.for_ui_state_with_collection(
298
299
            ui_state[:wellplate],
            CollectionsWellplate,
300
301
            current_collection_id
          )
302

303
          CollectionsWellplate.where(
304
            wellplate_id: wellplate_ids,
305
306
            collection_id: current_collection_id
          ).delete_all
307

308
309
310
311
312
313
314
315
316
317
          screen_ids = Screen.for_ui_state_with_collection(
            ui_state[:screen],
            CollectionsScreen,
            current_collection_id
          )

          CollectionsScreen.where(
            screen_id: screen_ids,
            collection_id: current_collection_id
          ).delete_all
318
319
        end

320
321
      end

322
323
324
325
326
327
328
329
330
331
332
333
      namespace :unshared do

        desc "Create an unshared collection"
        params do
          requires :label, type: String, desc: "Collection label"
        end
        post do
          Collection.create(user_id: current_user.id, label: params[:label])
        end

      end

334
335
336
    end
  end
end