77 "encoding/pem"
88 "fmt"
99 "io/ioutil"
10+ "math/rand"
1011 "net/http"
1112 "net/url"
1213 "time"
@@ -110,6 +111,7 @@ func loadSigningKey() (*PrivateKeyResult, *KeyLoadError) {
110111type QuestionnaireSchema struct {
111112 Metadata []Metadata `json:"metadata"`
112113 SchemaName string `json:"schema_name"`
114+ SurveyType string `json:"theme"`
113115}
114116
115117// Metadata is a representation of the metadata within the schema with an additional `Default` value
@@ -119,6 +121,59 @@ type Metadata struct {
119121 Default string `json:"default"`
120122}
121123
124+ func isSurveyMetadata (key string ) bool {
125+ switch key {
126+ case
127+ "case_ref" ,
128+ "case_type" ,
129+ "display_address" ,
130+ "employment_date" ,
131+ "form_type" ,
132+ "period_id" ,
133+ "period_str" ,
134+ "ref_p_end_date" ,
135+ "ref_p_start_date" ,
136+ "ru_name" ,
137+ "ru_ref" ,
138+ "trad_as" ,
139+ "user_id" ,
140+ "qid" :
141+ return true
142+ }
143+ return false
144+ }
145+
146+ func isRequiredMetadata (key string ) bool {
147+ switch key {
148+ case
149+ "case_id" ,
150+ "region_code" ,
151+ "channel" ,
152+ "language_code" ,
153+ "collection_exercise_sid" ,
154+ "response_expires_at" ,
155+ "response_id" ,
156+ "schema_name" ,
157+ "account_service_url" :
158+ return true
159+ }
160+ return false
161+ }
162+
163+ func getSurveyMetadataFromClaims (claimValues map [string ][]string , data map [string ]interface {}, claims map [string ]interface {}, surveyMetadata map [string ]interface {}) {
164+ for key , value := range claimValues {
165+ if isSurveyMetadata (key ) {
166+ data [key ] = value [0 ]
167+ } else if key != "roles" && isRequiredMetadata (key ) && value [0 ] != "" {
168+ claims [key ] = value [0 ]
169+ } else if key == "roles" {
170+ claims [key ] = value
171+ }
172+ }
173+ surveyMetadata ["data" ] = data
174+ claims ["survey_metadata" ] = surveyMetadata
175+ }
176+
122177func generateClaims (claimValues map [string ][]string , launcherSchema surveys.LauncherSchema ) (claims map [string ]interface {}) {
123178
124179 var roles []string
@@ -158,6 +213,42 @@ func generateClaims(claimValues map[string][]string, launcherSchema surveys.Laun
158213 return claims
159214}
160215
216+ func generateClaimsV2 (claimValues map [string ][]string , launcherSchema surveys.LauncherSchema , schema QuestionnaireSchema ) (claims map [string ]interface {}) {
217+
218+ var roles []string
219+ if rolesValues , ok := claimValues ["roles" ]; ok {
220+ roles = rolesValues
221+ } else {
222+ roles = []string {"dumper" }
223+ }
224+
225+ claims = make (map [string ]interface {})
226+
227+ claims ["roles" ] = roles
228+ TxID , _ := uuid .NewV4 ()
229+ claims ["tx_id" ] = TxID .String ()
230+ claims ["version" ] = "v2"
231+
232+ surveyMetadata := make (map [string ]interface {})
233+ data := make (map [string ]interface {})
234+
235+ if schema .SurveyType == "social" || schema .SurveyType == "health" {
236+ receiptingKeys := []string {"qid" }
237+ surveyMetadata ["receipting_keys" ] = receiptingKeys
238+ }
239+
240+ getSurveyMetadataFromClaims (claimValues , data , claims , surveyMetadata )
241+
242+ // When quicklaunching, schema_name will not be set, but launcherSchema will have the schema_name.
243+ if len (claimValues ["schema_name" ]) == 0 && launcherSchema .Name != "" {
244+ claims ["schema_name" ] = launcherSchema .Name
245+ }
246+
247+ log .Printf ("Using claims: %s" , claims )
248+
249+ return claims
250+ }
251+
161252// GenerateJwtClaims creates a jwtClaim needed to generate a token
162253func GenerateJwtClaims () (jwtClaims map [string ]interface {}) {
163254 issued := time .Now ()
@@ -219,11 +310,10 @@ func launcherSchemaFromURL(url string) (launcherSchema surveys.LauncherSchema, e
219310 schemaName = schema .SchemaName
220311 }
221312
222- log .Println ("Quicklaunch schema_name set to: " , schemaName )
223-
224313 launcherSchema = surveys.LauncherSchema {
225- URL : url + cacheBust ,
226- Name : schemaName ,
314+ URL : url + cacheBust ,
315+ Name : schemaName ,
316+ SurveyType : schema .SurveyType ,
227317 }
228318
229319 return launcherSchema , ""
@@ -388,6 +478,76 @@ func GenerateTokenFromDefaults(schemaURL string, accountServiceURL string, accou
388478 return token , ""
389479}
390480
481+ // GenerateTokenFromDefaultsV2 coverts a set of DEFAULT values into a JWT
482+ func GenerateTokenFromDefaultsV2 (schemaURL string , accountServiceURL string , urlValues url.Values ) (token string , error string ) {
483+ launcherSchema , validationError := launcherSchemaFromURL (schemaURL )
484+ if validationError != "" {
485+ return "" , validationError
486+ }
487+
488+ schema , error := getSchema (launcherSchema )
489+ if error != "" {
490+ return "" , fmt .Sprintf ("getSchema failed err: %v" , error )
491+ }
492+
493+ claims := make (map [string ]interface {})
494+ urlValues ["account_service_url" ] = []string {accountServiceURL }
495+
496+ claims = generateClaimsV2 (urlValues , launcherSchema , schema )
497+
498+ requiredMetadata , error := GetRequiredMetadata (launcherSchema )
499+ if error != "" {
500+ return "" , fmt .Sprintf ("GetRequiredMetadata failed err: %v" , error )
501+ }
502+
503+ data := make (map [string ]interface {})
504+
505+ for _ , metadata := range requiredMetadata {
506+ if metadata .Validator == "boolean" {
507+ data [metadata .Name ] = getBooleanOrDefault (metadata .Name , urlValues , false )
508+
509+ continue
510+ }
511+ data [metadata .Name ] = getStringOrDefault (metadata .Name , urlValues , metadata .Default )
512+ }
513+
514+ surveyMetadata := make (map [string ]interface {})
515+ updatedData := make (map [string ]interface {})
516+
517+ if claims ["survey_metadata" ] != nil {
518+ surveyMetadata = claims ["survey_metadata" ].(map [string ]interface {})
519+ }
520+ for key , value := range data {
521+ updatedData [key ] = value
522+ }
523+
524+ initialData := surveyMetadata ["data" ].(map [string ]interface {})
525+
526+ for key , value := range initialData {
527+ updatedData [key ] = value
528+ }
529+
530+ surveyMetadata ["data" ] = updatedData
531+ claims ["survey_metadata" ] = surveyMetadata
532+
533+ jwtClaims := GenerateJwtClaims ()
534+ for key , v := range jwtClaims {
535+ claims [key ] = v
536+ }
537+
538+ schemaClaims := getSchemaClaims (launcherSchema )
539+ for key , v := range schemaClaims {
540+ claims [key ] = v
541+ }
542+
543+ token , tokenError := generateTokenFromClaims (claims )
544+ if tokenError != nil {
545+ return token , fmt .Sprintf ("GenerateTokenFromDefaults failed err: %v" , tokenError )
546+ }
547+
548+ return token , ""
549+ }
550+
391551// TransformSchemaParamsToName Returns a schema name from business schema parameters
392552func TransformSchemaParamsToName (postValues url.Values ) string {
393553 if postValues .Get ("schema_name" ) != "" {
@@ -402,15 +562,26 @@ func TransformSchemaParamsToName(postValues url.Values) string {
402562}
403563
404564// GenerateTokenFromPost converts a set of POST values into a JWT
405- func GenerateTokenFromPost (postValues url.Values ) (string , string ) {
565+ func GenerateTokenFromPost (postValues url.Values , launchVersion2 bool ) (string , string ) {
406566 log .Println ("POST received: " , postValues )
407567
408568 schemaName := TransformSchemaParamsToName (postValues )
409569 schemaUrl := postValues .Get ("schema_url" )
410570
411571 launcherSchema := surveys .GetLauncherSchema (schemaName , schemaUrl )
412572
413- claims := generateClaims (postValues , launcherSchema )
573+ schema , error := getSchema (launcherSchema )
574+ if error != "" {
575+ return "" , fmt .Sprintf ("getSchema failed err: %v" , error )
576+ }
577+
578+ claims := make (map [string ]interface {})
579+
580+ if launchVersion2 {
581+ claims = generateClaimsV2 (postValues , launcherSchema , schema )
582+ } else {
583+ claims = generateClaims (postValues , launcherSchema )
584+ }
414585
415586 jwtClaims := GenerateJwtClaims ()
416587 for key , v := range jwtClaims {
@@ -448,6 +619,38 @@ func GenerateTokenFromPost(postValues url.Values) (string, string) {
448619
449620// GetRequiredMetadata Gets the required metadata from a schema
450621func GetRequiredMetadata (launcherSchema surveys.LauncherSchema ) ([]Metadata , string ) {
622+ schema , error := getSchema (launcherSchema )
623+ if error != "" {
624+ return nil , fmt .Sprintf ("getSchema failed err: %v" , error )
625+ }
626+
627+ defaults := GetDefaultValues ()
628+
629+ for i , value := range schema .Metadata {
630+ schema .Metadata [i ].Default = defaults [value .Name ]
631+
632+ if value .Validator == "boolean" {
633+ schema .Metadata [i ].Default = "false"
634+ }
635+ }
636+
637+ claims := make ([]string , 0 )
638+ for _ , v := range schema .Metadata {
639+ claims = append (claims , v .Name )
640+ }
641+
642+ mandatoryClaims := getMandatatoryClaims (schema .SurveyType , defaults )
643+
644+ missingClaims := getMissingMandatoryClaims (claims , mandatoryClaims )
645+
646+ for _ , v := range missingClaims {
647+ schema .Metadata = append (schema .Metadata , v )
648+ }
649+
650+ return schema .Metadata , ""
651+ }
652+
653+ func getSchema (launcherSchema surveys.LauncherSchema ) (QuestionnaireSchema , string ) {
451654 var url string
452655
453656 if launcherSchema .URL != "" {
@@ -461,50 +664,80 @@ func GetRequiredMetadata(launcherSchema surveys.LauncherSchema) ([]Metadata, str
461664
462665 log .Println ("Loading metadata from schema:" , url )
463666
667+ var schema QuestionnaireSchema
464668 resp , err := clients .GetHTTPClient ().Get (url )
465669 if err != nil {
466670 log .Println ("Failed to load schema from:" , url )
467- return nil , fmt .Sprintf ("Failed to load Schema from %s" , url )
671+ return schema , fmt .Sprintf ("Failed to load Schema from %s" , url )
468672 }
469673
470674 if resp .StatusCode != 200 {
471675 log .Print ("Invalid response code for schema from: " , url )
472- return nil , fmt .Sprintf ("Failed to load Schema from %s" , url )
676+ return schema , fmt .Sprintf ("Failed to load Schema from %s" , url )
473677 }
474678
475679 responseBody , err := ioutil .ReadAll (resp .Body )
476680 resp .Body .Close ()
477681 if err != nil {
478682 log .Print (err )
479- return nil , fmt .Sprintf ("Failed to load Schema from %s" , url )
683+ return schema , fmt .Sprintf ("Failed to load Schema from %s" , url )
480684 }
481685
482- var schema QuestionnaireSchema
483686 if err := json .Unmarshal (responseBody , & schema ); err != nil {
484687 log .Print (err )
485- return nil , fmt .Sprintf ("Failed to unmarshal Schema from %s" , url )
688+ return schema , fmt .Sprintf ("Failed to unmarshal Schema from %s" , url )
486689 }
487690
488- defaults := GetDefaultValues ()
691+ return schema , ""
692+ }
489693
490- for i , value := range schema .Metadata {
491- schema .Metadata [i ].Default = defaults [value .Name ]
694+ func getMandatatoryClaims (surveyType string , defaults map [string ]string ) []Metadata {
695+ claims := make ([]Metadata , 0 )
696+ if surveyType == "health" || surveyType == "social" {
697+ claims = []Metadata {
698+ {"qid" , "false" , defaults ["qid" ]},
699+ }
492700
493- if value .Validator == "boolean" {
494- schema .Metadata [i ].Default = "false"
701+ } else {
702+ claims = []Metadata {
703+ {"ru_ref" , "false" , defaults ["ru_ref" ]},
704+ {"period_id" , "false" , defaults ["period_id" ]},
705+ {"user_id" , "false" , defaults ["user_id" ]},
495706 }
496707 }
497708
498- return schema .Metadata , ""
709+ return claims
710+ }
711+
712+ func getMissingMandatoryClaims (claims []string , mandatoryClaims []Metadata ) []Metadata {
713+ missingClaims := make ([]Metadata , 0 )
714+ for _ , v := range mandatoryClaims {
715+ if ! (stringInSlice (v .Name , claims )) {
716+ missingClaims = append (missingClaims , v )
717+ }
718+ }
719+
720+ return missingClaims
721+ }
722+
723+ func stringInSlice (a string , list []string ) bool {
724+ for _ , b := range list {
725+ if b == a {
726+ return true
727+ }
728+ }
729+ return false
499730}
500731
501732// GetDefaultValues Returns a map of default values for metadata keys
502733func GetDefaultValues () map [string ]string {
503-
504734 defaults := make (map [string ]string )
505-
506735 collectionExerciseSid , _ := uuid .NewV4 ()
507736
737+ defaults ["collection_exercise_sid" ] = collectionExerciseSid .String ()
738+ defaults ["qid" ] = fmt .Sprintf ("%016d" , rand .Int63n (1e16 ))
739+ defaults ["version" ] = "v2"
740+ defaults ["case_type" ] = "B"
508741 defaults ["user_id" ] = "UNKNOWN"
509742 defaults ["period_id" ] = "201605"
510743 defaults ["period_str" ] = "May 2017"
0 commit comments