Newer
Older
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com

srosse
committed
import static org.olat.restapi.security.RestSecurityHelper.getIdentity;
import static org.olat.restapi.security.RestSecurityHelper.getLocale;
import static org.olat.restapi.security.RestSecurityHelper.getUserRequest;
import static org.olat.restapi.security.RestSecurityHelper.isUserManager;
import static org.olat.user.restapi.UserVOFactory.formatDbUserProperty;
import static org.olat.user.restapi.UserVOFactory.get;

srosse
committed
import static org.olat.user.restapi.UserVOFactory.getManaged;
import static org.olat.user.restapi.UserVOFactory.parseUserProperty;
import static org.olat.user.restapi.UserVOFactory.post;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

srosse
committed
import javax.ws.rs.core.UriInfo;
import org.olat.admin.user.delete.service.UserDeletionManager;
import org.olat.basesecurity.Authentication;
import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.BaseSecurityManager;
import org.olat.basesecurity.IdentityShort;

srosse
committed
import org.olat.basesecurity.SearchIdentityParams;
import org.olat.core.gui.components.form.ValidationError;
import org.olat.core.gui.translator.PackageTranslator;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.id.Preferences;
import org.olat.core.id.Roles;
import org.olat.core.id.User;
import org.olat.core.id.UserConstants;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;

