mirror of
				https://github.com/simon987/sist2.git
				synced 2025-10-30 23:46:52 +00:00 
			
		
		
		
	Add support for auth0
This commit is contained in:
		
							parent
							
								
									b9f008603a
								
							
						
					
					
						commit
						86ca9f1ecb
					
				| @ -1,7 +1,7 @@ | |||||||
| cmake_minimum_required(VERSION 3.7) | cmake_minimum_required(VERSION 3.7) | ||||||
| set(CMAKE_C_STANDARD 11) |  | ||||||
| 
 | 
 | ||||||
| project(sist2 C) | project(sist2) | ||||||
|  | set(CMAKE_C_STANDARD 11) | ||||||
| 
 | 
 | ||||||
| option(SIST_DEBUG "Build a debug executable" on) | option(SIST_DEBUG "Build a debug executable" on) | ||||||
| option(SIST_FAST "Enable more optimisation flags" off) | option(SIST_FAST "Enable more optimisation flags" off) | ||||||
| @ -40,9 +40,12 @@ add_executable(sist2 | |||||||
|         src/stats.c src/stats.h src/ctx.c |         src/stats.c src/stats.h src/ctx.c | ||||||
|         src/parsing/sidecar.c src/parsing/sidecar.h |         src/parsing/sidecar.c src/parsing/sidecar.h | ||||||
| 
 | 
 | ||||||
|  |         src/auth0/auth0_c_api.h src/auth0/auth0_c_api.cpp | ||||||
|  | 
 | ||||||
|         # argparse |         # argparse | ||||||
|         third-party/argparse/argparse.h third-party/argparse/argparse.c |         third-party/argparse/argparse.h third-party/argparse/argparse.c | ||||||
|         ) |         ) | ||||||
|  | set_target_properties(sist2 PROPERTIES LINKER_LANGUAGE C) | ||||||
| 
 | 
 | ||||||
| target_link_directories(sist2 PRIVATE BEFORE ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/) | target_link_directories(sist2 PRIVATE BEFORE ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/) | ||||||
| set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib) | set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib) | ||||||
|  | |||||||
| @ -74,6 +74,10 @@ Web options | |||||||
|     --es-index=<str>                  Elasticsearch index name. DEFAULT=sist2 |     --es-index=<str>                  Elasticsearch index name. DEFAULT=sist2 | ||||||
|     --bind=<str>                      Listen on this address. DEFAULT=localhost:4090 |     --bind=<str>                      Listen on this address. DEFAULT=localhost:4090 | ||||||
|     --auth=<str>                      Basic auth in user:password format |     --auth=<str>                      Basic auth in user:password format | ||||||
|  |     --auth0-audience=<str>            API audience/identifier | ||||||
|  |     --auth0-domain=<str>              Application domain | ||||||
|  |     --auth0-client-id=<str>           Application client ID | ||||||
|  |     --auth0-public-key-file=<str>     Path to Auth0 public key file extracted from <domain>/pem | ||||||
|     --tag-auth=<str>                  Basic auth in user:password format for tagging |     --tag-auth=<str>                  Basic auth in user:password format for tagging | ||||||
|     --tagline=<str>                   Tagline in navbar |     --tagline=<str>                   Tagline in navbar | ||||||
|     --dev                             Serve html & js files from disk (for development) |     --dev                             Serve html & js files from disk (for development) | ||||||
| @ -268,6 +272,7 @@ sist2 index --print ./my_index/ | jq | less | |||||||
|  * `--dev` Serve html & js files from disk (for development, used to modify frontend files without having to recompile) |  * `--dev` Serve html & js files from disk (for development, used to modify frontend files without having to recompile) | ||||||
|  * `--lang=<str>` Set the default web UI language (See #180 for a list of supported languages, default |  * `--lang=<str>` Set the default web UI language (See #180 for a list of supported languages, default | ||||||
|    is `en`). The user can change the language in the configuration page |    is `en`). The user can change the language in the configuration page | ||||||
|  |  * `--auth0-audience`, `--auth0-domain`, `--auth0-client-id`, `--auth0-public-key-file` See [Authentication with Auth0](auth0.md) | ||||||
| 
 | 
 | ||||||
| ### Web examples | ### Web examples | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								docs/auth0.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docs/auth0.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | 
 | ||||||
|  | # Authentication with Auth0 | ||||||
|  | 
 | ||||||
|  | 1. Create a new Auth0 application (Single page app) | ||||||
|  | 2. Create a new Auth0 API: | ||||||
|  |    1. Choose `RS256` signing algorithm | ||||||
|  |    2. Set identifier (audience) to `https://sist2` | ||||||
|  | 3. Download the Auth0 certificate from https://<domain>.auth0.com/pem (you can find the domain Applications->Basic information) | ||||||
|  | 4. Extract the public key from the certificate using `openssl x509 -pubkey -noout -in cert.pem > pubkey.txt` | ||||||
|  | 5. Start the sist2 web server | ||||||
|  | 
 | ||||||
|  | Example options: | ||||||
|  | ```bash | ||||||
|  | sist2 web \ | ||||||
|  |   --auth0-client-id XXX \ | ||||||
|  |   --auth0-audience https://sist2 \ | ||||||
|  |   --auth0-domain YYY.auth0.com \ | ||||||
|  |   --auth0-public-key-file /ZZZ/pubkey.txt | ||||||
|  | ``` | ||||||
							
								
								
									
										2
									
								
								sist2-admin/frontend/dist/index.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								sist2-admin/frontend/dist/index.html
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | |||||||
| <!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>sist2-admin</title><link href="css/app.0f0b676b.css" rel="preload" as="style"><link href="css/chunk-vendors.aa66c7e8.css" rel="preload" as="style"><link href="js/app.b34f501e.js" rel="preload" as="script"><link href="js/chunk-vendors.fad0ee6a.js" rel="preload" as="script"><link href="css/chunk-vendors.aa66c7e8.css" rel="stylesheet"><link href="css/app.0f0b676b.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but sist2-admin-vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.fad0ee6a.js"></script><script src="js/app.b34f501e.js"></script></body></html> | <!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>sist2-admin</title><link href="css/app.css" rel="preload" as="style"><link href="css/chunk-vendors.css" rel="preload" as="style"><link href="js/app.js" rel="preload" as="script"><link href="js/chunk-vendors.js" rel="preload" as="script"><link href="css/chunk-vendors.css" rel="stylesheet"><link href="css/app.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but sist2-admin-vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.js"></script><script src="js/app.js"></script></body></html> | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -341,5 +341,4 @@ var e="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),a= | |||||||
| //! moment.js locale configuration
 | //! moment.js locale configuration
 | ||||||
| var e=t.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",ss:"%d s~écóñ~ds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,a=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+a},week:{dow:1,doy:4}});return e}))},fdbf:function(t,e,a){var n=a("4930");t.exports=n&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},ffff:function(t,e,a){(function(t,e){e(a("c1df"))})(0,(function(t){"use strict"; | var e=t.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",ss:"%d s~écóñ~ds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,a=1===~~(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+a},week:{dow:1,doy:4}});return e}))},fdbf:function(t,e,a){var n=a("4930");t.exports=n&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},ffff:function(t,e,a){(function(t,e){e(a("c1df"))})(0,(function(t){"use strict"; | ||||||
| //! moment.js locale configuration
 | //! moment.js locale configuration
 | ||||||
| var e=t.defineLocale("se",{months:"ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu".split("_"),monthsShort:"ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov".split("_"),weekdays:"sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat".split("_"),weekdaysShort:"sotn_vuos_maŋ_gask_duor_bear_láv".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s geažes",past:"maŋit %s",s:"moadde sekunddat",ss:"%d sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta mánnu",MM:"%d mánut",y:"okta jahki",yy:"%d jagit"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return e}))}}]); | var e=t.defineLocale("se",{months:"ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu".split("_"),monthsShort:"ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov".split("_"),weekdays:"sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat".split("_"),weekdaysShort:"sotn_vuos_maŋ_gask_duor_bear_láv".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s geažes",past:"maŋit %s",s:"moadde sekunddat",ss:"%d sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta mánnu",MM:"%d mánut",y:"okta jahki",yy:"%d jagit"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}});return e}))}}]); | ||||||
| //# sourceMappingURL=chunk-vendors.fad0ee6a.js.map
 |  | ||||||
