diff --git a/inc/auth.php b/inc/auth.php new file mode 100644 index 0000000..8fdd49c --- /dev/null +++ b/inc/auth.php @@ -0,0 +1,217 @@ +oDb = $oDb; + $this->setUserId(0); + $this->sApiKey = $sApiKey; + if($bAutoLogin) $this->autoLogIn(); + } + + private function setUserId($iUserId) + { + $this->iUserId = $iUserId; + } + + public function getUserId() + { + return $this->iUserId; + } + + public function isLoggedIn() + { + return ($this->getUserId() > 0); + } + + public function logMeIn($sToken) + { + $sDesc = ''; + $asUser = $this->getUserFromToken($sToken); + if($asUser['success']) + { + if(self::checkPassword($asUser['http_pass'], $asUser['pass'])) + { + $this->setUserId($asUser[Db::getId(self::USER_TABLE)]); + $this->resetAuthCookie($this->getUserId()); + } + else $sDesc = 'wrong password'; + } + else $sDesc = $asUser['desc']; + + return array('success'=>$this->isLoggedIn(), 'desc'=>$sDesc); + } + + public function register($sToken, $sNickName, $bLogMeIn=false) + { + $bSuccess = false; + $sDesc = self::DEFAULT_ERROR; + $asUser = $this->getUserFromToken($sToken); + + if(array_key_exists('unknown_user', $asUser)) + { + $iUserId = $this->addUser($asUser['username'], $sNickName, $asUser['http_pass'], $bLogMeIn); + if($iUserId > 0) $bSuccess = true; + else $sDesc = 'Error: Could not add user'; + } + else $sDesc = 'Someone is already using this nickname, sorry!'; + + $asResult = array('success'=>$bSuccess, 'desc'=>$sDesc); + return $asResult; + } + + private function getUserFromToken($sToken) + { + $asResult = array(); + $bSuccess = false; + $sDesc = self::DEFAULT_ERROR; + + if($sToken!='') + { + $asResult['username'] = addslashes(strstr($sToken, self::TOKEN_SEP, true)); + $asResult['http_pass'] = substr(strstr($sToken, self::TOKEN_SEP), strlen(self::TOKEN_SEP)); + + if($asResult['username']!='' && $asResult['http_pass']!='') + { + $asUser = $this->oDb->selectRow(self::USER_TABLE, array(Db::getText(self::USER_TABLE)=>$asResult['username'])); + if(!empty($asUser)) + { + $asResult += $asUser; + $bSuccess = true; + } + else + { + $asResult['unknown_user'] = true; + $sDesc = 'unknown nickname'; + } + } + else $sDesc = 'corrupted token, please login again'; + } + else $sDesc = 'no credentials has been received by the server'; + + $asResult['success'] = $bSuccess; + $asResult['desc'] = $sDesc; + return $asResult; + } + + public function autoLogIn() + { + if(isset($_COOKIE[self::USER_COOKIE_PASS])) + { + $sCookie = $_COOKIE[self::USER_COOKIE_PASS]; + $iUserId = addslashes(strstr($sCookie, self::TOKEN_SEP, true)); + $sCookie = substr(strstr($sCookie, self::TOKEN_SEP), strlen(self::TOKEN_SEP)); + + $asEmpl = $this->oDb->selectRow(self::USER_TABLE, array(Db::getId(self::USER_TABLE)=>$iUserId)); + if(!empty($asEmpl)) + { + if($sCookie==$asEmpl['cookie']) + { + $this->setUserId($asEmpl[Db::getId(self::USER_TABLE)]); + + //Reset pass once a day + if(mb_substr($asEmpl['led'], 0, 10) != date('Y-m-d')) $this->resetAuthCookie($this->getUserId()); + } + else $this->addError('token corrompu pour le user '.$asEmpl[Db::getId(self::USER_TABLE)]); + } + else $this->addError('Utilisateur '.$iUserId.' inconnu'); + } + } + + public function addUser($sUserHash, $sNickName, $sLoginToken, $bLogMeIn=false) + { + $sPass = self::hashPassword($sLoginToken); + $bExist = $this->oDb->pingValue(self::USER_TABLE, array(Db::getText(self::USER_TABLE)=>$sUserHash)); + if($bExist) return -1; + else + { + $iUserId = $this->oDb->insertRow(self::USER_TABLE, array(Db::getText(self::USER_TABLE)=>$sUserHash, 'nickname'=>$sNickName, 'pass'=>$sPass)); + if($iUserId>0 && $bLogMeIn) + { + $this->logMeIn($sUserHash.self::TOKEN_SEP.$sPass); + } + } + return $iUserId; + } + + //TODO integrate with logMeIn() + public function checkApiKey($sApiKey) + { + return ($this->sApiKey!='' && $sApiKey==$this->sApiKey); + } + + private function resetPass($iUserId=0) + { + $sUserIdCol = Db::getId(self::USER_TABLE); + $sUserTextCol = Db::getText(self::USER_TABLE); + + $asInfo = array('select'=>array($sUserIdCol, $sUserTextCol), 'from'=>self::USER_TABLE); + if($iUserId>0) $asInfo['constraint'] = array($sUserIdCol=>$iUserId); + + $asUsers = $this->oDb->selectRows($asInfo); + foreach($asUsers as $asUser) + { + $sToken = self::hashPassword(self::getLoginToken($asUser[$sUserTextCol])); + $this->oDb->updateRow(self::USER_TABLE, array(Db::getId(self::USER_TABLE)=>$asUser[$sUserIdCol]), array('pass'=>$sToken)); + } + } + + public static function getLoginToken($sPass) + { + //Add Server Name + $sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD']; + $sAppPath = $_SERVER['REQUEST_SCHEME'].'://'.str_replace(array('http://', 'https://'), '', $sServerName.dirname($_SERVER['SCRIPT_NAME'])); + $_GET['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':''); + return md5($sPass.$_GET['serv_name']); + } + + private function resetAuthCookie($iUserId) + { + $sNewPass = self::getAuthCookie($iUserId); + $iTimeLimit = time() + 60 * 60 * 24 * 30; + $this->oDb->updateRow(self::USER_TABLE, array(Db::getId(self::USER_TABLE)=>$iUserId), array("cookie"=>$sNewPass)); + setcookie(self::USER_COOKIE_PASS, $iUserId.self::TOKEN_SEP.$sNewPass, $iTimeLimit); + } + + private static function getAuthCookie() + { + return self::hashPassword + ( + $_SERVER['HTTP_USER_AGENT']. + $_SERVER['REMOTE_ADDR']. + $_SERVER['REQUEST_TIME']. + mb_strstr(microtime(), ' ', true). + $_SERVER['SERVER_SIGNATURE']. + $_SERVER['SERVER_ADMIN'] + ); + } + + private static function hashPassword($sPass) + { + return password_hash($sPass, self::ALGO, array('cost'=>self::COST)); + } + + private static function checkPassword($sPass, $sHash) + { + return password_verify($sPass, $sHash); + } +} + +?> \ No newline at end of file diff --git a/inc/catc.php b/inc/catc.php new file mode 100644 index 0000000..94f28f6 --- /dev/null +++ b/inc/catc.php @@ -0,0 +1,149 @@ +'auth', 'project'=>true), + array('name'=>'course', 'project'=>true) + ); + parent::__construct($oClassManagement, $sProcessPage, $asClasses); + + //if($this->oDb->sDbState == Db::DB_PEACHY) $this->oAuth = new Auth($this->oDb, Settings::API_KEY); + $this->oAuth = new Auth($this->oDb, Settings::API_KEY); + } + + protected function install() + { + //Install DB + $this->oDb->install(); + } + + protected function getSqlOptions() + { + return array + ( + 'tables' => array + ( + Auth::USER_TABLE => array(Db::getText(Auth::USER_TABLE), 'nickname', 'pass', 'cookie'), + 'workshops' => array('dates'), + 'courses' => array(Db::getId('workshops'), 'description', 'timeslot', 'notes'), + 'docs' => array(Db::getId('courses'), 'type', 'path'), + 'todos' => array(Db::getId('courses'), 'description') + ), + 'types' => array + ( + Db::getText(Auth::USER_TABLE) => "VARCHAR(32) NOT NULL", + 'nickname' => "VARCHAR(60) NOT NULL", + 'pass' => "VARCHAR(256) NOT NULL", + 'cookie' => "VARCHAR(255)", + 'dates' => "VARCHAR(50)", + 'description' => "VARCHAR(200)", + 'timeslot' => "ENUM('SAT-M', 'SAT-A', 'SUN-M', 'SUN-A')", + 'notes' => "LONGTEXT", + 'type' => "VARCHAR(10)", + 'path' => "VARCHAR(100)" + ), + 'constraints' => array + ( + 'docs' => "UNIQUE KEY `uni_path` (`path`)" + ) + ); + } + + public function getPage() + { + //Constants + $asGlobalVars = array( + 'consts' => array( + 'token_sep' => Auth::TOKEN_SEP, + 'error' => self::ERROR, + 'success' => self::SUCCESS, + 'context' => $this->asContext, + 'cookie' => Auth::USER_COOKIE_PASS + ), + 'vars' => $this->getVars() + ); + + //Pages + $asPages = array('logon', 'logoff', 'template', 'workshops'); + foreach($asPages as $sPage) $asGlobalVars['consts']['pages'][$sPage] = $this->getPageContent($sPage); + + //Main Page + //TODO use getMainPage parent function + $sPage = $this->getPageContent('index'); + $sPage = str_replace('asGlobalVars', json_encode($asGlobalVars), $sPage); + return $sPage; + } + + private function getVars() { + return array( + 'id' => $this->oAuth->getUserId(), + 'log_in' => $this->isLoggedIn() + ); + } + + public function getMainPage($asGlobalVars = array(), $sMainPage = 'index', $asMainPageTags=array()) + { + return parent::getMainPage( + array( + 'consts' => array( + 'token_sep' => Auth::TOKEN_SEP, + 'error' => self::ERROR, + 'success' => self::SUCCESS, + 'context' => $this->asContext, + 'cookie' => Auth::USER_COOKIE_PASS + ), + 'vars' => $this->getVars() + ), + 'index', + array( + 'host_url' => $this->asContext['serv_name'] + ) + ); + } + + /* Authorizations handling */ + + public function register($sToken, $sNickname) + { + $asResult = $this->oAuth->register($sToken, $sNickname); + + if($asResult['success']) return $this->logMeIn($sToken); + else return self::getJsonResult($asResult['success'], $asResult['desc']); + } + + public function isLoggedIn() + { + return $this->oAuth->isLoggedIn(); + } + + public function logMeIn($sToken) + { + $asLogResult = $this->oAuth->logMeIn($sToken); + return self::getJsonResult($asLogResult['success'], $asLogResult['desc'], $this->getVars()); + } + + public function checkApiKey($sApiKey) + { + return $this->oAuth->checkApiKey($sApiKey); + } + + /* Managing projects */ + /* + public function upload() + { + $this->oClassManagement->incClass('uploader', true); + $oUploader = new Uploader($this->oMedia); + + return $oUploader->sBody; + } + */ +} \ No newline at end of file diff --git a/inc/course.php b/inc/course.php new file mode 100644 index 0000000..8c9d514 --- /dev/null +++ b/inc/course.php @@ -0,0 +1,5 @@ +isLoggedIn(); + +$sResult = ''; +if($sAction=='logmein') $sResult = $oCATC->logMeIn($sToken); +elseif($sAction!='' && $bLoggedIn) +{ + switch ($sAction) + { + default: + $sResult = CATC::getJsonResult(false, CATC::NOT_FOUND); + } +} +elseif($sAction!='' && !$bLoggedIn) +{ + if($oCATC->checkApiKey($iApiKey)) + { + switch ($sAction) + { + case '': + //$sResult = $oCATC->apifunction(); + break; + default: + $sResult = CATC::getJsonResult(false, CATC::NOT_FOUND); + } + } + elseif($sAction=='register') $sResult = $oCATC->register($sToken, $sNickName); + else $sResult = CATC::getJsonResult(false, CATC::UNAUTHORIZED); +} +else $sResult = $oCATC->getPage(); + +$sDebug = ob_get_clean(); +if(Settings::DEBUG && $sDebug!='') $oCATC->addUncaughtError($sDebug); + +echo $sResult; \ No newline at end of file diff --git a/settings-sample.php b/settings-sample.php new file mode 100644 index 0000000..0e2cc60 --- /dev/null +++ b/settings-sample.php @@ -0,0 +1,15 @@ +