/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	Login ログインBeanクラス
//			変更履歴
//				2004/01/08	新規作成	柴田宗近
//
package jp.co.ntt.lms.xms.login.base;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import jp.co.ntt.lms.xmo.Base.XMSBaseClient;
import jp.co.ntt.lms.xms.common.user.*;
import jp.co.ntt.lms.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsInnerException;
import jp.co.ntt.lms.xms.framework.XmsRequest;
import jp.co.ntt.lms.xms.framework.XmsResponse;
import jp.co.ntt.lms.xms.framework.XmsScreenAction;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xms.framework.XmsWarningException;

/**
 * ログイン処理クラス。<BR>
 * 
 * ユーザID、パスワードからログイン可能かどうかを判定し、基本画面へ遷移します。<BR>
 * 
 */
public class LoginAction extends XmsScreenAction {

	/**
	 * ユーザIDのパラメータキー<BR>
	 */
	public final String USER_ID = "userId";

	/**
	 * パスワードのパラメータキー<BR>
	 */
	public final String PASSWORD = "password";

	/**
	 * パスワード失敗有効回数<BR>
	 */
	private final int ERR_PASS_LIMIT_COUNT = 3;

	/**
	 * ログイン情報のセッションキー。<BR>
	 */
	private static final String IS_LOGIN = "isLogin";

	/**
	 * ログインIDのセッションキー。<BR>
	 */
	private static final String LOGIN_ID = "loginId";

	/**
	 * 初期フラグ。<BR>
	 */ 
	private static final String INI_FLAG = "ini_flag";

	/**
	 * 初期化処理を行います。<BR>
	 * 処理はありません。<BR>
	 * @param xmsRequest パラメータオブジェクト
	 * @param XmsResponse レスポンスオブジェクト
	 * @return なし
	 */
	protected void initProcessRequest( XmsRequest xmsRequest, XmsResponse xmsResponse ) {}

