Authorization fixes for Northbound bundles
[controller.git] / opendaylight / northbound / topology / src / main / java / org / opendaylight / controller / topology / northbound / TopologyNorthboundJAXRS.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.topology.northbound;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15 import java.util.concurrent.ConcurrentMap;
16
17 import javax.ws.rs.Consumes;
18 import javax.ws.rs.DELETE;
19 import javax.ws.rs.GET;
20 import javax.ws.rs.POST;
21 import javax.ws.rs.Path;
22 import javax.ws.rs.PathParam;
23 import javax.ws.rs.Produces;
24 import javax.ws.rs.core.Context;
25 import javax.ws.rs.core.MediaType;
26 import javax.ws.rs.core.Response;
27 import javax.ws.rs.core.SecurityContext;
28 import javax.xml.bind.JAXBElement;
29
30 import org.codehaus.enunciate.jaxrs.ResponseCode;
31 import org.codehaus.enunciate.jaxrs.StatusCodes;
32 import org.codehaus.enunciate.jaxrs.TypeHint;
33 import org.opendaylight.controller.northbound.commons.RestMessages;
34 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
35 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
36 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
37 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
38 import org.opendaylight.controller.sal.authorization.Privilege;
39 import org.opendaylight.controller.sal.core.Edge;
40 import org.opendaylight.controller.sal.core.Property;
41 import org.opendaylight.controller.sal.utils.ServiceHelper;
42 import org.opendaylight.controller.sal.utils.Status;
43 import org.opendaylight.controller.topologymanager.ITopologyManager;
44 import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
45
46 /**
47  * Topology Northbound REST API
48  * 
49  * <br>
50  * <br>
51  * Authentication scheme : <b>HTTP Basic</b><br>
52  * Authentication realm : <b>opendaylight</b><br>
53  * Transport : <b>HTTP and HTTPS</b><br>
54  * <br>
55  * HTTPS Authentication is disabled by default. Administrator can enable it in
56  * tomcat-server.xml after adding a proper keystore / SSL certificate from a
57  * trusted authority.<br>
58  * More info :
59  * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
60  */
61
62 @Path("/")
63 public class TopologyNorthboundJAXRS {
64
65     private String username;
66
67     @Context
68     public void setSecurityContext(SecurityContext context) {
69         username = context.getUserPrincipal().getName();
70     }
71
72     protected String getUserName() {
73         return username;
74     }
75
76     /**
77      * 
78      * Retrieve the Topology
79      * 
80      * @param containerName
81      *            The container for which we want to retrieve the topology
82      * 
83      * @return A List of EdgeProps each EdgeProp represent an Edge of the grap
84      *         with the corresponding properties attached to it.
85      */
86     @Path("/{containerName}")
87     @GET
88     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
89     @TypeHint(Topology.class)
90     @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name passed was not found") })
91     public Topology getTopology(@PathParam("containerName") String containerName) {
92
93         if (!NorthboundUtils.isAuthorized(
94                 getUserName(), containerName, Privilege.READ, this)) {
95             throw new UnauthorizedException(
96                     "User is not authorized to perform this operation on container "
97                             + containerName);
98         }
99         ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
100                 .getInstance(ITopologyManager.class, containerName, this);
101         if (topologyManager == null) {
102             throw new ResourceNotFoundException(
103                     RestMessages.NOCONTAINER.toString());
104         }
105
106         Map<Edge, Set<Property>> topo = topologyManager.getEdges();
107         if (topo != null) {
108             List<EdgeProperties> res = new ArrayList<EdgeProperties>();
109             for (Map.Entry<Edge, Set<Property>> entry : topo.entrySet()) {
110                 EdgeProperties el = new EdgeProperties(entry.getKey(),
111                         entry.getValue());
112                 res.add(el);
113             }
114             return new Topology(res);
115         }
116
117         return null;
118     }
119
120     /**
121      * Retrieve the user configured links
122      * 
123      * @param containerName
124      *            The container for which we want to retrieve the user links
125      * 
126      * @return A List of user configured links
127      */
128     @Path("/{containerName}/userLink")
129     @GET
130     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
131     @TypeHint(TopologyUserLinks.class)
132     @StatusCodes({ @ResponseCode(code = 404, condition = "The Container Name passed was not found") })
133     public TopologyUserLinks getUserLinks(
134             @PathParam("containerName") String containerName) {
135
136         if (!NorthboundUtils.isAuthorized(
137                 getUserName(), containerName, Privilege.READ, this)) {
138             throw new UnauthorizedException(
139                     "User is not authorized to perform this operation on container "
140                             + containerName);
141         }
142         ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
143                 .getInstance(ITopologyManager.class, containerName, this);
144         if (topologyManager == null) {
145             throw new ResourceNotFoundException(
146                     RestMessages.NOCONTAINER.toString());
147         }
148
149         ConcurrentMap<String, TopologyUserLinkConfig> userLinks = topologyManager
150                 .getUserLinks();
151         if ((userLinks != null) && (userLinks.values() != null)) {
152             List<TopologyUserLinkConfig> res = new ArrayList<TopologyUserLinkConfig>(
153                     userLinks.values());
154             return new TopologyUserLinks(res);
155         }
156
157         return null;
158     }
159
160     /**
161      * Add an User Link
162      * 
163      * @param containerName
164      *            Name of the Container. The base Container is "default".
165      * @param TopologyUserLinkConfig
166      *            in JSON or XML format
167      * @return Response as dictated by the HTTP Response Status code
168      */
169
170     @Path("/{containerName}/userLink")
171     @POST
172     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
173     @StatusCodes({
174             @ResponseCode(code = 201, condition = "User Link added successfully"),
175             @ResponseCode(code = 404, condition = "The Container Name passed was not found"),
176             @ResponseCode(code = 409, condition = "Failed to add User Link due to Conflicting Name"),
177             @ResponseCode(code = 500, condition = "Failed to add User Link. Failure Reason included in HTTP Error response"),
178             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
179     public Response addUserLink(
180             @PathParam(value = "containerName") String containerName,
181             @TypeHint(TopologyUserLinkConfig.class) JAXBElement<TopologyUserLinkConfig> userLinkConfig) {
182
183         if (!NorthboundUtils.isAuthorized(
184                 getUserName(), containerName, Privilege.WRITE, this)) {
185             throw new UnauthorizedException(
186                     "User is not authorized to perform this operation on container "
187                             + containerName);
188         }
189         ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
190                 .getInstance(ITopologyManager.class, containerName, this);
191         if (topologyManager == null) {
192             throw new ResourceNotFoundException(
193                     RestMessages.NOCONTAINER.toString());
194         }
195
196         Status status = topologyManager.addUserLink(userLinkConfig.getValue());
197         if (status.isSuccess()) {
198             return Response.status(Response.Status.CREATED).build();
199         }
200         throw new InternalServerErrorException(status.getDescription());
201     }
202
203     /**
204      * Delete an User Link
205      * 
206      * @param containerName
207      *            Name of the Container. The base Container is "default".
208      * @param name
209      *            Name of the Link Configuration
210      * @return Response as dictated by the HTTP Response Status code
211      */
212
213     @Path("/{containerName}/userLink/{name}")
214     @DELETE
215     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
216     @StatusCodes({
217             @ResponseCode(code = 200, condition = "Operation successful"),
218             @ResponseCode(code = 404, condition = "The Container Name or Link Configuration Name was not found"),
219             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
220     public Response deleteUserLink(
221             @PathParam("containerName") String containerName,
222             @PathParam("name") String name) {
223
224         if (!NorthboundUtils.isAuthorized(
225                 getUserName(), containerName, Privilege.WRITE, this)) {
226             throw new UnauthorizedException(
227                     "User is not authorized to perform this operation on container "
228                             + containerName);
229         }
230         ITopologyManager topologyManager = (ITopologyManager) ServiceHelper
231                 .getInstance(ITopologyManager.class, containerName, this);
232         if (topologyManager == null) {
233             throw new ResourceNotFoundException(
234                     RestMessages.NOCONTAINER.toString());
235         }
236
237         Status ret = topologyManager.deleteUserLink(name);
238         if (ret.isSuccess()) {
239             return Response.ok().build();
240         }
241         throw new ResourceNotFoundException(ret.getDescription());
242     }
243
244 }