srosse
committed
import org.olat.restapi.group.MyGroupWebService;
import org.olat.restapi.support.MultipartReader;
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import org.olat.restapi.support.vo.ErrorVO;
import org.olat.user.DisplayPortraitManager;
import org.olat.user.UserManager;
import org.olat.user.propertyhandlers.UserPropertyHandler;
/**
* This web service handles functionalities related to <code>User</code>.
*
* @author srosse, stephane.rosse@frentix.com
*/
@Path("users")
public class UserWebService {
private static final OLog log = Tracing.createLoggerFor(UserWebService.class);
private static final String VERSION = "1.0";
public static final String PROPERTY_HANDLER_IDENTIFIER = UserWebService.class.getName();
public static CacheControl cc = new CacheControl();
static {
cc.setMaxAge(-1);
}
/**
* The version of the User Web Service
* @response.representation.200.mediaType text/plain
* @response.representation.200.doc The version of this specific Web Service
* @response.representation.200.example 1.0
* @return The version number
*/
@GET
@Path("version")
@Produces(MediaType.TEXT_PLAIN)
public Response getVersion() {
return Response.ok(VERSION).build();
}
/**
* Search users and return them in a simple form (without user properties). User properties
* can be added two the query parameters. If the authUsername and the authProvider are set,
* the search is made only with these two parameters because they are sufficient to return
* a single user.<br>
* The search with login and user properties are made default with wild cards. If an exact
* match is needed, the parameter msut be quoted:<br>
* users?login="username"<br>
* Don't forget the right escaping in the URL!<br>
* You can make a search with the user properties like this:<br>
* users?telMobile=39847592&login=test
*
* @response.representation.200.qname {http://www.example.com}userVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The list of all users in the OLAT system
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVOes}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @param login The login (search with like)
* @param authProvider An authentication provider (optional)
* @param authUsername An specific username from the authentication provider
* @param uriInfo The URI infos
* @param httpRequest The HTTP request
* @return An array of users
*/
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getUserListQuery(@QueryParam("login") String login,
@QueryParam("authProvider") String authProvider, @QueryParam("authUsername") String authUsername,
@QueryParam("statusVisibleLimit") String statusVisibleLimit,
@Context UriInfo uriInfo, @Context HttpServletRequest httpRequest) {
if(!isUserManager(httpRequest)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
MultivaluedMap<String,String> params = uriInfo.getQueryParameters();
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
List<Identity> identities;
//make only a search by authUsername
if(StringHelper.containsNonWhitespace(authProvider) && StringHelper.containsNonWhitespace(authUsername)) {
Authentication auth =BaseSecurityManager.getInstance().findAuthenticationByAuthusername(authUsername, authProvider);
if(auth == null) {
identities = Collections.emptyList();
} else {
identities = Collections.singletonList(auth.getIdentity());
}
} else {
String[] authProviders = null;
if(StringHelper.containsNonWhitespace(authProvider)) {
authProviders = new String[]{authProvider};
}
//retrieve and convert the parameters value
Map<String,String> userProps = new HashMap<String,String>();
if(!params.isEmpty()) {
UserManager um = UserManager.getInstance();
Locale locale = getLocale(httpRequest);
List<UserPropertyHandler> propertyHandlers = um.getUserPropertyHandlersFor(PROPERTY_HANDLER_IDENTIFIER, false);
for(UserPropertyHandler handler:propertyHandlers) {
if(!params.containsKey(handler.getName())) continue;
List<String> values = params.get(handler.getName());
if(values.isEmpty()) continue;
String value = formatDbUserProperty(values.get(0), handler, locale);
userProps.put(handler.getName(), value);
}
}
Integer status = Identity.STATUS_VISIBLE_LIMIT;
if("all".equalsIgnoreCase(statusVisibleLimit)) {
status = null;
}
identities = BaseSecurityManager.getInstance().getIdentitiesByPowerSearch(login, userProps, true, null, null, authProviders, null, null, null, null, status);
}
int count = 0;
UserVO[] userVOs = new UserVO[identities.size()];
for(Identity identity:identities) {
userVOs[count++] = get(identity);
}
return Response.ok(userVOs).build();
}

srosse
committed
@GET
@Path("managed")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getManagedUsers(@Context HttpServletRequest httpRequest) {
if(!isUserManager(httpRequest)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
SearchIdentityParams params = new SearchIdentityParams();
params.setManaged(Boolean.TRUE);
List<Identity> identities = BaseSecurityManager.getInstance().getIdentitiesByPowerSearch(params, 0, -1);
int count = 0;
ManagedUserVO[] userVOs = new ManagedUserVO[identities.size()];
for(Identity identity:identities) {
userVOs[count++] = getManaged(identity);
}
return Response.ok(userVOs).build();
}
/**
* Creates and persists a new user entity
* @response.representation.qname {http://www.example.com}userVO
* @response.representation.mediaType application/xml, application/json
* @response.representation.doc The user to persist

srosse
committed
* @response.representation.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO}
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The persisted user

srosse
committed
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.406.mediaType application/xml, application/json
* @response.representation.406.doc The list of errors

srosse
committed
* @response.representation.406.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_ERRORVOes}
* @param user The user to persist
* @param request The HTTP request
* @return the new persisted <code>User</code>
*/
@PUT
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response create(UserVO user, @Context HttpServletRequest request) {
if(!isUserManager(request)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
// Check if login is still available
Identity identity = BaseSecurityManager.getInstance().findIdentityByName(user.getLogin());
if (identity != null) {
Locale locale = getLocale(request);
Translator translator = Util.createPackageTranslator(UserShortDescription.class, locale);
String translation = translator.translate("new.error.loginname.choosen");
ErrorVO[] errorVos = new ErrorVO[]{
new ErrorVO("org.olat.admin.user", "new.error.loginname.choosen", translation)
};
return Response.ok(errorVos).status(Status.NOT_ACCEPTABLE).build();
}

srosse
committed
List<ErrorVO> errors = validateUser(null, user, request);
if(errors.isEmpty()) {
User newUser = UserManager.getInstance().createUser(user.getFirstName(), user.getLastName(), user.getEmail());
Identity id = BaseSecurityManager.getInstance().createAndPersistIdentityAndUserWithDefaultProviderAndUserGroup(user.getLogin(), user.getExternalId(), user.getPassword(), newUser);
post(newUser, user, getLocale(request));
UserManager.getInstance().updateUser(newUser);
return Response.ok(get(id)).build();
}
//content not ok
ErrorVO[] errorVos = new ErrorVO[errors.size()];
errors.toArray(errorVos);
return Response.ok(errorVos).status(Status.NOT_ACCEPTABLE).build();
}
/**
* Retrieves the roles of a user given its unique key identifier
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_ROLESVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param httpRequest The HTTP request
* @return an xml or json representation of a the roles being search.
@GET
@Path("{identityKey}/roles")
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response getRoles(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
try {
boolean isUserManager = isUserManager(request);
if(!isUserManager) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
Roles roles = BaseSecurityManager.getInstance().getRoles(identity);
return Response.ok(new RolesVO(roles)).build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}
/**
* Update the roles of a user given its unique key identifier
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_ROLESVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param roles The updated roles
* @param httpRequest The HTTP request
* @return an xml or json representation of a the roles being search.
*/
@Path("{identityKey}/roles")
@Consumes({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response updateRoles(@PathParam("identityKey") Long identityKey, RolesVO roles, @Context HttpServletRequest request) {
try {
boolean isUserManager = isUserManager(request);
if(!isUserManager) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
Roles modRoles = roles.toRoles();
Identity actingIdentity = getIdentity(request);
BaseSecurityManager.getInstance().updateRoles(actingIdentity, identity, modRoles);
return Response.ok(new RolesVO(modRoles)).build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}

srosse
committed
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
/**
* Retrieves the status of a user given its unique key identifier
* @response.representation.qname {http://www.example.com}statusVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_STATUSVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param httpRequest The HTTP request
* @return an xml or json representation of a the status being search.
*/
@GET
@Path("{identityKey}/status")
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response getStatus(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
try {
boolean isUserManager = isUserManager(request);
if(!isUserManager) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
StatusVO status = new StatusVO();
status.setStatus(identity.getStatus());
return Response.ok(status).build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}
/**
* Update the roles of a user given its unique key identifier:
* <ul>
* <li>1: Permanent user</li>
* <li>2: activ</li>
* <li>101: login denied</li>
* <li>199: deleted</li>
* </ul>
*
* @response.representation.qname {http://www.example.com}statusVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_ROLESVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param status The status to update
* @param httpRequest The HTTP request
* @return An xml or json representation of a the status after update.
*/
@POST
@Path("{identityKey}/status")
@Consumes({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response updateStatus(@PathParam("identityKey") Long identityKey, StatusVO status, @Context HttpServletRequest request) {
try {
boolean isUserManager = isUserManager(request);
if(!isUserManager) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
Integer newStatus = status.getStatus();
identity = BaseSecurityManager.getInstance().saveIdentityStatus(identity, newStatus);
StatusVO reloadedStatus = new StatusVO();
reloadedStatus.setStatus(identity.getStatus());
return Response.ok(reloadedStatus).build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
/**
* Retrieves the preferences of a user given its unique key identifier
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The preferences
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_PREFERENCESVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param httpRequest The HTTP request
* @return an xml or json representation of a the roles being search.
*/
@GET
@Path("{identityKey}/preferences")
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response getUserPreferences(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
boolean isUserManager = isUserManager(request);
if(!isUserManager) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
Preferences prefs = identity.getUser().getPreferences();
return Response.ok(new PreferencesVO(prefs)).build();
}
/**
* Update the preferences of a user given its unique key identifier
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_PREFERENCESVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param preferences The updated preferences
* @param httpRequest The HTTP request
* @return an xml or json representation of a the roles being search.
*/
@POST
@Path("{identityKey}/preferences")
@Consumes({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response updatePreferences(@PathParam("identityKey") Long identityKey, PreferencesVO preferences, @Context HttpServletRequest request) {
try {
boolean isUserManager = isUserManager(request);
if(!isUserManager) {
return Response.serverError().status(Status.FORBIDDEN).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
Preferences prefs = identity.getUser().getPreferences();
prefs.setLanguage(preferences.getLanguage());
UserManager.getInstance().updateUserFromIdentity(identity);
return Response.ok(new PreferencesVO(prefs)).build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}
/**
* Retrieves an user given its unique key identifier
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier of the user being searched
* @param withPortrait If true return the portrait as Base64 (default false)
* @param httpRequest The HTTP request
* @return an xml or json representation of a the user being search. The xml
* correspond to a <code>UserVO</code>. <code>UserVO</code> is a
* simplified representation of the <code>User</code> and <code>Identity</code>
*/
@GET
@Path("{identityKey}")
@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
public Response findById(@PathParam("identityKey") Long identityKey, @QueryParam("withPortrait") @DefaultValue("false") Boolean withPortrait,
@Context HttpServletRequest httpRequest) {
try {
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
boolean isUserManager = isUserManager(httpRequest);
UserVO userVO = get(identity, null, true, isUserManager, withPortrait);
return Response.ok(userVO).build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}

srosse
committed
@Path("{identityKey}/folders")
public UserFoldersWebService getFoldersWebService(@PathParam("identityKey") Long identityKey) {
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
throw new WebApplicationException(Response.serverError().status(Status.NOT_FOUND).build());
}
return new UserFoldersWebService(identity);
}
@Path("{identityKey}/courses")
public UserCoursesWebService getCoursesWebService(@PathParam("identityKey") Long identityKey,
@Context HttpServletRequest httpRequest) {
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
throw new WebApplicationException(Response.serverError().status(Status.NOT_FOUND).build());
}
Identity ureqIdentity = getIdentity(httpRequest);
if(ureqIdentity == null || !ureqIdentity.equals(identity)) {
throw new WebApplicationException(Response.serverError().status(Status.UNAUTHORIZED).build());
}
return new UserCoursesWebService(identity);
}
/**
* Retrieves the portrait of an user
* @response.representation.200.mediaType application/octet-stream
* @response.representation.200.doc The portrait as image
* @response.representation.404.doc The identity or the portrait not found
* @param identityKey The identity key of the user being searched
* @param request The REST request
* @return The image
*/
@GET
@Path("{identityKey}/portrait")
@Produces({"image/jpeg","image/jpg",MediaType.APPLICATION_OCTET_STREAM})
public Response getPortrait(@PathParam("identityKey") Long identityKey, @Context Request request) {
try {
IdentityShort identity = BaseSecurityManager.getInstance().loadIdentityShortByKey(identityKey);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
File portrait = DisplayPortraitManager.getInstance().getBigPortrait(identity.getName());
if(portrait == null || !portrait.exists()) {
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
return Response.serverError().status(Status.NOT_FOUND).build();
}
Date lastModified = new Date(portrait.lastModified());
Response.ResponseBuilder response = request.evaluatePreconditions(lastModified);
if(response == null) {
response = Response.ok(portrait).lastModified(lastModified).cacheControl(cc);
}
return response.build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}
/**
* Upload the portrait of an user
* @response.representation.200.mediaType application/octet-stream
* @response.representation.200.doc The portrait as image
* @response.representation.401.doc Not authorized
* @response.representation.404.doc The identity or the portrait not found
* @param identityKey The user key identifier of the user being searched
* @param file The image
* @param request The REST request
* @return The image
*/
@POST
@Path("{identityKey}/portrait")
@Consumes({MediaType.MULTIPART_FORM_DATA})
public Response postPortrait(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
MultipartReader partsReader = null;
IdentityShort identity = BaseSecurityManager.getInstance().loadIdentityShortByKey(identityKey);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
Identity authIdentity = getUserRequest(request).getIdentity();
if(!isUserManager(request) && !identity.getKey().equals(authIdentity.getKey())) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
partsReader = new MultipartReader(request);
File tmpFile = partsReader.getFile();
String filename = partsReader.getFilename();
DisplayPortraitManager.getInstance().setPortrait(tmpFile, filename, identity.getName());
return Response.ok().build();
} catch (Throwable e) {
throw new WebApplicationException(e);
} finally {
MultipartReader.closeQuietly(partsReader);
}
}
/**
* Deletes the portrait of an user
* @response.representation.200.doc The portrait deleted
* @response.representation.401.doc Not authorized
* @param identityKey The identity key identifier of the user being searched
* @param request The REST request
* @return The image
*/
@DELETE
@Path("{identityKey}/portrait")
public Response deletePortrait(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
try {
Identity authIdentity = getUserRequest(request).getIdentity();
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
} else if(!isUserManager(request) && !identity.equalsByPersistableKey(authIdentity)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
DisplayPortraitManager.getInstance().deletePortrait(identity);
return Response.ok().build();
} catch (Throwable e) {
throw new WebApplicationException(e);
}
}
@Path("{identityKey}/groups")

srosse
committed
public MyGroupWebService getUserGroupList(@PathParam("identityKey") Long identityKey) {
Identity retrievedUser = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(retrievedUser == null) {

srosse
committed
return null;

srosse
committed
return new MyGroupWebService(retrievedUser);
}
/**
* Update an user
* @response.representation.qname {http://www.example.com}userVO
* @response.representation.mediaType application/xml, application/json
* @response.representation.doc The user
* @response.representation.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO}
* @response.representation.200.qname {http://www.example.com}userVO
* @response.representation.200.mediaType application/xml, application/json
* @response.representation.200.doc The user
* @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO}
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @response.representation.406.qname {http://www.example.com}errorVO
* @response.representation.406.mediaType application/xml, application/json
* @response.representation.406.doc The list of validation errors
* @response.representation.406.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_ERRORVOes}
* @param identityKey The user key identifier
* @param user The user datas
* @param request The HTTP request
* @return <code>User</code> object. The operation status (success or fail)
*/
@POST
@Path("{identityKey}")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response update(@PathParam("identityKey") Long identityKey, UserVO user, @Context HttpServletRequest request) {
try {
if(user == null) {
return Response.serverError().status(Status.NO_CONTENT).build();
}
if(!isUserManager(request)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
BaseSecurity baseSecurity = BaseSecurityManager.getInstance();
Identity retrievedIdentity = baseSecurity.loadIdentityByKey(identityKey, false);
if(retrievedIdentity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
User retrievedUser = retrievedIdentity.getUser();

srosse
committed
List<ErrorVO> errors = validateUser(retrievedUser, user, request);
if(StringHelper.containsNonWhitespace(user.getExternalId())
&& !user.getExternalId().equals(retrievedIdentity.getExternalId())) {
retrievedIdentity = baseSecurity.setExternalId(retrievedIdentity, user.getExternalId());
retrievedUser = retrievedIdentity.getUser();
}
post(retrievedUser, user, getLocale(request));
UserManager.getInstance().updateUser(retrievedUser);
return Response.ok(get(retrievedIdentity, true, true)).build();
}
//content not ok
ErrorVO[] errorVos = new ErrorVO[errors.size()];
errors.toArray(errorVos);
return Response.ok(errorVos).status(Status.NOT_ACCEPTABLE).build();
} catch (Exception e) {
log.error("Error updating an user", e);
return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
}
}

srosse
committed
private List<ErrorVO> validateUser(User user, UserVO userVo, HttpServletRequest request) {
UserManager um = UserManager.getInstance();
Locale locale = getLocale(request);
List<ErrorVO> errors = new ArrayList<ErrorVO>();
List<UserPropertyHandler> propertyHandlers = um.getUserPropertyHandlersFor(PROPERTY_HANDLER_IDENTIFIER, false);

srosse
committed
validateProperty(user, UserConstants.FIRSTNAME, userVo.getFirstName(), propertyHandlers, errors, um, locale);
validateProperty(user, UserConstants.LASTNAME, userVo.getLastName(), propertyHandlers, errors, um, locale);
validateProperty(user, UserConstants.EMAIL, userVo.getEmail(), propertyHandlers, errors, um, locale);
for (UserPropertyHandler propertyHandler : propertyHandlers) {
if(!UserConstants.FIRSTNAME.equals(propertyHandler.getName())
&& !UserConstants.LASTNAME.equals(propertyHandler.getName())
&& !UserConstants.EMAIL.equals(propertyHandler.getName())) {

srosse
committed
validateProperty(user, userVo, propertyHandler, errors, um, locale);

srosse
committed
private boolean validateProperty(User user, String name, String value, List<UserPropertyHandler> handlers, List<ErrorVO> errors, UserManager um, Locale locale) {
for(UserPropertyHandler handler:handlers) {
if(handler.getName().equals(name)) {

srosse
committed
return validateProperty(user, value, handler, errors, um, locale);

srosse
committed
private boolean validateProperty(User user, UserVO userVo, UserPropertyHandler userPropertyHandler, List<ErrorVO> errors, UserManager um, Locale locale) {
String value = userVo.getProperty(userPropertyHandler.getName());
return validateProperty(user, value, userPropertyHandler, errors, um, locale);

srosse
committed
private boolean validateProperty(User user, String value, UserPropertyHandler userPropertyHandler, List<ErrorVO> errors, UserManager um, Locale locale) {
ValidationError error = new ValidationError();
if(!StringHelper.containsNonWhitespace(value) && um.isMandatoryUserProperty(PROPERTY_HANDLER_IDENTIFIER, userPropertyHandler)) {
Translator translator = new PackageTranslator("org.olat.core", locale);
String translation = translator.translate("new.form.mandatory");
errors.add(new ErrorVO("org.olat.core", "new.form.mandatory", translation));
return false;
}
value = parseUserProperty(value, userPropertyHandler, locale);

srosse
committed
if (!userPropertyHandler.isValidValue(user, value, error, locale)) {
String pack = userPropertyHandler.getClass().getPackage().getName();
Translator translator = new PackageTranslator(pack, locale);

srosse
committed
String translation = translator.translate(error.getErrorKey(), error.getArgs());
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
errors.add(new ErrorVO(pack, error.getErrorKey(), translation));
return false;
}
return true;
}
/**
* Delete an user from the system
* @response.representation.200.doc The user is removed from the group
* @response.representation.401.doc The roles of the authenticated user are not sufficient
* @response.representation.404.doc The identity not found
* @param identityKey The user key identifier
* @param request The HTTP request
* @return <code>Response</code> object. The operation status (success or fail)
*/
@DELETE
@Path("{identityKey}")
public Response delete(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
if(!isUserManager(request)) {
return Response.serverError().status(Status.UNAUTHORIZED).build();
}
Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false);
if(identity == null) {
return Response.serverError().status(Status.NOT_FOUND).build();
}
UserDeletionManager.getInstance().deleteIdentity(identity);
return Response.ok().build();
}