se.kth.csc.controller.ApiProviderImpl.java Source code

Java tutorial

Introduction

Here is the source code for se.kth.csc.controller.ApiProviderImpl.java

Source

package se.kth.csc.controller;

/*
 * #%L
 * QWait
 * %%
 * Copyright (C) 2013 - 2014 KTH School of Computer Science and Communication
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import se.kth.csc.model.Account;
import se.kth.csc.model.Queue;
import se.kth.csc.model.QueuePosition;
import se.kth.csc.payload.api.Snapshotters;
import se.kth.csc.payload.message.*;
import se.kth.csc.persist.AccountStore;
import se.kth.csc.persist.QueuePositionStore;
import se.kth.csc.persist.QueueStore;

import java.util.Iterator;

/**
 * An implementation of all the actions that can be performed via the API. These are collected into a single class to
 * make security easier to handle. All of the security lock-downs can happen in this single class.
 */
@Component
public class ApiProviderImpl implements ApiProvider {
    private final AccountStore accountStore;
    private final QueueStore queueStore;
    private final QueuePositionStore queuePositionStore;
    private final SimpMessagingTemplate messageBus;

    @Autowired
    public ApiProviderImpl(AccountStore accountStore, QueueStore queueStore, QueuePositionStore queuePositionStore,
            SimpMessagingTemplate messageBus) {
        this.accountStore = accountStore;
        this.queueStore = queueStore;
        this.queuePositionStore = queuePositionStore;
        this.messageBus = messageBus;
    }

    @Override
    @PreAuthorize("isAuthenticated()")
    public Iterable<Account> findAccounts(boolean onlyAdmin, String query) {
        return accountStore.findAccounts(onlyAdmin, query);
    }

    @Override
    public Account fetchAccount(String userName) throws NotFoundException {
        return accountStore.fetchAccountWithPrincipalName(userName);
    }

    @Override
    public Queue fetchQueue(String queueName) throws NotFoundException {
        return queueStore.fetchQueueWithName(queueName);
    }

    @Override
    public Iterable<Queue> fetchAllQueues() {
        return queueStore.fetchAllQueues();
    }

    @Override
    public QueuePosition fetchQueuePosition(String queueName, String userName) {
        return queuePositionStore.fetchQueuePositionWithQueueAndUser(queueName, userName);
    }

    @Override
    @PreAuthorize("hasRole('admin')")
    public void createQueue(String queueName, String title) {
        Queue queue = new Queue();
        queue.setName(queueName);
        queue.setTitle(title);
        queue.setHidden(false);
        queue.setLocked(false);
        queueStore.storeQueue(queue);

        messageBus.convertAndSend("/topic/queue", new QueueCreated(queueName));
    }

    @Override
    @PreAuthorize("hasRole('admin')")
    public void setAdmin(Account account, boolean admin) throws ForbiddenException {
        if (!admin && Iterables.size(findAccounts(true, null)) < 2) { // Trying to remove an admin and less than two admins left
            throw new ForbiddenException("Can not remove the last admin");
        } else {
            account.setAdmin(admin);

            messageBus.convertAndSend("/topic/user/" + account.getPrincipalName(),
                    new UserAdminStatusChanged(account.getPrincipalName(), admin));
        }
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name)")
    public void removeQueue(Queue queue) {
        QueueRemoved message = new QueueRemoved(queue.getName());

        for (Account owner : ImmutableSet.copyOf(queue.getOwners())) {
            removeOwner(queue, owner);
        }

        for (Account moderator : ImmutableSet.copyOf(queue.getModerators())) {
            removeModerator(queue, moderator);
        }

        for (QueuePosition queuePosition : queue.getPositions()) {
            removeQueuePosition(queuePosition);
        }

        queueStore.removeQueue(queue);

        messageBus.convertAndSend("/topic/queue", message);
    }