	/**
	 * 画面からのログイン処理を行います。<BR>
	 * @param xmsRequest パラメータオブジェクト
	 * @param XmsResponse レスポンスオブジェクト
	 * @exception XmsException  XMS独自例外
	 */
	protected void processRequest( XmsRequest xmsRequest, XmsResponse xmsResponse )
		throws XmsException {

		// ユーザID
		String loginID = null;
		// パスワード
		String password = null;
		// 初期表示フラグ
		String iniflg = null;

		// リクエスト情報を取得
		HttpServletRequest request = xmsRequest.getRequest();

		// セッションを取得
		HttpSession session = request.getSession();
		session.removeAttribute( IS_LOGIN ); 

		// 初期表示フラグを取得
		// 初期表示フラグはカタログ承認結果画面からログイン時に「on」となる。
		// それ以外のログオン時は「null」となる
		iniflg = request.getParameter( INI_FLAG );

		// 「on」時はセッションよりログインIDとパスワードを取得
		if ( iniflg != null && iniflg.length() > 0 ) {
			loginID = (String)session.getAttribute( LOGIN_ID );
			password = (String)session.getAttribute( PASSWORD );
		} else {
			// パラメータの処理
			loginID = request.getParameter( USER_ID );
			password = request.getParameter( PASSWORD );
		}
		
		// パラメータのnullチェックを行う
		if( loginID == null ) {	
			// パラメータエラー処理
			throw new XmsInnerException( "パラメータエラー（ログインIDがnull）" );
		}
		if( password == null ) {
			// パラメータエラー処理
			throw new XmsInnerException( "パラメータエラー（パスワードがnull）" );
		}

		// XMOの起動チェック
		if( isLaunch() == false ) {
			// 起動中なら処理終了
			// XMO起動中
			// ワーニングメッセージに対応するキーをコンストラクタで設定する
			// 上位クラスでメッセージを取得し、画面に表示する
			throw new XmsWarningException( "base.w.login.starting" );
		}

		// ユーザオブジェクトのインスタンス化
		User userObject = new User();
		// ログインチェック処理の戻り値
		// ログイン処理ではログインIDとパスワードの正当性及び、削除フラグのチェックを行う。
		// 権限チェックは別途isRolesAssignmentメソッドで行う。
		boolean checkResultLogin = userObject.checkLogin( loginID, password );

		// ログイン処理が失敗した場合は
		// 失敗した内容をチェックする。
		if( checkResultLogin == false ) {

			// PeopleテーブルにログインIDが存在していたかどうか
			if( userObject.isExist() == false ) {
				// 存在していない場合
				// ワーニングとする
				throw new XmsWarningException( "base.w.login.loginidmissmatch" );
			}

			// 削除状態になっていたかどうか
			//-----------------------------------------------------------------------------
			// 削除状態とは
			//   ログインIDのレコードは存在するが、削除フラグが「1」になっていること。
			//   AD同期処理によって作られたユーザを削除した場合（未所属となる）が削除状態。
			//-----------------------------------------------------------------------------
			if( userObject.isDeleted() == true ) {
				// 存在していない場合
				// ワーニングとする
				throw new XmsWarningException( "base.w.login.loginidmissmatch" );
			}

			// パスワードが一致していたかどうか
			if( userObject.isAgreePassword() == false ) {
				// パスワードチェックで失敗した場合はパスワードリマインダチェックを行う
				// （連続して同一ログインIDで３回パスワードを間違えた場合は
				//   パスワードリマインダ画面に遷移する)

				// 現在のパスワード不一致回数を取得
				int intAccessCount = this.getErrPassCount( session, loginID );

				// 失敗回数が有効回数に達したかどうか
				if( intAccessCount == ERR_PASS_LIMIT_COUNT ) {
					// 達している場合
					// セッションに情報格納

					OperateSession.setSessionFromErrorPassword( session, 
																 loginID, 
																 new Integer( 0 ),
																 userObject.getUserID() );

					// ３回間違えた場合はパスワードリマインダ画面に遷移する

					// 返却値オブジェクトのインスタンス生成
					xmsResponse.setBusinessBeanName("Login");
					// 返却値タイプを設定　この場合はリダイレクト
					xmsResponse.setOutType( XmsResponse.REDIRECT );
					// リダイレクト先URLを設定
					xmsResponse.setUrl( "./SendMail.vm" );
					// 処理終了
					return;
				}

				// ３回未満の場合
				// その回数をセッションに格納

				OperateSession.setSessionFromErrorPassword( session, 
															 loginID, 
															 new Integer( intAccessCount ),
															 null );

				// パスワード不正メッセージ
				throw new XmsWarningException( "base.w.login.passwordmissmacth" );
			}

		}

		// 権限が割り当てられているか
		// ユーザにアサインされている役割（Role）が１つ以上あればtrue
		if( userObject.isRolesAssignment() == false ) {
			// １つも割り当てられていない場合
			// ワーニングとする
			// 権限割り当て無しのメッセージ
			throw new XmsWarningException( "base.w.login.noroles" );
		}

		// ログイン処理が正常に終了した場合
		// セッションの設定
		OperateSession.setSessionFromLogin( session, userObject );

		// デフォルトツリー表示タイプの取得
		//--------------------------------------------------------------
		// ツリー表示タイプとは
		// 基本画面にてユーザツリー、LOツリーのどちらを表示させるのか
		// という値
		//   ユーザツリー：「1」
		//   L0ツリー    ：「2」
		//
		// デフォルトツリータイプとは
		//   ユーザに割り当てられている権限（XMOEntry）を
		//   まとめたもの（初期メニュー）に割り当てられている優先度が
		//   一番高い（値が一番小さい）もののツリー表示タイプのこと
		//--------------------------------------------------------------
		String defaultTreeType = userObject.getDefaultTreeType();

		// 学習者かどうかの判定
		boolean isLearner = userObject.isLearner();

		// URLパラメータに使う文字列
		String learner = null;

		//--------------------------------------------------------------
		// 学習者フラグ
		//   学習者                  ：「YES」
		//   学習者じゃない（管理者）：「NO」
		//
		// 学習者とは
		//   ユーザに割り当てられている権限（XMOEntry）のうち、
		//      学習のみを持つ場合
		//      ログ管理のみを持つ場合
		//      学習とログ管理のみを持つ場合
		//   のいずれか。  
		//--------------------------------------------------------------
		if( isLearner == true ) {
			learner = "YES";
		}
		else {
			learner = "NO";
		}

		// 次画面URLの作成
		// 基本画面へ遷移
		//--------------------------------------------------------------------------
		// URLパラメータ説明
		// tree_view_type ：ツリー表示タイプ（1：ユーザツリー　2：LOツリー）
		// learner        ：学習者フラグ（※１）
		// ini_menu       ：初期メニュー（※２）
		//
		// ※１　学習者の場合は基本画面の振る舞いが異なる
		//       １．表示ツリー切り換えボタンを非表示にする。
		//       ２．プロパティ画面のタグを非表示にする。
		// ※２  初期メニューの用途
		//       ShowSubGroupChildren.jspまでURLパラメータとして引き継いでいるが、
		//       結局使用していない
		//--------------------------------------------------------------------------
		String url = "./frameset.vm?tree_view_type=" + defaultTreeType + 
						"&learner=" + learner + 
						"&ini_menu=";

		// 返却値オブジェクトのインスタンス生成
		xmsResponse.setBusinessBeanName( "Login" );

		// 返却値タイプを設定　この場合はリダイレクト
		xmsResponse.setOutType( XmsResponse.REDIRECT );

		// リダイレクト先URLを設定
		xmsResponse.setUrl( url );
	}

// ------------------ 内部関数 ----------------------------------
	/**
	 * XMO起動チェックを行う。<BR>
	 * @return true: 起動済み false: 起動中
	 * @exception XmsException システム例外
	 */
	private boolean isLaunch() 
		throws XmsException {
		
		try {
			// XMSクライアントを生成
			XMSBaseClient BaseObject = new XMSBaseClient();
	
			// XMO起動チェック
			// 返却値をそのまま返却する
			return BaseObject.isLaunch();
		
		}
		catch(Exception ex) {
			throw new XmsSystemException(ex);	
		}
	}
	
