Exemple #1
0
    def _perform_auth(self, method, context, request, **kw):
        "Internal method"

        if not getattr(request, 'gclient', None):
            request.gclient = {}
        if not getattr(request, 'gservice', None):
            request.gservice = {}

        request.gclient[self.client.__class__.__name__] = self.client
        request.gservice[self.service.__class__.__name__] = self.service

        identity = request.environ.get('repoze.who.identity')
        if not identity:
            raise Forbidden

        user = identity.get('user')
        user_domains = user.email_domains
        if user_domains: 
            user_domain = user_domains[0]
        else:
            user_domain = 'default'
        next_url = request.url

        request_token = request.params.get('token')
        if request_token:
            authsub_token = AuthSubToken(scopes=self.scopes)
            authsub_token.set_token_string(request_token)
            self.service.auth_token = authsub_token
            self.service.UpgradeToSessionToken(token=authsub_token)
            user.gdata_auth_token = self.service.auth_token.get_token_string()

            #cleanup qs
            qs = dict(parse_qsl(urlparse(next_url).query))
            try:
                del qs['auth_sub_scopes']
                del qs['token']
                del qs['force']
            except KeyError: pass

            next_url = '%s?%s' % (request.path_url, urlencode(qs))
            raise HTTPFound(next_url)

        authsub_token = AuthSubToken(user.gdata_auth_token, scopes=self.scopes)
        self.service.SetAuthSubToken(user.gdata_auth_token)

        try:
            self.service.AuthSubTokenInfo()
        except RequestError:
            user.gdata_auth_token = None
            raise AuthSubURLRedirect(next_url, self.scopes, domain=user_domain)

        self.client.auth_token = gAuthSubToken(user.gdata_auth_token, scopes=self.scopes)
        return method(context, request, **kw)
Exemple #2
0
def return_(request):
    next = request.GET["next"]
    gd_client = gdata.contacts.service.ContactsService()
    token = AuthSubToken()
    token.set_token_string(request.GET["token"])
    gd_client.UpgradeToSessionToken(token)

    query = gdata.contacts.service.ContactsQuery()
    query.max_results = getattr(settings, "DGCI_MAX_CONTACTS", 100)
    feed = gd_client.GetContactsFeed(query.ToUri())

    request.session["dgci_contact_feed"] = feed
    return HttpResponseRedirect(next)
