<?php
###############################################################################
# SAML.php
#
# @author Anil Kumar <akumar@codepunch.com>
# @link   https://codepunch.com
#
############################################################################### 

namespace 	CodePunch\Config\SAML;

use 		CodePunch\Base\Util as UTIL;
use			CodePunch\Base\Text as TEXT;
use			CodePunch\DB\Audit as AUDIT;
use 		Exception;

###############################################################################

class SAMLBase {
	
	private $authentication = null;
	
	###########################################################################
	
	public function __construct($auth, $doload=true)
	{ 
		$this->authentication = $auth;
	}
	
	###########################################################################
	
	public function getAuth()
	{
		return $this->authentication;
	}
	
	###########################################################################
	
	public function isEnabled()
	{
		return true;
	}
	
	###########################################################################
	# Local Logout
	
	public function logout()
	{
		$this->authentication->processLogout();
	}
	
	###########################################################################
	
	public function isLoggedIn()
	{
		if(isset($_SESSION[\CodePunch\Config\ConfigRoot::SAMLUSER])) {
			return true;
		}
		return false;
	}
	
	###########################################################################
	# returns 0 if not enabled, 1 if enabled but not logged in & 2 if logged in
	
	public static function getStatus($auth, &$name)
	{
		$name = "";
		$setup = new \CodePunch\Config\Settings($auth);
		$samlidp = $setup->getOption("saml_idp", "");
		if($samlidp != "" && $samlidp != "default") {
			$class = "\\CodePunch\\Config\\SAML\\" . $samlidp;
			if(class_exists($class)) {
				$sc = new $class($auth, false);
				if($sc->hasSettings() && $sc->isEnabled()) {
					$name = $sc->getName();
					if($sc->isLoggedIn())
						return 2;
					return 1;
				}
			}
		}
		return 0;
	}
	
	###########################################################################
	
	public function get_valid_user_name($samluser, $name="")
	{
		$auth = $this->getAuth();
		$user = "";
		$name = trim($name);
		$logger = new \CodePunch\Base\CPLogger();
		if($samluser != "" && $auth) {
			$db = $auth->getDatabase();
			if($db) {
				$setup = new \CodePunch\Config\Settings($this->getAuth());
				$matchmode = strtolower($setup->getOption("saml_match", "samluser"));
				if($db->hasRow($db->getUserTableName(), array('name', 'active'), array($samluser, 1)))
					$user = $samluser;
				else if($matchmode == "samluser") {
					if($db->hasRow($db->getUserTableName(), array('name', 'active'), array("samluser", 1)))
						$user = "samluser";
					else 
						$logger->error("Missing user 'samluser'");
				}
				else if($matchmode == "samldefault") {
					if($db->hasRow($db->getUserTableName(), array('name', 'active'), array("samldefault", 1))) {
						$db->createUserFromAnother("samldefault", $samluser, $name);
						if($db->hasRow($db->getUserTableName(), array('name', 'active'), array($samluser, 1))) {
							$logger->info("New user ($samluser) added using 'samldefault' template.");
							$user = $samluser;
							AUDIT::add($db, AUDIT::ADD_USER, "samldefault", $samluser);
						}
					}
					else if($db->hasRow($db->getUserTableName(), array('name', 'active'), array("samluser", 1))) {
						$db->createUserFromAnother("samluser", $samluser, $name);
						if($db->hasRow($db->getUserTableName(), array('name', 'active'), array($samluser, 1))) {
							$logger->info("New user ($samluser) added using 'samluser' template.");
							$user = $samluser;
							AUDIT::add($db, AUDIT::ADD_USER, "samluser", $samluser);
						}
					}
					else 
						$logger->error("Missing SAML user account [samldefault / samluser]");
				}
				else
					throw new Exception(TEXT::get("saml_no_usermatch"));
			}
		}
		return $user;
	}
	
	###########################################################################
	
	public function processUser($user, $authdata=null)
	{
		$db = null;
		$auth = $this->getAuth();
		if($auth) 
			$db = $auth->getDatabase();
		if($user != "" && $db) {
			$responce = array('status'=>'notok', 'user'=>'', 'group'=>'', 'error'=>'', 'secondary'=>0);
			$rows = $db->getFromTable("*", $db->getUserTableName(), "name=? AND active='1'", array($user));
			if($rows !== false) {
				$rows = UTIL::array_flatten($rows);
				$rows = array_change_key_case($rows, CASE_LOWER);
				if(isset($rows['id'])) {
					$responce['status'] = 'ok';
					$responce['userid'] = $rows['id'];
					$gids = $db->getUserGroups($rows['id']);
					$adminid = $db->findOneOf($db->getUserGroupsTableName(), "name", "admin", "id");
					$responce['admin'] = in_array($adminid, $gids) ? true : false;
					$responce['fullname'] = $rows['full_name'];
					$responce['displayname'] = $rows['display_name'];
					$responce['user'] = $rows['name'];
					$responce['rights'] = $rows['rights'];
					if($responce['rights']&\CodePunch\DB\DomainDB::ALLOW_ALL_DOMAINS_EVER)
						$db->addUserToAllCategories($responce['userid']);
					$responce['lastsignin'] = $rows['last_sign_in_stamp'];
					if($authdata != null) {
						$_SESSION[\CodePunch\Config\ConfigRoot::SAMLIDP] = UTIL::get_from_array($authdata['idp'], "");
						$_SESSION[\CodePunch\Config\ConfigRoot::SAMLUSER] = UTIL::get_from_array($authdata['user'], "");
					}
					$auth->loginCheckCompleted($responce);
					if($responce['status'] == 'ok') {
						$auth->getDatabase()->authenticationLog(true, $user, $responce['userid']);
						$responce = $auth->processPrimaryLogin($responce);
						$url = $responce['url'];
						header("Location: $url");
						exit;
					}
				}
			}
		}
		else {
			throw new Exception(TEXT::get("saml_invalidsetup"));
		}
		throw new Exception(TEXT::get("saml_no_usermatch"));
	}

	###########################################################################
}
