mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-06 20:30:52 +01:00
merged plugins pom
This commit is contained in:
@@ -78,6 +78,27 @@ public class HgConfigResource
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param uriInfo
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("auto-configuration")
|
||||
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public HgConfig autoConfiguration(@Context UriInfo uriInfo)
|
||||
{
|
||||
handler.setConfig(null);
|
||||
handler.doAutoConfiguration();
|
||||
|
||||
return handler.getConfig();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -101,11 +101,8 @@ public class HgRepositoryHandler
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void loadConfig()
|
||||
public void doAutoConfiguration()
|
||||
{
|
||||
super.loadConfig();
|
||||
|
||||
HgInstaller installer = null;
|
||||
|
||||
if (SystemUtil.isWindows())
|
||||
@@ -163,6 +160,17 @@ public class HgRepositoryHandler
|
||||
storeConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void loadConfig()
|
||||
{
|
||||
super.loadConfig();
|
||||
doAutoConfiguration();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
*/
|
||||
|
||||
registerConfigPanel({
|
||||
id: 'hgConfigForm',
|
||||
xtype : 'configForm',
|
||||
title : 'Mercurial Settings',
|
||||
items : [{
|
||||
@@ -56,6 +57,14 @@ registerConfigPanel({
|
||||
name: 'useOptimizedBytecode',
|
||||
fieldLabel: 'Optimized Bytecode (.pyo)',
|
||||
inputValue: 'true'
|
||||
},{
|
||||
xtype: 'button',
|
||||
text: 'Load Auto-Configuration',
|
||||
fieldLabel: 'Auto-Configuration',
|
||||
handler: function(){
|
||||
var self = Ext.getCmp('hgConfigForm');
|
||||
self.loadConfig( self.el, 'config/repositories/hg/auto-configuration.json', 'POST' );
|
||||
}
|
||||
}],
|
||||
|
||||
onSubmit: function(values){
|
||||
@@ -76,10 +85,14 @@ registerConfigPanel({
|
||||
},
|
||||
|
||||
onLoad: function(el){
|
||||
this.loadConfig(el, 'config/repositories/hg.json', 'GET');
|
||||
},
|
||||
|
||||
loadConfig: function(el, url, method){
|
||||
var tid = setTimeout( function(){ el.mask('Loading ...'); }, 100);
|
||||
Ext.Ajax.request({
|
||||
url: restUrl + 'config/repositories/hg.json',
|
||||
method: 'GET',
|
||||
url: restUrl + url,
|
||||
method: method,
|
||||
scope: this,
|
||||
disableCaching: true,
|
||||
success: function(response){
|
||||
|
||||
@@ -138,7 +138,7 @@ public class PAMAuthenticationHandler implements AuthenticationHandler
|
||||
User user = new User(username);
|
||||
|
||||
user.setAdmin(isAdmin(unixUser));
|
||||
result = new AuthenticationResult(user);
|
||||
result = new AuthenticationResult(user, unixUser.getGroups());
|
||||
}
|
||||
}
|
||||
catch (PAMException ex)
|
||||
|
||||
@@ -377,6 +377,19 @@ public class Group
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param member
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isMember(String member)
|
||||
{
|
||||
return (members != null) && members.contains(member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -38,10 +38,25 @@ package sonia.scm.group;
|
||||
import sonia.scm.ListenerSupport;
|
||||
import sonia.scm.Manager;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface GroupManager
|
||||
extends Manager<Group, GroupException>,
|
||||
ListenerSupport<GroupListener> {}
|
||||
extends Manager<Group, GroupException>, ListenerSupport<GroupListener>
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param member
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Collection<Group> getGroupsForMember(String member);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public class Permission implements Serializable
|
||||
*/
|
||||
public Permission(String name)
|
||||
{
|
||||
this();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -81,10 +82,24 @@ public class Permission implements Serializable
|
||||
*/
|
||||
public Permission(String name, PermissionType type)
|
||||
{
|
||||
this.name = name;
|
||||
this(name);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @param type
|
||||
* @param groupPermission
|
||||
*/
|
||||
public Permission(String name, PermissionType type, boolean groupPermission)
|
||||
{
|
||||
this(name, type);
|
||||
this.groupPermission = groupPermission;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -109,8 +124,30 @@ public class Permission implements Serializable
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isGroupPermission()
|
||||
{
|
||||
return groupPermission;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param groupPermission
|
||||
*/
|
||||
public void setGroupPermission(boolean groupPermission)
|
||||
{
|
||||
this.groupPermission = groupPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -135,6 +172,9 @@ public class Permission implements Serializable
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private boolean groupPermission = false;
|
||||
|
||||
/** Field description */
|
||||
private String name;
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -134,7 +135,8 @@ public class PermissionUtil
|
||||
|
||||
if (permissions != null)
|
||||
{
|
||||
result = hasPermission(permissions, username, pt);
|
||||
result = hasPermission(permissions, username,
|
||||
securityContext.getGroups(), pt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,12 +149,13 @@ public class PermissionUtil
|
||||
*
|
||||
* @param permissions
|
||||
* @param username
|
||||
* @param groups
|
||||
* @param pt
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static boolean hasPermission(List<Permission> permissions,
|
||||
String username, PermissionType pt)
|
||||
String username, Collection<String> groups, PermissionType pt)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
@@ -160,12 +163,15 @@ public class PermissionUtil
|
||||
{
|
||||
String name = p.getName();
|
||||
|
||||
if ((name != null) && name.equalsIgnoreCase(username)
|
||||
&& (p.getType().getValue() >= pt.getValue()))
|
||||
if ((name != null) && (p.getType().getValue() >= pt.getValue()))
|
||||
{
|
||||
result = true;
|
||||
if (name.equals(username)
|
||||
|| (p.isGroupPermission() && groups.contains(p.getName())))
|
||||
{
|
||||
result = true;
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.web.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.user.User;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class AbstractAuthenticationManager
|
||||
implements AuthenticationManager
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
@Override
|
||||
public void addListener(AuthenticationListener listener)
|
||||
{
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param listeners
|
||||
*/
|
||||
@Override
|
||||
public void addListeners(Collection<AuthenticationListener> listeners)
|
||||
{
|
||||
listeners.addAll(listeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
@Override
|
||||
public void removeListener(AuthenticationListener listener)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param user
|
||||
*/
|
||||
protected void fireAuthenticationEvent(HttpServletRequest request,
|
||||
HttpServletResponse response, User user)
|
||||
{
|
||||
for (AuthenticationListener listener : listeners)
|
||||
{
|
||||
listener.onAuthentication(request, response, user);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Set<AuthenticationListener> listeners =
|
||||
new HashSet<AuthenticationListener>();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.web.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.plugin.ExtensionPoint;
|
||||
import sonia.scm.user.User;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@ExtensionPoint
|
||||
public interface AuthenticationListener
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param user
|
||||
*/
|
||||
public void onAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response, User user);
|
||||
}
|
||||
@@ -36,7 +36,7 @@ package sonia.scm.web.security;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.Initable;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.ListenerSupport;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -49,7 +49,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public interface AuthenticationManager extends Initable, Closeable
|
||||
public interface AuthenticationManager
|
||||
extends Initable, Closeable, ListenerSupport<AuthenticationListener>
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -63,7 +64,6 @@ public interface AuthenticationManager extends Initable, Closeable
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public User authenticate(HttpServletRequest request,
|
||||
HttpServletResponse response, String username,
|
||||
String password);
|
||||
public AuthenticationResult authenticate(HttpServletRequest request,
|
||||
HttpServletResponse response, String username, String password);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ package sonia.scm.web.security;
|
||||
|
||||
import sonia.scm.user.User;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
@@ -91,6 +95,37 @@ public class AuthenticationResult
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
* @param groups
|
||||
*/
|
||||
public AuthenticationResult(User user, Collection<String> groups)
|
||||
{
|
||||
this.user = user;
|
||||
this.groups = groups;
|
||||
this.state = AuthenticationState.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
* @param groups
|
||||
* @param state
|
||||
*/
|
||||
public AuthenticationResult(User user, Collection<String> groups,
|
||||
AuthenticationState state)
|
||||
{
|
||||
this.user = user;
|
||||
this.groups = groups;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -118,6 +153,17 @@ public class AuthenticationResult
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Collection<String> getGroups()
|
||||
{
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -142,6 +188,9 @@ public class AuthenticationResult
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Collection<String> groups;
|
||||
|
||||
/** Field description */
|
||||
private AuthenticationState state;
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ import sonia.scm.user.User;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -76,6 +78,14 @@ public interface WebSecurityContext extends SecurityContext
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Collection<String> getGroups();
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -50,7 +50,10 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -108,6 +111,53 @@ public class PermissionUtilTest
|
||||
PermissionUtil.assertPermission(repository, admams, PermissionType.OWNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGroupPermissions()
|
||||
{
|
||||
WebSecurityContext dent = mockGroupCtx(new User("dent", "Arthur Dent",
|
||||
"arthur.dent@hitchhiker.com"),
|
||||
"devel", "qa");
|
||||
WebSecurityContext ford = mockGroupCtx(new User("ford", "Ford Prefect",
|
||||
"ford.prefect@hitchhiker.com"), "devel");
|
||||
WebSecurityContext zaphod = mockGroupCtx(new User("zaphod",
|
||||
"Zaphod Beeblebrox",
|
||||
"zaphod.beeblebrox@hitchhiker.com"), "qa");
|
||||
WebSecurityContext trillian = mockGroupCtx(new User("trillian",
|
||||
"Trillian Astra",
|
||||
"trillian.astra@hitchhiker.com"));
|
||||
Repository r = new Repository();
|
||||
|
||||
r.setPermissions(
|
||||
new ArrayList<Permission>(
|
||||
Arrays.asList(
|
||||
new Permission("dent"),
|
||||
new Permission("devel", PermissionType.WRITE, true),
|
||||
new Permission("qa", PermissionType.READ, true))));
|
||||
// member of both devel and qa
|
||||
assertTrue(PermissionUtil.hasPermission(r, dent, PermissionType.READ));
|
||||
assertTrue(PermissionUtil.hasPermission(r, dent, PermissionType.WRITE));
|
||||
assertFalse(PermissionUtil.hasPermission(r, dent, PermissionType.OWNER));
|
||||
// now, additionally the owner
|
||||
r.getPermissions().add(new Permission("dent", PermissionType.OWNER));
|
||||
assertTrue(PermissionUtil.hasPermission(r, dent, PermissionType.OWNER));
|
||||
// member of just devel
|
||||
assertTrue(PermissionUtil.hasPermission(r, ford, PermissionType.READ));
|
||||
assertTrue(PermissionUtil.hasPermission(r, ford, PermissionType.WRITE));
|
||||
assertFalse(PermissionUtil.hasPermission(r, ford, PermissionType.OWNER));
|
||||
// member of just qa
|
||||
assertTrue(PermissionUtil.hasPermission(r, zaphod, PermissionType.READ));
|
||||
assertFalse(PermissionUtil.hasPermission(r, zaphod, PermissionType.WRITE));
|
||||
assertFalse(PermissionUtil.hasPermission(r, zaphod, PermissionType.OWNER));
|
||||
// member of no groups
|
||||
assertFalse(PermissionUtil.hasPermission(r, trillian, PermissionType.READ));
|
||||
assertFalse(PermissionUtil.hasPermission(r, trillian, PermissionType.WRITE));
|
||||
assertFalse(PermissionUtil.hasPermission(r, trillian, PermissionType.OWNER));
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -162,6 +212,24 @@ public class PermissionUtilTest
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private WebSecurityContext mockGroupCtx(User user, String... groups)
|
||||
{
|
||||
WebSecurityContext context = mockCtx(user);
|
||||
|
||||
Set<String> groupSet = new HashSet<String>(Arrays.asList(groups));
|
||||
when(context.getGroups()).thenReturn(groupSet);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -39,6 +39,9 @@ import sonia.scm.user.User;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -97,6 +100,18 @@ public class DummyWebSecurityContext implements WebSecurityContext
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getGroups()
|
||||
{
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -123,6 +138,9 @@ public class DummyWebSecurityContext implements WebSecurityContext
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Set<String> groups = new HashSet<String>();
|
||||
|
||||
/** Field description */
|
||||
private User user;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import sonia.scm.repository.RepositoryListener;
|
||||
import sonia.scm.security.EncryptionHandler;
|
||||
import sonia.scm.user.UserListener;
|
||||
import sonia.scm.web.security.AuthenticationHandler;
|
||||
import sonia.scm.web.security.AuthenticationListener;
|
||||
import sonia.scm.web.security.XmlAuthenticationHandler;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -162,6 +163,19 @@ public class BindingExtensionProcessor implements ExtensionProcessor
|
||||
|
||||
repositoryListeners.add(listener);
|
||||
}
|
||||
else if (AuthenticationListener.class.isAssignableFrom(extensionClass))
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("bind AuthenticaitonListener {}",
|
||||
extensionClass.getName());
|
||||
}
|
||||
|
||||
AuthenticationListener listener =
|
||||
(AuthenticationListener) extensionClass.newInstance();
|
||||
|
||||
authenticationListeners.add(listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
@@ -206,6 +220,17 @@ public class BindingExtensionProcessor implements ExtensionProcessor
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<AuthenticationListener> getAuthenticationListeners()
|
||||
{
|
||||
return authenticationListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -307,6 +332,10 @@ public class BindingExtensionProcessor implements ExtensionProcessor
|
||||
private Set<RepositoryListener> repositoryListeners =
|
||||
new HashSet<RepositoryListener>();
|
||||
|
||||
/** Field description */
|
||||
private Set<AuthenticationListener> authenticationListeners =
|
||||
new HashSet<AuthenticationListener>();
|
||||
|
||||
/** Field description */
|
||||
private Set<UserListener> userListeners = new HashSet<UserListener>();
|
||||
|
||||
|
||||
@@ -144,7 +144,12 @@ public class ScmContextListener extends GuiceServletContextListener
|
||||
groupManager.init(context);
|
||||
|
||||
// init Authenticator
|
||||
injector.getInstance(AuthenticationManager.class).init(context);
|
||||
AuthenticationManager authenticationManager =
|
||||
injector.getInstance(AuthenticationManager.class);
|
||||
|
||||
authenticationManager.init(context);
|
||||
authenticationManager.addListeners(
|
||||
bindExtProcessor.getAuthenticationListeners());
|
||||
|
||||
return injector;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,12 @@ package sonia.scm;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -63,12 +66,15 @@ public class ScmState
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
*
|
||||
* @param securityContext
|
||||
* @param repositoryTypes
|
||||
*/
|
||||
public ScmState(User user, Type[] repositoryTypes)
|
||||
public ScmState(WebSecurityContext securityContext,
|
||||
Collection<Type> repositoryTypes)
|
||||
{
|
||||
this.user = user;
|
||||
this.user = securityContext.getUser();
|
||||
this.groups = securityContext.getGroups();
|
||||
this.repositoryTypes = repositoryTypes;
|
||||
}
|
||||
|
||||
@@ -80,7 +86,18 @@ public class ScmState
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Type[] getRepositoryTypes()
|
||||
public Collection<String> getGroups()
|
||||
{
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Collection<Type> getRepositoryTypes()
|
||||
{
|
||||
return repositoryTypes;
|
||||
}
|
||||
@@ -109,13 +126,24 @@ public class ScmState
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param groups
|
||||
*/
|
||||
public void setGroups(Collection<String> groups)
|
||||
{
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryTypes
|
||||
*/
|
||||
public void setRepositoryTypes(Type[] repositoryTypes)
|
||||
public void setRepositoryTypes(Collection<Type> repositoryTypes)
|
||||
{
|
||||
this.repositoryTypes = repositoryTypes;
|
||||
}
|
||||
@@ -144,9 +172,12 @@ public class ScmState
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Collection<String> groups;
|
||||
|
||||
/** Field description */
|
||||
@XmlElement(name = "repositoryTypes")
|
||||
private Type[] repositoryTypes;
|
||||
private Collection<Type> repositoryTypes;
|
||||
|
||||
/** Field description */
|
||||
private boolean success = true;
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.api.rest;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "result")
|
||||
public class RestActionResult
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public RestActionResult() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param success
|
||||
*/
|
||||
public RestActionResult(boolean success)
|
||||
{
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return success;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param success
|
||||
*/
|
||||
public void setSuccess(boolean success)
|
||||
{
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private boolean success = false;
|
||||
}
|
||||
@@ -99,7 +99,8 @@ public class AuthenticationResource
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
resp = Response.ok(getState(user)).build();
|
||||
resp = Response.ok(new ScmState(securityContext,
|
||||
repositoryManger.getTypes())).build();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,7 +136,7 @@ public class AuthenticationResource
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
state = getState(user);
|
||||
state = new ScmState(securityContext, repositoryManger.getTypes());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -167,7 +168,7 @@ public class AuthenticationResource
|
||||
logger.debug("return state for user {}", user.getName());
|
||||
}
|
||||
|
||||
state = getState(user);
|
||||
state = new ScmState(securityContext, repositoryManger.getTypes());
|
||||
response = Response.ok(state).build();
|
||||
}
|
||||
else
|
||||
@@ -178,25 +179,6 @@ public class AuthenticationResource
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ScmState getState(User user)
|
||||
{
|
||||
ScmState state = new ScmState();
|
||||
|
||||
state.setUser(user);
|
||||
state.setRepositoryTypes(repositoryManger.getTypes().toArray(new Type[0]));
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* 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.api.rest.resources;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.api.rest.RestActionResult;
|
||||
import sonia.scm.security.EncryptionHandler;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserException;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.user.xml.XmlUserManager;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Path("action/change-password")
|
||||
public class ChangePasswordResource
|
||||
{
|
||||
|
||||
/** the logger for ChangePasswordResource */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(ChangePasswordResource.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param userManager
|
||||
* @param encryptionHandler
|
||||
* @param securityContextProvider
|
||||
*/
|
||||
@Inject
|
||||
public ChangePasswordResource(
|
||||
UserManager userManager, EncryptionHandler encryptionHandler,
|
||||
Provider<WebSecurityContext> securityContextProvider)
|
||||
{
|
||||
this.userManager = userManager;
|
||||
this.encryptionHandler = encryptionHandler;
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param oldPassword
|
||||
* @param newPassword
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws UserException
|
||||
*/
|
||||
@POST
|
||||
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
|
||||
public Response changePassword(@FormParam("old-password") String oldPassword,
|
||||
@FormParam("new-password") String newPassword)
|
||||
throws UserException, IOException
|
||||
{
|
||||
AssertUtil.assertIsNotEmpty(oldPassword);
|
||||
AssertUtil.assertIsNotEmpty(newPassword);
|
||||
|
||||
int length = newPassword.length();
|
||||
|
||||
if ((length < 6) || (length > 32))
|
||||
{
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
Response response = null;
|
||||
WebSecurityContext securityContext = securityContextProvider.get();
|
||||
User currentUser = securityContext.getUser();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info("password change for user {}", currentUser.getName());
|
||||
}
|
||||
|
||||
if (currentUser.getType().equals(XmlUserManager.TYPE))
|
||||
{
|
||||
User dbUser = userManager.get(currentUser.getName());
|
||||
|
||||
if (encryptionHandler.encrypt(oldPassword).equals(dbUser.getPassword()))
|
||||
{
|
||||
dbUser.setPassword(encryptionHandler.encrypt(newPassword));
|
||||
userManager.modify(dbUser);
|
||||
response = Response.ok(new RestActionResult(true)).build();
|
||||
}
|
||||
else
|
||||
{
|
||||
response = Response.status(Response.Status.BAD_REQUEST).build();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("only xml user can change their passwor");
|
||||
response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private EncryptionHandler encryptionHandler;
|
||||
|
||||
/** Field description */
|
||||
private Provider<WebSecurityContext> securityContextProvider;
|
||||
|
||||
/** Field description */
|
||||
private UserManager userManager;
|
||||
}
|
||||
@@ -60,6 +60,7 @@ import java.io.IOException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -323,6 +324,30 @@ public class XmlGroupManager extends AbstractGroupManager
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param member
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<Group> getGroupsForMember(String member)
|
||||
{
|
||||
LinkedList<Group> groups = new LinkedList<Group>();
|
||||
|
||||
for (Group group : groupDB.values())
|
||||
{
|
||||
if (group.isMember(member))
|
||||
{
|
||||
groups.add(group.clone());
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,11 +42,18 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -74,15 +81,18 @@ public class BasicSecurityContext implements WebSecurityContext
|
||||
*
|
||||
* @param configuration
|
||||
* @param authenticator
|
||||
* @param groupManager
|
||||
* @param userManager
|
||||
*/
|
||||
@Inject
|
||||
public BasicSecurityContext(ScmConfiguration configuration,
|
||||
AuthenticationManager authenticator,
|
||||
GroupManager groupManager,
|
||||
UserManager userManager)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.authenticator = authenticator;
|
||||
this.groupManager = groupManager;
|
||||
this.userManager = userManager;
|
||||
}
|
||||
|
||||
@@ -104,10 +114,13 @@ public class BasicSecurityContext implements WebSecurityContext
|
||||
HttpServletResponse response, String username,
|
||||
String password)
|
||||
{
|
||||
user = authenticator.authenticate(request, response, username, password);
|
||||
AuthenticationResult ar = authenticator.authenticate(request, response,
|
||||
username, password);
|
||||
|
||||
if (user != null)
|
||||
if (ar != null)
|
||||
{
|
||||
user = ar.getUser();
|
||||
|
||||
try
|
||||
{
|
||||
user.setLastLogin(System.currentTimeMillis());
|
||||
@@ -128,6 +141,20 @@ public class BasicSecurityContext implements WebSecurityContext
|
||||
{
|
||||
userManager.create(user);
|
||||
}
|
||||
|
||||
Collection<String> groupCollection = ar.getGroups();
|
||||
|
||||
if (groupCollection != null)
|
||||
{
|
||||
groups.addAll(groupCollection);
|
||||
}
|
||||
|
||||
loadGroups();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logGroups();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -150,10 +177,28 @@ public class BasicSecurityContext implements WebSecurityContext
|
||||
public void logout(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
user = null;
|
||||
groups = new HashSet<String>();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Collection<String> getGroups()
|
||||
{
|
||||
if (groups == null)
|
||||
{
|
||||
groups = new HashSet<String>();
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -183,6 +228,51 @@ public class BasicSecurityContext implements WebSecurityContext
|
||||
return getUser() != null;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void loadGroups()
|
||||
{
|
||||
Collection<Group> groupCollection =
|
||||
groupManager.getGroupsForMember(user.getName());
|
||||
|
||||
if (groupCollection != null)
|
||||
{
|
||||
for (Group group : groupCollection)
|
||||
{
|
||||
groups.add(group.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
private void logGroups()
|
||||
{
|
||||
StringBuilder msg = new StringBuilder("user ");
|
||||
|
||||
msg.append(user.getName()).append(" is member of ");
|
||||
|
||||
Iterator<String> groupIt = groups.iterator();
|
||||
|
||||
while (groupIt.hasNext())
|
||||
{
|
||||
msg.append(groupIt.next());
|
||||
|
||||
if (groupIt.hasNext())
|
||||
{
|
||||
msg.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug(msg.toString());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@@ -191,6 +281,12 @@ public class BasicSecurityContext implements WebSecurityContext
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private GroupManager groupManager;
|
||||
|
||||
/** Field description */
|
||||
private Set<String> groups = new HashSet<String>();
|
||||
|
||||
/** Field description */
|
||||
private User user;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@Singleton
|
||||
public class ChainAuthenticatonManager implements AuthenticationManager
|
||||
public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
||||
{
|
||||
|
||||
/** the logger for ChainAuthenticatonManager */
|
||||
@@ -97,11 +97,10 @@ public class ChainAuthenticatonManager implements AuthenticationManager
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public User authenticate(HttpServletRequest request,
|
||||
HttpServletResponse response, String username,
|
||||
String password)
|
||||
public AuthenticationResult authenticate(HttpServletRequest request,
|
||||
HttpServletResponse response, String username, String password)
|
||||
{
|
||||
User user = null;
|
||||
AuthenticationResult ar = null;
|
||||
|
||||
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
||||
{
|
||||
@@ -122,8 +121,13 @@ public class ChainAuthenticatonManager implements AuthenticationManager
|
||||
{
|
||||
if (result.getState().isSuccessfully() && (result.getUser() != null))
|
||||
{
|
||||
user = result.getUser();
|
||||
User user = result.getUser();
|
||||
|
||||
user.setType(authenticator.getType());
|
||||
ar = result;
|
||||
|
||||
// notify authentication listeners
|
||||
fireAuthenticationEvent(request, response, user);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -135,7 +139,7 @@ public class ChainAuthenticatonManager implements AuthenticationManager
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
return ar;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<script type="text/javascript" src="resources/js/sonia.config.js"></script>
|
||||
<script type="text/javascript" src="resources/js/sonia.user.js"></script>
|
||||
<script type="text/javascript" src="resources/js/sonia.group.js"></script>
|
||||
<script type="text/javascript" src="resources/js/sonia.action.js"></script>
|
||||
<script type="text/javascript" src="resources/js/sonia.plugin.js"></script>
|
||||
<script type="text/javascript" src="resources/js/sonia.scm.js"></script>
|
||||
<script type="text/javascript" src="plugins/sonia.plugin.js"></script>
|
||||
|
||||
125
scm-webapp/src/main/webapp/resources/js/sonia.action.js
Normal file
125
scm-webapp/src/main/webapp/resources/js/sonia.action.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/* *
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.ns('Sonia.action');
|
||||
|
||||
Sonia.action.ChangePasswordWindow = Ext.extend(Ext.Window,{
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
var config = {
|
||||
layout:'fit',
|
||||
width:300,
|
||||
height:170,
|
||||
closable: false,
|
||||
resizable: false,
|
||||
plain: true,
|
||||
border: false,
|
||||
modal: true,
|
||||
items: [{
|
||||
id: 'changePasswordForm',
|
||||
url: restUrl + 'action/change-password.json',
|
||||
title: 'Change Password',
|
||||
frame: true,
|
||||
xtype: 'form',
|
||||
monitorValid: true,
|
||||
defaultType: 'textfield',
|
||||
items: [{
|
||||
name: 'old-password',
|
||||
fieldLabel: 'Old Password',
|
||||
inputType: 'password',
|
||||
allowBlank: false,
|
||||
minLength: 6,
|
||||
maxLength: 32
|
||||
},{
|
||||
id: 'new-password',
|
||||
name: 'new-password',
|
||||
fieldLabel: 'New Password',
|
||||
inputType: 'password',
|
||||
allowBlank: false,
|
||||
minLength: 6,
|
||||
maxLength: 32
|
||||
},{
|
||||
name: 'confirm-password',
|
||||
fieldLabel: 'Confirm Password',
|
||||
inputType: 'password',
|
||||
allowBlank: false,
|
||||
minLength: 6,
|
||||
maxLength: 32,
|
||||
vtype: 'password',
|
||||
initialPassField: 'new-password'
|
||||
}],
|
||||
buttons: [{
|
||||
text: 'Ok',
|
||||
formBind: true,
|
||||
scope: this,
|
||||
handler: this.changePassword
|
||||
},{
|
||||
text: 'Cancel',
|
||||
scope: this,
|
||||
handler: this.cancel
|
||||
}]
|
||||
}]
|
||||
}
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.action.ChangePasswordWindow.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
changePassword: function(){
|
||||
var win = this;
|
||||
var form = Ext.getCmp('changePasswordForm').getForm();
|
||||
form.submit({
|
||||
method:'POST',
|
||||
waitTitle:'Connecting',
|
||||
waitMsg:'Sending data...',
|
||||
|
||||
success: function(form, action){
|
||||
if ( debug ){
|
||||
console.debug( 'change password success' );
|
||||
}
|
||||
win.close();
|
||||
},
|
||||
|
||||
failure: function(form, action){
|
||||
if ( debug ){
|
||||
console.debug( 'change password failed' );
|
||||
}
|
||||
Ext.Msg.alert('change password failed!');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
cancel: function(){
|
||||
this.close();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -46,6 +46,35 @@ Ext.ns('Sonia.repository');
|
||||
|
||||
// functions
|
||||
|
||||
Sonia.repository.getPermissionValue = function(type){
|
||||
var value = 0;
|
||||
switch (type){
|
||||
case "READ":
|
||||
value = 0;
|
||||
break;
|
||||
case "WRITE":
|
||||
value = 10;
|
||||
break;
|
||||
case "OWNER":
|
||||
value = 100;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Sonia.repository.isMember = function(group){
|
||||
var result = false;
|
||||
if ( Ext.isDefined(state.groups) ){
|
||||
for ( var i=0; i<state.groups.length; i++ ){
|
||||
if ( state.groups[i] == group ){
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Sonia.repository.hasPermission = function(repository, type){
|
||||
var result = false;
|
||||
if ( admin ){
|
||||
@@ -53,10 +82,20 @@ Sonia.repository.hasPermission = function(repository, type){
|
||||
} else {
|
||||
var permissions = repository.permissions;
|
||||
if ( Ext.isDefined(permissions) ){
|
||||
var value = Sonia.repository.getPermissionValue( type );
|
||||
for (var i=0;i<permissions.length; i++ ){
|
||||
if ( permissions[i].name == state.user.name ){
|
||||
result = permissions[i].type == type;
|
||||
break;
|
||||
var p = permissions[i];
|
||||
var pv = Sonia.repository.getPermissionValue( p.type );
|
||||
if ( pv >= value ){
|
||||
if ( p.groupPermission ){
|
||||
if ( Sonia.repository.isMember( p.name ) ){
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
} else if ( p.name == state.user.name ) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +226,7 @@ Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
|
||||
this.permissionStore = new Ext.data.JsonStore({
|
||||
root: 'permissions',
|
||||
fields: [ 'name', 'type' ],
|
||||
fields: [ 'name', 'type', 'groupPermission' ],
|
||||
sortInfo: {
|
||||
field: 'name'
|
||||
}
|
||||
@@ -208,6 +247,7 @@ Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
id: 'type',
|
||||
header: 'Type',
|
||||
dataIndex: 'type',
|
||||
width: 80,
|
||||
editor: new Ext.form.ComboBox({
|
||||
valueField: 'type',
|
||||
displayField: 'type',
|
||||
@@ -224,8 +264,13 @@ Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
]
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
},{
|
||||
id: 'groupPermission',
|
||||
header: 'Group',
|
||||
dataIndex: 'groupPermission',
|
||||
width: 60,
|
||||
editor: new Ext.form.Checkbox()
|
||||
}]
|
||||
});
|
||||
|
||||
if ( update ){
|
||||
|
||||
@@ -120,7 +120,22 @@ Ext.onReady(function(){
|
||||
}]
|
||||
});
|
||||
|
||||
var securitySection = null;
|
||||
|
||||
if ( state.user.type == 'xml' && state.user.name != 'anonymous' ){
|
||||
securitySection = {
|
||||
title: 'Security',
|
||||
items: [{
|
||||
label: 'Change Password',
|
||||
fn: function(){
|
||||
new Sonia.action.ChangePasswordWindow().show();
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
if ( admin ){
|
||||
|
||||
panel.addSections([{
|
||||
id: 'navConfig',
|
||||
title: 'Config',
|
||||
@@ -140,20 +155,31 @@ Ext.onReady(function(){
|
||||
addTabPanel('plugins', 'pluginGrid', 'Plugins');
|
||||
}
|
||||
}]
|
||||
},{
|
||||
title: 'Security',
|
||||
items: [{
|
||||
label: 'Users',
|
||||
fn: function(){
|
||||
addTabPanel('users', 'userPanel', 'Users');
|
||||
}
|
||||
},{
|
||||
label: 'Groups',
|
||||
fn: function(){
|
||||
addTabPanel('groups', 'groupPanel', 'Groups');
|
||||
}
|
||||
}]
|
||||
}]);
|
||||
|
||||
if ( securitySection == null ){
|
||||
securitySection = {
|
||||
title: 'Security',
|
||||
items: []
|
||||
}
|
||||
}
|
||||
|
||||
securitySection.items.push({
|
||||
label: 'Users',
|
||||
fn: function(){
|
||||
addTabPanel('users', 'userPanel', 'Users');
|
||||
}
|
||||
});
|
||||
securitySection.items.push({
|
||||
label: 'Groups',
|
||||
fn: function(){
|
||||
addTabPanel('groups', 'groupPanel', 'Groups');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ( securitySection != null ){
|
||||
panel.addSection( securitySection );
|
||||
}
|
||||
|
||||
if ( state.user.name == 'anonymous' ){
|
||||
|
||||
@@ -69,10 +69,10 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
@Test
|
||||
public void testAuthenticateFailed()
|
||||
{
|
||||
User user = manager.authenticate(request, response, trillian.getName(),
|
||||
AuthenticationResult result = manager.authenticate(request, response, trillian.getName(),
|
||||
"trillian");
|
||||
|
||||
assertNull(user);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,9 +82,9 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
@Test
|
||||
public void testAuthenticateNotFound()
|
||||
{
|
||||
User user = manager.authenticate(request, response, "dent", "trillian");
|
||||
AuthenticationResult result = manager.authenticate(request, response, "dent", "trillian");
|
||||
|
||||
assertNull(user);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,17 +94,17 @@ public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
@Test
|
||||
public void testAuthenticateSuccess()
|
||||
{
|
||||
User user = manager.authenticate(request, response, trillian.getName(),
|
||||
AuthenticationResult result = manager.authenticate(request, response, trillian.getName(),
|
||||
"trillian123");
|
||||
|
||||
assertNotNull(user);
|
||||
assertUserEquals(trillian, user);
|
||||
assertEquals("trilliansType", user.getType());
|
||||
user = manager.authenticate(request, response, perfect.getName(),
|
||||
assertNotNull(result);
|
||||
assertUserEquals(trillian, result.getUser());
|
||||
assertEquals("trilliansType", result.getUser().getType());
|
||||
result = manager.authenticate(request, response, perfect.getName(),
|
||||
"perfect123");
|
||||
assertNotNull(perfect);
|
||||
assertUserEquals(perfect, user);
|
||||
assertEquals("perfectsType", user.getType());
|
||||
assertUserEquals(perfect, result.getUser());
|
||||
assertEquals("perfectsType", result.getUser().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user