ClientApiServlet.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. * Password Management Servlets (PWM)
  3. * http://www.pwm-project.org
  4. *
  5. * Copyright (c) 2006-2009 Novell, Inc.
  6. * Copyright (c) 2009-2019 The PWM Project
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. package password.pwm.http.servlet;
  21. import com.novell.ldapchai.exception.ChaiUnavailableException;
  22. import lombok.Data;
  23. import password.pwm.AppProperty;
  24. import password.pwm.Permission;
  25. import password.pwm.PwmApplication;
  26. import password.pwm.PwmApplicationMode;
  27. import password.pwm.PwmConstants;
  28. import password.pwm.config.Configuration;
  29. import password.pwm.config.PwmSetting;
  30. import password.pwm.config.option.SelectableContextMode;
  31. import password.pwm.error.ErrorInformation;
  32. import password.pwm.error.PwmError;
  33. import password.pwm.error.PwmUnrecoverableException;
  34. import password.pwm.http.HttpHeader;
  35. import password.pwm.http.HttpMethod;
  36. import password.pwm.http.IdleTimeoutCalculator;
  37. import password.pwm.http.ProcessStatus;
  38. import password.pwm.http.PwmHttpRequestWrapper;
  39. import password.pwm.http.PwmRequest;
  40. import password.pwm.http.PwmSession;
  41. import password.pwm.http.PwmURL;
  42. import password.pwm.i18n.Display;
  43. import password.pwm.svc.stats.EpsStatistic;
  44. import password.pwm.svc.stats.Statistic;
  45. import password.pwm.svc.stats.StatisticsManager;
  46. import password.pwm.util.i18n.LocaleHelper;
  47. import password.pwm.util.java.TimeDuration;
  48. import password.pwm.util.logging.PwmLogger;
  49. import password.pwm.util.macro.MacroMachine;
  50. import password.pwm.util.secure.PwmHashAlgorithm;
  51. import password.pwm.util.secure.SecureEngine;
  52. import password.pwm.ws.server.RestResultBean;
  53. import password.pwm.ws.server.rest.RestHealthServer;
  54. import password.pwm.ws.server.rest.RestStatisticsServer;
  55. import password.pwm.ws.server.rest.bean.HealthData;
  56. import javax.servlet.ServletException;
  57. import javax.servlet.annotation.WebServlet;
  58. import javax.servlet.http.HttpServletRequest;
  59. import javax.servlet.http.HttpServletResponse;
  60. import java.io.IOException;
  61. import java.io.Serializable;
  62. import java.net.URI;
  63. import java.time.Instant;
  64. import java.util.ArrayList;
  65. import java.util.Collection;
  66. import java.util.Collections;
  67. import java.util.LinkedHashMap;
  68. import java.util.List;
  69. import java.util.Locale;
  70. import java.util.Map;
  71. import java.util.ResourceBundle;
  72. import java.util.TreeMap;
  73. import java.util.TreeSet;
  74. @WebServlet(
  75. name = "ClientApiServlet",
  76. urlPatterns = {
  77. PwmConstants.URL_PREFIX_PUBLIC + "/api",
  78. }
  79. )
  80. public class ClientApiServlet extends ControlledPwmServlet
  81. {
  82. private static final PwmLogger LOGGER = PwmLogger.forClass( ClientApiServlet.class );
  83. @Data
  84. public static class AppData implements Serializable
  85. {
  86. @SuppressWarnings( "checkstyle:MemberName" )
  87. public Map<String, Object> PWM_GLOBAL;
  88. }
  89. @Data
  90. public static class PingResponse implements Serializable
  91. {
  92. private Instant time;
  93. private String runtimeNonce;
  94. }
  95. public enum ClientApiAction implements AbstractPwmServlet.ProcessAction
  96. {
  97. clientData( HttpMethod.GET ),
  98. strings( HttpMethod.GET ),
  99. health( HttpMethod.GET ),
  100. ping( HttpMethod.GET ),
  101. statistics( HttpMethod.GET ),;
  102. private final HttpMethod method;
  103. ClientApiAction( final HttpMethod method )
  104. {
  105. this.method = method;
  106. }
  107. public Collection<HttpMethod> permittedMethods( )
  108. {
  109. return Collections.singletonList( method );
  110. }
  111. }
  112. @Override
  113. public Class<? extends ProcessAction> getProcessActionsClass( )
  114. {
  115. return ClientApiServlet.ClientApiAction.class;
  116. }
  117. @Override
  118. protected void nextStep( final PwmRequest pwmRequest ) throws PwmUnrecoverableException, IOException, ChaiUnavailableException, ServletException
  119. {
  120. // no mvc pattern in this servlet
  121. }
  122. @Override
  123. public ProcessStatus preProcessCheck( final PwmRequest pwmRequest ) throws PwmUnrecoverableException, IOException, ServletException
  124. {
  125. return ProcessStatus.Continue;
  126. }
  127. @ActionHandler( action = "clientData" )
  128. public ProcessStatus processRestClientData( final PwmRequest pwmRequest )
  129. throws PwmUnrecoverableException, IOException, ChaiUnavailableException
  130. {
  131. final String pageUrl = pwmRequest.readParameterAsString( "pageUrl", PwmHttpRequestWrapper.Flag.BypassValidation );
  132. final String etagParam = pwmRequest.readParameterAsString( "etag", PwmHttpRequestWrapper.Flag.BypassValidation );
  133. final int maxCacheAgeSeconds = 60 * 5;
  134. final String eTagValue = makeClientEtag( pwmRequest.getPwmApplication(), pwmRequest.getPwmSession(), pwmRequest.getHttpServletRequest() );
  135. // check the incoming header;
  136. final String ifNoneMatchValue = pwmRequest.readHeaderValueAsString( "If-None-Match" );
  137. if ( ifNoneMatchValue != null && ifNoneMatchValue.equals( eTagValue ) && eTagValue.equals( etagParam ) )
  138. {
  139. pwmRequest.getPwmResponse().setStatus( 304 );
  140. return ProcessStatus.Halt;
  141. }
  142. pwmRequest.getPwmResponse().setHeader( HttpHeader.ETag, eTagValue );
  143. pwmRequest.getPwmResponse().setHeader( HttpHeader.Expires, String.valueOf( System.currentTimeMillis() + ( maxCacheAgeSeconds * 1000 ) ) );
  144. pwmRequest.getPwmResponse().setHeader( HttpHeader.CacheControl, "public, max-age=" + maxCacheAgeSeconds );
  145. final AppData appData = makeAppData(
  146. pwmRequest.getPwmApplication(),
  147. pwmRequest,
  148. pwmRequest.getHttpServletRequest(),
  149. pwmRequest.getPwmResponse().getHttpServletResponse(),
  150. pageUrl
  151. );
  152. final RestResultBean restResultBean = RestResultBean.withData( appData );
  153. pwmRequest.outputJsonResult( restResultBean );
  154. return ProcessStatus.Halt;
  155. }
  156. @ActionHandler( action = "strings" )
  157. public ProcessStatus doGetStringsData( final PwmRequest pwmRequest
  158. )
  159. throws PwmUnrecoverableException, IOException, ChaiUnavailableException, ServletException
  160. {
  161. final String bundleName = pwmRequest.readParameterAsString( "bundle" );
  162. final int maxCacheAgeSeconds = 60 * 5;
  163. final String eTagValue = makeClientEtag( pwmRequest.getPwmApplication(), pwmRequest.getPwmSession(), pwmRequest.getHttpServletRequest() );
  164. pwmRequest.getPwmResponse().setHeader( HttpHeader.ETag, eTagValue );
  165. pwmRequest.getPwmResponse().setHeader( HttpHeader.Expires, String.valueOf( System.currentTimeMillis() + ( maxCacheAgeSeconds * 1000 ) ) );
  166. pwmRequest.getPwmResponse().setHeader( HttpHeader.CacheControl, "public, max-age=" + maxCacheAgeSeconds );
  167. try
  168. {
  169. final LinkedHashMap<String, String> displayData = new LinkedHashMap<>( makeDisplayData( pwmRequest.getPwmApplication(),
  170. pwmRequest, bundleName ) );
  171. final RestResultBean restResultBean = RestResultBean.withData( displayData );
  172. pwmRequest.outputJsonResult( restResultBean );
  173. }
  174. catch ( final Exception e )
  175. {
  176. final String errorMSg = "error during rest /strings call for bundle " + bundleName + ", error: " + e.getMessage();
  177. final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMSg );
  178. LOGGER.debug( pwmRequest, errorInformation );
  179. pwmRequest.respondWithError( errorInformation );
  180. }
  181. return ProcessStatus.Halt;
  182. }
  183. @ActionHandler( action = "health" )
  184. public ProcessStatus restHealthProcessor( final PwmRequest pwmRequest )
  185. throws IOException, ServletException, PwmUnrecoverableException
  186. {
  187. precheckPublicHealthAndStats( pwmRequest );
  188. try
  189. {
  190. final HealthData jsonOutput = RestHealthServer.processGetHealthCheckData(
  191. pwmRequest.getPwmApplication(),
  192. pwmRequest.getLocale() );
  193. final RestResultBean restResultBean = RestResultBean.withData( jsonOutput );
  194. pwmRequest.outputJsonResult( restResultBean );
  195. }
  196. catch ( final Exception e )
  197. {
  198. final String errorMessage = "unexpected error executing web service: " + e.getMessage();
  199. final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMessage );
  200. LOGGER.debug( pwmRequest, errorInformation );
  201. pwmRequest.respondWithError( errorInformation );
  202. }
  203. return ProcessStatus.Halt;
  204. }
  205. @ActionHandler( action = "ping" )
  206. public ProcessStatus processPingRequest( final PwmRequest pwmRequest )
  207. throws IOException
  208. {
  209. final PingResponse pingResponse = new PingResponse();
  210. pingResponse.setTime( Instant.now() );
  211. pingResponse.setRuntimeNonce( pwmRequest.getPwmApplication().getRuntimeNonce() );
  212. pwmRequest.outputJsonResult( RestResultBean.withData( pingResponse ) );
  213. return ProcessStatus.Halt;
  214. }
  215. public static String makeClientEtag( final PwmRequest pwmRequest )
  216. throws PwmUnrecoverableException
  217. {
  218. return makeClientEtag( pwmRequest.getPwmApplication(), pwmRequest.getPwmSession(), pwmRequest.getHttpServletRequest() );
  219. }
  220. public static String makeClientEtag(
  221. final PwmApplication pwmApplication,
  222. final PwmSession pwmSession,
  223. final HttpServletRequest httpServletRequest
  224. )
  225. throws PwmUnrecoverableException
  226. {
  227. final StringBuilder inputString = new StringBuilder();
  228. inputString.append( PwmConstants.BUILD_NUMBER );
  229. inputString.append( pwmApplication.getStartupTime().toEpochMilli() );
  230. inputString.append( httpServletRequest.getSession().getMaxInactiveInterval() );
  231. inputString.append( pwmApplication.getRuntimeNonce() );
  232. if ( pwmSession.getSessionStateBean().getLocale() != null )
  233. {
  234. inputString.append( pwmSession.getSessionStateBean().getLocale() );
  235. }
  236. inputString.append( pwmSession.getSessionStateBean().getSessionID() );
  237. if ( pwmSession.isAuthenticated() )
  238. {
  239. inputString.append( pwmSession.getUserInfo().getUserGuid() );
  240. inputString.append( pwmSession.getLoginInfoBean().getAuthTime() );
  241. }
  242. return SecureEngine.hash( inputString.toString(), PwmHashAlgorithm.SHA1 ).toLowerCase();
  243. }
  244. private AppData makeAppData(
  245. final PwmApplication pwmApplication,
  246. final PwmRequest pwmSession,
  247. final HttpServletRequest request,
  248. final HttpServletResponse response,
  249. final String pageUrl
  250. )
  251. throws ChaiUnavailableException, PwmUnrecoverableException
  252. {
  253. final AppData appData = new AppData();
  254. appData.PWM_GLOBAL = makeClientData( pwmApplication, pwmSession, request, response, pageUrl );
  255. return appData;
  256. }
  257. private static Map<String, Object> makeClientData(
  258. final PwmApplication pwmApplication,
  259. final PwmRequest pwmRequest,
  260. final HttpServletRequest request,
  261. final HttpServletResponse response,
  262. final String pageUrl
  263. )
  264. throws ChaiUnavailableException, PwmUnrecoverableException
  265. {
  266. final PwmSession pwmSession = pwmRequest.getPwmSession();
  267. final Locale userLocale = pwmSession.getSessionStateBean().getLocale();
  268. final Configuration config = pwmApplication.getConfig();
  269. final TreeMap<String, Object> settingMap = new TreeMap<>();
  270. settingMap.put( "client.ajaxTypingTimeout", Integer.parseInt( config.readAppProperty( AppProperty.CLIENT_AJAX_TYPING_TIMEOUT ) ) );
  271. settingMap.put( "client.ajaxTypingWait", Integer.parseInt( config.readAppProperty( AppProperty.CLIENT_AJAX_TYPING_WAIT ) ) );
  272. settingMap.put( "client.activityMaxEpsRate", Integer.parseInt( config.readAppProperty( AppProperty.CLIENT_ACTIVITY_MAX_EPS_RATE ) ) );
  273. settingMap.put( "client.js.enableHtml5Dialog", Boolean.parseBoolean( config.readAppProperty( AppProperty.CLIENT_JS_ENABLE_HTML5DIALOG ) ) );
  274. settingMap.put( "client.locale", LocaleHelper.getBrowserLocaleString( pwmSession.getSessionStateBean().getLocale() ) );
  275. settingMap.put( "client.pwShowRevertTimeout", Integer.parseInt( config.readAppProperty( AppProperty.CLIENT_PW_SHOW_REVERT_TIMEOUT ) ) );
  276. settingMap.put( "enableIdleTimeout", config.readSettingAsBoolean( PwmSetting.DISPLAY_IDLE_TIMEOUT ) );
  277. settingMap.put( "pageLeaveNotice", config.readSettingAsLong( PwmSetting.SECURITY_PAGE_LEAVE_NOTICE_TIMEOUT ) );
  278. settingMap.put( "setting-showHidePasswordFields", pwmApplication.getConfig().readSettingAsBoolean( password.pwm.config.PwmSetting.DISPLAY_SHOW_HIDE_PASSWORD_FIELDS ) );
  279. settingMap.put( "setting-displayEula", PwmConstants.ENABLE_EULA_DISPLAY );
  280. settingMap.put( "setting-showStrengthMeter", config.readSettingAsBoolean( PwmSetting.PASSWORD_SHOW_STRENGTH_METER ) );
  281. {
  282. long idleSeconds = config.readSettingAsLong( PwmSetting.IDLE_TIMEOUT_SECONDS );
  283. if ( pageUrl == null || pageUrl.isEmpty() )
  284. {
  285. LOGGER.warn( pwmRequest, "request to /client data did not include pageUrl" );
  286. }
  287. else
  288. {
  289. try
  290. {
  291. final PwmURL pwmURL = new PwmURL( new URI( pageUrl ), request.getContextPath() );
  292. final TimeDuration maxIdleTime = IdleTimeoutCalculator.idleTimeoutForRequest( pwmRequest );
  293. idleSeconds = maxIdleTime.as( TimeDuration.Unit.SECONDS );
  294. }
  295. catch ( final Exception e )
  296. {
  297. LOGGER.error( pwmRequest, "error determining idle timeout time for request: " + e.getMessage() );
  298. }
  299. }
  300. settingMap.put( "MaxInactiveInterval", idleSeconds );
  301. }
  302. settingMap.put( "paramName.locale", config.readAppProperty( AppProperty.HTTP_PARAM_NAME_LOCALE ) );
  303. settingMap.put( "runtimeNonce", pwmApplication.getRuntimeNonce() );
  304. settingMap.put( "applicationMode", pwmApplication.getApplicationMode() );
  305. final String contextPath = request.getContextPath();
  306. settingMap.put( "url-context", contextPath );
  307. settingMap.put( "url-logout", contextPath + PwmServletDefinition.Logout.servletUrl() );
  308. settingMap.put( "url-command", contextPath + PwmServletDefinition.PublicCommand.servletUrl() );
  309. settingMap.put( "url-resources", contextPath + "/public/resources" + pwmApplication.getResourceServletService().getResourceNonce() );
  310. settingMap.put( "url-restservice", contextPath + "/public/rest" );
  311. {
  312. String passwordGuideText = pwmApplication.getConfig().readSettingAsLocalizedString(
  313. PwmSetting.DISPLAY_PASSWORD_GUIDE_TEXT,
  314. pwmSession.getSessionStateBean().getLocale()
  315. );
  316. final MacroMachine macroMachine = pwmSession.getSessionManager().getMacroMachine( );
  317. passwordGuideText = macroMachine.expandMacros( passwordGuideText );
  318. settingMap.put( "passwordGuideText", passwordGuideText );
  319. }
  320. {
  321. final List<String> epsTypes = new ArrayList<>();
  322. for ( final EpsStatistic loopEpsType : EpsStatistic.values() )
  323. {
  324. epsTypes.add( loopEpsType.toString() );
  325. }
  326. settingMap.put( "epsTypes", epsTypes );
  327. }
  328. {
  329. final List<String> epsDurations = new ArrayList<>();
  330. for ( final Statistic.EpsDuration loopEpsDuration : Statistic.EpsDuration.values() )
  331. {
  332. epsDurations.add( loopEpsDuration.toString() );
  333. }
  334. settingMap.put( "epsDurations", epsDurations );
  335. }
  336. {
  337. final Map<String, String> localeInfo = new LinkedHashMap<>();
  338. final Map<String, String> localeDisplayNames = new LinkedHashMap<>();
  339. final Map<String, String> localeFlags = new LinkedHashMap<>();
  340. final List<Locale> knownLocales = new ArrayList<>( pwmApplication.getConfig().getKnownLocales() );
  341. knownLocales.sort( LocaleHelper.localeComparator( PwmConstants.DEFAULT_LOCALE ) );
  342. for ( final Locale locale : knownLocales )
  343. {
  344. final String flagCode = pwmApplication.getConfig().getKnownLocaleFlagMap().get( locale );
  345. localeFlags.put( locale.toString(), flagCode );
  346. localeInfo.put( locale.toString(), locale.getDisplayName( PwmConstants.DEFAULT_LOCALE ) + " - " + locale.getDisplayLanguage( userLocale ) );
  347. localeDisplayNames.put( locale.toString(), locale.getDisplayLanguage() );
  348. }
  349. settingMap.put( "localeInfo", localeInfo );
  350. settingMap.put( "localeDisplayNames", localeDisplayNames );
  351. settingMap.put( "localeFlags", localeFlags );
  352. settingMap.put( "defaultLocale", PwmConstants.DEFAULT_LOCALE.toString() );
  353. }
  354. if ( pwmApplication.getConfig().readSettingAsEnum( PwmSetting.LDAP_SELECTABLE_CONTEXT_MODE, SelectableContextMode.class ) != SelectableContextMode.NONE )
  355. {
  356. final Map<String, Map<String, String>> ldapProfiles = new LinkedHashMap<>();
  357. for ( final String ldapProfile : pwmApplication.getConfig().getLdapProfiles().keySet() )
  358. {
  359. final Map<String, String> contexts = pwmApplication.getConfig().getLdapProfiles().get( ldapProfile ).getSelectableContexts( pwmApplication );
  360. ldapProfiles.put( ldapProfile, contexts );
  361. }
  362. settingMap.put( "ldapProfiles", ldapProfiles );
  363. }
  364. return settingMap;
  365. }
  366. private Map<String, String> makeDisplayData(
  367. final PwmApplication pwmApplication,
  368. final PwmRequest pwmRequest,
  369. final String bundleName
  370. )
  371. {
  372. final PwmSession pwmSession = pwmRequest.getPwmSession();
  373. Class displayClass = LocaleHelper.classForShortName( bundleName );
  374. displayClass = displayClass == null ? Display.class : displayClass;
  375. final Locale userLocale = pwmSession.getSessionStateBean().getLocale();
  376. final Configuration config = pwmApplication.getConfig();
  377. final TreeMap<String, String> displayStrings = new TreeMap<>();
  378. final ResourceBundle bundle = ResourceBundle.getBundle( displayClass.getName() );
  379. try
  380. {
  381. final MacroMachine macroMachine = pwmSession.getSessionManager().getMacroMachine( );
  382. for ( final String key : new TreeSet<>( Collections.list( bundle.getKeys() ) ) )
  383. {
  384. String displayValue = LocaleHelper.getLocalizedMessage( userLocale, key, config, displayClass );
  385. displayValue = macroMachine.expandMacros( displayValue );
  386. displayStrings.put( key, displayValue );
  387. }
  388. }
  389. catch ( final Exception e )
  390. {
  391. LOGGER.error( pwmRequest, "error expanding macro display value: " + e.getMessage() );
  392. }
  393. return displayStrings;
  394. }
  395. @ActionHandler( action = "statistics" )
  396. private ProcessStatus restStatisticsHandler( final PwmRequest pwmRequest )
  397. throws ChaiUnavailableException, PwmUnrecoverableException, IOException
  398. {
  399. precheckPublicHealthAndStats( pwmRequest );
  400. final String statKey = pwmRequest.readParameterAsString( "statKey" );
  401. final String statName = pwmRequest.readParameterAsString( "statName" );
  402. final String days = pwmRequest.readParameterAsString( "days" );
  403. final StatisticsManager statisticsManager = pwmRequest.getPwmApplication().getStatisticsManager();
  404. final RestStatisticsServer.OutputVersion1.JsonOutput jsonOutput = new RestStatisticsServer.OutputVersion1.JsonOutput();
  405. jsonOutput.EPS = RestStatisticsServer.OutputVersion1.addEpsStats( statisticsManager );
  406. if ( statName != null && statName.length() > 0 )
  407. {
  408. jsonOutput.nameData = RestStatisticsServer.OutputVersion1.doNameStat( statisticsManager, statName, days );
  409. }
  410. else
  411. {
  412. jsonOutput.keyData = RestStatisticsServer.OutputVersion1.doKeyStat( statisticsManager, statKey );
  413. }
  414. final RestResultBean restResultBean = RestResultBean.withData( jsonOutput );
  415. pwmRequest.outputJsonResult( restResultBean );
  416. return ProcessStatus.Halt;
  417. }
  418. private void precheckPublicHealthAndStats( final PwmRequest pwmRequest )
  419. throws PwmUnrecoverableException
  420. {
  421. if (
  422. pwmRequest.getPwmApplication().getApplicationMode() != PwmApplicationMode.RUNNING
  423. && pwmRequest.getPwmApplication().getApplicationMode() != PwmApplicationMode.CONFIGURATION
  424. )
  425. {
  426. final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_SERVICE_NOT_AVAILABLE );
  427. throw new PwmUnrecoverableException( errorInformation );
  428. }
  429. if ( !pwmRequest.getConfig().readSettingAsBoolean( PwmSetting.PUBLIC_HEALTH_STATS_WEBSERVICES ) )
  430. {
  431. if ( !pwmRequest.isAuthenticated() )
  432. {
  433. final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_AUTHENTICATION_REQUIRED );
  434. throw new PwmUnrecoverableException( errorInformation );
  435. }
  436. if ( !pwmRequest.getPwmSession().getSessionManager().checkPermission( pwmRequest.getPwmApplication(), Permission.PWMADMIN ) )
  437. {
  438. final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_UNAUTHORIZED, "admin privileges required" );
  439. throw new PwmUnrecoverableException( errorInformation );
  440. }
  441. }
  442. }
  443. }