Search in sources :

Example 1 with WorkflowBuilder

use of org.apache.wiki.workflow.WorkflowBuilder in project jspwiki by apache.

the class UserManager method setUserProfile.

/**
 * <p>
 * Saves the {@link org.apache.wiki.auth.user.UserProfile}for the user in
 * a wiki session. This method verifies that a user profile to be saved
 * doesn't collide with existing profiles; that is, the login name
 * or full name is already used by another profile. If the profile
 * collides, a <code>DuplicateUserException</code> is thrown. After saving
 * the profile, the user database changes are committed, and the user's
 * credential set is refreshed; if custom authentication is used, this means
 * the user will be automatically be logged in.
 * </p>
 * <p>
 * When the user's profile is saved successfully, this method fires a
 * {@link WikiSecurityEvent#PROFILE_SAVE} event with the WikiSession as the
 * source and the UserProfile as target. For existing profiles, if the
 * user's full name changes, this method also fires a "name changed"
 * event ({@link WikiSecurityEvent#PROFILE_NAME_CHANGED}) with the
 * WikiSession as the source and an array containing the old and new
 * UserProfiles, respectively. The <code>NAME_CHANGED</code> event allows
 * the GroupManager and PageManager can change group memberships and
 * ACLs if needed.
 * </p>
 * <p>
 * Note that WikiSessions normally attach event listeners to the
 * UserManager, so changes to the profile will automatically cause the
 * correct Principals to be reloaded into the current WikiSession's Subject.
 * </p>
 * @param session the wiki session, which may not be <code>null</code>
 * @param profile the user profile, which may not be <code>null</code>
 * @throws DuplicateUserException if the proposed profile's login name or full name collides with another
 * @throws WikiException if the save fails for some reason. If the current user does not have
 * permission to save the profile, this will be a {@link org.apache.wiki.auth.WikiSecurityException};
 * if if the user profile must be approved before it can be saved, it will be a
 * {@link org.apache.wiki.workflow.DecisionRequiredException}. All other WikiException
 * indicate a condition that is not normal is probably due to mis-configuration
 */
