Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Lewis <jtl1728@rit.edu>2010-01-11 22:38:48 (GMT)
committer Justin Lewis <jtl1728@rit.edu>2010-01-11 22:42:14 (GMT)
commit537cb64fa14b682bea94d949ee6b4db7866c6631 (patch)
treea51e015898a8f2a8a8a2c4548a9530d1c882737a
parent6372bc63a14c01a5d5fa7f1d5bf4d990a2f17700 (diff)
Basic permissions: download only, add/remove, admin.
The first user to connect to the server is added as an admin. Admins will get a "Server Settings" button on their UI. When clicked, they will be presented with a list of all users ever connected to the server. There they can give them upload/remove and admin privileges if desired.
-rw-r--r--FileShare.activity/FileShareActivity.py56
-rw-r--r--FileShare.activity/GuiView.py78
-rw-r--r--FileShare.server/server.py154
-rw-r--r--FileShare.server/shared_files/__file_data.json (copied from FileShare.server/shared_files/__json_data.json)0
-rw-r--r--FileShare.server/shared_files/__user_data.json (renamed from FileShare.server/shared_files/__json_data.json)0
5 files changed, 256 insertions, 32 deletions
diff --git a/FileShare.activity/FileShareActivity.py b/FileShare.activity/FileShareActivity.py
index cd1eb70..dd83102 100644
--- a/FileShare.activity/FileShareActivity.py
+++ b/FileShare.activity/FileShareActivity.py
@@ -24,6 +24,7 @@ import journalentrybundle
import dbus
import gobject
import zipfile
+from hashlib import sha1
from gettext import gettext as _
from sugar.activity.activity import Activity, ActivityToolbox
@@ -101,6 +102,10 @@ class FileShareActivity(Activity):
self._mode = "P2P"
prof = profile.get_profile()
+ self._user_key_hash = sha1(prof.pubkey).hexdigest()
+ self._user_nick = profile.get_nick_name()
+ self._user_permissions = 0
+
jabber_serv = None
#Need to check if on 82 or higher
if hasattr(prof, 'jabber_server'):
@@ -114,6 +119,7 @@ class FileShareActivity(Activity):
if jabber_serv:
self.server_ip = jabber_serv
self.server_port= 14623
+ self.s_version = 0
if self.isServer and self.check_for_server() and self._server_mode():
self._mode = "SERVER"
@@ -156,12 +162,50 @@ class FileShareActivity(Activity):
if r1.status == 200:
s_version= r1.read()
conn.close()
- return s_version
+
+ if int(s_version) >= 2:
+ # Version 2 supports permissions, announce user so server
+ # can cache user info and be added to the access list if allowed
+
+ params = { 'id': self._user_key_hash,
+ 'nick': self._user_nick
+ }
+ try:
+ opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler)
+ f = opener.open("http://%s:%d/announce_user"%(self.server_ip, self.server_port), params)
+ self._user_permissions = int(f.read())
+ except:
+ raise ServerRequestFailure
+
+ else:
+ # Older version didn't have permissions, set 1 as default (upload/remove)
+ self._user_permissions = 1
+ self.s_version = s_version
+ return True
else:
return False
except:
return False
+ def get_server_user_list(self):
+ params = { 'id': self._user_key_hash }
+ try:
+ opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler)
+ f = opener.open("http://%s:%d/user_list"%(self.server_ip, self.server_port), params)
+ return simplejson.loads(f.read())
+ except:
+ raise ServerRequestFailure
+
+ def change_server_user(self, userId, level):
+ params = { 'id': self._user_key_hash,
+ 'userid': userId,
+ 'level': level
+ }
+ try:
+ opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler)
+ f = opener.open("http://%s:%d/user_mod"%(self.server_ip, self.server_port), params)
+ except:
+ raise ServerRequestFailure
def build_file(self, jobject):
#If object has activity id and it is filled in, use that as hash
@@ -209,6 +253,10 @@ class FileShareActivity(Activity):
params = { 'jdata': simplejson.dumps(file_info.share_dump()),
'file': open(bundle_path, 'rb')
}
+
+ if self.s_version >= 2:
+ params['id'] = self._user_key_hash
+
try:
opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler)
opener.open("http://%s:%d/upload"%(self.server_ip, self.server_port), params)
@@ -216,7 +264,11 @@ class FileShareActivity(Activity):
raise FileUploadFailure()
def remove_file_from_server( self, file_id ):
- params = { 'id': file_id }
+ params = { 'fid': file_id }
+
+ if self.s_version >= 2:
+ params['id'] = self._user_key_hash
+
try:
opener = urllib2.build_opener( MultipartPostHandler.MultipartPostHandler)
opener.open("http://%s:%d/remove"%(self.server_ip, self.server_port), params)
diff --git a/FileShare.activity/GuiView.py b/FileShare.activity/GuiView.py
index ba49b1d..528df49 100644
--- a/FileShare.activity/GuiView.py
+++ b/FileShare.activity/GuiView.py
@@ -188,6 +188,77 @@ class GuiHandler():
def _alert_cancel_cb(self, alert, response_id):
self.activity.remove_alert(alert)
+ def showAdmin(self, widget, data=None):
+ def call():
+ try:
+ userList = self.activity.get_server_user_list()
+
+ except ServerRequestFailure:
+ self._alert(_("Failed to get user list from server"))
+ self.show_throbber( False )
+ else:
+ level = [_("Download Only"), _("Upload/Remove"), _("Admin")]
+
+ myTable = gtk.Table(10, 1, False)
+ hbbox = gtk.HButtonBox()
+ returnBut = gtk.Button(_("Return to Main Screen"))
+ returnBut.connect("clicked",self.restore_view, None)
+ hbbox.add(returnBut)
+
+ listbox = gtk.VBox()
+
+ for key in userList:
+ holder = gtk.HBox()
+ label = gtk.Label(userList[key][0])
+ label.set_alignment(0, 0)
+ holder.pack_start(label)
+
+ if key == self.activity._user_key_hash:
+ mode_box = gtk.Label(level[userList[key][1]])
+ mode_box.set_alignment(1,0)
+ else:
+ mode_box = gtk.combo_box_new_text()
+ for option in level:
+ mode_box.append_text( option )
+
+ mode_box.set_active(userList[key][1])
+ mode_box.connect("changed", self.user_changed, key)
+
+ holder.pack_start(mode_box, False, False, 0)
+ listbox.pack_start(holder, False, False, 0)
+
+ window = gtk.ScrolledWindow()
+ window.add_with_viewport(listbox)
+
+ myTable.attach(hbbox,0,1,0,1)
+ myTable.attach(window,0,1,1,10)
+
+ self.activity.set_canvas(myTable)
+ self.activity.show_all()
+
+ self.show_throbber(True, _("Please Wait... Requesting user list from server"))
+ threading.Thread(target=call).start()
+
+
+ def user_changed(self, widget, id):
+ widget.set_sensitive(False)
+ def change():
+ try:
+ self.activity.change_server_user(id, widget.get_active())
+ widget.set_sensitive(True)
+ except ServerRequestFailure:
+ parent = widget.get_parent()
+ parent.remove(widget)
+ lbl = gtk.Label(_("User Change Failed"))
+ lbl.set_alignment(1,0)
+ lbl.show()
+ parent.add( lbl )
+
+ threading.Thread(target=change).start()
+
+ def restore_view(self, widget, data = None):
+ self.show_throbber( False )
+
class GuiView(gtk.Table):
"""
@@ -219,7 +290,7 @@ class GuiView(gtk.Table):
hbbox.add(remFileButton)
else:
- if activity._mode == 'SERVER':
+ if activity._mode == 'SERVER' and activity._user_permissions != 0:
addFileButton = gtk.Button(_("Upload A File"))
addFileButton.connect("clicked", self.guiHandler.requestAddFile, {'upload':True})
hbbox.add(addFileButton)
@@ -228,7 +299,10 @@ class GuiView(gtk.Table):
remFileButton.connect("clicked", self.guiHandler.requestRemFile, {'remove':True})
hbbox.add(remFileButton)
-
+ if activity._user_permissions == 2:
+ adminButton = gtk.Button(_("Server Settings"))
+ adminButton.connect("clicked", self.guiHandler.showAdmin, None)
+ hbbox.add(adminButton)
downloadFileButton = gtk.Button(_("Download File"))
downloadFileButton.connect("clicked", self.guiHandler.requestDownloadFile, None)
diff --git a/FileShare.server/server.py b/FileShare.server/server.py
index 231c35e..3cff570 100644
--- a/FileShare.server/server.py
+++ b/FileShare.server/server.py
@@ -5,7 +5,7 @@ import os
import cgi
# Version string for future protocol change as well as server verification
-s_version = 1
+s_version = 2
port = 14623
class FileManager:
@@ -14,6 +14,7 @@ class FileManager:
"""
def __init__(self, file_path = "shared_files"):
self.fileList = {}
+ self.userList = {}
self.file_path = file_path
self.load()
@@ -22,19 +23,28 @@ class FileManager:
Loads file data from __json_data.json if it exists in the
file_path
"""
- settings_path = os.path.join(self.file_path, "__json_data.json")
+ settings_path = os.path.join(self.file_path, "__file_data.json")
if os.path.exists( settings_path ):
self.fileList = simplejson.loads( open( settings_path, 'r' ).read() )
+ settings_path = os.path.join(self.file_path, "__user_data.json")
+ if os.path.exists( settings_path ):
+ self.userList = simplejson.loads( open( settings_path, 'r' ).read() )
+
def save(self):
"""
Saves the current file list into __json_data.json
"""
- settings_path = os.path.join(self.file_path, "__json_data.json")
+ settings_path = os.path.join(self.file_path, "__file_data.json")
f = open( settings_path, 'w' )
f.write( simplejson.dumps( self.fileList ) )
f.close()
+ settings_path = os.path.join(self.file_path, "__user_data.json")
+ f = open( settings_path, 'w' )
+ f.write( simplejson.dumps( self.userList ) )
+ f.close()
+
def add_file(self, key, dict, data):
"""
Adds a file to the file list and saves the file to the file_path
@@ -72,6 +82,12 @@ class FileManager:
"""
return simplejson.dumps(self.fileList)
+ def get_user_str(self):
+ """
+ Dumps a json string of the user list
+ """
+ return simplejson.dumps(self.userList)
+
def get_file_contents(self, key):
"""
Returns the file data based off its key
@@ -87,17 +103,53 @@ class FileManager:
"""
return self.fileList.has_key( key )
+ def user_permissions(self, id, nick):
+ print "GOT USER REQUEST %s (%s)" % (nick, id)
+ if self.userList.has_key(id) == False:
+ permission = 0
+ if len( self.userList ) == 0:
+ permission = 2
+ self.userList[id] = [nick, permission]
+ self.save()
+
+ if self.userList[id][0] != nick:
+ self.userList[id][0] = nick
+ self.save()
+
+ return self.userList[id][1]
+
+ def change_user_permissions(self, id, level):
+ if self.userList.has_key(id):
+ self.userList[id][1] = int(level)
+ self.save()
+
+ def can_rem(self, id):
+ return self.userList.has_key(id) and self.userList[id][1] != 0
+
+ def can_upload(self, id):
+ return self.userList.has_key(id) and self.userList[id][1] != 0
+
+ def can_admin(self, id):
+ return self.userList.has_key(id) and self.userList[id][1] == 2
+
class MyServer(BaseHTTPServer.BaseHTTPRequestHandler):
"""
Simple http server:
Pages:
- * /, /index.html A page saying that the system is running
- * /version Returns server revision number
- * /fileList A json string of the file list
- * /ANYFILEID Downloads the file if the id matches
- * POST /upload Expects an upload jdata and file
+ GET:
+ * /, /index.html A page saying that the system is running
+ * /version Returns server revision number
+ * /fileList A json string of the file list
+ * /{ANY_ID} Downloads the file if the id matches
+ POST:
+ * /upload Adds file (expects id, jdata and file)
+ * /remove Removes file (expects id and fid)
+ * /announce_user Adds user to list (and responds with permission level)
+ (expects id, nick)
+ * /user_list Returns user list (expects id, must have admin permission level)
+ * /user_mod Changes user permissions (expects id (ADMIN), userId, level)
"""
def do_GET(self):
if self.path == "/" or self.path == "/index.html":
@@ -147,34 +199,80 @@ class MyServer(BaseHTTPServer.BaseHTTPRequestHandler):
})
if self.path == "/upload":
- # Begin the response
- self.send_response(200)
- self.end_headers()
+ if form.has_key('id') and fileMan.can_upload( form['id'].value ):
+ # Begin the response
+ self.send_response(200, 'OK')
+ self.end_headers()
+
+ if( form.has_key('jdata') and form.has_key('file') ):
+ try:
+ data = simplejson.loads( form['jdata'].value )
+ file_data = form['file'].file.read()
+ fileMan.add_file(data[0], data, file_data)
+
+ # Begin the response
+ self.send_response(200)
+ self.end_headers()
+ except:
+ self.send_error(500,'Server Error or Invalid Request')
+ self.end_headers()
+ return
+ else:
+ self.send_error(403, "Forbidden")
+ self.end_headers()
+ elif self.path == "/remove":
+ if( form.has_key('id') and fileMan.can_rem( form['id'].value ) ):
+ self.send_response(200, 'OK')
+ self.end_headers()
+
+ if( form.has_key('fid') and fileMan.has_file_key( form['fid'].value ) ):
+ fileMan.rem_file( form['fid'].value )
+ else:
+ self.send_error(403, "Forbidden")
+ self.end_headers()
- if( form.has_key('jdata') and form.has_key('file') ):
- try:
- data = simplejson.loads( form['jdata'].value )
- file_data = form['file'].file.read()
- fileMan.add_file(data[0], data, file_data)
+ elif self.path == "/announce_user":
+ if( form.has_key('id') and form.has_key('nick') ):
+ self.send_response(200, 'OK')
+ self.end_headers()
+ self.wfile.write( fileMan.user_permissions(form['id'].value, form['nick'].value) )
+ else:
+ self.send_error(400, 'Bad Request')
+ self.end_headers()
- # Begin the response
- self.send_response(200)
+ elif self.path == "/user_list":
+ if form.has_key('id'):
+ if fileMan.can_admin( form['id'].value ):
+ self.send_response(200, 'OK')
self.end_headers()
- except:
- self.send_error(500,'Server Error or Invalid Request')
+ self.wfile.write( fileMan.get_user_str() )
+ else:
+ self.send_error(403, "Forbidden")
self.end_headers()
- return
- elif self.path == "/remove":
- self.send_response(200)
- self.end_headers()
-
- print form.keys()
+ else:
+ self.send_error(400, 'Bad Request')
+ self.end_headers()
- if( form.has_key('id') and fileMan.has_file_key( form['id'].value ) ):
- fileMan.rem_file( form['id'].value )
+ elif self.path == "/user_mod":
+ if form.has_key('id') and form.has_key('userid') and form.has_key('level'):
+ if fileMan.can_admin( form['id'].value ):
+ if form['id'].value != form['userid'].value:
+ self.send_response(200, 'OK')
+ self.end_headers()
+ fileMan.change_user_permissions(form['userid'].value, form['level'].value)
+ else:
+ self.send_error(400, 'Bad Request, Can not modify yourself')
+ self.end_headers()
+ else:
+ self.send_error(403, "Forbidden")
+ self.end_headers()
+ else:
+ self.send_error(400, 'Bad Request')
+ self.end_headers()
else:
self.send_error(404,'File Not Found (POST): %s' % self.path)
+ self.end_headers()
diff --git a/FileShare.server/shared_files/__json_data.json b/FileShare.server/shared_files/__file_data.json
index 9e26dfe..9e26dfe 100644
--- a/FileShare.server/shared_files/__json_data.json
+++ b/FileShare.server/shared_files/__file_data.json
diff --git a/FileShare.server/shared_files/__json_data.json b/FileShare.server/shared_files/__user_data.json
index 9e26dfe..9e26dfe 100644
--- a/FileShare.server/shared_files/__json_data.json
+++ b/FileShare.server/shared_files/__user_data.json