Lots of work on user storage quotas:
* Each model.User now has a current storage bytes and a rate plan. * model.User.to_dict() updated accordingly. * Minor Scheduler.add() change to bail of the given thread is None. * controller.Users.current() returns current user's rate plan details. * controller.Users.update_storage() now takes an optional callback. * Various methods in controller.Notebooks responsible for calling controller.Users.update_storage(). * Added rate plan details to config/Common.py. * Added quota utilization colors to style.css. * Implemented quota utilization calculation and display in Wiki.js. Still to-do: Return updated storage bytes where appropriate in controller.Notebook and update the client accordingly.
This commit is contained in:
parent
ebf1538313
commit
4d736d4821
|
@ -1,6 +1,9 @@
|
||||||
import cherrypy
|
import cherrypy
|
||||||
|
|
||||||
|
|
||||||
|
MEGABYTE = 1024 * 1024
|
||||||
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
"global": {
|
"global": {
|
||||||
"server.socket_port": 8081,
|
"server.socket_port": 8081,
|
||||||
|
@ -20,5 +23,19 @@ settings = {
|
||||||
"luminotes.http_proxy_ip": "127.0.0.1",
|
"luminotes.http_proxy_ip": "127.0.0.1",
|
||||||
"luminotes.https_proxy_ip": "127.0.0.2",
|
"luminotes.https_proxy_ip": "127.0.0.2",
|
||||||
"luminotes.support_email": "support@luminotes.com",
|
"luminotes.support_email": "support@luminotes.com",
|
||||||
|
"luminotes.rate_plans": [
|
||||||
|
{
|
||||||
|
"name": "basic",
|
||||||
|
"storage_quota_bytes": 30 * MEGABYTE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "standard",
|
||||||
|
"storage_quota_bytes": 100 * MEGABYTE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "professional",
|
||||||
|
"storage_quota_bytes": 300 * MEGABYTE,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Notebooks( object ):
|
||||||
"""
|
"""
|
||||||
Controller for dealing with notebooks and their notes, corresponding to the "/notebooks" URL.
|
Controller for dealing with notebooks and their notes, corresponding to the "/notebooks" URL.
|
||||||
"""
|
"""
|
||||||
def __init__( self, scheduler, database ):
|
def __init__( self, scheduler, database, users ):
|
||||||
"""
|
"""
|
||||||
Create a new Notebooks object.
|
Create a new Notebooks object.
|
||||||
|
|
||||||
|
@ -41,11 +41,14 @@ class Notebooks( object ):
|
||||||
@param scheduler: scheduler to use for asynchronous calls
|
@param scheduler: scheduler to use for asynchronous calls
|
||||||
@type database: controller.Database
|
@type database: controller.Database
|
||||||
@param database: database that notebooks are stored in
|
@param database: database that notebooks are stored in
|
||||||
|
@type users: controller.Users
|
||||||
|
@param users: controller for all users, used here for updating storage utilization
|
||||||
@rtype: Notebooks
|
@rtype: Notebooks
|
||||||
@return: newly constructed Notebooks
|
@return: newly constructed Notebooks
|
||||||
"""
|
"""
|
||||||
self.__scheduler = scheduler
|
self.__scheduler = scheduler
|
||||||
self.__database = database
|
self.__database = database
|
||||||
|
self.__users = users
|
||||||
|
|
||||||
@expose( view = Main_page )
|
@expose( view = Main_page )
|
||||||
@validate(
|
@validate(
|
||||||
|
@ -363,7 +366,11 @@ class Notebooks( object ):
|
||||||
startup_changed = notebook.remove_startup_note( note )
|
startup_changed = notebook.remove_startup_note( note )
|
||||||
|
|
||||||
if new_revision or startup_changed:
|
if new_revision or startup_changed:
|
||||||
self.__database.save( notebook )
|
self.__database.save( notebook, self.__scheduler.thread )
|
||||||
|
yield Scheduler.SLEEP
|
||||||
|
self.__users.update_storage( user_id, self.__scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
self.__database.save( user )
|
||||||
|
|
||||||
yield dict(
|
yield dict(
|
||||||
new_revision = new_revision,
|
new_revision = new_revision,
|
||||||
|
@ -411,7 +418,11 @@ class Notebooks( object ):
|
||||||
|
|
||||||
if note:
|
if note:
|
||||||
notebook.add_startup_note( note )
|
notebook.add_startup_note( note )
|
||||||
self.__database.save( notebook )
|
self.__database.save( notebook, self.__scheduler.thread )
|
||||||
|
yield Scheduler.SLEEP
|
||||||
|
self.__users.update_storage( user_id, self.__scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
self.__database.save( user )
|
||||||
|
|
||||||
yield dict()
|
yield dict()
|
||||||
|
|
||||||
|
@ -456,7 +467,11 @@ class Notebooks( object ):
|
||||||
|
|
||||||
if note:
|
if note:
|
||||||
notebook.remove_startup_note( note )
|
notebook.remove_startup_note( note )
|
||||||
self.__database.save( notebook )
|
self.__database.save( notebook, self.__scheduler.thread )
|
||||||
|
yield Scheduler.SLEEP
|
||||||
|
self.__users.update_storage( user_id, self.__scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
self.__database.save( user )
|
||||||
|
|
||||||
yield dict()
|
yield dict()
|
||||||
|
|
||||||
|
@ -508,7 +523,11 @@ class Notebooks( object ):
|
||||||
notebook.trash.add_note( note )
|
notebook.trash.add_note( note )
|
||||||
notebook.trash.add_startup_note( note )
|
notebook.trash.add_startup_note( note )
|
||||||
|
|
||||||
self.__database.save( notebook )
|
self.__database.save( notebook, self.__scheduler.thread )
|
||||||
|
yield Scheduler.SLEEP
|
||||||
|
self.__users.update_storage( user_id, self.__scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
self.__database.save( user )
|
||||||
|
|
||||||
yield dict()
|
yield dict()
|
||||||
|
|
||||||
|
@ -567,7 +586,11 @@ class Notebooks( object ):
|
||||||
notebook.add_note( note )
|
notebook.add_note( note )
|
||||||
notebook.add_startup_note( note )
|
notebook.add_startup_note( note )
|
||||||
|
|
||||||
self.__database.save( notebook )
|
self.__database.save( notebook, self.__scheduler.thread )
|
||||||
|
yield Scheduler.SLEEP
|
||||||
|
self.__users.update_storage( user_id, self.__scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
self.__database.save( user )
|
||||||
|
|
||||||
yield dict()
|
yield dict()
|
||||||
|
|
||||||
|
@ -613,7 +636,11 @@ class Notebooks( object ):
|
||||||
notebook.trash.add_note( note )
|
notebook.trash.add_note( note )
|
||||||
notebook.trash.add_startup_note( note )
|
notebook.trash.add_startup_note( note )
|
||||||
|
|
||||||
self.__database.save( notebook )
|
self.__database.save( notebook, self.__scheduler.thread )
|
||||||
|
yield Scheduler.SLEEP
|
||||||
|
self.__users.update_storage( user_id, self.__scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
self.__database.save( user )
|
||||||
|
|
||||||
yield dict()
|
yield dict()
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,14 @@ class Root( object ):
|
||||||
self.__scheduler = scheduler
|
self.__scheduler = scheduler
|
||||||
self.__database = database
|
self.__database = database
|
||||||
self.__settings = settings
|
self.__settings = settings
|
||||||
self.__notebooks = Notebooks( scheduler, database )
|
|
||||||
self.__users = Users(
|
self.__users = Users(
|
||||||
scheduler,
|
scheduler,
|
||||||
database,
|
database,
|
||||||
settings[ u"global" ].get( u"luminotes.http_url", u"" ),
|
settings[ u"global" ].get( u"luminotes.http_url", u"" ),
|
||||||
settings[ u"global" ].get( u"luminotes.https_url", u"" ),
|
settings[ u"global" ].get( u"luminotes.https_url", u"" ),
|
||||||
|
settings[ u"global" ].get( u"luminotes.rate_plans", [] ),
|
||||||
)
|
)
|
||||||
|
self.__notebooks = Notebooks( scheduler, database, self.__users )
|
||||||
|
|
||||||
@expose( view = Main_page )
|
@expose( view = Main_page )
|
||||||
def index( self ):
|
def index( self ):
|
||||||
|
|
|
@ -125,6 +125,9 @@ class Scheduler( object ):
|
||||||
@type args: tuple
|
@type args: tuple
|
||||||
@param args: arguments to send() to the given thread when it is executed
|
@param args: arguments to send() to the given thread when it is executed
|
||||||
"""
|
"""
|
||||||
|
if thread is None:
|
||||||
|
return
|
||||||
|
|
||||||
self.__idle.release()
|
self.__idle.release()
|
||||||
|
|
||||||
if thread in self.__sleeping:
|
if thread in self.__sleeping:
|
||||||
|
|
|
@ -106,7 +106,7 @@ class Users( object ):
|
||||||
"""
|
"""
|
||||||
Controller for dealing with users, corresponding to the "/users" URL.
|
Controller for dealing with users, corresponding to the "/users" URL.
|
||||||
"""
|
"""
|
||||||
def __init__( self, scheduler, database, http_url, https_url ):
|
def __init__( self, scheduler, database, http_url, https_url, rate_plans ):
|
||||||
"""
|
"""
|
||||||
Create a new Users object.
|
Create a new Users object.
|
||||||
|
|
||||||
|
@ -118,6 +118,8 @@ class Users( object ):
|
||||||
@param http_url: base URL to use for non-SSL http requests, or an empty string
|
@param http_url: base URL to use for non-SSL http requests, or an empty string
|
||||||
@type https_url: unicode
|
@type https_url: unicode
|
||||||
@param https_url: base URL to use for SSL http requests, or an empty string
|
@param https_url: base URL to use for SSL http requests, or an empty string
|
||||||
|
@type rate_plans: [ { "name": unicode, "storage_quota_bytes": int } ]
|
||||||
|
@param rate_plans: list of configured rate plans
|
||||||
@rtype: Users
|
@rtype: Users
|
||||||
@return: newly constructed Users
|
@return: newly constructed Users
|
||||||
"""
|
"""
|
||||||
|
@ -125,6 +127,7 @@ class Users( object ):
|
||||||
self.__database = database
|
self.__database = database
|
||||||
self.__http_url = http_url
|
self.__http_url = http_url
|
||||||
self.__https_url = https_url
|
self.__https_url = https_url
|
||||||
|
self.__rate_plans = rate_plans
|
||||||
|
|
||||||
@expose( view = Json )
|
@expose( view = Json )
|
||||||
@update_auth
|
@update_auth
|
||||||
|
@ -275,7 +278,14 @@ class Users( object ):
|
||||||
@type user_id: unicode
|
@type user_id: unicode
|
||||||
@param user_id: id of current logged-in user (if any), determined by @grab_user_id
|
@param user_id: id of current logged-in user (if any), determined by @grab_user_id
|
||||||
@rtype: json dict
|
@rtype: json dict
|
||||||
@return: { 'user': userdict or None, 'notebooks': notebooksdict, 'http_url': url }
|
@return: {
|
||||||
|
'user': userdict or None,
|
||||||
|
'notebooks': notebooksdict,
|
||||||
|
'startup_notes': noteslist,
|
||||||
|
'http_url': url,
|
||||||
|
'login_url': url,
|
||||||
|
'rate_plan': rateplandict,
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
# if there's no logged-in user, default to the anonymous user
|
# if there's no logged-in user, default to the anonymous user
|
||||||
self.__database.load( user_id or u"User anonymous", self.__scheduler.thread )
|
self.__database.load( user_id or u"User anonymous", self.__scheduler.thread )
|
||||||
|
@ -312,6 +322,7 @@ class Users( object ):
|
||||||
startup_notes = include_startup_notes and len( notebooks ) > 0 and notebooks[ 0 ].startup_notes or [],
|
startup_notes = include_startup_notes and len( notebooks ) > 0 and notebooks[ 0 ].startup_notes or [],
|
||||||
http_url = self.__http_url,
|
http_url = self.__http_url,
|
||||||
login_url = login_url,
|
login_url = login_url,
|
||||||
|
rate_plan = ( user.rate_plan < len( self.__rate_plans ) ) and self.__rate_plans[ user.rate_plan ] or {},
|
||||||
)
|
)
|
||||||
|
|
||||||
def calculate_storage( self, user ):
|
def calculate_storage( self, user ):
|
||||||
|
@ -344,13 +355,20 @@ class Users( object ):
|
||||||
return total_bytes
|
return total_bytes
|
||||||
|
|
||||||
@async
|
@async
|
||||||
def update_storage( self, user ):
|
def update_storage( self, user_id, callback = None ):
|
||||||
"""
|
"""
|
||||||
Calculate and record total storage utilization for the given user.
|
Calculate and record total storage utilization for the given user.
|
||||||
@type user: User
|
@type user_id: unicode or NoneType
|
||||||
@param user: user for which to calculate storage utilization
|
@param user_id: id of user for which to calculate storage utilization
|
||||||
|
@type callback: generator or NoneType
|
||||||
|
@param callback: generator to wakeup when the update is complete (optional)
|
||||||
"""
|
"""
|
||||||
user.storage_bytes = self.calculate_storage( user )
|
self.__database.load( user_id, self.__scheduler.thread )
|
||||||
yield None
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
|
||||||
|
if user:
|
||||||
|
user.storage_bytes = self.calculate_storage( user )
|
||||||
|
|
||||||
|
yield callback, user
|
||||||
|
|
||||||
scheduler = property( lambda self: self.__scheduler )
|
scheduler = property( lambda self: self.__scheduler )
|
||||||
|
|
|
@ -19,6 +19,16 @@ class Test_controller( object ):
|
||||||
u"luminotes.https_url" : u"https://luminotes.com",
|
u"luminotes.https_url" : u"https://luminotes.com",
|
||||||
u"luminotes.http_proxy_ip" : u"127.0.0.1",
|
u"luminotes.http_proxy_ip" : u"127.0.0.1",
|
||||||
u"luminotes.https_proxy_ip" : u"127.0.0.2",
|
u"luminotes.https_proxy_ip" : u"127.0.0.2",
|
||||||
|
"luminotes.rate_plans": [
|
||||||
|
{
|
||||||
|
"name": "super",
|
||||||
|
"storage_quota_bytes": 1337,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "extra super",
|
||||||
|
"storage_quota_bytes": 31337,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,12 +66,14 @@ class Test_notebooks( Test_controller ):
|
||||||
result = self.http_get( "/notebooks/%s" % self.notebook.object_id )
|
result = self.http_get( "/notebooks/%s" % self.notebook.object_id )
|
||||||
|
|
||||||
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_default_with_note( self ):
|
def test_default_with_note( self ):
|
||||||
result = self.http_get( "/notebooks/%s?note_id=%s" % ( self.notebook.object_id, self.note.object_id ) )
|
result = self.http_get( "/notebooks/%s?note_id=%s" % ( self.notebook.object_id, self.note.object_id ) )
|
||||||
|
|
||||||
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
||||||
assert result.get( u"note_id" ) == self.note.object_id
|
assert result.get( u"note_id" ) == self.note.object_id
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_default_with_note_and_revision( self ):
|
def test_default_with_note_and_revision( self ):
|
||||||
result = self.http_get( "/notebooks/%s?note_id=%s&revision=%s" % (
|
result = self.http_get( "/notebooks/%s?note_id=%s&revision=%s" % (
|
||||||
|
@ -83,6 +85,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
||||||
assert result.get( u"note_id" ) == self.note.object_id
|
assert result.get( u"note_id" ) == self.note.object_id
|
||||||
assert result.get( u"revision" ) == unicode( self.note.revision )
|
assert result.get( u"revision" ) == unicode( self.note.revision )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_default_with_parent( self ):
|
def test_default_with_parent( self ):
|
||||||
parent_id = "foo"
|
parent_id = "foo"
|
||||||
|
@ -90,6 +93,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
assert result.get( u"notebook_id" ) == self.notebook.object_id
|
||||||
assert result.get( u"parent_id" ) == parent_id
|
assert result.get( u"parent_id" ) == parent_id
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_contents( self ):
|
def test_contents( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -105,6 +109,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert notebook.object_id == self.notebook.object_id
|
assert notebook.object_id == self.notebook.object_id
|
||||||
assert len( startup_notes ) == 1
|
assert len( startup_notes ) == 1
|
||||||
assert startup_notes[ 0 ] == self.note
|
assert startup_notes[ 0 ] == self.note
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_contents_with_note( self ):
|
def test_contents_with_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -124,6 +129,7 @@ class Test_notebooks( Test_controller ):
|
||||||
note = result[ "note" ]
|
note = result[ "note" ]
|
||||||
|
|
||||||
assert note.object_id == self.note.object_id
|
assert note.object_id == self.note.object_id
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_contents_with_note_and_revision( self ):
|
def test_contents_with_note_and_revision( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -147,6 +153,7 @@ class Test_notebooks( Test_controller ):
|
||||||
note = result[ "note" ]
|
note = result[ "note" ]
|
||||||
|
|
||||||
assert note.object_id == self.note.object_id
|
assert note.object_id == self.note.object_id
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_contents_without_login( self ):
|
def test_contents_without_login( self ):
|
||||||
result = self.http_get(
|
result = self.http_get(
|
||||||
|
@ -155,6 +162,7 @@ class Test_notebooks( Test_controller ):
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_note( self ):
|
def test_load_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -169,6 +177,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert note.object_id == self.note.object_id
|
assert note.object_id == self.note.object_id
|
||||||
assert note.title == self.note.title
|
assert note.title == self.note.title
|
||||||
assert note.contents == self.note.contents
|
assert note.contents == self.note.contents
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_note_with_revision( self ):
|
def test_load_note_with_revision( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -198,6 +207,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert note.revision == previous_revision
|
assert note.revision == previous_revision
|
||||||
assert note.title == previous_title
|
assert note.title == previous_title
|
||||||
assert note.contents == previous_contents
|
assert note.contents == previous_contents
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_note_without_login( self ):
|
def test_load_note_without_login( self ):
|
||||||
result = self.http_post( "/notebooks/load_note/", dict(
|
result = self.http_post( "/notebooks/load_note/", dict(
|
||||||
|
@ -216,6 +226,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_unknown_note( self ):
|
def test_load_unknown_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -227,6 +238,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
note = result[ "note" ]
|
note = result[ "note" ]
|
||||||
assert note == None
|
assert note == None
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_note_by_title( self ):
|
def test_load_note_by_title( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -241,6 +253,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert note.object_id == self.note.object_id
|
assert note.object_id == self.note.object_id
|
||||||
assert note.title == self.note.title
|
assert note.title == self.note.title
|
||||||
assert note.contents == self.note.contents
|
assert note.contents == self.note.contents
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_note_by_title_without_login( self ):
|
def test_load_note_by_title_without_login( self ):
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -249,6 +262,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_note_by_title_with_unknown_notebook( self ):
|
def test_load_note_by_title_with_unknown_notebook( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -259,6 +273,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_load_unknown_note_by_title( self ):
|
def test_load_unknown_note_by_title( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -270,6 +285,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
note = result[ "note" ]
|
note = result[ "note" ]
|
||||||
assert note == None
|
assert note == None
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_lookup_note_id( self ):
|
def test_lookup_note_id( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -280,6 +296,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "note_id" ) == self.note.object_id
|
assert result.get( "note_id" ) == self.note.object_id
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_lookup_note_id_without_login( self ):
|
def test_lookup_note_id_without_login( self ):
|
||||||
result = self.http_post( "/notebooks/lookup_note_id/", dict(
|
result = self.http_post( "/notebooks/lookup_note_id/", dict(
|
||||||
|
@ -288,6 +305,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_lookup_note_id_with_unknown_notebook( self ):
|
def test_lookup_note_id_with_unknown_notebook( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -298,6 +316,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_lookup_unknown_note_id( self ):
|
def test_lookup_unknown_note_id( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -308,6 +327,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "note_id" ) == None
|
assert result.get( "note_id" ) == None
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_save_note( self, startup = False ):
|
def test_save_note( self, startup = False ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -325,6 +345,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
||||||
assert result[ "previous_revision" ] == previous_revision
|
assert result[ "previous_revision" ] == previous_revision
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
# make sure the old title can no longer be loaded
|
# make sure the old title can no longer be loaded
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -367,6 +388,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_save_startup_note_without_login( self ):
|
def test_save_startup_note_without_login( self ):
|
||||||
self.test_save_note_without_login( startup = True )
|
self.test_save_note_without_login( startup = True )
|
||||||
|
@ -393,6 +415,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
||||||
assert result[ "previous_revision" ] == previous_revision
|
assert result[ "previous_revision" ] == previous_revision
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
# make sure the old title can no longer be loaded
|
# make sure the old title can no longer be loaded
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -446,6 +469,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
# now attempt to save over that note again without changing the contents
|
# now attempt to save over that note again without changing the contents
|
||||||
|
previous_storage_bytes = self.user.storage_bytes
|
||||||
previous_revision = self.note.revision
|
previous_revision = self.note.revision
|
||||||
result = self.http_post( "/notebooks/save_note/", dict(
|
result = self.http_post( "/notebooks/save_note/", dict(
|
||||||
notebook_id = self.notebook.object_id,
|
notebook_id = self.notebook.object_id,
|
||||||
|
@ -458,6 +482,7 @@ class Test_notebooks( Test_controller ):
|
||||||
# assert that the note wasn't actually updated the second time
|
# assert that the note wasn't actually updated the second time
|
||||||
assert result[ "new_revision" ] == None
|
assert result[ "new_revision" ] == None
|
||||||
assert result[ "previous_revision" ] == previous_revision
|
assert result[ "previous_revision" ] == previous_revision
|
||||||
|
assert self.user.storage_bytes == previous_storage_bytes
|
||||||
|
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
notebook_id = self.notebook.object_id,
|
notebook_id = self.notebook.object_id,
|
||||||
|
@ -491,6 +516,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
# now attempt to save over that note again without changing the contents
|
# now attempt to save over that note again without changing the contents
|
||||||
|
previous_storage_bytes = self.user.storage_bytes
|
||||||
previous_revision = self.note.revision
|
previous_revision = self.note.revision
|
||||||
result = self.http_post( "/notebooks/save_note/", dict(
|
result = self.http_post( "/notebooks/save_note/", dict(
|
||||||
notebook_id = self.notebook.object_id,
|
notebook_id = self.notebook.object_id,
|
||||||
|
@ -503,6 +529,7 @@ class Test_notebooks( Test_controller ):
|
||||||
# assert that the note wasn't actually updated the second time
|
# assert that the note wasn't actually updated the second time
|
||||||
assert result[ "new_revision" ] == None
|
assert result[ "new_revision" ] == None
|
||||||
assert result[ "previous_revision" ] == previous_revision
|
assert result[ "previous_revision" ] == previous_revision
|
||||||
|
assert self.user.storage_bytes == previous_storage_bytes
|
||||||
|
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
notebook_id = self.notebook.object_id,
|
notebook_id = self.notebook.object_id,
|
||||||
|
@ -553,6 +580,7 @@ class Test_notebooks( Test_controller ):
|
||||||
# assert that the note wasn't actually updated the second time
|
# assert that the note wasn't actually updated the second time
|
||||||
assert result[ "new_revision" ] == None
|
assert result[ "new_revision" ] == None
|
||||||
assert result[ "previous_revision" ] == previous_revision
|
assert result[ "previous_revision" ] == previous_revision
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
notebook_id = self.notebook.object_id,
|
notebook_id = self.notebook.object_id,
|
||||||
|
@ -602,6 +630,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert result[ "new_revision" ]
|
assert result[ "new_revision" ]
|
||||||
assert result[ "new_revision" ] not in ( first_revision, second_revision )
|
assert result[ "new_revision" ] not in ( first_revision, second_revision )
|
||||||
assert result[ "previous_revision" ] == second_revision
|
assert result[ "previous_revision" ] == second_revision
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
# make sure the first title can no longer be loaded
|
# make sure the first title can no longer be loaded
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -646,6 +675,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_save_new_note( self, startup = False ):
|
def test_save_new_note( self, startup = False ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -663,6 +693,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
||||||
assert result[ "previous_revision" ] == None
|
assert result[ "previous_revision" ] == None
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
# make sure the new title is now loadable
|
# make sure the new title is now loadable
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -705,6 +736,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
||||||
assert result[ "previous_revision" ] == None
|
assert result[ "previous_revision" ] == None
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
# make sure the new title is now loadable
|
# make sure the new title is now loadable
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -738,6 +770,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
assert result[ "new_revision" ] and result[ "new_revision" ] != previous_revision
|
||||||
assert result[ "previous_revision" ] == None
|
assert result[ "previous_revision" ] == None
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
# make sure the new title is now loadable
|
# make sure the new title is now loadable
|
||||||
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
result = self.http_post( "/notebooks/load_note_by_title/", dict(
|
||||||
|
@ -770,6 +803,7 @@ class Test_notebooks( Test_controller ):
|
||||||
assert len( notebook.startup_notes ) == 2
|
assert len( notebook.startup_notes ) == 2
|
||||||
assert notebook.startup_notes[ 0 ] == self.note
|
assert notebook.startup_notes[ 0 ] == self.note
|
||||||
assert notebook.startup_notes[ 1 ] == self.note2
|
assert notebook.startup_notes[ 1 ] == self.note2
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
def test_add_startup_note_without_login( self ):
|
def test_add_startup_note_without_login( self ):
|
||||||
result = self.http_post( "/notebooks/add_startup_note/", dict(
|
result = self.http_post( "/notebooks/add_startup_note/", dict(
|
||||||
|
@ -778,6 +812,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_add_startup_note_with_unknown_notebook( self ):
|
def test_add_startup_note_with_unknown_notebook( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -797,6 +832,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert len( notebook.startup_notes ) == 1
|
assert len( notebook.startup_notes ) == 1
|
||||||
assert notebook.startup_notes[ 0 ] == self.note
|
assert notebook.startup_notes[ 0 ] == self.note
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_add_startup_unknown_note( self ):
|
def test_add_startup_unknown_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -816,6 +852,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert len( notebook.startup_notes ) == 1
|
assert len( notebook.startup_notes ) == 1
|
||||||
assert notebook.startup_notes[ 0 ] == self.note
|
assert notebook.startup_notes[ 0 ] == self.note
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_remove_startup_note( self ):
|
def test_remove_startup_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -834,6 +871,7 @@ class Test_notebooks( Test_controller ):
|
||||||
notebook = result[ "notebook" ]
|
notebook = result[ "notebook" ]
|
||||||
|
|
||||||
assert len( notebook.startup_notes ) == 0
|
assert len( notebook.startup_notes ) == 0
|
||||||
|
assert self.user.storage_bytes > 0
|
||||||
|
|
||||||
def test_remove_startup_note_without_login( self ):
|
def test_remove_startup_note_without_login( self ):
|
||||||
result = self.http_post( "/notebooks/remove_startup_note/", dict(
|
result = self.http_post( "/notebooks/remove_startup_note/", dict(
|
||||||
|
@ -842,6 +880,7 @@ class Test_notebooks( Test_controller ):
|
||||||
), session_id = self.session_id )
|
), session_id = self.session_id )
|
||||||
|
|
||||||
assert result.get( "error" )
|
assert result.get( "error" )
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_remove_startup_note_with_unknown_notebook( self ):
|
def test_remove_startup_note_with_unknown_notebook( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -861,6 +900,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert len( notebook.startup_notes ) == 1
|
assert len( notebook.startup_notes ) == 1
|
||||||
assert notebook.startup_notes[ 0 ] == self.note
|
assert notebook.startup_notes[ 0 ] == self.note
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_remove_startup_unknown_note( self ):
|
def test_remove_startup_unknown_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
@ -880,6 +920,7 @@ class Test_notebooks( Test_controller ):
|
||||||
|
|
||||||
assert len( notebook.startup_notes ) == 1
|
assert len( notebook.startup_notes ) == 1
|
||||||
assert notebook.startup_notes[ 0 ] == self.note
|
assert notebook.startup_notes[ 0 ] == self.note
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
|
||||||
def test_is_startup_note( self ):
|
def test_is_startup_note( self ):
|
||||||
self.login()
|
self.login()
|
||||||
|
|
|
@ -98,6 +98,10 @@ class Test_users( Test_controller ):
|
||||||
else:
|
else:
|
||||||
assert startup_notes == []
|
assert startup_notes == []
|
||||||
|
|
||||||
|
rate_plan = result[ u"rate_plan" ]
|
||||||
|
assert rate_plan[ u"name" ] == u"super"
|
||||||
|
assert rate_plan[ u"storage_quota_bytes" ] == 1337
|
||||||
|
|
||||||
def test_current_with_startup_notes_after_signup( self ):
|
def test_current_with_startup_notes_after_signup( self ):
|
||||||
self.test_current_after_signup( include_startup_notes = True )
|
self.test_current_after_signup( include_startup_notes = True )
|
||||||
|
|
||||||
|
@ -229,10 +233,37 @@ class Test_users( Test_controller ):
|
||||||
def test_update_storage( self ):
|
def test_update_storage( self ):
|
||||||
previous_revision = self.user.revision
|
previous_revision = self.user.revision
|
||||||
|
|
||||||
cherrypy.root.users.update_storage( self.user )
|
cherrypy.root.users.update_storage( self.user.object_id )
|
||||||
self.scheduler.wait_until_idle()
|
self.scheduler.wait_until_idle()
|
||||||
|
|
||||||
expected_size = cherrypy.root.users.calculate_storage( self.user )
|
expected_size = cherrypy.root.users.calculate_storage( self.user )
|
||||||
|
|
||||||
assert self.user.storage_bytes == expected_size
|
assert self.user.storage_bytes == expected_size
|
||||||
assert self.user.revision > previous_revision
|
assert self.user.revision > previous_revision
|
||||||
|
|
||||||
|
def test_update_storage_with_unknown_user_id( self ):
|
||||||
|
original_revision = self.user.revision
|
||||||
|
|
||||||
|
cherrypy.root.users.update_storage( 77 )
|
||||||
|
self.scheduler.wait_until_idle()
|
||||||
|
|
||||||
|
expected_size = cherrypy.root.users.calculate_storage( self.user )
|
||||||
|
|
||||||
|
assert self.user.storage_bytes == 0
|
||||||
|
assert self.user.revision == original_revision
|
||||||
|
|
||||||
|
def test_update_storage_with_callback( self ):
|
||||||
|
def gen():
|
||||||
|
previous_revision = self.user.revision
|
||||||
|
|
||||||
|
cherrypy.root.users.update_storage( self.user.object_id, self.scheduler.thread )
|
||||||
|
user = ( yield Scheduler.SLEEP )
|
||||||
|
|
||||||
|
expected_size = cherrypy.root.users.calculate_storage( self.user )
|
||||||
|
assert user == self.user
|
||||||
|
assert self.user.storage_bytes == expected_size
|
||||||
|
assert self.user.revision > previous_revision
|
||||||
|
|
||||||
|
g = gen()
|
||||||
|
self.scheduler.add( g )
|
||||||
|
self.scheduler.wait_for( g )
|
||||||
|
|
|
@ -13,7 +13,9 @@ class User( Persistent ):
|
||||||
|
|
||||||
def __setstate__( self, state ):
|
def __setstate__( self, state ):
|
||||||
if "_User__storage_bytes" not in state:
|
if "_User__storage_bytes" not in state:
|
||||||
state[ "_User__storage_bytes" ] = False
|
state[ "_User__storage_bytes" ] = 0
|
||||||
|
if "_User__rate_plan" not in state:
|
||||||
|
state[ "_User__rate_plan" ] = 0
|
||||||
|
|
||||||
self.__dict__.update( state )
|
self.__dict__.update( state )
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ class User( Persistent ):
|
||||||
self.__email_address = email_address
|
self.__email_address = email_address
|
||||||
self.__notebooks = notebooks or []
|
self.__notebooks = notebooks or []
|
||||||
self.__storage_bytes = 0 # total storage bytes for this user's notebooks, notes, and revisions
|
self.__storage_bytes = 0 # total storage bytes for this user's notebooks, notes, and revisions
|
||||||
|
self.__rate_plan = 0 # each rate plan is an integer index into the array in config/Common.py
|
||||||
|
|
||||||
def __create_salt( self ):
|
def __create_salt( self ):
|
||||||
return "".join( [ random.choice( self.SALT_CHARS ) for i in range( self.SALT_SIZE ) ] )
|
return "".join( [ random.choice( self.SALT_CHARS ) for i in range( self.SALT_SIZE ) ] )
|
||||||
|
@ -82,6 +85,8 @@ class User( Persistent ):
|
||||||
d = Persistent.to_dict( self )
|
d = Persistent.to_dict( self )
|
||||||
d.update( dict(
|
d.update( dict(
|
||||||
username = self.username,
|
username = self.username,
|
||||||
|
storage_bytes = self.__storage_bytes,
|
||||||
|
rate_plan = self.__rate_plan,
|
||||||
) )
|
) )
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
@ -99,10 +104,15 @@ class User( Persistent ):
|
||||||
self.update_revision()
|
self.update_revision()
|
||||||
self.__storage_bytes = storage_bytes
|
self.__storage_bytes = storage_bytes
|
||||||
|
|
||||||
|
def __set_rate_plan( self, rate_plan ):
|
||||||
|
self.update_revision()
|
||||||
|
self.__rate_plan = rate_plan
|
||||||
|
|
||||||
username = property( lambda self: self.secondary_id )
|
username = property( lambda self: self.secondary_id )
|
||||||
email_address = property( lambda self: self.__email_address )
|
email_address = property( lambda self: self.__email_address )
|
||||||
password = property( None, __set_password )
|
password = property( None, __set_password )
|
||||||
storage_bytes = property( lambda self: self.__storage_bytes, __set_storage_bytes )
|
storage_bytes = property( lambda self: self.__storage_bytes, __set_storage_bytes )
|
||||||
|
rate_plan = property( lambda self: self.__rate_plan, __set_rate_plan )
|
||||||
|
|
||||||
# the notebooks (read-only and read-write) that this user has access to
|
# the notebooks (read-only and read-write) that this user has access to
|
||||||
notebooks = property( lambda self: copy( self.__notebooks ), __set_notebooks )
|
notebooks = property( lambda self: copy( self.__notebooks ), __set_notebooks )
|
||||||
|
|
|
@ -17,6 +17,7 @@ class Test_user( object ):
|
||||||
assert self.user.email_address == self.email_address
|
assert self.user.email_address == self.email_address
|
||||||
assert self.user.notebooks == []
|
assert self.user.notebooks == []
|
||||||
assert self.user.storage_bytes == 0
|
assert self.user.storage_bytes == 0
|
||||||
|
assert self.user.rate_plan == 0
|
||||||
|
|
||||||
def test_check_correct_password( self ):
|
def test_check_correct_password( self ):
|
||||||
assert self.user.check_password( self.password ) == True
|
assert self.user.check_password( self.password ) == True
|
||||||
|
@ -60,6 +61,14 @@ class Test_user( object ):
|
||||||
assert self.user.storage_bytes == storage_bytes
|
assert self.user.storage_bytes == storage_bytes
|
||||||
assert self.user.revision > previous_revision
|
assert self.user.revision > previous_revision
|
||||||
|
|
||||||
|
def test_set_rate_plan( self ):
|
||||||
|
previous_revision = self.user.revision
|
||||||
|
rate_plan = 2
|
||||||
|
self.user.rate_plan = rate_plan
|
||||||
|
|
||||||
|
assert self.user.rate_plan == rate_plan
|
||||||
|
assert self.user.revision > previous_revision
|
||||||
|
|
||||||
|
|
||||||
class Test_user_with_notebooks( object ):
|
class Test_user_with_notebooks( object ):
|
||||||
def setUp( self ):
|
def setUp( self ):
|
||||||
|
@ -116,3 +125,10 @@ class Test_user_with_notebooks( object ):
|
||||||
trash = Notebook( trash_id, u"trash" )
|
trash = Notebook( trash_id, u"trash" )
|
||||||
notebook = Notebook( notebook_id, u"my new notebook", trash )
|
notebook = Notebook( notebook_id, u"my new notebook", trash )
|
||||||
assert self.user.has_access( notebook.object_id ) == False
|
assert self.user.has_access( notebook.object_id ) == False
|
||||||
|
|
||||||
|
def test_to_dict( self ):
|
||||||
|
d = self.user.to_dict()
|
||||||
|
|
||||||
|
assert d.get( "username" ) == self.username
|
||||||
|
assert d.get( "storage_bytes" ) == self.user.storage_bytes
|
||||||
|
assert d.get( "rate_plan" ) == self.user.rate_plan
|
||||||
|
|
|
@ -346,6 +346,27 @@ ol li {
|
||||||
padding: 0.25em 0.25em 0.25em 0.5em;
|
padding: 0.25em 0.25em 0.25em 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.storage_usage_area {
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage_usage_low {
|
||||||
|
color: green;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage_usage_medium {
|
||||||
|
color: orange;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage_usage_high {
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.current_notebook_name {
|
.current_notebook_name {
|
||||||
background-color: #b0d0ff;
|
background-color: #b0d0ff;
|
||||||
-moz-border-radius: 0.5em;
|
-moz-border-radius: 0.5em;
|
||||||
|
|
|
@ -12,6 +12,7 @@ function Wiki( invoker ) {
|
||||||
this.search_results_editor = null; // editor for display of search results
|
this.search_results_editor = null; // editor for display of search results
|
||||||
this.invoker = invoker;
|
this.invoker = invoker;
|
||||||
this.search_titles_only = true;
|
this.search_titles_only = true;
|
||||||
|
this.rate_plan = null;
|
||||||
|
|
||||||
connect( this.invoker, "error_message", this, "display_error" );
|
connect( this.invoker, "error_message", this, "display_error" );
|
||||||
connect( "search_form", "onsubmit", this, "search" );
|
connect( "search_form", "onsubmit", this, "search" );
|
||||||
|
@ -86,6 +87,9 @@ Wiki.prototype.display_user = function ( result ) {
|
||||||
}, notebook.name ) ) );
|
}, notebook.name ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rate_plan = result.rate_plan;
|
||||||
|
this.display_storage_usage( result.user.storage_bytes );
|
||||||
|
|
||||||
// display the name of the logged in user and a logout link
|
// display the name of the logged in user and a logout link
|
||||||
appendChildNodes( user_span, "logged in as " + result.user.username );
|
appendChildNodes( user_span, "logged in as " + result.user.username );
|
||||||
appendChildNodes( user_span, " | " );
|
appendChildNodes( user_span, " | " );
|
||||||
|
@ -99,6 +103,30 @@ Wiki.prototype.display_user = function ( result ) {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Wiki.prototype.display_storage_usage = function( storage_bytes ) {
|
||||||
|
// display the user's current storage usage
|
||||||
|
var MEGABYTE = 1024 * 1024;
|
||||||
|
function bytes_to_megabytes( storage_bytes ) {
|
||||||
|
return Math.round( storage_bytes / MEGABYTE );
|
||||||
|
}
|
||||||
|
|
||||||
|
var quota_bytes = this.rate_plan.storage_quota_bytes || 0;
|
||||||
|
var usage_percent = Math.round( storage_bytes / quota_bytes * 100.0 );
|
||||||
|
|
||||||
|
if ( usage_percent > 90 )
|
||||||
|
var storage_usage_class = "storage_usage_high";
|
||||||
|
else if ( usage_percent > 75 )
|
||||||
|
var storage_usage_class = "storage_usage_medium";
|
||||||
|
else
|
||||||
|
var storage_usage_class = "storage_usage_low";
|
||||||
|
|
||||||
|
replaceChildNodes(
|
||||||
|
"storage_usage_area",
|
||||||
|
createDOM( "div", { "class": storage_usage_class },
|
||||||
|
bytes_to_megabytes( storage_bytes ) + " MB (" + usage_percent + "%) of " + bytes_to_megabytes( quota_bytes ) + " MB used" )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Wiki.prototype.populate = function ( result ) {
|
Wiki.prototype.populate = function ( result ) {
|
||||||
this.notebook = result.notebook;
|
this.notebook = result.notebook;
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
|
@ -11,4 +11,7 @@ class Link_area( Div ):
|
||||||
Div(
|
Div(
|
||||||
id = u"notebooks_area",
|
id = u"notebooks_area",
|
||||||
),
|
),
|
||||||
|
Div(
|
||||||
|
id = u"storage_usage_area",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
Reference in New Issue