Files
core/src/sammo/API/Login/LoginByToken.php
T

190 lines
5.7 KiB
PHP

<?php
namespace sammo\API\Login;
use sammo\Session;
use DateTimeInterface;
use sammo\BaseAPI;
use sammo\Enums\APIRecoveryType;
use sammo\Json;
use sammo\KakaoUtil;
use sammo\RootDB;
use sammo\TimeUtil;
use sammo\Util;
use sammo\Validator;
use function sammo\logError;
class LoginByToken extends LoginByID
{
static array $sensitiveArgs = ['hashedToken'];
public static function kakaoFailureResponse(bool $reqOTP, string $reason): string | array
{
if (!$reqOTP) {
return $reason;
}
return [
'result' => false,
'silent' => false,
'reqOTP' => true,
'reason' => $reason,
];
}
public static function shouldDiscardTokenAfterKakaoFailure(bool $reqOTP): bool
{
return !$reqOTP;
}
public static function pendingSessionTokenID(bool $reqOTP, int $tokenID): ?int
{
return $reqOTP ? $tokenID : null;
}
public function getRequiredSessionMode(): int
{
return \sammo\BaseAPI::NO_LOGIN;
}
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v
->rule('required', [
'token_id',
'hashedToken'
]);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$loginNonce = $session->loginNonce ?? null;
$loginNonceExpired = $session->loginNonceExpired ?? null;
if (!is_string($loginNonce) || !is_string($loginNonceExpired)) {
return '자동 로그인: 절차 오류';
}
$RootDB = RootDB::db();
if ($session->isLoggedIn()) {
$session->logout();
}
$token_id = $this->args['token_id'];
$token_info = $RootDB->queryFirstRow('SELECT * FROM login_token WHERE id = %i', $token_id);
if (!$token_info) {
return [
'result' => false,
'silent' => true,
'reason' => 'failed'
];
}
$hashedToken = $this->args['hashedToken'];
$tokenAnswer = hash('sha512', "{$token_info['base_token']}{$loginNonce}");
if (strtolower($hashedToken) != strtolower($tokenAnswer)) {
return [
'result' => false,
'silent' => true,
'reason' => 'failed'
];
}
$userInfo = $RootDB->queryFirstRow(
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_id, oauth_type, oauth_info, token_valid_until ' .
'from member where NO = %i',
$token_info['user_id']
);
if(!$userInfo){
return '자동 로그인: 올바른 계정이 아닙니다.';
}
$canLogin = $RootDB->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1');
if ($canLogin != 'Y' && $userInfo['grade'] < 5) {
return '자동 로그인: 현재는 로그인이 금지되어있습니다!';
}
$nowDate = TimeUtil::now();
if ($userInfo['delete_after']) {
if ($userInfo['delete_after'] < $nowDate) {
$RootDB->delete('member', 'no=%i', $userInfo['no']);
return [
'result' => false,
'silent' => true,
'reason' => "기간 만기"
];
} else {
return [
'result' => false,
'silent' => true,
'reason' => "삭제 요청된 계정[{$userInfo['delete_after']}]"
];
}
}
$RootDB->insert('member_log', [
'member_no' => $userInfo['no'],
'action_type' => 'login',
'action' => Json::encode([
'ip' => Util::get_client_ip(true),
'type' => 'auto'
])
]);
if ($userInfo['oauth_type'] == 'KAKAO') {
$oauthFailResult = KakaoUtil::kakaoOAuthCheck($userInfo);
if ($oauthFailResult !== null) {
[$oauthReqOTP, $oauthFailReason] = $oauthFailResult;
$session->login(
$userInfo['no'],
$userInfo['name'],
$userInfo['grade'],
true,
$userInfo['token_valid_until'],
static::pendingSessionTokenID($oauthReqOTP, $token_id),
Json::decode($userInfo['acl'] ?? '{}')
);
if (static::shouldDiscardTokenAfterKakaoFailure($oauthReqOTP)) {
$RootDB->delete(
'login_token',
'id = %i',
$token_id
);
}
return static::kakaoFailureResponse($oauthReqOTP, $oauthFailReason);
}
}
$session->login($userInfo['no'], $userInfo['name'], $userInfo['grade'], false, $userInfo['token_valid_until'], $token_id, Json::decode($userInfo['acl'] ?? '{}'));
$this->scrubToken($userInfo['no']);
$nextDate = TimeUtil::nowAddDays(2);
if($nextDate < $token_info['expire_date']){
return [
'result' => true,
'silent' => true,
'reason' => 'success'
];
}
$RootDB->delete(
'login_token',
'id = %i', $token_id
);
$nextToken = $this->addToken($userInfo['no']);
return [
'result' => true,
'silent' => true,
'nextToken' => $nextToken,
'reason' => 'success'
];
}
}