Changes on server
- bugfixes in gcal callback - requirements txt
This commit is contained in:
		
							parent
							
								
									aac687c0c7
								
							
						
					
					
						commit
						46b4078fac
					
				|  | @ -1 +1 @@ | ||||||
| {"_module": "oauth2client.client", "token_expiry": "2014-04-19T18:37:13Z", "access_token": "ya29.1.AADtN_UNi3N8wJ5AiTZ3ced1ho7-ZOhe9cV0TqJ7lByEy_h5SHGm0EuZBSWVOQ3q3g", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "ya29.1.AADtN_UNi3N8wJ5AiTZ3ced1ho7-ZOhe9cV0TqJ7lByEy_h5SHGm0EuZBSWVOQ3q3g", "token_type": "Bearer", "expires_in": 3600}, "client_id": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com", "id_token": null, "client_secret": "y4t9XBrJdCODPTO5UvtONWWn", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "1/7-6-m_lLAKX8IeD7OuGtkcIiprty_nZUSxhMunSC5b0", "user_agent": null} | {"_module": "oauth2client.client", "token_expiry": "2014-04-20T19:09:26Z", "access_token": "ya29.1.AADtN_VE0fTw3cu2E9SR0XoblR3gXjnON1u2Qy__EB7E6HyEpaDky0LA-SmZVyok6A", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "ya29.1.AADtN_VE0fTw3cu2E9SR0XoblR3gXjnON1u2Qy__EB7E6HyEpaDky0LA-SmZVyok6A", "token_type": "Bearer", "expires_in": 3600}, "client_id": "34462582242-4kpdvvbi27ajt4u22uitqurpve9o8ipj.apps.googleusercontent.com", "id_token": null, "client_secret": "y4t9XBrJdCODPTO5UvtONWWn", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "1/7-6-m_lLAKX8IeD7OuGtkcIiprty_nZUSxhMunSC5b0", "user_agent": null} | ||||||
|  | @ -79,7 +79,7 @@ STATIC_ROOT = PROJECT_PATH + '/static_collection' | ||||||
| STATIC_URL = '/static/' | STATIC_URL = '/static/' | ||||||
| 
 | 
 | ||||||
| LOGIN_URL="/musicians/login" | LOGIN_URL="/musicians/login" | ||||||
| PUBLIC_URLS=( "^musicians/login/?$", "^musicians/login/usernames/?$") | PUBLIC_URLS=( "^musicians/login/?$", "^musicians/login/usernames/?$", "^eventplanner_gcal/gcalApiCallback*") | ||||||
| 
 | 
 | ||||||
