mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 08:55:44 +01:00
merge with brach issue-42
This commit is contained in:
@@ -33,6 +33,10 @@
|
||||
|
||||
package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
* Configuration object for a SCM-Manager
|
||||
* client (WebInterface, RestClient, ...).
|
||||
@@ -48,6 +52,20 @@ public class ScmClientConfig
|
||||
*/
|
||||
public ScmClientConfig() {}
|
||||
|
||||
/**
|
||||
* Constructs {@link ScmClientConfig} object
|
||||
*
|
||||
*
|
||||
* @param configuration SCM-Manager main configuration
|
||||
* @since 1.14
|
||||
*/
|
||||
public ScmClientConfig(ScmConfiguration configuration)
|
||||
{
|
||||
this.dateFormat = configuration.getDateFormat();
|
||||
this.disableGroupingGrid = configuration.isDisableGroupingGrid();
|
||||
this.enableRepositoryArchive = configuration.isEnableRepositoryArchive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs {@link ScmClientConfig} object
|
||||
*
|
||||
@@ -100,6 +118,18 @@ public class ScmClientConfig
|
||||
return disableGroupingGrid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the repository archive is disabled.
|
||||
*
|
||||
*
|
||||
* @return true if the repository archive is disabled
|
||||
* @since 1.14
|
||||
*/
|
||||
public boolean isEnableRepositoryArchive()
|
||||
{
|
||||
return enableRepositoryArchive;
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -127,11 +157,26 @@ public class ScmClientConfig
|
||||
this.disableGroupingGrid = disableGroupingGrid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the repository archive. Default is disabled.
|
||||
*
|
||||
*
|
||||
* @param enableRepositoryArchive true to disable the repository archive
|
||||
* @since 1.14
|
||||
*/
|
||||
public void setEnableRepositoryArchive(boolean enableRepositoryArchive)
|
||||
{
|
||||
this.enableRepositoryArchive = enableRepositoryArchive;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String dateFormat;
|
||||
|
||||
/** Field description */
|
||||
private boolean enableRepositoryArchive = true;
|
||||
|
||||
/** Field description */
|
||||
private boolean disableGroupingGrid = true;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ public class ScmConfiguration
|
||||
this.forceBaseUrl = other.forceBaseUrl;
|
||||
this.baseUrl = other.baseUrl;
|
||||
this.disableGroupingGrid = other.disableGroupingGrid;
|
||||
this.enableRepositoryArchive = other.enableRepositoryArchive;
|
||||
|
||||
// deprecated fields
|
||||
this.sslPort = other.sslPort;
|
||||
@@ -381,6 +382,18 @@ public class ScmConfiguration
|
||||
return enableProxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the repository archive is enabled.
|
||||
*
|
||||
*
|
||||
* @return true if the repository archive is enabled
|
||||
* @since 1.14
|
||||
*/
|
||||
public boolean isEnableRepositoryArchive()
|
||||
{
|
||||
return enableRepositoryArchive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if ssl is enabled.
|
||||
*
|
||||
@@ -499,6 +512,18 @@ public class ScmConfiguration
|
||||
this.enableProxy = enableProxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the repository archive. Default is disabled.
|
||||
*
|
||||
*
|
||||
* @param enableRepositoryArchive true to disable the repository archive
|
||||
* @since 1.14
|
||||
*/
|
||||
public void setEnableRepositoryArchive(boolean enableRepositoryArchive)
|
||||
{
|
||||
this.enableRepositoryArchive = enableRepositoryArchive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -682,6 +707,9 @@ public class ScmConfiguration
|
||||
private Set<ConfigChangedListener> listeners =
|
||||
new HashSet<ConfigChangedListener>();
|
||||
|
||||
/** Field description */
|
||||
private boolean enableRepositoryArchive = false;
|
||||
|
||||
/** Field description */
|
||||
private boolean disableGroupingGrid = false;
|
||||
|
||||
|
||||
@@ -37,6 +37,10 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
@@ -54,6 +58,14 @@ import java.util.List;
|
||||
public class PermissionUtil
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for PermissionUtil
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(PermissionUtil.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -151,6 +163,40 @@ public class PermissionUtil
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the repository is writable.
|
||||
*
|
||||
*
|
||||
* @param configuration SCM-Manager main configuration
|
||||
* @param repository repository to check
|
||||
* @param securityContext current user security context
|
||||
*
|
||||
* @return true if the repository is writable
|
||||
* @since 1.14
|
||||
*/
|
||||
public static boolean isWritable(ScmConfiguration configuration,
|
||||
Repository repository,
|
||||
WebSecurityContext securityContext)
|
||||
{
|
||||
boolean permitted = false;
|
||||
|
||||
if (configuration.isEnableRepositoryArchive() && repository.isArchived())
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("{} is archived and is not writeable",
|
||||
repository.getName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
permitted = PermissionUtil.hasPermission(repository, securityContext,
|
||||
PermissionType.WRITE);
|
||||
}
|
||||
|
||||
return permitted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -345,6 +345,18 @@ public class Repository extends BasicPropertiesAware implements ModelObject
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the repository is archived.
|
||||
*
|
||||
*
|
||||
* @return true if the repository is archived
|
||||
* @since 1.14
|
||||
*/
|
||||
public boolean isArchived()
|
||||
{
|
||||
return archived;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the {@link Repository} is public readable.
|
||||
*
|
||||
@@ -377,6 +389,18 @@ public class Repository extends BasicPropertiesAware implements ModelObject
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Archive or un archive this repository.
|
||||
*
|
||||
*
|
||||
* @param archived true to enable archive
|
||||
* @since 1.14
|
||||
*/
|
||||
public void setArchived(boolean archived)
|
||||
{
|
||||
this.archived = archived;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the contact of the {@link Repository}. The contact address should be
|
||||
* a email address of a person who is responsible for the {@link Repository}.
|
||||
@@ -516,6 +540,9 @@ public class Repository extends BasicPropertiesAware implements ModelObject
|
||||
@XmlElement(name = "public")
|
||||
private boolean publicReadable = false;
|
||||
|
||||
/** Field description */
|
||||
private boolean archived = false;
|
||||
|
||||
/** Field description */
|
||||
private String type;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.PermissionUtil;
|
||||
import sonia.scm.repository.Repository;
|
||||
@@ -76,10 +77,14 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param securityContextProvider
|
||||
*/
|
||||
public PermissionFilter(Provider<WebSecurityContext> securityContextProvider)
|
||||
public PermissionFilter(ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
}
|
||||
|
||||
@@ -139,10 +144,7 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
{
|
||||
boolean writeRequest = isWriteRequest(request);
|
||||
|
||||
if (PermissionUtil.hasPermission(repository, securityContext,
|
||||
writeRequest
|
||||
? PermissionType.WRITE
|
||||
: PermissionType.READ))
|
||||
if (hasPermission(repository, securityContext, writeRequest))
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
@@ -213,8 +215,43 @@ public abstract class PermissionFilter extends HttpFilter
|
||||
}
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param securityContext
|
||||
* @param writeRequest
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private boolean hasPermission(Repository repository,
|
||||
WebSecurityContext securityContext,
|
||||
boolean writeRequest)
|
||||
{
|
||||
boolean permitted = false;
|
||||
|
||||
if (writeRequest)
|
||||
{
|
||||
permitted = PermissionUtil.isWritable(configuration, repository,
|
||||
securityContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
permitted = PermissionUtil.hasPermission(repository, securityContext,
|
||||
PermissionType.READ);
|
||||
}
|
||||
|
||||
return permitted;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
protected Provider<WebSecurityContext> securityContextProvider;
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import sonia.scm.web.security.WebSecurityContext;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -61,10 +62,11 @@ public abstract class ProviderPermissionFilter extends PermissionFilter
|
||||
* @param repositoryProvider
|
||||
*/
|
||||
public ProviderPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryProvider repositoryProvider)
|
||||
{
|
||||
super(securityContextProvider);
|
||||
super(configuration, securityContextProvider);
|
||||
this.repositoryProvider = repositoryProvider;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ package sonia.scm.web.filter;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
@@ -65,14 +66,17 @@ public abstract class RegexPermissionFilter extends PermissionFilter
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param securityContextProvider
|
||||
* @param repositoryManager
|
||||
*/
|
||||
public RegexPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryManager repositoryManager)
|
||||
{
|
||||
super(securityContextProvider);
|
||||
super(configuration, securityContextProvider);
|
||||
this.repositoryManager = repositoryManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
@@ -65,17 +67,7 @@ public class PermissionUtilTest
|
||||
*/
|
||||
public PermissionUtilTest()
|
||||
{
|
||||
repository = new Repository();
|
||||
admams.getUser().setAdmin(true);
|
||||
|
||||
Permission[] permissions = new Permission[] {
|
||||
new Permission("dent", PermissionType.READ),
|
||||
new Permission("perfect",
|
||||
PermissionType.WRITE),
|
||||
new Permission("marvin",
|
||||
PermissionType.OWNER) };
|
||||
|
||||
repository.setPermissions(Arrays.asList(permissions));
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -108,6 +100,25 @@ public class PermissionUtilTest
|
||||
PermissionUtil.assertPermission(repository, admams, PermissionType.OWNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
repository = new Repository();
|
||||
|
||||
Permission[] permissions = new Permission[] {
|
||||
new Permission("dent", PermissionType.READ),
|
||||
new Permission("perfect",
|
||||
PermissionType.WRITE),
|
||||
new Permission("marvin",
|
||||
PermissionType.OWNER) };
|
||||
|
||||
repository.setPermissions(Arrays.asList(permissions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -161,6 +172,31 @@ public class PermissionUtilTest
|
||||
PermissionType.OWNER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testIsWritable()
|
||||
{
|
||||
ScmConfiguration configuration = new ScmConfiguration();
|
||||
|
||||
configuration.setEnableRepositoryArchive(true);
|
||||
assertTrue(PermissionUtil.isWritable(configuration, repository, perfect));
|
||||
repository.setArchived(true);
|
||||
assertFalse(PermissionUtil.isWritable(configuration, repository, perfect));
|
||||
assertFalse(PermissionUtil.isWritable(configuration, repository, admams));
|
||||
configuration.setEnableRepositoryArchive(false);
|
||||
assertTrue(PermissionUtil.isWritable(configuration, repository, perfect));
|
||||
assertTrue(PermissionUtil.isWritable(configuration, repository, admams));
|
||||
assertFalse(PermissionUtil.isWritable(configuration, repository, dent));
|
||||
configuration.setEnableRepositoryArchive(true);
|
||||
repository.setArchived(false);
|
||||
assertTrue(PermissionUtil.isWritable(configuration, repository, perfect));
|
||||
assertTrue(PermissionUtil.isWritable(configuration, repository, admams));
|
||||
assertFalse(PermissionUtil.isWritable(configuration, repository, dent));
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,7 @@ import sonia.scm.web.security.WebSecurityContext;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -79,10 +80,11 @@ public class GitPermissionFilter extends ProviderPermissionFilter
|
||||
*/
|
||||
@Inject
|
||||
public GitPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryProvider repositoryProvider)
|
||||
{
|
||||
super(securityContextProvider, repositoryProvider);
|
||||
super(configuration, securityContextProvider, repositoryProvider);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
@@ -46,6 +46,7 @@ import sonia.scm.web.security.WebSecurityContext;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -64,10 +65,11 @@ public class HgPermissionFilter extends ProviderPermissionFilter
|
||||
*/
|
||||
@Inject
|
||||
public HgPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryProvider repositoryProvider)
|
||||
{
|
||||
super(securityContextProvider, repositoryProvider);
|
||||
super(configuration, securityContextProvider, repositoryProvider);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.RepositoryProvider;
|
||||
import sonia.scm.web.filter.ProviderPermissionFilter;
|
||||
import sonia.scm.web.security.WebSecurityContext;
|
||||
@@ -72,15 +73,18 @@ public class SvnPermissionFilter extends ProviderPermissionFilter
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param securityContextProvider
|
||||
* @param repository
|
||||
*/
|
||||
@Inject
|
||||
public SvnPermissionFilter(
|
||||
ScmConfiguration configuration,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryProvider repository)
|
||||
{
|
||||
super(securityContextProvider, repository);
|
||||
super(configuration, securityContextProvider, repository);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
@@ -251,8 +251,7 @@ public class AuthenticationResource
|
||||
return new ScmState(contextProvider, securityContext,
|
||||
repositoryManger.getConfiguredTypes(),
|
||||
userManager.getDefaultType(),
|
||||
new ScmClientConfig(configuration.getDateFormat(),
|
||||
configuration.isDisableGroupingGrid()));
|
||||
new ScmClientConfig(configuration));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
@@ -46,6 +46,25 @@ import sonia.scm.ConfigurationException;
|
||||
import sonia.scm.HandlerEvent;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.Type;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.AbstractRepositoryManager;
|
||||
import sonia.scm.repository.BlameViewer;
|
||||
import sonia.scm.repository.ChangesetViewer;
|
||||
import sonia.scm.repository.DiffViewer;
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.PermissionUtil;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryAllreadyExistExeption;
|
||||
import sonia.scm.repository.RepositoryBrowser;
|
||||
import sonia.scm.repository.RepositoryException;
|
||||
import sonia.scm.repository.RepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryHandlerNotFoundException;
|
||||
import sonia.scm.repository.RepositoryHook;
|
||||
import sonia.scm.repository.RepositoryHookEvent;
|
||||
import sonia.scm.repository.RepositoryListener;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.CollectionAppender;
|
||||
@@ -92,6 +111,8 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param contextProvider
|
||||
* @param securityContextProvider
|
||||
* @param repositoryDAO
|
||||
@@ -101,12 +122,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
|
||||
*/
|
||||
@Inject
|
||||
public DefaultRepositoryManager(
|
||||
SCMContextProvider contextProvider,
|
||||
ScmConfiguration configuration, SCMContextProvider contextProvider,
|
||||
Provider<WebSecurityContext> securityContextProvider,
|
||||
RepositoryDAO repositoryDAO, Set<RepositoryHandler> handlerSet,
|
||||
Provider<Set<RepositoryListener>> repositoryListenersProvider,
|
||||
Provider<Set<RepositoryHook>> repositoryHooksProvider)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.securityContextProvider = securityContextProvider;
|
||||
this.repositoryDAO = repositoryDAO;
|
||||
this.repositoryListenersProvider = repositoryListenersProvider;
|
||||
@@ -213,6 +235,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
|
||||
|
||||
assertIsOwner(repository);
|
||||
|
||||
if (configuration.isEnableRepositoryArchive() &&!repository.isArchived())
|
||||
{
|
||||
throw new RepositoryException(
|
||||
"Repository could not deleted, because it is not archived.");
|
||||
}
|
||||
|
||||
if (repositoryDAO.contains(repository))
|
||||
{
|
||||
getHandler(repository).delete(repository);
|
||||
@@ -932,6 +960,9 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private Map<String, RepositoryHandler> handlerMap;
|
||||
|
||||
|
||||
BIN
scm-webapp/src/main/webapp/resources/images/archive.png
Executable file
BIN
scm-webapp/src/main/webapp/resources/images/archive.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 555 B |
@@ -57,6 +57,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
baseUrlText: 'Base Url',
|
||||
forceBaseUrlText: 'Force Base Url',
|
||||
disableGroupingGridText: 'Disable repository Groups',
|
||||
enableRepositoryArchiveText: 'Enable repository archive',
|
||||
|
||||
|
||||
// help
|
||||
@@ -81,7 +82,7 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
baseUrlHelpText: 'The url of the application (with context path) i.e. http://localhost:8080/scm',
|
||||
forceBaseUrlHelpText: 'Redirects to the base url if the request comes from a other url',
|
||||
disableGroupingGridHelpText: 'Disable repository Groups. A complete page reload is required after a change of this value.',
|
||||
|
||||
enableRepositoryArchiveHelpText: 'Enable repository archives. A complete page reload is required after a change of this value.',
|
||||
|
||||
initComponent: function(){
|
||||
|
||||
@@ -108,6 +109,12 @@ Sonia.config.ScmConfigPanel = Ext.extend(Sonia.config.ConfigPanel,{
|
||||
name: 'disableGroupingGrid',
|
||||
inputValue: 'true',
|
||||
helpText: this.disableGroupingGridHelpText
|
||||
},{
|
||||
xtype: 'checkbox',
|
||||
fieldLabel: this.enableRepositoryArchiveText,
|
||||
name: 'enableRepositoryArchive',
|
||||
inputValue: 'true',
|
||||
helpText: this.enableRepositoryArchiveHelpText
|
||||
},{
|
||||
xtype: 'textfield',
|
||||
fieldLabel: this.dateFormatText,
|
||||
|
||||
@@ -36,11 +36,23 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
colDescriptionText: 'Description',
|
||||
colCreationDateText: 'Creation date',
|
||||
colUrlText: 'Url',
|
||||
colArchiveText: 'Archive',
|
||||
emptyText: 'No repository is configured',
|
||||
formTitleText: 'Repository Form',
|
||||
unknownType: 'Unknown',
|
||||
|
||||
archiveIcon: 'resources/images/archive.png',
|
||||
|
||||
filterRequest: null,
|
||||
|
||||
/**
|
||||
* @deprecated use filterRequest
|
||||
*/
|
||||
searchValue: null,
|
||||
|
||||
/**
|
||||
* @deprecated use filterRequest
|
||||
*/
|
||||
typeFilter: null,
|
||||
|
||||
// TODO find better text
|
||||
@@ -82,6 +94,8 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
name:'permissions'
|
||||
},{
|
||||
name: 'properties'
|
||||
},{
|
||||
name: 'archived'
|
||||
}]
|
||||
}),
|
||||
sortInfo: {
|
||||
@@ -139,6 +153,14 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
dataIndex: 'url',
|
||||
renderer: this.renderUrl,
|
||||
width: 250
|
||||
},{
|
||||
id: 'Archive',
|
||||
header: this.colArchiveText,
|
||||
dataIndex: 'archived',
|
||||
width: 40,
|
||||
hidden: ! state.clientConfig.enableRepositoryArchive,
|
||||
renderer: this.renderArchive,
|
||||
scope: this
|
||||
},{
|
||||
id: 'group',
|
||||
dataIndex: 'group',
|
||||
@@ -159,6 +181,13 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
console.debug( msg );
|
||||
}
|
||||
|
||||
if ( state.clientConfig.enableRepositoryArchive ){
|
||||
if ( !this.filterRequest ){
|
||||
this.filterRequest = {};
|
||||
}
|
||||
this.filterRequest.archived = false;
|
||||
}
|
||||
|
||||
var config = {
|
||||
autoExpandColumn: 'description',
|
||||
store: repositoryStore,
|
||||
@@ -180,6 +209,8 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
})
|
||||
};
|
||||
|
||||
this.addEvents('repositorySelected');
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.repository.Grid.superclass.initComponent.apply(this, arguments);
|
||||
|
||||
@@ -188,6 +219,10 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
}
|
||||
},
|
||||
|
||||
renderArchive: function(v){
|
||||
return v ? '<img src=' + this.archiveIcon + ' alt=' + v + '>' : '';
|
||||
},
|
||||
|
||||
convertToGroup: function(v, data){
|
||||
var name = data.name;
|
||||
var i = name.lastIndexOf('/');
|
||||
@@ -220,6 +255,9 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
this.filterStore();
|
||||
}
|
||||
this.ready = true;
|
||||
if (this.filterRequest){
|
||||
this.filterByRequest();
|
||||
}
|
||||
},
|
||||
|
||||
onFallBelowMinHeight: function(height, minHeight){
|
||||
@@ -233,23 +271,63 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
this.ownerCt.doLayout();
|
||||
},
|
||||
|
||||
getFilterRequest: function(){
|
||||
if ( ! this.filterRequest ){
|
||||
this.filterRequest = {};
|
||||
}
|
||||
return this.filterRequest;
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated use filterByRequest
|
||||
*/
|
||||
search: function(value){
|
||||
this.searchValue = value;
|
||||
this.filterStore();
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated use filterByRequest
|
||||
*/
|
||||
filter: function(type){
|
||||
this.typeFilter = type;
|
||||
this.filterStore();
|
||||
},
|
||||
|
||||
clearStoreFilter: function(){
|
||||
this.filterRequest = null;
|
||||
this.searchValue = null;
|
||||
this.typeFilter = null;
|
||||
this.getStore().clearFilter();
|
||||
},
|
||||
|
||||
filterByRequest: function(){
|
||||
if (debug){
|
||||
console.debug('filter repository store by request:');
|
||||
console.debug(this.filterRequest);
|
||||
}
|
||||
var store = this.getStore();
|
||||
if ( ! this.filterRequest ){
|
||||
store.clearFilter();
|
||||
} else {
|
||||
var query = this.filterRequest.query;
|
||||
if ( query ){
|
||||
query = query.toLowerCase();
|
||||
}
|
||||
var archived = ! state.clientConfig.enableRepositoryArchive || this.filterRequest.archived;
|
||||
store.filterBy(function(rec){
|
||||
var desc = rec.get('description');
|
||||
return (! query || rec.get('name').toLowerCase().indexOf(query) >= 0 ||
|
||||
(desc && desc.toLowerCase().indexOf(query) >= 0)) &&
|
||||
(! this.filterRequest.type || rec.get('type') == this.filterRequest.type) &&
|
||||
(archived || ! rec.get('archived'));
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated use filterByRequest
|
||||
*/
|
||||
filterStore: function(){
|
||||
var store = this.getStore();
|
||||
if ( ! this.searchValue && ! this.typeFilter ){
|
||||
@@ -268,6 +346,9 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* TODO move to panel
|
||||
*/
|
||||
selectItem: function(item){
|
||||
if ( debug ){
|
||||
console.debug( item.name + ' selected' );
|
||||
@@ -277,13 +358,16 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
this.parentPanel.updateHistory(item);
|
||||
}
|
||||
|
||||
var owner = Sonia.repository.isOwner(item);
|
||||
|
||||
this.fireEvent('repositorySelected', item, owner);
|
||||
|
||||
var infoPanel = main.getInfoPanel(item.type);
|
||||
infoPanel.item = item;
|
||||
|
||||
var panels = [infoPanel];
|
||||
|
||||
if ( Sonia.repository.isOwner(item) ){
|
||||
Ext.getCmp('repoRmButton').setDisabled(false);
|
||||
if ( owner ){
|
||||
panels.push({
|
||||
item: item,
|
||||
xtype: 'repositorySettingsForm',
|
||||
|
||||
@@ -34,11 +34,21 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
|
||||
titleText: 'Repository Form',
|
||||
emptyText: 'Add or select an Repository',
|
||||
|
||||
// TODO i18n
|
||||
archiveText: 'Archive',
|
||||
unarchiveText: 'Unarchive',
|
||||
archiveTitleText: 'Archive Repository',
|
||||
archiveMsgText: 'Archive Repository "{0}"?',
|
||||
errorArchiveMsgText: 'Repository archival failed',
|
||||
|
||||
removeTitleText: 'Remove Repository',
|
||||
removeMsgText: 'Remove Repository "{0}"?',
|
||||
errorTitleText: 'Error',
|
||||
errorMsgText: 'Repository deletion failed',
|
||||
|
||||
archiveIcon: 'resources/images/archive.png',
|
||||
|
||||
repositoryGrid: null,
|
||||
|
||||
initComponent: function(){
|
||||
@@ -70,6 +80,20 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
handler: this.showAddForm
|
||||
});
|
||||
}
|
||||
|
||||
// repository archive
|
||||
if (state.clientConfig.enableRepositoryArchive){
|
||||
toolbar.push({
|
||||
xtype: 'tbbutton',
|
||||
id: 'repoArchiveButton',
|
||||
disabled: true,
|
||||
text: this.archiveText,
|
||||
icon: this.archiveIcon,
|
||||
scope: this,
|
||||
handler: this.toggleArchive
|
||||
});
|
||||
}
|
||||
|
||||
toolbar.push({
|
||||
xtype: 'tbbutton',
|
||||
id: 'repoRmButton',
|
||||
@@ -127,13 +151,37 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
}
|
||||
});
|
||||
|
||||
// repository archive
|
||||
if (state.clientConfig.enableRepositoryArchive){
|
||||
toolbar.push(' ',{
|
||||
id: 'displayArchived',
|
||||
xtype: 'checkbox',
|
||||
listeners: {
|
||||
check: {
|
||||
fn: this.filterByArchived,
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
},{
|
||||
xtype: 'label',
|
||||
text: 'Archive',
|
||||
cls: 'ytb-text'
|
||||
})
|
||||
}
|
||||
|
||||
var config = {
|
||||
tbar: toolbar,
|
||||
items: [{
|
||||
id: 'repositoryGrid',
|
||||
xtype: 'repositoryGrid',
|
||||
region: 'center',
|
||||
parentPanel: this
|
||||
parentPanel: this,
|
||||
listeners: {
|
||||
repositorySelected: {
|
||||
fn: this.onRepositorySelection,
|
||||
scope: this
|
||||
}
|
||||
}
|
||||
},{
|
||||
id: 'repositoryEditPanel',
|
||||
xtype: 'tabpanel',
|
||||
@@ -170,57 +218,144 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
Sonia.History.add(token);
|
||||
},
|
||||
|
||||
filterByArchived: function(checkbox, checked){
|
||||
var grid = this.getGrid();
|
||||
grid.getFilterRequest().archived = checked;
|
||||
grid.filterByRequest();
|
||||
},
|
||||
|
||||
filterByType: function(combo, rec){
|
||||
this.getGrid().filter(rec.get('name'));
|
||||
var grid = this.getGrid();
|
||||
grid.getFilterRequest().type = rec.get('name');
|
||||
grid.filterByRequest();
|
||||
},
|
||||
|
||||
search: function(field){
|
||||
this.getGrid().search(field.getValue());
|
||||
var grid = this.getGrid();
|
||||
grid.getFilterRequest().query = field.getValue();
|
||||
grid.filterByRequest();
|
||||
},
|
||||
|
||||
removeRepository: function(){
|
||||
getSelectedRepository: function(){
|
||||
var repository = null;
|
||||
var grid = this.getGrid();
|
||||
var selected = grid.getSelectionModel().getSelected();
|
||||
if ( selected ){
|
||||
var item = selected.data;
|
||||
var url = restUrl + 'repositories/' + item.id + '.json';
|
||||
repository = selected.data;
|
||||
} else if (debug) {
|
||||
console.debug( 'no repository selected' );
|
||||
}
|
||||
return repository;
|
||||
},
|
||||
|
||||
executeRemoteCall: function(title, message, method, url, data, failureCallback){
|
||||
Ext.MessageBox.show({
|
||||
title: this.removeTitleText,
|
||||
msg: String.format(this.removeMsgText, item.name),
|
||||
title: title,
|
||||
msg: message,
|
||||
buttons: Ext.MessageBox.OKCANCEL,
|
||||
icon: Ext.MessageBox.QUESTION,
|
||||
fn: function(result){
|
||||
if ( result == 'ok' ){
|
||||
|
||||
if ( debug ){
|
||||
console.debug( 'remove repository ' + item.name );
|
||||
console.debug('call repository repository action '+ method + ' on ' + url );
|
||||
}
|
||||
|
||||
var el = this.el;
|
||||
var tid = setTimeout( function(){el.mask('Loading ...');}, 100);
|
||||
|
||||
if (data && data.group){
|
||||
delete data.group;
|
||||
}
|
||||
|
||||
Ext.Ajax.request({
|
||||
url: url,
|
||||
method: 'DELETE',
|
||||
method: method,
|
||||
jsonData: data,
|
||||
scope: this,
|
||||
success: function(){
|
||||
this.reload();
|
||||
this.resetPanel();
|
||||
clearTimeout(tid);
|
||||
el.unmask();
|
||||
},
|
||||
failure: function(result){
|
||||
main.handleRestFailure(
|
||||
result,
|
||||
clearTimeout(tid);
|
||||
el.unmask();
|
||||
failureCallback.call(this, result);
|
||||
}
|
||||
});
|
||||
} // canceled
|
||||
},
|
||||
scope: this
|
||||
});
|
||||
},
|
||||
|
||||
toggleArchive: function(){
|
||||
var item = this.getSelectedRepository();
|
||||
if ( item ){
|
||||
console.debug(item);
|
||||
|
||||
item.archived = ! item.archived;
|
||||
if (debug){
|
||||
console.debug('toggle repository ' + item.name + ' archive to ' + item.archived);
|
||||
}
|
||||
|
||||
var url = restUrl + 'repositories/' + item.id + '.json';
|
||||
this.executeRemoteCall(this.archiveTitleText,
|
||||
String.format(this.archiveMsgText, item.name),
|
||||
'PUT', url, item, function(result){
|
||||
main.handleFailure(
|
||||
result.status,
|
||||
this.errorTitleText,
|
||||
this.errorArchiveMsgText
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
removeRepository: function(){
|
||||
var item = this.getSelectedRepository();
|
||||
if ( item ){
|
||||
if ( debug ){
|
||||
console.debug( 'remove repository ' + item.name );
|
||||
}
|
||||
|
||||
var url = restUrl + 'repositories/' + item.id + '.json';
|
||||
this.executeRemoteCall(this.archiveTitleText,
|
||||
String.format(this.archiveMsgText, item.name),
|
||||
'DELETE', url, null, function(result){
|
||||
main.handleFailure(
|
||||
result.status,
|
||||
this.errorTitleText,
|
||||
this.errorMsgText
|
||||
);
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
scope: this
|
||||
});
|
||||
|
||||
} else if ( debug ){
|
||||
console.debug( 'no repository selected' );
|
||||
onRepositorySelection: function(item, owner){
|
||||
if ( owner ){
|
||||
if (state.clientConfig.enableRepositoryArchive){
|
||||
var archiveBt = Ext.getCmp('repoArchiveButton');
|
||||
if ( item.archived ){
|
||||
archiveBt.setText(this.unarchiveText);
|
||||
Ext.getCmp('repoRmButton').setDisabled(false);
|
||||
} else {
|
||||
archiveBt.setText(this.archiveText);
|
||||
Ext.getCmp('repoRmButton').setDisabled(true);
|
||||
}
|
||||
archiveBt.setDisabled(false);
|
||||
} else {
|
||||
Ext.getCmp('repoRmButton').setDisabled(false);
|
||||
}
|
||||
} else {
|
||||
Ext.getCmp('repoRmButton').setDisabled(false);
|
||||
if (state.clientConfig.enableRepositoryArchive){
|
||||
Ext.getCmp('repoArchiveButton').setDisabled(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -271,6 +406,10 @@ Sonia.repository.Panel = Ext.extend(Sonia.rest.Panel, {
|
||||
|
||||
reload: function(){
|
||||
this.getGrid().reload();
|
||||
var repo = this.getSelectedRepository();
|
||||
if ( repo ){
|
||||
this.onRepositorySelection(repo, Sonia.repository.isOwner(repo));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.junit.Test;
|
||||
|
||||
import sonia.scm.Type;
|
||||
import sonia.scm.repository.xml.XmlRepositoryDAO;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.store.JAXBStoreFactory;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
import sonia.scm.util.MockUtil;
|
||||
@@ -134,7 +135,9 @@ public class DefaultRepositoryManagerTest extends RepositoryManagerTestBase
|
||||
|
||||
XmlRepositoryDAO repositoryDAO = new XmlRepositoryDAO(factory);
|
||||
|
||||
return new DefaultRepositoryManager(contextProvider,
|
||||
ScmConfiguration configuration = new ScmConfiguration();
|
||||
|
||||
return new DefaultRepositoryManager(configuration, contextProvider,
|
||||
MockUtil.getAdminSecurityContextProvider(), repositoryDAO,
|
||||
handlerSet, listenerProvider, hookProvider);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user