	/**
	 * 連続して同一ログインIDでパスワードを間違えた回数を返す。<BR>
	 * 前回のログインIDと今回のログインIDが同一の場合は、セッションに保持した
	 * パスワードを間違えた回数を１プラスし、同一でない場合は１を返す。
	 * @param session HTTPSessionオブジェクト
	 * @param loginID 今回のログインID
	 * @return int 連続して同一ログインIDでパスワードを間違えた回数
	 */
	private int getErrPassCount( HttpSession session, String loginID ) {

		// 現在のパスワード不一致回数をセッションから取得
		Integer objAccessCount = ( Integer ) session.getAttribute( OperateSession.ERR_PASS_COUNT );

		// 前回のログインIDをセッションから取得
		String strBeforeLoginID = (String)session.getAttribute( OperateSession.LOGIN_ID );

		// アクセス回数
		int intAccessCount = 0;

		if(objAccessCount != null) {
			intAccessCount = ( objAccessCount ).intValue();
		}

		if( loginID.equals(strBeforeLoginID) == true ) {
			// 直前に入力したログインIDと今回のログインIDが同一の場合は
			// 回数を１プラスして返す。
			intAccessCount++;
		}
		else {
			// 直前に入力されたログインIDと今回の
			// ログインIDが異なる場合は１を返す。
			intAccessCount = 1;	
		}

		return intAccessCount;
	}
}