summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Behrens <tbehrens@suse.com>2013-04-15 03:33:49 +0200
committerThorsten Behrens <tbehrens@suse.com>2013-04-15 03:33:49 +0200
commite11f6e4d9d2b4e17b9ae7be7611a66bfb810bca7 (patch)
tree74260d3af300a724f0209098edfd9f5301cb5cfe
parenta5772fb74fbb0c2a8dbaa81449a76ee69fa20556 (diff)
implement slide groups, ensuing rework
- slide thumbnail no longer bear slide number to ease symlinking - split up tree between decks and groups (also for preview/thumbnailing) - some tweaks around ssl support
-rwxr-xr-xconvert_deck.sh2
-rwxr-xr-xslideapi.py185
-rw-r--r--views/decksgroups.tpl21
-rw-r--r--views/groups.tpl9
4 files changed, 153 insertions, 64 deletions
diff --git a/convert_deck.sh b/convert_deck.sh
index e410b94..77d7fc7 100755
--- a/convert_deck.sh
+++ b/convert_deck.sh
@@ -14,6 +14,6 @@ for i in $1/deck-*.png; do
rev1=${i/*deck-/}
rev2=${rev1/.png/}
mkdir -p $1/$rev2
- mv $i $1/$rev2/$rev2.png
+ mv $i $1/$rev2/thumbnail.png
done
diff --git a/slideapi.py b/slideapi.py
index 7c78a0e..8e99410 100755
--- a/slideapi.py
+++ b/slideapi.py
@@ -18,10 +18,10 @@ from subprocess import call
# we understand:
# local_conf["users"], yielding {<username>: {"password": <password>, "description": <description>}, ... }
# local_conf["thumbnails"], yielding {"soffice": <path>, "convert": <path>, "thumbnail_size": <128x128>}
-# local_conf["tags"], yielding [ <tagname>, ... ]
+# local_conf["tags"], yielding { <tagname>: <tag_desc, ... }
#
local_conf=json.loads(open('local.json').read()) if os.path.exists('local.json') else {}
-root='filestore'
+root=local_conf["filestore"]
def validate_auth(user, password):
if "users" in local_conf:
@@ -51,7 +51,7 @@ def get_tags():
@get('/api/tags/')
def tags():
- return json.dumps(get_tags())
+ return get_tags()
@get('/tags/')
@view('tags')
@@ -61,13 +61,19 @@ def tags():
# -------------------------------------------------------------------
def get_decks(user):
- path = "%s/%s/" % (root,user)
+ path = "%s/%s/decks/" % (root,user)
if not os.path.isdir(path):
return []
return [deck for deck in os.listdir(path) if os.path.isdir(path+deck)]
-def get_lastrev(user,deck):
- path = "%s/%s/%s/" % (root,user,deck)
+def get_groups(user):
+ path = "%s/%s/groups/" % (root,user)
+ if not os.path.isdir(path):
+ return []
+ return [group for group in os.listdir(path) if os.path.isdir(path+group)]
+
+def get_lastrev(user,part,deck):
+ path = "%s/%s/%s/%s/" % (root,user,part,deck)
if not os.path.isdir(path):
return 0
# get last revision
@@ -75,44 +81,62 @@ def get_lastrev(user,deck):
@get('/api/users/<user>/')
def list_decks(user):
+ return json.dumps(['decks/'+deck for deck in get_decks(user)] + ['groups/'+group for group in get_groups(user)])
+
+@get('/api/users/<user>/decks/')
+def list_decks(user):
return json.dumps(get_decks(user))
+@get('/api/users/<user>/groups/')
+def list_groups(user):
+ return json.dumps(get_groups(user))
+
@get('/users/<user>/')
+@view('decksgroups')
+def list_decksgroups(user):
+ return dict(decks=get_decks(user), groups=get_groups(user))
+
+@get('/users/<user>/decks/')
@view('decks')
def list_decks(user):
return dict(decks=get_decks(user))
-@get('/users/<user>/<deck>/thumbnail.png')
-@get('/api/users/<user>/<deck>/thumbnail.png')
-def get_thumbnail(user, deck):
- path = "%s/%s/%s/" % (root,user,deck)
- last_rev = get_lastrev(user,deck)
+@get('/users/<user>/groups/')
+@view('groups')
+def list_groups(user):
+ return dict(groups=get_groups(user))
+
+@get('/users/<user>/<part>/<deck>/thumbnail.png')
+@get('/api/users/<user>/<part>/<deck>/thumbnail.png')
+def get_thumbnail(user, part, deck):
+ path = "%s/%s/%s/%s/" % (root,user,part,deck)
+ last_rev = get_lastrev(user,part,deck)
# serve thumbnail from that rev, first slide
- return static_file('0.png', root=path+str(last_rev)+'/0/', mimetype='image/png')
+ return static_file('thumbnail.png', root=path+str(last_rev)+'/0/', mimetype='image/png')
# -------------------------------------------------------------------
-def get_revs(user,deck):
- path = "%s/%s/%s/" % (root,user,deck)
+def get_revs(user,part,deck):
+ path = "%s/%s/%s/%s/" % (root,user,part,deck)
if not os.path.isdir(path):
return []
return sorted([rev for rev in os.listdir(path) if os.path.isdir(path+rev)], key=int)
-@get('/api/users/<user>/<deck>/')
-def list_revs(user,deck):
- return json.dumps(get_revs(user,deck))
+@get('/api/users/<user>/<part>/<deck>/')
+def list_revs(user,part,deck):
+ return json.dumps(get_revs(user,part,deck))
-@get('/users/<user>/<deck>/')
+@get('/users/<user>/<part>/<deck>/')
@view('revs')
-def list_revs(user,deck):
- return dict(revs=get_revs(user,deck))
+def list_revs(user,part,deck):
+ return dict(revs=get_revs(user,part,deck))
-@post('/users/<user>/<deck>')
-@post('/api/users/<user>/<deck>')
+@post('/users/<user>/decks/<deck>')
+@post('/api/users/<user>/decks/<deck>')
@auth_basic(validate_auth, realm='upload')
def upload_deck(user,deck):
- path = "%s/%s/%s/" % (root,user,deck)
- new_rev = get_lastrev(user,deck) + 1
+ path = "%s/%s/decks/%s/" % (root,user,deck)
+ new_rev = get_lastrev(user,'decks',deck) + 1
new_path = path+str(new_rev)
if os.path.isdir(new_path):
@@ -145,30 +169,64 @@ def upload_deck(user,deck):
# thumbnail generation happens asynchronously via updatedeck.py
return 'Success:'+tag+':'+content.filename
+@post('/users/<user>/groups/<deck>')
+@post('/api/users/<user>/groups/<deck>')
+@auth_basic(validate_auth, realm='upload')
+def upload_group(user,deck):
+ path = "%s/%s/groups/%s/" % (root,user,deck)
+ new_rev = get_lastrev(user,'groups',deck) + 1
+ new_path = path+str(new_rev)
+
+ if os.path.isdir(new_path):
+ raise HTTPError(body='inconsistent repo, bailing out')
+
+ if request.auth[0] != user:
+ raise HTTPError(body='invalid user or insufficient rights, bailing out')
+
+ properties = request.json
+ if properties[u'name'] != deck:
+ raise HTTPError(body='Failue: url / name mismatch')
+
+ os.makedirs(new_path)
+ upload_path = new_path
+
+ # link slides/decks
+ for index, slide in enumerate(properties['slides']):
+ if not os.path.isdir(root+'/'+slide):
+ raise HTTPError(body='non-existing slide %d at path %s, bailing out' % (index, root+slide)) # todo: cleanup!!
+ os.symlink('../../../../'+slide, upload_path+'/'+str(index))
+
+ out = open(upload_path+'/meta.json', 'wb')
+ json.dump({'server_version': '1',
+ 'payload': properties},
+ out)
+
+ return 'Success'
+
-@get('/users/<user>/<deck>/<rev:int>/thumbnail.png')
-@get('/api/users/<user>/<deck>/<rev:int>/thumbnail.png')
-def get_thumbnail(user, deck, rev):
- path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+@get('/users/<user>/<part>/<deck>/<rev:int>/thumbnail.png')
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/thumbnail.png')
+def get_thumbnail(user, part, deck, rev):
+ path = "%s/%s/%s/%s/%d/" % (root,user,part,deck,rev)
# serve thumbnail from that rev, first slide
- return static_file('0.png', root=path+'/0/', mimetype='image/png')
+ return static_file('thumbnail.png', root=path+'/0/', mimetype='image/png')
-@get('/users/<user>/<deck>/<rev:int>/deck.odp')
-@get('/api/users/<user>/<deck>/<rev:int>/deck.odp')
-def send_deck(user, deck, rev):
- path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+@get('/users/<user>/<part>/<deck>/<rev:int>/deck.odp')
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/deck.odp')
+def send_deck(user, part, deck, rev):
+ path = "%s/%s/%s/%s/%d/" % (root,user,part,deck,rev)
return static_file(deck+'.odp', root=path, mimetype='text/xml')
# -------------------------------------------------------------------
-def get_slides(user,deck,rev):
- path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+def get_slides(user,part,deck,rev):
+ path = "%s/%s/%s/%s/%d/" % (root,user,part,deck,rev)
if not os.path.isdir(path):
return []
return sorted([slide for slide in os.listdir(path) if os.path.isdir(path+slide)], key=int)
-def get_revmeta(user,deck,rev):
- path = "%s/%s/%s/%d/" % (root,user,deck,rev)
+def get_revmeta(user,part,deck,rev):
+ path = "%s/%s/%s/%s/%d/" % (root,user,part,deck,rev)
comment = open(path+'comment').read() if os.path.exists(path+'comment') else ''
meta = json.loads(open(path+'meta.json').read()) if os.path.exists(path+'meta.json') else {}
return {'CreationDate': time.strftime("%a, %d %b %Y %H:%M:%S GMT",
@@ -176,39 +234,40 @@ def get_revmeta(user,deck,rev):
'CommitComment': comment,
'Meta': meta}
-@get('/api/users/<user>/<deck>/<rev:int>/')
-def list_slides(user, deck, rev):
- return json.dumps(get_slides(user,deck,rev))
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/')
+def list_slides(user, part, deck, rev):
+ return json.dumps(get_slides(user,part,deck,rev))
-@get('/users/<user>/<deck>/<rev:int>/')
+@get('/users/<user>/<part>/<deck>/<rev:int>/')
@view('slides')
-def list_slides(user, deck, rev):
- return dict(slides=get_slides(user,deck,rev), revmeta=get_revmeta(user,deck,rev))
+def list_slides(user, part, deck, rev):
+ return dict(slides=get_slides(user,part,deck,rev), revmeta=get_revmeta(user,part,deck,rev))
-@get('/users/<user>/<deck>/<rev:int>/<slide:int>/thumbnail.png')
-@get('/api/users/<user>/<deck>/<rev:int>/<slide:int>/thumbnail.png')
-def get_thumbnail(user, deck, rev, slide):
- path = "%s/%s/%s/%d/%d/" % (root,user,deck,rev,slide)
- return static_file(str(slide)+'.png', root=path, mimetype='image/png')
+@get('/users/<user>/<part>/<deck>/<rev:int>/<slide:int>/thumbnail.png')
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/<slide:int>/thumbnail.png')
+def get_thumbnail(user, part, deck, rev, slide):
+ path = "%s/%s/%s/%s/%d/%d/" % (root,user,part,deck,rev,slide)
+ print path
+ return static_file('thumbnail.png', root=path, mimetype='image/png')
-@get('/api/users/<user>/<deck>/<rev:int>/meta.json')
-def list_revmeta(user,deck,rev):
- return get_revmeta(user,deck,rev)
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/meta.json')
+def list_revmeta(user,part,deck,rev):
+ return get_revmeta(user,part,deck,rev)
# -------------------------------------------------------------------
-def get_slidemeta(user,deck,rev,slide):
- path = "%s/%s/%s/%d/%d/" % (root,user,deck,rev,slide)
+def get_slidemeta(user,part,deck,rev,slide):
+ path = "%s/%s/%s/%s/%d/%d/" % (root,user,part,deck,rev,slide)
return json.loads(open(path+'meta.json').read()) if os.path.exists(path+'meta.json') else {}
-@get('/api/users/<user>/<deck>/<rev:int>/<slide:int>/meta.json')
-def list_slidemeta(user, deck, rev, slide):
- return get_slidemeta(user, deck, rev, slide)
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/<slide:int>/meta.json')
+def list_slidemeta(user, part, deck, rev, slide):
+ return get_slidemeta(user, part, deck, rev, slide)
-@get('/users/<user>/<deck>/<rev:int>/<slide:int>/slide.odp')
-@get('/api/users/<user>/<deck>/<rev:int>/<slide:int>/slide.odp')
-def send_slide(user, deck, rev, slide):
- path = "%s/%s/%s/%d/%d/" % (root,user,deck,rev,slide)
+@get('/users/<user>/<part>/<deck>/<rev:int>/<slide:int>/slide.odp')
+@get('/api/users/<user>/<part>/<deck>/<rev:int>/<slide:int>/slide.odp')
+def send_slide(user, part, deck, rev, slide):
+ path = "%s/%s/%s/%s/%d/%d/" % (root,user,part,deck,rev,slide)
return static_file(str(slide)+'.odp', root=path, mimetype='text/xml')
@get('/')
@@ -220,9 +279,9 @@ def home_page():
class SSLInterface(ServerAdapter):
def run(self, handler):
server = _cpwsgiserver3.CherryPyWSGIServer((self.host, self.port), handler)
- cert = 'server.pem'
- server.ssl_certificate = cert
- server.ssl_private_key = cert
+ #cert = 'server.pem'
+ #server.ssl_certificate = cert
+ #server.ssl_private_key = cert
try:
server.start()
finally:
diff --git a/views/decksgroups.tpl b/views/decksgroups.tpl
new file mode 100644
index 0000000..87c66cb
--- /dev/null
+++ b/views/decksgroups.tpl
@@ -0,0 +1,21 @@
+%#generate HTML table of all decks
+<table border="1">
+ <tr>
+ <th colspan=2><b>Decks</b></th>
+ </tr>
+%for deckname in decks:
+ <tr>
+ <td><a href="decks/{{deckname}}/">{{deckname}}</a></td>
+ <td><a href="decks/{{deckname}}/"><img src="decks/{{deckname}}/thumbnail.png"></a></td>
+ </tr>
+%end
+ <tr>
+ <th colspan=2><b>Groups</b></th>
+ </tr>
+%for groupname in groups:
+ <tr>
+ <td><a href="groups/{{groupname}}/">{{groupname}}</a></td>
+ <td><a href="groups/{{groupname}}/"><img src="groups/{{groupname}}/thumbnail.png"></a></td>
+ </tr>
+%end
+</table>
diff --git a/views/groups.tpl b/views/groups.tpl
new file mode 100644
index 0000000..33c0df9
--- /dev/null
+++ b/views/groups.tpl
@@ -0,0 +1,9 @@
+%#generate HTML table of all decks
+<table border="1">
+%for groupname in groups:
+ <tr>
+ <td><a href="{{groupname}}/">{{groupname}}</a></td>
+ <td><a href="{{groupname}}/"><img src="{{groupname}}/thumbnail.png"></a></td>
+ </tr>
+%end
+</table>