1
1
package life .qbic .projectmanagement .application .api ;
2
2
3
+ import static life .qbic .projectmanagement .application .authorization .ReactiveSecurityContextUtils .applySecurityContext ;
4
+ import static life .qbic .projectmanagement .application .authorization .ReactiveSecurityContextUtils .applySecurityContextMany ;
5
+ import static life .qbic .projectmanagement .application .authorization .ReactiveSecurityContextUtils .writeSecurityContext ;
6
+ import static life .qbic .projectmanagement .application .authorization .ReactiveSecurityContextUtils .writeSecurityContextMany ;
7
+
3
8
import java .nio .ByteBuffer ;
9
+ import java .util .List ;
4
10
import java .util .Objects ;
11
+ import life .qbic .application .commons .SortOrder ;
5
12
import life .qbic .logging .api .Logger ;
6
13
import life .qbic .logging .service .LoggerFactory ;
7
14
import life .qbic .projectmanagement .application .ProjectInformationService ;
8
- import static life .qbic .projectmanagement .application .authorization .ReactiveSecurityContextUtils .applySecurityContext ;
9
- import static life .qbic .projectmanagement .application .authorization .ReactiveSecurityContextUtils .writeSecurityContext ;
10
- import life .qbic .projectmanagement .application .sample .SampleIdCodeEntry ;
15
+ import life .qbic .projectmanagement .application .sample .SampleInformationService ;
11
16
import life .qbic .projectmanagement .application .sample .SamplePreview ;
17
+ import life .qbic .projectmanagement .domain .model .experiment .ExperimentId ;
12
18
import life .qbic .projectmanagement .domain .model .project .ProjectId ;
13
19
import life .qbic .projectmanagement .domain .model .sample .Sample ;
20
+ import life .qbic .projectmanagement .domain .model .sample .SampleId ;
14
21
import org .springframework .beans .factory .annotation .Autowired ;
15
22
import org .springframework .lang .NonNull ;
16
23
import org .springframework .security .core .context .SecurityContext ;
32
39
@ Service
33
40
public class AsyncProjectServiceImpl implements AsyncProjectService {
34
41
42
+ public static final String ACCESS_DENIED = "Access denied" ;
35
43
private static final Logger log = LoggerFactory .logger (AsyncProjectServiceImpl .class );
36
44
private final ProjectInformationService projectService ;
37
45
private final Scheduler scheduler ;
46
+ private final SampleInformationService sampleInfoService ;
38
47
39
48
public AsyncProjectServiceImpl (@ Autowired ProjectInformationService projectService ,
49
+ @ Autowired SampleInformationService sampleInfoService ,
40
50
@ Autowired Scheduler scheduler ) {
41
51
this .projectService = Objects .requireNonNull (projectService );
52
+ this .sampleInfoService = Objects .requireNonNull (sampleInfoService );
42
53
this .scheduler = Objects .requireNonNull (scheduler );
43
54
}
44
55
@@ -75,22 +86,55 @@ public Flux<ByteBuffer> roCrateSummary(String projectId) {
75
86
throw new RuntimeException ("not implemented" );
76
87
}
77
88
78
- @ Override
79
- public Flux <SamplePreview > getSamplePreviews (String projectId , String experimentId )
80
- throws RequestFailedException {
81
- throw new RuntimeException ("not implemented" );
82
- }
83
89
84
90
@ Override
85
91
public Flux <SamplePreview > getSamplePreviews (String projectId , String experimentId , int offset ,
86
- int limit ) {
87
- throw new RuntimeException ("not implemented" );
92
+ int limit , List <SortOrder > sortOrders , String filter ) {
93
+ SecurityContext securityContext = SecurityContextHolder .getContext ();
94
+ return applySecurityContextMany (Flux .defer (() ->
95
+ fetchSamplePreviews (projectId , experimentId , offset , limit , sortOrders , filter )))
96
+ .subscribeOn (scheduler )
97
+ .transform (original -> writeSecurityContextMany (original , securityContext ))
98
+ .retryWhen (defaultRetryStrategy ());
99
+ }
100
+
101
+ private Flux <SamplePreview > fetchSamplePreviews (String projectId , String experimentId , int offset ,
102
+ int limit , List <SortOrder > sortOrders , String filter ) {
103
+ try {
104
+ return Flux .fromIterable (
105
+ sampleInfoService .queryPreview (ProjectId .parse (projectId ),
106
+ ExperimentId .parse (experimentId ), offset , limit ,
107
+ sortOrders , filter ));
108
+ } catch (Exception e ) {
109
+ log .error ("Error getting sample previews" , e );
110
+ return Flux .error (new RequestFailedException ("Error getting sample previews" ));
111
+ }
88
112
}
89
113
90
114
@ Override
91
115
public Flux <Sample > getSamples (String projectId , String experimentId )
92
116
throws RequestFailedException {
93
- throw new RuntimeException ("not implemented" );
117
+ SecurityContext securityContext = SecurityContextHolder .getContext ();
118
+ return applySecurityContextMany (Flux .defer (() -> fetchSamples (projectId , experimentId )))
119
+ .subscribeOn (scheduler )
120
+ .transform (original -> writeSecurityContextMany (original , securityContext ))
121
+ .retryWhen (defaultRetryStrategy ());
122
+ }
123
+
124
+ // disclaimer: no security context, no scheduler applied
125
+ private Flux <Sample > fetchSamples (String projectId , String experimentId ) {
126
+ try {
127
+ return Flux .fromIterable (
128
+ sampleInfoService .retrieveSamplesForExperiment (ProjectId .parse (projectId ),
129
+ experimentId ));
130
+ } catch (org .springframework .security .access .AccessDeniedException e ) {
131
+ log .error ("Error getting samples" , e );
132
+ return Flux .error (new AccessDeniedException (ACCESS_DENIED ));
133
+ } catch (Exception e ) {
134
+ log .error ("Unexpected exception getting samples" , e );
135
+ return Flux .error (
136
+ new RequestFailedException ("Error getting samples for experiment " + experimentId ));
137
+ }
94
138
}
95
139
96
140
@ Override
@@ -100,9 +144,20 @@ public Flux<Sample> getSamplesForBatch(String projectId, String batchId)
100
144
}
101
145
102
146
@ Override
103
- public Mono <SampleIdCodeEntry > findSampleId (String projectId , String sampleCode )
104
- throws RequestFailedException {
105
- throw new RuntimeException ("not implemented" );
147
+ public Mono <Sample > findSample (String projectId , String sampleId ) {
148
+ return Mono .defer (() -> {
149
+ try {
150
+ return Mono .justOrEmpty (
151
+ sampleInfoService .findSample (ProjectId .parse (projectId ), SampleId .parse (sampleId )));
152
+ } catch (org .springframework .security .access .AccessDeniedException e ) {
153
+ log .error (ACCESS_DENIED , e );
154
+ return Mono .error (new AccessDeniedException (ACCESS_DENIED ));
155
+ } catch (Exception e ) {
156
+ log .error ("Error getting sample for sample " + sampleId , e );
157
+ return Mono .error (
158
+ new RequestFailedException ("Error getting sample for sample " + sampleId ));
159
+ }
160
+ }).subscribeOn (scheduler );
106
161
}
107
162
108
163
@ Override
@@ -165,7 +220,7 @@ private Mono<ProjectUpdateResponse> updateProjectDesign(String projectId, Projec
165
220
} catch (IllegalArgumentException e ) {
166
221
sink .error (new RequestFailedException ("Invalid project id: " + projectId ));
167
222
} catch (org .springframework .security .access .AccessDeniedException e ) {
168
- sink .error (new AccessDeniedException ("Access denied" ));
223
+ sink .error (new AccessDeniedException (ACCESS_DENIED ));
169
224
} catch (RuntimeException e ) {
170
225
sink .error (new RequestFailedException ("Update project design failed" , e ));
171
226
}
0 commit comments