public void setUserProfile(WikiSession session, UserProfile profile) throws DuplicateUserException, WikiException {
    // Verify user is allowed to save profile!
    final Permission p = new WikiPermission(m_engine.getApplicationName(), WikiPermission.EDIT_PROFILE_ACTION);
    if (!m_engine.getAuthorizationManager().checkPermission(session, p)) {
        throw new WikiSecurityException("You are not allowed to save wiki profiles.");
    }
    // Check if profile is new, and see if container allows creation
    final boolean newProfile = profile.isNew();
    // Check if another user profile already has the fullname or loginname
    final UserProfile oldProfile = getUserProfile(session);
    final boolean nameChanged = (oldProfile == null || oldProfile.getFullname() == null) ? false : !(oldProfile.getFullname().equals(profile.getFullname()) && oldProfile.getLoginName().equals(profile.getLoginName()));
    UserProfile otherProfile;
    try {
        otherProfile = getUserDatabase().findByLoginName(profile.getLoginName());
        if (otherProfile != null && !otherProfile.equals(oldProfile)) {
            throw new DuplicateUserException("security.error.login.taken", profile.getLoginName());
        }
    } catch (final NoSuchPrincipalException e) {
    }
    try {
        otherProfile = getUserDatabase().findByFullName(profile.getFullname());
        if (otherProfile != null && !otherProfile.equals(oldProfile)) {
            throw new DuplicateUserException("security.error.fullname.taken", profile.getFullname());
        }
    } catch (final NoSuchPrincipalException e) {
    }
    // For new accounts, create approval workflow for user profile save.
    if (newProfile && oldProfile != null && oldProfile.isNew()) {
        final WorkflowBuilder builder = WorkflowBuilder.getBuilder(m_engine);
        final Principal submitter = session.getUserPrincipal();
        final Task completionTask = new SaveUserProfileTask(m_engine, session.getLocale());
        // Add user profile attribute as Facts for the approver (if required)
        final boolean hasEmail = profile.getEmail() != null;
        final Fact[] facts = new Fact[hasEmail ? 4 : 3];
        facts[0] = new Fact(PREFS_FULL_NAME, profile.getFullname());
        facts[1] = new Fact(PREFS_LOGIN_NAME, profile.getLoginName());
        facts[2] = new Fact(FACT_SUBMITTER, submitter.getName());
        if (hasEmail) {
            facts[3] = new Fact(PREFS_EMAIL, profile.getEmail());
        }
        final Workflow workflow = builder.buildApprovalWorkflow(submitter, SAVE_APPROVER, null, SAVE_DECISION_MESSAGE_KEY, facts, completionTask, null);
        workflow.setAttribute(SAVED_PROFILE, profile);
        m_engine.getWorkflowManager().start(workflow);
        final boolean approvalRequired = workflow.getCurrentStep() instanceof Decision;
        // If the profile requires approval, redirect user to message page
        if (approvalRequired) {
            throw new DecisionRequiredException("This profile must be approved before it becomes active");
        }
        try {
            final AuthenticationManager mgr = m_engine.getAuthenticationManager();
            if (newProfile && !mgr.isContainerAuthenticated()) {
                mgr.login(session, null, profile.getLoginName(), profile.getPassword());
            }
        } catch (final WikiException e) {
            throw new WikiSecurityException(e.getMessage(), e);
        }
        // Alert all listeners that the profile changed...
        // ...this will cause credentials to be reloaded in the wiki session
        fireEvent(WikiSecurityEvent.PROFILE_SAVE, session, profile);
    } else // For existing accounts, just save the profile
    {
        // If login name changed, rename it first
        if (nameChanged && oldProfile != null && !oldProfile.getLoginName().equals(profile.getLoginName())) {
            getUserDatabase().rename(oldProfile.getLoginName(), profile.getLoginName());
        }
        // Now, save the profile (userdatabase will take care of timestamps for us)
        getUserDatabase().save(profile);
        if (nameChanged) {
            // Fire an event if the login name or full name changed
            final UserProfile[] profiles = new UserProfile[] { oldProfile, profile };
            fireEvent(WikiSecurityEvent.PROFILE_NAME_CHANGED, session, profiles);
        } else {
            // Fire an event that says we have new a new profile (new principals)
            fireEvent(WikiSecurityEvent.PROFILE_SAVE, session, profile);
        }
    }
}
Also used : Task(org.apache.wiki.workflow.Task) WikiException(org.apache.wiki.api.exceptions.WikiException) UserProfile(org.apache.wiki.auth.user.UserProfile) DecisionRequiredException(org.apache.wiki.workflow.DecisionRequiredException) Workflow(org.apache.wiki.workflow.Workflow) DuplicateUserException(org.apache.wiki.auth.user.DuplicateUserException) Fact(org.apache.wiki.workflow.Fact) Decision(org.apache.wiki.workflow.Decision) WikiPermission(org.apache.wiki.auth.permissions.WikiPermission) Permission(java.security.Permission) AllPermission(org.apache.wiki.auth.permissions.AllPermission) WorkflowBuilder(org.apache.wiki.workflow.WorkflowBuilder) WikiPermission(org.apache.wiki.auth.permissions.WikiPermission) Principal(java.security.Principal)

Example 2 with WorkflowBuilder

use of org.apache.wiki.workflow.WorkflowBuilder in project jspwiki by apache.

the class WikiEngine method saveText.

/**
 *  Writes the WikiText of a page into the
 *  page repository. If the <code>jspwiki.properties</code> file contains
 *  the property <code>jspwiki.approver.workflow.saveWikiPage</code> and
 *  its value resolves to a valid user, {@link org.apache.wiki.auth.authorize.Group}
 *  or {@link org.apache.wiki.auth.authorize.Role}, this method will
 *  place a {@link org.apache.wiki.workflow.Decision} in the approver's
 *  workflow inbox and throw a {@link org.apache.wiki.workflow.DecisionRequiredException}.
 *  If the submitting user is authenticated and the page save is rejected,
 *  a notification will be placed in the user's decision queue.
 *
 *  @since 2.1.28
 *  @param context The current WikiContext
 *  @param text    The Wiki markup for the page.
 *  @throws WikiException if the save operation encounters an error during the
 *  save operation. If the page-save operation requires approval, the exception will
 *  be of type {@link org.apache.wiki.workflow.DecisionRequiredException}. Individual
 *  PageFilters, such as the {@link org.apache.wiki.filters.SpamFilter} may also
 *  throw a {@link org.apache.wiki.api.exceptions.RedirectException}.
 */
