Implemented basic user account settings. Now you can change your email
address.
This commit is contained in:
parent
11263d65fa
commit
18982dc129
6
NEWS
6
NEWS
|
@ -1,3 +1,9 @@
|
|||
1.3.17: May 7, 2008
|
||||
* Implemented basic user account settings. Now you can change your email
|
||||
address.
|
||||
* Fixed a bug where if you load a particular note in its own window, and
|
||||
that note is a startup note, it shows up in the note tree twice.
|
||||
|
||||
1.3.16: May 6, 2008
|
||||
* Fixed a bug where an invite sent for a notebook with an accented unicode
|
||||
name would cause a UnicodeEncodeError upon sending the invite email. Now
|
||||
|
|
|
@ -1208,3 +1208,46 @@ class Users( object ):
|
|||
|
||||
def rate_plan( self, plan_index ):
|
||||
return self.__rate_plans[ plan_index ]
|
||||
|
||||
@expose( view = Json )
|
||||
@end_transaction
|
||||
@grab_user_id
|
||||
@validate(
|
||||
email_address = ( Valid_string( min = 0, max = 60 ) ),
|
||||
settings_button = unicode,
|
||||
user_id = Valid_id( none_okay = True ),
|
||||
)
|
||||
def update_settings( self, email_address, settings_button, user_id ):
|
||||
"""
|
||||
Update the settings for a particular user.
|
||||
|
||||
@type email_address: unicode
|
||||
@param email_address: new email address
|
||||
@type settings_button: unicode
|
||||
@param settings_button: ignored
|
||||
@type user_id: unicode
|
||||
@param user_id: id of current logged-in user (if any), determined by @grab_user_id
|
||||
@rtype: json dict
|
||||
@return: { "email_address": new_email_address }
|
||||
@raise Validation_error: one of the arguments is invalid
|
||||
@raise Access_error: the given user id is unknown
|
||||
"""
|
||||
if len( email_address ) > 0:
|
||||
try:
|
||||
email_address = valid_email_address( email_address )
|
||||
except ValueError:
|
||||
raise Validation_error( "email_address", email_address, valid_email_address )
|
||||
else:
|
||||
email_address = None
|
||||
|
||||
user = self.__database.load( User, user_id )
|
||||
if not user:
|
||||
raise Access_error()
|
||||
|
||||
if email_address != user.email_address:
|
||||
user.email_address = email_address
|
||||
self.__database.save( user )
|
||||
|
||||
return dict(
|
||||
email_address = email_address,
|
||||
)
|
||||
|
|
|
@ -3630,6 +3630,79 @@ class Test_users( Test_controller ):
|
|||
assert rate_plan
|
||||
assert rate_plan == self.settings[ u"global" ][ u"luminotes.rate_plans" ][ plan_index ]
|
||||
|
||||
def test_update_settings( self ):
|
||||
self.login()
|
||||
previous_revision = self.user.revision
|
||||
|
||||
result = self.http_post( "/users/update_settings", dict(
|
||||
email_address = self.new_email_address,
|
||||
settings_button = u"save settings",
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result[ u"email_address" ] == self.new_email_address
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.email_address == self.new_email_address
|
||||
assert user.revision > previous_revision
|
||||
|
||||
def test_update_settings_without_login( self ):
|
||||
original_revision = self.user.revision
|
||||
|
||||
result = self.http_post( "/users/update_settings", dict(
|
||||
email_address = self.new_email_address,
|
||||
settings_button = u"save settings",
|
||||
) )
|
||||
|
||||
assert u"access" in result[ u"error" ]
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.email_address == self.email_address
|
||||
assert user.revision == original_revision
|
||||
|
||||
def test_update_settings_with_same_email_address( self ):
|
||||
self.login()
|
||||
original_revision = self.user.revision
|
||||
|
||||
result = self.http_post( "/users/update_settings", dict(
|
||||
email_address = self.email_address,
|
||||
settings_button = u"save settings",
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result[ u"email_address" ] == self.email_address
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.email_address == self.email_address
|
||||
assert user.revision == original_revision
|
||||
|
||||
def test_update_settings_with_invalid_email_address( self ):
|
||||
original_revision = self.user.revision
|
||||
|
||||
result = self.http_post( "/users/update_settings", dict(
|
||||
email_address = u"foo@bar@com",
|
||||
settings_button = u"save settings",
|
||||
) )
|
||||
|
||||
assert u"invalid" in result[ u"error" ]
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.email_address == self.email_address
|
||||
assert user.revision == original_revision
|
||||
|
||||
def test_update_settings_with_blank_email_address( self ):
|
||||
self.login()
|
||||
previous_revision = self.user.revision
|
||||
|
||||
result = self.http_post( "/users/update_settings", dict(
|
||||
email_address = u"",
|
||||
settings_button = u"save settings",
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result[ u"email_address" ] == None
|
||||
|
||||
user = self.database.load( User, self.user.object_id )
|
||||
assert user.email_address == None
|
||||
assert user.revision > previous_revision
|
||||
|
||||
def login( self ):
|
||||
result = self.http_post( "/users/login", dict(
|
||||
username = self.username,
|
||||
|
|
|
@ -281,6 +281,10 @@ class User( Persistent ):
|
|||
|
||||
return d
|
||||
|
||||
def __set_email_address( self, email_address ):
|
||||
self.update_revision()
|
||||
self.__email_address = email_address
|
||||
|
||||
def __set_password( self, password ):
|
||||
self.update_revision()
|
||||
self.__salt = User.__create_salt()
|
||||
|
@ -295,7 +299,7 @@ class User( Persistent ):
|
|||
self.__rate_plan = rate_plan
|
||||
|
||||
username = property( lambda self: self.__username )
|
||||
email_address = property( lambda self: self.__email_address )
|
||||
email_address = property( lambda self: self.__email_address, __set_email_address )
|
||||
password = property( None, __set_password )
|
||||
storage_bytes = property( lambda self: self.__storage_bytes, __set_storage_bytes )
|
||||
rate_plan = property( lambda self: self.__rate_plan, __set_rate_plan )
|
||||
|
|
|
@ -27,6 +27,22 @@ class Test_user( object ):
|
|||
def test_check_incorrect_password( self ):
|
||||
assert self.user.check_password( u"wrong" ) == False
|
||||
|
||||
def test_set_email_address( self ):
|
||||
previous_revision = self.user.revision
|
||||
email_address = u"alice@example.com"
|
||||
self.user.email_address = email_address
|
||||
|
||||
assert self.user.email_address == email_address
|
||||
assert self.user.revision > previous_revision
|
||||
|
||||
def test_set_none_email_address( self ):
|
||||
previous_revision = self.user.revision
|
||||
email_address = None
|
||||
self.user.email_address = email_address
|
||||
|
||||
assert self.user.email_address == email_address
|
||||
assert self.user.revision > previous_revision
|
||||
|
||||
def test_set_password( self ):
|
||||
previous_revision = self.user.revision
|
||||
new_password = u"newpass"
|
||||
|
|
|
@ -213,6 +213,17 @@ Editor.prototype.finish_init = function () {
|
|||
connect_button( revoke_button, invite_id );
|
||||
}
|
||||
}
|
||||
|
||||
var settings_button = getElement( "settings_button" );
|
||||
if ( settings_button ) {
|
||||
var settings_form = getElement( "settings_form" );
|
||||
connect( settings_button, "onclick", function ( event ) {
|
||||
signal( self, "submit_form", "/users/update_settings", settings_form, function ( result ) {
|
||||
signal( self, "settings_updated", result );
|
||||
} );
|
||||
event.stop();
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
// browsers such as Firefox, but not Opera
|
||||
|
|
|
@ -17,6 +17,7 @@ function Wiki( invoker ) {
|
|||
this.invite_id = getElement( "invite_id" ).value;
|
||||
this.after_login = getElement( "after_login" ).value;
|
||||
this.signup_plan = getElement( "signup_plan" ).value;
|
||||
this.email_address = getElement( "email_address" ).value || "";
|
||||
this.font_size = null;
|
||||
|
||||
var total_notes_count_node = getElement( "total_notes_count" );
|
||||
|
@ -361,6 +362,14 @@ Wiki.prototype.populate = function ( startup_notes, current_notes, note_read_wri
|
|||
} );
|
||||
}
|
||||
|
||||
var settings_link = getElement( "settings_link" );
|
||||
if ( settings_link ) {
|
||||
connect( settings_link, "onclick", function ( event ) {
|
||||
self.load_editor( "account settings", "null", null, null, null, getElement( "notes_top" ) );
|
||||
event.stop();
|
||||
} );
|
||||
}
|
||||
|
||||
var declutter_link = getElement( "declutter_link" );
|
||||
if ( declutter_link ) {
|
||||
connect( declutter_link, "onclick", function ( event ) {
|
||||
|
@ -468,6 +477,16 @@ Wiki.prototype.load_editor = function ( note_title, note_id, revision, previous_
|
|||
this.share_notebook();
|
||||
return;
|
||||
}
|
||||
if ( note_title == "account settings" ) {
|
||||
var editor = this.open_editors[ note_title ];
|
||||
if ( editor ) {
|
||||
editor.highlight();
|
||||
return;
|
||||
}
|
||||
|
||||
this.display_settings();
|
||||
return;
|
||||
}
|
||||
|
||||
// but if the note corresponding to the link's title is already open, highlight it and bail
|
||||
if ( !revision ) {
|
||||
|
@ -512,7 +531,7 @@ Wiki.prototype.resolve_link = function ( note_title, link, callback ) {
|
|||
if ( link && link.target )
|
||||
link.removeAttribute( "target" );
|
||||
|
||||
if ( note_title == "search results" || note_title == "share this notebook" ) {
|
||||
if ( note_title == "search results" || note_title == "share this notebook" || note_title == "account settings" ) {
|
||||
link.href = "/notebooks/" + this.notebook_id + "?" + queryString(
|
||||
[ "title", "note_id" ],
|
||||
[ note_title, "null" ]
|
||||
|
@ -520,8 +539,10 @@ Wiki.prototype.resolve_link = function ( note_title, link, callback ) {
|
|||
if ( callback ) {
|
||||
if ( note_title == "search results" )
|
||||
callback( "current search results" );
|
||||
else
|
||||
else if ( note_title == "share this notebook" )
|
||||
callback( "share this notebook with others" );
|
||||
else
|
||||
callback( "account settings" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -694,6 +715,11 @@ Wiki.prototype.create_editor = function ( id, note_text, deleted_from_id, revisi
|
|||
connect( editor, "load_editor", this, "load_editor" );
|
||||
connect( editor, "hide_clicked", function ( event ) { self.hide_editor( event, editor ) } );
|
||||
connect( editor, "invites_updated", function ( invites ) { self.invites = invites; self.share_notebook(); } );
|
||||
connect( editor, "settings_updated", function ( result ) {
|
||||
self.email_address = result.email_address || "";
|
||||
self.display_message( "Your account settings have been updated." );
|
||||
} );
|
||||
|
||||
connect( editor, "submit_form", function ( url, form, callback ) {
|
||||
var args = {}
|
||||
if ( url == "/users/signup" ) {
|
||||
|
@ -1556,6 +1582,41 @@ Wiki.prototype.display_invites = function ( invite_area ) {
|
|||
replaceChildNodes( invite_area, div );
|
||||
}
|
||||
|
||||
Wiki.prototype.display_settings = function () {
|
||||
this.clear_pulldowns();
|
||||
|
||||
var settings_frame = getElement( "note_settings" );
|
||||
if ( settings_frame ) {
|
||||
settings_frame.editor.highlight();
|
||||
return;
|
||||
}
|
||||
|
||||
var div = createDOM( "div", {},
|
||||
createDOM( "form", { "id": "settings_form" },
|
||||
createDOM( "p", {},
|
||||
createDOM( "b", {}, "email address" ),
|
||||
createDOM( "br", {} ),
|
||||
createDOM( "input",
|
||||
{ "type": "text", "name": "email_address", "id": "email_address", "class": "text_field",
|
||||
"size": "30", "maxlength": "60", "value": this.email_address || "" }
|
||||
)
|
||||
),
|
||||
createDOM( "p", {},
|
||||
createDOM( "input",
|
||||
{ "type": "submit", "name": "settings_button", "id": "settings_button", "class": "button", "value": "save settings" }
|
||||
)
|
||||
),
|
||||
createDOM( "p", {},
|
||||
"Your email address will ",
|
||||
createDOM( "a", { "href": "/privacy", "target": "_new" }, "never be shared" ),
|
||||
". It will only be used for password resets, contacting you about account problems, and the from address in any invite emails you send."
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
this.create_editor( "settings", "<h3>account settings</h3>" + div.innerHTML, undefined, undefined, undefined, false, true, true, getElement( "notes_top" ) );
|
||||
}
|
||||
|
||||
Wiki.prototype.declutter_clicked = function () {
|
||||
var header = getElement( "header" );
|
||||
if ( header )
|
||||
|
@ -2269,6 +2330,12 @@ function Link_pulldown( wiki, notebook_id, invoker, editor, link ) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( title == "account settings" ) {
|
||||
this.title_field.value = title;
|
||||
this.display_summary( title, "account settings" );
|
||||
return;
|
||||
}
|
||||
|
||||
this.invoker.invoke(
|
||||
"/notebooks/load_note_by_title", "GET", {
|
||||
"notebook_id": this.notebook_id,
|
||||
|
|
|
@ -32,6 +32,15 @@ class Header( Div ):
|
|||
),
|
||||
u" | ",
|
||||
) or None,
|
||||
user.username and Span(
|
||||
A(
|
||||
u"settings",
|
||||
href = u"#",
|
||||
title = u"Update your account settings.",
|
||||
id = u"settings_link",
|
||||
),
|
||||
" | ",
|
||||
) or None,
|
||||
user.username and Span(
|
||||
A(
|
||||
u"upgrade",
|
||||
|
|
|
@ -141,6 +141,7 @@ class Main_page( Page ):
|
|||
Input( type = u"hidden", name = u"invite_id", id = u"invite_id", value = invite_id ),
|
||||
Input( type = u"hidden", name = u"after_login", id = u"after_login", value = after_login ),
|
||||
Input( type = u"hidden", name = u"signup_plan", id = u"signup_plan", value = signup_plan ),
|
||||
Input( type = u"hidden", name = u"email_address", id = u"email_address", value = user.email_address ),
|
||||
Div(
|
||||
id = u"status_area",
|
||||
),
|
||||
|
|
Reference in New Issue