Showing posts with label Google App Engine. Show all posts
Showing posts with label Google App Engine. Show all posts

Friday, October 16, 2015

The hello world web app of OAuth 2.0 client for Google App Engine

The sample project is here.

However, the missing installation and setup instructions for development server are:
(1) download the above project sample and say put it in project folder called helloworld
(2) install google-api-python-client in the project folder helloworld
(2a) Create a file appengine_config.py in the project folder with the following contents
from google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.
vendor.add('lib')

(2b) Download google-api-python-client and related libraries into the lib sub-folder of the project folder
cd helloworld
mkdir lib
# if your Mac doesn't have pip do this -> sudo easy_install -U pip
pip install -t lib google-api-python-client

(3) Follow the instructions in here to setup OAuth 2.0 in the developer console for web app in Google App Engine Developer Console

(4) Make sure to enable Google+ API in the console or else you will get KeyError: 'id' when testing


(5) Fill in Authorised Javascript origins and Authorised redirect URIs in the developer console and click create or save


(6) copy the created Client ID and Client secret from the developer console and fill in the file client_secrets.json, like below


(7) Wait a few minutes and start the development server and test



Here is how to add other OAuth 2.0 apps such as Windows Live or facebook.
(1) Setup and revoke websites are :
# Google+ APIs
# Manage Application - https://console.developers.google.com
# Revoke Consent - https://www.google.com/accounts/b/0/IssuedAuthSubTokens
# OAuth 2.0 info https://developers.google.com/api-client-library/python/auth/web-app

# Windows Live API
# Manage Application - https://account.live.com/developers/applications
# Revoke Consent - https://account.live.com/consent/Manage
# OAuth 2.0 info https://msdn.microsoft.com/en-us/library/hh243647.aspx

# Facebook auth apis
# Manage Application - https://developers.facebook.com/apps/
# Revoke Consent Procedure
# Log on to Facebook.
# Click the drop-down arrow in the upper right, then select "Settings"
# Select "Apps" on the left sidebar.
# Scan the list and click the "x" on the right of any app you want to clear.

(2.1) The client_secrets_windows_live.json file is like this
{
  "web": {
    "client_id": "0000000012345678",
    "client_secret": "abcdefg1lHiJK5HCnlZb-aaaaaXX",
    "redirect_uris": ["http://localhost:8080/windows_live_callback"],
    "auth_uri": "https://login.live.com/oauth20_authorize.srf",
    "token_uri": "https://login.live.com/oauth20_token.srf"
  }
}


(2.2) The client_secrets_facebook.json files is like this
{
  "web": {
    "client_id": "123456789012345",
    "client_secret": "a1234567e123456bc4b123456ab6543g",
    "redirect_uris": ["http://localhost:8080/facebook_callback"],
    "auth_uri": "https://www.facebook.com/dialog/oauth",
    "token_uri": "https://graph.facebook.com/oauth/access_token"
  }
}


(3.1) The decorator_windows_live is like these
# Scopes are space-separated, e.g. 'wl.signin wl.basic'.
decorator_windows_live = appengine.oauth2decorator_from_clientsecrets( os.path.join(os.path.dirname(__file__), 'client_secrets_windows_live.json'), scope='wl.signin wl.basic', message=MISSING_CLIENT_SECRETS_MESSAGE)


(3.2) The decorator_facebook is like this
# Multiple Scopes should be comma-separated, e.g. 'user_about_me,email'.
decorator_facebook = appengine.oauth2decorator_from_clientsecrets( os.path.join(os.path.dirname(__file__), 'client_secrets_facebook.json'), scope='user_about_me,email', message=MISSING_CLIENT_SECRETS_MESSAGE)


Monday, October 12, 2015

The Hello World of Google Protocol RPC (javascript part)

The Hello World of Google Protocol RPC using python is here https://cloud.google.com/appengine/docs/python/tools/protorpc/#The_Hello_World_of_ProtoRPC

with an example on Testing the Service from the Command Line

Here I add the javascript part on how to test the RPC service in the browser using the google app engine
templates/index.html    Select all
<!DOCTYPE html> <html><head><title>post service demo</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script language="javascript" type="text/javascript"> function submitform() { $.ajax({ headers: { "Accept": "application/json", "Content-Type": "application/json" }, type: "POST", url : "/hello.hello", dataType : "json", data : JSON.stringify({"my_name": $("#my_name").val()}), error: function () { alert("loading Ajax failure"); }, onFailure: function () { alert("Ajax Failure"); }, statusCode: { 404: function() { alert("missing info"); } }, success: function (response) { alert("The server says: " + JSON.stringify(response)); } }) .done(function(data) { $("#result").text(data["hello"]); }); };</script></head> <body> <h1>Hello world!</h1><br> <p><form id="myform" method="post" action="/hello.hello"><input type="text" id="my_name" name="my_name" value="javacom"><input type="button" id="submit" value="submit" onclick="submitform();"></form></p> <p><div id="result"></div></p> </body> </html>


main.py    Select all
import os import jinja2 import webapp2 TEMPLATE_DIR = 'templates' JINJA_ENVIRONMENT = jinja2.Environment( loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), TEMPLATE_DIR)), extensions=['jinja2.ext.autoescape'], autoescape=True) class MainHandler(webapp2.RequestHandler): def get(self): template = JINJA_ENVIRONMENT.get_template('index.html') self.response.write(template.render()) app = webapp2.WSGIApplication([ ('/', MainHandler) ], debug=True)


