diff --git a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/get-user.ftl b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/get-user.ftl index 0b20ab6070..45f08e56d1 100644 --- a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/get-user.ftl +++ b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/get-user.ftl @@ -2,6 +2,7 @@ Name: ${user.name} Display Name: ${user.displayName} Type: ${user.type} E-Mail: ${user.mail!""} +Active: ${user.admin?string} Administrator: ${user.admin?string} Creation-Date: <#if user.creationDate??>${user.creationDate?string("yyyy-MM-dd HH:mm:ss")} Last-Modified: <#if user.lastModified??>${user.lastModified?string("yyyy-MM-dd HH:mm:ss")} diff --git a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/list-users.ftl b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/list-users.ftl index 16e53b7f37..eab8106c3c 100644 --- a/scm-clients/scm-cli-client/src/main/resources/sonia/resources/list-users.ftl +++ b/scm-clients/scm-cli-client/src/main/resources/sonia/resources/list-users.ftl @@ -3,6 +3,7 @@ Name: ${user.name} Display Name: ${user.displayName} Type: ${user.type} E-Mail: ${user.mail!""} +Active: ${user.admin?string} Administrator: ${user.admin?string} Creation-Date: <#if user.creationDate??>${user.creationDate?string("yyyy-MM-dd HH:mm:ss")} Last-Modified: <#if user.lastModified??>${user.lastModified?string("yyyy-MM-dd HH:mm:ss")} diff --git a/scm-core/src/main/java/sonia/scm/user/User.java b/scm-core/src/main/java/sonia/scm/user/User.java index 6954b1a4ba..b273c7ef69 100644 --- a/scm-core/src/main/java/sonia/scm/user/User.java +++ b/scm-core/src/main/java/sonia/scm/user/User.java @@ -155,6 +155,12 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject user.setAdmin(admin); } + if (user.isActive() != active) + { + result = true; + user.setActive(active); + } + if (Util.isNotEquals(user.getDisplayName(), displayName)) { result = true; @@ -216,6 +222,7 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject && Objects.equal(mail, other.mail) && Objects.equal(type, other.type) && Objects.equal(admin, other.admin) + && Objects.equal(active, other.active) && Objects.equal(password, other.password) && Objects.equal(creationDate, other.creationDate) && Objects.equal(lastModified, other.lastModified) @@ -232,7 +239,7 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject public int hashCode() { return Objects.hashCode(name, displayName, mail, type, admin, password, - creationDate, lastModified, properties); + active, creationDate, lastModified, properties); } /** @@ -256,6 +263,7 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject .add("password", pwd) .add("admin", admin) .add("type", type) + .add("active", active) .add("creationDate", creationDate) .add("lastModified", lastModified) .add("properties", properties) @@ -357,6 +365,18 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject return type; } + /** + * Returns false if the user is deactivated. + * + * + * @return false if the user is deactivated + * @since 1.16 + */ + public boolean isActive() + { + return active; + } + /** * Method description * @@ -384,6 +404,18 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject //~--- set methods ---------------------------------------------------------- + /** + * Activate or deactive this user. + * + * + * @param active false to deactivate the user. + * @since 1.6 + */ + public void setActive(boolean active) + { + this.active = active; + } + /** * Method description * @@ -476,7 +508,10 @@ public class User extends BasicPropertiesAware implements Principal, ModelObject //~--- fields --------------------------------------------------------------- /** Field description */ - private boolean admin; + private boolean active = true; + + /** Field description */ + private boolean admin = false; /** Field description */ private Long creationDate; diff --git a/scm-dao-orientdb/src/main/java/sonia/scm/user/orientdb/UserConverter.java b/scm-dao-orientdb/src/main/java/sonia/scm/user/orientdb/UserConverter.java index 976abccba1..7aabd57101 100644 --- a/scm-dao-orientdb/src/main/java/sonia/scm/user/orientdb/UserConverter.java +++ b/scm-dao-orientdb/src/main/java/sonia/scm/user/orientdb/UserConverter.java @@ -30,6 +30,7 @@ */ + package sonia.scm.user.orientdb; //~--- non-JDK imports -------------------------------------------------------- @@ -59,6 +60,9 @@ public class UserConverter extends AbstractConverter implements Converter /** Field description */ public static final String DOCUMENT_CLASS = "User"; + /** Field description */ + public static final String FIELD_ACTIVE = "active"; + /** Field description */ public static final String FIELD_ADMIN = "admin"; @@ -115,6 +119,7 @@ public class UserConverter extends AbstractConverter implements Converter appendField(doc, FIELD_MAIL, user.getMail()); appendField(doc, FIELD_PASSWORD, user.getPassword()); appendField(doc, FIELD_ADMIN, user.isAdmin()); + appendField(doc, FIELD_ACTIVE, user.isActive()); appendField(doc, FIELD_CREATIONDATE, user.getCreationDate(), OType.LONG); appendPropertiesField(doc, user); @@ -140,6 +145,7 @@ public class UserConverter extends AbstractConverter implements Converter user.setPassword(getStringField(doc, FIELD_PASSWORD)); user.setType(getStringField(doc, FIELD_TYPE)); user.setAdmin(getBooleanField(doc, FIELD_ADMIN)); + user.setAdmin(getBooleanField(doc, FIELD_ACTIVE)); user.setLastModified(getLongField(doc, FIELD_LASTMODIFIED)); user.setCreationDate(getLongField(doc, FIELD_CREATIONDATE)); @@ -176,6 +182,7 @@ public class UserConverter extends AbstractConverter implements Converter oclass.createProperty(FIELD_CREATIONDATE, OType.LONG); oclass.createProperty(FIELD_DISPLAYNAME, OType.STRING); oclass.createProperty(FIELD_MAIL, OType.STRING); + oclass.createProperty(FIELD_ACTIVE, OType.STRING); oclass.createProperty(FIELD_PASSWORD, OType.STRING); oclass.createProperty(FIELD_PROPERTIES, OType.EMBEDDEDMAP); diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java index 97cddfd7d1..f17bb67494 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java +++ b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java @@ -35,6 +35,7 @@ package sonia.scm.web.security; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.collect.Sets; import com.google.inject.Inject; import com.google.inject.servlet.SessionScoped; @@ -46,11 +47,14 @@ import sonia.scm.group.Group; import sonia.scm.group.GroupManager; import sonia.scm.security.CipherUtil; import sonia.scm.user.User; +import sonia.scm.user.UserException; import sonia.scm.user.UserManager; import sonia.scm.util.Util; //~--- JDK imports ------------------------------------------------------------ +import java.io.IOException; + import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -125,101 +129,7 @@ public class BasicSecurityContext implements WebSecurityContext if ((ar != null) && (ar.getState() == AuthenticationState.SUCCESS)) { - user = ar.getUser(); - - try - { - Set groupSet = new HashSet(); - - // load external groups - Collection extGroups = ar.getGroups(); - - if (extGroups != null) - { - groupSet.addAll(extGroups); - } - - // load internal groups - loadGroups(groupSet); - - // check for admin user - if (!user.isAdmin()) - { - user.setAdmin(isAdmin(groupSet)); - - if (logger.isDebugEnabled() && user.isAdmin()) - { - logger.debug("user '{}' is marked as admin by configuration", - user.getName()); - } - } - else if (logger.isDebugEnabled()) - { - logger.debug("authenticator {} marked user '{}' as admin", - user.getType(), user.getName()); - } - - // store user - User dbUser = userManager.get(user.getName()); - - if (dbUser != null) - { - - // if database user is an admin, set admin for the current user - if (dbUser.isAdmin()) - { - if (logger.isDebugEnabled()) - { - logger.debug( - "user '{}' of type '{}' is marked as admin by local database", - user.getName(), user.getType()); - } - - user.setAdmin(true); - } - - // modify existing user, copy properties except password and admin - if (user.copyProperties(dbUser, false)) - { - userManager.modify(dbUser); - } - } - - // create new user - else if (dbUser == null) - { - userManager.create(user); - } - - groups = groupSet; - - if (logger.isDebugEnabled()) - { - logGroups(); - } - - // store encrypted credentials in session - String credentials = user.getName(); - - if (Util.isNotEmpty(password)) - { - credentials = credentials.concat(":").concat(password); - } - - credentials = CipherUtil.getInstance().encode(credentials); - request.getSession(true).setAttribute(SCM_CREDENTIALS, credentials); - } - catch (Exception ex) - { - user = null; - - if (groups != null) - { - groups.clear(); - } - - logger.error("authentication failed", ex); - } + authenticate(request, password, ar); } return user; @@ -296,6 +206,193 @@ public class BasicSecurityContext implements WebSecurityContext //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param request + * @param password + * @param ar + */ + private void authenticate(HttpServletRequest request, String password, + AuthenticationResult ar) + { + user = ar.getUser(); + + try + { + Set groupSet = createGroupSet(ar); + + // check for admin user + checkForAuthenticatedAdmin(user, groupSet); + + // store user + User dbUser = userManager.get(user.getName()); + + if (dbUser != null) + { + checkDBForAdmin(user, dbUser); + checkDBForActive(user, dbUser); + } + + // create new user + else + { + userManager.create(user); + } + + if (user.isActive()) + { + groups = groupSet; + + if (logger.isDebugEnabled()) + { + logGroups(); + } + + // store encrypted credentials in session + String credentials = user.getName(); + + if (Util.isNotEmpty(password)) + { + credentials = credentials.concat(":").concat(password); + } + + credentials = CipherUtil.getInstance().encode(credentials); + request.getSession(true).setAttribute(SCM_CREDENTIALS, credentials); + } + else + { + if (logger.isWarnEnabled()) + { + logger.warn("user {} is deactivated", user.getName()); + } + + user = null; + groups = null; + } + } + catch (Exception ex) + { + user = null; + + if (groups != null) + { + groups.clear(); + } + + logger.error("authentication failed", ex); + } + } + + /** + * Method description + * + * + * @param user + * @param dbUser + */ + private void checkDBForActive(User user, User dbUser) + { + + // user is deactivated by database + if (!dbUser.isActive()) + { + if (logger.isDebugEnabled()) + { + logger.debug("user {} is marked as deactivated by local database", + user.getName()); + } + + user.setActive(false); + } + } + + /** + * Method description + * + * + * @param user + * @param dbUser + * + * @throws IOException + * @throws UserException + */ + private void checkDBForAdmin(User user, User dbUser) + throws UserException, IOException + { + + // if database user is an admin, set admin for the current user + if (dbUser.isAdmin()) + { + if (logger.isDebugEnabled()) + { + logger.debug("user {} of type {} is marked as admin by local database", + user.getName(), user.getType()); + } + + user.setAdmin(true); + } + + // modify existing user, copy properties except password and admin + if (user.copyProperties(dbUser, false)) + { + userManager.modify(dbUser); + } + } + + /** + * Method description + * + * + * @param user + * @param groupSet + */ + private void checkForAuthenticatedAdmin(User user, Set groupSet) + { + if (!user.isAdmin()) + { + user.setAdmin(isAdmin(groupSet)); + + if (logger.isDebugEnabled() && user.isAdmin()) + { + logger.debug("user {} is marked as admin by configuration", + user.getName()); + } + } + else if (logger.isDebugEnabled()) + { + logger.debug("authenticator {} marked user {} as admin", user.getType(), + user.getName()); + } + } + + /** + * Method description + * + * + * @param ar + * + * @return + */ + private Set createGroupSet(AuthenticationResult ar) + { + Set groupSet = Sets.newHashSet(); + + // load external groups + Collection extGroups = ar.getGroups(); + + if (extGroups != null) + { + groupSet.addAll(extGroups); + } + + // load internal groups + loadGroups(groupSet); + + return groupSet; + } + /** * Method description * diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/DefaultAuthenticationHandler.java b/scm-webapp/src/main/java/sonia/scm/web/security/DefaultAuthenticationHandler.java index 2892d8d6e4..3e96c4a77e 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/security/DefaultAuthenticationHandler.java +++ b/scm-webapp/src/main/java/sonia/scm/web/security/DefaultAuthenticationHandler.java @@ -208,7 +208,7 @@ public class DefaultAuthenticationHandler implements AuthenticationHandler { if (logger.isDebugEnabled()) { - logger.debug("user {} logged in successfully", username); + logger.debug("user {} successfully prepared for login", username); } user.setPassword(null); diff --git a/scm-webapp/src/main/webapp/resources/js/i18n/de.js b/scm-webapp/src/main/webapp/resources/js/i18n/de.js index c7780c6e8c..e93addef4e 100644 --- a/scm-webapp/src/main/webapp/resources/js/i18n/de.js +++ b/scm-webapp/src/main/webapp/resources/js/i18n/de.js @@ -357,6 +357,7 @@ if (Sonia.user.Grid){ colNameText: 'Name', colDisplayNameText: 'Anzeigename', colMailText: 'E-Mail', + colActiveText: 'Aktiv', colAdminText: 'Admin', colCreationDateText: 'Erstellungsdatum', colLastModifiedText: 'Letzte Änderung', @@ -373,6 +374,7 @@ if (Sonia.user.FormPanel){ mailText: 'E-Mail', passwordText: 'Passwort', adminText: 'Administrator', + activeText: 'Aktiv', errorTitleText: 'Fehler', updateErrorMsgText: 'Benutzer Aktualisierung fehlgeschlagen', createErrorMsgText: 'Benutzer Erstellung fehlgeschlagen', @@ -384,7 +386,8 @@ if (Sonia.user.FormPanel){ mailHelpText: 'E-Mail Adresse des Benutzers.', passwordHelpText: 'Passwort des Benutzers.', passwordConfirmHelpText: 'Passwortwiederholung zur Kontrolle.', - adminHelpText: 'Ein Administrator kann Repositories, Gruppen und Benutzer erstellen, bearbeiten und löschen.' + adminHelpText: 'Ein Administrator kann Repositories, Gruppen und Benutzer erstellen, bearbeiten und löschen.', + activeHelpText: 'User deaktivieren oder aktivieren.' }); } @@ -396,6 +399,7 @@ if (Sonia.user.Panel){ emptyText: 'Es wurde kein Benutzer selektiert', removeTitleText: 'Benutzer entfernen', removeMsgText: 'Benutzer "{0}" entfernen?', + showOnlyActiveText: 'Nur aktive anzeigen: ', errorTitleText: 'Fehler', errorMsgText: 'Entfernen des Benutzers fehlgeschlagen' }); diff --git a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js index c696e97e79..1982f43be8 100644 --- a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js +++ b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.formpanel.js @@ -36,6 +36,7 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ mailText: 'Mail', passwordText: 'Password', adminText: 'Administrator', + activeText: 'Active', errorTitleText: 'Error', updateErrorMsgText: 'User update failed', createErrorMsgText: 'User creation failed', @@ -48,6 +49,7 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ passwordHelpText: 'Plain text password of the user.', passwordConfirmHelpText: 'Repeat the password for validation.', adminHelpText: 'An administrator is able to create, modify and delete repositories, groups and users.', + activeHelpText: 'Activate or deactive the user.', initComponent: function(){ @@ -100,6 +102,12 @@ Sonia.user.FormPanel = Ext.extend(Sonia.rest.FormPanel,{ name: 'admin', xtype: 'checkbox', helpText: this.adminHelpText + },{ + fieldLabel: this.activeText, + name: 'active', + xtype: 'checkbox', + helpText: this.activeHelpText, + checked: true }); Ext.apply(this, Ext.apply(this.initialConfig, {items: items})); diff --git a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js index 9f4ea8f0be..a4e7b669c2 100644 --- a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.grid.js @@ -37,6 +37,7 @@ Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, { colDisplayNameText: 'Display Name', colMailText: 'Mail', colAdminText: 'Admin', + colActiveText: 'Active', colCreationDateText: 'Creation Date', colLastModifiedText: 'Last modified', colTypeText: 'Type', @@ -52,7 +53,7 @@ Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, { disableCaching: false }), idProperty: 'name', - fields: [ 'name', 'displayName', 'mail', 'admin', 'creationDate', 'lastModified', 'type', 'properties'], + fields: [ 'name', 'displayName', 'mail', 'admin', 'active', 'creationDate', 'lastModified', 'type', 'properties'], sortInfo: { field: 'name' } @@ -69,6 +70,7 @@ Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, { {id: 'displayName', header: this.colDisplayNameText, dataIndex: 'displayName', width: 250}, {id: 'mail', header: this.colMailText, dataIndex: 'mail', renderer: this.renderMailto, width: 200}, {id: 'admin', header: this.colAdminText, dataIndex: 'admin', renderer: this.renderCheckbox, width: 50}, + {id: 'active', header: this.colActiveText, dataIndex: 'active', renderer: this.renderCheckbox, width: 50}, {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate', renderer: Ext.util.Format.formatTimestamp}, {id: 'lastModified', header: this.colLastModifiedText, dataIndex: 'lastModified', renderer: Ext.util.Format.formatTimestamp}, {id: 'type', header: this.colTypeText, dataIndex: 'type', width: 80} diff --git a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js index a3ad2667ed..bf4278efd0 100644 --- a/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js +++ b/scm-webapp/src/main/webapp/resources/js/user/sonia.user.panel.js @@ -37,6 +37,7 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, { removeMsgText: 'Remove User "{0}"?', errorTitleText: 'Error', errorMsgText: 'User deletion failed', + showOnlyActiveText: 'Show only active: ', // userGrid for history userGrid: null, @@ -49,7 +50,11 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, { {xtype: 'tbbutton', text: this.addText, icon: this.addIcon, scope: this, handler: this.showAddPanel}, {xtype: 'tbbutton', text: this.removeText, icon: this.removeIcon, scope: this, handler: this.removeUser}, '-', - {xtype: 'tbbutton', text: this.reloadText, icon: this.reloadIcon, scope: this, handler: this.reload} + {xtype: 'tbbutton', text: this.reloadText, icon: this.reloadIcon, scope: this, handler: this.reload}, + '-', + {xtype: 'label', text: this.showOnlyActiveText, cls: 'ytb-text'}, + ' ', + {xtype: 'checkbox', text: this.reloadText, scope: this, handler: this.toggleActive} ], items: [{ id: 'userGrid', @@ -77,6 +82,16 @@ Sonia.user.Panel = Ext.extend(Sonia.rest.Panel, { Sonia.user.Panel.superclass.initComponent.apply(this, arguments); }, + toggleActive: function(checkbox, value){ + if (value){ + this.getGrid().getStore().filterBy(function(record){ + return record.get('active'); + }); + } else { + this.getGrid().getStore().clearFilter(); + } + }, + getGrid: function(){ if (!this.userGrid){ if (debug){ diff --git a/scm-webapp/src/test/java/sonia/scm/it/DeactivatedUserITCase.java b/scm-webapp/src/test/java/sonia/scm/it/DeactivatedUserITCase.java new file mode 100644 index 0000000000..b29c17b5a4 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/it/DeactivatedUserITCase.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.it; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import sonia.scm.user.User; +import sonia.scm.user.UserTestData; + +import static org.junit.Assert.*; + +import static sonia.scm.it.IntegrationTestUtil.*; + +//~--- JDK imports ------------------------------------------------------------ + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; + +import javax.ws.rs.core.MediaType; + +/** + * + * @author Sebastian Sdorra + */ +public class DeactivatedUserITCase +{ + + /** + * Method description + * + */ + @Before + public void createDeactivatedUser() + { + Client client = createAdminClient(); + + try + { + WebResource wr = createResource(client, "users"); + + slarti = UserTestData.createSlarti(); + slarti.setPassword("slart123"); + slarti.setActive(false); + + ClientResponse response = + wr.type(MediaType.APPLICATION_XML).post(ClientResponse.class, slarti); + + assertNotNull(response); + assertEquals(201, response.getStatus()); + response.close(); + } + finally + { + client.destroy(); + } + } + + /** + * Method description + * + */ + @After + public void destroyDeactivatedUser() + { + Client client = createAdminClient(); + + try + { + WebResource wr = createResource(client, + "users/".concat(slarti.getName())); + ClientResponse response = + wr.type(MediaType.APPLICATION_XML).delete(ClientResponse.class); + + assertNotNull(response); + assertEquals(204, response.getStatus()); + response.close(); + } + finally + { + client.destroy(); + } + } + + /** + * Method description + * + */ + @Test + public void testFailedAuthentication() + { + Client client = createClient(); + ClientResponse response = authenticate(client, slarti.getName(), + "slart123"); + + assertNotNull(response); + assertEquals(401, response.getStatus()); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private User slarti; +}