witten
/
luminotes
Archived
1
0
Fork 0

Non-paying users can now invite people to their notebook, but only as viewers.

Paying users can invite them as viewers, collaborators, or owners.
This commit is contained in:
Dan Helfman 2007-12-11 02:58:31 +00:00
parent 5554b1df17
commit 52c111895a
6 changed files with 104 additions and 50 deletions

3
NEWS
View File

@ -1,4 +1,5 @@
1.0.4: December ??, 2007
1.1.0: December ??, 2007
* Ability to invite people to your notebook.
* When the web browser is resized, all notes are automatically resized as well.
* Fixed note focusing in Safari.
* Fixed note state detection (bold, italic, etc.) in Safari.

View File

@ -27,22 +27,22 @@ settings = {
{
"name": "free",
"storage_quota_bytes": 30 * MEGABYTE,
"notebook_sharing": False,
"notebook_collaboration": False,
},
{
"name": "basic",
"storage_quota_bytes": 250 * MEGABYTE,
"notebook_sharing": True,
"notebook_collaboration": True,
},
{
"name": "standard",
"storage_quota_bytes": 500 * MEGABYTE,
"notebook_sharing": True,
"notebook_collaboration": True,
},
{
"name": "premium",
"storage_quota_bytes": 1000 * MEGABYTE,
"notebook_sharing": True,
"notebook_collaboration": True,
},
],
},

View File

