Disabling account deletion button for now, since deletion hits resource limits; switching to MD5 hash of Google user ID as sync user name; added logout URL to start page

This commit is contained in:
Leslie Michael Orchard 2010-07-05 17:05:44 -04:00
Родитель 58e9bcd8e0
Коммит 2bb1a2cefc
6 изменённых файлов: 49 добавлений и 32 удалений

Просмотреть файл

@ -5,7 +5,7 @@ import sys, os, os.path
base_dir = os.path.dirname( os.path.dirname(__file__) )
sys.path.extend([ os.path.join(base_dir, d) for d in ('lib', 'extlib') ])
import random, string, logging
import random, string, logging, hashlib
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util, template
@ -34,7 +34,8 @@ class StartHandler(webapp.RequestHandler):
return self.render_template('main/start.html', {
'user': user,
'profile': profile,
'sync_url': '%s/sync/' % self.request.application_url
'sync_url': '%s/sync/' % self.request.application_url,
'logout_url': users.create_logout_url(self.request.uri)
})
def post(self):
@ -49,8 +50,9 @@ class StartHandler(webapp.RequestHandler):
# Create a new profile, with auto-generated password
new_profile = Profile(
user = user,
user_id = user.user_id(),
user_name = user.nickname(),
user_name = hashlib.md5(user.user_id()).hexdigest(),
password = Profile.generate_password()
)
new_profile.put()

Просмотреть файл

@ -1,4 +1,8 @@
/**
* Main styles
*/
.sync_details { }
.sync_details tr { }
.sync_details tr th { width: 15ex; vertical-align: top; text-align: right; padding: 0.5em 0.25em 0.5em 0.25em; }
.sync_details tr td { padding: 0.5em 0.25em 0.5em 0.25em; }

Просмотреть файл

@ -43,4 +43,3 @@ indexes:
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.

Просмотреть файл

@ -14,8 +14,21 @@ from time import mktime
WBO_PAGE_SIZE = 25
def paginate(items, page_len):
"""Paginage a list of items into a list of page lists"""
total_len = len(items)
num_pages = total_len / page_len
(d, m) = divmod(total_len, page_len)
if m > 0:
num_pages += 1
return (
items[ (i * page_len):(i * page_len + page_len) ]
for i in xrange(num_pages)
)
class Profile(db.Model):
"""Sync profile associated with logged in account"""
user = db.UserProperty(auto_current_user_add=True)
user_name = db.StringProperty(required=True)
user_id = db.StringProperty(required=True)
password = db.StringProperty(required=True)
@ -46,28 +59,18 @@ class Profile(db.Model):
return ( profile and profile.password == password )
def delete(self):
w_keys = []
c_keys = []
cs = Collection.all().ancestor(self)
for c in cs:
c_keys.append(c.key())
w_keys.extend(WBO.all(keys_only=True).ancestor(c))
db.delete(w_keys)
while True:
# HACK: This smells like trouble - switch to Task Queue?
w_keys = WBO.all(keys_only=True).ancestor(c).fetch(500)
if not w_keys: break
db.delete(w_keys)
db.delete(c_keys)
db.Model.delete(self)
def paginate(items, page_len):
"""Paginage a list of items into a list of page lists"""
total_len = len(items)
num_pages = total_len / page_len
(d, m) = divmod(total_len, page_len)
if m > 0:
num_pages += 1
return (
items[ (i * page_len):(i * page_len + page_len) ]
for i in xrange(num_pages)
)
class Collection(db.Model):
profile = db.ReferenceProperty(Profile, required=True)
name = db.StringProperty(required=True)
@ -78,7 +81,11 @@ class Collection(db.Model):
)
def delete(self):
db.delete(WBO.all(keys_only=True).ancestor(self))
while True:
# HACK: This smells like trouble - switch to Task Queue?
w_keys = WBO.all(keys_only=True).ancestor(self).fetch(500)
if not w_keys: break
db.delete(w_keys)
db.Model.delete(self)
def retrieve(self,
@ -156,6 +163,8 @@ class Collection(db.Model):
keys = [db.Key(x) for x in key_set]
key_pages = paginate(keys, WBO_PAGE_SIZE)
# Use the key pages for a combo result here.
final_query = WBO.all().ancestor(self).filter('__key__ IN', keys)
# Determine which sort order to use.

Просмотреть файл

@ -3,9 +3,10 @@
{% block page_title %}Sync Start{% endblock %}
{% block content %}
<h1>Sync Start</h1>
<h1>Sync Profile</h1>
<p>You are logged in as: <code>{{ user.nickname }}</code></p>
<p>You are logged in as <code>{{ user.nickname }}</code>
(<a href="{{ logout_url }}">logout</a>).</p>
{% if not profile %}
@ -16,27 +17,29 @@
</form>
{% else %}
<p>A sync profile exists.</p>
<dl>
<dt>Server URL</dt><dd>{{sync_url}}</dd>
<dt>User Name</dt><dd>{{ profile.user_name }}</dd>
<dt>Password</dt>
<dd>
<p>Use these custom server details when setting up Firefox Sync:</p>
<table class="sync_details">
<tr><th>Server URL</th><td>{{sync_url}}</td></tr>
<tr><th>User Name</th><td>{{ profile.user_name }}</td></tr>
<tr><th>Password</th>
<td>
<span>{{ profile.password }}</span>
<form action="" method="post">
<input type="hidden" name="action" value="regenerate_password" />
<input type="submit" value="Re-generate password" /></p>
</form>
</dd>
</dl>
</td></tr>
</table>
{% comment %}
<!-- TODO: Enable this in the future -->
<p>Would you like to delete the sync profile for this login?
<form action="" method="post">
<input type="hidden" name="action" value="delete_profile" />
<input type="submit" value="Yes, delete all my data, please." /></p>
</form>
{% endcomment %}
{% endif %}

Просмотреть файл

@ -714,7 +714,7 @@ class SyncApiTests(unittest.TestCase):
def test_header_if_unmodified_since(self):
"""Ensure that X-If-Unmodified-Since header is honored in PUT / POST / DELETE"""
pass
self.fail("TODO")
def build_wbo_parents_and_predecessors(self):
(p, c, ah) = (self.profile, self.collection, self.auth_header)