use of org.apache.wiki.workflow.DecisionRequiredException in project jspwiki by apache.
the class UserManagerTest method testSetUserProfileWithDenial.
@Test
public void testSetUserProfileWithDenial() throws Exception {
setUpWithWorkflow();
// First, count the number of users in the db now.
int oldUserCount = m_db.getWikiNames().length;
// Create a new user with random name
WikiSession session = m_engine.guestSession();
String loginName = "TestUser" + String.valueOf(System.currentTimeMillis());
UserProfile profile = m_db.newProfile();
profile.setEmail("jspwiki.tests@mailinator.com");
profile.setLoginName(loginName);
profile.setFullname("FullName" + loginName);
profile.setPassword("password");
// Because user profile saves require approvals, we will catch a Redirect
try {
m_mgr.setUserProfile(session, profile);
Assert.fail("We should have caught a DecisionRequiredException caused by approval!");
} catch (DecisionRequiredException e) {
}
// The user should NOT be saved yet
Assert.assertEquals(oldUserCount, m_db.getWikiNames().length);
// Now, look in Admin's queue, and verify there's a pending Decision there
DecisionQueue dq = m_engine.getWorkflowManager().getDecisionQueue();
Collection decisions = dq.getActorDecisions(m_engine.adminSession());
Assert.assertEquals(1, decisions.size());
// Verify that the Decision has all the facts and attributes we need
Decision d = (Decision) decisions.iterator().next();
List facts = d.getFacts();
Assert.assertEquals(new Fact(UserManager.PREFS_FULL_NAME, profile.getFullname()), facts.get(0));
Assert.assertEquals(new Fact(UserManager.PREFS_LOGIN_NAME, profile.getLoginName()), facts.get(1));
Assert.assertEquals(new Fact(UserManager.FACT_SUBMITTER, session.getUserPrincipal().getName()), facts.get(2));
Assert.assertEquals(new Fact(UserManager.PREFS_EMAIL, profile.getEmail()), facts.get(3));
Assert.assertEquals(profile, d.getWorkflow().getAttribute(UserManager.SAVED_PROFILE));
// Approve the profile
d.decide(Outcome.DECISION_DENY);
// Make sure the profile did NOT save
Assert.assertEquals(oldUserCount, m_db.getWikiNames().length);
}
use of org.apache.wiki.workflow.DecisionRequiredException in project jspwiki by apache.
the class UserManagerTest method testSetUserProfileWithApproval.
@Test
public void testSetUserProfileWithApproval() throws Exception {
setUpWithWorkflow();
// First, count the number of users in the db now.
int oldUserCount = m_db.getWikiNames().length;
// Create a new user with random name
WikiSession session = m_engine.guestSession();
String loginName = "TestUser" + String.valueOf(System.currentTimeMillis());
UserProfile profile = m_db.newProfile();
profile.setEmail("jspwiki.tests@mailinator.com");
profile.setLoginName(loginName);
profile.setFullname("FullName" + loginName);
profile.setPassword("password");
// Because user profile saves require approvals, we will catch a Redirect
try {
m_mgr.setUserProfile(session, profile);
Assert.fail("We should have caught a DecisionRequiredException caused by approval!");
} catch (DecisionRequiredException e) {
}
// The user should NOT be saved yet
Assert.assertEquals(oldUserCount, m_db.getWikiNames().length);
// Now, look in Admin's queue, and verify there's a pending Decision there
DecisionQueue dq = m_engine.getWorkflowManager().getDecisionQueue();
Collection decisions = dq.getActorDecisions(m_engine.adminSession());
Assert.assertEquals(1, decisions.size());
// Verify that the Decision has all the facts and attributes we need
Decision d = (Decision) decisions.iterator().next();
List facts = d.getFacts();
Assert.assertEquals(new Fact(UserManager.PREFS_FULL_NAME, profile.getFullname()), facts.get(0));
Assert.assertEquals(new Fact(UserManager.PREFS_LOGIN_NAME, profile.getLoginName()), facts.get(1));
Assert.assertEquals(new Fact(UserManager.FACT_SUBMITTER, session.getUserPrincipal().getName()), facts.get(2));
Assert.assertEquals(new Fact(UserManager.PREFS_EMAIL, profile.getEmail()), facts.get(3));
Assert.assertEquals(profile, d.getWorkflow().getAttribute(UserManager.SAVED_PROFILE));
// Approve the profile
d.decide(Outcome.DECISION_APPROVE);
// Make sure the profile saved successfully
Assert.assertEquals(oldUserCount + 1, m_db.getWikiNames().length);
// Now delete the profile; should be back to old count
m_db.deleteByLoginName(loginName);
Assert.assertEquals(oldUserCount, m_db.getWikiNames().length);
}
use of org.apache.wiki.workflow.DecisionRequiredException 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);
}
}
}
use of org.apache.wiki.workflow.DecisionRequiredException 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.");
}
}
Aggregations