fm.pattern.tokamak.server.service.ClientServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for fm.pattern.tokamak.server.service.ClientServiceImpl.java

Source

/*
 * Copyright 2012-2017 the original author or authors.
 *
 * 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 fm.pattern.tokamak.server.service;

import static org.apache.commons.lang3.StringUtils.isBlank;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import fm.pattern.tokamak.server.model.Client;
import fm.pattern.tokamak.server.model.PasswordPolicy;
import fm.pattern.tokamak.server.repository.Cache;
import fm.pattern.tokamak.server.repository.Criteria;
import fm.pattern.tokamak.server.repository.PaginatedList;
import fm.pattern.tokamak.server.validation.PasswordValidator;
import fm.pattern.valex.Reportable;
import fm.pattern.valex.Result;

@Service
@SuppressWarnings("unchecked")
class ClientServiceImpl extends DataServiceImpl<Client> implements ClientService {

    private static final String id_key = "clients:id:%s";
    private static final String client_id_key = "clients:client_id:%s";

    private final PasswordEncodingService passwordEncodingService;
    private final PasswordPolicyService passwordPolicyService;
    private final PasswordValidator passwordValidator;
    private final Cache cache;

    @Autowired
    public ClientServiceImpl(PasswordEncodingService passwordEncodingService,
            PasswordPolicyService passwordPolicyService, PasswordValidator passwordValidator,
            @Qualifier("clientCache") Cache cache) {
        this.passwordEncodingService = passwordEncodingService;
        this.passwordPolicyService = passwordPolicyService;
        this.passwordValidator = passwordValidator;
        this.cache = cache;
    }

    @Transactional
    public Result<Client> create(Client client) {
        PasswordPolicy policy = passwordPolicyService.findByName("client-password-policy").orThrow();

        Result<String> password = passwordValidator.validate(client.getClientSecret(), policy);
        if (password.rejected()) {
            return Result.reject(password.getErrors().toArray(new Reportable[password.getErrors().size()]));
        }

        Result<Client> result = super.create(
                client.clientSecret(passwordEncodingService.encode(client.getClientSecret())));
        if (result.accepted()) {
            cache(result.getInstance());
        }

        return result;
    }

    @Transactional
    public Result<Client> update(Client client) {
        Result<Client> result = super.update(client);
        if (result.accepted()) {
            cache(result.getInstance());
        }
        return result;
    }

    @Transactional
    public Result<Client> updateClientSecret(Client client, String newSecret) {
        PasswordPolicy policy = passwordPolicyService.findByName("client-password-policy").orThrow();

        Result<String> result = passwordValidator.validate(newSecret, policy);
        if (result.rejected()) {
            return Result.reject(result.getErrors().toArray(new Reportable[result.getErrors().size()]));
        }

        return update(client.clientSecret(passwordEncodingService.encode(newSecret)));
    }

    @Transactional
    public Result<Client> updateClientSecret(Client client, String currentSecret, String newSecret) {
        if (isBlank(currentSecret)) {
            return Result.reject("current.secret.required");
        }
        if (!passwordEncodingService.matches(currentSecret, client.getClientSecret())) {
            return Result.reject("current.secret.mismatch");
        }
        return updateClientSecret(client, newSecret);
    }

    @Transactional
    public Result<Client> delete(Client client) {
        Result<Client> result = super.delete(client);
        if (result.accepted()) {
            cache.delete(String.format(id_key, client.getId()));
            cache.delete(String.format(client_id_key, client.getClientId()));
        }
        return result;
    }

    @Transactional(readOnly = true)
    public Result<Client> findById(String id) {
        Client client = cache.get(String.format(id_key, id), Client.class);
        if (client != null) {
            return Result.accept(client);
        }

        Result<Client> result = super.findById(id, Client.class);
        if (result.accepted()) {
            cache(result.getInstance());
        }

        return result;
    }

    @Transactional(readOnly = true)
    public Result<Client> findByClientId(String clientId) {
        if (isBlank(clientId)) {
            return Result.reject("client.clientId.required");
        }

        Client client = cache.get(String.format(client_id_key, clientId), Client.class);
        if (client != null) {
            return Result.accept(client);
        }

        Result<Client> result = super.findBy("clientId", clientId, Client.class);
        if (result.accepted()) {
            cache(result.getInstance());
        }

        return result.accepted() ? result : Result.reject("client.clientId.not_found", clientId);
    }

    @Transactional(readOnly = true)
    public Result<List<Client>> list(Criteria criteria) {
        Long count = super.count(super.query("select count(client.id) from Clients client"));
        List<Client> clients = super.query("from Clients order by created desc")
                .setFirstResult(criteria.getFirstResult()).setMaxResults(criteria.getLimit()).getResultList();
        return Result.accept((List<Client>) new PaginatedList<Client>(clients, count.intValue(), criteria));
    }

    private void cache(Client client) {
        cache.put(String.format(id_key, client.getId()), client);
        cache.put(String.format(client_id_key, client.getClientId()), client);
    }

}