public void saveText(WikiContext context, String text) throws WikiException {
    // Check if page data actually changed; bail if not
    WikiPage page = context.getPage();
    String oldText = getPureText(page);
    String proposedText = TextUtil.normalizePostData(text);
    if (oldText != null && oldText.equals(proposedText)) {
        return;
    }
    // Check if creation of empty pages is allowed; bail if not
    boolean allowEmpty = TextUtil.getBooleanProperty(m_properties, PROP_ALLOW_CREATION_OF_EMPTY_PAGES, false);
    if (!allowEmpty && !pageExists(page) && text.trim().equals("")) {
        return;
    }
    // Create approval workflow for page save; add the diffed, proposed
    // and old text versions as Facts for the approver (if approval is required)
    // If submitter is authenticated, any reject messages will appear in his/her workflow inbox.
    WorkflowBuilder builder = WorkflowBuilder.getBuilder(this);
    Principal submitter = context.getCurrentUser();
    Task prepTask = new PageManager.PreSaveWikiPageTask(context, proposedText);
    Task completionTask = new PageManager.SaveWikiPageTask();
    String diffText = m_differenceManager.makeDiff(context, oldText, proposedText);
    boolean isAuthenticated = context.getWikiSession().isAuthenticated();
    Fact[] facts = new Fact[5];
    facts[0] = new Fact(PageManager.FACT_PAGE_NAME, page.getName());
    facts[1] = new Fact(PageManager.FACT_DIFF_TEXT, diffText);
    facts[2] = new Fact(PageManager.FACT_PROPOSED_TEXT, proposedText);
    facts[3] = new Fact(PageManager.FACT_CURRENT_TEXT, oldText);
    facts[4] = new Fact(PageManager.FACT_IS_AUTHENTICATED, Boolean.valueOf(isAuthenticated));
    String rejectKey = isAuthenticated ? PageManager.SAVE_REJECT_MESSAGE_KEY : null;
    Workflow workflow = builder.buildApprovalWorkflow(submitter, PageManager.SAVE_APPROVER, prepTask, PageManager.SAVE_DECISION_MESSAGE_KEY, facts, completionTask, rejectKey);
    m_workflowMgr.start(workflow);
    // Let callers know if the page-save requires approval
    if (workflow.getCurrentStep() instanceof Decision) {
        throw new DecisionRequiredException("The page contents must be approved before they become active.");
    }
}
Also used : Task(org.apache.wiki.workflow.Task) DecisionRequiredException(org.apache.wiki.workflow.DecisionRequiredException) Workflow(org.apache.wiki.workflow.Workflow) Fact(org.apache.wiki.workflow.Fact) Decision(org.apache.wiki.workflow.Decision) WorkflowBuilder(org.apache.wiki.workflow.WorkflowBuilder) Principal(java.security.Principal)

Aggregations

Principal (java.security.Principal)2 Decision (org.apache.wiki.workflow.Decision)2 DecisionRequiredException (org.apache.wiki.workflow.DecisionRequiredException)2 Fact (org.apache.wiki.workflow.Fact)2 Task (org.apache.wiki.workflow.Task)2 Workflow (org.apache.wiki.workflow.Workflow)2 WorkflowBuilder (org.apache.wiki.workflow.WorkflowBuilder)2 Permission (java.security.Permission)1 WikiException (org.apache.wiki.api.exceptions.WikiException)1 AllPermission (org.apache.wiki.auth.permissions.AllPermission)1 WikiPermission (org.apache.wiki.auth.permissions.WikiPermission)1 DuplicateUserException (org.apache.wiki.auth.user.DuplicateUserException)1 UserProfile (org.apache.wiki.auth.user.UserProfile)1