001/*******************************************************************************
002 * Copyright 2017 The MIT Internet Trust Consortium
003 *
004 * Portions copyright 2011-2013 The MITRE Corporation
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 *******************************************************************************/
018/**
019 *
020 */
021package org.mitre.oauth2.web;
022
023import java.util.Set;
024
025import org.mitre.oauth2.model.SystemScope;
026import org.mitre.oauth2.service.SystemScopeService;
027import org.mitre.openid.connect.view.HttpCodeView;
028import org.mitre.openid.connect.view.JsonEntityView;
029import org.mitre.openid.connect.view.JsonErrorView;
030import org.mitre.openid.connect.web.RootController;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033import org.springframework.beans.factory.annotation.Autowired;
034import org.springframework.http.HttpStatus;
035import org.springframework.http.MediaType;
036import org.springframework.security.access.prepost.PreAuthorize;
037import org.springframework.stereotype.Controller;
038import org.springframework.ui.ModelMap;
039import org.springframework.web.bind.annotation.PathVariable;
040import org.springframework.web.bind.annotation.RequestBody;
041import org.springframework.web.bind.annotation.RequestMapping;
042import org.springframework.web.bind.annotation.RequestMethod;
043
044import com.google.gson.Gson;
045
046/**
047 * @author jricher
048 *
049 */
050@Controller
051@RequestMapping("/" + ScopeAPI.URL)
052@PreAuthorize("hasRole('ROLE_USER')")
053public class ScopeAPI {
054
055        public static final String URL = RootController.API_URL + "/scopes";
056
057        @Autowired
058        private SystemScopeService scopeService;
059
060        /**
061         * Logger for this class
062         */
063        private static final Logger logger = LoggerFactory.getLogger(ScopeAPI.class);
064
065        private Gson gson = new Gson();
066
067        @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
068        public String getAll(ModelMap m) {
069
070                Set<SystemScope> allScopes = scopeService.getAll();
071
072                m.put(JsonEntityView.ENTITY, allScopes);
073
074                return JsonEntityView.VIEWNAME;
075        }
076
077        @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
078        public String getScope(@PathVariable("id") Long id, ModelMap m) {
079
080                SystemScope scope = scopeService.getById(id);
081
082                if (scope != null) {
083
084                        m.put(JsonEntityView.ENTITY, scope);
085
086                        return JsonEntityView.VIEWNAME;
087                } else {
088
089                        logger.error("getScope failed; scope not found: " + id);
090
091                        m.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
092                        m.put(JsonErrorView.ERROR_MESSAGE, "The requested scope with id " + id + " could not be found.");
093                        return JsonErrorView.VIEWNAME;
094                }
095        }
096
097        @PreAuthorize("hasRole('ROLE_ADMIN')")
098        @RequestMapping(value = "/{id}", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
099        public String updateScope(@PathVariable("id") Long id, @RequestBody String json, ModelMap m) {
100
101                SystemScope existing = scopeService.getById(id);
102
103                SystemScope scope = gson.fromJson(json, SystemScope.class);
104
105                if (existing != null && scope != null) {
106
107                        if (existing.getId().equals(scope.getId())) {
108                                // sanity check
109
110                                scope = scopeService.save(scope);
111
112                                m.put(JsonEntityView.ENTITY, scope);
113
114                                return JsonEntityView.VIEWNAME;
115                        } else {
116
117                                logger.error("updateScope failed; scope ids to not match: got "
118                                                + existing.getId() + " and " + scope.getId());
119
120                                m.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
121                                m.put(JsonErrorView.ERROR_MESSAGE, "Could not update scope. Scope ids to not match: got "
122                                                + existing.getId() + " and " + scope.getId());
123                                return JsonErrorView.VIEWNAME;
124                        }
125
126                } else {
127
128                        logger.error("updateScope failed; scope with id " + id + " not found.");
129                        m.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
130                        m.put(JsonErrorView.ERROR_MESSAGE, "Could not update scope. The scope with id " + id + " could not be found.");
131                        return JsonErrorView.VIEWNAME;
132                }
133        }
134
135        @PreAuthorize("hasRole('ROLE_ADMIN')")
136        @RequestMapping(value = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
137        public String createScope(@RequestBody String json, ModelMap m) {
138                SystemScope scope = gson.fromJson(json, SystemScope.class);
139
140                SystemScope alreadyExists = scopeService.getByValue(scope.getValue());
141                if (alreadyExists != null) {
142                        //Error, cannot save a scope with the same value as an existing one
143                        logger.error("Error: attempting to save a scope with a value that already exists: " + scope.getValue());
144                        m.put(HttpCodeView.CODE, HttpStatus.CONFLICT);
145                        m.put(JsonErrorView.ERROR_MESSAGE, "A scope with value " + scope.getValue() + " already exists, please choose a different value.");
146                        return JsonErrorView.VIEWNAME;
147                }
148
149                scope = scopeService.save(scope);
150
151                if (scope != null && scope.getId() != null) {
152
153                        m.put(JsonEntityView.ENTITY, scope);
154
155                        return JsonEntityView.VIEWNAME;
156                } else {
157
158                        logger.error("createScope failed; JSON was invalid: " + json);
159                        m.put(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
160                        m.put(JsonErrorView.ERROR_MESSAGE, "Could not save new scope " + scope + ". The scope service failed to return a saved entity.");
161                        return JsonErrorView.VIEWNAME;
162
163                }
164        }
165
166        @PreAuthorize("hasRole('ROLE_ADMIN')")
167        @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
168        public String deleteScope(@PathVariable("id") Long id, ModelMap m) {
169                SystemScope existing = scopeService.getById(id);
170
171                if (existing != null) {
172
173                        scopeService.remove(existing);
174
175                        return HttpCodeView.VIEWNAME;
176                } else {
177
178                        logger.error("deleteScope failed; scope with id " + id + " not found.");
179                        m.put(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
180                        m.put(JsonErrorView.ERROR_MESSAGE, "Could not delete scope. The requested scope with id " + id + " could not be found.");
181                        return JsonErrorView.VIEWNAME;
182                }
183        }
184}