app.yaml    Select all
application: helloworld version: 1 runtime: python27 api_version: 1 threadsafe: yes handlers: - url: /hello.* script: services.app - url: .* script: main.app libraries: - name: webapp2 version: "2.5.2" - name: jinja2 version: "2.6"



Saturday, June 29, 2013

Personal Migration Guide for Google App Engine from python 2.5 to 2.7

app.yaml    Select all
#change application name to new id that enable HRD #application: myapp application: myapp-hrd #change runtime #runtime: python runtime: python27 #add threadsafe threadsafe: true #change remote_api handlers: #- url: /remote_api # script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py # login: admin - url: /remoteapi.* script: google.appengine.ext.remote_api.handler.app login: admin #change url for app - url: .* script: myapp.app # script: myapp.py #add libraries libraries: - name: webapp2 version: "2.5.2" - name: jinja2 version: "2.6" #add services inbound_services: - warmup




myapp.py    Select all
#import webapp2 and jinja2 import webapp2 import jinja2 #import wsgiref.handlers #from google.appengine.ext import webapp #from google.appengine.ext.webapp import RequestHandler #from google.appengine.ext.webapp import template #from google.appengine.ext.webapp.util import run_wsgi_app #use ndb instead of db #from google.appengine.ext import db #class Greeting(db.Model): # author = db.UserProperty() # content = db.StringProperty(indexed=False) # role = db.StringProperty(required=True, choices=set(["executive", "manager", "helper"])) # date = db.DateTimeProperty(auto_now_add=True) from google.appengine.ext import ndb class Greeting(ndb.Model): """Models an individual Guestbook entry with author, content, and date.""" author = ndb.UserProperty() content = ndb.StringProperty(indexed=False) role = ndb.StringProperty(required=True, choices=set(["executive", "manager", "helper"])) date = ndb.DateTimeProperty(auto_now_add=True) #use TEMPLATE_DIR and JINJA_ENVIRONMENT TEMPLATE_DIR = 'templates' JINJA_ENVIRONMENT = jinja2.Environment( loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), TEMPLATE_DIR)), # loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), extensions=['jinja2.ext.autoescape']) #use jinja2 template # path = os.path.abspath(os.path.join(os.path.dirname(__file__), TEMPLATE_DIR, fileName)) # self.response.out.write(template.render(path, values)) template = JINJA_ENVIRONMENT.get_template(fileName) self.response.write(template.render(values)) #use webapp2 instead of webapp #def main(): #application = webapp.WSGIApplication( app = webapp2.WSGIApplication( [('/', MainHandler) # %3D does not work now # ,(r'/id%3D([A-Za-z0-9-.]*)', IDHandler) ,(r'/id=([A-Za-z0-9-.]*)', IDHandler) ], debug=True) # run_wsgi_app(application) #if __name__ == '__main__': # main()




Then, Duplicate Application Settings to a new application id say myapp-hrd

Finally, Migrate the app to the High Replication Datastore (HRD) in Google App Engine admin before uploading the python 2.7 code to the newly converted application id myapp-hrd

At the end of the migration process, the new HRD app (myapp-hrd) will be aliased to the old appid.




Sunday, June 20, 2010

How to download / upload data to Google App Engine for localhost

The appcfg.py --dump option is not working
with this error appcfg.py: error: no such option: --dump

Deprecated method (Code for Configuration) is used instead to upload_data / download_data to localhost app

Here is an example

(1) modify app.yaml and add this under handlers:
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin


You have to restart the app after modifying app.yaml

(2) create this file : album_load.py

# album_loader.py
import datetime
from google.appengine.ext import db
from google.appengine.tools import bulkloader

class Album(db.Model):
artist = db.StringProperty()
title = db.StringProperty()
publication_date = db.DateProperty()
length_in_minutes = db.IntegerProperty()

class AlbumLoader(bulkloader.Loader):
def __init__(self):
bulkloader.Loader.__init__(self, 'Album',
[('title', str),
('artist', str),
('publication_date',
lambda x: datetime.datetime.strptime(x, '%m/%d/%Y').date()),
('length_in_minutes', int),
])

loaders = [AlbumLoader]


(3) prepare an upload file : album.csv

title1,artist1,1/1/2000,12
title2,artist2,1/1/2001,22
title3,artist3,1/1/2002,32


(3) Launch your app in localhost and upload using this command

appcfg.py upload_data --config_file=album_loader.py --application=yourappid --kind=Album --url=http://localhost:8080/remote_api --filename=album.csv


(4) check the table data in your Google App SDK console

(5) to download data create this file : album_exporter.py

# album_exporter.py
import datetime
from google.appengine.ext import db
from google.appengine.tools import bulkloader

class Album(db.Model):
artist = db.StringProperty()
title = db.StringProperty()
publication_date = db.DateProperty()
length_in_minutes = db.IntegerProperty()

class AlbumExporter(bulkloader.Exporter):
def __init__(self):
bulkloader.Exporter.__init__(self, 'Album',
[('title', str, None),
('artist', str, None),
('publication_date', str, None),
('length_in_minutes', int, None),
])

exporters = [AlbumExporter]


(6) use this command to download data
appcfg.py download_data --config_file=album_exporter.py --application=yourappid --kind=Album --url=http://localhost:8080/remote_api --filename=albumout.csv
.
.
.