3 namespace App\Controller;
5 use App\Controller\AppController;
6 use Cake\Core\Configure;
10 use Google_Service_Calendar;
11 use App\Traits\GoogleOauthTrait;
12 use App\View\Cell\GoogleCalendarCell;
17 * @property \App\Model\Table\UsersTable $Users
19 * @method \App\Model\Entity\User[] paginate($object = null, array $settings = [])
21 class UsersController extends AppController
25 public function initialize()
29 // configure the cache for our class.
31 $prefix = 'av_'. strtolower($this->name) .'-';
32 // av_ prefix so we can delete all files generated in cache/sql/ except for .gitignore
34 $locales = Configure::read('avenger.locales');
35 if(!empty($locales)) {
36 $prefix .= Configure::read('Config.language') .'-';
38 Log::debug('cache prefix will be: ' . $prefix);
40 // configure a file cache for storing calendar data.
41 Cache::config('calendar_cache', [
42 'className' => 'File',
44 'duration' => '+2 hours',
51 * @return \Cake\Http\Response|void
53 public function index() {
54 $users = $this->paginate ( $this->Users );
56 $this->set ( compact ( 'users' ) );
57 $this->set ( '_serialize', [
65 * @param string|null $id
67 * @return \Cake\Http\Response|void
68 * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
70 public function view($id = null) {
71 $user = $this->Users->get ( $id, [
75 $this->set ( 'user', $user );
76 $this->set ( '_serialize', [
82 * prepares the google oauth process by stuffing required information into the session.
83 * we'll then redirect over to the authorizer controller to get the work done.
85 public function requestGoogleOauth($id)
87 //hmmm: if no id, bail out to error page.
89 Log::debug("into requestGoogleOauth...");
91 if (session_status() == PHP_SESSION_NONE) {
95 // add the post-authorization redirect url for the auth controller.
96 $this->setPostAuthorizationURL('/users/callback/' . $id);
97 // set the scopes that we want to request.
98 $this->setRequestedScopes([Google_Service_Calendar::CALENDAR_READONLY]);
101 // $urlcheck = $_SESSION[$this->POST_AUTHORIZATION_JUMP()];
102 // Log::debug('callback url found in session: ' . var_export($urlcheck, true));
103 // $scopecheck = $_SESSION[$this->POST_AUTHORIZATION_JUMP()];
104 // Log::debug('scopes found in session: ' . var_export($scopecheck , true));
106 Log::debug("before redirecting from requestGoogleOauth...");
108 // get the user to authorize us, and subsequently we'll record the access token.
110 'controller' => 'Authorizer',
111 'action' => 'googleLogin'
118 * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
120 public function add() {
123 $user = $this->Users->newEntity ();
124 if ($this->request->is ( 'post' )) {
125 $user = $this->Users->patchEntity ( $user, $this->request->getData () );
126 if ($this->Users->save ( $user )) {
127 $this->Flash->success ( __ ( 'The user has been saved.' ) );
128 // now get the oauth mojo working...
129 $this->requestGoogleOauth($user->id);
132 $this->Flash->error ( __ ( 'The user could not be saved. Please, try again.' ) );
134 $this->set ( compact ( 'user' ) );
135 $this->set ( '_serialize', [
141 * a whole bunch of redirection happens when the oauth process starts, but this is our
142 * return point for this application after all that's done. this is registered as the
143 * post authorization redirection location, and should have a valid access token available
144 * for the specified user.
148 public function callback($id) {
149 Log::debug ( 'got to the users controller callback' );
151 $user = $this->Users->get ( $id );
153 // retrieve the access token, which is hopefully totally valid now...
154 $token = $this->getLastOAuthToken ();
156 $user->token = json_encode ( $token );
157 $this->Users->save ( $user );
159 $this->set ( 'user', $user );
160 $this->set ( '_serialize', [
168 * @param string|null $id
170 * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
171 * @throws \Cake\Network\Exception\NotFoundException When record not found.
173 public function edit($id = null) {
174 $user = $this->Users->get ( $id, [
177 if ($this->request->is ( [
182 $user = $this->Users->patchEntity ( $user, $this->request->getData () );
183 if ($this->Users->save ( $user )) {
184 $this->Flash->success ( __ ( 'The user has been saved.' ) );
186 return $this->redirect ( [
190 $this->Flash->error ( __ ( 'The user could not be saved. Please, try again.' ) );
192 $this->set ( compact ( 'user' ) );
193 $this->set ( '_serialize', [
201 * @param string|null $id
203 * @return \Cake\Http\Response|null Redirects to index.
204 * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
206 public function delete($id = null) {
207 $this->request->allowMethod ( [
211 $user = $this->Users->get ( $id );
212 if ($this->Users->delete ( $user )) {
213 $this->Flash->success ( __ ( 'The user has been deleted.' ) );
215 $this->Flash->error ( __ ( 'The user could not be deleted. Please, try again.' ) );
218 return $this->redirect ( [
224 * shows the upcoming appointments on the calendar.
226 public function showCalendar($id) {
227 Log::debug ( 'into the show calendar method' );
231 $user = $this->Users->get ( $id );
233 if (! $user->token) {
234 // apparently we need to re-acquire this for the user.
235 // NOTE: in real app, this will be a failure and a place to send email.
236 $this->requestGoogleOauth($id);
239 $accessToken = json_decode ( $user->token, true );
241 $client = $this->createGoogleClient( [
242 Google_Service_Calendar::CALENDAR_READONLY
245 $client->setAccessToken ( $accessToken );
247 // make sure that the token is still valid, and if not, refresh it.
248 $newToken = $this->freshenTokenInClient($client);
250 // save the new token in the db again.
251 $accessToken = $newToken;
252 $user->token = json_encode ( $accessToken );
253 $this->Users->save ( $user );
256 // start from beginning of today.
257 $start = new DateTime();
258 $start->setTime(0, 0);
260 // see if we have a cached calendar available.
261 $cacheKey = 'cal-' . $id . '--' . $start->format('Y-m-d_H-i-s');
262 $calEvents = Cache::read($cacheKey, 'calendar_cache');
264 Log::debug('found cached events for calendar.');
266 // an unfortunate kludge below; if we delay calling the google listEvents method,
267 // we can get an exception that requires reauthorization. but the view cell has no
268 // way to get to the controller to start the authorization process again, so we do
270 $calEvents = GoogleCalendarCell::prepareCalendar($client, $start);
271 Log::debug('contacted google to get events for calendar.');
273 // we have lost our authorization somehow.
274 $this->requestGoogleOauth($id);
277 Cache::write($cacheKey, $calEvents, 'calendar_cache');
279 $this->set('calEvents', $calEvents);
280 $this->set ( '_serialize', [
286 * revokes authorization granted by google for current token.
288 public function revoke($id) {
289 $user = $this->Users->get ( $id );
291 $this->set ( 'user', $user );
292 $this->set ( '_serialize', [
296 $token = json_decode ( $user->token, true );
298 Log::debug ( 'revoking token: ' . var_export ( $token, true ) );
300 $this->revokeToken($token);
301 Log::debug ( 'after revoking the access token.' );
303 // update with no token.
305 $this->Users->save ( $user );