📄 groupmanager.java
字号:
// If passed members not empty, overwrite String[] members = extractMembers( memberLine ); if ( members.length > 0 ) { group.clear(); for( String member : members ) { group.add( new WikiPrincipal( member ) ); } } return group; } /** * <p> * Extracts group name and members from the HTTP request and populates an * existing Group with them. The Group will either be a copy of an existing * Group (if one can be found), or a new, unregistered Group (if not). * Optionally, this method can throw a WikiSecurityException if the Group * does not yet exist in the GroupManager cache. * </p> * <p> * The <code>group</code> parameter in the HTTP request contains the Group * name to look up and populate. The <code>members</code> parameter * contains the member list. If these differ from those in the existing * group, the passed values override the old values. * </p> * <p> * This method does not commit the new Group to the GroupManager cache. To * do that, use {@link #setGroup(WikiSession, Group)}. * </p> * @param context the current wiki context * @param create whether this method should create a new, empty Group if one * with the requested name is not found. If <code>false</code>, * groups that do not exist will cause a * <code>NoSuchPrincipalException</code> to be thrown * @return a new, populated group * @throws WikiSecurityException if the group name isn't allowed, or if * <code>create</code> is <code>false</code> * and the Group does not exist */ public final Group parseGroup( WikiContext context, boolean create ) throws WikiSecurityException { // Extract parameters HttpServletRequest request = context.getHttpRequest(); String name = request.getParameter( "group" ); String memberLine = request.getParameter( "members" ); // Create the named group; we pass on any NoSuchPrincipalExceptions // that may be thrown if create == false, or WikiSecurityExceptions Group group = parseGroup( name, memberLine, create ); // If no members, add the current user by default if ( group.members().length == 0 ) { group.add( context.getWikiSession().getUserPrincipal() ); } return group; } /** * Removes a named Group from the group database. If not found, throws a * <code>NoSuchPrincipalException</code>. After removal, this method will * commit the delete to the back-end group database. It will also fire a * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_REMOVE} event with * the GroupManager instance as the source and the Group as target. * If <code>index</code> is <code>null</code>, this method throws * an {@link IllegalArgumentException}. * @param index the group to remove * @throws WikiSecurityException if the Group cannot be removed by * the back-end * @see com.ecyrd.jspwiki.auth.authorize.GroupDatabase#delete(Group) */ public final void removeGroup( String index ) throws WikiSecurityException { if ( index == null ) { throw new IllegalArgumentException( "Group cannot be null." ); } Group group = m_groups.get( new GroupPrincipal( index ) ); if ( group == null ) { throw new NoSuchPrincipalException( "Group " + index + " not found" ); } // Delete the group // TODO: need rollback procedure synchronized( m_groups ) { m_groups.remove( group.getPrincipal() ); } m_groupDatabase.delete( group ); fireEvent( WikiSecurityEvent.GROUP_REMOVE, group ); } /** * <p> * Saves the {@link Group} created by a user in a wiki session. This method * registers the Group with the GroupManager and saves it to the back-end * database. If an existing Group with the same name already exists, the new * group will overwrite it. After saving the Group, the group database * changes are committed. * </p> * <p> * This method fires the following events: * </p> * <ul> * <li><strong>When creating a new Group</strong>, this method fires a * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_ADD} with the * GroupManager instance as its source and the new Group as the target.</li> * <li><strong>When overwriting an existing Group</strong>, this method * fires a new {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_REMOVE} * with this GroupManager instance as the source, and the new Group as the * target. It then fires a * {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#GROUP_ADD} event with the * same source and target.</li> * </ul> * <p> * In addition, if the save or commit actions fail, this method will attempt * to restore the older version of the wiki group if it exists. This will * result in a <code>GROUP_REMOVE</code> event (for the new version of the * Group) followed by a <code>GROUP_ADD</code> event (to indicate * restoration of the old version). * </p> * <p> * This method will register the new Group with the GroupManager. For example, * {@link com.ecyrd.jspwiki.auth.AuthenticationManager} attaches each * WikiSession as a GroupManager listener. Thus, the act of registering a * Group with <code>setGroup</code> means that all WikiSessions will * automatically receive group add/change/delete events immediately. * </p> * @param session the wiki session, which may not be <code>null</code> * @param group the Group, which may not be <code>null</code> * @throws WikiSecurityException if the Group cannot be saved by the back-end */ public final void setGroup( WikiSession session, Group group ) throws WikiSecurityException { // TODO: check for appropriate permissions // If group already exists, delete it; fire GROUP_REMOVE event Group oldGroup = m_groups.get( group.getPrincipal() ); if ( oldGroup != null ) { fireEvent( WikiSecurityEvent.GROUP_REMOVE, oldGroup ); synchronized( m_groups ) { m_groups.remove( oldGroup.getPrincipal() ); } } // Copy existing modifier info & timestamps if ( oldGroup != null ) { group.setCreator( oldGroup.getCreator() ); group.setCreated( oldGroup.getCreated() ); group.setModifier( oldGroup.getModifier() ); group.setLastModified( oldGroup.getLastModified() ); } // Add new group to cache; announce GROUP_ADD event synchronized( m_groups ) { m_groups.put( group.getPrincipal(), group ); } fireEvent( WikiSecurityEvent.GROUP_ADD, group ); // Save the group to back-end database; if it fails, // roll back to previous state. Note that the back-end // MUST timestammp the create/modify fields in the Group. try { m_groupDatabase.save( group, session.getUserPrincipal() ); } // We got an exception! Roll back... catch( WikiSecurityException e ) { if ( oldGroup != null ) { // Restore previous version, re-throw... fireEvent( WikiSecurityEvent.GROUP_REMOVE, group ); fireEvent( WikiSecurityEvent.GROUP_ADD, oldGroup ); synchronized( m_groups ) { m_groups.put( oldGroup.getPrincipal(), oldGroup ); } throw new WikiSecurityException( e.getMessage() + " (rolled back to previous version)." ); } // Re-throw security exception throw new WikiSecurityException( e.getMessage() ); } } /** * Validates a Group, and appends any errors to the session errors list. Any * validation errors are added to the wiki session's messages collection * (see {@link WikiSession#getMessages()}. * @param context the current wiki context * @param group the supplied Group */ public final void validateGroup( WikiContext context, Group group ) { InputValidator validator = new InputValidator( MESSAGES_KEY, context ); // Name cannot be null or one of the restricted names try { checkGroupName( context, group.getName() ); } catch( WikiSecurityException e ) { } // Member names must be "safe" strings Principal[] members = group.members(); for( int i = 0; i < members.length; i++ ) { validator.validateNotNull( members[i].getName(), "Full name", InputValidator.ID ); } } /** * Extracts carriage-return separated members into a Set of String objects. * @param memberLine the list of members * @return the list of members */ protected final String[] extractMembers( String memberLine ) { Set<String> members = new HashSet<String>(); if ( memberLine != null ) { StringTokenizer tok = new StringTokenizer( memberLine, "\n" ); while( tok.hasMoreTokens() ) { String uid = tok.nextToken().trim(); if ( uid != null && uid.length() > 0 ) { members.add( uid ); } } } return members.toArray( new String[members.size()] ); } /** * Checks if a String is blank or a restricted Group name, and if it is, * appends an error to the WikiSession's message list. * @param context the wiki context * @param name the Group name to test * @throws WikiSecurityException if <code>session</code> is * <code>null</code> or the Group name is illegal * @see Group#RESTRICTED_GROUPNAMES */ protected final void checkGroupName( WikiContext context, String name ) throws WikiSecurityException { //TODO: groups cannot have the same name as a user // Name cannot be null InputValidator validator = new InputValidator( MESSAGES_KEY, context ); validator.validateNotNull( name, "Group name" ); // Name cannot be one of the restricted names either if( ArrayUtils.contains( Group.RESTRICTED_GROUPNAMES, name ) ) { throw new WikiSecurityException( "The group name '" + name + "' is illegal. Choose another." ); } } // events processing ....................................................... /** * Registers a WikiEventListener with this instance. * This is a convenience method. * @param listener the event listener */ public final synchronized void addWikiEventListener( WikiEventListener listener ) { WikiEventManager.addWikiEventListener( this, listener ); } /** * Un-registers a WikiEventListener with this instance. * This is a convenience method. * @param listener the event listener */ public final synchronized void removeWikiEventListener( WikiEventListener listener ) { WikiEventManager.removeWikiEventListener( this, listener ); } /** * Fires a WikiSecurityEvent of the provided type, Principal and target Object * to all registered listeners. * * @see com.ecyrd.jspwiki.event.WikiSecurityEvent * @param type the event type to be fired * @param target the changed Object, which may be <code>null</code> */ protected final void fireEvent( int type, Object target ) { if ( WikiEventManager.isListening(this) ) { WikiEventManager.fireEvent(this,new WikiSecurityEvent(this,type,target)); } } /** * Listens for {@link com.ecyrd.jspwiki.event.WikiSecurityEvent#PROFILE_NAME_CHANGED} * events. If a user profile's name changes, each group is inspected. If an entry contains * a name that has changed, it is replaced with the new one. No group events are emitted * as a consequence of this method, because the group memberships are still the same; it is * only the representations of the names within that are changing. * @param event the incoming event */ public void actionPerformed(WikiEvent event) { if (! ( event instanceof WikiSecurityEvent ) ) { return; } WikiSecurityEvent se = (WikiSecurityEvent)event; if ( se.getType() == WikiSecurityEvent.PROFILE_NAME_CHANGED ) { WikiSession session = (WikiSession)se.getSource(); UserProfile[] profiles = (UserProfile[])se.getTarget(); Principal[] oldPrincipals = new Principal[] { new WikiPrincipal( profiles[0].getLoginName() ), new WikiPrincipal( profiles[0].getFullname() ), new WikiPrincipal( profiles[0].getWikiName() ) }; Principal newPrincipal = new WikiPrincipal( profiles[1].getFullname() ); // Examine each group int groupsChanged = 0; try { for ( Group group : m_groupDatabase.groups() ) { boolean groupChanged = false; for ( Principal oldPrincipal : oldPrincipals ) { if ( group.isMember( oldPrincipal ) ) { group.remove( oldPrincipal ); group.add( newPrincipal ); groupChanged = true; } } if ( groupChanged ) { setGroup( session, group ); groupsChanged++; } } } catch ( WikiException e ) { // Oooo! This is really bad... log.error( "Could not change user name in Group lists because of GroupDatabase error:" + e.getMessage() ); } log.info( "Profile name change for '" + newPrincipal.toString() + "' caused " + groupsChanged + " groups to change also." ); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -