adding example apps, fixing powerup issues
[feisty_meow.git] / production / example_apps / shared_calendar / src / Controller / UsersController.php
1 <?php
2
3 namespace App\Controller;
4
5 use App\Controller\AppController;
6 use Cake\Core\Configure;
7 use Cake\Cache\Cache;
8 use Cake\Log\Log;
9 use DateTime;
10 use Google_Service_Calendar;
11 use App\Traits\GoogleOauthTrait;
12 use App\View\Cell\GoogleCalendarCell;
13
14 /**
15  * Users Controller
16  *
17  * @property \App\Model\Table\UsersTable $Users
18  *
19  * @method \App\Model\Entity\User[] paginate($object = null, array $settings = [])
20  */
21 class UsersController extends AppController 
22 {
23         use GoogleOauthTrait;
24         
25         public function initialize()
26         {
27                 parent::initialize();
28                 
29                 // configure the cache for our class.
30                 
31                 $prefix = 'av_'. strtolower($this->name) .'-';
32                 // av_ prefix so we can delete all files generated in cache/sql/ except for .gitignore
33                 
34                 $locales = Configure::read('avenger.locales');          
35                 if(!empty($locales)) {                  
36                         $prefix .= Configure::read('Config.language') .'-';                     
37                 }
38                 Log::debug('cache prefix will be: ' . $prefix);
39                 
40                 // configure a file cache for storing calendar data.
41                 Cache::config('calendar_cache', [
42                                 'className' => 'File',
43                                 'prefix'     => $prefix,
44                                 'duration'   => '+2 hours',                     
45                 ]);             
46         }
47         
48         /**
49          * Index method
50          *
51          * @return \Cake\Http\Response|void
52          */
53         public function index() {
54                 $users = $this->paginate ( $this->Users );
55                 
56                 $this->set ( compact ( 'users' ) );
57                 $this->set ( '_serialize', [ 
58                                 'users' 
59                 ] );
60         }
61         
62         /**
63          * View method
64          *
65          * @param string|null $id
66          *              User id.
67          * @return \Cake\Http\Response|void
68          * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
69          */
70         public function view($id = null) {
71                 $user = $this->Users->get ( $id, [ 
72                                 'contain' => [ ] 
73                 ] );
74                 
75                 $this->set ( 'user', $user );
76                 $this->set ( '_serialize', [ 
77                                 'user' 
78                 ] );
79         }
80         
81         /**
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.
84          */
85         public function requestGoogleOauth($id)
86         {
87                 //hmmm: if no id, bail out to error page.
88
89                 Log::debug("into requestGoogleOauth...");
90                 
91                 if (session_status() == PHP_SESSION_NONE) {
92                         session_start ();
93                 }
94                 
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]);
99                 
100 //              //temp
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));
105                 
106                 Log::debug("before redirecting from requestGoogleOauth...");
107                                 
108                 // get the user to authorize us, and subsequently we'll record the access token.
109                 $this->redirect ( [
110                                 'controller' => 'Authorizer',
111                                 'action' => 'googleLogin'
112                 ] );
113         }
114         
115         /**
116          * Add method
117          *
118          * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
119          */
120         public function add() {
121                 session_start ();
122                 
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);
130                                 return;
131                         }
132                         $this->Flash->error ( __ ( 'The user could not be saved. Please, try again.' ) );
133                 }
134                 $this->set ( compact ( 'user' ) );
135                 $this->set ( '_serialize', [ 
136                                 'user' 
137                 ] );
138         }
139         
140         /**
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.
145          * 
146          * @param unknown $id
147          */
148         public function callback($id) {
149                 Log::debug ( 'got to the users controller callback' );
150                 
151                 $user = $this->Users->get ( $id );
152                 
153                 // retrieve the access token, which is hopefully totally valid now...
154                 $token = $this->getLastOAuthToken ();
155                 if ($token) {
156                         $user->token = json_encode ( $token );
157                         $this->Users->save ( $user );
158                 }
159                 $this->set ( 'user', $user );
160                 $this->set ( '_serialize', [ 
161                                 'user' 
162                 ] );
163         }
164         
165         /**
166          * Edit method
167          *
168          * @param string|null $id
169          *              User id.
170          * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
171          * @throws \Cake\Network\Exception\NotFoundException When record not found.
172          */
173         public function edit($id = null) {
174                 $user = $this->Users->get ( $id, [ 
175                                 'contain' => [ ] 
176                 ] );
177                 if ($this->request->is ( [ 
178                                 'patch',
179                                 'post',
180                                 'put' 
181                 ] )) {
182                         $user = $this->Users->patchEntity ( $user, $this->request->getData () );
183                         if ($this->Users->save ( $user )) {
184                                 $this->Flash->success ( __ ( 'The user has been saved.' ) );
185                                 
186                                 return $this->redirect ( [ 
187                                                 'action' => 'index' 
188                                 ] );
189                         }
190                         $this->Flash->error ( __ ( 'The user could not be saved. Please, try again.' ) );
191                 }
192                 $this->set ( compact ( 'user' ) );
193                 $this->set ( '_serialize', [ 
194                                 'user' 
195                 ] );
196         }
197         
198         /**
199          * Delete method
200          *
201          * @param string|null $id
202          *              User id.
203          * @return \Cake\Http\Response|null Redirects to index.
204          * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
205          */
206         public function delete($id = null) {
207                 $this->request->allowMethod ( [ 
208                                 'post',
209                                 'delete' 
210                 ] );
211                 $user = $this->Users->get ( $id );
212                 if ($this->Users->delete ( $user )) {
213                         $this->Flash->success ( __ ( 'The user has been deleted.' ) );
214                 } else {
215                         $this->Flash->error ( __ ( 'The user could not be deleted. Please, try again.' ) );
216                 }
217                 
218                 return $this->redirect ( [ 
219                                 'action' => 'index' 
220                 ] );
221         }
222         
223         /**
224          * shows the upcoming appointments on the calendar.
225          */
226         public function showCalendar($id) {
227                 Log::debug ( 'into the show calendar method' );
228                 
229                 session_start ();
230                 
231                 $user = $this->Users->get ( $id );
232
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);
237                         return;
238                 }
239                 $accessToken = json_decode ( $user->token, true );
240                 
241                 $client = $this->createGoogleClient( [ 
242                                 Google_Service_Calendar::CALENDAR_READONLY 
243                 ] );
244                 
245                 $client->setAccessToken ( $accessToken );
246                 
247                 // make sure that the token is still valid, and if not, refresh it.
248                 $newToken = $this->freshenTokenInClient($client);
249                 if ($newToken) {
250                         // save the new token in the db again.
251                         $accessToken = $newToken;
252                         $user->token = json_encode ( $accessToken );
253                         $this->Users->save ( $user );
254                 }
255
256                 // start from beginning of today.
257                 $start = new DateTime();
258                 $start->setTime(0, 0);
259                 
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');
263                 if ($calEvents) {
264                         Log::debug('found cached events for calendar.');
265                 } else {
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
269                         // it here instead.
270                         $calEvents = GoogleCalendarCell::prepareCalendar($client, $start);
271                         Log::debug('contacted google to get events for calendar.');
272                         if (! $calEvents) {
273                                 // we have lost our authorization somehow.
274                                 $this->requestGoogleOauth($id);
275                                 return;
276                         }
277                         Cache::write($cacheKey, $calEvents, 'calendar_cache');
278                 }
279                 $this->set('calEvents', $calEvents);
280                 $this->set ( '_serialize', [
281                                 'calEvents'
282                 ] );
283         }
284         
285         /**
286          * revokes authorization granted by google for current token.
287          */
288         public function revoke($id) {
289                 $user = $this->Users->get ( $id );
290                 
291                 $this->set ( 'user', $user );
292                 $this->set ( '_serialize', [ 
293                                 'user' 
294                 ] );
295                 
296                 $token = json_decode ( $user->token, true );
297                 
298                 Log::debug ( 'revoking token: ' . var_export ( $token, true ) );
299
300                 $this->revokeToken($token);             
301                 Log::debug ( 'after revoking the access token.' );
302                 
303                 // update with no token.
304                 $user->token = null;
305                 $this->Users->save ( $user );
306         }
307         
308
309 }