def serve_doc(req, id_source, annotated=False): serve_dir = settings.ANNOTATED_DIR if annotated else settings.REPOSITORY_DIR qual = "_annotated" if annotated else "" uid = UR.getUserId(req) if not auth.canDownloadPDF(uid, id_source): return HttpResponse("Error: You don't have credentials to see file #%s" % (id_source, )) try: response = serve(req, id_source,"%s/%s" % (settings.HTTPD_MEDIA, serve_dir)) response["Content-Type"]='application/pdf' #the following makes sure that: #- the downloaded file name always ends up w/ '.pdf' #- it conatains the qualif. '_annotated' if it's... er... well.... annotated : ) #- the filename only contains ascii characters, so that we don't get an UnicodeEncodeError since the # filename is part of the response headers and that HTTP response headers can only contain ascii characters. filename = "" try: filename = M.Source.objects.get(pk=id_source).title.partition(".pdf")[0].encode("ascii").replace(" ", "_") except UnicodeEncodeError: filename = id_source filename = "%s%s%s" % (filename, qual, ".pdf") response['Content-Disposition'] = "attachment; filename=%s" % (filename, ) signals.file_downloaded.send("file", req=req, uid=uid, id_source=id_source, annotated=annotated) return response except Http404: logging.info("missing "+id_source) return HttpResponse("Error - No such file: #%s %s" % (id_source, qual) )
def upload(req): r = HttpResponse() f = req.FILES["file"] id_ensemble = req.GET["id_ensemble"] id_source = req.GET["id_source"] id_folder = req.GET.get("id_folder", None) uid = UR.getUserId(req); logging.info("upload uid=%s, id_source=%s, id_ensemble=%s, id_folder=%s" % (uid,id_source,id_ensemble,id_folder)) url = "http://%s:%s/%s?id_ensemble=%s" %("localhost", "8080",f.name, id_ensemble) payload = {"url": url, "id_source": id_source, "id_folder": id_folder } if auth.canInsertFile(uid, id_ensemble, id_folder): #the followong data will be deleted in utils_pdf if an PDF error happens later... annotations.createSource(uid, payload) annotations.addOwnership(id_source, id_ensemble, id_folder) REPOSITORY_DIR = "%s/%s" % (settings.HTTPD_MEDIA, "/pdf/repository") f2 = open("%s/%s" % (REPOSITORY_DIR, id_source,),"wb") f2.write(f.read()) f2.close() basedir = dirname(dirname(abspath(__file__))) #do the rest in the background, so server remains responsive cmd = "(cd %s; python -m upload.jobs file_img %s >/tmp/uploadscript_%s.log 2>&1 &)" %(basedir, id_source, id_log ) logging.info(cmd) os.system(cmd) r.content = UR.prepare_response({}) else: r.content = UR.prepare_response({}, 1, "NOT ALLOWED to insert a file to this group") return r
def serve_grades_spreadsheet(req, id_ensemble): uid = UR.getUserId(req) if not auth.canSeeGrades(uid, id_ensemble): return HttpResponse("Error: You don't have credentials to see grades for class %s" % (id_ensemble,)) import xlwt wbk = xlwt.Workbook() #first, generate the sheets with comment, words, char counts: stats = add_count_sheets(id_ensemble, wbk) #now add a sheet for labeled comments if there are any: add_labeledcomments_sheet(uid, id_ensemble, wbk) #now add sheets for the social graph # FIXME: this is broken for ensemble 6010 on nb.mit.edu. Disabling for now. # https://github.com/nbproject/nbproject/issues/199 #add_socialgraph_sheets(id_ensemble, stats["users"], wbk) import datetime a = datetime.datetime.now() fn = "stats_%s_%04d%02d%02d_%02d%02d.xls" % (id_ensemble,a.year, a.month, a.day, a.hour, a.minute) wbk.save("/tmp/%s" %(fn,)) response = serve(req, fn,"/tmp/") os.remove("/tmp/%s" %(fn,)) response["Content-Type"]='application/vnd.ms-excel' response['Content-Disposition'] = "attachment; filename=%s" % (fn, ) return response
def serve_doc(req, id_source, annotated=False): serve_dir = settings.ANNOTATED_DIR if annotated else settings.REPOSITORY_DIR qual = "_annotated" if annotated else "" uid = UR.getUserId(req) if not auth.canDownloadPDF(uid, id_source): return HttpResponse( "Error: You don't have credentials to see file #%s" % (id_source, )) try: response = serve(req, id_source, "%s/%s" % (settings.HTTPD_MEDIA, serve_dir)) response["Content-Type"] = 'application/pdf' #the following makes sure that: #- the downloaded file name always ends up w/ '.pdf' #- it conatains the qualif. '_annotated' if it's... er... well.... annotated : ) #- the filename only contains ascii characters, so that we don't get an UnicodeEncodeError since the # filename is part of the response headers and that HTTP response headers can only contain ascii characters. filename = "" try: filename = M.Source.objects.get(pk=id_source).title.partition( ".pdf")[0].encode("ascii").replace(" ", "_") except UnicodeEncodeError: filename = id_source filename = "%s%s%s" % (filename, qual, ".pdf") response['Content-Disposition'] = "attachment; filename=%s" % ( filename, ) signals.file_downloaded.send("file", req=req, uid=uid, id_source=id_source, annotated=annotated) return response except Http404: logging.info("missing " + id_source) return HttpResponse("Error - No such file: #%s %s" % (id_source, qual))
def set_comment_label(P, req): uid = UR.getUserId(req) cid = P["comment_id"] if not auth.canLabelComment(uid, cid): return UR.prepare_response({}, 1, "NOT ALLOWED") record = None try: record = M.CommentLabel.objects.get(grader__id=uid, comment__id=cid, category_id=P["category_id"]) rh = M.CommentLabelHistory() rh.grader = record.grader rh.ctime = record.ctime rh.grade = record.grade rh.category = record.category rh.comment = record.comment rh.save() record.ctime = datetime.datetime.now() except M.CommentLabel.DoesNotExist: record = M.CommentLabel() record.category_id = P["category_id"] record.comment_id = cid record.grade = P["grade"] record.grader_id = uid record.save() retval = {"commentlabels":{record.id: UR.model2dict(record)}} return UR.prepare_response(retval)
def getHTML5Info(payload, req): if "url" not in payload: return UR.prepare_response({}, 1, "missing url !") url = payload["url"].partition("#")[0].rstrip( "/" ) # remove hash part of the URL by default, as well as trailing slash. #TODO: use optional argument id_ensemble to disambiguate if provided. sources_info = M.HTML5Info.objects.filter(url=url) ownerships = M.Ownership.objects.select_related( "source", "ensemble", "folder").filter(source__html5info__in=sources_info, deleted=False) if not ownerships.exists(): return UR.prepare_response({}, 1, "this URL is not recognized: ") output = { "files": UR.qs2dict(ownerships, annotations.__NAMES["files2"], "ID"), "ensembles": UR.qs2dict(ownerships, annotations.__NAMES["ensembles2"], "ID"), "folders": UR.qs2dict(ownerships, annotations.__NAMES["folders2"], "ID"), } for i in output["ensembles"]: if not (output["ensembles"][i]["allow_guest"] or auth.isMember(UR.getUserId(req), i)): return UR.prepare_response( {}, 1, "not allowed: guest access isn't allowed for this file.") return UR.prepare_response(output)
def getHTML5Info(payload, req): if "url" not in payload: return UR.prepare_response({}, 1, "missing url !") url = payload["url"].partition("#")[0].rstrip( "/" ) # remove hash part of the URL by default, as well as trailing slash. #TODO: use optional argument id_ensemble to disambiguate if provided. sources_info = M.HTML5Info.objects.filter(url=url) ownerships = M.Ownership.objects.select_related( "source", "ensemble", "folder").filter(source__html5info__in=sources_info, deleted=False) #TODO: with django 1.9, you can use Q objects to OR two conditions #so instead of iterating to test below, just add .filter(Q(ensemble__memberships__user=UR.getUserId(req)) | Q(ensemble.allow_guest)) #then use UR.qs2dict as was done previously if not ownerships.exists(): return UR.prepare_response({}, 1, "this URL is not recognized: ") output = {"files": {}, "ensembles": {}, "folders": {}} for r in ownerships: if (r.ensemble.allow_guest or auth.isMember(UR.getUserId(req), r.ensemble_id)): output["ensembles"][r.ensemble_id] = UR.model2dict( r, annotations.__NAMES["ensembles2"]) output["files"][r.source_id] = UR.model2dict( r, annotations.__NAMES["files2"]) output["folders"][r.folder_id] = UR.model2dict( r, annotations.__NAMES["folders2"]) if (output["ensembles"]): return UR.prepare_response(output) else: return UR.prepare_response( {}, 1, "not allowed: guest access isn't allowed for this file.")
def set_grade_assignment(P, req): uid = UR.getUserId(req) if not auth.canGrade(uid, P["id_source"], P["id_user"]): return UR.prepare_response({}, 1, "NOT ALLOWED") retval = {} retval["grades"] = annotations.set_grade_assignment(uid, {"id_source": P["id_source"], "id_user": P["id_user"], "grade": P["grade"]}) return UR.prepare_response(retval)
def get_stats_ensemble(payload, req): uid = UR.getUserId(req) id_ensemble = payload["id_ensemble"] if not auth.canSeeGrades(uid, id_ensemble): return UR.prepare_response({}, 1, "NOT ALLOWED") retval = annotations.get_stats_ensemble(payload) return UR.prepare_response(retval)
def set_location_section(P, req): uid = UR.getUserId(req) if not auth.canAdministrateLocation(uid, P["id_location"]): return UR.prepare_response({}, 1, "NOT ALLOWED") result = annotations.setLocationSection(P["id_location"], P["id_section"]) locations, html5locations = annotations.getLocation(result.pk) return UR.prepare_response( locations )
def get_class_settings(payload, req): uid = UR.getUserId(req) if "id_ensemble" in payload: if auth.canGetMembers(uid, payload["id_ensemble"]): class_settings = annotations.get_class_settings(uid, payload) return UR.prepare_response(class_settings) return UR.prepare_response({}, 1, "NOT ALLOWED")
def update_ensemble(P, req): uid = UR.getUserId(req) eid = P["id_ensemble"] if uid is None or eid is None: return UR.prepare_response({}, 1, "NOT ALLOWED") ensemble = M.Ensemble.objects.get(pk=eid) if "name" in P: ensemble.name = P["name"] if "description" in P: ensemble.description = P["description"] if "allow_staffonly" in P: ensemble.allow_staffonly = P["allow_staffonly"] if "allow_anonymous" in P: ensemble.allow_anonymous = P["allow_anonymous"] if "allow_tag_private" in P: ensemble.allow_tag_private = P["allow_tag_private"] if "allow_guest" in P: ensemble.allow_guest = P["allow_guest"] if "use_invitekey" in P: ensemble.use_invitekey = P["use_invitekey"] if "allow_download" in P: ensemble.allow_download = P["allow_download"] if "allow_ondemand" in P: ensemble.allow_ondemand = P["allow_ondemand"] if "default_pause" in P: ensemble.default_pause = P["default_pause"] if "section_assignment" in P: ensemble.section_assignment = P["section_assignment"] if "metadata" in P: ensemble.metadata = P["metadata"] ensemble.save() return UR.prepare_response(annotations.get_class_settings(uid, {"id_ensemble":P["id_ensemble"]}))
def get_section_participants(payload, req): uid = UR.getUserId(req) if "id_ensemble" in payload: if auth.canGetMembers(uid, payload["id_ensemble"]): section_participants = annotations.get_section_participants(uid, payload) return UR.prepare_response(section_participants) return UR.prepare_response({}, 1, "NOT ALLOWED")
def deleteThread(payload, req): uid = UR.getUserId(req) if not auth.canDeleteThread(uid, payload["id_location"]): return UR.prepare_response({}, 1, "NOT ALLOWED") else: annotations.deleteThread(payload) return UR.prepare_response({"id_location": payload["id_location"]})
def saveNote(payload, req): uid = UR.getUserId(req) if not auth.canAnnotate(uid, payload["id_ensemble"]): return UR.prepare_response({}, 1, "NOT ALLOWED") payload["id_author"] = uid retval = {} a = annotations.addNote(payload) if len(a) == 0: return UR.prepare_response({}, 2, "DUPLICATE") tms = {} for mark in payload["marks"]: tm = M.ThreadMark() m_types = [c[0] for c in tm.TYPES if c[1]==mark] if len(m_types): #old clients may return types we don't have in DB so ignore them tm.type = m_types[0] tm.user_id = uid tm.comment=a[0] tm.location_id=tm.comment.location_id tm.save() tms[tm.id] = UR.model2dict(tm) retval["locations"], html5 = annotations.getLocation(a[0].location_id) if (html5 is not None): retval["html5locations"]=html5 retval["comments"] = {} retval["tags"] = {} for annotation in a: retval["comments"].update(annotations.getComment(annotation.id, uid)) retval["tags"].update(annotations.getTagsByComment(annotation.id)) retval["threadmarks"] = tms return UR.prepare_response(retval)
def save_settings(payload, req): uid = UR.getUserId(req) if uid is None: return UR.prepare_response({}, 1, "NOT ALLOWED") else: return UR.prepare_response( {"settings": annotations.save_settings(uid, payload)})
def set_location_section(P, req): uid = UR.getUserId(req) if not auth.canAdministrateLocation(uid, P["id_location"]): return UR.prepare_response({}, 1, "NOT ALLOWED") result = annotations.setLocationSection(P["id_location"], P["id_section"]) locations, html5locations = annotations.getLocation(result.pk) return UR.prepare_response(locations)
def getMembers(payload, req): uid = UR.getUserId(req) if "id_ensemble" in payload: if auth.canGetMembers(uid, payload["id_ensemble"]): return UR.prepare_response( annotations.get_members(payload["id_ensemble"])) return UR.prepare_response({}, 1, "NOT ALLOWED")
def serve_img(req, res, scale, id_source): #print "img request of page %s of file %s at res %s and scale %s w/ invite_key=%s and req=%s" % (req.GET["page"], id_file, res, scale, req.GET["invite_key"], req ) #TODO: check permissions. uid = UR.getUserId(req); if not auth.canReadFile(uid, id_source): return HttpResponse("Error: You don't have credentials to see this file %s " % (id_source,)) page = int(req.GET["page"])-1 page_str = settings.IMG_FMT_STRING % (page,) filename = req.META["PATH_INFO"].rstrip('/') filename = "%s_%s.png" % (filename, page_str) response = None try: response = serve(req, filename,settings.HTTPD_MEDIA_CACHE) return response except Http404: #let's generate on demand try: pdf_dir = "%s/%s" % (settings.HTTPD_MEDIA,settings.REPOSITORY_DIR) img_dir = "%s/%s" % (settings.HTTPD_MEDIA_CACHE,settings.CACHE_DIR) process_page(id_source, page, res, scale, pdf_dir, img_dir, settings.IMG_FMT_STRING) response = serve(req, filename,settings.HTTPD_MEDIA_CACHE) return response except Http404: basedir = dirname(dirname(dirname(abspath(__file__)))) #TODO: would be better to do a redirect to the not_available page f = open("%s/content/data/icons/png/not_available.png" % basedir) s = f.read() f.close() return HttpResponse(s)
def presearch(payload, req): #cid = req.getConnectionId() cid = UR.CID uid = UR.getUserId(req); id_search = annotations.save_presearch(cid, payload) output = annotations.presearch(uid, id_search, payload) #{"total": 130, "items": "blahblah"} return UR.prepare_response(output)
def delete_file(P, req): #this method is used to rename both files and folders. uid = UR.getUserId(req) f_auth = auth.canDeleteFile if P["item_type"]=="file" else auth.canDeleteFolder if not f_auth(uid, P["id"]): return UR.prepare_response({}, 1, "NOT ALLOWED") return UR.prepare_response({"id": annotations.delete_file(uid, P)}) #special form since file isn't in there anymore
def getHTML5Info(payload, req): if "url" not in payload: return UR.prepare_response({}, 1, "missing url !") url = payload["url"].partition("#")[0].rstrip("/") # remove hash part of the URL by default, as well as trailing slash. #TODO: use optional argument id_ensemble to disambiguate if provided. sources_info = M.HTML5Info.objects.filter(url=url) ownerships = M.Ownership.objects.select_related("source", "ensemble", "folder").filter(source__html5info__in=sources_info, deleted=False) #TODO: with django 1.9, you can use Q objects to OR two conditions #so instead of iterating to test below, just add .filter(Q(ensemble__memberships__user=UR.getUserId(req)) | Q(ensemble.allow_guest)) #then use UR.qs2dict as was done previously if not ownerships.exists(): return UR.prepare_response({}, 1, "this URL is not recognized: ") output = { "files": {}, "ensembles": {}, "folders": {} } for r in ownerships: if (r.ensemble.allow_guest or auth.isMember(UR.getUserId(req),r.ensemble_id)): output["ensembles"][r.ensemble_id]=UR.model2dict(r,annotations.__NAMES["ensembles2"]) output["files"][r.source_id]=UR.model2dict(r,annotations.__NAMES["files2"]) output["folders"][r.folder_id]=UR.model2dict(r,annotations.__NAMES["folders2"]) if (output["ensembles"]): return UR.prepare_response(output) else: return UR.prepare_response({}, 1, "not allowed: guest access isn't allowed for this file.")
def rename_file(P, req): #this method is used to rename both files and folders. uid = UR.getUserId(req) f_auth = auth.canRenameFile if P["item_type"]=="file" else auth.canRenameFolder if not f_auth(uid, P["id"]): return UR.prepare_response({}, 1, "NOT ALLOWED") return UR.prepare_response({P["item_type"]+"s": annotations.rename_file(uid, P)})
def serve_grades_spreadsheet(req, id_ensemble): uid = UR.getUserId(req) if not auth.canSeeGrades(uid, id_ensemble): return HttpResponse( "Error: You don't have credentials to see grades for class %s" % (id_ensemble, )) import xlwt wbk = xlwt.Workbook() #first, generate the sheets with comment, words, char counts: stats = add_count_sheets(id_ensemble, wbk) #now add a sheet for labeled comments if there are any: add_labeledcomments_sheet(uid, id_ensemble, wbk) #now add sheets for the social graph # FIXME: this is broken for ensemble 6010 on nb.mit.edu. Disabling for now. # https://github.com/nbproject/nbproject/issues/199 #add_socialgraph_sheets(id_ensemble, stats["users"], wbk) import datetime a = datetime.datetime.now() fn = "stats_%s_%04d%02d%02d_%02d%02d.xls" % (id_ensemble, a.year, a.month, a.day, a.hour, a.minute) wbk.save("/tmp/%s" % (fn, )) response = serve(req, fn, "/tmp/") os.remove("/tmp/%s" % (fn, )) response["Content-Type"] = 'application/vnd.ms-excel' response['Content-Disposition'] = "attachment; filename=%s" % (fn, ) return response
def saveNote(payload, req): uid = UR.getUserId(req) if not auth.canAnnotate(uid, payload["id_ensemble"]): return UR.prepare_response({}, 1, "NOT ALLOWED") payload["id_author"] = uid retval = {} a = annotations.addNote(payload) if len(a) == 0: return UR.prepare_response({}, 2, "DUPLICATE") tms = {} for mark in payload["marks"]: tm = M.ThreadMark() m_types = [c[0] for c in tm.TYPES if c[1] == mark] if len( m_types ): #old clients may return types we don't have in DB so ignore them tm.type = m_types[0] tm.user_id = uid tm.comment = a[0] tm.location_id = tm.comment.location_id tm.save() tms[tm.id] = UR.model2dict(tm) retval["locations"], html5 = annotations.getLocation(a[0].location_id) if (html5 is not None): retval["html5locations"] = html5 retval["comments"] = {} retval["tags"] = {} for annotation in a: retval["comments"].update(annotations.getComment(annotation.id, uid)) retval["tags"].update(annotations.getTagsByComment(annotation.id)) retval["threadmarks"] = tms return UR.prepare_response(retval)
def serve_img(req, res, scale, id_source): #print "img request of page %s of file %s at res %s and scale %s w/ invite_key=%s and req=%s" % (req.GET["page"], id_file, res, scale, req.GET["invite_key"], req ) #TODO: check permissions. uid = UR.getUserId(req) if not auth.canReadFile(uid, id_source): return HttpResponse( "Error: You don't have credentials to see this file %s " % (id_source, )) page = int(req.GET["page"]) - 1 page_str = settings.IMG_FMT_STRING % (page, ) filename = req.META["PATH_INFO"].rstrip('/') filename = "%s_%s.png" % (filename, page_str) response = None try: response = serve(req, filename, settings.HTTPD_MEDIA_CACHE) return response except Http404: #let's generate on demand try: pdf_dir = "%s/%s" % (settings.HTTPD_MEDIA, settings.REPOSITORY_DIR) img_dir = "%s/%s" % (settings.HTTPD_MEDIA_CACHE, settings.CACHE_DIR) process_page(id_source, page, res, scale, pdf_dir, img_dir, settings.IMG_FMT_STRING) response = serve(req, filename, settings.HTTPD_MEDIA_CACHE) return response except Http404: basedir = dirname(dirname(dirname(abspath(__file__)))) #TODO: would be better to do a redirect to the not_available page f = open("%s/content/data/icons/png/not_available.png" % basedir) s = f.read() f.close() return HttpResponse(s)
def update_ensemble(P, req): uid = UR.getUserId(req) eid = P["id_ensemble"] if uid is None or eid is None: return UR.prepare_response({}, 1, "NOT ALLOWED") ensemble = M.Ensemble.objects.get(pk=eid) if "name" in P: ensemble.name = P["name"] if "description" in P: ensemble.description = P["description"] if "allow_staffonly" in P: ensemble.allow_staffonly = P["allow_staffonly"] if "allow_anonymous" in P: ensemble.allow_anonymous = P["allow_anonymous"] if "allow_tag_private" in P: ensemble.allow_tag_private = P["allow_tag_private"] if "allow_guest" in P: ensemble.allow_guest = P["allow_guest"] if "use_invitekey" in P: ensemble.use_invitekey = P["use_invitekey"] if "allow_download" in P: ensemble.allow_download = P["allow_download"] if "allow_ondemand" in P: ensemble.allow_ondemand = P["allow_ondemand"] if "default_pause" in P: ensemble.default_pause = P["default_pause"] if "section_assignment" in P: ensemble.section_assignment = P["section_assignment"] if "metadata" in P: ensemble.metadata = P["metadata"] ensemble.save() return UR.prepare_response( annotations.get_class_settings(uid, {"id_ensemble": P["id_ensemble"]}))
def deleteNote(payload, req): uid = UR.getUserId(req) #print "trying to delete %s" %( payload["id_comment"],) if not auth.canDelete(uid, payload["id_comment"]): return UR.prepare_response({}, 1, "NOT ALLOWED") else: annotations.deleteNote(payload) return UR.prepare_response({"id_comment": payload["id_comment"] })
def add_folder(payload, req): uid = UR.getUserId(req) id_ensemble = payload["id_ensemble"] id_parent = payload["id_parent"] if not auth.canAddFolder(uid, id_ensemble, id_parent): return UR.prepare_response({}, 1, "NOT ALLOWED") id_folder = annotations.create_folder(id_ensemble, id_parent, payload["name"]) return UR.prepare_response(annotations.get_folders(uid, {"id": id_folder}))
def move_file(P, req): uid = UR.getUserId(req) f_auth = auth.canMoveFile if P[ "item_type"] == "file" else auth.canMoveFolder if not f_auth(uid, P["id"], P["dest"]): return UR.prepare_response({}, 1, "NOT ALLOWED") return UR.prepare_response( {P["item_type"] + "s": annotations.move_file(uid, P)})
def editNote(payload, req): uid = UR.getUserId(req) if not auth.canEdit(uid, payload["id_comment"]): return UR.prepare_response({}, 1, "NOT ALLOWED") else: annotations.editNote(payload) #no need to worry about threadmarks: they can't be changed from an "edit-mode" editor return UR.prepare_response({"comments": annotations.getComment(payload["id_comment"], uid)})
def get_section_participants(payload, req): uid = UR.getUserId(req) if "id_ensemble" in payload: if auth.canGetMembers(uid, payload["id_ensemble"]): section_participants = annotations.get_section_participants( uid, payload) return UR.prepare_response(section_participants) return UR.prepare_response({}, 1, "NOT ALLOWED")
def editPoll(payload, req): uid = UR.getUserId(req) if uid is None or ("id_poll" not in payload) or not annotations.canEditPoll( uid, payload["id_poll"]): return UR.prepare_response({}, 1, "NOT ALLOWED") annotations.editPoll(uid, payload) return UR.prepare_response({})
def getMyNotes(payload, req): uid = UR.getUserId(req) if uid is None or payload.get("query") not in __AVAILABLE_STATS: return UR.prepare_response({}, 1, "NOT ALLOWED") else: output= getattr(annotations, "get_comments_"+payload.get("query"))(uid, payload) #referer = None if "referer" not in req.META else req.META["referer"] #TODO annotations.addCollageHistory(uid, referer, query) return UR.prepare_response(output)
def getGuestFileInfo(payload, req): if "id_source" not in payload: return UR.prepare_response({}, 1, "missing id_source !") id_source = payload["id_source"] output = annotations.get_guestfileinfo(id_source) for i in output["ensembles"]: if not (output["ensembles"][i]["allow_guest"] or auth.isMember(UR.getUserId(req), i)): return UR.prepare_response({}, 1, "not allowed: guest access isn't allowed for this file.") return UR.prepare_response(output)
def bulk_import_annotations(P, req): uid = UR.getUserId(req) if not auth.canImportAnnotation(uid, P["from_source_id"], P["to_source_id"]): return UR.prepare_response({}, 1, "NOT ALLOWED") return UR.prepare_response( annotations.bulkImportAnnotations(P["from_source_id"], P["to_source_id"], P["locs_array"], P["import_type"]))
def get_location_info(payload, req): id = payload["id"] uid = UR.getUserId(req); #SACHA TODO: check I'm allowed to know this retval={} retval["locations"], retval["html5locations"] = annotations.getLocation(id) if "org" in payload: annotations.logDirectURL(uid, id, payload["org"]) return UR.prepare_response(retval)
def markNote(payload, req): uid = UR.getUserId(req) id_comment = payload["id_comment"] if not auth.canMark(uid,id_comment ): return UR.prepare_response({}, 1, "NOT ALLOWED") else: annotations.markNote(uid, payload); comments = annotations.getComment(id_comment,uid) p = {"locations":annotations.getLocation(comments[int(id_comment)]["ID_location"]), "marks": annotations.getMark(uid, payload), "comments": comments} return UR.prepare_response(p)
def getSectionsInfo(payload, req): uid = UR.getUserId(req) if "id_ensemble" not in payload: return UR.prepare_response({}, 1, "MISSING id_ensemble") id_ensemble = payload["id_ensemble"] if auth.canGetSectionsInfo(uid, id_ensemble): m = M.Membership.objects.filter(user__id=uid, ensemble__id=id_ensemble, deleted=False) output={"sections": UR.qs2dict(m[0].ensemble.section_set.all())}; return UR.prepare_response(output) return UR.prepare_response({}, 1, "NOT ALLOWED")
def approveNote(payload, req): uid = UR.getUserId(req) id_comment = payload["id_comment"] if not auth.canApprove(uid,id_comment ): return UR.prepare_response({}, 1, "NOT ALLOWED") else: annotations.approveNote(uid, payload); p = {"comments":annotations.getComment(id_comment,uid) } return UR.prepare_response(p) annotations.addApproveHistory(uid, payload)
def sendInvites(payload, req): from django.core import mail from django.core.mail import EmailMessage uid = UR.getUserId(req); id_ensemble = payload["id_ensemble"] id_section = payload.get("id_section", None) admin = 0 if "admin" not in payload else payload["admin"] if not auth.canSendInvite(uid,id_ensemble): return UR.prepare_response({}, 1, "NOT ALLOWED") #extract emails in a somewhat robust fashion (i.e. using several possible delimiters) emails = parseEntities(payload["to"], [",", "\n", " "]) #remove spurious stuff: strings that don't have an "@" and trailings "<" and ">" characters, #because some emails the following format: John Doe <*****@*****.**> emails = [o.replace("<", "").replace(">", "") for o in emails if "@" in o] logging.info("to: %s, extracted: %s" % (payload["to"], emails)) #add new users to DB w/ pending status connection = mail.get_connection() emailmessages = [] for email in emails: user = auth.user_from_email(email) password="" if user is None: ckey = "".join([ random.choice(string.ascii_letters+string.digits) for i in xrange(0,32)]) password = "".join([ random.choice(string.ascii_letters+string.digits) for i in xrange(0,4)]) user = auth.addUser(email, password, ckey) invite_key = "".join([ random.choice(string.ascii_letters+string.digits) for i in xrange(0,50)]) auth.addInvite(invite_key, user.id, id_ensemble, id_section, admin) link = "http://%s/confirm_invite?invite_key=%s" % (settings.HOSTNAME, invite_key,) ensemble = M.Ensemble.objects.get(pk=id_ensemble) p = { "name": ensemble.name, "description": ensemble.description, "link": link, "contact": user.firstname if user.firstname != None else user.email } if payload["msg"] != "": p["msg_perso"] = payload["msg"] # TODO: We still include the password in the e-mail, should we stop doing that? if password != "": p["password"] = password p["email"] = email msg = render_to_string("email/msg_invite",p) bcc = [] if settings.SMTP_CC_USER is None else (settings.SMTP_CC_USER,) e = EmailMessage("You're invited on the %s channel !" % (p["name"],), msg, settings.EMAIL_FROM, (email, ), bcc,connection=connection) emailmessages.append(e) #time.sleep(SLEEPTIME) #in order not to stress out the email server connection.send_messages(emailmessages) return UR.prepare_response({"msg": "Invite for %s sent to %s" % (ensemble.name, emails,)})
def editNote(payload, req): uid = UR.getUserId(req) if not auth.canEdit(uid, payload["id_comment"]): return UR.prepare_response({}, 1, "NOT ALLOWED") else: annotations.editNote(payload) #for mark in payload["marks"]: # annotations.markNote(uid, {"action": payload["marks"][mark], "id_comment": payload["id_comment"]}) return UR.prepare_response({"comments": annotations.getComment(payload["id_comment"], uid), "marks": annotations.getMark(uid,{"id_comment": payload["id_comment"]}) })
def markThread(payload, req): uid = UR.getUserId(req) id_location = payload["id_location"] if not auth.canMarkThread(uid,id_location ): return UR.prepare_response({}, 1, "NOT ALLOWED") else: mark = annotations.markThread(uid, payload); tms = {} tms[mark["id"]] = mark p = {"threadmarks": tms} return UR.prepare_response(p)
def get_comment_info(payload, req): id = int(payload["id"]) uid = UR.getUserId(req); #SACHA TODO: check I'm allowed to know this retval={} comments = annotations.getComment(id, uid) id_location = comments[id]["ID_location"] retval["comments"] = {id: {"ID": id, "ID_location": id_location}} #share only what's needed #print retval["comments"] retval["locations"] , retval["html5locations"] = annotations.getLocation( id_location) if "org" in payload: annotations.logDirectURL(uid, id, payload["org"]) return UR.prepare_response(retval)