@ -668,7 +668,8 @@ class Users( object ):
@type email_addresses: unicode
@param email_addresses: a string containing whitespace- or comma-separated email addresses
@type access: unicode
@param access: type of access to grant, either "collaborator", "viewer", or "owner"
@param access: type of access to grant, either "collaborator", "viewer", or "owner". with
certain rate plans, only "viewer" is allowed
@type invite_button: unicode
@param invite_button: ignored
@type user_id: unicode
@ -677,13 +678,22 @@ class Users( object ):
@return: { 'message': message }
@raise Password_reset_error: an error occured when sending the password reset email
@raise Validation_error: one of the arguments is invalid
@raise Access_error: user_id doesn't have owner-level notebook access to send an invite
@raise Access_error: user_id doesn't have owner-level notebook access to send an invite or
doesn't have a rate plan supporting notebook collaboration
"""
if len( email_addresses ) < 5:
raise Invite_error( u"Please enter at least one valid email address." )
if len( email_addresses ) > 5000:
raise Invite_error( u"Please enter fewer email addresses." )
if not self.check_access( user_id, notebook_id, read_write = True, owner = True ):
raise Access_error()
# this feature requires a rate plan above basic
user = self.__database.load( User, user_id )
if user is None or ( user.rate_plan == 0 and access != u"viewer" ):
raise Access_error()
if access == u"collaborator":
read_write = True
owner = False
@ -696,14 +706,6 @@ class Users( object ):
else:
raise Access_error()
if not self.check_access( user_id, notebook_id, read_write = True, owner = True ):
raise Access_error()
# this feature requires a rate plan above basic
user = self.__database.load( User, user_id )
if user is None or user.rate_plan == 0:
raise Access_error()
notebook = self.__database.load( Notebook, notebook_id )
if notebook is None:
raise Access_error()

View File

@ -1180,7 +1180,7 @@ class Test_users( Test_controller ):
assert result[ u"error" ]
assert "access" in result[ u"error" ]
def test_send_invites_without_sufficient_rate_plan( self ):
def test_send_invites_viewer_with_lowest_rate_plan( self ):
Stub_smtp.reset()
smtplib.SMTP = Stub_smtp
self.login()
@ -1196,6 +1196,51 @@ class Test_users( Test_controller ):
), session_id = self.session_id )
session_id = result[ u"session_id" ]
assert u"An invitation has been sent." in result[ u"message" ]
assert smtplib.SMTP.connected == False
assert len( smtplib.SMTP.emails ) == 1
( from_address, to_addresses, message ) = smtplib.SMTP.emails[ 0 ]
assert self.email_address in from_address
assert to_addresses == email_addresses_list
assert self.notebooks[ 0 ].name in message
assert self.INVITE_LINK_PATTERN.search( message )
def test_send_invites_collaborator_with_lowest_rate_plan( self ):
Stub_smtp.reset()
smtplib.SMTP = Stub_smtp
self.login()
email_addresses_list = [ u"foo@example.com" ]
email_addresses = email_addresses_list[ 0 ]
result = self.http_post( "/users/send_invites", dict(
notebook_id = self.notebooks[ 0 ].object_id,
email_addresses = email_addresses,
access = u"collaborator",
invite_button = u"send invites",
), session_id = self.session_id )
session_id = result[ u"session_id" ]
assert result[ u"error" ]
assert "access" in result[ u"error" ]
def test_send_invites_owner_with_lowest_rate_plan( self ):
Stub_smtp.reset()
smtplib.SMTP = Stub_smtp
self.login()
email_addresses_list = [ u"foo@example.com" ]
email_addresses = email_addresses_list[ 0 ]
result = self.http_post( "/users/send_invites", dict(
notebook_id = self.notebooks[ 0 ].object_id,
email_addresses = email_addresses,
access = u"owner",
invite_button = u"send invites",
), session_id = self.session_id )
session_id = result[ u"session_id" ]
assert result[ u"error" ]
assert "access" in result[ u"error" ]

View File

@ -185,23 +185,25 @@ Editor.prototype.finish_init = function () {
var invite_button = getElement( "invite_button" );
if ( invite_button ) {
var collaborators_radio = getElement( "collaborators_radio" );
connect( "collaborators_link", "onclick", function ( event ) {
collaborators_radio.checked = true;
event.stop();
} );
if ( getElement( "access_choices" ) ) {
var collaborators_radio = getElement( "collaborators_radio" );
connect( "collaborators_link", "onclick", function ( event ) {
collaborators_radio.checked = true;
event.stop();
} );
var viewers_radio = getElement( "viewers_radio" );
connect( "viewers_link", "onclick", function ( event ) {
viewers_radio.checked = true;
event.stop();
} );
var viewers_radio = getElement( "viewers_radio" );
connect( "viewers_link", "onclick", function ( event ) {
viewers_radio.checked = true;
event.stop();
} );
var owners_radio = getElement( "owners_radio" );
connect( "owners_link", "onclick", function ( event ) {
owners_radio.checked = true;
event.stop();
} );
var owners_radio = getElement( "owners_radio" );
connect( "owners_link", "onclick", function ( event ) {
owners_radio.checked = true;
event.stop();
} );
}
var invite_form = getElement( "invite_form" );
connect( invite_button, "onclick", function ( event ) {

View File

@ -1250,15 +1250,6 @@ Wiki.prototype.share_notebook = function () {
return;
}
if ( !this.rate_plan.notebook_sharing ) {
this.display_message(
"If you'd like to share your notebook, please ",
[ createDOM( "a", { "href": "/upgrade", "target": "_new" }, "upgrade" ),
" your account first." ]
);
return;
}
var collaborators_link = createDOM( "a",
{ "href": "#", "id": "collaborators_link", "class": "radio_link", "title": "Collaborators may view and edit this notebook." },
"collaborators"
@ -1282,6 +1273,28 @@ Wiki.prototype.share_notebook = function () {
{ "type": "radio", "id": "owners_radio", "name": "access", "value": "owner" }
)
if ( this.rate_plan.notebook_collaboration ) {
var access_area = createDOM( "p", { "id": "access_choices" },
createDOM( "p", {}, "Invite these people as:" ),
createDOM( "table" , { "id": "access_table" },
createDOM( "tr", {},
createDOM( "td", {}, collaborators_radio, collaborators_link ),
createDOM( "td", {}, viewers_radio, viewers_link ),
createDOM( "td", {}, owners_radio, owners_link )
)
)
);
} else {
var access_area = createDOM( "p", {},
createDOM( "b", {}, "Note: " ),
"These people will only be able to view your notebook. If you'd like them to be able to edit ",
"your notebook as well, please ",
createDOM( "a", { "href": "/upgrade", "target": "_new" }, "upgrade" ),
" your account.",
createDOM( "input", { "type": "hidden", "name": "access", "value": "viewer" } )
);
}
var div = createDOM( "div", {},
createDOM( "form", { "id": "invite_form" },
createDOM( "input", { "type": "hidden", "name": "notebook_id", "value": this.notebook_id } ),
@ -1293,16 +1306,7 @@ Wiki.prototype.share_notebook = function () {
)
),
createDOM( "p", {}, "Please separate email addresses with commas, spaces, or the enter key." ),
createDOM( "p", {},
createDOM( "p", {}, "Invite these people as:" ),
createDOM( "table" , { "id": "access_table" },
createDOM( "tr", {},
createDOM( "td", {}, collaborators_radio, collaborators_link ),
createDOM( "td", {}, viewers_radio, viewers_link ),
createDOM( "td", {}, owners_radio, owners_link )
)
)
),
access_area,
createDOM( "p", {},
createDOM( "input",
{ "type": "submit", "name": "invite_button", "id": "invite_button", "class": "button", "value": "send invites" }