| @ -34,6 +34,22 @@ | |||||||
|     <label>{{ $t("webOptions.tagAuth") }}</label> |     <label>{{ $t("webOptions.tagAuth") }}</label> | ||||||
|     <b-form-input v-model="options.tag_auth" @change="update()"></b-form-input> |     <b-form-input v-model="options.tag_auth" @change="update()"></b-form-input> | ||||||
| 
 | 
 | ||||||
|  |     <br> | ||||||
|  |     <h5>Auth0 options</h5> | ||||||
|  |     <label>{{ $t("webOptions.auth0Audience") }}</label> | ||||||
|  |     <b-form-input v-model="options.auth0_audience" @change="update()"></b-form-input> | ||||||
|  | 
 | ||||||
|  |     <label>{{ $t("webOptions.auth0Domain") }}</label> | ||||||
|  |     <b-form-input v-model="options.auth0_domain" @change="update()"></b-form-input> | ||||||
|  | 
 | ||||||
|  |     <label>{{ $t("webOptions.auth0ClientId") }}</label> | ||||||
|  |     <b-form-input v-model="options.auth0_client_id" @change="update()"></b-form-input> | ||||||
|  | 
 | ||||||
|  |     <label>{{ $t("webOptions.auth0PublicKey") }}</label> | ||||||
|  |     <b-textarea rows="10" v-model="options.auth0_public_key" @change="update()"></b-textarea> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -47,6 +47,7 @@ export default { | |||||||
| 
 | 
 | ||||||
|         selectJobs: "Select jobs", |         selectJobs: "Select jobs", | ||||||
|         webOptions: { |         webOptions: { | ||||||
|  |             title: "Web options", | ||||||
|             esUrl: "Elasticsearch URL", |             esUrl: "Elasticsearch URL", | ||||||
|             esIndex: "Elasticsearch index name", |             esIndex: "Elasticsearch index name", | ||||||
|             esInsecure: "Do not verify SSL connections to Elasticsearch.", |             esInsecure: "Do not verify SSL connections to Elasticsearch.", | ||||||
|  | |||||||
| @ -48,7 +48,7 @@ | |||||||
| 
 | 
 | ||||||
|       <br/> |       <br/> | ||||||
| 
 | 
 | ||||||
|       <h4>{{ $t("jobOptions.title") }}</h4> |       <h4>{{ $t("webOptions.title") }}</h4> | ||||||
|       <b-card> |       <b-card> | ||||||
|         <WebOptions :options="frontend.web_options" :frontend-name="$route.params.name" @change="update()"></WebOptions> |         <WebOptions :options="frontend.web_options" :frontend-name="$route.params.name" @change="update()"></WebOptions> | ||||||
|       </b-card> |       </b-card> | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
| module.exports = { | module.exports = { | ||||||
|     publicPath: "" |     publicPath: "", | ||||||
|  |     filenameHashing: false, | ||||||
|  |     productionSourceMap: false, | ||||||
| }; | }; | ||||||
| @ -37,6 +37,11 @@ class WebOptions(BaseModel): | |||||||
|     tagline: str = "Lightning-fast file system indexer and search tool" |     tagline: str = "Lightning-fast file system indexer and search tool" | ||||||
|     dev: bool = False |     dev: bool = False | ||||||
|     lang: str = "en" |     lang: str = "en" | ||||||
|  |     auth0_audience: str = None | ||||||
|  |     auth0_domain: str = None | ||||||
|  |     auth0_client_id: str = None | ||||||
|  |     auth0_public_key: str = None | ||||||
|  |     auth0_public_key_file: str = None | ||||||
| 
 | 
 | ||||||
|     def __init__(self, **kwargs): |     def __init__(self, **kwargs): | ||||||
|         super().__init__(**kwargs) |         super().__init__(**kwargs) | ||||||
| @ -45,6 +50,14 @@ class WebOptions(BaseModel): | |||||||
|         args = ["web", f"--es-url={self.es_url}", f"--bind={self.bind}", |         args = ["web", f"--es-url={self.es_url}", f"--bind={self.bind}", | ||||||
|                 f"--tagline={self.tagline}", f"--lang={self.lang}"] |                 f"--tagline={self.tagline}", f"--lang={self.lang}"] | ||||||
| 
 | 
 | ||||||
|  |         if self.auth0_audience: | ||||||
|  |             args.append(f"--auth0-audience={self.auth0_audience}") | ||||||
|  |         if self.auth0_domain: | ||||||
|  |             args.append(f"--auth0-domain={self.auth0_domain}") | ||||||
|  |         if self.auth0_client_id: | ||||||
|  |             args.append(f"--auth0-client-id={self.auth0_client_id}") | ||||||
|  |         if self.auth0_public_key_file: | ||||||
|  |             args.append(f"--auth0-public-key-file={self.auth0_public_key_file}") | ||||||
|         if self.es_insecure_ssl: |         if self.es_insecure_ssl: | ||||||
|             args.append(f"--es-insecure-ssl") |             args.append(f"--es-insecure-ssl") | ||||||
|         if self.auth: |         if self.auth: | ||||||
| @ -283,6 +296,14 @@ class Sist2: | |||||||
|             # pipe_wrapper.close() |             # pipe_wrapper.close() | ||||||
| 
 | 
 | ||||||
|     def web(self, options: WebOptions, name: str): |     def web(self, options: WebOptions, name: str): | ||||||
|  | 
 | ||||||
|  |         if options.auth0_public_key: | ||||||
|  |             with NamedTemporaryFile("w", prefix="sist2-admin", suffix=".txt", delete=False) as f: | ||||||
|  |                 f.write(options.auth0_public_key) | ||||||
|  |             options.auth0_public_key_file = f.name | ||||||
|  |         else: | ||||||
|  |             options.auth0_public_key_file = None | ||||||
|  | 
 | ||||||
|         args = [ |         args = [ | ||||||
|             self._bin_path, |             self._bin_path, | ||||||
|             *options.args() |             *options.args() | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								sist2-vue/dist/css/chunk-vendors.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								sist2-vue/dist/css/chunk-vendors.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								sist2-vue/dist/css/index.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								sist2-vue/dist/css/index.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										33
									
								
								sist2-vue/dist/index.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								sist2-vue/dist/index.html
									
									
									
									
										vendored
									
									
								
							| @ -1,32 +1,3 @@ | |||||||
| <!DOCTYPE html> | <!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/><title>sist2</title><script defer="defer" src="js/chunk-vendors.js"></script><script defer="defer" src="js/index.js"></script><link href="css/chunk-vendors.css" rel="stylesheet"><link href="css/index.css" rel="stylesheet"></head><body><noscript><style>body { | ||||||
| <html lang="en"> |  | ||||||
| <head> |  | ||||||
|     <meta charset="utf-8"> |  | ||||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"> |  | ||||||
|     <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'/> |  | ||||||
| 
 |  | ||||||
|     <title>sist2</title> |  | ||||||
| <link href="js/chunk-vendors.js" rel="preload" as="script"><link href="js/index.js" rel="preload" as="script"></head> |  | ||||||
| <body> |  | ||||||
| <noscript> |  | ||||||
|     <style> |  | ||||||
|         body { |  | ||||||
|             height: initial; |             height: initial; | ||||||
|         } |         }</style><div style="text-align: center; margin-top: 100px"><strong>We're sorry but sist2 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong><br/><strong>Nous sommes désolés mais sist2 ne fonctionne pas correctement si JavaScript est activé. Veuillez l'activer pour continuer.</strong></div></noscript><div id="app"></div></body></html> | ||||||
|     </style> |  | ||||||
|     <div style="text-align: center; margin-top: 100px"> |  | ||||||
|         <strong> |  | ||||||
|             We're sorry but sist2 doesn't work properly without JavaScript enabled. |  | ||||||
|             Please enable it to continue. |  | ||||||
|         </strong> |  | ||||||
|         <br/> |  | ||||||
|         <strong> |  | ||||||
|             Nous sommes désolés mais sist2 ne fonctionne pas correctement |  | ||||||
|             si JavaScript est activé. |  | ||||||
|             Veuillez l'activer pour continuer. |  | ||||||
|         </strong> |  | ||||||
|     </div> |  | ||||||
| </noscript> |  | ||||||
| <div id="app"></div> |  | ||||||
| <script type="text/javascript" src="js/chunk-vendors.js"></script><script type="text/javascript" src="js/index.js"></script></body> |  | ||||||
| </html> |  | ||||||
							
								
								
									
										19501
									
								
								sist2-vue/dist/js/chunk-vendors.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19501
									
								
								sist2-vue/dist/js/chunk-vendors.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										4102
									
								
								sist2-vue/dist/js/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4102
									
								
								sist2-vue/dist/js/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										23299
									
								
								sist2-vue/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										23299
									
								
								sist2-vue/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -7,14 +7,15 @@ | |||||||
|     "build": "vue-cli-service build --mode production" |     "build": "vue-cli-service build --mode production" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|  |     "@auth0/auth0-spa-js": "^2.0.2", | ||||||
|     "@egjs/vue-infinitegrid": "3.3.0", |     "@egjs/vue-infinitegrid": "3.3.0", | ||||||
|     "axios": "^0.25.0", |     "axios": "^0.25.0", | ||||||
|     "bootstrap-vue": "^2.21.2", |     "bootstrap-vue": "^2.21.2", | ||||||
|     "core-js": "^3.6.5", |     "core-js": "^3.6.5", | ||||||
|     "d3": "^7.6.1", |     "d3": "^5.6.1", | ||||||
|     "date-fns": "^2.21.3", |     "date-fns": "^2.21.3", | ||||||
|     "dom-to-image": "^2.6.0", |     "dom-to-image": "^2.6.0", | ||||||
|     "fslightbox-vue": "file:../../../mnt/Hatchery/main/projects/sist2/fslightbox-vue-pro-1.3.1.tgz", |     "fslightbox-vue": "file:../../../../mnt/Hatchery/projects/sist2/fslightbox-vue-pro-1.3.1.tgz", | ||||||
|     "nouislider": "^15.2.0", |     "nouislider": "^15.2.0", | ||||||
|     "underscore": "^1.13.1", |     "underscore": "^1.13.1", | ||||||
|     "vue": "^2.6.12", |     "vue": "^2.6.12", | ||||||
| @ -26,12 +27,12 @@ | |||||||
|     "vuex": "^3.4.0" |     "vuex": "^3.4.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@babel/polyfill": "^7.11.5", |     "@babel/polyfill": "^7.12.1", | ||||||
|     "@vue/cli-plugin-babel": "~4.5.0", |     "@vue/cli-plugin-babel": "~5.0.8", | ||||||
|     "@vue/cli-plugin-router": "~4.5.0", |     "@vue/cli-plugin-router": "~5.0.8", | ||||||
|     "@vue/cli-plugin-typescript": "~4.5.0", |     "@vue/cli-plugin-typescript": "^5.0.8", | ||||||
|     "@vue/cli-plugin-vuex": "~4.5.0", |     "@vue/cli-plugin-vuex": "~5.0.8", | ||||||
|     "@vue/cli-service": "~4.5.0", |     "@vue/cli-service": "^5.0.8", | ||||||
|     "@vue/test-utils": "^1.0.3", |     "@vue/test-utils": "^1.0.3", | ||||||
|     "bootstrap": "^4.5.2", |     "bootstrap": "^4.5.2", | ||||||
|     "inspire-tree": "^4.3.1", |     "inspire-tree": "^4.3.1", | ||||||
|  | |||||||
| @ -1,19 +1,33 @@ | |||||||
| <template> | <template> | ||||||
|   <div id="app" :class="getClass()"> |   <div id="app" :class="getClass()" v-if="!authLoading"> | ||||||
|     <NavBar></NavBar> |     <NavBar></NavBar> | ||||||
|     <router-view v-if="!configLoading"/> |     <router-view v-if="!configLoading"/> | ||||||
|   </div> |   </div> | ||||||
|  |   <div class="loading-page" v-else> | ||||||
|  |     <div class="loading-spinners"> | ||||||
|  |       <b-spinner type="grow" variant="primary"></b-spinner> | ||||||
|  |       <b-spinner type="grow" variant="primary"></b-spinner> | ||||||
|  |       <b-spinner type="grow" variant="primary"></b-spinner> | ||||||
|  |     </div> | ||||||
|  |     <div class="loading-text"> | ||||||
|  |       Loading • Chargement • 装载 | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script> | ||||||
| import NavBar from "@/components/NavBar"; | import NavBar from "@/components/NavBar"; | ||||||
| import {mapGetters} from "vuex"; | import {mapActions, mapGetters, mapMutations} from "vuex"; | ||||||
|  | import Sist2Api from "@/Sist2Api"; | ||||||
|  | import {setupAuth0} from "@/main"; | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|   components: {NavBar}, |   components: {NavBar}, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       configLoading: false |       configLoading: false, | ||||||
|  |       authLoading: true, | ||||||
|  |       sist2InfoLoading: true | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   computed: { |   computed: { | ||||||
| @ -30,9 +44,43 @@ export default { | |||||||
|         this.configLoading = true; |         this.configLoading = true; | ||||||
|         window.setTimeout(() => this.configLoading = false, 10); |         window.setTimeout(() => this.configLoading = false, 10); | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       if (mutation.type === "setAuth0Token") { | ||||||
|  |         this.authLoading = false; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     Sist2Api.getSist2Info().then(data => { | ||||||
|  | 
 | ||||||
|  |       if (data.auth0Enabled) { | ||||||
|  |         this.authLoading = true; | ||||||
|  |         setupAuth0(data.auth0Domain, data.auth0ClientId, data.auth0Audience) | ||||||
|  | 
 | ||||||
|  |         this.$auth.$watch("loading", loading => { | ||||||
|  |           if (loading === false) { | ||||||
|  | 
 | ||||||
|  |             if (!this.$auth.isAuthenticated) { | ||||||
|  |               this.$auth.loginWithRedirect(); | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Remove "code" param | ||||||
|  |             window.history.replaceState({}, "", "/" + window.location.hash); | ||||||
|  | 
 | ||||||
|  |             this.$store.dispatch("loadAuth0Token"); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |       } else { | ||||||
|  |         this.authLoading = false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       this.setSist2Info(data); | ||||||
|  |       this.setIndices(data.indices) | ||||||
|     }); |     }); | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  |     ...mapActions(["setSist2Info",]), | ||||||
|  |     ...mapMutations(["setIndices",]), | ||||||
|     getClass() { |     getClass() { | ||||||
|       return { |       return { | ||||||
|         "theme-light": this.optTheme === "light", |         "theme-light": this.optTheme === "light", | ||||||
| @ -314,4 +362,22 @@ mark { | |||||||
| .pointer { | .pointer { | ||||||
|   cursor: pointer; |   cursor: pointer; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .loading-page { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   flex-direction: column; | ||||||
|  |   height: 100%; | ||||||
|  |   gap: 15px | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .loading-spinners { | ||||||
|  |   display: flex; | ||||||
|  |   gap: 10px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .loading-text { | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
| </style> | </style> | ||||||
|  | |||||||
| @ -9,13 +9,15 @@ | |||||||
| 
 | 
 | ||||||
|     <span class="badge badge-pill version" v-if="$store && $store.state.sist2Info"> |     <span class="badge badge-pill version" v-if="$store && $store.state.sist2Info"> | ||||||
|       v{{ sist2Version() }}<span v-if="isDebug()">-dbg</span><span v-if="isLegacy() && !hideLegacy()">-<a |       v{{ sist2Version() }}<span v-if="isDebug()">-dbg</span><span v-if="isLegacy() && !hideLegacy()">-<a | ||||||
|         href="https://github.com/simon987/sist2/blob/master/docs/USAGE.md#elasticsearch" target="_blank">legacyES</a></span> |         href="https://github.com/simon987/sist2/blob/master/docs/USAGE.md#elasticsearch" | ||||||
|  |         target="_blank">legacyES</a></span> | ||||||
|     </span> |     </span> | ||||||
| 
 | 
 | ||||||
|     <span v-if="$store && $store.state.sist2Info" class="tagline" v-html="tagline()"></span> |     <span v-if="$store && $store.state.sist2Info" class="tagline" v-html="tagline()"></span> | ||||||
| 
 | 
 | ||||||
|     <b-button class="ml-auto" to="stats" variant="link">{{ $t("stats") }}</b-button> |     <b-button class="ml-auto" to="stats" variant="link">{{ $t("stats") }}</b-button> | ||||||
|     <b-button to="config" variant="link">{{ $t("config") }}</b-button> |     <b-button to="config" variant="link">{{ $t("config") }}</b-button> | ||||||
|  |     <b-button v-if="$auth && $auth.isAuthenticated" variant="link" @click="onLogoutClick()">logout</b-button> | ||||||
|   </b-navbar> |   </b-navbar> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| @ -40,6 +42,9 @@ export default { | |||||||
|     }, |     }, | ||||||
|     hideLegacy() { |     hideLegacy() { | ||||||
|       return this.$store.state.optHideLegacy; |       return this.$store.state.optHideLegacy; | ||||||
|  |     }, | ||||||
|  |     onLogoutClick() { | ||||||
|  |       this.$auth.logout(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -335,8 +335,8 @@ export default { | |||||||
|         indexPicker: { |         indexPicker: { | ||||||
|             selectNone: "Sélectionner aucun", |             selectNone: "Sélectionner aucun", | ||||||
|             selectAll: "Sélectionner tout", |             selectAll: "Sélectionner tout", | ||||||
|             selectedIndex: "indice sélectionné", |             selectedIndex: "index sélectionné", | ||||||
|             selectedIndices: "indices sélectionnés", |             selectedIndices: "index sélectionnés", | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
|     "zh-CN": { |     "zh-CN": { | ||||||
|  | |||||||
| @ -3,16 +3,32 @@ import 'mutationobserver-shim' | |||||||
| import Vue from 'vue' | import Vue from 'vue' | ||||||
| import './plugins/bootstrap-vue' | import './plugins/bootstrap-vue' | ||||||
| import App from './App.vue' | import App from './App.vue' | ||||||
| import router from './router' | import router, {setUseAuth0} from './router' | ||||||
| import store from './store' | import store from './store' | ||||||
| import VueI18n from "vue-i18n"; | import VueI18n from "vue-i18n"; | ||||||
| import messages from "@/i18n/messages"; | import messages from "@/i18n/messages"; | ||||||
| 
 | import { Auth0Plugin } from './plugins/auth0'; | ||||||
| 
 | 
 | ||||||
| import VueRouter from "vue-router"; | import VueRouter from "vue-router"; | ||||||
| 
 | 
 | ||||||
| Vue.config.productionTip = false; | Vue.config.productionTip = false; | ||||||
| 
 | 
 | ||||||
|  | export function setupAuth0(domain, clientId, audience) { | ||||||
|  | 
 | ||||||
|  |     setUseAuth0(true); | ||||||
|  | 
 | ||||||
|  |     Vue.use(Auth0Plugin, { | ||||||
|  |         domain, | ||||||
|  |         clientId, | ||||||
|  |         audience, | ||||||
|  |         onRedirectCallback: appState => {} | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Vue.prototype.$auth = null; | ||||||
|  | 
 | ||||||
|  | Vue.config.productionTip = false; | ||||||
|  | 
 | ||||||
| Vue.use(VueI18n); | Vue.use(VueI18n); | ||||||
| Vue.use(VueRouter); | Vue.use(VueRouter); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										138
									
								
								sist2-vue/src/plugins/auth0.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								sist2-vue/src/plugins/auth0.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,138 @@ | |||||||
|  | import Vue from 'vue'; | ||||||
|  | import {createAuth0Client} from '@auth0/auth0-spa-js'; | ||||||
|  | 
 | ||||||
|  | /** Define a default action to perform after authentication */ | ||||||
|  | const DEFAULT_REDIRECT_CALLBACK = () => | ||||||
|  |     window.history.replaceState({}, document.title, window.location.pathname); | ||||||
|  | 
 | ||||||
|  | let instance; | ||||||
|  | 
 | ||||||
|  | /** Returns the current instance of the SDK */ | ||||||
|  | export const getInstance = () => instance; | ||||||
|  | 
 | ||||||
|  | /** Creates an instance of the Auth0 SDK. If one has already been created, it returns that instance */ | ||||||
|  | export const useAuth0 = ({ | ||||||
|  |                              domain, clientId, audience, | ||||||
|  |                              onRedirectCallback = DEFAULT_REDIRECT_CALLBACK, | ||||||
|  |                              redirectUri = window.location.origin, | ||||||
|  |                          }) => { | ||||||
|  |     if (instance) return instance; | ||||||
|  | 
 | ||||||
|  |     // The 'instance' is simply a Vue object
 | ||||||
|  |     instance = new Vue({ | ||||||
|  |         data() { | ||||||
|  |             return { | ||||||
|  |                 loading: true, | ||||||
|  |                 isAuthenticated: false, | ||||||
|  |                 user: {}, | ||||||
|  |                 auth0Client: null, | ||||||
|  |                 popupOpen: false, | ||||||
|  |                 error: null | ||||||
|  |             }; | ||||||
|  |         }, | ||||||
|  |         methods: { | ||||||
|  |             /** Authenticates the user using a popup window */ | ||||||
|  |             async loginWithPopup(options, config) { | ||||||
|  |                 this.popupOpen = true; | ||||||
|  | 
 | ||||||
|  |                 try { | ||||||
|  |                     await this.auth0Client.loginWithPopup(options, config); | ||||||
|  |                     this.user = await this.auth0Client.getUser(); | ||||||
|  |                     this.isAuthenticated = await this.auth0Client.isAuthenticated(); | ||||||
|  |                     this.error = null; | ||||||
|  |                 } catch (e) { | ||||||
|  |                     this.error = e; | ||||||
|  |                     // eslint-disable-next-line
 | ||||||
|  |                     console.error(e); | ||||||
|  |                 } finally { | ||||||
|  |                     this.popupOpen = false; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 this.user = await this.auth0Client.getUser(); | ||||||
|  |                 this.isAuthenticated = true; | ||||||
|  |             }, | ||||||
|  |             /** Handles the callback when logging in using a redirect */ | ||||||
|  |             async handleRedirectCallback() { | ||||||
|  |                 this.loading = true; | ||||||
|  |                 try { | ||||||
|  |                     await this.auth0Client.handleRedirectCallback(); | ||||||
|  |                     this.user = await this.auth0Client.getUser(); | ||||||
|  |                     this.isAuthenticated = true; | ||||||
|  |                     this.error = null; | ||||||
|  |                 } catch (e) { | ||||||
|  |                     this.error = e; | ||||||
|  |                 } finally { | ||||||
|  |                     this.loading = false; | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             /** Authenticates the user using the redirect method */ | ||||||
|  |             loginWithRedirect(o) { | ||||||
|  |                 return this.auth0Client.loginWithRedirect(o); | ||||||
|  |             }, | ||||||
|  |             /** Returns all the claims present in the ID token */ | ||||||
|  |             getIdTokenClaims(o) { | ||||||
|  |                 return this.auth0Client.getIdTokenClaims(o); | ||||||
|  |             }, | ||||||
|  |             /** Returns the access token. If the token is invalid or missing, a new one is retrieved */ | ||||||
|  |             getTokenSilently(o) { | ||||||
|  |                 return this.auth0Client.getTokenSilently(o); | ||||||
|  |             }, | ||||||
|  | 
 | ||||||
|  |             /** Gets the access token using a popup window */ | ||||||
|  | 
 | ||||||
|  |             getTokenWithPopup(o) { | ||||||
|  |                 return this.auth0Client.getTokenWithPopup(o); | ||||||
|  |             }, | ||||||
|  |             /** Logs the user out and removes their session on the authorization server */ | ||||||
|  |             logout() { | ||||||
|  |                 return this.auth0Client.logout({ logoutParams: { returnTo: window.location.origin } }); | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         /** Use this lifecycle method to instantiate the SDK client */ | ||||||
|  |         async created() { | ||||||
|  |             // Create a new instance of the SDK client using members of the given options object
 | ||||||
|  |             this.auth0Client = await createAuth0Client({ | ||||||
|  |                 domain: domain, | ||||||
|  |                 clientId: clientId, | ||||||
|  | 
 | ||||||
|  |                 authorizationParams: { | ||||||
|  |                     redirect_uri: redirectUri, | ||||||
|  |                     audience: audience, | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             try { | ||||||
|  |                 // If the user is returning to the app after authentication..
 | ||||||
|  |                 if ( | ||||||
|  |                     window.location.search.includes('code=') && | ||||||
|  |                     window.location.search.includes('state=') | ||||||
|  |                 ) { | ||||||
|  |                     // handle the redirect and retrieve tokens
 | ||||||
|  |                     const {appState} = await this.auth0Client.handleRedirectCallback(); | ||||||
|  | 
 | ||||||
|  |                     this.error = null; | ||||||
|  | 
 | ||||||
|  |                     // Notify subscribers that the redirect callback has happened, passing the appState
 | ||||||
|  |                     // (useful for retrieving any pre-authentication state)
 | ||||||
|  |                     onRedirectCallback(appState); | ||||||
|  |                 } | ||||||
|  |             } catch (e) { | ||||||
|  |                 this.error = e; | ||||||
|  |             } finally { | ||||||
|  |                 // Initialize our internal authentication state
 | ||||||
|  |                 this.isAuthenticated = await this.auth0Client.isAuthenticated(); | ||||||
|  |                 this.user = await this.auth0Client.getUser(); | ||||||
|  |                 this.loading = false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return instance; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // Create a simple Vue plugin to expose the wrapper object throughout the application
 | ||||||
|  | export const Auth0Plugin = { | ||||||
|  |     install(Vue, options) { | ||||||
|  |         Vue.prototype.$auth = useAuth0(options); | ||||||
|  |     } | ||||||
|  | }; | ||||||
							
								
								
									
										28
									
								
								sist2-vue/src/router/auth0.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								sist2-vue/src/router/auth0.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | import {getInstance} from "@/plugins/auth0"; | ||||||
|  | 
 | ||||||
|  | export const authGuard = (to, from, next) => { | ||||||
|  | 
 | ||||||
|  |     const authService = getInstance(); | ||||||
|  | 
 | ||||||
|  |     const fn = () => { | ||||||
|  |         // If the user is authenticated, continue with the route
 | ||||||
|  |         if (authService.isAuthenticated) { | ||||||
|  |             return next(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Otherwise, log in
 | ||||||
|  |         authService.loginWithRedirect({appState: {targetUrl: to.fullPath}}); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // If loading has already finished, check our auth state using `fn()`
 | ||||||
|  |     if (!authService.loading) { | ||||||
|  |         return fn(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Watch for the loading property to change before we check isAuthenticated
 | ||||||
|  |     authService.$watch("loading", loading => { | ||||||
|  |         if (loading === false) { | ||||||
|  |             return fn(); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | }; | ||||||
| @ -4,14 +4,29 @@ import StatsPage from "../views/StatsPage.vue" | |||||||
| import Configuration from "../views/Configuration.vue" | import Configuration from "../views/Configuration.vue" | ||||||
| import SearchPage from "@/views/SearchPage.vue"; | import SearchPage from "@/views/SearchPage.vue"; | ||||||
| import FilePage from "@/views/FilePage.vue"; | import FilePage from "@/views/FilePage.vue"; | ||||||
|  | import {authGuard as auth0AuthGuard} from "@/router/auth0"; | ||||||
| 
 | 
 | ||||||
| Vue.use(VueRouter) | Vue.use(VueRouter) | ||||||
| 
 | 
 | ||||||
|  | let USE_AUTH0 = false | ||||||
|  | export function setUseAuth0(val) { | ||||||
|  |     USE_AUTH0 = val; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const authGuard = (to, from, next) => { | ||||||
|  |     if (USE_AUTH0) { | ||||||
|  |         return auth0AuthGuard(to, from, next); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     next(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const routes: Array<RouteConfig> = [ | const routes: Array<RouteConfig> = [ | ||||||
|     { |     { | ||||||
|         path: "/", |         path: "/", | ||||||
|         name: "SearchPage", |         name: "SearchPage", | ||||||
|         component: SearchPage |         component: SearchPage, | ||||||
|  |         beforeEnter: authGuard | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         path: "/stats", |         path: "/stats", | ||||||
| @ -34,7 +49,7 @@ const router = new VueRouter({ | |||||||
|     mode: "hash", |     mode: "hash", | ||||||
|     base: process.env.BASE_URL, |     base: process.env.BASE_URL, | ||||||
|     routes, |     routes, | ||||||
|     scrollBehavior (to, from, savedPosition) { |     scrollBehavior(to, from, savedPosition) { | ||||||
|         // return desired position
 |         // return desired position
 | ||||||
|     } |     } | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ import Vuex from "vuex" | |||||||
| import VueRouter, {Route} from "vue-router"; | import VueRouter, {Route} from "vue-router"; | ||||||
| import {EsHit, EsResult, EsTag, Index, Tag} from "@/Sist2Api"; | import {EsHit, EsResult, EsTag, Index, Tag} from "@/Sist2Api"; | ||||||
| import {deserializeMimes, randomSeed, serializeMimes} from "@/util"; | import {deserializeMimes, randomSeed, serializeMimes} from "@/util"; | ||||||
|  | import {getInstance} from "@/plugins/auth0.js"; | ||||||
| 
 | 
 | ||||||
| const CONF_VERSION = 2; | const CONF_VERSION = 2; | ||||||
| 
 | 
 | ||||||
| @ -82,7 +83,9 @@ export default new Vuex.Store({ | |||||||
|         uiDetailsMimeAgg: null, |         uiDetailsMimeAgg: null, | ||||||
|         uiShowDetails: false, |         uiShowDetails: false, | ||||||
| 
 | 
 | ||||||
|         uiMimeMap: [] as any[] |         uiMimeMap: [] as any[], | ||||||
|  | 
 | ||||||
|  |         auth0Token: null | ||||||
|     }, |     }, | ||||||
|     mutations: { |     mutations: { | ||||||
|         setUiShowDetails: (state, val) => state.uiShowDetails = val, |         setUiShowDetails: (state, val) => state.uiShowDetails = val, | ||||||
| @ -188,6 +191,7 @@ export default new Vuex.Store({ | |||||||
|         busTnTouchStart: (doc_id) => { |         busTnTouchStart: (doc_id) => { | ||||||
|             // noop
 |             // noop
 | ||||||
|         }, |         }, | ||||||
|  |         setAuth0Token: (state, val) => state.auth0Token = val, | ||||||
|     }, |     }, | ||||||
|     actions: { |     actions: { | ||||||
|         setSist2Info: (store, val) => { |         setSist2Info: (store, val) => { | ||||||
| @ -332,6 +336,14 @@ export default new Vuex.Store({ | |||||||
|             commit("setUiLightboxCaptions", []); |             commit("setUiLightboxCaptions", []); | ||||||
|             commit("setUiLightboxKey", 0); |             commit("setUiLightboxKey", 0); | ||||||
|             commit("setUiDetailsMimeAgg", null); |             commit("setUiDetailsMimeAgg", null); | ||||||
|  |         }, | ||||||
|  |         async loadAuth0Token({commit}) { | ||||||
|  |             const authService = getInstance(); | ||||||
|  | 
 | ||||||
|  |             const accessToken = await authService.getTokenSilently() | ||||||
|  |             commit("setAuth0Token", accessToken); | ||||||
|  | 
 | ||||||
|  |             document.cookie = `sist2-auth0=${accessToken};`; | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     modules: {}, |     modules: {}, | ||||||
|  | |||||||
| @ -153,7 +153,7 @@ export default { | |||||||
|   components: {LanguageIcon, GearIcon, DebugInfo, Preloader}, |   components: {LanguageIcon, GearIcon, DebugInfo, Preloader}, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       loading: true, |       loading: false, | ||||||
|       configLoading: false, |       configLoading: false, | ||||||
|       langOptions: [ |       langOptions: [ | ||||||
|         {value: "en", text: this.$t("lang.en")}, |         {value: "en", text: this.$t("lang.en")}, | ||||||
| @ -257,11 +257,6 @@ export default { | |||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   mounted() { |   mounted() { | ||||||
|     sist2.getSist2Info().then(data => { |  | ||||||
|       this.setSist2Info(data); |  | ||||||
|       this.loading = false; |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     this.$store.subscribe((mutation) => { |     this.$store.subscribe((mutation) => { | ||||||
|       if (mutation.type.startsWith("setOpt")) { |       if (mutation.type.startsWith("setOpt")) { | ||||||
|         this.$store.dispatch("updateConfiguration"); |         this.$store.dispatch("updateConfiguration"); | ||||||
|  | |||||||
| @ -107,13 +107,6 @@ export default Vue.extend({ | |||||||
| 
 | 
 | ||||||
|   }, |   }, | ||||||
|   mounted() { |   mounted() { | ||||||
|     if (this.$store.state.sist2Info === null) { |  | ||||||
|       sist2.getSist2Info().then(data => { |  | ||||||
|         this.$store.dispatch("setSist2Info", data); |  | ||||||
|         this.$store.commit("setIndices", data.indices); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let query = null; |     let query = null; | ||||||
|     if (this.$route.query.byId) { |     if (this.$route.query.byId) { | ||||||
|       query = this.findById(this.$route.query.byId); |       query = this.findById(this.$route.query.byId); | ||||||
|  | |||||||
| @ -130,25 +130,18 @@ export default Vue.extend({ | |||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     this.setIndices(this.$store.getters["sist2Info"].indices) | ||||||
| 
 | 
 | ||||||
|     this.getDateRange().then((range: { min: number, max: number }) => { |     this.getDateRange().then((range: { min: number, max: number }) => { | ||||||
|       this.setDateBoundsMin(range.min); |       this.setDateBoundsMin(range.min); | ||||||
|       this.setDateBoundsMax(range.max); |       this.setDateBoundsMax(range.max); | ||||||
| 
 | 
 | ||||||
|       sist2.getSist2Info().then(data => { |       const doBlankSearch = !this.$store.state.optUpdateMimeMap; | ||||||
|         this.setSist2Info(data); |  | ||||||
|         this.setIndices(data.indices); |  | ||||||
| 
 | 
 | ||||||
|         const doBlankSearch = !this.$store.state.optUpdateMimeMap; |       Sist2Api.getMimeTypes(Sist2Query.searchQuery(doBlankSearch)).then(({mimeMap}) => { | ||||||
| 
 |         this.$store.commit("setUiMimeMap", mimeMap); | ||||||
|         Sist2Api.getMimeTypes(Sist2Query.searchQuery(doBlankSearch)).then(({mimeMap}) => { |         this.uiLoading = false; | ||||||
|           this.$store.commit("setUiMimeMap", mimeMap); |         this.search(true); | ||||||
|           this.uiLoading = false; |  | ||||||
|           this.search(true); |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|       }).catch(() => { |  | ||||||
|         this.showErrorToast(); |  | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   }, |   }, | ||||||
|  | |||||||
							
								
								
									
										48
									
								
								src/auth0/auth0_c_api.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/auth0/auth0_c_api.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | #include "auth0_c_api.h" | ||||||
|  | #include "jwt/jwt.hpp" | ||||||
|  | #include "iostream" | ||||||
|  | #include "cjson/cJSON.h" | ||||||
|  | 
 | ||||||
|  | int auth0_verify_jwt(const char *secret_str, const char *token, const char *audience) { | ||||||
|  | 
 | ||||||
|  |     using namespace jwt::params; | ||||||
|  | 
 | ||||||
|  |     jwt::jwt_object object; | ||||||
|  |     try { | ||||||
|  |         object = jwt::decode( | ||||||
|  |                 token, | ||||||
|  |                 algorithms({"RS256"}), | ||||||
|  |                 secret(secret_str), | ||||||
|  |                 verify(true) | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |     } catch (const jwt::TokenExpiredError& e) { | ||||||
|  |         return AUTH0_ERR_EXPIRED; | ||||||
|  |     } catch (const jwt::SignatureFormatError& e) { | ||||||
|  |         return AUTH0_ERR_SIG_FORMAT; | ||||||
|  |     } catch (const jwt::DecodeError& e) { | ||||||
|  |         return AUTH0_ERR_DECODE; | ||||||
|  |     } catch (const jwt::VerificationError& e) { | ||||||
|  |         return AUTH0_ERR_VERIFICATION; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::stringstream buf; | ||||||
|  |     buf << object.payload(); | ||||||
|  |     std::string json_payload_str = buf.str(); | ||||||
|  |     cJSON *payload = cJSON_Parse(json_payload_str.c_str()); | ||||||
|  | 
 | ||||||
|  |     bool audience_ok = false; | ||||||
|  |     cJSON *aud; | ||||||
|  |     cJSON_ArrayForEach(aud, cJSON_GetObjectItem(payload, "aud")) { | ||||||
|  |         if (aud != nullptr && strcmp(aud->valuestring, audience) == 0) { | ||||||
|  |             audience_ok = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     cJSON_Delete(payload); | ||||||
|  | 
 | ||||||
|  |     if (!audience_ok) { | ||||||
|  |         return AUTH0_ERR_AUDIENCE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return AUTH0_OK; | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								src/auth0/auth0_c_api.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/auth0/auth0_c_api.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #ifndef SIST2_AUTH0_C_API_H | ||||||
|  | #define SIST2_AUTH0_C_API_H | ||||||
|  | 
 | ||||||
|  | #include "stdlib.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | #define EXTERNC extern "C" | ||||||
|  | #else | ||||||
|  | #define EXTERNC | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define AUTH0_OK (0) | ||||||
|  | #define AUTH0_ERR_EXPIRED (1) | ||||||
|  | #define AUTH0_ERR_SIG_FORMAT (2) | ||||||
|  | #define AUTH0_ERR_DECODE (3) | ||||||
|  | #define AUTH0_ERR_VERIFICATION (4) | ||||||
|  | #define AUTH0_ERR_AUDIENCE (5) | ||||||
|  | 
 | ||||||
|  | EXTERNC int auth0_verify_jwt(const char *secret, const char *token, const char* audience); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										31
									
								
								src/cli.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/cli.c
									
									
									
									
									
								
							| @ -501,6 +501,37 @@ int web_args_validate(web_args_t *args, int argc, const char **argv) { | |||||||
|         args->tag_auth_enabled = FALSE; |         args->tag_auth_enabled = FALSE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (args->auth0_public_key_path != NULL || args->auth0_audience != NULL || args->auth0_client_id || | ||||||
|  |         args->auth0_domain) { | ||||||
|  | 
 | ||||||
|  |         if (args->auth0_public_key_path == NULL) { | ||||||
|  |             fprintf(stderr, "Missing --auth0-public-key-file argument"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |         if (args->auth0_audience == NULL) { | ||||||
|  |             fprintf(stderr, "Missing --auth0-audience argument"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |         if (args->auth0_client_id == NULL) { | ||||||
|  |             fprintf(stderr, "Missing --auth0-client-id argument"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |         if (args->auth0_domain == NULL) { | ||||||
|  |             fprintf(stderr, "Missing --auth0-domain argument"); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (args->auth0_public_key_path != NULL) { | ||||||
|  |         if (load_external_file(args->auth0_public_key_path, &args->auth0_public_key) != 0) { | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         args->auth0_enabled = TRUE; | ||||||
|  |     } else { | ||||||
|  |         args->auth0_enabled = FALSE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     args->index_count = argc - 1; |     args->index_count = argc - 1; | ||||||
|     args->indices = argv + 1; |     args->indices = argv + 1; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -77,6 +77,12 @@ typedef struct web_args { | |||||||
|     char *lang; |     char *lang; | ||||||
|     char auth_user[256]; |     char auth_user[256]; | ||||||
|     char auth_pass[256]; |     char auth_pass[256]; | ||||||
|  |     int auth0_enabled; | ||||||
|  |     char *auth0_audience; | ||||||
|  |     char *auth0_domain; | ||||||
|  |     char *auth0_client_id; | ||||||
|  |     char *auth0_public_key_path; | ||||||
|  |     char *auth0_public_key; | ||||||
|     int auth_enabled; |     int auth_enabled; | ||||||
|     int tag_auth_enabled; |     int tag_auth_enabled; | ||||||
|     int index_count; |     int index_count; | ||||||
|  | |||||||
| @ -105,6 +105,13 @@ typedef struct { | |||||||
|     char *auth_pass; |     char *auth_pass; | ||||||
|     int auth_enabled; |     int auth_enabled; | ||||||
|     int tag_auth_enabled; |     int tag_auth_enabled; | ||||||
|  | 
 | ||||||
|  |     int auth0_enabled; | ||||||
|  |     char *auth0_public_key; | ||||||
|  |     char *auth0_audience; | ||||||
|  |     char *auth0_domain; | ||||||
|  |     char *auth0_client_id; | ||||||
|  | 
 | ||||||
|     char *tagline; |     char *tagline; | ||||||
|     struct index_t indices[256]; |     struct index_t indices[256]; | ||||||
|     char lang[10]; |     char lang[10]; | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.c
									
									
									
									
									
								
							| @ -13,6 +13,7 @@ | |||||||
| #include "web/serve.h" | #include "web/serve.h" | ||||||
| #include "parsing/mime.h" | #include "parsing/mime.h" | ||||||
| #include "parsing/parse.h" | #include "parsing/parse.h" | ||||||
|  | #include "auth0/auth0_c_api.h" | ||||||
| 
 | 
 | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| @ -562,6 +563,11 @@ void sist2_web(web_args_t *args) { | |||||||
|     WebCtx.tag_auth_enabled = args->tag_auth_enabled; |     WebCtx.tag_auth_enabled = args->tag_auth_enabled; | ||||||
|     WebCtx.tagline = args->tagline; |     WebCtx.tagline = args->tagline; | ||||||
|     WebCtx.dev = args->dev; |     WebCtx.dev = args->dev; | ||||||
|  |     WebCtx.auth0_enabled = args->auth0_enabled; | ||||||
|  |     WebCtx.auth0_public_key = args->auth0_public_key; | ||||||
|  |     WebCtx.auth0_client_id = args->auth0_client_id; | ||||||
|  |     WebCtx.auth0_domain = args->auth0_domain; | ||||||
|  |     WebCtx.auth0_audience = args->auth0_audience; | ||||||
|     strcpy(WebCtx.lang, args->lang); |     strcpy(WebCtx.lang, args->lang); | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < args->index_count; i++) { |     for (int i = 0; i < args->index_count; i++) { | ||||||
| @ -711,6 +717,10 @@ int main(int argc, const char *argv[]) { | |||||||
|             OPT_STRING(0, "es-index", &common_es_index, "Elasticsearch index name. DEFAULT=sist2"), |             OPT_STRING(0, "es-index", &common_es_index, "Elasticsearch index name. DEFAULT=sist2"), | ||||||
|             OPT_STRING(0, "bind", &web_args->listen_address, "Listen on this address. DEFAULT=localhost:4090"), |             OPT_STRING(0, "bind", &web_args->listen_address, "Listen on this address. DEFAULT=localhost:4090"), | ||||||
|             OPT_STRING(0, "auth", &web_args->credentials, "Basic auth in user:password format"), |             OPT_STRING(0, "auth", &web_args->credentials, "Basic auth in user:password format"), | ||||||
|  |             OPT_STRING(0, "auth0-audience", &web_args->auth0_audience, "API audience/identifier"), | ||||||
|  |             OPT_STRING(0, "auth0-domain", &web_args->auth0_domain, "Application domain"), | ||||||
|  |             OPT_STRING(0, "auth0-client-id", &web_args->auth0_client_id, "Application client ID"), | ||||||
|  |             OPT_STRING(0, "auth0-public-key-file", &web_args->auth0_public_key_path, "Path to Auth0 public key file extracted from <domain>/pem"), | ||||||
|             OPT_STRING(0, "tag-auth", &web_args->tag_credentials, "Basic auth in user:password format for tagging"), |             OPT_STRING(0, "tag-auth", &web_args->tag_credentials, "Basic auth in user:password format for tagging"), | ||||||
|             OPT_STRING(0, "tagline", &web_args->tagline, "Tagline in navbar"), |             OPT_STRING(0, "tagline", &web_args->tagline, "Tagline in navbar"), | ||||||
|             OPT_BOOLEAN(0, "dev", &web_args->dev, "Serve html & js files from disk (for development)"), |             OPT_BOOLEAN(0, "dev", &web_args->dev, "Serve html & js files from disk (for development)"), | ||||||
|  | |||||||
| @ -49,7 +49,7 @@ | |||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #include "git_hash.h" | #include "git_hash.h" | ||||||
| 
 | 
 | ||||||
| #define VERSION "2.13.0" | #define VERSION "2.13.1" | ||||||
| static const char *const Version = VERSION; | static const char *const Version = VERSION; | ||||||
| 
 | 
 | ||||||
| #ifndef SIST_PLATFORM | #ifndef SIST_PLATFORM | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ | |||||||
| #include "static_generated.c" | #include "static_generated.c" | ||||||
| #include "src/index/elastic.h" | #include "src/index/elastic.h" | ||||||
| #include "src/index/web.h" | #include "src/index/web.h" | ||||||
|  | #include "src/auth0/auth0_c_api.h" | ||||||
| 
 | 
 | ||||||
| #include <src/ctx.h> | #include <src/ctx.h> | ||||||
| 
 | 
 | ||||||
| @ -342,6 +343,14 @@ void index_info(struct mg_connection *nc) { | |||||||
|     cJSON_AddStringToObject(json, "sist2Hash", Sist2CommitHash); |     cJSON_AddStringToObject(json, "sist2Hash", Sist2CommitHash); | ||||||
|     cJSON_AddStringToObject(json, "lang", WebCtx.lang); |     cJSON_AddStringToObject(json, "lang", WebCtx.lang); | ||||||
|     cJSON_AddBoolToObject(json, "dev", WebCtx.dev); |     cJSON_AddBoolToObject(json, "dev", WebCtx.dev); | ||||||
|  | 
 | ||||||
|  |     cJSON_AddBoolToObject(json, "auth0Enabled", WebCtx.auth0_enabled); | ||||||
|  |     if (WebCtx.auth0_enabled) { | ||||||
|  |         cJSON_AddStringToObject(json, "auth0Domain", WebCtx.auth0_domain); | ||||||
|  |         cJSON_AddStringToObject(json, "auth0ClientId", WebCtx.auth0_client_id); | ||||||
|  |         cJSON_AddStringToObject(json, "auth0Audience", WebCtx.auth0_audience); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| #ifdef SIST_DEBUG | #ifdef SIST_DEBUG | ||||||
|     cJSON_AddBoolToObject(json, "debug", TRUE); |     cJSON_AddBoolToObject(json, "debug", TRUE); | ||||||
| #else | #else | ||||||
| @ -588,6 +597,42 @@ int validate_auth(struct mg_connection *nc, struct mg_http_message *hm) { | |||||||
|     return TRUE; |     return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int check_auth0(struct mg_http_message *hm) { | ||||||
|  | 
 | ||||||
|  |     struct mg_str *cookie = mg_http_get_header(hm, "Cookie"); | ||||||
|  |     if (cookie == NULL) { | ||||||
|  |         LOG_WARNING("serve.c", "Unauthorized request (no auth cookie)") | ||||||
|  |         return FALSE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     struct mg_str token = mg_str(""); | ||||||
|  |     char *token_str = NULL; | ||||||
|  | 
 | ||||||
|  |     token = mg_http_get_header_var(*cookie, mg_str("sist2-auth0")); | ||||||
|  |     if (token.len == 0) { | ||||||
|  |         LOG_WARNING("serve.c", "Unauthorized request (no auth cookie)") | ||||||
|  |         return FALSE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     token_str = malloc(token.len + 1); | ||||||
|  |     strncpy(token_str, token.ptr, token.len); | ||||||
|  |     *(token_str + token.len) = '\0'; | ||||||
|  | 
 | ||||||
|  |     int res = auth0_verify_jwt( | ||||||
|  |             WebCtx.auth0_public_key, | ||||||
|  |             token_str, | ||||||
|  |             WebCtx.auth0_audience | ||||||
|  |     ); | ||||||
|  |     free(token_str); | ||||||
|  | 
 | ||||||
|  |     if (res != AUTH0_OK) { | ||||||
|  |         LOG_WARNINGF("serve.c", "Unauthorized request (JWT validation error: %d)", res); | ||||||
|  |         return FALSE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return TRUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void ev_router(struct mg_connection *nc, int ev, void *ev_data, UNUSED(void *fn_data)) { | static void ev_router(struct mg_connection *nc, int ev, void *ev_data, UNUSED(void *fn_data)) { | ||||||
| 
 | 
 | ||||||
|     if (ev == MG_EV_HTTP_MSG) { |     if (ev == MG_EV_HTTP_MSG) { | ||||||
| @ -606,20 +651,34 @@ static void ev_router(struct mg_connection *nc, int ev, void *ev_data, UNUSED(vo | |||||||
| 
 | 
 | ||||||
|         if (mg_http_match_uri(hm, "/")) { |         if (mg_http_match_uri(hm, "/")) { | ||||||
|             search_index(nc, hm); |             search_index(nc, hm); | ||||||
|  |             return; | ||||||
|         } else if (mg_http_match_uri(hm, "/favicon.ico")) { |         } else if (mg_http_match_uri(hm, "/favicon.ico")) { | ||||||
|             favicon(nc, hm); |             favicon(nc, hm); | ||||||
|  |             return; | ||||||
|         } else if (mg_http_match_uri(hm, "/css/index.css")) { |         } else if (mg_http_match_uri(hm, "/css/index.css")) { | ||||||
|             style(nc, hm); |             style(nc, hm); | ||||||
|  |             return; | ||||||
|         } else if (mg_http_match_uri(hm, "/css/chunk-vendors.css")) { |         } else if (mg_http_match_uri(hm, "/css/chunk-vendors.css")) { | ||||||
|             style_vendor(nc, hm); |             style_vendor(nc, hm); | ||||||
|  |             return; | ||||||
|         } else if (mg_http_match_uri(hm, "/js/index.js")) { |         } else if (mg_http_match_uri(hm, "/js/index.js")) { | ||||||
|             javascript(nc, hm); |             javascript(nc, hm); | ||||||
|  |             return; | ||||||
|         } else if (mg_http_match_uri(hm, "/js/chunk-vendors.js")) { |         } else if (mg_http_match_uri(hm, "/js/chunk-vendors.js")) { | ||||||
|             javascript_vendor(nc, hm); |             javascript_vendor(nc, hm); | ||||||
|         } else if (mg_http_match_uri(hm, "/es")) { |             return; | ||||||
|             search(nc, hm); |  | ||||||
|         } else if (mg_http_match_uri(hm, "/i")) { |         } else if (mg_http_match_uri(hm, "/i")) { | ||||||
|             index_info(nc); |             index_info(nc); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (WebCtx.auth0_enabled && !check_auth0(hm)) { | ||||||
|  |             mg_http_reply(nc, 403, HTTP_SERVER_HEADER HTTP_TEXT_TYPE_HEADER, "Unauthorized (auth0 error)"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (mg_http_match_uri(hm, "/es")) { | ||||||
|  |             search(nc, hm); | ||||||
|         } else if (mg_http_match_uri(hm, "/status")) { |         } else if (mg_http_match_uri(hm, "/status")) { | ||||||
|             status(nc); |             status(nc); | ||||||
|         } else if (mg_http_match_uri(hm, "/f/*")) { |         } else if (mg_http_match_uri(hm, "/f/*")) { | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								src/web/static_generated.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								src/web/static_generated.c
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user