/* * Copyright 2014-2016 CyberVision, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kaaproject.kaa.server.operations.service.akka.actors.core; import static org.kaaproject.kaa.server.common.verifier.UserVerifierErrorCode.NO_VERIFIER_CONFIGURED; import static org.kaaproject.kaa.server.operations.service.akka.messages.core.user.verification.UserVerificationResponseMessage.failure; import static org.kaaproject.kaa.server.operations.service.akka.messages.core.user.verification.UserVerificationResponseMessage.success; import akka.actor.ActorRef; import org.kaaproject.kaa.common.dto.user.UserVerifierDto; import org.kaaproject.kaa.server.common.thrift.gen.operations.Notification; import org.kaaproject.kaa.server.common.verifier.UserVerifier; import org.kaaproject.kaa.server.common.verifier.UserVerifierCallback; import org.kaaproject.kaa.server.common.verifier.UserVerifierContext; import org.kaaproject.kaa.server.common.verifier.UserVerifierErrorCode; import org.kaaproject.kaa.server.common.verifier.UserVerifierLifecycleException; import org.kaaproject.kaa.server.operations.service.akka.messages.core.user.verification.UserVerificationRequestMessage; import org.kaaproject.kaa.server.operations.service.akka.messages.core.user.verification.UserVerificationResponseMessage; import org.kaaproject.kaa.server.operations.service.user.EndpointUserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; public class ApplicationUserVerifierActorMessageProcessor { private static final Logger LOG = LoggerFactory .getLogger(ApplicationUserVerifierActorMessageProcessor.class); private final EndpointUserService endpointUserService; private final String applicationId; private Map<String, UserVerifier> userVerifiers; ApplicationUserVerifierActorMessageProcessor(EndpointUserService endpointUserService, String applicationId) { this.applicationId = applicationId; this.endpointUserService = endpointUserService; initUserVerifiers(); } private void initUserVerifiers() { this.userVerifiers = new HashMap<>(); for (UserVerifierDto dto : endpointUserService.findUserVerifiers(applicationId)) { try { LOG.trace("Initializing user verifier for {}", dto); UserVerifier verifier = createUserVerifier(dto); LOG.trace("Registering user verifier with token {}", dto.getVerifierToken()); userVerifiers.put(dto.getVerifierToken(), verifier); } catch (Exception ex) { LOG.error("Failed to create user verifier", ex); } } } private UserVerifier createUserVerifier(UserVerifierDto verifierDto) throws Exception { if (verifierDto == null) { throw new IllegalArgumentException("verifier dto can't be null"); } try { @SuppressWarnings("unchecked") Class<UserVerifier> verifierClass = (Class<UserVerifier>) Class .forName(verifierDto.getPluginClassName()); UserVerifier userVerifier = verifierClass.newInstance(); userVerifier.init(new UserVerifierContext(verifierDto)); userVerifier.start(); return userVerifier; } catch (ClassNotFoundException ex) { LOG.error("Unable to find custom verifier class {}", verifierDto.getPluginClassName()); throw ex; } catch (InstantiationException | IllegalAccessException | UserVerifierLifecycleException ex) { LOG.error("Unable to instantiate custom verifier from class {}", verifierDto.getPluginClassName()); throw ex; } } /** * Verifies a user. * * @param message user verification request message */ public void verifyUser(UserVerificationRequestMessage message) { UserVerifier verifier = userVerifiers.get(message.getVerifierId()); if (verifier != null) { verifier.checkAccessToken(message.getUserId(), message.getAccessToken(), new DefaultVerifierCallback(message)); } else { LOG.debug("Failed to find verifier with token {}", message.getVerifierId()); message.getOriginator() .tell(failure(message.getRequestid(), message.getUserId(), NO_VERIFIER_CONFIGURED), ActorRef.noSender()); } } /** * Process a notification. * * @param notification notification */ public void processNotification(Notification notification) { LOG.debug("Process user verifier notification [{}]", notification); String verifierToken = notification.getUserVerifierToken(); switch (notification.getOp()) { case ADD_USER_VERIFIER: addUserVerifier(verifierToken); break; case REMOVE_USER_VERIFIER: removeUserVerifier(verifierToken); break; case UPDATE_USER_VERIFIER: removeUserVerifier(verifierToken); addUserVerifier(verifierToken); break; default: LOG.debug("[{}][{}] Operation [{}] is not supported.", applicationId, verifierToken, notification.getOp()); } } private void addUserVerifier(String verifierToken) { LOG.info("[{}] Adding user verifier with token [{}].", applicationId, verifierToken); if (!userVerifiers.containsKey(verifierToken)) { UserVerifierDto verifierDto = endpointUserService .findUserVerifier(applicationId, verifierToken); if (verifierDto != null) { try { userVerifiers.put(verifierToken, createUserVerifier(verifierDto)); LOG.info("[{}] user verifier [{}] registered.", applicationId, verifierToken); } catch (Exception ex) { LOG.error("Failed to create user verifier", ex); } } } else { LOG.info("[{}] User verifier [{}] is already registered.", applicationId, verifierToken); } } private void removeUserVerifier(String verifierToken) { if (userVerifiers.containsKey(verifierToken)) { LOG.info("[{}] Stopping user verifier with token [{}].", applicationId, verifierToken); userVerifiers.remove(verifierToken).stop(); } else { LOG.warn("[{}] Can't remove unregistered user verifier with token [{}]", applicationId, verifierToken); } } void preStart() { // Do nothing } ; void postStop() { for (Entry<String, UserVerifier> verifier : userVerifiers.entrySet()) { LOG.info("[{}] Stopping user verifier with id [{}].", applicationId, verifier.getKey()); verifier.getValue().stop(); } } private static class DefaultVerifierCallback implements UserVerifierCallback { private final ActorRef endpointActor; private final UUID requestId; private final String userId; public DefaultVerifierCallback(UserVerificationRequestMessage message) { super(); this.endpointActor = message.getOriginator(); this.requestId = message.getRequestid(); this.userId = message.getUserId(); } private void tellFailure(UserVerifierErrorCode errorCode) { tellFailure(errorCode, null); } private void tellFailure(UserVerifierErrorCode errorCode, String reason) { endpointActor.tell(failure(requestId, reason, errorCode, reason), ActorRef.noSender()); } @Override public void onSuccess() { endpointActor.tell(success(requestId, userId), ActorRef.noSender()); } @Override public void onTokenInvalid() { tellFailure(UserVerifierErrorCode.TOKEN_INVALID); } @Override public void onTokenExpired() { tellFailure(UserVerifierErrorCode.TOKEN_EXPIRED); } @Override public void onVerificationFailure(String reason) { tellFailure(UserVerifierErrorCode.OTHER, reason); } @Override public void onInternalError() { tellFailure(UserVerifierErrorCode.INTERNAL_ERROR); } @Override public void onInternalError(String reason) { tellFailure(UserVerifierErrorCode.INTERNAL_ERROR, reason); } @Override public void onConnectionError() { tellFailure(UserVerifierErrorCode.CONNECTION_ERROR); } @Override public void onConnectionError(String reason) { tellFailure(UserVerifierErrorCode.CONNECTION_ERROR, reason); } @Override public void onRemoteError() { tellFailure(UserVerifierErrorCode.REMOTE_ERROR); } @Override public void onRemoteError(String reason) { tellFailure(UserVerifierErrorCode.REMOTE_ERROR, reason); } } }