| # Additional locations of static files | # Additional locations of static files | ||||||
| STATICFILES_DIRS = ( | STATICFILES_DIRS = ( | ||||||
|  | @ -195,49 +195,29 @@ CRISPY_TEMPLATE_PACK = 'bootstrap' | ||||||
| # the site admins on every HTTP 500 error when DEBUG=False. | # the site admins on every HTTP 500 error when DEBUG=False. | ||||||
| # See http://docs.djangoproject.com/en/dev/topics/logging for | # See http://docs.djangoproject.com/en/dev/topics/logging for | ||||||
| # more details on how to customize your logging configuration. | # more details on how to customize your logging configuration. | ||||||
|  | 
 | ||||||
| LOGGING = { | LOGGING = { | ||||||
|     'version': 1, |     'version': 1, | ||||||
|     'disable_existing_loggers': True, |     'disable_existing_loggers': False, | ||||||
|     'formatters': { |  | ||||||
|         'standard': { |  | ||||||
|             'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s", |  | ||||||
|             'datefmt' : "%d/%b/%Y %H:%M:%S" |  | ||||||
|         }, |  | ||||||
|     }, |  | ||||||
|     'handlers': { |     'handlers': { | ||||||
|         'null': { |         'file': { | ||||||
|             'level': 'DEBUG', |             'level': 'DEBUG', | ||||||
|             'class':'django.utils.log.NullHandler', |             'class': 'logging.FileHandler', | ||||||
|         }, |             'filename': '/srv/test/eventplanner.log', | ||||||
|         'logfile': { |  | ||||||
|             'level':'DEBUG', |  | ||||||
|             'class':'logging.handlers.RotatingFileHandler', |  | ||||||
|             'filename': PROJECT_PATH + "/logfile", |  | ||||||
|             'maxBytes': 50000, |  | ||||||
|             'backupCount': 2, |  | ||||||
|             'formatter': 'standard', |  | ||||||
|         }, |  | ||||||
|         'console':{ |  | ||||||
|             'level':'INFO', |  | ||||||
|             'class':'logging.StreamHandler', |  | ||||||
|             'formatter': 'standard' |  | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
|     'loggers': { |     'loggers': { | ||||||
|         'django': { |         'eventplanner_gcal': { | ||||||
|             'handlers':['console'], |             'handlers': ['file'], | ||||||
|  |             'level': 'DEBUG', | ||||||
|             'propagate': True, |             'propagate': True, | ||||||
|             'level':'WARN', |  | ||||||
|         }, |         }, | ||||||
|         'django.db.backends': { |         'eventplanner': {  | ||||||
|             'handlers': ['console'], |             'handler': ['file'], | ||||||
|             'level': 'DEBUG', |             'level': 'DEBUG', | ||||||
|             'propagate': False, |             'propagate': True, | ||||||
|         }, |  | ||||||
|         'musicians': { |  | ||||||
|             'handlers': ['console', 'logfile'], |  | ||||||
|             'level': 'DEBUG', |  | ||||||
|         }, |  | ||||||
| 	} | 	} | ||||||
|  |     }, | ||||||
|  |     | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,6 +15,13 @@ framework. | ||||||
| """ | """ | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
|  | import site | ||||||
|  | import sys | ||||||
|  | site.addsitedir('/srv/test/env/lib/python2.7/site-packages') | ||||||
|  | sys.path.append('/srv/test') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks | ||||||
| # if running multiple sites in the same mod_wsgi process. To fix this, use | # if running multiple sites in the same mod_wsgi process. To fix this, use | ||||||
| # mod_wsgi daemon mode with each site in its own daemon process, or use | # mod_wsgi daemon mode with each site in its own daemon process, or use | ||||||
|  |  | ||||||
|  | @ -132,6 +132,12 @@ class EventParticipation( models.Model ): | ||||||
|     def get_username(self): |     def get_username(self): | ||||||
|         return self.user.username |         return self.user.username | ||||||
|      |      | ||||||
|  |     def save( self, *args, **kwargs ): | ||||||
|  | 	prev = EventParticipation.objects.get( event = self.event, user = self.user ) | ||||||
|  | 	if prev.status != self.status or prev.comment != self.comment: | ||||||
|  | 	    super(EventParticipation,self).save( *args,**kwargs) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def hasUserSetParticipationForAllEvents( user ): |     def hasUserSetParticipationForAllEvents( user ): | ||||||
|         if not EventParticipation.isMember(user): |         if not EventParticipation.isMember(user): | ||||||
|  |  | ||||||
|  | @ -282,10 +282,10 @@ def checkGCalSubscription(): | ||||||
|     global service |     global service | ||||||
|     callbackUrl = settings.GCAL_COUPLING['push_url'] |     callbackUrl = settings.GCAL_COUPLING['push_url'] | ||||||
| 
 | 
 | ||||||
|     #timeToLive        = 14*24*3600 # how long the channel should be active |     timeToLive        = 14*24*3600 # how long the channel should be active | ||||||
|     #renewBeforeExpiry =  2*24*3600 # duration before expiry when channel is renewed |     renewBeforeExpiry =  2*24*3600 # duration before expiry when channel is renewed | ||||||
|     timeToLive = 60*5 |     #timeToLive = 60*5 | ||||||
|     renewBeforeExpiry = 60*3 |     #renewBeforeExpiry = 60*3 | ||||||
| 
 | 
 | ||||||
|     # Test if a channel already exists for this callbackURL |     # Test if a channel already exists for this callbackURL | ||||||
|     try: |     try: | ||||||
|  |  | ||||||
|  | @ -2,9 +2,11 @@ from django.db.models.signals import post_save,pre_delete | ||||||
| from django.dispatch import receiver | from django.dispatch import receiver | ||||||
| from eventplanner.models import Event, EventParticipation | from eventplanner.models import Event, EventParticipation | ||||||
| from django.contrib.auth.models import User | from django.contrib.auth.models import User | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| import eventplanner_gcal.models | import eventplanner_gcal.models | ||||||
|  | import logging | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger( __name__ ) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class SignalLock: | class SignalLock: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|  | @ -25,10 +27,21 @@ class SignalLock: | ||||||
| 
 | 
 | ||||||
| signalLock = SignalLock() | signalLock = SignalLock() | ||||||
| 
 | 
 | ||||||
| @receiver( post_save, sender=User ) | 
 | ||||||
| def user_changed( **kwargs ): | def onGoogleCallback(): | ||||||
|     if not signalLock.isLocked(): |     if not signalLock.isLocked(): | ||||||
|         with signalLock: |         with signalLock: | ||||||
|  | 	    logger.info( "Sync back from google" ) | ||||||
|  |             eventplanner_gcal.models.syncParticipationFromGoogleToLocal() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @receiver( post_save, sender=User ) | ||||||
|  | def user_changed( **kwargs ): | ||||||
|  |     logger.info("User info changed") | ||||||
|  |     if not signalLock.isLocked(): | ||||||
|  |         with signalLock: | ||||||
|  |             logger.info("Synchronizing with google - user information changed") | ||||||
|  |             eventplanner_gcal.models.deleteAllGCalEvents() | ||||||
|             eventplanner_gcal.models.syncGCalEvents() |             eventplanner_gcal.models.syncGCalEvents() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -39,10 +52,10 @@ def event_post_save_handler( **kwargs): | ||||||
|             event = kwargs['instance'] |             event = kwargs['instance'] | ||||||
|             created = kwargs['created'] |             created = kwargs['created'] | ||||||
|             if created: |             if created: | ||||||
|                 print("Creating Gcal event") |                 logger.info("Creating Gcal event") | ||||||
|                 eventplanner_gcal.models.createGCalEvent( event ).execute() |                 eventplanner_gcal.models.createGCalEvent( event ).execute() | ||||||
|             else: |             else: | ||||||
|                 print( "Updating Gcal event") |                 logger.info( "Updating Gcal event") | ||||||
|                 eventplanner_gcal.models.updateGCalEvent( event ).execute() |                 eventplanner_gcal.models.updateGCalEvent( event ).execute() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -52,7 +65,7 @@ def event_pre_delete_handler( **kwargs): | ||||||
|     if not signalLock.isLocked(): |     if not signalLock.isLocked(): | ||||||
|         with signalLock: |         with signalLock: | ||||||
|             event = kwargs['instance'] |             event = kwargs['instance'] | ||||||
|             print ("Deleting GCAL event") |             logger.info ("Deleting GCAL event") | ||||||
|             eventplanner_gcal.models.deleteGCalEvent( event ).execute() |             eventplanner_gcal.models.deleteGCalEvent( event ).execute() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -61,7 +74,7 @@ def participation_post_save_handler( **kwargs): | ||||||
|     if not signalLock.isLocked(): |     if not signalLock.isLocked(): | ||||||
|         with signalLock: |         with signalLock: | ||||||
|             participation = kwargs['instance'] |             participation = kwargs['instance'] | ||||||
|             print("Participation post save -> update gcal") |             logger.info("Participation post save -> update gcal") | ||||||
|             eventplanner_gcal.models.updateGCalEvent( participation.event ).execute() |             eventplanner_gcal.models.updateGCalEvent( participation.event ).execute() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,16 +1,24 @@ | ||||||
| from django.shortcuts import  redirect | from django.shortcuts import  redirect | ||||||
| from eventplanner_gcal.models import syncGCalEvents, syncParticipationFromGoogleToLocal | from eventplanner_gcal.models import syncGCalEvents, syncParticipationFromGoogleToLocal | ||||||
|  | from eventplanner_gcal.signals import onGoogleCallback | ||||||
|  | from django.http import HttpResponse | ||||||
|  | from django.views.decorators.csrf import csrf_exempt | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger( __name__ ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def runSync( request ): | def runSync( request ): | ||||||
|     syncGCalEvents() |     syncGCalEvents() | ||||||
|  |      | ||||||
|     return redirect("/") |     return redirect("/") | ||||||
| 
 | 
 | ||||||
| 
 | @csrf_exempt | ||||||
| def gcalApiCallback( request ): | def gcalApiCallback( request ): | ||||||
|     syncParticipationFromGoogleToLocal() |     onGoogleCallback() | ||||||
|     print ( "gcalApiCallback called" ) |     logger.info("Received callback from GCal - updating event participations... ") | ||||||
|     return redirect("/") |     return HttpResponse('<h1>Callback successful</h1>') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | Django==1.5.5 | ||||||
|  | PIL==1.1.7 | ||||||
|  | South==0.8.2 | ||||||
|  | django-classy-tags==0.4 | ||||||
|  | django-crispy-forms==1.4.0 | ||||||
|  | django-sekizai==0.7 | ||||||
|  | django-tagging==0.3.1 | ||||||
|  | djangorestframework==2.3.8 | ||||||
|  | google-api-python-client==1.2 | ||||||
|  | httplib2==0.9 | ||||||
|  | reportlab==3.0 | ||||||
|  | sorl-thumbnail==11.12 | ||||||
|  | tagging==0.2.1 | ||||||
|  | wsgiref==0.1.2 | ||||||
|  | @ -82,7 +82,7 @@ | ||||||
|         <img class="asset left-30 sp600 t150 z1" src="{{STATIC_URL}}/img/googleCalNew.png" /> |         <img class="asset left-30 sp600 t150 z1" src="{{STATIC_URL}}/img/googleCalNew.png" /> | ||||||
| 		<div class="info"> | 		<div class="info"> | ||||||
| 			<a href="/musicians/profile">GoogleCalendar</a> | 			<a href="/musicians/profile">GoogleCalendar</a> | ||||||
| 			<div class="subtitle subtitlebg">Geht ganz einfach: Im Profil eine Google Mail Adresse eintragen</div> | 			<div class="subtitle subtitlebg">Jetzt auch auf dem Handy im GoogleCalendar Termine planen: Einfach im Profil eine Google Email Adresse eintragen...</div> | ||||||
| 		</div> | 		</div> | ||||||
| 
 | 
 | ||||||
| 	</article> | 	</article> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue