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:
Родитель
58e9bcd8e0
Коммит
2bb1a2cefc
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче