/**
   * Checks whether received credentials for accessing API is authorized for exporting and importing
   * APIs
   *
   * @param headers HTTP headers of the received request
   * @return Response indicating whether authentication and authorization for accessing API got
   *     succeeded
   * @throws APIExportException If an error occurs while authorizing current user
   */
  public static Response authorizeUser(HttpHeaders headers) throws APIExportException {
    if (!isValidCredentials(headers)) {
      log.error("No username and password is provided for authentication");
      return Response.status(Response.Status.UNAUTHORIZED)
          .entity("No username and password is provided for authentication")
          .type(MediaType.APPLICATION_JSON)
          .build();
    }

    try {
      String tenantDomain = MultitenantUtils.getTenantDomain(username);
      PrivilegedCarbonContext.startTenantFlow();
      PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);

      UserStoreManager userstoremanager =
          CarbonContext.getThreadLocalCarbonContext().getUserRealm().getUserStoreManager();

      String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username);

      // authenticate user provided credentials
      if (userstoremanager.authenticate(tenantAwareUsername, password)) {
        log.info(username + " user authenticated successfully");
        // Get admin role name of the current domain
        String adminRoleName =
            CarbonContext.getCurrentContext()
                .getUserRealm()
                .getRealmConfiguration()
                .getAdminRoleName();

        String[] userRoles = userstoremanager.getRoleListOfUser(tenantAwareUsername);

        // user is only authorized for exporting and importing if he is an admin of his
        // domain
        if (Arrays.asList(userRoles).contains(adminRoleName)) {
          log.info(username + " is authorized to import and export APIs");
          return Response.ok().build();
        } else {
          return Response.status(Response.Status.FORBIDDEN)
              .entity("User Authorization " + "Failed")
              .type(MediaType.APPLICATION_JSON)
              .build();
        }

      } else {
        return Response.status(Response.Status.UNAUTHORIZED)
            .entity("User Authentication " + "Failed")
            .type(MediaType.APPLICATION_JSON)
            .build();
      }

    } catch (UserStoreException e) {
      log.error("Error while accessing user configuration" + e.getMessage());
      throw new APIExportException("Error while accessing user configuration", e);
    } finally {
      PrivilegedCarbonContext.endTenantFlow();
    }
  }
 /**
  * Deleting cache data in JDBCTenantManager
  *
  * @param arg0 - ConfigurationContext
  */
 @Override
 public void execute(ConfigurationContext arg0) throws ClusteringFault {
   TenantManager tenantManager = TenantMgtServiceComponent.getTenantManager();
   try {
     tenantManager.deleteTenant(tenantId, IS_DELETE_PERSISTANCE_STORAGE);
   } catch (UserStoreException e) {
     log.error("Error occured while deleting cache : " + e.getMessage());
   }
 }
 @Path("device/download")
 @GET
 @Produces("application/zip")
 public Response downloadSketch(
     @QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType) {
   try {
     ZipArchive zipFile =
         createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType);
     Response.ResponseBuilder response =
         Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile()));
     response.status(Response.Status.OK);
     response.type("application/zip");
     response.header(
         "Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
     Response resp = response.build();
     zipFile.getZipFile().delete();
     return resp;
   } catch (IllegalArgumentException ex) {
     return Response.status(400).entity(ex.getMessage()).build(); // bad request
   } catch (DeviceManagementException ex) {
     log.error(ex.getMessage(), ex);
     return Response.status(500).entity(ex.getMessage()).build();
   } catch (JWTClientException ex) {
     log.error(ex.getMessage(), ex);
     return Response.status(500).entity(ex.getMessage()).build();
   } catch (APIManagerException ex) {
     log.error(ex.getMessage(), ex);
     return Response.status(500).entity(ex.getMessage()).build();
   } catch (IOException ex) {
     log.error(ex.getMessage(), ex);
     return Response.status(500).entity(ex.getMessage()).build();
   } catch (UserStoreException ex) {
     log.error(ex.getMessage(), ex);
     return Response.status(500).entity(ex.getMessage()).build();
   } catch (VirtualFirealarmDeviceMgtPluginException ex) {
     log.error(ex.getMessage(), ex);
     return Response.status(500).entity(ex.getMessage()).build();
   }
 }
  /**
   * Builds the response to change the password of a user
   *
   * @param credentials - User credentials
   * @return Response Object
   */
  public static Response buildChangePasswordResponse(OldPasswordResetWrapper credentials) {
    String username = "";
    try {
      RequestValidationUtil.validateCredentials(credentials);
      if (!validateCredential(credentials.getNewPassword())) {
        String errorMsg =
            DeviceMgtAPIUtils.getRealmService()
                .getBootstrapRealmConfiguration()
                .getUserStoreProperty(PASSWORD_VALIDATION_ERROR_MSG_TAG);
        return Response.status(Response.Status.BAD_REQUEST)
            .entity(new ErrorResponse.ErrorResponseBuilder().setMessage(errorMsg).build())
            .build();
      }

      UserStoreManager userStoreManager = DeviceMgtAPIUtils.getUserStoreManager();
      // this is the user who initiates the request
      username = CarbonContext.getThreadLocalCarbonContext().getUsername();
      userStoreManager.updateCredential(
          username, credentials.getNewPassword(), credentials.getOldPassword());
      return Response.status(Response.Status.OK)
          .entity("UserImpl password by username: "******" was successfully changed.")
          .build();
    } catch (UserStoreException e) {
      log.error(e.getMessage(), e);
      return Response.serverError()
          .entity(new ErrorResponse.ErrorResponseBuilder().setMessage(e.getMessage()).build())
          .build();
    } catch (UnsupportedEncodingException e) {
      String msg =
          "Could not change the password of the user: "******". The Character Encoding is not supported.";
      log.error(msg, e);
      return Response.serverError()
          .entity(new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build())
          .build();
    }
  }
  @Override
  public SortedMap<String, String> getClaims(String endUserName, String[] requestedClaims)
      throws IdentityOAuth2Exception {
    SortedMap<String, String> claimValues;
    try {
      int tenantId = JWTTokenGenerator.getTenantId(endUserName);
      // check in local cache
      String key = endUserName + ":" + tenantId;
      CacheKey cacheKey = new ClaimCacheKey(key);
      Object result = claimsLocalCache.getValueFromCache(cacheKey);

      if (result != null) {
        claimValues = ((UserClaims) result).getClaimValues();
      } else {
        // if no claims were requested, return all
        if (requestedClaims == null) {
          log.debug("No claims set requested. Returning all claims in the dialect");
          ClaimManager claimManager =
              OAuthComponentServiceHolder.getRealmService()
                  .getTenantUserRealm(tenantId)
                  .getClaimManager();
          ClaimMapping[] claims = claimManager.getAllClaimMappings(dialectURI);
          requestedClaims = claimToString(claims);
        }

        UserStoreManager userStoreManager =
            OAuthComponentServiceHolder.getRealmService()
                .getTenantUserRealm(tenantId)
                .getUserStoreManager();
        claimValues =
            new TreeMap(userStoreManager.getUserClaimValues(endUserName, requestedClaims, null));
        UserClaims userClaims = new UserClaims(claimValues);
        claimsLocalCache.addToCache(cacheKey, userClaims);
      }
    } catch (UserStoreException e) {
      log.debug("Error while reading user claims ", e);
      throw new IdentityOAuth2Exception(
          "Error while retrieving user claim values from " + "user store: " + e.getMessage());
    }
    return claimValues;
  }
 private void doAddUser(
     int i,
     UserStoreManager admin,
     String[] identityRoleNames,
     String userName,
     Permission permission)
     throws IdentityException, UserStoreException {
   try {
     if (!admin.isExistingRole(identityRoleNames[i], false)) {
       permission = new Permission("/permission/admin/login", UserMgtConstants.EXECUTE_ACTION);
       admin.addRole(
           identityRoleNames[i], new String[] {userName}, new Permission[] {permission}, false);
     } else {
       // if role already exists, just add user to role
       admin.updateUserListOfRole(identityRoleNames[i], new String[] {}, new String[] {userName});
     }
   } catch (org.wso2.carbon.user.api.UserStoreException e) {
     // If something goes wrong here - then remove the already added user.
     admin.deleteUser(userName);
     throw new IdentityException(
         "Error occurred while adding user : "******". " + e.getMessage(), e);
   }
 }
  /** Process the response of the Inwebo end-point */
  @Override
  protected void processAuthenticationResponse(
      HttpServletRequest request, HttpServletResponse response, AuthenticationContext context)
      throws AuthenticationFailedException {
    int waitTime;
    int retryInterval;
    String username = null;

    // Getting the last authenticated local user
    for (Integer stepMap : context.getSequenceConfig().getStepMap().keySet())
      if (context.getSequenceConfig().getStepMap().get(stepMap).getAuthenticatedUser() != null
          && context
                  .getSequenceConfig()
                  .getStepMap()
                  .get(stepMap)
                  .getAuthenticatedAutenticator()
                  .getApplicationAuthenticator()
              instanceof LocalApplicationAuthenticator) {
        username =
            String.valueOf(
                context.getSequenceConfig().getStepMap().get(stepMap).getAuthenticatedUser());
        break;
      }
    if (username != null) {
      UserRealm userRealm = null;
      try {
        String tenantDomain = MultitenantUtils.getTenantDomain(username);
        int tenantId = IdentityTenantUtil.getTenantId(tenantDomain);
        RealmService realmService = IdentityTenantUtil.getRealmService();
        userRealm = (UserRealm) realmService.getTenantUserRealm(tenantId);
        username = MultitenantUtils.getTenantAwareUsername(username);
        if (userRealm != null) {
          userId =
              userRealm
                  .getUserStoreManager()
                  .getUserClaimValue(username, InweboConstants.INWEBO_USERID, null)
                  .toString();
        } else {
          throw new AuthenticationFailedException(
              "Cannot find the user claim for the given userId: " + userId);
        }
      } catch (UserStoreException e) {
        throw new AuthenticationFailedException(
            "Error while getting the user realm" + e.getMessage(), e);
      }
    }
    Map<String, String> authenticatorProperties = context.getAuthenticatorProperties();
    if (authenticatorProperties != null) {
      String serviceId = authenticatorProperties.get(InweboConstants.SERVICE_ID);
      String p12file = authenticatorProperties.get(InweboConstants.INWEBO_P12FILE);
      String p12password = authenticatorProperties.get(InweboConstants.INWEBO_P12PASSWORD);
      if (!StringUtils.isEmpty(authenticatorProperties.get(InweboConstants.RETRY_COUNT))) {
        waitTime = Integer.parseInt(authenticatorProperties.get(InweboConstants.RETRY_COUNT));
      } else {
        waitTime = Integer.parseInt(InweboConstants.WAITTIME_DEFAULT);
      }
      if (!StringUtils.isEmpty(authenticatorProperties.get(InweboConstants.RETRY_INTERVAL))) {
        retryInterval =
            Integer.parseInt(authenticatorProperties.get(InweboConstants.RETRY_INTERVAL));
      } else {
        retryInterval = Integer.parseInt(InweboConstants.RETRYINTERVAL_DEFAULT);
      }
      PushRestCall push =
          new PushRestCall(serviceId, p12file, p12password, userId, waitTime, retryInterval);
      pushResponse = push.run();

      if (pushResponse.contains(InweboConstants.PUSHRESPONSE)) {
        if (log.isDebugEnabled()) {
          log.info("Authentication successful");
        }
        context.setSubject(
            AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(userId));
      } else {
        throw new AuthenticationFailedException("Authentication failed");
      }
      pushResponse = null;
      userId = null;
    } else {
      throw new AuthenticationFailedException("Required parameters are empty");
    }
  }
  @Override
  public boolean validateScope(AccessTokenDO accessTokenDO, String resource)
      throws IdentityOAuth2Exception {
    boolean status = true;
    // Extract the url & http method
    int idx = resource.lastIndexOf(':');
    String url = resource.substring(0, idx);
    String method = resource.substring(++idx, resource.length());
    // This is to remove the url params for request path.
    int urlParamIndex = url.indexOf('?');
    if (urlParamIndex > 0) {
      url = url.substring(0, urlParamIndex);
    }

    Properties properties = new Properties();
    properties.put(PermissionBasedScopeValidator.URL_PROPERTY, url.toLowerCase());
    properties.put(PermissionBasedScopeValidator.HTTP_METHOD_PROPERTY, method.toUpperCase());
    PermissionManagerService permissionManagerService =
        OAuthExtensionsDataHolder.getInstance().getPermissionManagerService();
    try {
      Permission permission = permissionManagerService.getPermission(properties);
      User authzUser = accessTokenDO.getAuthzUser();
      if ((permission != null) && (authzUser != null)) {
        if (permission.getPath() == null) {
          if (log.isDebugEnabled()) {
            log.debug("Permission is not defined for the resource '" + resource + "'");
          }
          return true;
        }
        String username = authzUser.getUserName();
        String userStore = authzUser.getUserStoreDomain();
        int tenantId = OAuthExtUtils.getTenantId(authzUser.getTenantDomain());
        UserRealm userRealm =
            OAuthExtensionsDataHolder.getInstance().getRealmService().getTenantUserRealm(tenantId);
        if (userRealm != null && userRealm.getAuthorizationManager() != null) {
          if (userStore != null) {
            status =
                userRealm
                    .getAuthorizationManager()
                    .isUserAuthorized(
                        userStore + "/" + username,
                        permission.getPath(),
                        PermissionMethod.UI_EXECUTE);
          } else {
            status =
                userRealm
                    .getAuthorizationManager()
                    .isUserAuthorized(username, permission.getPath(), PermissionMethod.UI_EXECUTE);
          }
        }
      }
    } catch (PermissionManagementException e) {
      log.error(
          "Error occurred while validating the resource scope for : "
              + resource
              + ", Msg = "
              + e.getMessage(),
          e);
    } catch (UserStoreException e) {
      log.error("Error occurred while retrieving user store. " + e.getMessage());
    }
    return status;
  }