3f384f47724d49e90996f6e62f714cfa43e7167b
[controller.git] / opendaylight / northbound / usermanager / src / main / java / org / opendaylight / controller / usermanager / northbound / UserManagerNorthbound.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 package org.opendaylight.controller.usermanager.northbound;
9
10 import java.net.URI;
11
12 import javax.ws.rs.Consumes;
13 import javax.ws.rs.DELETE;
14 import javax.ws.rs.POST;
15 import javax.ws.rs.Path;
16 import javax.ws.rs.PathParam;
17 import javax.ws.rs.core.Context;
18 import javax.ws.rs.core.MediaType;
19 import javax.ws.rs.core.Response;
20 import javax.ws.rs.core.SecurityContext;
21 import javax.ws.rs.core.UriInfo;
22
23 import org.codehaus.enunciate.jaxrs.ResponseCode;
24 import org.codehaus.enunciate.jaxrs.StatusCodes;
25 import org.codehaus.enunciate.jaxrs.TypeHint;
26 import org.opendaylight.controller.northbound.commons.RestMessages;
27 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
28 import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
29 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
30 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
31 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
32 import org.opendaylight.controller.sal.authorization.UserLevel;
33 import org.opendaylight.controller.sal.utils.ServiceHelper;
34 import org.opendaylight.controller.sal.utils.Status;
35 import org.opendaylight.controller.usermanager.IUserManager;
36 import org.opendaylight.controller.usermanager.UserConfig;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * This class provides REST APIs to manage users.
42  * This API will only be availalbe via HTTPS.
43  * <br>
44  * <br>
45  * Authentication scheme : <b>HTTP Basic</b><br>
46  * Authentication realm : <b>opendaylight</b><br>
47  * Transport : <b> HTTPS </b><br>
48  * <br>
49  * HTTPS Authentication is disabled by default so to
50  * use UserManager APIs turn on HTTPS on Web Server
51  */
52
53 @Path("/")
54 public class UserManagerNorthbound {
55
56     protected static final Logger logger = LoggerFactory.getLogger(UserManagerNorthbound.class);
57
58     private String username;
59     @Context
60     UriInfo uriInfo;
61
62     @Context
63     public void setSecurityContext(SecurityContext context) {
64         if (context != null && context.getUserPrincipal() != null) {
65             username = context.getUserPrincipal().getName();
66         }
67     }
68
69     protected String getUserName() {
70         return username;
71     }
72
73     private void handleNameMismatch(String name, String nameinURL) {
74         if (name == null || nameinURL == null) {
75             throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : Name is null");
76         }
77
78         if (name.equals(nameinURL)) {
79             return;
80         }
81         throw new ResourceConflictException(RestMessages.INVALIDDATA.toString()
82                 + " : Name in URL does not match the name in request body");
83     }
84
85     /**
86      * Add a user
87      *
88      * @param userConfigData
89      *            the {@link UserConfig} user config structure in request body
90      *
91      * @return Response as dictated by the HTTP Response Status code
92      *
93      *         <pre>
94      * Example:
95      *
96      * Request URL:
97      * https://localhost/controller/nb/v2/usermanager/users
98      *
99      * Request body in XML:
100      *  &lt;userConfig&gt;
101      *      &lt;user&gt;testuser&lt;/user&gt;
102      *      &lt;roles&gt;Network-Admin&lt;/roles&gt;
103      *      &lt;password&gt;pass!23&lt;/password&gt;
104      *  &lt;/userConfig&gt;
105      *
106      * Request body in JSON:
107      * {
108      *  "user":"testuser",
109      *  "password":"pass!23",
110      *  "roles":[
111      *       "Network-Admin"
112      *       ]
113      * }
114      * </pre>
115      */
116
117     @Path("/users")
118     @POST
119     @StatusCodes({ @ResponseCode(code = 201, condition = "User created successfully"),
120         @ResponseCode(code = 400, condition = "Invalid data passed"),
121         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
122         @ResponseCode(code = 409, condition = "User name in url conflicts with name in request body"),
123         @ResponseCode(code = 404, condition = "User config is null"),
124         @ResponseCode(code = 500, condition = "Internal Server Error: Addition of user failed"),
125         @ResponseCode(code = 503, condition = "Service unavailable") })
126     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
127     public Response addLocalUser(@TypeHint(UserConfig.class) UserConfig userConfigData) {
128
129         if (!isAdminUser()) {
130             throw new UnauthorizedException("User is not authorized to perform user management operations ");
131         }
132
133         // Reconstructing the object so password can be hashed in userConfig
134         UserConfig userCfgObject = new UserConfig(userConfigData.getUser(),userConfigData.getPassword(),
135                  userConfigData.getRoles());
136
137         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
138         if (userManager == null) {
139             throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
140         }
141         Status status = userManager.addLocalUser(userCfgObject);
142         if (status.isSuccess()) {
143
144             NorthboundUtils.auditlog("User", username, "added", userCfgObject.getUser());
145             URI uri = uriInfo.getAbsolutePathBuilder().path("/"+userCfgObject.getUser()).build();
146             return Response.created(uri).build();
147         }
148         return NorthboundUtils.getResponse(status);
149     }
150
151     /**
152      * Delete a user
153      *
154      * @param userName
155      *            name of user to be deleted
156      * @return Response as dictated by the HTTP Response Status code
157      *
158      * <pre>
159      * Example:
160      *
161      * Request URL:
162      * https://localhost/controller/nb/v2/usermanager/users/testuser
163      *
164      * </pre>
165      */
166     @Path("/users/{userName}")
167     @DELETE
168     @StatusCodes({ @ResponseCode(code = 204, condition = "User Deleted Successfully"),
169         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
170         @ResponseCode(code = 404, condition = "The userName passed was not found"),
171         @ResponseCode(code = 500, condition = "Internal Server Error : Removal of user failed"),
172         @ResponseCode(code = 503, condition = "Service unavailable") })
173     public Response removeLocalUser(@PathParam("userName") String userToBeRemoved) {
174
175         if (!isAdminUser()) {
176             throw new UnauthorizedException("User is not authorized to perform user management operations ");
177         }
178
179         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
180         if (userManager == null) {
181             throw new ServiceUnavailableException("UserManager " + RestMessages.SERVICEUNAVAILABLE.toString());
182         }
183         Status status = userManager.removeLocalUser(userToBeRemoved);
184         if (status.isSuccess()) {
185             NorthboundUtils.auditlog("User", username, "removed", userToBeRemoved);
186             return Response.noContent().build();
187         }
188         return NorthboundUtils.getResponse(status);
189     }
190
191     private boolean isAdminUser(){
192         // get UserManager's instance
193         IUserManager auth = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
194         // check if logged in user has privileges of NETWORK_ADMIN or SYSTEM_ADMIN, if so return true
195         return auth.getUserLevel(getUserName()).ordinal() <= UserLevel.NETWORKADMIN.ordinal();
196     }
197
198 }