001/*******************************************************************************
002 * Copyright 2017 The MIT Internet Trust Consortium
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *******************************************************************************/
016
017package org.mitre.uma.service.impl;
018
019import java.util.Collection;
020
021import org.mitre.oauth2.model.ClientDetailsEntity;
022import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
023import org.mitre.oauth2.repository.OAuth2TokenRepository;
024import org.mitre.uma.model.PermissionTicket;
025import org.mitre.uma.model.Policy;
026import org.mitre.uma.model.ResourceSet;
027import org.mitre.uma.repository.PermissionRepository;
028import org.mitre.uma.repository.ResourceSetRepository;
029import org.mitre.uma.service.ResourceSetService;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032import org.springframework.beans.factory.annotation.Autowired;
033import org.springframework.context.annotation.Primary;
034import org.springframework.stereotype.Service;
035
036/**
037 * @author jricher
038 *
039 */
040@Service
041@Primary
042public class DefaultResourceSetService implements ResourceSetService {
043
044        private static final Logger logger = LoggerFactory.getLogger(DefaultResourceSetService.class);
045
046        @Autowired
047        private ResourceSetRepository repository;
048
049        @Autowired
050        private OAuth2TokenRepository tokenRepository;
051
052        @Autowired
053        private PermissionRepository ticketRepository;
054
055        @Override
056        public ResourceSet saveNew(ResourceSet rs) {
057
058                if (rs.getId() != null) {
059                        throw new IllegalArgumentException("Can't save a new resource set with an ID already set to it.");
060                }
061
062                if (!checkScopeConsistency(rs)) {
063                        throw new IllegalArgumentException("Can't save a resource set with inconsistent claims.");
064                }
065
066                ResourceSet saved = repository.save(rs);
067
068                return saved;
069
070        }
071
072        @Override
073        public ResourceSet getById(Long id) {
074                return repository.getById(id);
075        }
076
077        @Override
078        public ResourceSet update(ResourceSet oldRs, ResourceSet newRs) {
079
080                if (oldRs.getId() == null || newRs.getId() == null
081                                || !oldRs.getId().equals(newRs.getId())) {
082
083                        throw new IllegalArgumentException("Resource set IDs mismatched");
084
085                }
086
087                if (!checkScopeConsistency(newRs)) {
088                        throw new IllegalArgumentException("Can't save a resource set with inconsistent claims.");
089                }
090
091                newRs.setOwner(oldRs.getOwner()); // preserve the owner tag across updates
092                newRs.setClientId(oldRs.getClientId()); // preserve the client id across updates
093
094                ResourceSet saved = repository.save(newRs);
095
096                return saved;
097
098        }
099
100        @Override
101        public void remove(ResourceSet rs) {
102                // find all the access tokens issued against this resource set and revoke them
103                Collection<OAuth2AccessTokenEntity> tokens = tokenRepository.getAccessTokensForResourceSet(rs);
104                for (OAuth2AccessTokenEntity token : tokens) {
105                        tokenRepository.removeAccessToken(token);
106                }
107
108                // find all outstanding tickets issued against this resource set and revoke them too
109                Collection<PermissionTicket> tickets = ticketRepository.getPermissionTicketsForResourceSet(rs);
110                for (PermissionTicket ticket : tickets) {
111                        ticketRepository.remove(ticket);
112                }
113
114                repository.remove(rs);
115        }
116
117        @Override
118        public Collection<ResourceSet> getAllForOwner(String owner) {
119                return repository.getAllForOwner(owner);
120        }
121
122        @Override
123        public Collection<ResourceSet> getAllForOwnerAndClient(String owner, String clientId) {
124                return repository.getAllForOwnerAndClient(owner, clientId);
125        }
126
127        private boolean checkScopeConsistency(ResourceSet rs) {
128                if (rs.getPolicies() == null) {
129                        // nothing to check, no problem!
130                        return true;
131                }
132                for (Policy policy : rs.getPolicies()) {
133                        if (!rs.getScopes().containsAll(policy.getScopes())) {
134                                return false;
135                        }
136                }
137                // we've checked everything, we're good
138                return true;
139        }
140
141        /* (non-Javadoc)
142         * @see org.mitre.uma.service.ResourceSetService#getAllForClient(org.mitre.oauth2.model.ClientDetailsEntity)
143         */
144        @Override
145        public Collection<ResourceSet> getAllForClient(ClientDetailsEntity client) {
146                return repository.getAllForClient(client.getClientId());
147        }
148
149}