Package org.waveprotocol.box.server.robots.agent.passwd

Source Code of org.waveprotocol.box.server.robots.agent.passwd.PasswordRobot

/**
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.waveprotocol.box.server.robots.agent.passwd;

import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.CANNOT_CHANGE_PASSWORD_FOR_USER;
import static org.waveprotocol.box.server.robots.agent.RobotAgentUtil.changeUserPassword;

import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;

import org.apache.commons.cli.CommandLine;
import org.eclipse.jetty.util.MultiMap;
import org.waveprotocol.box.server.authentication.HttpRequestBasedCallbackHandler;
import org.waveprotocol.box.server.persistence.PersistenceException;
import org.waveprotocol.box.server.robots.agent.AbstractCliRobotAgent;
import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
import org.waveprotocol.wave.model.wave.ParticipantId;

import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

/**
* Robot agent that allows a user to change her own password. The userId should
* be from this wave domain.
*
* When the robot is added to a wave, it prints basic description and then
* inspects text entered by the user. When a new line char is entered it scans
* the last line of the text in the blip and parses it using Apache CLI command
* line interpreter. If the command found to be valid, the robot validates user
* credentials and then changes the password of the user to a new one.
*
* @author yurize@apache.org (Yuri Zelikov)
*/
@SuppressWarnings("serial")
@Singleton
public final class PasswordRobot extends AbstractCliRobotAgent {

  private static final Logger LOG = Logger.getLogger(PasswordRobot.class.getName());
  public static final String ROBOT_URI = AGENT_PREFIX_URI + "/passwd/user";

  /** Configuration for the LoginContext. */
  private final Configuration configuration;
 
  @Inject
  public PasswordRobot(Injector injector) {
    super(injector);
    configuration = injector.getInstance(Configuration.class);
  }

  @Override
  protected String maybeExecuteCommand(CommandLine commandLine, String modifiedBy) {
    String robotMessage = null;
    // Get the user that wants to change her own password.
    if (!modifiedBy.endsWith("@" + getWaveDomain())) {
      // Can change passwords only for users on this wave domain.
      robotMessage =
          String.format("User %s does not belong to the @%s domain\n", modifiedBy,
              getWaveDomain());
    } else {
      String[] args = commandLine.getArgs();
      try {
        ParticipantId participantId = ParticipantId.of(modifiedBy);
        if (args.length == 2) {
          // If current password is empty, i.e. "", then user should pass
          // only the new password.
          args = Arrays.copyOf(args, 3);
          args[2] = args[1];
          args[1] = "";
        }
        String oldPassword = args[1];
        String newPassword = args[2];
        verifyCredentials(oldPassword, participantId);
        changeUserPassword(newPassword, participantId, getAccountStore());
        robotMessage =
            String.format("Changed password for user %s, the new password is: %s", modifiedBy,
                newPassword);
        LOG.info(modifiedBy + " changed  password for user: " + modifiedBy);
      } catch (IllegalArgumentException e) {
        robotMessage = e.getMessage();
        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
      } catch (PersistenceException e) {
        robotMessage = CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy;
        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
      } catch (InvalidParticipantAddress e) {
        robotMessage = CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy;
        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
      } catch (LoginException e) {
        robotMessage =
            CANNOT_CHANGE_PASSWORD_FOR_USER + modifiedBy
                + ". Please verify your old password";
        LOG.log(Level.SEVERE, "userId: " + modifiedBy, e);
      }
    }
    return robotMessage;
  }

  /**
   * Verifies user credentials.
   *
   * @param oldPassword the password to verify.
   * @param participantId the participantId of the user.
   * @throws LoginException if the user provided incorrect password.
   */
  private void verifyCredentials(String password, ParticipantId participantId)
      throws LoginException {
    MultiMap<String> parameters = new MultiMap<String>();
    parameters.putAll(ImmutableMap.of("password", password, "address", participantId.getAddress()));
    CallbackHandler callbackHandler = new HttpRequestBasedCallbackHandler(parameters);
    LoginContext context = new LoginContext("Wave", new Subject(), callbackHandler, configuration);
    // If authentication fails, login() will throw a LoginException.
    context.login();
  }

  @Override
  public String getFullDescription() {
    return getShortDescription() + " If your password is empty - enter only the new password.\n"
        + getUsage() + "\nExample: " + getCommandName() + " " + getExample();
  }

  @Override
  public String getCmdLineSyntax() {
    return "[OPTIONS] [OLD_PASSWORD] [NEW_PASSWORD]";
  }

  @Override
  public String getExample() {
    return "old_password new_password";
  }

  @Override
  public String getShortDescription() {
    return "The command allows users to change their own password. "
    + "Please make sure to use it in a wave without other participants. "
    + "It is also advised to remove yourself from the wave "
    + "when you finished changing the password.";
  }

  @Override
  public String getCommandName() {
    return "passwd";
  }

  @Override
  public String getRobotName() {
    return "Passwd-Bot";
  }

  @Override
  public int getMinNumOfArguments() {
    return 1;
  }
 
  @Override
  public int getMaxNumOfArguments() {
    return 2;
  }
 
  @Override
  public String getRobotUri() {
    return ROBOT_URI;
  }
 
  @Override
  public String getRobotId() {
    return "passwd-bot";
  }
}
TOP

Related Classes of org.waveprotocol.box.server.robots.agent.passwd.PasswordRobot

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.