663 lines
20 KiB
PHP
663 lines
20 KiB
PHP
<?php
|
|
|
|
namespace App\Controller\ResqAPI;
|
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\Dotenv\Dotenv;
|
|
|
|
use Doctrine\ORM\Query;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
use Catalyst\APIBundle\Controller\APIController;
|
|
use Catalyst\APIBundle\Response\APIResponse;
|
|
|
|
use App\Entity\MobileUser;
|
|
use App\Entity\Customer;
|
|
use App\Entity\PrivacyPolicy;
|
|
|
|
use App\Service\RisingTideGateway;
|
|
|
|
use App\Ramcar\CustomerSource;
|
|
|
|
use Catalyst\APIBundle\Access\Generator as ACLGenerator;
|
|
|
|
use DateTime;
|
|
|
|
class CustomerController extends APIController
|
|
{
|
|
protected $acl_gen;
|
|
|
|
public function __construct(ACLGenerator $acl_gen)
|
|
{
|
|
$this->acl_gen = $acl_gen;
|
|
}
|
|
|
|
public function register(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.register', null, 'No access.');
|
|
|
|
// confirm parameters
|
|
$required_params = [
|
|
'phone_model',
|
|
'os_type',
|
|
'os_version',
|
|
'phone_id'
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// check if capi user already has a mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
if ($mobile_user != null)
|
|
return new APIResponse(false, 'User already registered');
|
|
|
|
// retry until we get a unique id
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
// create mobile user
|
|
$mobile_user = new MobileUser();
|
|
$mobile_user->setPhoneModel($req->request->get('phone_model'))
|
|
->setOSType($req->request->get('os_type'))
|
|
->setOSVersion($req->request->get('os_version'))
|
|
->setPhoneID($req->request->get('phone_id'))
|
|
->setCapiUserId($user_id);
|
|
|
|
// reopen in case we get an exception
|
|
if (!$em->isOpen())
|
|
{
|
|
$em = $em->create(
|
|
$em->getConnection(),
|
|
$em->getConfiguration()
|
|
);
|
|
}
|
|
|
|
// save
|
|
$em->persist($mobile_user);
|
|
$em->flush();
|
|
}
|
|
catch (DBALException $e)
|
|
{
|
|
error_log($e->getMessage());
|
|
// delay one second and try again
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// return data
|
|
// TODO: do we need to return the same names as before?
|
|
// right now, still usind the old names so we use session_id name
|
|
$data = [
|
|
'session_id' => $mobile_user->getID()
|
|
];
|
|
|
|
// response
|
|
return new APIResponse(true, 'Mobile user created.', $data);
|
|
}
|
|
|
|
public function confirmNumber(RisingTideGateway $rt, Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.confirm.number', null, 'No access.');
|
|
|
|
// check parameters
|
|
$required_params = [
|
|
'phone_number',
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
// phone number
|
|
$phone_number = $req->request->get('phone_number');
|
|
|
|
// get otp_mode from .env
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../../.env');
|
|
|
|
$otp_mode = $_ENV['OTP_MODE'];
|
|
|
|
// check for hardcoded phone number for app store testing
|
|
if ($phone_number == '639221111111')
|
|
{
|
|
$code = '123456';
|
|
$mobile_user->setConfirmCode($code)
|
|
->setPhoneNumber($phone_number);
|
|
$em->flush();
|
|
|
|
return new APIResponse(true, 'Number confirmed.');
|
|
}
|
|
|
|
// check if otp_mode is test
|
|
if ($otp_mode == 'test')
|
|
{
|
|
$code = '123456';
|
|
$mobile_user->setConfirmCode($code)
|
|
->setPhoneNumber($phone_number);
|
|
$em->flush();
|
|
|
|
return new APIResponse(true, 'Number confirmed.');
|
|
}
|
|
|
|
// TODO: spam protection
|
|
|
|
// TODO: validate phone number
|
|
|
|
// generate code and save
|
|
$code = $this->generateConfirmCode();
|
|
$mobile_user->setConfirmCode($code)
|
|
->setPhoneNumber($phone_number);
|
|
$em->flush();
|
|
|
|
if ($otp_mode != 'test')
|
|
{
|
|
// send sms to number
|
|
$this->sendConfirmationCode($rt, $phone_number, $code);
|
|
}
|
|
|
|
// response
|
|
return new APIResponse(true, 'Number confirmed.');
|
|
}
|
|
|
|
public function validateCode(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.validate.code', null, 'No access.');
|
|
|
|
// check parameters
|
|
$required_params = [
|
|
'code',
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
// code is wrong
|
|
$code = $req->request->get('code');
|
|
if ($mobile_user->getConfirmCode() != $code)
|
|
return new APIResponse(false, 'Wrong confirm code');
|
|
|
|
// set confirm date
|
|
$date = new DateTime();
|
|
$mobile_user->setDateConfirmed($date)
|
|
->setConfirmed();
|
|
|
|
// TODO: check if we have the number registered before and merge
|
|
$dupe_user = $this->findNumberMobileUser($mobile_user->getPhoneNumber(), $em);
|
|
if ($dupe_user != null)
|
|
{
|
|
$dupe_cust = $dupe_user->getCustomer();
|
|
$mobile_user->setCustomer($dupe_cust);
|
|
}
|
|
|
|
// TODO: check if mobile matches mobile of customer
|
|
$customer = $this->findCustomerByNumber($mobile_user->getPhoneNumber(), $em);
|
|
if ($customer != null)
|
|
{
|
|
// TODO: if there is a dupe_sess, do we need to check if
|
|
// dupe_cust is the same as the customer we found?
|
|
$mobile_user->setCustomer($customer);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
// response
|
|
return new APIResponse(true, 'Code validated');
|
|
}
|
|
|
|
public function getInfo(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.get.info', null, 'No access.');
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
// if no customer found
|
|
$cust = $mobile_user->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$data = [
|
|
'first_name' => '',
|
|
'last_name' => '',
|
|
'priv_third_party' => (bool) false,
|
|
'priv_promo' => (bool) false,
|
|
];
|
|
|
|
return new APIResponse(true, 'No customer info found', $data);
|
|
}
|
|
|
|
// send back customer details
|
|
$data = [
|
|
'first_name' => $cust->getFirstName(),
|
|
'last_name' => $cust->getLastName(),
|
|
'priv_third_party' => (bool) $cust->getPrivacyThirdParty(),
|
|
'priv_promo' => (bool) $cust->getPrivacyPromo(),
|
|
];
|
|
|
|
return new APIResponse(true, 'Customer info found', $data);
|
|
}
|
|
|
|
public function updateInfo(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.update.info', null, 'No access.');
|
|
|
|
// check required parameters
|
|
$required_params = [
|
|
'first_name',
|
|
'last_name',
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
$cust = $this->updateCustomerInfo($req, $em, $mobile_user);
|
|
|
|
// get privacy policy for mobile
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../../.env');
|
|
|
|
$policy_mobile_id = $_ENV['POLICY_MOBILE'];
|
|
|
|
$mobile_policy = $em->getRepository(PrivacyPolicy::class)->find($policy_mobile_id);
|
|
|
|
// set policy id
|
|
if ($mobile_policy != null)
|
|
{
|
|
$cust->setPrivacyPolicyMobile($mobile_policy);
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return new APIResponse(true, 'Customer info updated');
|
|
}
|
|
|
|
public function getStatus(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.get.status', null, 'No access.');
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
// set data
|
|
$data = [];
|
|
if ($mobile_user->isConfirmed())
|
|
$data['status'] = 'confirmed';
|
|
else
|
|
$data['status'] = 'unconfirmed';
|
|
|
|
return new APIResponse(true, 'Customer status', $data);
|
|
}
|
|
|
|
public function resendCode(Request $req, RisingTideGateway $rt, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.resend.code', null, 'No access.');
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
// already confirmed
|
|
if ($mobile_user->isConfirmed())
|
|
return new APIResponse(true, 'User is already confirmed');
|
|
|
|
// have sent code before
|
|
if ($mobile_session->getDateCodeSent() != null)
|
|
return new APIResponse(true, 'Can only send confirm code every 5 mins');
|
|
|
|
// TODO: send via sms
|
|
$phone_number = $mobile_user->getPhoneNumber();
|
|
$code = $mobile_user->getConfirmCode();
|
|
$this->sendConfirmationCode($rt, $phone_number, $code);
|
|
|
|
return new APIResponse(true, 'Code re-sent');
|
|
}
|
|
|
|
public function versionCheck(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.version.check', null, 'No access.');
|
|
|
|
$required_params = [
|
|
'version',
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
$need_update = false;
|
|
$msg = 'Version is up to date.';
|
|
|
|
$api_version = $this->getParameter('api_version');
|
|
|
|
$app_version = $req->query->get('version');
|
|
|
|
$api_v = explode('.', $api_version);
|
|
$app_v = explode('.', $app_version);
|
|
|
|
if ($api_v[0] < $app_v[0])
|
|
return new APIResponse(false, 'Invalid application version: ' . $app_version);
|
|
|
|
if ($api_v[0] > $app_v[0])
|
|
{
|
|
$need_update = true;
|
|
$msg = 'Your version is outdated and needs an update to use the latest features RES-Q has to offer.';
|
|
}
|
|
|
|
|
|
$data = [
|
|
'need_update' => $need_update,
|
|
'message' => $msg,
|
|
];
|
|
|
|
return new APIResponse(true, 'Version checked', $data);
|
|
}
|
|
|
|
public function updateDeviceID(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.update.deviceid', null, 'No access.');
|
|
|
|
$required_params = [
|
|
'device_id',
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
$device_id = $req->request->get('device_id');
|
|
$mobile_user->setDevicePushID($device_id);
|
|
|
|
$em->flush();
|
|
|
|
// response
|
|
return new APIResponse(true, 'Device ID updated');
|
|
}
|
|
|
|
public function privacySettings(Request $req, EntityManagerInterface $em)
|
|
{
|
|
$this->denyAccessUnlessGranted('mobile_user.privacy.settings', null, 'No access.');
|
|
|
|
$required_params = [
|
|
'priv_third_party',
|
|
// 'priv_promo',
|
|
];
|
|
|
|
// check required parameters
|
|
$msg = $this->checkRequiredParameters($req, $required_params);
|
|
if ($msg)
|
|
return new APIResponse(false, $msg);
|
|
|
|
// get mobile user
|
|
$mobile_user = $this->findMobileUser($em);
|
|
|
|
if ($mobile_user == null)
|
|
return new APIResponse(false, 'No mobile user found.');
|
|
|
|
// get customer
|
|
$cust = $mobile_user->getCustomer();
|
|
if ($cust == null)
|
|
return new APIResponse(false, 'No customer information found');
|
|
|
|
// set privacy settings
|
|
$priv_promo = $req->request->get('priv_promo', false);
|
|
$priv_third_party = $req->request->get('priv_third_party');
|
|
$cust->setPrivacyThirdParty($priv_third_party)
|
|
->setPrivacyPromo($priv_promo);
|
|
|
|
// get the policy ids from .env
|
|
$dotenv = new Dotenv();
|
|
$dotenv->loadEnv(__DIR__.'/../../../.env');
|
|
|
|
$policy_promo_id = $_ENV['POLICY_PROMO'];
|
|
$policy_third_party_id = $_ENV['POLICY_THIRD_PARTY'];
|
|
|
|
// check if privacy settings are true
|
|
// if true, set the private policy for the customer
|
|
if ($priv_promo)
|
|
{
|
|
// find the promo policy
|
|
$policy = $em->getRepository(PrivacyPolicy::class)->find($policy_promo_id);
|
|
|
|
// set policy id
|
|
if ($policy != null)
|
|
{
|
|
$cust->setPrivacyPolicyPromo($policy);
|
|
}
|
|
}
|
|
|
|
if ($priv_third_party)
|
|
{
|
|
// find the third party policy
|
|
$policy = $em->getRepository(PrivacyPolicy::class)->find($policy_third_party_id);
|
|
|
|
// set policy id
|
|
if ($policy != null)
|
|
{
|
|
$cust->setPrivacyPolicyThirdParty($policy);
|
|
}
|
|
}
|
|
|
|
$em->flush();
|
|
|
|
return new APIResponse(true, 'Privacy policy settings set');
|
|
}
|
|
|
|
protected function findMobileUser($em)
|
|
{
|
|
// get capi user to link to mobile user
|
|
$user_id = $this->getUser()->getID();
|
|
$mobile_user = $em->getRepository(MobileUser::class)->findOneBy(['capi_user_id' => $user_id]);
|
|
|
|
return $mobile_user;
|
|
}
|
|
|
|
// TODO: find session customer by phone number
|
|
protected function findNumberMobileUser($number, $em)
|
|
{
|
|
$query = $em->getRepository(MobileUser::class)->createQueryBuilder('s')
|
|
->where('s.phone_number = :number')
|
|
->andWhere('s.customer is not null')
|
|
->andWhere('s.confirm_flag = 1')
|
|
->setParameter('number', $number)
|
|
->setMaxResults(1)
|
|
->getQuery();
|
|
|
|
// we just need one
|
|
$res = $query->getOneOrNullResult();
|
|
|
|
return $res;
|
|
}
|
|
|
|
protected function findCustomerByNumber($number, $em)
|
|
{
|
|
$customers = $em->getRepository(Customer::class)->findBy(['phone_mobile' => $number]);
|
|
|
|
// find the customer with the most number of cars
|
|
$car_count = 0;
|
|
$cust = null;
|
|
|
|
foreach($customers as $customer)
|
|
{
|
|
$vehicles = $customer->getVehicles();
|
|
if (count($vehicles) > $car_count)
|
|
{
|
|
$car_count = count($vehicles);
|
|
|
|
// "save" customer object
|
|
$cust = $customer;
|
|
}
|
|
}
|
|
|
|
return $cust;
|
|
}
|
|
|
|
protected function updateCustomerInfo($req, $em, $mobile_user)
|
|
{
|
|
// create new customer if it's not there
|
|
$cust = $mobile_user->getCustomer();
|
|
if ($cust == null)
|
|
{
|
|
$cust = new Customer();
|
|
|
|
// set customer source
|
|
$cust->setCreateSource(CustomerSource::MOBILE);
|
|
$em->persist($cust);
|
|
|
|
$mobile_user->setCustomer($cust);
|
|
}
|
|
|
|
$cust->setFirstName($req->request->get('first_name'))
|
|
->setLastName($req->request->get('last_name'))
|
|
->setEmail($req->request->get('email', ''))
|
|
->setConfirmed($mobile_user->isConfirmed());
|
|
|
|
// update mobile phone of customer
|
|
$cust->setPhoneMobile(substr($mobile_user->getPhoneNumber(), 2));
|
|
|
|
return $cust;
|
|
}
|
|
|
|
protected function sendConfirmationCode(RisingTideGateway $rt, $phone_number, $code)
|
|
{
|
|
// send sms to number
|
|
$message = "Your Resq confirmation code is $code.";
|
|
$rt->sendSMS($phone_number, 'MOTOLITE', $message);
|
|
}
|
|
|
|
|
|
// TODO: this might not be needed if we use APIController's checkRequiredParameters
|
|
// or we put this into a service?
|
|
protected function checkMissingParameters(Request $req, $params = [])
|
|
{
|
|
$missing = [];
|
|
|
|
// check if parameters are there
|
|
foreach ($params as $param)
|
|
{
|
|
if ($req->getMethod() == 'GET')
|
|
{
|
|
$check = $req->query->get($param);
|
|
if (empty($check))
|
|
$missing[] = $param;
|
|
}
|
|
else if ($req->getMethod() == 'POST')
|
|
{
|
|
$check = $req->request->get($param);
|
|
if (empty($check))
|
|
$missing[] = $param;
|
|
}
|
|
else
|
|
return $params;
|
|
}
|
|
|
|
return $missing;
|
|
}
|
|
|
|
// TODO: since we broke the functions into separate files, we need
|
|
// to figure out how to make this accessible to all ResqAPI controllers
|
|
protected function checkParamsAndKey(Request $req, $em, $params)
|
|
{
|
|
// TODO: depends on what we decide to return
|
|
// returns APIResult object
|
|
$res = new APIResult();
|
|
|
|
// check for api_key in query string
|
|
$api_key = $req->query->get('api_key');
|
|
if (empty($api_key))
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Missing API key');
|
|
return $res;
|
|
}
|
|
|
|
// check missing parameters
|
|
$missing = $this->checkMissingParameters($req, $params);
|
|
if (count($missing) > 0)
|
|
{
|
|
$miss_string = implode(', ', $missing);
|
|
$res->setError(true)
|
|
->setErrorMessage('Missing parameter(s): ' . $miss_string);
|
|
return $res;
|
|
}
|
|
|
|
// check api key
|
|
$mobile_user = $this->checkAPIKey($em, $req->query->get('api_key'));
|
|
if ($mobile_user == null)
|
|
{
|
|
$res->setError(true)
|
|
->setErrorMessage('Invalid API Key');
|
|
return $res;
|
|
}
|
|
|
|
// store session
|
|
$this->session = $sess;
|
|
|
|
return $res;
|
|
}
|
|
|
|
// TODO: type hint entity manager
|
|
// TODO: since we broke the functions into separate files, we need
|
|
// to figure out how to make this accessible to all ResqAPI controllers
|
|
protected function checkAPIKey($em, $api_key)
|
|
{
|
|
// find the api key (session id)
|
|
// TODO: user validation needs to be changed
|
|
$m_user = $em->getRepository(MobileUser::class)->find($api_key);
|
|
if ($m_user == null)
|
|
return null;
|
|
|
|
return $m_user;
|
|
}
|
|
}
|