How to set up gmail push notification - push-notification

I tried to understand how this works since more than a day, and I'm totally confused right now.
Here is my (very simple) goal: make a GET request on a URL when I receive a new email.
I have created a topic as they asked (named new-email)
I have a subscription in that topic (named new-email-inbox), with delivery type push, and setting my endpoint URL.
I gave my subscription authorization to this account: gmail-api-push#system.gserviceaccount.com (Editor & Editor Pub/Sub)
How do I set up the rest ? I don't understand what to do now..

I did a Symfony4 command, executed everyday like a cron:
class WatchGoogleClient extends Command {
private $kernel;
private $gmailService;
public function __construct(GmailService $gmailService, Kernel $kernel)
{
parent::__construct();
$this->gmailService = $gmailService;
$this->kernel = $kernel;
}
protected function configure()
{
$this->setName('app:watch-google-client')
->setDescription('watch-google-client')
->setHelp('Reset the google watch timer');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// This getClient function is basically what is given by the google API tutorial
$client = $this->gmailService->getClient($this->kernel);
$service = new \Google_Service_Gmail($client);
$watchreq = new \Google_Service_Gmail_WatchRequest();
$watchreq->setLabelIds(array('INBOX'));
$watchreq->setTopicName('YOUR_TOPIC_NAME');
$msg = $service->users->watch('me', $watchreq);
var_dump($msg);
// DO WHAT YOU WANT WITH THIS RESPONSE BUT THE WATCH REQUEST IS SET
}
}

Related

Symfony mail on Command class - get undefined method named "get"

I try to send mail (swiftmail) via command of symfony.
Here is my code :
class CommandMail extends Command
{
protected static $defaultName = 'app:send-daily-mail';
protected function configure() {
$this
->setDescription('Send automatic reminders mail everyday.')
->setHelp('This command allows you to send automatic reminder mail to Rhys, everyday...');
}
protected function execute(InputInterface $input, OutputInterface $output) {
$message = (new \Swift_Message('test auto mail cron 12 24 TEST'))
->setFrom('xxxxxx.xxxxxxx#gmail.com')
->setTo('wwwww.wwwwwww#gmail.com')
->setBody('test body');
$this->get('mailer')->send($message);
}
}
I have following error :
In CommandMail.php line 54:
Attempted to call an undefined method named "get" of class
"AppBundle\Command\CommandMail".
Did you mean to call e.g. "getAliases", "getApplication",
"getDefaultName", "getDefinition", "getDescription", "getHelp",
"getHelper", "getHelperSet", "getName", "getNativeDefin ition",
"getProcessedHelp", "getSynopsis" or "getUsages"?
I try many things (getContainer() ie and many others) but nothing is working.
Thanks for your help !
(Symfony 3, SMTP gmail)
If you are using Symfony 4, inject the dependency by constructor:
private $swiftMailerService;
public function __construct(\Swift_Mailer $swiftMailerService)
{
parent::__construct();
$this->swiftMailerService = $swiftMailerService;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$message = (new \Swift_Message('test auto mail cron 12 24 TEST'))
->setFrom('xxxxxx.xxxxxxx#gmail.com')
->setTo('wwwww.wwwwwww#gmail.com')
->setBody('test body');
$this->swiftMailerService->send($message);
}

Symfony : how to set init data on login