class GDataConnector(connector_interface.ConnectorInterface):
    @staticmethod
    def get_spreadsheet_id(feed, name):
        for spreadsheet in feed.entry:
            if spreadsheet.title.text == name:
                return spreadsheet.id.text.split("/")[-1]

        return None

    @staticmethod
    def get_worksheet_dictionary(feed):
        output = {}

        for worksheet in feed.entry:
            output[worksheet.title.text] = worksheet.id.text.split("/")[-1]

        return output

    @staticmethod
    def get_key_dictionary(feed, key_label="key"):
        output = {}

        for row in feed.entry:
            key = row.custom.get(key_label)
            if not key:
                continue
            output[key.text] = row

        return output

    @staticmethod
    def get_neutral_rows(feed):
        output = []

        for row in feed.entry:
            dictionary = {}
            for k, v in row.custom.items():
                dictionary[k] = v.text

            output.append(dictionary)

        return output

    def __init__(self, options, name="unknown"):
        self.kind_name = name
        self.token_string = options.get("token", AUTHSUB_TOKEN)
        self.spreadsheet_name = options.get("spreadsheet", SPREADSHEET)
        self.worksheet_name = options.get("worksheet", name)
        self.key_label = options.get("key_label", "key")

    def setup_client(self, spreadsheet):
        try:
            from google.appengine.api import apiproxy_stub_map
            from google.appengine.api import urlfetch_stub

            apiproxy_stub_map.apiproxy.RegisterStub("urlfetch", urlfetch_stub.URLFetchServiceStub())
        except:
            pass

        self.spreadsheet = spreadsheet

        self.client = gdata.spreadsheet.service.SpreadsheetsService()
        gdata.alt.appengine.run_on_appengine(self.client, store_tokens=False)

        self.token = AuthSubToken()
        self.token.set_token_string(self.token_string)
        self.token.scopes = lookup_scopes(self.client.service)
        self.client.current_token = self.token
        self.feed = self.client.GetSpreadsheetsFeed()
        self.id = GDataConnector.get_spreadsheet_id(self.feed, spreadsheet)
        self.worksheets = GDataConnector.get_worksheet_dictionary(self.client.GetWorksheetsFeed(self.id))

    def generate_import_record(self, filename, bulkload_state):
        if not hasattr(self, "client"):
            self.setup_client(self.spreadsheet_name)

        worksheet = self.worksheets.get(self.worksheet_name)
        if worksheet is None:
            raise WorksheetMissing(
                "There is no worksheet to import for %s" % self.kind_name
            )  # if the sheet doesn't exist raise an exception

        # get every row
        feed = self.client.GetListFeed(self.id, worksheet)
        rows = self.get_neutral_rows(feed)

        # yield each row as a dictionary
        for row in rows:
            yield row

    def initialize_export(self, filename, bulkload_state):
        if self.spreadsheet_name:
            SPREADSHEET = self.spreadsheet_name

        if hasattr(self, "client"):
            return

        self.setup_client(SPREADSHEET)

        worksheet = self.worksheets.get(self.worksheet_name)

        if worksheet != None:
            feed = self.client.GetListFeed(self.id, worksheet)
            self.key_dictionary = self.get_key_dictionary(feed, self.key_label)
        else:
            self.key_dictionary = {}

    def write_dict(self, dictionary):
        # find out which model we are writing
        # open/create that worksheet
        # make sure the worksheet has the header row

        worksheet = self.worksheets.get(self.worksheet_name)
        if worksheet is None:
            entry = self.client.AddWorksheet(self.worksheet_name, 2, len(dictionary), self.id)

            self.worksheets[self.worksheet_name] = worksheet = entry.id.text.split("/")[-1]

            i = 1
            # FIXME: painfully slow. Could be improved with a batch submit
            for key in dictionary.keys():
                entry = self.client.UpdateCell(row=1, col=i, inputValue=key, key=self.id, wksht_id=worksheet)
                i += 1

        row = self.key_dictionary.get(dictionary.get(self.key_label, ""))

        # we know we've found the exact row
        if row:
            # FIXME: could skip the update if the feed.entry is the same as the dictionary for all key/values
            entry = self.client.UpdateRow(row, dictionary)
        else:
            entry = self.client.InsertRow(dictionary, self.id, worksheet)

    def finalize_export(self):
        # don't think I need to do anything?
        pass
	def get(self):
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write('<html><head><title>GV Scheduler</title></head><body><div id="main">')
		self.cal_client = gdata.calendar.service.CalendarService()
		# Tell the client that we are running in single user mode, and it should not
		# automatically try to associate the token with the current user then store
		# it in the datastore.
		gdata.alt.appengine.run_on_appengine(self.cal_client, store_tokens=False, single_user_mode=True)
		# Load processed events to avoid multiple calls for the same event
		self.processed_events = memcache.get(MEMKEY)
		if self.processed_events is None:
			self.processed_events = defaultdict(set)
		#logging.debug('Loaded memcache: %s' % str(self.processed_events))
       	# Find an AuthSub token in the current URL if we arrived at this page from an AuthSub redirect
		session_token = None
		auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
		if auth_token:
			# Upgrade the single-use AuthSub token to a multi-use session token.
			session_token = self.cal_client.upgrade_to_session_token(auth_token)
            # Store the token in the datastore
			if session_token:
				tkn = Token()
				tkn.tokenstr = session_token.get_token_string()
				tkn.put()
				#logging.debug('Storing session token: %s' % session_token)
				self.response.out.write('</div></body></html>')
				self.redirect("/")
		else:
			# Token stored in DB?
			tknn = (db.GqlQuery("SELECT * FROM Token ORDER BY date DESC LIMIT 1")).get()
			if tknn:
				session_token = AuthSubToken()
				session_token.set_token_string(tknn.tokenstr)				
				#logging.debug('Read session token from DB: %s' % session_token)
		#Is this app authorized to access Google Calendar?
		feed_url = 'http://www.google.com/calendar/feeds/'
		if not session_token:
			# Tell the user that they need to login to authorize this app by logging in at the following URL.
			next = atom.url.Url('http', HOST_NAME, path='/', params={'feed_url': feed_url})
			auth_sub_url = self.cal_client.GenerateAuthSubURL(next, feed_url, secure=False, session=True)
			self.response.out.write('<a href="%s">Please click here to authorize GVScheduler to access your Google Calendar</a>' % (auth_sub_url))
			logging.error('Please visit your app URL (e.g. http://YOUR_GAE_APP_NAME.appspot.com/) to authorize access to your Google Calendar')
		else:
			#logging.debug('Found session_token: %s' % session_token)
			self.cal_client.SetAuthSubToken(session_token)
			self.response.out.write('GVScheduler is up and running - <font color=green>OK</font>...')
			feed = self.GetEventsFromCalendar()
			if feed:
				if feed.entry:
					for i, an_event in zip(xrange(len(feed.entry)), feed.entry):
						# Look in Title and Content of the event...
						combstring = an_event.title.text if an_event.title.text is not None else ''
						combstring += ('\n' + an_event.content.text) if an_event.content.text is not None else '' 
						kd = self.ParseString(combstring)
						# Test if call needs to be placed. Entry must have "GVCall=number" in Title or in Content
						if ("gvcall" in kd):
							pn = self.FormatPhoneNumber(kd['gvcall'])
							starttime = an_event.when[0].start_time
							# Check if the call for this event was already placed
							if (not self.processed_events[starttime]) or (pn not in self.processed_events[starttime]):
								if ("gvringnumber" in kd):
									rn = self.FormatPhoneNumber(kd['gvringnumber'])
								else:
									rn = config.forwardingNumber
								if ("gvringtype" in kd):
									rt = kd['gvringtype']
								else:
									rt = config.phoneType
								logging.info('Event: %s, Calling: %s, Ringing: %s (Type: %s)' % (an_event.title.text, pn, rn, rt))
								self.GVPlaceCall(pn, rn, rt)
								self.processed_events[starttime].add(pn)
								#logging.debug('Adding to memcache: [%s] = (%s)' % (starttime, pn))
							#else:
							#	logging.debug('Skipping processed event: [%s] = (%s)' % (starttime, pn))
					memcache.set(MEMKEY, self.processed_events)
				else:
					# No events fetched, clear the cache
					memcache.flush_all()
					#logging.debug('Deleting memcache...')
		self.response.out.write('</div></body></html>')