Merged enterprise features

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2746 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Paul Holmes-Higgin
2006-05-03 18:34:13 +00:00
parent b620d62954
commit 737f4fa8de
15 changed files with 3535 additions and 10 deletions

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.web.app.servlet;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AbstractAuthenticationFilter
{
private static Log logger = LogFactory.getLog(AbstractAuthenticationFilter.class);
public AbstractAuthenticationFilter()
{
super();
}
/**
* Parse the Accept-Lanaguage HTTP header value
*
* @param req HttpServletRequest
* @return Locale
*/
protected static final Locale parseAcceptLanguageHeader(HttpServletRequest req, List<String> m_languages)
{
// Default the locale
Locale locale = Locale.getDefault();
// Get the accept language header value
String acceptHeader = req.getHeader("Accept-Language");
if ( acceptHeader != null)
{
// Parse the accepted language list
StringTokenizer tokens = new StringTokenizer(acceptHeader, ",");
List<AcceptLanguage> langList = new ArrayList<AcceptLanguage>();
while ( tokens.hasMoreTokens())
{
// Get the current language token
String lang = tokens.nextToken();
float quality = 1.0f;
// Check if the optional quality has been specified
int qpos = lang.indexOf(";");
if ( qpos != -1)
{
// Parse the quality value
try
{
quality = Float.parseFloat(lang.substring(qpos+3));
}
catch (NumberFormatException ex)
{
logger.error("Error parsing Accept-Language value " + lang);
}
// Strip the quality value from the language token
lang = lang.substring(0,qpos);
}
// Add the language to the list
langList.add(new AcceptLanguage(lang, quality));
}
// Debug
if ( logger.isDebugEnabled())
logger.debug("Accept-Language list : " + langList);
// Match the client languages to the available locales
if ( langList.size() > 0)
{
// Search for the best match locale to use for this client
AcceptLanguage useLang = null;
String useName = null;
boolean match = false;
for ( AcceptLanguage curLang : langList)
{
// Match against the available languages
for(String availLang : m_languages)
{
// The accept language may be in 'cc' or 'cc_cc' format
match = false;
if ( curLang.getLanguage().length() == 2)
{
if ( availLang.startsWith(curLang.getLanguage()))
match = true;
}
else if ( availLang.equalsIgnoreCase(curLang.getLanguage()))
match = true;
// If we found a match check if it is a higher quality than the current match.
// If the quality is the same we stick with the existing match as it was nearer the
// start of the list.
if ( match == true)
{
if ( useLang == null ||
( curLang.getQuality() > useLang.getQuality()))
{
useLang = curLang;
useName = availLang;
}
}
}
}
// Debug
if ( logger.isDebugEnabled())
logger.debug("Accept-Language using " + (useLang != null ? useLang.toString() : "<none>"));
// Create the required user locale
if ( useLang != null)
{
Locale useLocale = AcceptLanguage.createLocale(useName);
if ( useLocale != null)
{
locale = useLocale;
// Debug
if ( logger.isDebugEnabled())
logger.debug("Using language " + useLang + ", locale " + locale);
}
}
}
}
// Return the selected locale
return locale;
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.web.app.servlet;
import java.util.Locale;
import java.util.StringTokenizer;
/**
* Accept Language Class
*
* <p>Holds the details of an accepted language from a HTTP Accept-Language header
*
* @author gkspencer
*/
class AcceptLanguage
{
// Language name
private String m_language;
// Quality
private float m_quality = 1.0f;
/**
* Class constructor
*
* @param lang String
* @param quality float
*/
public AcceptLanguage(String lang, float quality)
{
// Convert the language to Java format
m_language = lang.replace('-', '_');
m_quality = quality;
}
/**
* Return the language
*
* @return String
*/
public final String getLanguage()
{
return m_language;
}
/**
* Return the quality
*
* @return float
*/
public final float getQuality()
{
return m_quality;
}
/**
* Create a locale for this language
*
* @return Locale
*/
public final Locale createLocale()
{
return createLocale(getLanguage());
}
/**
* Create a locale for this language
*
* @param locName String
* @return Locale
*/
public final static Locale createLocale(String locName)
{
Locale locale = null;
StringTokenizer t = new StringTokenizer(locName, "_");
int tokens = t.countTokens();
if (tokens == 1)
{
locale = new Locale(locName);
}
else if (tokens == 2)
{
locale = new Locale(t.nextToken(), t.nextToken());
}
else if (tokens == 3)
{
locale = new Locale(t.nextToken(), t.nextToken(), t.nextToken());
}
return locale;
}
/**
* Return the accept language as a string
*
* @return String
*/
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("[");
str.append(getLanguage());
str.append(",");
str.append(getQuality());
str.append("]");
return str.toString();
}
}

View File

@@ -0,0 +1,920 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;
import net.sf.acegisecurity.BadCredentialsException;
import org.alfresco.config.ConfigService;
import org.alfresco.filesys.server.auth.PasswordEncryptor;
import org.alfresco.filesys.server.auth.ntlm.NTLM;
import org.alfresco.filesys.server.auth.ntlm.NTLMLogonDetails;
import org.alfresco.filesys.server.auth.ntlm.NTLMMessage;
import org.alfresco.filesys.server.auth.ntlm.TargetInfo;
import org.alfresco.filesys.server.auth.ntlm.Type1NTLMMessage;
import org.alfresco.filesys.server.auth.ntlm.Type2NTLMMessage;
import org.alfresco.filesys.server.auth.ntlm.Type3NTLMMessage;
import org.alfresco.filesys.server.config.ServerConfiguration;
import org.alfresco.filesys.util.DataPacker;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.MD4PasswordEncoder;
import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl;
import org.alfresco.repo.security.authentication.NTLMMode;
import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* NTLM Authentication Filter Class
*
* @author GKSpencer
*/
public class NTLMAuthenticationFilter extends AbstractAuthenticationFilter implements Filter
{
// NTLM authentication session object names
public static final String NTLM_AUTH_SESSION = "_alfNTLMAuthSess";
public static final String NTLM_AUTH_DETAILS = "_alfNTLMDetails";
// Locale object stored in the session
private static final String LOCALE = "locale";
public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
// NTLM flags mask, used to mask out features that are not supported
private static final int NTLM_FLAGS = NTLM.Flag56Bit + NTLM.FlagLanManKey + NTLM.FlagNegotiateNTLM +
NTLM.FlagNegotiateOEM + NTLM.FlagNegotiateUnicode;
// Debug logging
private static Log logger = LogFactory.getLog(NTLMAuthenticationFilter.class);
// Servlet context, required to get authentication service
private ServletContext m_context;
// File server configuration
private ServerConfiguration m_srvConfig;
// Various services required by NTLM authenticator
private AuthenticationService m_authService;
private AuthenticationComponent m_authComponent;
private PersonService m_personService;
private NodeService m_nodeService;
private TransactionService m_transactionService;
private ConfigService m_configService;
// Password encryptor
private PasswordEncryptor m_encryptor = new PasswordEncryptor();
// Allow guest access
private boolean m_allowGuest;
// Login page address
private String m_loginPage;
// Random number generator used to generate challenge keys
private Random m_random = new Random(System.currentTimeMillis());
// MD4 hash decoder
private MD4PasswordEncoder m_md4Encoder = new MD4PasswordEncoderImpl();
// Local server name, from either the file servers config or DNS host name
private String m_srvName;
// List of available locales (from the web-client configuration)
private List<String> m_languages;
/**
* Initialize the filter
*
* @param args FilterConfig
* @exception ServletException
*/
public void init(FilterConfig args) throws ServletException
{
// Save the servlet context, needed to get hold of the authentication service
m_context = args.getServletContext();
// Setup the authentication context
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
m_nodeService = serviceRegistry.getNodeService();
m_transactionService = serviceRegistry.getTransactionService();
m_authService = (AuthenticationService) ctx.getBean("authenticationService");
m_authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
m_personService = (PersonService) ctx.getBean("personService");
m_configService = (ConfigService) ctx.getBean("webClientConfigService");
m_srvConfig = (ServerConfiguration) ctx.getBean(ServerConfiguration.SERVER_CONFIGURATION);
// Check that the authentication component supports the required mode
if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
m_authComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
{
throw new ServletException("Required authentication mode not available");
}
// Get the local server name, try the file server config first
if ( m_srvConfig != null)
{
m_srvName = m_srvConfig.getServerName();
if ( m_srvName == null)
{
// CIFS server may not be running so the local server name has not been set, generate
// a server name
m_srvName = m_srvConfig.getLocalServerName(true) + "_A";
}
}
else
{
// Get the host name
try
{
// Get the local host name
m_srvName = InetAddress.getLocalHost().getHostName();
// Strip any domain name
int pos = m_srvName.indexOf(".");
if ( pos != -1)
m_srvName = m_srvName.substring(0, pos - 1);
}
catch (UnknownHostException ex)
{
// Log the error
if ( logger.isErrorEnabled())
logger.error("NTLM filter, error getting local host name", ex);
}
}
// Check if the server name is valid
if ( m_srvName == null || m_srvName.length() == 0)
throw new ServletException("Failed to get local server name");
// Check if guest access is to be allowed
String guestAccess = args.getInitParameter("AllowGuest");
if ( guestAccess != null)
{
m_allowGuest = Boolean.parseBoolean(guestAccess);
// Debug
if ( logger.isDebugEnabled() && m_allowGuest)
logger.debug("NTLM filter guest access allowed");
}
// Get a list of the available locales
LanguagesConfigElement config = (LanguagesConfigElement) m_configService.
getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
m_languages = config.getLanguages();
}
/**
* Run the filter
*
* @param sreq ServletRequest
* @param sresp ServletResponse
* @param chain FilterChain
* @exception IOException
* @exception ServletException
*/
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException,
ServletException
{
// Get the HTTP request/response/session
HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse resp = (HttpServletResponse) sresp;
HttpSession httpSess = req.getSession(true);
// Check if there is an authorization header with an NTLM security blob
String authHdr = req.getHeader("Authorization");
boolean reqAuth = false;
if ( authHdr != null && authHdr.startsWith("NTLM"))
reqAuth = true;
// Check if the user is already authenticated
User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
if ( user != null && reqAuth == false)
{
try
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("User " + user.getUserName() + " validate ticket");
// Validate the user ticket
m_authService.validate( user.getTicket());
reqAuth = false;
// Set the current locale
I18NUtil.setLocale(Application.getLanguage(httpSess));
}
catch (AuthenticationException ex)
{
if ( logger.isErrorEnabled())
logger.error("Failed to validate user " + user.getUserName(), ex);
reqAuth = true;
}
}
// If the user has been validated and we do not require re-authentication then continue to
// the next filter
if ( reqAuth == false && user != null)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Authentication not required, chaining ...");
// Chain to the next filter
chain.doFilter(sreq, sresp);
return;
}
// Check if the login page is being accessed, do not intercept the login page
if ( req.getRequestURI().endsWith(getLoginPage()) == true)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Login page requested, chaining ...");
// Chain to the next filter
chain.doFilter( sreq, sresp);
return;
}
// Check if the browser is Opera, if so then display the login page as Opera does not
// support NTLM and displays an error page if a request to use NTLM is sent to it
String userAgent = req.getHeader("user-agent");
if ( userAgent != null && userAgent.indexOf("Opera ") != -1)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Opera detected, redirecting to login page");
// Redirect to the login page
resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
return;
}
// Check the authorization header
if ( authHdr == null) {
// Debug
if ( logger.isDebugEnabled())
logger.debug("New NTLM auth request from " + req.getRemoteHost() + " (" +
req.getRemoteAddr() + ":" + req.getRemotePort() + ")");
// Send back a request for NTLM authentication
resp.setHeader("WWW-Authenticate", "NTLM");
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.flushBuffer();
}
else
{
// Decode the received NTLM blob and validate
final byte[] ntlmByts = Base64.decodeBase64( authHdr.substring(5).getBytes());
int ntlmTyp = NTLMMessage.isNTLMType(ntlmByts);
if ( ntlmTyp == NTLM.Type1)
{
// Process the type 1 NTLM message
Type1NTLMMessage type1Msg = new Type1NTLMMessage(ntlmByts);
processType1(type1Msg, req, resp, httpSess);
}
else if ( ntlmTyp == NTLM.Type3)
{
// Process the type 3 NTLM message
Type3NTLMMessage type3Msg = new Type3NTLMMessage(ntlmByts);
processType3(type3Msg, req, resp, httpSess, chain);
}
else
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("NTLM not handled, redirecting to login page");
// Redirect to the login page
resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
}
}
}
/**
* Return the login page address
*
* @return String
*/
private String getLoginPage()
{
if (m_loginPage == null)
{
m_loginPage = Application.getLoginPage(m_context);
}
return m_loginPage;
}
/**
* Delete the servlet filter
*/
public void destroy()
{
}
/**
* Process a type 1 NTLM message
*
* @param type1Msg Type1NTLMMessage
* @param req HttpServletRequest
* @param resp HttpServletResponse
* @param httpSess HttpSession
* @exception IOException
*/
private void processType1(Type1NTLMMessage type1Msg, HttpServletRequest req, HttpServletResponse resp,
HttpSession httpSess) throws IOException
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Received type1 " + type1Msg);
// Get the existing NTLM details
NTLMLogonDetails ntlmDetails = null;
if ( httpSess != null)
{
ntlmDetails = (NTLMLogonDetails) httpSess.getAttribute(NTLM_AUTH_DETAILS);
}
// Check if cached logon details are available
if ( ntlmDetails != null && ntlmDetails.hasType2Message() && ntlmDetails.hasNTLMHashedPassword() &&
ntlmDetails.hasAuthenticationToken())
{
// Get the authentication server type2 response
Type2NTLMMessage cachedType2 = ntlmDetails.getType2Message();
byte[] type2Bytes = cachedType2.getBytes();
String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes));
// Debug
if ( logger.isDebugEnabled())
logger.debug("Sending cached NTLM type2 to client - " + cachedType2);
// Send back a request for NTLM authentication
resp.setHeader("WWW-Authenticate", ntlmBlob);
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.flushBuffer();
return;
}
else
{
// Clear any cached logon details
httpSess.removeAttribute(NTLM_AUTH_DETAILS);
// Set the 8 byte challenge for the new logon request
byte[] challenge = null;
NTLMPassthruToken authToken = null;
if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
// Generate a random 8 byte challenge
challenge = new byte[8];
DataPacker.putIntelLong(m_random.nextLong(), challenge, 0);
}
else
{
// Create an authentication token for the new logon
authToken = new NTLMPassthruToken();
// Run the first stage of the passthru authentication to get the challenge
m_authComponent.authenticate( authToken);
// Get the challenge from the token
if ( authToken.getChallenge() != null)
challenge = authToken.getChallenge().getBytes();
}
// Get the flags from the client request and mask out unsupported features
int ntlmFlags = type1Msg.getFlags() & NTLM_FLAGS;
// Build a type2 message to send back to the client, containing the challenge
List<TargetInfo> tList = new ArrayList<TargetInfo>();
tList.add(new TargetInfo(NTLM.TargetServer, m_srvName));
Type2NTLMMessage type2Msg = new Type2NTLMMessage();
type2Msg.buildType2(ntlmFlags, m_srvName, challenge, null, tList);
// Store the NTLM logon details, cache the type2 message, and token if using passthru
ntlmDetails = new NTLMLogonDetails();
ntlmDetails.setType2Message( type2Msg);
ntlmDetails.setAuthenticationToken(authToken);
httpSess.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
// Debug
if ( logger.isDebugEnabled())
logger.debug("Sending NTLM type2 to client - " + type2Msg);
// Send back a request for NTLM authentication
byte[] type2Bytes = type2Msg.getBytes();
String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes));
resp.setHeader("WWW-Authenticate", ntlmBlob);
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.flushBuffer();
return;
}
}
/**
* Process a type 3 NTLM message
*
* @param type3Msg Type3NTLMMessage
* @param req HttpServletRequest
* @param resp HttpServletResponse
* @param httpSess HttpSession
* @param chain FilterChain
* @exception IOException
* @exception ServletException
*/
private void processType3(Type3NTLMMessage type3Msg, HttpServletRequest req, HttpServletResponse resp,
HttpSession httpSess, FilterChain chain) throws IOException, ServletException
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Received type3 " + type3Msg);
// Get the existing NTLM details
NTLMLogonDetails ntlmDetails = null;
User user = null;
if ( httpSess != null)
{
ntlmDetails = (NTLMLogonDetails) httpSess.getAttribute(NTLM_AUTH_DETAILS);
user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
}
// Get the NTLM logon details
String userName = type3Msg.getUserName();
String workstation = type3Msg.getWorkstation();
String domain = type3Msg.getDomain();
boolean authenticated = false;
boolean useNTLM = true;
// Check if we are using cached details for the authentication
if ( user != null && ntlmDetails != null && ntlmDetails.hasNTLMHashedPassword())
{
// Check if the received NTLM hashed password matches the cached password
byte[] ntlmPwd = type3Msg.getNTLMHash();
byte[] cachedPwd = ntlmDetails.getNTLMHashedPassword();
if ( ntlmPwd != null)
{
if ( ntlmPwd.length == cachedPwd.length)
{
authenticated = true;
for ( int i = 0; i < ntlmPwd.length; i++)
{
if ( ntlmPwd[i] != cachedPwd[i])
authenticated = false;
}
}
}
// Debug
if ( logger.isDebugEnabled())
logger.debug("Using cached NTLM hash, authenticated = " + authenticated);
try
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("User " + user.getUserName() + " validate ticket");
// Validate the user ticket
m_authService.validate( user.getTicket());
// Set the current locale
I18NUtil.setLocale(Application.getLanguage(httpSess));
}
catch (AuthenticationException ex)
{
if ( logger.isErrorEnabled())
logger.error("Failed to validate user " + user.getUserName(), ex);
// Redirect to the login page
resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
return;
}
// Allow the user to access the requested page
chain.doFilter( req, resp);
return;
}
else
{
// Check if we are using local MD4 password hashes or passthru authentication
if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
{
// Get the stored MD4 hashed password for the user, or null if the user does not exist
String md4hash = m_authComponent.getMD4HashedPassword(userName);
if ( md4hash != null)
{
// Generate the local encrypted password using the challenge that was sent to the client
byte[] p21 = new byte[21];
byte[] md4byts = m_md4Encoder.decodeHash(md4hash);
System.arraycopy(md4byts, 0, p21, 0, 16);
// Generate the local hash of the password using the same challenge
byte[] localHash = null;
try
{
localHash = m_encryptor.doNTLM1Encryption(p21, ntlmDetails.getChallengeKey());
}
catch (NoSuchAlgorithmException ex)
{
}
// Validate the password
byte[] clientHash = type3Msg.getNTLMHash();
if ( clientHash != null && localHash != null && clientHash.length == localHash.length)
{
int i = 0;
while ( i < clientHash.length && clientHash[i] == localHash[i])
i++;
if ( i == clientHash.length)
authenticated = true;
}
}
else
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("User " + userName + " does not have Alfresco account");
// Bypass NTLM authentication and display the logon screen, user account does not
// exist in Alfresco
authenticated = false;
}
}
else
{
// Passthru mode, send the hashed password details to the passthru authentication server
NTLMPassthruToken authToken = (NTLMPassthruToken) ntlmDetails.getAuthenticationToken();
authToken.setUserAndPassword( type3Msg.getUserName(), type3Msg.getNTLMHash(), PasswordEncryptor.NTLM1);
try
{
// Run the second stage of the passthru authentication
m_authComponent.authenticate(authToken);
authenticated = true;
}
catch (BadCredentialsException ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Authentication failed, " + ex.getMessage());
}
catch (AuthenticationException ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Authentication failed, " + ex.getMessage());
}
finally
{
// Clear the authentication token from the NTLM details
ntlmDetails.setAuthenticationToken(null);
}
}
// Check if the user has been authenticated, if so then setup the user environment
if ( authenticated == true)
{
UserTransaction tx = m_transactionService.getUserTransaction();
NodeRef homeSpaceRef = null;
try
{
tx.begin();
// Get user details for the authenticated user
m_authComponent.setCurrentUser(userName.toLowerCase());
// The user name used may be a different case to the NTLM supplied user name, read the current
// user and use that name
userName = m_authComponent.getCurrentUserName();
// Setup User object and Home space ID etc.
NodeRef personNodeRef = m_personService.getPerson(userName);
String currentTicket = m_authService.getCurrentTicket();
user = new User(userName, currentTicket, personNodeRef);
homeSpaceRef = (NodeRef) m_nodeService.getProperty(
personNodeRef,
ContentModel.PROP_HOMEFOLDER);
user.setHomeSpaceId(homeSpaceRef.getId());
// commit
tx.commit();
}
catch (Throwable ex)
{
try
{
tx.rollback();
}
catch (Exception ex2)
{
logger.error("Failed to rollback transaction", ex2);
}
if(ex instanceof RuntimeException)
{
throw (RuntimeException)ex;
}
else if(ex instanceof IOException)
{
throw (IOException)ex;
}
else if(ex instanceof ServletException)
{
throw (ServletException)ex;
}
else
{
throw new RuntimeException("Authentication setup failed", ex);
}
}
// Store the user
httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);
// Set the current locale from the Accept-Lanaguage header if available
Locale userLocale = parseAcceptLanguageHeader(req, m_languages);
if ( userLocale != null)
{
httpSess.setAttribute(LOCALE, userLocale);
httpSess.removeAttribute(MESSAGE_BUNDLE);
}
// Set the locale using the session
I18NUtil.setLocale(Application.getLanguage(httpSess));
// Update the NTLM logon details in the session
if ( ntlmDetails == null)
{
// No cached NTLM details
ntlmDetails = new NTLMLogonDetails( userName, workstation, domain, false, m_srvName);
httpSess.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
// Debug
if ( logger.isDebugEnabled())
logger.debug("No cached NTLM details, created");
}
else
{
// Update the cached NTLM details
ntlmDetails.setDetails(userName, workstation, domain, false, m_srvName);
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
// Debug
if ( logger.isDebugEnabled())
logger.debug("Updated cached NTLM details");
}
// Debug
if ( logger.isDebugEnabled())
logger.debug("User logged on via NTLM, " + ntlmDetails);
// If the original URL requested was the login page then redirect to the browse view
if (req.getRequestURI().endsWith(getLoginPage()) == true)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Login page requested, redirecting to browse page");
// Redirect to the browse view
resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
return;
}
else
{
// Allow the user to access the requested page
chain.doFilter( req, resp);
return;
}
}
else
{
// Check if NTLM should be used, switched off if the user does not exist in the Alfresco
// user database
if (useNTLM == true)
{
// Remove any existing session and NTLM details from the session
httpSess.removeAttribute(NTLM_AUTH_SESSION);
httpSess.removeAttribute(NTLM_AUTH_DETAILS);
// Force the logon to start again
resp.setHeader("WWW-Authenticate", "NTLM");
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resp.flushBuffer();
return;
}
else
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Redirecting to login page");
// Redirect to the login page
resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
return;
}
}
}
}
}

View File

@@ -0,0 +1,317 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;
import org.alfresco.config.ConfigService;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Sample authentication for Novell ICHAINS.
*
* @author Andy Hind
*/
public class NovellIChainsHTTPRequestAuthenticationFilter extends AbstractAuthenticationFilter implements Filter
{
private static final String LOCALE = "locale";
public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
private static Log logger = LogFactory.getLog(NovellIChainsHTTPRequestAuthenticationFilter.class);
private ServletContext context;
private String loginPage;
private AuthenticationComponent authComponent;
private AuthenticationService authService;
private TransactionService transactionService;
private PersonService personService;
private NodeService nodeService;
private List<String> m_languages;
public NovellIChainsHTTPRequestAuthenticationFilter()
{
super();
}
public void destroy()
{
// Nothing to do
}
/**
* Run the filter
*
* @param sreq
* ServletRequest
* @param sresp
* ServletResponse
* @param chain
* FilterChain
* @exception IOException
* @exception ServletException
*/
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException,
ServletException
{
// Get the HTTP request/response/session
HttpServletRequest req = (HttpServletRequest) sreq;
HttpServletResponse resp = (HttpServletResponse) sresp;
HttpSession httpSess = req.getSession(true);
// Check for the ICHAINS header
String authHdr = req.getHeader("x-user");
if(logger.isDebugEnabled())
{
if(authHdr == null)
{
logger.debug("x-user header not found.");
}
else
{
logger.debug("x-user header is <" + authHdr + ">");
}
}
// Throw an error if we have an unknown authentication
if ((authHdr == null) || (authHdr.length() < 1))
{
resp.sendRedirect(req.getContextPath() + "/jsp/noaccess.jsp");
return;
}
// Get the user
String userName = authHdr;
if(logger.isDebugEnabled())
{
logger.debug("User = "+ userName);
}
// See if there is a user in the session and test if it matches
User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
if (user != null)
{
try
{
// Debug
if (logger.isDebugEnabled())
logger.debug("User " + user.getUserName() + " validate ticket");
// Validate the user ticket
if (user.getUserName().equals(userName))
{
// Set the current locale
authComponent.setCurrentUser(user.getUserName());
I18NUtil.setLocale(Application.getLanguage(httpSess));
chain.doFilter(sreq, sresp);
return;
}
else
{
// No match
setAuthenticatedUser(req, httpSess, userName);
}
}
catch (AuthenticationException ex)
{
if (logger.isErrorEnabled())
logger.error("Failed to validate user " + user.getUserName(), ex);
}
}
setAuthenticatedUser(req, httpSess, userName);
// Redirect the login page as it is never seen as we always login by name
if (req.getRequestURI().endsWith(getLoginPage()) == true)
{
if (logger.isDebugEnabled())
logger.debug("Login page requested, chaining ...");
resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
return;
}
else
{
chain.doFilter(sreq, sresp);
return;
}
}
/**
* Set the authenticated user.
*
* It does not check that the user exists at the moment.
*
* @param req
* @param httpSess
* @param userName
*/
private void setAuthenticatedUser(HttpServletRequest req, HttpSession httpSess, String userName)
{
// Set the authentication
authComponent.setCurrentUser(userName);
User user = new User(userName, authService.getCurrentTicket(), personService.getPerson(userName));
// Set up the user information
UserTransaction tx = transactionService.getUserTransaction();
NodeRef homeSpaceRef = null;
try
{
tx.begin();
homeSpaceRef = (NodeRef) nodeService.getProperty(personService.getPerson(userName),
ContentModel.PROP_HOMEFOLDER);
user.setHomeSpaceId(homeSpaceRef.getId());
tx.commit();
}
catch (Throwable ex)
{
logger.error(ex);
try
{
tx.rollback();
}
catch (Exception ex2)
{
logger.error("Failed to rollback transaction", ex2);
}
if(ex instanceof RuntimeException)
{
throw (RuntimeException)ex;
}
else
{
throw new RuntimeException("Failed to set authenticated user", ex);
}
}
// Store the user
httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);
// Set the current locale from the Accept-Lanaguage header if available
Locale userLocale = parseAcceptLanguageHeader(req, m_languages);
if (userLocale != null)
{
httpSess.setAttribute(LOCALE, userLocale);
httpSess.removeAttribute(MESSAGE_BUNDLE);
}
// Set the locale using the session
I18NUtil.setLocale(Application.getLanguage(httpSess));
}
public void init(FilterConfig config) throws ServletException
{
this.context = config.getServletContext();
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
transactionService = serviceRegistry.getTransactionService();
nodeService = serviceRegistry.getNodeService();
authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authService = (AuthenticationService) ctx.getBean("authenticationService");
personService = (PersonService) ctx.getBean("personService");
// Get a list of the available locales
ConfigService configServiceService = (ConfigService) ctx.getBean("webClientConfigService");
LanguagesConfigElement configElement = (LanguagesConfigElement) configServiceService.
getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
m_languages = configElement.getLanguages();
}
/**
* Return the login page address
*
* @return String
*/
private String getLoginPage()
{
if (loginPage == null)
{
loginPage = Application.getLoginPage(context);
}
return loginPage;
}
}

View File

@@ -0,0 +1,979 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.web.bean;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.IContextListener;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.SortableSelectItem;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.common.component.UIBreadcrumb;
import org.alfresco.web.ui.common.component.UIGenericPicker;
import org.alfresco.web.ui.common.component.UIModeList;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.apache.log4j.Logger;
/**
* Backing Bean for the Groups Management pages.
*
* @author Kevin Roast
*/
public class GroupsBean implements IContextListener
{
private static final String FILTER_CHILDREN = "children";
private static final String FILTER_ALL = "all";
private static final String DEFAULT_OUTCOME = "finish";
private static final String MSG_GROUPS = "root_groups";
private static Logger logger = Logger.getLogger(GroupsBean.class);
/** The NodeService to be used by the bean */
private NodeService nodeService;
/** The AuthorityService to be used by the bean */
private AuthorityService authService;
/** personService bean reference */
private PersonService personService;
/** Component references */
private UIRichList groupsRichList;
private UIRichList usersRichList;
/** datamodel for table of users added to group */
private DataModel usersDataModel = null;
/** Currently visible Group Authority */
private String group = null;
private String groupName = null;
/** Action group authority */
private String actionGroup = null;
private String actionGroupName = null;
private int actionGroupItems = 0;
/** selected users to be added to a group */
private List<UserAuthorityDetails> usersForGroup = null;
/** Dialog properties */
private String name = null;
/** RichList view mode */
private String viewMode = "icons";
/** List filter mode */
private String filterMode = FILTER_CHILDREN;
/** Groups path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
// ------------------------------------------------------------------------------
// Construction
/**
* Default Constructor
*/
public GroupsBean()
{
UIContextService.getInstance(FacesContext.getCurrentInstance()).registerBean(this);
}
// ------------------------------------------------------------------------------
// Bean property getters and setters
/**
* @param nodeService The NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param authService The AuthorityService to set.
*/
public void setAuthorityService(AuthorityService authService)
{
this.authService = authService;
}
/**
* @param permissionService The PermissionService to set.
*/
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
/**
* @return Returns the groups RichList to set.
*/
public UIRichList getGroupsRichList()
{
return this.groupsRichList;
}
/**
* @param list The RichList to set.
*/
public void setGroupsRichList(UIRichList list)
{
this.groupsRichList = list;
}
/**
* @return Returns the users RichList.
*/
public UIRichList getUsersRichList()
{
return this.usersRichList;
}
/**
* @param usersRichList The RichList to set.
*/
public void setUsersRichList(UIRichList usersRichList)
{
this.usersRichList = usersRichList;
}
/**
* @return Returns the usersDataModel.
*/
public DataModel getUsersDataModel()
{
if (this.usersDataModel == null)
{
this.usersDataModel = new ListDataModel();
}
this.usersDataModel.setWrappedData(this.usersForGroup);
return this.usersDataModel;
}
/**
* @param usersDataModel The usersDataModel to set.
*/
public void setUsersDataModel(DataModel usersDataModel)
{
this.usersDataModel = usersDataModel;
}
/**
* @return Returns the name.
*/
public String getName()
{
return this.name;
}
/**
* @param name The name to set.
*/
public void setName(String name)
{
this.name = name;
}
/**
* @return Returns the viewMode.
*/
public String getViewMode()
{
return this.viewMode;
}
/**
* @param viewMode The viewMode to set.
*/
public void setViewMode(String viewMode)
{
this.viewMode = viewMode;
}
/**
* @return Returns the filterMode.
*/
public String getFilterMode()
{
return this.filterMode;
}
/**
* @param filterMode The filterMode to set.
*/
public void setFilterMode(String filterMode)
{
this.filterMode = filterMode;
// clear datalist cache ready to change results based on filter setting
contextUpdated();
}
/**
* @return Returns the Group being used for the current action screen.
*/
public String getActionGroup()
{
return this.actionGroup;
}
/**
* @param actionSpace Set the Group to be used for the current action screen.
*/
public void setActionGroup(String group)
{
this.actionGroup = group;
if (group != null)
{
// calculate action group metadata
setActionGroupName(this.authService.getShortName(group));
int count = this.authService.getContainedAuthorities(AuthorityType.GROUP, group, false).size();
count += this.authService.getContainedAuthorities(AuthorityType.USER, group, false).size();
setActionGroupItems(count);
}
else
{
setActionGroupName(null);
setActionGroupItems(0);
}
// clear value used by Create Group form
this.name = null;
// clear list for Add Users to Group screen
this.usersForGroup = new ArrayList<UserAuthorityDetails>();
}
/**
* @return Returns the actionGroupName.
*/
public String getActionGroupName()
{
return this.actionGroupName;
}
/**
* @param actionGroupName The actionGroupName to set.
*/
public void setActionGroupName(String actionGroupName)
{
this.actionGroupName = actionGroupName;
}
/**
* @return Returns the action Group Items count.
*/
public int getActionGroupItems()
{
return this.actionGroupItems;
}
/**
* @param actionGroupItems The action Group Items count to set.
*/
public void setActionGroupItems(int actionGroupItems)
{
this.actionGroupItems = actionGroupItems;
}
/**
* @return The currently displayed group or null if at the root.
*/
public String getCurrentGroup()
{
return this.group;
}
/**
* Set the current Group Authority.
* <p>
* Setting this value causes the UI to update and display the specified node as current.
*
* @param group The current group authority.
*/
public void setCurrentGroup(String group, String groupName)
{
if (logger.isDebugEnabled())
logger.debug("Setting current group: " + group);
// set the current Group Authority for our UI context operations
this.group = group;
this.groupName = groupName;
// inform that the UI needs updating after this change
contextUpdated();
}
/**
* @return Returns the groupName.
*/
public String getGroupName()
{
return this.groupName;
}
/**
* @param groupName The groupName to set.
*/
public void setGroupName(String groupName)
{
this.groupName = groupName;
}
/**
* @return Breadcrumb location list
*/
public List<IBreadcrumbHandler> getLocation()
{
if (this.location == null)
{
List<IBreadcrumbHandler> loc = new ArrayList<IBreadcrumbHandler>(8);
loc.add(new GroupBreadcrumbHandler(null,
Application.getMessage(FacesContext.getCurrentInstance(), MSG_GROUPS)));
this.location = loc;
}
return this.location;
}
/**
* @param location Breadcrumb location list
*/
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
/**
* @return The list of group objects to display. Returns the list of root groups or the
* list of sub-groups for the current group if set.
*/
public List<Map> getGroups()
{
List<Map> groups;
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
Set<String> authorities;
boolean immediate = (this.filterMode.equals(FILTER_CHILDREN));
if (this.group == null)
{
// root groups
if (immediate == true)
{
authorities = this.authService.getAllRootAuthorities(AuthorityType.GROUP);
}
else
{
authorities = this.authService.getAllAuthorities(AuthorityType.GROUP);
}
}
else
{
// sub-group of an existing group
authorities = this.authService.getContainedAuthorities(AuthorityType.GROUP, group, immediate);
}
groups = new ArrayList<Map>(authorities.size());
for (String authority : authorities)
{
Map authMap = new HashMap(3, 1.0f);
String name = this.authService.getShortName(authority);
authMap.put("name", name);
authMap.put("id", authority);
groups.add(authMap);
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
groups = Collections.<Map>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
return groups;
}
/**
* @return The list of user objects to display. Returns the list of user for the current group.
*/
public List<Map> getUsers()
{
List<Map> users;
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
Set<String> authorities;
if (this.group == null)
{
authorities = Collections.<String>emptySet();
}
else
{
// users of an existing group
boolean immediate = (this.filterMode.equals(FILTER_CHILDREN));
authorities = this.authService.getContainedAuthorities(AuthorityType.USER, group, immediate);
}
users = new ArrayList<Map>(authorities.size());
for (String authority : authorities)
{
Map authMap = new HashMap(3, 1.0f);
String userName = this.authService.getShortName(authority);
authMap.put("userName", userName);
authMap.put("id", authority);
// get Person details for this Authority
NodeRef ref = this.personService.getPerson(authority);
String firstName = (String)this.nodeService.getProperty(ref, ContentModel.PROP_FIRSTNAME);
String lastName = (String)this.nodeService.getProperty(ref, ContentModel.PROP_LASTNAME);
// build a sensible label for display
StringBuilder label = new StringBuilder(48);
label.append(firstName)
.append(' ')
.append(lastName);
authMap.put("name", label.toString());
users.add(authMap);
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
users = Collections.<Map>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
return users;
}
/**
* Validate password field data is acceptable
*/
public void validateGroupName(FacesContext context, UIComponent component, Object value)
throws ValidatorException
{
String name = (String)value;
if (name.indexOf('\'') != -1 || name.indexOf('"') != -1 || name.indexOf('\\') != -1)
{
String err = MessageFormat.format(Application.getMessage(context, "groups_err_group_name"),
new Object[]{"', \", \\"});
throw new ValidatorException(new FacesMessage(err));
}
}
/**
* Query callback method executed by the Generic Picker component.
* This method is part of the contract to the Generic Picker, it is up to the backing bean
* to execute whatever query is appropriate and return the results.
*
* @param filterIndex Index of the filter drop-down selection
* @param contains Text from the contains textbox
*
* @return An array of SelectItem objects containing the results to display in the picker.
*/
public SelectItem[] pickerCallback(int filterIndex, String contains)
{
FacesContext context = FacesContext.getCurrentInstance();
SelectItem[] items;
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context);
tx.begin();
// build xpath to match available User/Person objects
ServiceRegistry services = Repository.getServiceRegistry(context);
NodeRef peopleRef = personService.getPeopleContainer();
String xpath = "*[like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "firstName, '%" + contains + "%', false)" +
" or " + "like(@" + NamespaceService.CONTENT_MODEL_PREFIX + ":" + "lastName, '%" + contains + "%', false)]";
List<NodeRef> nodes = services.getSearchService().selectNodes(
peopleRef,
xpath,
null,
services.getNamespaceService(),
false);
items = new SelectItem[nodes.size()];
for (int index=0; index<nodes.size(); index++)
{
NodeRef personRef = nodes.get(index);
String firstName = (String)this.nodeService.getProperty(personRef, ContentModel.PROP_FIRSTNAME);
String lastName = (String)this.nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME);
String username = (String)this.nodeService.getProperty(personRef, ContentModel.PROP_USERNAME);
SelectItem item = new SortableSelectItem(username, firstName + " " + lastName, lastName);
items[index] = item;
}
// commit the transaction
tx.commit();
}
catch (Exception err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err );
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
items = new SelectItem[0];
}
return items;
}
/**
* Set the Group to be used for next action dialog
*/
public void setupGroupAction(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String group = params.get("id");
if (group != null && group.length() != 0)
{
if (logger.isDebugEnabled())
logger.debug("Setup for action, setting current Group to: " + group);
// prepare a node for the action context
setActionGroup(group);
// clear datalist cache ready from return from action dialog
contextUpdated();
}
}
/**
* Clear the Group action context - e.g. ready for a Create Root Group operation
*/
public void clearGroupAction(ActionEvent event)
{
setActionGroup(null);
// clear datalist cache ready from return from action dialog
contextUpdated();
}
/**
* Action called when a Group folder is clicked.
* Navigate into the Group and show child Groups and child Users.
*/
public void clickGroup(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String group = params.get("id");
if (group != null && group.length() != 0)
{
// refresh UI based on node selection
updateUILocation(group);
}
}
/**
* Action handler called on Create Group finish button click.
*/
public String finishCreate()
{
String outcome = DEFAULT_OUTCOME;
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
// create new Group using Authentication Service
this.authService.createAuthority(AuthorityType.GROUP, getActionGroup(), this.name);
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
}
return outcome;
}
/**
* Action handler called on Delete Group finish button click.
*/
public String finishDelete()
{
String outcome = DEFAULT_OUTCOME;
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
// delete group using the Authentication Service
this.authService.deleteAuthority(getActionGroup());
// commit the transaction
tx.commit();
// remove this node from the breadcrumb if required
List<IBreadcrumbHandler> location = getLocation();
GroupBreadcrumbHandler handler = (GroupBreadcrumbHandler)location.get(location.size() - 1);
// see if the current breadcrumb location is our Group
if ( getActionGroup().equals(handler.Group) )
{
location.remove(location.size() - 1);
// now work out which Group to set the list to refresh against
if (location.size() != 0)
{
handler = (GroupBreadcrumbHandler)location.get(location.size() - 1);
this.setCurrentGroup(handler.Group, handler.Label);
}
}
// clear action context
setActionGroup(null);
}
catch (Throwable err)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
}
return outcome;
}
/**
* Remove specified user from the current group
*/
public void removeUser(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String authority = params.get("id");
if (authority != null && authority.length() != 0)
{
try
{
this.authService.removeAuthority(this.group, authority);
// refresh UI after change
contextUpdated();
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
}
}
}
/**
* Action handler called when Finish button clicked on Add User to Group page
*/
public String finishAddUser()
{
String outcome = DEFAULT_OUTCOME;
UserTransaction tx = null;
try
{
FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context);
tx.begin();
// add each selected user to the current group in turn
for (UserAuthorityDetails wrapper : this.usersForGroup)
{
this.authService.addAuthority(getActionGroup(), wrapper.authority);
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
}
return outcome;
}
/**
* Add the selected User to the list for adding to a Group
*/
public void addSelectedUsers(ActionEvent event)
{
UIGenericPicker picker = (UIGenericPicker)event.getComponent().findComponent("picker");
String[] results = picker.getSelectedResults();
if (results != null)
{
for (int i=0; i<results.length; i++)
{
String authority = results[i];
// check for same authority so not added twice
boolean foundExisting = false;
for (int n=0; n<this.usersForGroup.size(); n++)
{
UserAuthorityDetails wrapper = this.usersForGroup.get(n);
if (authority.equals(wrapper.getAuthority()))
{
foundExisting = true;
break;
}
}
if (foundExisting == false)
{
StringBuilder label = new StringBuilder(48);
// build a display label showing the user person name
if (this.personService.personExists(authority) == true)
{
// found a Person with a User authority
NodeRef ref = this.personService.getPerson(authority);
String firstName = (String)this.nodeService.getProperty(ref, ContentModel.PROP_FIRSTNAME);
String lastName = (String)this.nodeService.getProperty(ref, ContentModel.PROP_LASTNAME);
// build a sensible label for display
label.append(firstName)
.append(' ')
.append(lastName);
// add a wrapper object with the details to the results list for display
UserAuthorityDetails userDetails = new UserAuthorityDetails(label.toString(), authority);
this.usersForGroup.add(userDetails);
}
}
}
}
}
/**
* Action handler called when the Remove button is pressed to remove a user from the results list
*/
public void removeUserSelection(ActionEvent event)
{
UserAuthorityDetails wrapper = (UserAuthorityDetails)this.usersDataModel.getRowData();
if (wrapper != null)
{
this.usersForGroup.remove(wrapper);
}
}
/**
* Change the current view mode based on user selection
*/
public void viewModeChanged(ActionEvent event)
{
UIModeList viewList = (UIModeList)event.getComponent();
// update view mode from user selection
setViewMode(viewList.getValue().toString());
}
/**
* Change the current list filter mode based on user selection
*/
public void filterModeChanged(ActionEvent event)
{
UIModeList viewList = (UIModeList)event.getComponent();
// update list filter mode from user selection
setFilterMode(viewList.getValue().toString());
}
/**
* Update the breadcrumb with the clicked Group location
*/
private void updateUILocation(String group)
{
String groupName = this.authService.getShortName(group);
this.location.add(new GroupBreadcrumbHandler(group, groupName));
this.setCurrentGroup(group, groupName);
}
// ------------------------------------------------------------------------------
// IContextListener implementation
/**
* @see org.alfresco.web.app.context.IContextListener#contextUpdated()
*/
public void contextUpdated()
{
if (logger.isDebugEnabled())
logger.debug("Invalidating Group Management Components...");
// force a requery of the richlist dataset
this.groupsRichList.setValue(null);
this.usersRichList.setValue(null);
}
// ------------------------------------------------------------------------------
// Inner classes
/**
* Class to handle breadcrumb interaction for Group pages
*/
private class GroupBreadcrumbHandler implements IBreadcrumbHandler
{
private static final long serialVersionUID = 1871876653151036630L;
/**
* Constructor
*
* @param group The group for this navigation element if any
* @param label Element label
*/
public GroupBreadcrumbHandler(String group, String label)
{
this.Group = group;
this.Label = label;
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
return this.Label;
}
/**
* @see org.alfresco.web.ui.common.component.IBreadcrumbHandler#navigationOutcome(org.alfresco.web.ui.common.component.UIBreadcrumb)
*/
public String navigationOutcome(UIBreadcrumb breadcrumb)
{
// All group breadcrumb elements relate to a Group
// when selected we set the current Group Id and return
setCurrentGroup(this.Group, this.Label);
setLocation( (List)breadcrumb.getValue() );
return null;
}
public String Group;
public String Label;
}
/**
* Simple wrapper bean exposing user authority and person details for JSF results list
*/
public static class UserAuthorityDetails
{
public UserAuthorityDetails(String name, String authority)
{
this.name = name;
this.authority = authority;
}
public String getName()
{
return this.name;
}
public String getAuthority()
{
return this.authority;
}
private String name;
private String authority;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
* Copyright (C) 2005-2006 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
@@ -41,10 +41,24 @@ public class PageTag extends TagSupport
private final static String SCRIPTS_WEBDAV = "/scripts/webdav.js\"></script>\n";
private final static String STYLES_START = "<link rel=\"stylesheet\" href=\"";
private final static String STYLES_MAIN = "/css/main.css\" TYPE=\"text/css\">\n";
/**
* Please ensure you understand the terms of the license before changing the contents of this file.
*/
private final static String ALF_URL = "http://www.alfresco.com";
private final static String ALF_LOGO = "/images/logo/alfresco_logo.gif";
private final static String ALF_TEXT = "Content managed by Alfresco";
private final static String ALF_COPY = "Alfresco Software Inc. (C) 2005-2006 All rights reserved.";
private final static String ALF_LOGO = "http://www.alfresco.com/images/alfresco_community_horizont.gif";
private final static String ALF_TEXT = "Alfresco Community";
private final static String ALF_COPY = "Supplied free of charge with " +
"<a class=footer href='http://www.alfresco.com/services/support/communityterms/#support'>no support</a>, " +
"<a class=footer href='http://www.alfresco.com/services/support/communityterms/#certification'>no certification</a>, " +
"<a class=footer href='http://www.alfresco.com/services/support/communityterms/#maintenance'>no maintenance</a>, " +
"<a class=footer href='http://www.alfresco.com/services/support/communityterms/#warranty'>no warranty</a> and " +
"<a class=footer href='http://www.alfresco.com/services/support/communityterms/#indemnity'>no indemnity</a> by " +
"<a class=footer href='http://www.alfresco.com'>Alfresco</a> or its " +
"<a class=footer href='http://www.alfresco.com/partners/'>Certified Partners</a>. " +
"<a class=footer href='http://www.alfresco.com/services/support/'>Click here for support</a>. " +
"Alfresco Software Inc. <20> 2005-2006 All rights reserved.";
private static Log logger = LogFactory.getLog(PageTag.class);
private static String alfresco = null;
@@ -185,17 +199,22 @@ public class PageTag extends TagSupport
return loginPage;
}
/**
* Please ensure you understand the terms of the license before changing the contents of this file.
*/
private String getAlfrescoButton()
{
if (alfresco == null)
{
String reqPath = ((HttpServletRequest)pageContext.getRequest()).getContextPath();
alfresco = "<center>" +
alfresco = "<center><table><tr><td>" +
"<a href='" + ALF_URL + "'>" +
"<img border=0 alt='' title='" + ALF_TEXT + "' align=absmiddle src='" + reqPath + ALF_LOGO + "'>" +
"</a>&nbsp;" +
"<span style='font-family:Arial,Helvetica,sans-serif;font-size:10px'>" + ALF_COPY +
"</span></center>";
"<img border=0 alt='' title='" + ALF_TEXT + "' align=absmiddle src='" + ALF_LOGO + "'>" +
"</a></td><td align=center>" +
"<span class=footer>" + ALF_COPY +
"</span></td><td><a href='http://sourceforge.net/projects/alfresco'><img border=0 alt='' title='SourceForge' align=absmiddle src='http://sflogo.sourceforge.net/sflogo.php?group_id=143373&type=1'></a>" +
"</td></tr></table></center>";
}
return alfresco;

View File

@@ -296,6 +296,27 @@
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that holds state for the Groups Management screens.
</description>
<managed-bean-name>GroupsBean</managed-bean-name>
<managed-bean-class>org.alfresco.web.bean.GroupsBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>authorityService</property-name>
<value>#{AuthorityService}</value>
</managed-property>
<managed-property>
<property-name>personService</property-name>
<value>#{PersonService}</value>
</managed-property>
</managed-bean>
<managed-bean>
<description>
The bean that holds state for the Category Management screens.

View File

@@ -191,6 +191,10 @@
<from-outcome>manageUsers</from-outcome>
<to-view-id>/jsp/users/users.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>manageGroups</from-outcome>
<to-view-id>/jsp/groups/groups.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>showSystemInfo</from-outcome>
<to-view-id>/jsp/dialog/system-info.jsp</to-view-id>
@@ -633,6 +637,35 @@
</navigation-case>
</navigation-rule>
<!-- navigation rules for the Group Management pages -->
<navigation-rule>
<from-view-id>/jsp/groups/*</from-view-id>
<navigation-case>
<from-outcome>newGroup</from-outcome>
<to-view-id>/jsp/groups/new-group.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>deleteGroup</from-outcome>
<to-view-id>/jsp/groups/delete-group.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>addUser</from-outcome>
<to-view-id>/jsp/groups/add-user.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>deleteUser</from-outcome>
<to-view-id>/jsp/groups/delete-user.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>finish</from-outcome>
<to-view-id>/jsp/groups/groups.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>cancel</from-outcome>
<to-view-id>/jsp/groups/groups.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- Categories screen action outcomes -->
<navigation-rule>
<from-view-id>/jsp/categories/*</from-view-id>

View File

@@ -118,6 +118,26 @@ a.small:hover
color: #4272B4;
}
a.footer:link, a.footer:visited
{
font-size: 10px;
text-decoration: underline;
color: #003366;
}
a.footer:hover
{
font-size: 10px;
text-decoration: underline;
color: #4272B4;
}
.footer
{
font-family:Arial,Helvetica;
font-size: 10px;
}
.pageTitle
{
color: #003366;

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -100,6 +100,9 @@
<tr>
<td><a:actionLink value="#{msg.manage_users}" image="/images/icons/users.gif" action="manageUsers" styleClass="title" actionListener="#{NewUserWizard.setupUsers}" /></td>
</tr>
<tr>
<td><a:actionLink value="#{msg.manage_groups}" image="/images/icons/group.gif" action="manageGroups" styleClass="title" /></td>
</tr>
<tr>
<td><a:actionLink value="#{msg.category_management}" image="/images/icons/categories.gif" action="manageCategories" styleClass="title" /></td>
</tr>

View File

@@ -0,0 +1,194 @@
<%--
Copyright (C) 2005 Alfresco, Inc.
Licensed under the Alfresco Network License. You may obtain a
copy of the License at
http://www.alfrescosoftware.com/legal/
Please view the license relevant to your network subscription.
BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
--%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<r:page titleId="title_add_user_group">
<f:view>
<%-- load a bundle of properties with I18N strings --%>
<f:loadBundle basename="alfresco.messages.webclient" var="msg"/>
<h:form acceptCharset="UTF-8" id="add-user-group">
<%-- Main outer table --%>
<table cellspacing="0" cellpadding="2">
<%-- Title bar --%>
<tr>
<td colspan="2">
<%@ include file="../parts/titlebar.jsp" %>
</td>
</tr>
<%-- Main area --%>
<tr valign="top">
<%-- Shelf --%>
<td>
<%@ include file="../parts/shelf.jsp" %>
</td>
<%-- Work Area --%>
<td width="100%">
<table cellspacing="0" cellpadding="0" width="100%">
<%-- Breadcrumb --%>
<%@ include file="../parts/breadcrumb.jsp" %>
<%-- Status and Actions --%>
<tr>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_4.gif)" width="4"></td>
<td bgcolor="#EEEEEE">
<%-- Status and Actions inner contents table --%>
<%-- Generally this consists of an icon, textual summary and actions for the current object --%>
<table cellspacing="4" cellpadding="0" width="100%">
<tr>
<td width="32">
<h:graphicImage id="logo" url="/images/icons/add_user_large.gif" />
</td>
<td>
<div class="mainSubTitle"><h:outputText value="#{GroupsBean.actionGroupName}" /></div>
<div class="mainTitle"><h:outputText value="#{msg.add_user}" /></div>
<div class="mainSubText"><h:outputText value="#{msg.add_user_group_description}" /></div>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with gradient shadow --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_7.gif" width="4" height="9"></td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_9.gif" width="4" height="9"></td>
</tr>
<%-- Details --%>
<tr valign=top>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_4.gif)" width="4"></td>
<td>
<table cellspacing="0" cellpadding="3" border="0" width="100%">
<tr>
<td width="100%" valign="top">
<a:errors message="#{msg.error_wizard}" styleClass="errorMessage" />
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %>
<table cellpadding="2" cellspacing="2" border="0" width="100%">
<tr>
<td class="mainSubTitle"><h:outputText value="#{msg.select_users}" /></td>
</tr>
<tr>
<td><a:genericPicker id="picker" showFilter="false" queryCallback="#{GroupsBean.pickerCallback}"
actionListener="#{GroupsBean.addSelectedUsers}" /></td>
</tr>
<tr><td class="paddingRow"></td></tr>
<tr>
<td class="mainSubTitle"><h:outputText value="#{msg.selected_users}" /></td>
</tr>
<tr>
<td>
<h:dataTable value="#{GroupsBean.usersDataModel}" var="row"
rowClasses="selectedItemsRow,selectedItemsRowAlt"
styleClass="selectedItems" headerClass="selectedItemsHeader"
cellspacing="0" cellpadding="4"
rendered="#{GroupsBean.usersDataModel.rowCount != 0}">
<h:column>
<f:facet name="header">
<h:outputText value="#{msg.name}" />
</f:facet>
<h:outputText value="#{row.name}" />
</h:column>
<h:column>
<a:actionLink actionListener="#{GroupsBean.removeUserSelection}" image="/images/icons/delete.gif"
value="#{msg.remove}" showLink="false" style="padding-left:6px" />
</h:column>
</h:dataTable>
<a:panel id="no-items" rendered="#{GroupsBean.usersDataModel.rowCount == 0}">
<table cellspacing='0' cellpadding='2' border='0' class='selectedItems'>
<tr>
<td colspan='2' class='selectedItemsHeader'><h:outputText id="no-items-name" value="#{msg.name}" /></td>
</tr>
<tr>
<td class='selectedItemsRow'><h:outputText id="no-items-msg" value="#{msg.no_selected_items}" /></td>
</tr>
</table>
</a:panel>
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %>
</td>
<td valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %>
<table cellpadding="1" cellspacing="1" border="0">
<tr>
<td align="center">
<h:commandButton id="ok-button" value="#{msg.finish_button}" action="#{GroupsBean.finishAddUser}"
styleClass="wizardButton" />
</td>
</tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="cancel" styleClass="wizardButton" />
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with bottom panel graphics --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_7.gif" width="4" height="4"></td>
<td width="100%" align="center" style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_9.gif" width="4" height="4"></td>
</tr>
</table>
</td>
</tr>
</table>
</h:form>
</f:view>
</r:page>

View File

@@ -0,0 +1,182 @@
<%--
Copyright (C) 2005 Alfresco, Inc.
Licensed under the Alfresco Network License. You may obtain a
copy of the License at
http://www.alfrescosoftware.com/legal/
Please view the license relevant to your network subscription.
BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
--%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<r:page titleId="title_delete_group">
<f:view>
<%-- load a bundle of properties with I18N strings --%>
<f:loadBundle basename="alfresco.messages.webclient" var="msg"/>
<%-- set the form name here --%>
<h:form acceptCharset="UTF-8" id="delete-group">
<%-- Main outer table --%>
<table cellspacing="0" cellpadding="2">
<%-- Title bar --%>
<tr>
<td colspan="2">
<%@ include file="../parts/titlebar.jsp" %>
</td>
</tr>
<%-- Main area --%>
<tr valign="top">
<%-- Shelf --%>
<td>
<%@ include file="../parts/shelf.jsp" %>
</td>
<%-- Work Area --%>
<td width="100%">
<table cellspacing="0" cellpadding="0" width="100%">
<%-- Breadcrumb --%>
<%@ include file="../parts/breadcrumb.jsp" %>
<%-- Status and Actions --%>
<tr>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_4.gif)" width="4"></td>
<td bgcolor="#EEEEEE">
<%-- Status and Actions inner contents table --%>
<%-- Generally this consists of an icon, textual summary and actions for the current object --%>
<table cellspacing="4" cellpadding="0" width="100%">
<tr>
<td width="32">
<h:graphicImage url="/images/icons/delete_group_large.gif"/>
</td>
<td>
<div class="mainTitle"><h:outputText value="#{msg.delete_group}" /> '<h:outputText value="#{GroupsBean.actionGroupName}" />'</div>
<div class="mainSubText"><h:outputText value="#{msg.delete_group_info}" /></div>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with gradient shadow --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_7.gif" width="4" height="9"></td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_9.gif" width="4" height="9"></td>
</tr>
<%-- Details --%>
<tr valign=top>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_4.gif)" width="4"></td>
<td>
<table cellspacing="0" cellpadding="4" border="0" width="100%">
<tr>
<td width="100%" valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %>
<table cellpadding="2" cellspacing="2" border="0">
<a:panel id="delete-panel" rendered="#{GroupsBean.actionGroupItems != 0}">
<tr>
<td width="100%" valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellowInner", "#ffffcc"); %>
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td valign=top style="padding-top:2px" width=20><h:graphicImage url="/images/icons/info_icon.gif" width="16" height="16"/></td>
<td class="mainSubText">
<h:outputFormat value="#{msg.delete_group_warning}">
<f:param value="#{GroupsBean.actionGroupItems}" />
</h:outputFormat>
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "yellowInner"); %>
</td>
</tr>
</a:panel>
<tr>
<td class="mainSubTitle">
<h:outputFormat value="#{msg.delete_group_confirm}">
<f:param value="#{GroupsBean.actionGroupName}"/>
</h:outputFormat>
</td>
</tr>
<tr>
<td>
<%-- Error Messages --%>
<%-- messages tag to show messages not handled by other specific message tags --%>
<h:messages globalOnly="true" styleClass="errorMessage" layout="table" />
<td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %>
</td>
<td valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %>
<table cellpadding="1" cellspacing="1" border="0">
<tr>
<td align="center">
<h:commandButton value="#{msg.delete}" action="#{GroupsBean.finishDelete}" styleClass="dialogControls" />
</td>
</tr>
<tr><td class="dialogButtonSpacing"></td></tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="cancel" styleClass="dialogControls" />
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with bottom panel graphics --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_7.gif" width="4" height="4"></td>
<td width="100%" align="center" style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_9.gif" width="4" height="4"></td>
</tr>
</table>
</td>
</tr>
</table>
</h:form>
</f:view>
</r:page>

View File

@@ -0,0 +1,319 @@
<%--
Copyright (C) 2005 Alfresco, Inc.
Licensed under the Alfresco Network License. You may obtain a
copy of the License at
http://www.alfrescosoftware.com/legal/
Please view the license relevant to your network subscription.
BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
--%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<r:page titleId="title_groups_list">
<f:view>
<%-- load a bundle of properties with I18N strings --%>
<f:loadBundle basename="alfresco.messages.webclient" var="msg"/>
<h:form acceptCharset="UTF-8" id="groups">
<%-- Main outer table --%>
<table cellspacing="0" cellpadding="2">
<%-- Title bar --%>
<tr>
<td colspan="2">
<%@ include file="../parts/titlebar.jsp" %>
</td>
</tr>
<%-- Main area --%>
<tr valign="top">
<%-- Shelf --%>
<td>
<%@ include file="../parts/shelf.jsp" %>
</td>
<%-- Work Area --%>
<td width="100%">
<table cellspacing="0" cellpadding="0" width="100%">
<%-- Breadcrumb --%>
<%@ include file="../parts/breadcrumb.jsp" %>
<%-- Status and Actions --%>
<tr>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_4.gif)" width="4"></td>
<td bgcolor="#EEEEEE">
<%-- Status and Actions inner contents table --%>
<%-- Generally this consists of an icon, textual summary and actions for the current object --%>
<table cellspacing="4" cellpadding="0" width="100%">
<tr>
<td width="32">
<h:graphicImage id="logo" url="/images/icons/group_large.gif" />
</td>
<td>
<div class="mainTitle"><h:outputText value="#{msg.groups_management}" /></div>
<div class="mainSubTitle">
<%-- show either root message or the current group name --%>
<h:outputText value="#{msg.root_groups}" rendered="#{GroupsBean.currentGroup == null}" />
<h:outputText value="#{GroupsBean.groupName}" rendered="#{GroupsBean.currentGroup != null}" />
</div>
<div class="mainSubText"><h:outputText value="#{msg.groups_description}" /></div>
</td>
<td align=right>
<%-- Create actions menu --%>
<a:menu id="createMenu" itemSpacing="4" label="#{msg.create_options}" image="/images/icons/menu.gif" menuStyleClass="moreActionsMenu" style="white-space:nowrap">
<a:booleanEvaluator value="#{GroupsBean.currentGroup == null}">
<a:actionLink value="#{msg.new_group}" image="/images/icons/create_group.gif" action="newGroup" actionListener="#{GroupsBean.clearGroupAction}" />
</a:booleanEvaluator>
<a:booleanEvaluator value="#{GroupsBean.currentGroup != null}">
<a:actionLink value="#{msg.new_sub_group}" image="/images/icons/create_group.gif" action="newGroup" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{GroupsBean.currentGroup}" />
</a:actionLink>
</a:booleanEvaluator>
</a:menu>
</td>
<td style="padding-left:4px" width=80>
<%-- More actions menu --%>
<a:menu id="actionsMenu" itemSpacing="4" label="#{msg.more_actions}" image="/images/icons/menu.gif" menuStyleClass="moreActionsMenu" style="white-space:nowrap">
<a:booleanEvaluator value="#{GroupsBean.currentGroup != null}">
<a:actionLink value="#{msg.new_sub_group}" image="/images/icons/create_group.gif" action="newGroup" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{GroupsBean.currentGroup}" />
</a:actionLink>
<a:actionLink value="#{msg.delete_group}" image="/images/icons/delete_group.gif" action="deleteGroup" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{GroupsBean.currentGroup}" />
</a:actionLink>
<%-- TODO: should this be add user(S) - multiple required on generic picker? --%>
<a:actionLink value="#{msg.add_user}" image="/images/icons/add_user.gif" action="addUser" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{GroupsBean.currentGroup}" />
</a:actionLink>
</a:booleanEvaluator>
</a:menu>
</td>
<td class="separator" width=1></td>
<td style="padding-left:4px" width=80 valign=middle>
<%-- Filter settings --%>
<a:modeList itemSpacing="3" iconColumnWidth="20" selectedStyleClass="statusListHighlight" selectedImage="/images/icons/filter.gif"
value="#{GroupsBean.filterMode}" actionListener="#{GroupsBean.filterModeChanged}" menu="true" menuImage="/images/icons/menu.gif" styleClass="moreActionsMenu">
<a:listItem value="children" label="#{msg.group_filter_children}" />
<a:listItem value="all" label="#{msg.group_filter_all}" />
</a:modeList>
</td>
<td class="separator" width=1></td>
<td style="padding-left:4px" width=80 valign=middle>
<%-- View mode settings --%>
<a:modeList itemSpacing="3" iconColumnWidth="20" selectedStyleClass="statusListHighlight" selectedImage="/images/icons/Details.gif"
value="#{GroupsBean.viewMode}" actionListener="#{GroupsBean.viewModeChanged}" menu="true" menuImage="/images/icons/menu.gif" styleClass="moreActionsMenu">
<a:listItem value="icons" label="#{msg.group_icons}" />
<a:listItem value="details" label="#{msg.group_details}" />
</a:modeList>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with gradient shadow --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_7.gif" width="4" height="9"></td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_9.gif" width="4" height="9"></td>
</tr>
<%-- Details --%>
<tr valign=top>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_4.gif)" width="4"></td>
<td>
<table cellspacing="0" cellpadding="3" border="0" width="100%">
<tr>
<td width="100%" valign="top">
<%-- Group Path Breadcrumb --%>
<div style="padding-left:8px;padding-top:4px;padding-bottom:4px">
<a:breadcrumb value="#{GroupsBean.location}" styleClass="title" />
</div>
<%-- Groups List --%>
<div style="padding:4px">
<a:panel id="groups-panel" border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle" label="#{msg.groups}">
<a:richList id="groups-list" binding="#{GroupsBean.groupsRichList}" viewMode="#{GroupsBean.viewMode}" pageSize="12"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow" altRowStyleClass="recordSetRowAlt" width="100%"
value="#{GroupsBean.groups}" var="r" initialSortColumn="name" initialSortDescending="true">
<%-- Primary column for icons view mode --%>
<a:column primary="true" style="padding:2px;text-align:left;vertical-align:top" rendered="#{GroupsBean.viewMode == 'icons'}">
<f:facet name="large-icon">
<a:actionLink value="#{r.name}" image="/images/icons/group_large.gif" actionListener="#{GroupsBean.clickGroup}" showLink="false">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</f:facet>
<a:actionLink value="#{r.name}" actionListener="#{GroupsBean.clickGroup}" styleClass="header">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
<%-- Primary column for details view mode --%>
<a:column primary="true" style="padding:2px;text-align:left" rendered="#{GroupsBean.viewMode == 'details'}">
<f:facet name="small-icon">
<a:actionLink value="#{r.name}" image="/images/icons/group.gif" actionListener="#{GroupsBean.clickGroup}" showLink="false">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</f:facet>
<f:facet name="header">
<a:sortLink label="#{msg.identifier}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<a:actionLink value="#{r.name}" actionListener="#{GroupsBean.clickGroup}">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
<%-- Actions column --%>
<a:column actions="true" style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.actions}"/>
</f:facet>
<a:actionLink value="#{msg.new_sub_group}" image="/images/icons/create_group.gif" showLink="false" styleClass="inlineAction" action="newGroup" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
<a:actionLink value="#{msg.add_user}" image="/images/icons/add_user.gif" showLink="false" styleClass="inlineAction" action="addUser" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
<a:actionLink value="#{msg.delete}" image="/images/icons/delete_group.gif" showLink="false" styleClass="inlineAction" action="deleteGroup" actionListener="#{GroupsBean.setupGroupAction}">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
<a:dataPager/>
</a:richList>
</a:panel>
</div>
<%-- Users in Group list --%>
<div style="padding:4px">
<a:panel id="users-panel" border="white" bgcolor="white" titleBorder="blue" titleBgcolor="#D3E6FE" styleClass="mainSubTitle" label="#{msg.users}">
<a:richList id="users-list" binding="#{GroupsBean.usersRichList}" viewMode="#{GroupsBean.viewMode}" pageSize="12"
styleClass="recordSet" headerStyleClass="recordSetHeader" rowStyleClass="recordSetRow" altRowStyleClass="recordSetRowAlt" width="100%"
value="#{GroupsBean.users}" var="r" initialSortColumn="name" initialSortDescending="true">
<%-- Primary column for icons view mode --%>
<a:column primary="true" style="padding:2px;text-align:left;vertical-align:top;font-weight: bold;" rendered="#{GroupsBean.viewMode == 'icons'}">
<f:facet name="large-icon">
<h:graphicImage alt="#{r.name}" value="/images/icons/user_large.gif" />
</f:facet>
<h:outputText value="#{r.name}" />
</a:column>
<%-- Primary column for details view mode --%>
<a:column primary="true" style="padding:2px;text-align:left;" rendered="#{GroupsBean.viewMode == 'details'}">
<f:facet name="small-icon">
<h:graphicImage alt="#{r.name}" value="/images/icons/person.gif" />
</f:facet>
<f:facet name="header">
<a:sortLink label="#{msg.name}" value="name" mode="case-insensitive" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.name}" />
</a:column>
<%-- Username column --%>
<a:column width="120" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{msg.username}" value="userName" styleClass="header"/>
</f:facet>
<h:outputText value="#{r.userName}" />
</a:column>
<%-- Actions column --%>
<a:column actions="true" style="text-align:left">
<f:facet name="header">
<h:outputText value="#{msg.actions}"/>
</f:facet>
<a:actionLink value="#{msg.remove}" image="/images/icons/remove_user.gif" showLink="false" styleClass="inlineAction" actionListener="#{GroupsBean.removeUser}">
<f:param name="id" value="#{r.id}" />
</a:actionLink>
</a:column>
<a:dataPager/>
</a:richList>
</a:panel>
<div>
</td>
<td valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %>
<table cellpadding="1" cellspacing="1" border="0">
<tr>
<td align="center">
<h:commandButton value="#{msg.close}" action="adminConsole" styleClass="wizardButton" />
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_6.gif)" width="4"></td>
</tr>
<%-- Error Messages --%>
<tr valign="top">
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_4.gif)" width="4"></td>
<td>
<%-- messages tag to show messages not handled by other specific message tags --%>
<h:messages globalOnly="true" styleClass="errorMessage" layout="table" />
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with bottom panel graphics --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_7.gif" width="4" height="4"></td>
<td width="100%" align="center" style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_9.gif" width="4" height="4"></td>
</tr>
</table>
</td>
</tr>
</table>
</h:form>
</f:view>
</r:page>

View File

@@ -0,0 +1,203 @@
<%--
Copyright (C) 2005 Alfresco, Inc.
Licensed under the Alfresco Network License. You may obtain a
copy of the License at
http://www.alfrescosoftware.com/legal/
Please view the license relevant to your network subscription.
BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
--%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<r:page titleId="title_create_group">
<script language="JavaScript1.2">
window.onload = pageLoaded;
function pageLoaded()
{
document.getElementById("new-group:name").focus();
checkButtonState();
}
function checkButtonState()
{
if (document.getElementById("new-group:name").value.length == 0 )
{
document.getElementById("new-group:ok-button").disabled = true;
}
else
{
document.getElementById("new-group:ok-button").disabled = false;
}
}
</script>
<f:view>
<%-- load a bundle of properties with I18N strings --%>
<f:loadBundle basename="alfresco.messages.webclient" var="msg"/>
<h:form acceptCharset="UTF-8" id="new-group">
<%-- Main outer table --%>
<table cellspacing="0" cellpadding="2">
<%-- Title bar --%>
<tr>
<td colspan="2">
<%@ include file="../parts/titlebar.jsp" %>
</td>
</tr>
<%-- Main area --%>
<tr valign="top">
<%-- Shelf --%>
<td>
<%@ include file="../parts/shelf.jsp" %>
</td>
<%-- Work Area --%>
<td width="100%">
<table cellspacing="0" cellpadding="0" width="100%">
<%-- Breadcrumb --%>
<%@ include file="../parts/breadcrumb.jsp" %>
<%-- Status and Actions --%>
<tr>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_4.gif)" width="4"></td>
<td bgcolor="#EEEEEE">
<%-- Status and Actions inner contents table --%>
<%-- Generally this consists of an icon, textual summary and actions for the current object --%>
<table cellspacing="4" cellpadding="0" width="100%">
<tr>
<td width="32">
<h:graphicImage id="logo" url="/images/icons/create_group_large.gif" />
</td>
<td>
<div class="mainSubTitle">
<h:outputText value="#{GroupsBean.groupName}" rendered="#{GroupsBean.actionGroup == null}" />
<h:outputText value="#{GroupsBean.actionGroupName}" rendered="#{GroupsBean.actionGroup != null}" />
</div>
<div class="mainTitle"><h:outputText value="#{msg.new_group}" /></div>
<div class="mainSubText"><h:outputText value="#{msg.new_group_description}" /></div>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with gradient shadow --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_7.gif" width="4" height="9"></td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/statuspanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/statuspanel_9.gif" width="4" height="9"></td>
</tr>
<%-- Details --%>
<tr valign=top>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_4.gif)" width="4"></td>
<td>
<table cellspacing="0" cellpadding="3" border="0" width="100%">
<tr>
<td width="100%" valign="top">
<a:errors message="#{msg.error_create_group_dialog}" styleClass="errorMessage" />
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "white", "white"); %>
<table cellpadding="2" cellspacing="2" border="0" width="100%">
<tr>
<td colspan="2" class="wizardSectionHeading"><h:outputText value="#{msg.group_props}" /></td>
</tr>
<tr>
<td colspan="2" width="100%" valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellowInner", "#ffffcc"); %>
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td valign=top style="padding-top:2px" width=20><h:graphicImage url="/images/icons/info_icon.gif" width="16" height="16"/></td>
<td class="mainSubText">
<h:outputText value="#{msg.create_group_warning}" />
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "yellowInner"); %>
</td>
</tr>
<tr>
<td><h:outputText value="#{msg.identifier}" />:</td>
<td width="100%">
<h:inputText id="name" value="#{GroupsBean.name}" size="35" maxlength="1024" validator="#{GroupsBean.validateGroupName}"
onkeyup="javascript:checkButtonState();" onchange="javascript:checkButtonState();"/>&nbsp;*
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %>
</td>
<td valign="top">
<% PanelGenerator.generatePanelStart(out, request.getContextPath(), "blue", "#D3E6FE"); %>
<table cellpadding="1" cellspacing="1" border="0">
<tr>
<td align="center">
<h:commandButton id="ok-button" value="#{msg.new_group}" action="#{GroupsBean.finishCreate}"
styleClass="wizardButton" disabled="true" />
</td>
</tr>
<tr>
<td align="center">
<h:commandButton value="#{msg.cancel}" action="cancel" styleClass="wizardButton" immediate="true" />
</td>
</tr>
</table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "blue"); %>
</td>
</tr>
</table>
</td>
<td style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_6.gif)" width="4"></td>
</tr>
<%-- separator row with bottom panel graphics --%>
<tr>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_7.gif" width="4" height="4"></td>
<td width="100%" align="center" style="background-image: url(<%=request.getContextPath()%>/images/parts/whitepanel_8.gif)"></td>
<td><img src="<%=request.getContextPath()%>/images/parts/whitepanel_9.gif" width="4" height="4"></td>
</tr>
</table>
</td>
</tr>
</table>
</h:form>
</f:view>
</r:page>