I'm facing a dilemna as well as an optimization problem :
In my Symfony 2.8 application, I have custom settings and other business logic data to load (from database tables, not from SF parameters) that a logged in user can be needed to use at different pages.
At first those data where scarcely needed, so i loaded them only when the page required it. But now as the application grows, i need them more often.
So i was thinking about loading them when the user logs in, and save them as localStorage on client side because cookies are too small.
But i'm not sure how to best do it.
I have a login success handler, that allows to redirect on the correct page when user is successfully logged.
For the moment i have this one :
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Router;
class LoginSuccessHandler implements AuthenticationSuccessHandlerInterface
{
protected $router;
protected $authorizationChecker;
public function __construct(Router $router, AuthorizationChecker $authorizationChecker)
{
$this->router = $router;
$this->authorizationChecker = $authorizationChecker;
}
/**
* What to do when user logs in.
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
$response = null;
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
//an admin is redirected towards this page
$response = new RedirectResponse($this->router->generate('my_back_admin'));
} else if ($this->authorizationChecker->isGranted('ROLE_USER')) {
//a user is redirected towards this page
$response = new RedirectResponse($this->router->generate('my_back_user'));
}
//redirect to any last visited page if any
$key = '_security.main.target_path';
if ($request->getSession()->has($key)) {
$url = $request->getSession()->get($key);
$request->getSession()->remove($key);
$response = new RedirectResponse($url);
}
return $response;
}
}
So i was thinking about adding a setInitialData() method in which i would get all the settings i need and modifying onAuthenticationSuccess :
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
$response = null;
//retrieve array of data to be set in the init
$toBeSaved = $this->setInitialData();
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
//an admin is redirected towards this page
$response = new RedirectResponse($this->router->generate('my_back_admin', ['initdata'=>$toBeSaved]));
} else if ($this->authorizationChecker->isGranted('ROLE_USER')) {
//a user is redirected towards this page
$response = new RedirectResponse($this->router->generate('my_back_user', ['initdata'=>$toBeSaved]));
}
//redirect to any last visited page if any
$key = '_security.main.target_path';
if ($request->getSession()->has($key)) {
$url = $request->getSession()->get($key);
$request->getSession()->remove($key);
$response = new RedirectResponse($url, ['initdata'=>$toBeSaved]);
}
return $response;
}
And then on the main template, i would retrieve that data
{% for paramName, paramValue in app.request.query %}
{% if paramName == 'initdata' %}
<div id="initdata" data-init="{{paramValue|json_encode}}"></div>
{% endif %}
{% endfor %}
and add a javascript block with something like :
<script>
if ($('#initdata').length > 0){
localStorage.removeItem('initdata');
localStorage.setItem('initdata', JSON.stringify($('#initdata').data('init')));
}
</script>
But this method doesn't seems right : i'm not sure this is the best way to do it.
And furthermore, since these are sent in a redirect, the data are shown in the query string, which is not ideal :(
This will not fly as by having multiple parameters you create multiple <div> elements with identical ID = initdata. Subsequent jQuery selector will only capture the first one (afaik).
I see that you indeed send params via query string. This takes care of multiple value, but this also exposes your user setting in user URL, doesn't it? If it does, it has security vulnerability all over the wall. Remember, such URLs are persisted in your browser's history.
Instead, I suggest you create a separate controller action /_get_user_settings which you will call via AJAX GET. Server will serve JSON response which you can save to your localStorage with little or no problem at all.
Hope this helps...

Having issues getting the notification feed for new follows when using stream-laravel

I am building a small project using Getstream Laravel package. However I am having a problem trying to display notifications for new followers. I get an empty result set when I call \FeedManager::getNotificationFeed($request->user()->id)->getActivities() in a controller method. I have my follow model looking like this:
class Follow extends Model
{
protected $fillable = ['target_id'];
public function user()
{
return $this->belongsTo(User::class);
}
public function target()
{
return $this->belongsTo(User::class);
}
public function activityNotify()
{
$targetFeed = \FeedManager::getNotificationFeed($this->target->id);
return array($targetFeed);
}
}
Then the controller action to get the notifications for new follows looks like this:
public function notification(Request $request)
{
$feed = \FeedManager::getNotificationFeed($request->user()->id);
dd($feed->getActivities());
$activities = $feed->getActivities(0,25)['results'];
return view('feed.notifications', [
'activities' => $activities,
]);
}
In the user model I have defined a relationship that a user has many follows. And lastly the follow and unfollow actions in the FollowController look like this:
public function follow(Request $request)
{
// Create a new follow instance for the authenticated user
// This target_id will come from a hidden field input after clicking the
// follow button
$request->user()->follows()->create([
'target_id' => $request->target_id,
]);
\FeedManager::followUser($request->user()->id, $request->target_id);
return redirect()->back();
}
public function unfollow($user_id, Request $request)
{
$follow = $request->user()->follows()->where('target_id', $user_id)->first();
\FeedManager::unfollowUser($request->user()->id, $follow->target_id);
$follow->delete();
return redirect()->back();
}
Not sure if there's something I left out but I can't get results for the notification feed. If I head over to the explorer tab from the Stream dashboard, I can see that I got two new follows which generated both timeline and timeline_aggregated type of feed. Or how should I get the notification feed from a controller action? Thanks in advance
The \FeedManager::followUser method create a two follow relationships: timeline to user and timeline_aggregated to user.
In this case what you want to create a follow relationship between notification and user. Something like this should do it:
\FeedManager:: getNotificationFeed($request->user()->id)
.followFeed('user', $follow->target_id)

Symfony StopWatch events not appearing in profiler timeline

I'm trying to get additional timing information into the Symfony Profiler Timeline, but I can't get anything to appear. According to the documentation I've read, it should be as simple as the following example, but this doesn't cause any additional info to appear on the timeline.
Do I need to somehow make the profiler aware of the events I'm starting and stopping?
use Symfony\Component\Stopwatch\Stopwatch;
class DefaultController extends Controller
{
public function testAction()
{
$stopwatch = new Stopwatch();
$stopwatch->start('testController');
usleep(1000000);
$response = new Response(
'<body>Hi</body>',
Response::HTTP_OK,
array('content-type' => 'text/html')
);
$event = $stopwatch->stop('testController');
return $response;
}
}
Symfony's profiler can't scan to code for all stopwatch instances and put that into the timeline. You have to use the preconfigured stopwatch provided by the profiler instead:
public function testAction()
{
$stopwatch = $this->get('debug.stopwatch');
$stopwatch->start('testController');
// ...
$event = $stopwatch->stop('testController');
return $response;
}
However, your controller is already on the timeline...
You should inject the stopwacth as a service in your constructor or a specific function, becasue after Symfony 3.4: Services are private by default.
testAction(\Symfony\Component\Stopwatch\Stopwatch $stopwatch) {
$stopwatch->start('testController');
// ...
$event = $stopwatch->stop('testController');
}

symfony test database insert

I have a functional test that creates and persists some things in the database and I want to test that the correct number of items was inserted (there is a scenario where it currently inserts two instead of one).
In the controller everything seems to work and if I use the code below (in the controller) to debug it, I get the expected (wrong) value of "2":
$em = $this->getDoctrine()->getManager();
$fooRepo = $em->getRepository('CompanyProjectBundle:Foo');
$foos = $fooRepo->retrieveByBar(3);
echo count($foos); // Gives a result of 2
However, if I try something similar from within my Test class I get zero...
/**
* {#inheritDoc}
*/
protected function setUp()
{
static::$kernel = static::createKernel();
static::$kernel->boot();
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager()
;
$this->em->getConnection()->beginTransaction();
}
/**
* {#inheritDoc}
*/
protected function tearDown()
{
parent::tearDown();
$this->em->getConnection()->rollback();
$this->em->close();
}
public function testFooForm()
{
// ... do some testing
$fooRepo = $this->em->getRepository('CompanyProjectBundle:Foo');
$foos = $fooRepo->retrieveByBar(3);
echo count($foos); // gives a result of ZERO
// ... more happens later
}
Is it getting a different entity manager or something like that? Should I be using some other method to get hold of the correct EM so I can then view the same data that the app is running from?
Everything's running inside a transaction (which is rolled back when the test client is destroyed), but that happens after the snippet shown above.
Ah... solved my own problem. I think I was getting the wrong EntityManager. I fixed it by getting the EntityManager via the client's container instead of the kernel's one:
public function testFooForm()
{
// ... do some testing
$clientEm = $client->getContainer()->get('doctrine.orm.entity_manager');
$fooRepo = $clientEm->getRepository('CompanyProjectBundle:Foo');
$foos = $fooRepo->retrieveByBar(3);
echo count($foos); // gives the correct result of 2
// ... more happens later
}

Resources