source: trunk/grails-app/controllers/RestController.groovy @ 1992

Last change on this file since 1992 was 1992, checked in by business@…, 11 years ago

added exception handling for host resolving

  • Property svn:keywords set to Rev Author Date
File size: 23.9 KB
Line 
1/**
2 * RestController
3 *
4 * This controler provides a REST service.
5 * The names of the RESET resources are the same as the names of this
6 * controller's actions. E.g., the resources called getStudies simply
7 * corresponds to the action getStudies. Some of the resources are parameterized.
8 * The parameters are passed as parameters in the url and are available in the
9 * params respecting Grails' conventions. In this file, we adher to the javadoc 
10 * convention for describing parameters ("@param"), but actually we mean
11 * key-value pairs in the params object of each Grails action we comment on.
12 *
13 * @author      Jahn-Takeshi Saito
14 * @since       20100601
15 *
16 */
17
18import dbnp.studycapturing.Study
19import dbnp.studycapturing.Assay
20import dbnp.authentication.SecUser
21import grails.converters.*
22import nl.metabolomicscentre.dsp.http.BasicAuthentication
23import dbnp.rest.common.CommunicationManager
24import org.springframework.security.core.context.SecurityContextHolder;
25
26class RestController {
27
28        /**************************************************/
29        /** Rest resources for Simple Assay Module (SAM) **/
30        /**************************************************/
31
32        def authenticationService
33        //def beforeInterceptor = [action:this.&auth,except:["isUser"]]
34        def credentials
35        def requestUser
36
37        /**
38         * Authorization closure, which is run before executing any of the REST resource actions
39         * It fetches a consumer/token combination from the url and checks whether
40         * that is a correct and known combination
41         *
42         * @param       consumer        consumer name of the calling module
43         * @param       token           token for the authenticated user (e.g. session_id)
44         * @return  true if the user is remotely logged in, false otherwise
45         */
46        private def auth() {
47                if( !authenticationService.isRemotelyLoggedIn( params.consumer, params.token ) ) {
48                        response.sendError(403)
49                        return false
50                } else {
51                        return true
52                }
53        }
54
55        /**
56         * REST resource for data modules.
57         * Consumer and token should be supplied via URL parameters.
58         * Determines whether the given user/password combination is a valid GSCF account.
59         *
60         * @param       consumer        consumer name of the calling module
61         * @param       token           token for the authenticated user (e.g. session_id)
62         * @return bool {"authenticated":true} when user/password is a valid GSCF account, {"authenticated":false} otherwise.
63         */
64        def isUser = {
65                boolean isUser = authenticationService.isRemotelyLoggedIn( params.consumer, params.token )
66                def reply = ['authenticated':isUser]
67
68                // set output header to json
69                response.contentType = 'application/json'
70
71                render reply as JSON
72        }
73
74        /**
75         * REST resource for data modules.
76         * Consumer and token should be supplied via URL parameters.
77         * Provides the details of the user that has logged in
78         *
79         * @param       consumer        consumer name of the calling module
80         * @param       token           token for the authenticated user (e.g. session_id)
81         * @return bool {"username": "...", "id": ... } when user/password is logged in.
82         */
83        def getUser = {
84                if( !auth() )
85                        return;
86               
87                SecUser user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
88                def reply = [username: user.username, id: user.id, isAdministrator: user.hasAdminRights() ]
89
90                // set output header to json
91                response.contentType = 'application/json'
92
93                render reply as JSON
94        }
95
96        /**
97         * REST resource for data modules.
98         * Consumer and token should be supplied via URL parameters.
99         * Provide a list of all studies owned by the supplied user.
100         *
101         * @param       studyToken  optional parameter. If no studyToken is given, all studies available to user are returned.
102         *                      Otherwise, the studies for which the studyTokens are given are be returned.
103         * @param       consumer        consumer name of the calling module
104         * @param       token           token for the authenticated user (e.g. session_id)
105         * @return  JSON object list containing 'studyToken', and 'name' (title) for each study
106         *
107         * If one study is requested, a 404 error might occur if the study doesn't exist, and a 401 error if the user is not
108         * authorized to access this study. If multiple studies are requrested, non-existing studies or studies for which the
109         * user is not authorized are not returned in the list (so the list might be empty).
110         *
111         * Example 1. REST call without studyToken.
112         *
113         * Call: http://localhost:8080/gscf/rest/getStudies/query
114         *
115         * Result: [{"title":"NuGO PPS3 mouse study leptin module","studyToken":"PPS3_leptin_module",
116         *                      "startDate":"2008-01-01T23:00:00Z","published":false,"Description":"C57Bl/6 mice were fed a high fat (45 en%)
117         *                      or low fat (10 en%) diet after a four week run-in on low fat diet.","Objectives":null,"Consortium":null,
118         *                      "Cohort name":null,"Lab id":null,"Institute":null,"Study protocol":null},
119         *                      {"title":"NuGO PPS human study","studyToken":"PPSH","startDate":"2008-01-13T23:00:00Z","published":false,
120         *                      "Description":"Human study performed at RRI; centres involved: RRI, IFR, TUM, Maastricht U.","Objectives":null,
121         *                      "Consortium":null,"Cohort name":null,"Lab id":null,"Institute":null,"Study protocol":null}]
122         *
123         *
124         * Example 2. REST call with one studyToken.
125         *
126         * Call: http://localhost:8080/gscf/rest/getStudies/query?studyToken=PPSH
127         *
128         * Result: [{"title":"NuGO PPS human study","studyToken":"PPSH","startDate":"2008-01-13T23:00:00Z",
129         *              "published":false,"Description":"Human study performed at RRI; centres involved: RRI, IFR, TUM, Maastricht U.",
130         *              "Objectives":null,"Consortium":null,"Cohort name":null,"Lab id":null,"Institute":null,"Study protocol":null}]
131         *
132         *
133         *
134         * Example 2. REST call with two studyTokens.
135         *
136         * http://localhost:8080/gscf/rest/getStudies/query?studyToken=PPSH&studyToken=PPS3_leptin_module
137         *
138         * Result: same as result of Example 1.
139         */
140        def getStudies = {
141                def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
142               
143                List returnStudies = []
144                List studies = []
145
146                if( !params.studyToken ) {
147                        studies = Study.findAll()
148                }
149                else if( params.studyToken instanceof String ) {
150                        def study = Study.findByStudyUUID( params.studyToken )
151                        if( study ) {
152                                if( !study.canRead(user) ) {
153                                        response.sendError(401)
154                                        return false
155                                }
156
157                                studies.push study
158                        } else {
159                                response.sendError(404)
160                                return false
161                        }
162
163                }
164                else {
165                        params.studyToken.each{ studyToken ->
166                                def study = Study.findByStudyUUID( studyToken );
167                                if( study )
168                                        studies.push study
169                        }
170                }
171
172
173                studies.each { study ->
174                        if(study) {
175                                // Check whether the person is allowed to read the data of this study
176                                if( study.canRead(user)) {
177
178                                        def items = [studyToken:study.giveUUID(), 'public': study.publicstudy]
179                                        study.giveFields().each { field ->
180                                                def name = field.name
181                                                def value = study.getFieldValue( name )
182                                                items[name] = value
183                                        }
184
185                                        // Add study version number
186                                        items['version'] = study.version;
187
188                                        returnStudies.push items
189                                }
190                        }
191                }
192
193                // set output header to json
194                response.contentType = 'application/json'
195
196                render returnStudies as JSON
197        }
198
199        /**
200         * REST resource for data modules.
201         * Consumer and token should be supplied via URL parameters.
202         * Provides the version number of the specified study
203         *
204         * @param       studyToken  optional parameter. If no studyToken is given, a 400 error is given
205         * @param       consumer        consumer name of the calling module
206         * @param       token           token for the authenticated user (e.g. session_id)
207         * @return  JSON object list containing 'studyToken', and 'version'
208         *
209         * A 404 error might occur if the study doesn't exist, and a 401 error if the user is not
210         * authorized to access this study.
211         *
212         * Example. REST call with one studyToken.
213         *
214         * Call: http://localhost:8080/gscf/rest/getStudyVersion?studyToken=PPSH
215         *
216         * Result: {"studyToken":"PPSH","version":31}
217         */
218        def getStudyVersion = {
219                def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
220               
221                def versionInfo = [:];
222                def study
223
224                if( !params.studyToken || !(params.studyToken instanceof String)) {
225                        response.sendError(400)
226                        return false
227                } else {
228                        study = Study.findByStudyUUID( params.studyToken )
229                        if( study ) {
230                                if( !study.canRead(user) ) {
231                                        response.sendError(401)
232                                        return false
233                                }
234                        } else {
235                                response.sendError(404)
236                                return false
237                        }
238                }
239
240                versionInfo[ 'studyToken' ] = params.studyToken;
241                versionInfo[ 'version' ] = study.version;
242
243                // set output header to json
244                response.contentType = 'application/json'
245
246                render versionInfo as JSON
247        }
248
249        /**
250        * REST resource for data modules.
251        * Consumer and token should be supplied via URL parameters.
252        * Provides the version number of all studies readable by this user
253        *
254        * @param        consumer        consumer name of the calling module
255        * @param        token           token for the authenticated user (e.g. session_id)
256        * @return  JSON object list containing studies with 'studyToken', and 'version'
257        *
258        * A 404 error might occur if the study doesn't exist, and a 401 error if the user is not
259        * authorized to access this study.
260        *
261        * Example. REST call with one studyToken.
262        *
263        * Call: http://localhost:8080/gscf/rest/getStudyVersions
264        *
265        * Result: [{"studyToken":"PPSH","version":31},{"studyToken":"Other study", "version":3}]
266        */
267   def getStudyVersions = {
268           // Check which user has been logged in
269           def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
270           
271           def jsonList = []
272           
273                Study.giveReadableStudies( user ).each { study ->
274                        if(study) {
275                                jsonList << [studyToken:study.giveUUID(), version: study.version]
276                        }
277                }
278
279                // set output header to json
280                response.contentType = 'application/json'
281
282                render jsonList as JSON
283   }
284
285       
286        /**
287         * REST resource for data modules.
288         * Consumer and token should be supplied via URL parameters.
289         * Provide a list of all subjects belonging to a study.
290         *
291         * If the user is not allowed to read the study contents, a 401 error is given. If the study doesn't exist, a 404 error is given
292         *
293         * @param       studyToken      String The external study id (code) of the target GSCF Study object
294         * @param       consumer        consumer name of the calling module
295         * @param       token           token for the authenticated user (e.g. session_id)
296         * @return JSON object list of subject names
297         */
298        def getSubjects = {
299                // Check which user has been logged in
300                def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
301 
302                List subjects = []
303                if( params.studyToken ) {
304                        def study = Study.findByStudyUUID( params.studyToken)
305
306                        if(study) {
307                                // Check whether the person is allowed to read the data of this study
308                                if( !study.canRead(user) ) {
309                                        response.sendError(401)
310                                        return false
311                                }
312
313                                study.subjects.each { subjects.push it.name }
314                        } else {
315                                response.sendError(404)
316                                return false
317                        }
318                }
319
320                // set output header to json
321                response.contentType = 'application/json'
322
323                render subjects as JSON
324        }
325
326
327        /**
328         * REST resource for data modules.
329         * Consumer and token should be supplied via URL parameters.
330         * Provide a list of all assays for a given study.
331         *
332         * If the user is not allowed to read the study contents, a 401 error is given. If the study doesn't exist, a 404 error is given
333         *
334         * @param       studyToken      String The external study id (code) of the target GSCF Study object
335         * @param       consumer        consumer name of the calling module
336         * @return list of assays in the study as JSON object list, filtered to only contain assays
337         *         for the specified module, with 'assayToken' and 'name' for each assay
338         *
339         *
340         * Example 1. REST call without assayToken
341         *            http://localhost:8080/gscf/rest/getAssays/aas?studyToken=PPSH
342         *                              &consumer=http://localhost:8182/sam
343         *
344         * Result: [{"name":"Glucose assay after",
345         *                      "module":{"class":"dbnp.studycapturing.AssayModule","id":1,"name":"SAM module for clinical data",
346         *                              "platform":"clinical measurements","url":"http://localhost:8182/sam"},
347         *                      "externalAssayID":"PPSH-Glu-A", "Description":null,"parentStudyToken":"PPSH"},
348         *                      {"name":"Glucose assay before",
349         *                              "module":{"class":"dbnp.studycapturing.AssayModule","id":1,"name":"SAM module for clinical data",
350         *                              "platform":"clinical measurements","url":"http://localhost:8182/sam"},
351         *                              "externalAssayID":"PPSH-Glu-B","Description":null,"parentStudyToken":"PPSH"}]
352         *
353         *
354         * Example 2. REST call with one assayToken
355         *                        http://localhost:8080/gscf/rest/getAssays/queryOneTokenz?studyToken=PPSH
356         *                              &consumer=http://localhost:8182/sam&assayToken=PPSH-Glu-A
357         *
358         * Result: [{"name":"Glucose assay after","module":{"class":"dbnp.studycapturing.AssayModule","id":1,
359         *                      "name":"SAM module for clinical data","platform":"clinical measurements","url":"http://localhost:8182/sam"},
360         *                      "externalAssayID":"PPSH-Glu-A","Description":null,"parentStudyToken":"PPSH"}]
361         *
362         *
363         * Example 3. REST call with two assayTokens.
364         *
365         * Result: Same as result in Example 1.
366         */
367        def getAssays = {
368                def moduleURL, moduleInet, assayModuleURL, assayModuleInet
369
370                // Check which user has been logged in
371                def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
372 
373                // set output header to json
374                response.contentType = 'application/json'
375
376                List returnList = []    // return list of hashes each containing fields and values belonging to an assay
377
378                // Check if required parameters are present
379                def validCall = CommunicationManager.hasValidParams( params, "consumer" )
380                if( !validCall ) {
381                        response.status = 500;
382                        render "Error. Wrong or insufficient parameters." as JSON
383                        return
384                }
385
386                def assays = []
387               
388                if( params.studyToken ) {
389                        def study = Study.findByStudyUUID(params.studyToken)
390
391                        if(study) {
392                                // Check whether the person is allowed to read the data of this study
393                                if( !study.canRead(user)) {
394                                        response.sendError(401)
395                                        return false
396                                }
397
398                                if(params.assayToken==null) {
399                                        assays = study.assays
400                                }
401                                else if( params.assayToken instanceof String ) {
402                                        def assay = study.assays.find{ it.giveUUID() == params.assayToken }
403                                        if( assay ) {
404                                                assays.push assay
405                                        }
406                                }
407                                else {                                                                                                  // there are multiple assayTokens instances
408                                        params.assayToken.each { assayToken ->
409                                                def assay = study.assays.find{ it.giveUUID() == assayToken }
410                                                if(assay) {
411                                                        assays.push assay
412                                                }
413                                        }
414                                }
415
416                        } else {
417                                response.sendError(404)
418                                return false
419                        }
420
421                } else {
422                        // Return all assays for the given module
423                        assays = Assay.list().findAll{ it.parent.canRead( user ) }
424                }
425
426                // Create data for all assays
427                moduleURL = new URL(params.moduleURL)
428                try {
429                        moduleInet = InetAddress.getByName(moduleURL.getHost())
430                }
431                catch(Exception e) {
432                        moduleInet = moduleURL.host
433                }
434
435                assays.each{ assay ->
436                        /**
437                         * assay.module.url does not necessarily have to match the moduleURL
438                         * completely (e.g. when using a hosts file vs ip), especially when using
439                         * localhost, 127.0.01 or a host name that aliasses localhost.
440                         *
441                         * Therefore we will resolve the host names and compare the resulting ip
442                         * addresses and see if they match
443                         *
444                         * future improvement: do not use the module URL for matching at all. Perhaps
445                         * a module identifier or a 'module token' would be better as this is not
446                         * url dependant.
447                         *
448                         * check if:
449                         *  1. we've for a module url
450                         *      2. we've got an assay
451                         *      3. the calling module is the same as the assay's module by checking if:
452                         *              a. the module urls match, or
453                         *              b. the (resolved) ip addresses and path part of the module's url match
454                         */
455                        if (
456                                assay.module?.url &&
457                                assay &&
458                                (
459                                        assay.module.url.equals(params.moduleURL) ||
460                                        this.doesModuleMatch(assay, moduleURL, moduleInet)
461                                )
462                        ) {
463                                def map = [assayToken: assay.giveUUID()]
464
465                                assay.giveFields().each { field ->
466                                        def name = field.name
467                                        def value = assay.getFieldValue(name)
468                                        map[name] = value
469                                }
470
471                                map["parentStudyToken"] = assay.parent.giveUUID()
472                                returnList.push(map)
473                        }
474                }
475
476                render returnList as JSON
477        }
478
479        def doesModuleMatch = { assay, moduleURL, moduleInet ->
480
481                try {
482
483                        // only resolve hosts if the urls do not match identically
484                        def assayModuleURL = new URL(assay.module.url)
485                        def assayModuleInet = InetAddress.getByName(assayModuleURL.getHost())
486
487                        return (
488                                moduleInet.hostAddress == assayModuleInet.hostAddress &&
489                                (moduleURL.path.replaceAll(/[^a-zA-Z0-9]/, "") == assayModuleURL.path.replaceAll(/[^a-zA-Z0-9]/, ""))
490                        )
491                }
492                catch (Exception e) {
493                        // If for some reason an error occurs (e.g. because the hostname is invalid and throws an UnknownHostException)
494                        // assume the calling module does not equal the assay module considered
495                        return false
496                }
497        }
498
499        /**
500         * REST resource for data modules.
501         * Provide all samples of a given Assay. The result is an enriched list with additional information for each sample.
502         *
503         * If the user is not allowed to read the study contents, a 401 error is given. If the assay doesn't exist, a 404 error is given
504         *
505         * @param       assayToken      String (assayToken of some Assay in GSCF)
506         * @param       sampleToken Optional parameter. One or more sampleTokens to specify what sample to give exectly.
507         *                      If not given, return all samples for specified assay.
508         * @param       consumer        consumer name of the calling module
509         * @param       token           token for the authenticated user (e.g. session_id)
510         * @return As a JSON object list, for each sample in that assay:
511         * @return 'name' (Sample name, which is unique)
512         * @return 'material' (Sample material)
513         * @return 'subject' (The name of the subject from which the sample was taken)
514         * @return 'event' (the name of the template of the SamplingEvent describing the sampling)
515         * @return 'startTime' (the time the sample was taken relative to the start of the study, as a string)
516         * @return additional template fields are returned
517         *
518         *
519         *
520         * Example 1: no sampleTokens given.
521         * Query:
522         * http://localhost:8080/gscf/rest/getSamples/query?assayToken=PPSH-Glu-A
523         *
524         * Result:
525         * [{"sampleToken":"5_A","material":"blood plasma","subject":"5","event":"Blood extraction","startTime":"4 days, 6 hours"},
526         * {"sampleToken":"6_A","mateauthenticationService.getRemotelyLoggedInUser( params.consumer, params.token )rial":"blood plasma","subject":"6","event":"Blood extraction","startTime":"4 days, 6 hours"},
527         * {"sampleToken":"10_A","material":"blood plasma","subject":"10","event":"Blood extraction","startTime":"4 days, 6 hours"},
528         * {"sampleToken":"2_A","material":"blood plasma","subject":"2","event":"Blood extraction","startTime":"4 days, 6 hours"},
529         * {"sampleToken":"11_A","material":"blood plasma","subject":"11","event":"Blood extraction","startTime":"4 days, 6 hours"},
530         * {"sampleToken":"1_A","material":"blood plasma","subject":"1","event":"Blood extraction","startTime":"4 days, 6 hours"},
531         * {"sampleToken":"9_A","material":"blood plasma","subject":"9","event":"Blood extraction","startTime":"4 days, 6 hours"},
532         * {"sampleToken":"4_A","material":"blood plasma","subject":"4","event":"Blood extraction","startTime":"4 days, 6 hours"},
533         * {"sampleToken":"8_A","material":"blood plasma","subject":"8","event":"Blood extraction","startTime":"4 days, 6 hours"},
534         * {"sampleToken":"7_A","material":"blood plasma","subject":"7","event":"Blood extraction","startTime":"4 days, 6 hours"},
535         * {"sampleToken":"3_A","material":"blood plasma","subject":"3","event":"Blood extraction","startTime":"4 days, 6 hours"}]
536         *
537         *
538         *
539         * Example 2: one sampleToken given.
540         * Query:
541         * http://localhost:8080/gscf/rest/getSamples/query?assayToken=PPSH-Glu-A&sampleToken=5_A
542         *
543         * Result:
544         * [{"sampleToken":"5_A","material":"blood plasma","subject":"5","event":"Blood extraction","startTime":"4 days, 6 hours"}]
545         *
546         *
547         *
548         * Example 3: two sampleTokens given.
549         * Query:
550         * http://localhost:8080/gscf/rest/getSamples/query?assayToken=PPSH-Glu-A&sampleToken=5_A&sampleToken=6_A
551         *
552         * Result:
553         * [{"sampleToken":"5_A","material":"blood plasma","subject":"5","event":"Blood extraction","startTime":"4 days, 6 hours"},
554         *  {"sampleToken":"6_A","material":"blood plasma","subject":"6","event":"Blood extraction","startTime":"4 days, 6 hours"}]
555         *
556         *
557         * Example 4: no assaytoken given
558         * Query:
559         * http://localhost:8080/gscf/rest/getSamples/query?sampleToken=5_A&sampleToken=6_A
560         *
561         * Result:
562         * [{"sampleToken":"5_A","material":"blood plasma","subject":"5","event":"Blood extraction","startTime":"4 days, 6 hours"},
563         *  {"sampleToken":"6_A","material":"blood plasma","subject":"6","event":"Blood extraction","startTime":"4 days, 6 hours"}]
564         *
565         */
566        def getSamples = {
567                // Check which user has been logged in
568                def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token )
569
570                def items = []
571                def samples
572                if( params.assayToken ) {
573                        def assay = Assay.findByAssayUUID( params.assayToken );
574
575                        if( assay )  {
576                                // Check whether the person is allowed to read the data of this study
577                                if( !assay.parent.canRead( user )) {
578                                        response.sendError(401)
579                                        return false
580                                }
581
582                                samples = assay.getSamples() // on all samples
583                        } else {
584                                // Assay not found
585                                response.sendError(404)
586                                return false
587                        }
588                } else {
589                        // Find all samples from studies the user can read
590                        def studies = Study.list().findAll { it.canRead( user ) };
591                        samples = studies*.getSamples().flatten();
592                }
593
594                // Check whether only a subset of samples should be returned
595                if( params.sampleToken ) {
596                        def sampleTokens = params.list( "sampleToken" );
597                        samples = samples.findAll { sampleTokens.contains( it.giveUUID() ) }
598                }
599
600                samples.each { sample ->
601
602                        def item = [
603                                                'sampleToken' : sample.giveUUID(),
604                                                'material'        : sample.material?.name,
605                                                'subject'         : sample.parentSubject?.name,
606                                                'event'           : sample.parentEvent?.template?.name,
607                                                'startTime'       : sample.parentEvent?.getStartTimeString()
608                                        ]
609
610                        sample.giveFields().each { field ->
611                                def name = field.name
612                                def value = sample.getFieldValue( name )
613                                if(name!='material')
614                                {
615                                        item[name]=value
616                                }
617                        }
618
619                        if(sample.parentEvent) {
620                                def parentEvent = sample.parentEvent
621                                def eventHash = [:]
622                                parentEvent.giveFields().each { field ->
623                                        def name = field.name
624                                        if( name !='sampleTemplate' && name != 'fields') {
625                                                def value = parentEvent.getFieldValue( name )
626                                                eventHash[name]=value
627                                        }
628                                }
629                                item['eventObject'] = eventHash
630                        }
631
632                        if(sample.parentSubject) {
633                                def parentSubject = sample.parentSubject
634                                def subject = [:]
635                                parentSubject.giveFields().each { field ->
636                                        def name = field.name
637                                        if( name!='fields') {
638                                                def value = parentSubject.getFieldValue( name )
639                                                subject[name]=value
640                                        }
641                                }
642                                item['subjectObject'] = subject
643                        }
644
645                        items.push item
646                }
647
648                // set output header to json
649                response.contentType = 'application/json'
650
651                render items as JSON
652        }
653
654        /**
655         * Returns the authorization level the user has for a given study or assay.
656         *
657         * If no studyToken or assayToken is given, a 400 (Bad Request) error is given.
658         * If both a studyToken and assayToken are given, the studyToken is used and the assayToken is ignored.
659         * If the given assay or study doesn't exist, a 404 (Not found) error is given.
660         *
661         * @param       consumer        consumer name of the calling module
662         * @param       token           token for the authenticated user (e.g. session_id)
663         * @param       studyToken      token of the study for which the authorization is asked
664         * @param       assayToken      token of the study for which the authorization is asked
665         * @return      JSON Object
666         * @return  { isOwner: true/false, 'canRead': true/false, 'canWrite': true/false }
667         */
668        def getAuthorizationLevel = {
669                def study
670               
671                if( params.studyToken ) {
672                        study = Study.findByStudyUUID(params.studyToken);
673                } else if( params.assayToken ) {
674                        study = Assay.findByAssayUUID(params.assayToken)?.parent;
675                } else {
676                        response.sendError(400)
677                        return false
678                }
679
680                if( !study ) {
681                        response.sendError(404)
682                        return false
683                }
684
685                def user = authenticationService.getRemotelyLoggedInUser( params.consumer, params.token );
686                def auth = ['isOwner': study.isOwner(user), 'canRead': study.canRead(user), 'canWrite': study.canWrite(user)];
687                log.trace "Authorization for study " + study.title + " and user " + user?.username + ": " + auth
688
689                // set output header to json
690                response.contentType = 'application/json'
691
692                render auth as JSON;
693        }
694}
Note: See TracBrowser for help on using the repository browser.