    @Override
    @PreAuthorize("!#queue.locked and !#queue.hidden and #account.principalName == authentication.name")
    public void addQueuePosition(Queue queue, Account account) {
        QueuePosition queuePosition = new QueuePosition();
        queuePosition.setQueue(queue);
        queuePosition.setAccount(account);
        queuePosition.setReadableName(account.getName());
        queuePosition.setStartTime(DateTime.now());

        queuePositionStore.storeQueuePosition(queuePosition);

        QueuePositionCreatedInQueue message1 = new QueuePositionCreatedInQueue(
                Snapshotters.QueuePositionInQueueSnapshotter.INSTANCE.apply(queuePosition), queue.getName());
        QueuePositionCreatedInAccount message2 = new QueuePositionCreatedInAccount(
                Snapshotters.QueuePositionInAccountSnapshotter.INSTANCE.apply(queuePosition),
                account.getPrincipalName());
        messageBus.convertAndSend("/topic/queue/" + queue.getName(), message1);
        messageBus.convertAndSend("/topic/user/" + account.getPrincipalName(), message2);
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queuePosition.queue.ownerNames.contains(authentication.name) or #queuePosition.queue.moderatorNames.contains(authentication.name) or #queuePosition.account.principalName == authentication.name")
    public void removeQueuePosition(QueuePosition queuePosition) {
        QueuePositionRemoved message = new QueuePositionRemoved(queuePosition.getQueue().getName(),
                queuePosition.getAccount().getPrincipalName());

        messageBus.convertAndSend("/topic/queue/" + queuePosition.getQueue().getName(), message);
        queuePosition.getQueue().getPositions().remove(queuePosition);
        messageBus.convertAndSend("/topic/user/" + queuePosition.getAccount().getPrincipalName(), message);
        queuePosition.getAccount().getPositions().remove(queuePosition);

        queuePositionStore.removeQueuePosition(queuePosition);
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queuePosition.account.principalName == authentication.name")
    public void setComment(QueuePosition queuePosition, String comment) throws BadRequestException {
        if (comment != null && comment.length() > 20) {
            throw new BadRequestException("Comment length cannot exceed 20 characters");
        } else {
            queuePosition.setComment(comment);
            QueuePositionCommentChanged message = new QueuePositionCommentChanged(
                    queuePosition.getQueue().getName(), queuePosition.getAccount().getPrincipalName(), comment);
            messageBus.convertAndSend("/topic/queue/" + queuePosition.getQueue().getName(), message);
            messageBus.convertAndSend("/topic/user/" + queuePosition.getAccount().getPrincipalName(), message);
        }
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queuePosition.account.principalName == authentication.name")
    public void setLocation(QueuePosition queuePosition, String location) throws BadRequestException {
        if (location != null && location.length() > 20) {
            throw new BadRequestException("Location length cannot exceed 20 characters");
        } else {
            queuePosition.setLocation(location);
            QueuePositionLocationChanged message = new QueuePositionLocationChanged(
                    queuePosition.getQueue().getName(), queuePosition.getAccount().getPrincipalName(), location);
            messageBus.convertAndSend("/topic/queue/" + queuePosition.getQueue().getName(), message);
            messageBus.convertAndSend("/topic/user/" + queuePosition.getAccount().getPrincipalName(), message);
        }
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name) or #queue.moderatorNames.contains(authentication.name)")
    public void clearQueue(Queue queue) {
        for (QueuePosition position : ImmutableSet.copyOf(queue.getPositions())) {
            removeQueuePosition(position);
        }
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name)")
    public void setHidden(Queue queue, boolean hidden) {
        queue.setHidden(hidden);
        setLocked(queue, hidden);
        if (hidden) {
            clearQueue(queue);
        }
        messageBus.convertAndSend("/topic/queue/" + queue.getName(),
                new QueueHiddenStatusChanged(queue.getName(), hidden));
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name) or #queue.moderatorNames.contains(authentication.name)")
    public void setLocked(Queue queue, boolean locked) {
        queue.setLocked(locked);

        messageBus.convertAndSend("/topic/queue/" + queue.getName(),
                new QueueLockedStatusChanged(queue.getName(), locked));
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name)")
    public void addOwner(Queue queue, Account owner) {
        queue.getOwners().add(owner);
        owner.getOwnedQueues().add(queue);

        QueueOwnerAdded message = new QueueOwnerAdded(queue.getName(), owner.getPrincipalName());
        messageBus.convertAndSend("/topic/queue/" + queue.getName(), message);
        messageBus.convertAndSend("/topic/user/" + owner.getPrincipalName(), message);
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name)")
    public void removeOwner(Queue queue, Account owner) {
        queue.getOwners().remove(owner);
        owner.getOwnedQueues().remove(queue);

        QueueOwnerRemoved message = new QueueOwnerRemoved(queue.getName(), owner.getPrincipalName());
        messageBus.convertAndSend("/topic/queue/" + queue.getName(), message);
        messageBus.convertAndSend("/topic/user/" + owner.getPrincipalName(), message);
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name)")
    public void addModerator(Queue queue, Account moderator) {
        queue.getModerators().add(moderator);
        moderator.getModeratedQueues().add(queue);

        QueueModeratorAdded message = new QueueModeratorAdded(queue.getName(), moderator.getPrincipalName());
        messageBus.convertAndSend("/topic/queue/" + queue.getName(), message);
        messageBus.convertAndSend("/topic/user/" + moderator.getPrincipalName(), message);
    }

    @Override
    @PreAuthorize("hasRole('admin') or #queue.ownerNames.contains(authentication.name)")
    public void removeModerator(Queue queue, Account moderator) {
        queue.getModerators().remove(moderator);
        moderator.getModeratedQueues().remove(queue);

        QueueModeratorRemoved message = new QueueModeratorRemoved(queue.getName(), moderator.getPrincipalName());
        messageBus.convertAndSend("/topic/queue/" + queue.getName(), message);
        messageBus.convertAndSend("/topic/user/" + moderator.getPrincipalName(), message);
    }
}