root/trunk/grails-app/controllers/RestController.groovy @ 2180

Revision 2180, 23.5 KB (checked in by work@…, 2 years ago)

- adding support for programmatic logins using the 'hello' method in the restController over http basic authentication.
- e.g. /rest/hello?consumer=myConsumerId

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