how can i modify the following python code to upload the ecg.txt to google drive every 5 seconds where i update this text file. the code now ask for Oauth every time it upload the file , i want it to ask for authentication only in the first time.
#!/usr/bin/python
import httplib2
import pprint
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
from oauth2client.client import OAuth2WebServerFlow
# Copy your credentials from the console
CLIENT_ID = XXXXXX
CLIENT_SECRET = XXXXX
# Check https://developers.google.com/drive/scopes for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive'
# Redirect URI for installed apps
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Path to the file to upload
FILENAME = 'ecg.txt'
# Run through the OAuth flow and retrieve credentials
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()
print 'Go to the following link in your browser: ' + authorize_url
code = raw_input('Enter verification code: ').strip()
credentials = flow.step2_exchange(code)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
drive_service = build('drive', 'v2', http=http)
# Insert a file
media_body = MediaFileUpload(FILENAME, mimetype='text/plain', resumable=True)
body = {
'title': 'My document',
'description': 'A test document',
'mimeType': 'text/plain'
}
file = drive_service.files().insert(body=body, media_body=media_body).execute()
pprint.pprint(file)
If you use the decorator as seen in the video bellow it stores your access token in the db for you and handles refreshing when needed.
https://www.youtube.com/watch?v=HoUdWBzUZ-M
https://developers.google.com/api-client-library/python/guide/google_app_engine
from oauth2client.appengine import OAuth2Decorator
decorator = OAuth2Decorator(client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
scope=OAUTH_SCOPE,
callback_path=REDIRECT_URI)
class MainPage(webapp2.RequestHandler):
#decorator.oauth_required #Simply place this above any function that requires login.
def get(self):
Related
I'm using gmail API to insert an email to the inbox. When the From domain is outside the organization, I expect the external label to be added but it's not.
I'm using python and everything else is working, I am using a service account and able to impersonate on behalf the user's email and I'm using labelIds of ['INBOX', 'UNREAD'] and I need the newly external label as well but couldn't figure a way to add it through the API.
This feature is turned ON for the workspace.
Update - adding my code:
from googleapiclient import discovery, errors
from google.oauth2 import service_account
from email.mime.text import MIMEText
import base64
SERVICE_ACCOUNT_FILE = 'insert-messages-91e77b62878f.json'
SCOPES = ['https://www.googleapis.com/auth/gmail.insert']
def validationService():
# Set the credentials
credentials = service_account.Credentials.\
from_service_account_file(SERVICE_ACCOUNT_FILE, scopes= SCOPES)
# Delegate the credentials to the user you want to impersonate
delegated_credentials = credentials.with_subject('<some_user>')
service = discovery.build('gmail', 'v1', credentials=delegated_credentials)
return service
def SendMessage(service, message):
message = service.users().messages().insert(userId='me', body=message).execute() # me will use <some_user> from above
return message
def CreateMessage(sender, to, subject, message_text):
message = MIMEText(message_text)
message['To'] = to
message['From'] = sender
message['Subject'] = subject
return {'raw': base64.urlsafe_b64encode(message.as_string().encode()).decode(), 'labelIds': ['INBOX', 'UNREAD']}
def main():
try:
service = validationService()
email = CreateMessage('some#external.com', "<some_user>", "Test", "This is a test")
email_sent = SendMessage(service, email)
print('Message Id:', email_sent['id'])
except errors.HttpError as err:
print('\n---------------You have the following error-------------')
print(err)
print('---------------You have the following error-------------\n')
if __name__ == '__main__':
main()
So I've deployed my flask app with react front end to heroku, but there seems to be some problem where flask is running on my local host instead of one the heroku server.
I've read tons of stackoverflow posts on this but to no resolution. Here is my flask code:
from flask import Flask, request
import flask
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_cors import CORS
app = Flask(__name__,static_folder="./build",static_url_path="/")
app.config['SQLALCHEMY_DATABASE_URI'] = 'my database url'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.secret_key = 'secret string'
CORS(app)
db = SQLAlchemy(app)
class Feature_votes(db.Model):
feature = db.Column(db.String(500), primary_key=True)
votes = db.Column(db.Integer, nullable=False)
date = db.Column(db.DateTime, nullable=False)
def __init__(self, feature, votes, date):
self.feature = feature
self.votes = votes
self.date = date
# Serve the react app
#app.route("/")
def index():
return app.send_static_file("index.html")
# Retrieve currently polled features from Feature_votes
#app.route("/getVotes", methods=['GET'])
def getVotes():
rows = Feature_votes.query.filter().order_by(Feature_votes.date)
response = []
for row in rows:
response.append(
{"feature": row.feature,
"votes": row.votes
})
return flask.jsonify(response)
# Add a new feature to the db with votes set to 0
#app.route("/featureAdd", methods=['POST'])
def featureAdd():
feature = request.get_json()["feature"]
featureEntry = Feature_votes(feature, 0, datetime.utcnow())
db.session.add(featureEntry)
db.session.commit()
response = {"feature": featureEntry.feature,
"votes": 0,
"date": featureEntry.date
}
return response
#app.route("/featureModifyVotes", methods=['POST'])
def featureUnvote():
feature = request.get_json()["feature"]
direction = request.get_json()["direction"]
featureEntry = Feature_votes.query.filter_by(feature=feature).first()
if (direction == "increase"):
featureEntry.votes += 1
else:
featureEntry.votes -= 1
db.session.commit()
response = {featureEntry.feature: featureEntry.votes}
return response
if __name__ == '__main__':
app.run()
and here is my Procfile
web: gunicorn --bind 0.0.0.0:$PORT server:app
Also here is a snip I took from inspect element to show that this request is being served locally.
I am relatively new to web development so it is possible I made a lot of mistakes. Please let me know if you can help or need any more info from me. Thanks.
So apparently that screenshot I posted in the question didn't mean that my server was running on localhost, but rather that my request was being made to the localhost. Turns out I had fetch("http://localhost...) in my build files. After using a relative path, rebuilding and pushing to heroku, everything is working.
I am integrating federated login using firebase authentication and I have REST API's on google appengine endpoints and other servers that am accessing.
Conceptually, the user logs in via firebase google signin, the angular web client gets the id token using the firebase client libraries and sends it to the google endpoint. The google endpoint verifies the id token to grant access.
After reading and working through various articles I have finally got something working, however I have very little experience in this area of authorization and was wondering if there was a better way to do this.
Code to get the id token on the client side is
firebase.auth().currentUser.getToken(true).then(function(idToken) {
// Send token to your backend via HTTPS
}
This code works and I get the correct id token.
For now I am using postman to send this id token to the app engine endpoint in the authorization header.
Google appengine endpoint code is
# only showing imports specifically required for cryptography
import jwt
import jwt.algorithms
from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
jwt.register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))
logging.debug("algorithms = ", jwt.algorithms.get_default_algorithms())
#had to install pyjwt as a library in appengine https://cloud.google.com/appengine/docs/python/tools/using-libraries-python-27
import json
import base64
from Crypto.Util.asn1 import DerSequence
from Crypto.PublicKey import RSA
from binascii import a2b_base64
import httplib
""" Message to accept a JWT for access """
class UserJWTMsg(messages.Message):
token = messages.StringField(1)
class UserMsg(messages.Message):
name = messages.StringField(1)
# [START user_api]
#endpoints.api(name='user', version='v1')
class UserApi(remote.Service):
""" Access with id Token """
#endpoints.method(
message_types.VoidMessage,
UserMsg,
path='access-with-idToken',
http_method='GET',
name='access-with-idToken')
def access_with_id_token(self, request):
id_token = self.request_state.headers.get('authorization')
id_token_parts = id_token.split('.')
#get key id from the token header
#check if padding needs to be added to the id token header
padding_count = 4 - len(id_token_parts[0])%4
if padding_count:
id_token_header = id_token_parts[0] + b'='*padding_count
#decode base64 header
decoded_id_token_header_json = base64.b64decode(id_token_header)
decoded_id_token_header = json.loads(decoded_id_token_header_json)
#get key id from the header
key_id = decoded_id_token_header['kid']
#get certificate for the given key id, #cert = CERTS.get(key_id)
cert = getCertificate(key_id)
#get the public key from certificate
public_key = pubKeyFrmCert(cert)
#decode / verify id token
decoded_payload = jwt.decode(id_token, public_key, audience='audience')
return UserMsg(name=json.dumps(decoded_payload));
""" get Certificate for key id """
def getCertificate(key_id):
c = httplib.HTTPSConnection("www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com")
c.request("GET", "/")
response = c.getresponse()
cert_str = response.read()
cert_obj = json.loads(cert_str)
cert = cert_obj.get(key_id)
return(cert)
""" return a public key from a X509 certificate """
""" http://stackoverflow.com/questions/12911373/how-do-i-use-a-x509-certificate-with-pycrypto """
def pubKeyFrmCert(cert):
lines = cert.replace(" ",'').split()
der = a2b_base64(''.join(lines[1:-1]))
# Extract subjectPublicKeyInfo field from X.509 certificate (see RFC3280)
cert = DerSequence()
cert.decode(der)
tbsCertificate = DerSequence()
tbsCertificate.decode(cert[0])
subjectPublicKeyInfo = tbsCertificate[6]
# Initialize RSA key
rsa_key = RSA.importKey(subjectPublicKeyInfo)
return(rsa_key)
I want to get unread mails from yesterday. So i had to implement multiple queries in the message.list function which give me an error of invalid syntax. How do i do it? Can someone help me? And will internalDate help me anyway?
from __future__ import print_function
import httplib2
import os
from email.utils import parsedate_tz,mktime_tz,formatdate
from requests.adapters import HTTPAdapter
import datetime
from datetime import date,timedelta
import time
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
import json
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://www.googleapis.com/auth/gmail.readonly'
CLIENT_SECRET_FILE = 'client_server.json'
APPLICATION_NAME = 'Gmail API Python Quickstart'
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'gmail-python-quickstart.json')
store = oauth2client.file.Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
da=date.fromordinal(730920)
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('gmail', 'v1', http=http)
today=date.today()
print (today)
yesterday=today-timedelta(1)
print (yesterday)
response = service.users().messages().list(userId='me',q='{in:inbox is:unread} AND {after: {0}.format(yesterday.strftime('%Y/%m/%d'))}').execute()
messages=[]
store=[]
message1=[]
test2=[]
da=[]
if 'messages' in response:
messages.extend(response['messages'])
fo = open("foo.txt", "wb")
for i in range(len(messages)):
store=messages[i]['id']
message = service.users().messages().get(userId='me',id=store,format='metadata',metadataHeaders=['from','date']).execute()
fo.write(store+" ");
#print(message['payload']['headers'][0])
fo.write(message['snippet'].encode('utf-8')+" ")
if message['payload']['headers'][0]['name'].lower()=="from":
From=message['payload']['headers'][0]['value']
fo.write(From+" ");
elif message['payload']['headers'][0]['name'].lower()=="date":
da=message['payload']['headers'][0]['value']
fo.write(da+"\n");
for line in open("foo.txt"):
print(line)
# Open a file
# Close opend file
fo.close()
if __name__ == '__main__':
main()
Use:
q='in:inbox is:unread newer_than:3d'
as the query. Gmail queries don't have a concept of timezones so if you try to get one day worth of email you'll end up with some overlap. Just use local filtering to narrow those down. See advanced Gmail search for more help. The API and Gmail UI use the same query syntax and should show the same results so you can do testing in the UI.
I tried to implement GAE's webapp2 session, but there seems very little documentation about it. According to http://webapp-improved.appspot.com/api/webapp2_extras/sessions.html, my steps are as follows:
1.Configure and add config to the main application:
config = {}
config['webapp2_extras.sessions'] = {
'secret_key': 'my_secret_key',
}
app = webapp2.WSGIApplication([...], config=config)
2.Create session in the login handler
# Delete existent session
--> not mention in the tutorial
# member is found
self.session_store = sessions.get_store(request=handler.request)
self.session['account'] = member.account
3.Check if a session exists at various locations in my program
if self.session['account']:
# Session exists
4.Delete session when user logs out
--> not mentioned in the tutorial
My questions:
I got error message " ... object has no attribute 'session'" during the session creation process (Step 2)
How do I delete a session in steps 2 and 4?
Is the overall session management process correct?
Thanks.
Here is an example of the handler and how to use webapp2 extra sessions
main.py with the BaseHandler and a MainHandler
import webapp2
from webapp2_extras import sessions
class BaseHandler(webapp2.RequestHandler): # taken from the webapp2 extrta session example
def dispatch(self): # override dispatch
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self) # dispatch the main handler
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
# Returns a session using the default cookie key.
return self.session_store.get_session()
class YourMainHandler(BaseHandler):
def get(self):
....
self.session['foo'] = 'bar'
def post(self):
foo = self.session.get('foo')
And if you have a seperate login.py :
.... other imports
import main
class Login(main.BaseHandler):
def get(self):
....
self.session['foo'] = 'bar'
def post(self):
foo = self.session.get('foo')
This may not be a direct answer to the question, but it is a solution I found using gaesessions instead of GAE's webapp2 session and I would like to share with everybody. Here we go:
Download gaesessions from https://github.com/dound/gae-sessions by clicking "Download ZIP" button. The downloaded file is "gae-sessions-master.zip".
Unzip the file (a directory "gae-sessions-master" will be created), and copy the directory "gaessions" to the root directory of your application (i.e., where "app.yaml" is)
Create a file called "appengine_config.py" in the root directory, with the following content (copied form https://github.com/dound/gae-sessions/tree/master/demo):
from gaesessions import SessionMiddleware
# Original comments deleted ...
# Create a random string for COOKIE_KDY and the string has to
# be permanent. "os.urandom(64)" function may be used but do
# not use it *dynamically*.
# For me, I just randomly generate a string of length 64
# and paste it here, such as the following:
COOKIE_KEY = 'ppb52adekdhD25dqpbKu39dDKsd.....'
def webapp_add_wsgi_middleware(app):
from google.appengine.ext.appstats import recording
app = SessionMiddleware(app, cookie_key=COOKIE_KEY)
app = recording.appstats_wsgi_middleware(app)
return app
Create a session when a user logs in (variable account is the user's account):
from gaesessions import get_current_session
session = get_current_session()
if session.is_active():
session.terminate()
# start a session for the user (old one was terminated)
session['account'] = account
Check if the user's session exists, if yes, return user's account:
from gaesessions import get_current_session
def checkSession():
session = get_current_session()
if session.is_active():
return session['account']
return False
Delete the session when the user logs out:
def logout():
session = get_current_session()
if session.is_active():
session.terminate()
Finally, you may create a cron job to clean expired sessions periodically:
cron.yaml:
- description: daily session cleanup
url: /clean_up_sessions
schedule: every day 3:00
timezone: ... (Your time zone)
Function:
from gaesessions import delete_expired_sessions
class clean_up_sessions(webapp2.RequestHandler):
def get(self):
while not delete_expired_sessions():
pass
Hope this helps.
In your RequestHandler override dispatch:
from webapp2_extras import sessions
def dispatch(self):
self.session_store = sessions.get_store(request=self.request)
try:
webapp2.RequestHandler.dispatch(self)
finally:
self.session_store.save_sessions(self.response)
and make a webapp2.cached_property called session:
#webapp2.cached_property
def session(self):
return self.session_store.get_session(backend="<whatever you want here>")
When you want to access session values, you do self.session[<key>]
When a user logs in, you can call either:
self.auth.get_user_by_password(auth_id, password, remember=True,
save_session=True)
which will take care of getting rid of the old session and creating the new one for you, or:
self.auth.set_session(self.auth.store.user_to_dict(self.user), remember=True)
As far as logging out, all you should need to call is:
self.auth.unset_session()