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