Example #1
0
def sheet_node_api(request, sheet_id, node_id):
	if request.method == "GET":
		sheet_node = get_sheet_node(int(sheet_id),int(node_id))
		return jsonResponse(sheet_node, callback=request.GET.get("callback", None))

	if request.method == "POST":
		return jsonResponse({"error": "Unsupported HTTP method."})
Example #2
0
def export_to_drive(request, credential, sheet_id):
	"""
	Export a sheet to Google Drive.
	"""

	http = credential.authorize(httplib2.Http())
	service = build('drive', 'v3', http=http)

	sheet = get_sheet(sheet_id)
	if 'error' in sheet:
		return jsonResponse({'error': {'message': sheet["error"]}})

	file_metadata = {
		'name': strip_tags(sheet['title'].strip()),
		'mimeType': 'application/vnd.google-apps.document'
	}

	html_string = sheet_to_html_string(sheet)

	media = MediaIoBaseUpload(
		StringIO(html_string),
		mimetype='text/html',
		resumable=True)

	new_file = service.files().create(body=file_metadata,
									  media_body=media,
									  fields='webViewLink').execute()

	return jsonResponse(new_file)
Example #3
0
def generate_feedback(request):

    data = json.loads(request.POST.get('json', {}))

    fb_type = data.get('type', None)
    refs = data.get('refs', None)
    url = data.get('url', None)
    versions = data.get('currVersions', None)
    uid = data.get('uid', None)
    from_email = data.get('email', None)
    msg = data.get('msg', None)

    if not from_email:
        from_email = model.user_profile.UserProfile(id=uid).email

    if fb_type == "content_issue":
        to_email = "*****@*****.**"
        subject = "Correction from website - " + ' / '.join(refs)
        message_html = msg + "\n\n" + "refs: " + ' / '.join(refs) + "\n" + "versions: " + str(versions) + "\n\n" + "URL: " + url
    else:
        to_email = "*****@*****.**"
        subject = "Feedback from website - " + fb_type.replace("_"," ")
        message_html = msg + "\n\n" + "URL: " + url



    try:
        send_email(subject, message_html, from_email, to_email)
        return jsonResponse({"status": "ok"})
    except:
        return jsonResponse({"error": _("Sorry, there was an error.")})
Example #4
0
def file_upload(request, resize_image=True):
    from PIL import Image
    from tempfile import NamedTemporaryFile
    from sefaria.s3 import HostedFile
    if request.method == "POST":
        MAX_FILE_MB = 2
        MAX_FILE_SIZE = MAX_FILE_MB * 1024 * 1024
        MAX_FILE_DIMENSIONS = (1048, 1048)
        uploaded_file = request.FILES['file']
        if uploaded_file.size > MAX_FILE_SIZE:
            return jsonResponse({"error": "Uploaded files must be smaller than %dMB." % MAX_FILE_MB})
        name, extension = os.path.splitext(uploaded_file.name)
        with NamedTemporaryFile(suffix=extension) as temp_uploaded_file:
            temp_uploaded_file.write(uploaded_file.read())

            with NamedTemporaryFile(suffix=extension) as temp_resized_file:
                image = Image.open(temp_uploaded_file)
                if resize_image:
                    image.thumbnail(MAX_FILE_DIMENSIONS, Image.ANTIALIAS)
                image.save(temp_resized_file, optimize=True, quality=70)

                name, extension = os.path.splitext(temp_resized_file.name)
                hosted_file = HostedFile(filepath=temp_resized_file.name, content_type=uploaded_file.content_type)
                try:
                    url = hosted_file.upload()
                    return jsonResponse({"status": "success", "url": url})
                except:
                    return jsonResponse({"error": "There was an error uploading your file."})
    else:
        return jsonResponse({"error": "Unsupported HTTP method."})
Example #5
0
def groups_invite_api(request, group_name, uid_or_email, uninvite=False):
	"""
	API for adding or removing group members, or group invitations
	"""
	if request.method != "POST":
		return jsonResponse({"error": "Unsupported HTTP method."})
	group = Group().load({"name": group_name})
	if not group:
		return jsonResponse({"error": "No group named %s." % group_name})
	if request.user.id not in group.admins:
		return jsonResponse({"error": "You must be a group admin to invite new members."})

	user = UserProfile(email=uid_or_email)
	if not user.exists():
		if uninvite:
			group.remove_invitation(uid_or_email)
			message = "Invitation removed."
		else:
			group.invite_member(uid_or_email, request.user.id)
			message = "Invitation sent."
	else:
		is_new_member = not group.is_member(user.id)

		if is_new_member:
			group.add_member(user.id)
			from sefaria.model.notification import Notification
			notification = Notification({"uid": user.id})
			notification.make_group_add(adder_id=request.user.id, group_name=group_name)
			notification.save()
			message = "Group member added."
		else:
			message = "%s is already a member of this group." % user.full_name

	group_content = group.contents(with_content=True, authenticated=True)
	return jsonResponse({"group": group_content, "message": message})
Example #6
0
def user_sheet_list_api(request, user_id):
	"""
	API for listing the sheets that belong to user_id.
	"""
	if int(user_id) != request.user.id:
		return jsonResponse({"error": "You are not authorized to view that."})
	return jsonResponse(user_sheets(user_id), callback=request.GET.get("callback", None))
Example #7
0
def user_sheet_list_api_with_sort(request, user_id, sort_by="date", limiter=0, offset=0):
	limiter  = int(limiter)
	offset   = int(offset)

	if int(user_id) != request.user.id:
		return jsonResponse({"error": "You are not authorized to view that."})
	return jsonResponse(user_sheets(user_id, sort_by, limit=limiter, skip=offset), callback=request.GET.get("callback", None))
Example #8
0
def sheet_list_api(request):
	"""
	API for listing available sheets
	"""
	if request.method == "GET":
		return jsonResponse(sheet_list(), callback=request.GET.get("callback", None))

	# Save a sheet
	if request.method == "POST":
		if not request.user.is_authenticated():
			return jsonResponse({"error": "You must be logged in to save."})
		
		j = request.POST.get("json")
		if not j:
			return jsonResponse({"error": "No JSON given in post data."})
		sheet = json.loads(j)
		if "id" in sheet:
			existing = get_sheet(sheet["id"])
			if "error" not in existing  and \
				not can_edit(request.user, existing) and \
				not can_add(request.user, existing):
				
				return jsonResponse({"error": "You don't have permission to edit this sheet."})
		
		responseSheet = save_sheet(sheet, request.user.id)
		if "rebuild" in responseSheet and responseSheet["rebuild"]:
			# Don't bother adding user links if this data won't be used to rebuild the sheet
			responseSheet["sources"] = annotate_user_links(responseSheet["sources"])

		return jsonResponse(responseSheet)
Example #9
0
def add_ref_to_sheet_api(request, sheet_id):
	"""
	API to add a source to a sheet using only a ref.
	"""
	ref = request.POST.get("ref")
	if not ref:
		return jsonResponse({"error": "No ref given in post data."})
	return jsonResponse(add_ref_to_sheet(int(sheet_id), ref))
Example #10
0
def add_source_to_sheet_api(request, sheet_id):
	"""
	API to add a fully formed source (posted as JSON) to sheet_id.
	"""
	source = json.loads(request.POST.get("source"))
	if not source:
		return jsonResponse({"error": "No source to copy given."})
	return jsonResponse(add_source_to_sheet(int(sheet_id), source))
Example #11
0
def add_source_to_sheet_api(request, sheet_id):
	"""
	API to add a fully formed source (posted as JSON) to sheet_id.

	The contents of the "source" field will be a dictionary.
	The input format is similar to, but differs slightly from, the internal format for sources on source sheets.
	This method reformats the source to the format expected by add_source_to_sheet().

	Fields of input dictionary:
		either `refs` - an array of string refs, indicating a range
			or `ref` - a string ref
			or `outsideText` - a string
			or `outsideBiText` - a dictionary with string fields "he" and "en"
			or `comment` - a string
			or `media` - a URL string

		If the `ref` or `refs` fields are present, the `version`, `he` or `en` fields
		can further specify the origin or content of text for that ref.

	"""
	source = json.loads(request.POST.get("source"))
	if not source:
		return jsonResponse({"error": "No source to copy given."})

	if "refs" in source and source["refs"]:
		ref = Ref(source["refs"][0]).to(Ref(source["refs"][-1]))
		source["ref"] = ref.normal()
		del source["refs"]

	if "ref" in source and source["ref"]:
		ref = Ref(source["ref"])
		source["heRef"] = ref.he_normal()

		if "version" in source or "en" in source or "he" in source:
			text = {}
			if "en" in source:
				text["en"] = source["en"]
				tc = TextChunk(ref, "he", source["version"]) if source.get("versionLanguage") == "he" else TextChunk(ref, "he")
				text["he"] = tc.ja().flatten_to_string()
				del source["en"]
			elif "he" in source:
				text["he"] = source["he"]
				tc = TextChunk(ref, "en", source["version"]) if source.get("versionLanguage") == "en" else TextChunk(ref, "en")
				text["en"] = tc.ja().flatten_to_string()
				del source["he"]
			else:  # "version" in source
				text[source["versionLanguage"]] = TextChunk(ref, source["versionLanguage"], source["version"]).ja().flatten_to_string()
				other = "he" if source["versionLanguage"] == "en" else "en"
				text[other] = TextChunk(ref, other).ja().flatten_to_string()
			source.pop("version", None)
			source.pop("versionLanguage", None)
			source["text"] = text


	note = request.POST.get("note", None)
	response = add_source_to_sheet(int(sheet_id), source, note=note)

	return jsonResponse(response)
Example #12
0
def private_sheet_list_api(request, partner):
	partner = partner.replace("-", " ").replace("_", " ")
	group   = Group().load({"name": partner})
	if not group:
		raise Http404
	if request.user.is_authenticated() and group.name in [g.name for g in request.user.groups.all()]:
		return jsonResponse(partner_sheets(partner, True), callback=request.GET.get("callback", None))
	else:
		return jsonResponse(partner_sheets(partner, False), callback=request.GET.get("callback", None))
Example #13
0
def copy_source_to_sheet_api(request, sheet_id):
	"""
	API to copy a source from one sheet to another. 
	"""
	copy_sheet = request.POST.get("sheet")
	copy_source = request.POST.get("source")
	if not copy_sheet and copy_source:
		return jsonResponse({"error": "Need both a sheet and source number to copy."})
	return jsonResponse(copy_source_to_sheet(int(sheet_id), int(copy_sheet), int(copy_source)))
Example #14
0
def private_sheet_list_api(request, group):
	group = group.replace("-", " ").replace("_", " ")
	group   = Group().load({"name": group})
	if not group:
		raise Http404
	if request.user.is_authenticated and group.is_member(request.user.id):
		return jsonResponse(group_sheets(group, True), callback=request.GET.get("callback", None))
	else:
		return jsonResponse(group_sheets(group, False), callback=request.GET.get("callback", None))
Example #15
0
def sheet_api(request, sheet_id):
	"""
	API for accessing and individual sheet.
	"""
	if request.method == "GET":
		sheet = get_sheet(int(sheet_id))
		return jsonResponse(sheet, callback=request.GET.get("callback", None))

	if request.method == "POST":
		return jsonResponse({"error": "TODO - save to sheet by id"})
Example #16
0
def unlike_sheet_api(request, sheet_id):
	"""
	API to unlike sheet_id.
	"""
	if not request.user.is_authenticated:
		return jsonResponse({"error": "You must be logged in to like sheets."})
	if request.method != "POST":
		return jsonResponse({"error": "Unsupported HTTP method."})

	remove_like_from_sheet(int(sheet_id), request.user.id)
	return jsonResponse({"status": "ok"})
Example #17
0
def add_source_to_sheet_api(request, sheet_id):
	"""
	API to add a fully formed source (posted as JSON) to sheet_id.
	"""
	source = json.loads(request.POST.get("source"))
	if not source:
		return jsonResponse({"error": "No source to copy given."})
	if "refs" in source:
		source["ref"] = Ref(source["refs"][0]).to(Ref(source["refs"][-1])).normal()
		del source["refs"]
	return jsonResponse(add_source_to_sheet(int(sheet_id), source))
Example #18
0
def get_aliyot_by_parasha_api(request, parasha):
	response = {"ref":[]};

	if parasha == "V'Zot HaBerachah":
		return jsonResponse({"ref":["Deuteronomy 33:1-7","Deuteronomy 33:8-12","Deuteronomy 33:13-17","Deuteronomy 33:18-21","Deuteronomy 33:22-26","Deuteronomy 33:27-29","Deuteronomy 34:1-12"]}, callback=request.GET.get("callback", None))

	else:
		p = db.parshiot.find({"parasha": parasha}, limit=1).sort([("date", 1)])
		p = p.next()

		for aliyah in p["aliyot"]:
			response["ref"].append(aliyah)
		return jsonResponse(response, callback=request.GET.get("callback", None))
Example #19
0
def visual_sheet_api(request, sheet_id):
	"""
	API for visual source sheet layout
	"""
	if not request.user.is_authenticated:
		return {"error": "You must be logged in to save a sheet layout."}
	if request.method != "POST":
		return jsonResponse({"error": "Unsupported HTTP method."})

	visualNodes = json.loads(request.POST.get("visualNodes"))
	zoomLevel =  json.loads(request.POST.get("zoom"))
	add_visual_data(int(sheet_id), visualNodes, zoomLevel)
	return jsonResponse({"status": "ok"})
Example #20
0
def groups_pin_sheet_api(request, group_name, sheet_id):
	if request.method != "POST":
		return jsonResponse({"error": "Unsupported HTTP method."})
	group = Group().load({"name": group_name})
	if not group:
		return jsonResponse({"error": "No group named %s." % group_name})
	if request.user.id not in group.admins:
		return jsonResponse({"error": "You must be a group admin to invite new members."})

	sheet_id = int(sheet_id)
	group.pin_sheet(sheet_id)
	group_content = group.contents(with_content=True, authenticated=True)
	return jsonResponse({"group": group_content, "status": "success"})
Example #21
0
def copy_source_to_sheet_api(request, sheet_id):
	"""
	API to copy a source from one sheet to another.
	"""
	copy_sheet = request.POST.get("sheetID")
	copy_source = request.POST.get("nodeID")
	if not copy_sheet and copy_source:
		return jsonResponse({"error": "Need both a sheet and source node ID to copy."})

	source = get_sheet_node(int(copy_sheet), int(copy_source))
	del source["node"]
	response = add_source_to_sheet(int(sheet_id), source)

	return jsonResponse(response)
Example #22
0
def subscribe(request, email):
    """
    API for subscribg is mailing lists, in `lists` url param.
    Currently active lists are:
    "Announcements_General", "Announcements_General_Hebrew", "Announcements_Edu", "Announcements_Edu_Hebrew"
    """
    lists = request.GET.get("lists", "")
    lists = lists.split("|")
    if len(lists) == 0:
        return jsonResponse({"error": "Please specifiy a list."})
    if subscribe_to_list(lists + ["Newsletter_Sign_Up"], email, direct_sign_up=True):
        return jsonResponse({"status": "ok"})
    else:
        return jsonResponse({"error": _("Sorry, there was an error.")})
Example #23
0
def sheet_api(request, sheet_id):
	"""
	API for accessing and individual sheet.
	"""
	if request.method == "GET":
		more_data = request.GET.get('more_data', '0')
		if more_data == '1':
			sheet = get_sheet_for_panel(int(sheet_id))
		else:
			sheet = get_sheet(int(sheet_id))
		return jsonResponse(sheet, callback=request.GET.get("callback", None))

	if request.method == "POST":
		return jsonResponse({"error": "TODO - save to sheet by id"})
Example #24
0
def groups_api(request, group=None):
	if request.method == "GET":
		if not group:
			return jsonResponse({
				"private": [g.listing_contents() for g in GroupSet().for_user(request.user.id)],
				"public": [g.listing_contents() for g in GroupSet({"listed": True, "moderationStatus": {"$ne": "nolist"}}, sort=[("name", 1)])]
			})
		group = Group().load({"name": group})
		if not group:
			return jsonResponse({"error": "No group named '%s'" % group})
		is_member = request.user.is_authenticated and group.is_member(request.user.id)
		group_content = group.contents(with_content=True, authenticated=is_member)
		return jsonResponse(group_content)
	else:
		return groups_post_api(request, group_name=group)
Example #25
0
def delete_sheet_api(request, sheet_id):
	"""
	Deletes sheet with id, only if the requester is the sheet owner. 
	"""
	id = int(sheet_id)
	sheet = db.sheets.find_one({"id": id})
	if not sheet:
		return jsonResponse({"error": "Sheet %d not found." % id})

	if request.user.id != sheet["owner"]:
		return jsonResponse({"error": "Only the sheet owner may delete a sheet."})

	db.sheets.remove({"id": id})

	return jsonResponse({"status": "ok"})
Example #26
0
def text_upload_api(request):
    if request.method != "POST":
        return jsonResponse({"error": "Unsupported Method: {}".format(request.method)})

    from sefaria.export import import_versions_from_stream
    message = ""
    files = request.FILES.getlist("texts[]")
    for f in files:
        try:
            import_versions_from_stream(f, [1], request.user.id)
            message += "Imported: {}.  ".format(f.name)
        except Exception as e:
            return jsonResponse({"error": e.message, "message": message})

    message = "Successfully imported {} versions".format(len(files))
    return jsonResponse({"status": "ok", "message": message})
Example #27
0
def cache_stats(request):
    import resource
    resp = {
        'ref_cache_size': model.Ref.cache_size(),
        'memory usage': resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
    }
    return jsonResponse(resp)
Example #28
0
 def wrapper(*args, **kwargs):
     try:
         result = func(*args, **kwargs)
     except exps.InputError as e:
         logger.warning(u"An exception occurred while running {}. Caught as JSON".format(func.__name__), exc_info=True)
         return jsonResponse({"error": unicode(e)})
     return result
Example #29
0
def all_sheets_api(request, limiter, offset=0):
	limiter  = int(limiter)
	offset   = int(offset)
	response = public_sheets(limit=limiter, skip=offset)
	response = jsonResponse(response, callback=request.GET.get("callback", None))
	response["Cache-Control"] = "max-age=3600"
	return response
Example #30
0
def bulktext_api(request, refs):
    """
    Used by the linker.
    :param request:
    :param refs:
    :return:
    """
    if request.method == "GET":
        cb = request.GET.get("callback", None)
        refs = set(refs.split("|"))
        res = {}
        for tref in refs:
            try:
                oref = model.Ref(tref)
                lang = "he" if is_hebrew(tref) else "en"
                he = model.TextChunk(oref, "he").text
                en = model.TextChunk(oref, "en").text
                res[tref] = {
                    'he': he if isinstance(he, basestring) else JaggedTextArray(he).flatten_to_string(),  # these could be flattened on the client, if need be.
                    'en': en if isinstance(en, basestring) else JaggedTextArray(en).flatten_to_string(),
                    'lang': lang,
                    'ref': oref.normal(),
                    'heRef': oref.he_normal(),
                    'url': oref.url()
                }
            except (InputError, ValueError, AttributeError) as e:
                referer = request.META.get("HTTP_REFERER", "unknown page")
                logger.warning(u"Linker failed to parse {} from {} : {}".format(tref, referer, e))
                res[tref] = {"error": 1}
        resp = jsonResponse(res, cb)
        resp['Access-Control-Allow-Origin'] = '*'
        return resp
Example #31
0
def groups_post_api(request, user_id, group_name=None):
    if request.method == "POST":
        j = request.POST.get("json")
        if not j:
            return jsonResponse({"error": "No JSON given in post data."})
        group = json.loads(j)
        existing = Group().load({"name": group.get("previousName", group["name"])})
        if existing:
            # Don't overwrite existing group when posting to create a new group
            if "new" in group:
                return jsonResponse({"error": "A group with this name already exists."})
            # check poster is a group admin
            if user_id not in existing.admins:
                return jsonResponse({"error": "You do not have permission to edit this group."})

            existing.load_from_dict(group)
            existing.save()
        else:
            del group["new"]
            group["admins"] = [user_id]
            group["publishers"] = []
            group["members"] = []
            Group(group).save()
        return jsonResponse({"status": "ok"})

    elif request.method == "DELETE":
        if not group_name:
            return jsonResponse({"error": "Please specify a group name in the URL."})
        existing = Group().load({"name": group_name})
        if existing:
            if user_id not in existing.admins:
                return jsonResponse({"error": "You do not have permission to delete this group."})
            else:
                GroupSet({"name": group_name}).delete()
                return jsonResponse({"status": "ok"})
        else:
            return jsonResponse({"error": "Group named %s does not exist" % group_name})

    else:
        return jsonResponse({"error": "Unsupported HTTP method."})
Example #32
0
def bulktext_api(request, refs):
    """
    Used by the linker.
    :param request:
    :param refs:
    :return:
    """
    if request.method == "GET":
        cb = request.GET.get("callback", None)
        refs = set(refs.split("|"))
        g = lambda x: request.GET.get(x, None)
        min_char = int(g("minChar")) if g("minChar") else None
        max_char = int(g("maxChar")) if g("maxChar") else None
        res = bundle_many_texts(refs, g("useTextFamily"), g("asSizedString"), min_char, max_char)
        resp = jsonResponse(res, cb)
        return resp
Example #33
0
def cache_stats(request):
    import resource
    from sefaria.utils.util import get_size
    from sefaria.model.user_profile import public_user_data_cache
    # from sefaria.sheets import last_updated
    resp = {
        'ref_cache_size': f'{model.Ref.cache_size():,}',
        # 'ref_cache_bytes': model.Ref.cache_size_bytes(), # This pretty expensive, not sure if it should run on prod.
        'public_user_data_size': f'{len(public_user_data_cache):,}',
        'public_user_data_bytes': f'{get_size(public_user_data_cache):,}',
        # 'sheets_last_updated_size': len(last_updated),
        # 'sheets_last_updated_bytes': get_size(last_updated),
        'memory usage':
        f'{resource.getrusage(resource.RUSAGE_SELF).ru_maxrss:,}'
    }
    return jsonResponse(resp)
Example #34
0
def bulktext_api(request, refs):
    """
    Used by the linker.
    :param request:
    :param refs:
    :return:
    """
    if request.method == "GET":
        cb = request.GET.get("callback", None)
        useTextFamily = request.GET.get("useTextFamily", None)
        refs = set(refs.split("|"))
        res = {}
        for tref in refs:
            try:
                oref = model.Ref(tref)
                lang = "he" if is_hebrew(tref) else "en"
                if useTextFamily:
                    text_fam = model.TextFamily(oref, commentary=0, context=0, pad=False)
                    he = text_fam.he
                    en = text_fam.text
                    res[tref] = {
                        'he': he,
                        'en': en,
                        'lang': lang,
                        'ref': oref.normal(),
                        'primary_category': text_fam.contents()['primary_category'],
                        'heRef': oref.he_normal(),
                        'url': oref.url()
                    }
                else:
                    he = model.TextChunk(oref, "he").text
                    en = model.TextChunk(oref, "en").text
                    res[tref] = {
                        'he': he if isinstance(he, basestring) else JaggedTextArray(he).flatten_to_string(),  # these could be flattened on the client, if need be.
                        'en': en if isinstance(en, basestring) else JaggedTextArray(en).flatten_to_string(),
                        'lang': lang,
                        'ref': oref.normal(),
                        'heRef': oref.he_normal(),
                        'url': oref.url()
                    }
            except (InputError, ValueError, AttributeError, KeyError) as e:
                # referer = request.META.get("HTTP_REFERER", "unknown page")
                # This chatter fills up the logs.  todo: put in it's own file
                # logger.warning(u"Linker failed to parse {} from {} : {}".format(tref, referer, e))
                res[tref] = {"error": 1}
        resp = jsonResponse(res, cb)
        return resp
Example #35
0
def collections_post_api(request, user_id, slug=None):
    if request.method == "POST":
        j = request.POST.get("json")
        if not j:
            return jsonResponse({"error": "No JSON given in post data."})
        collection_data = json.loads(j)
        if "slug" in collection_data:
            collection = Collection().load({"slug": collection_data["slug"]})
            if not collection:
                return jsonResponse({"error": "Collection with slug `{}` not found.".format(collection["slug"])})
            # check poster is a collection admin
            if user_id not in collection.admins:
                return jsonResponse({"error": "You do not have permission to edit this collection."})

            collection.load_from_dict(collection_data)
            collection.save()
        else:
            collection_data["admins"] = [user_id]
            collection = Collection(collection_data)
            collection.save()
        return jsonResponse({"status": "ok", "collection": collection.listing_contents(request.user.id)})

    elif request.method == "DELETE":
        if not slug:
            return jsonResponse({"error": "Please specify a collection in the URL."})
        existing = Collection().load({"slug": slug})
        if existing:
            if user_id not in existing.admins:
                return jsonResponse({"error": "You do not have permission to delete this collection."})
            else:
                CollectionSet({"slug": slug}).delete()
                return jsonResponse({"status": "ok"})
        else:
            return jsonResponse({"error": "Collection with the slug `{}` does not exist".format(slug)})

    else:
        return jsonResponse({"error": "Unsupported HTTP method."})
Example #36
0
def title_regex_api(request, titles):
    if request.method == "GET":
        cb = request.GET.get("callback", None)
        titles = set(titles.split("|"))
        res = {}
        errors = []
        for title in titles:
            lang = "he" if is_hebrew(title) else "en"
            try:
                re_string = model.library.get_regex_string(title, lang, anchored=False, for_js=True)
                res[title] = re_string
            except (AttributeError, AssertionError) as e:
                # There are normal errors here, when a title matches a schema node, the chatter fills up the logs.
                # logger.warning(u"Library._build_ref_from_string() failed to create regex for: {}.  {}".format(title, e))
                errors.append(u"{} : {}".format(title, e))
        if len(errors):
            res["error"] = errors
        resp = jsonResponse(res, cb)
        return resp
Example #37
0
def title_regex_api(request, titles):
    if request.method == "GET":
        cb = request.GET.get("callback", None)
        titles = set(titles.split("|"))
        res = {}
        errors = []
        for title in titles:
            lang = "he" if is_hebrew(title) else "en"
            try:
                re_string = model.library.get_regex_string(title, lang, for_js=True)
                res[title] = re_string
            except (AttributeError, AssertionError) as e:
                logger.warning(u"Library._build_ref_from_string() failed to create regex for: {}.  {}".format(title, e))
                errors.append(u"{} : {}".format(title, e))
        if len(errors):
            res["error"] = errors
        resp = jsonResponse(res, cb)
        resp['Access-Control-Allow-Origin'] = '*'
        return resp
Example #38
0
def bulktext_api(request, refs):
    """
    Used by the linker.
    :param request:
    :param refs:
    :return:
    """
    if request.method == "GET":
        cb = request.GET.get("callback", None)
        refs = set(refs.split("|"))
        res = {}
        for tref in refs:
            try:
                oref = model.Ref(tref)
                lang = "he" if is_hebrew(tref) else "en"
                he = model.TextChunk(oref, "he").text
                en = model.TextChunk(oref, "en").text
                res[tref] = {
                    'he':
                    he if isinstance(he, basestring) else
                    JaggedTextArray(he).flatten_to_string(
                    ),  # these could be flattened on the client, if need be.
                    'en':
                    en if isinstance(en, basestring) else
                    JaggedTextArray(en).flatten_to_string(),
                    'lang':
                    lang,
                    'ref':
                    oref.normal(),
                    'heRef':
                    oref.he_normal(),
                    'url':
                    oref.url()
                }
            except (InputError, ValueError, AttributeError) as e:
                referer = request.META.get("HTTP_REFERER", "unknown page")
                logger.warning(
                    u"Linker failed to parse {} from {} : {}".format(
                        tref, referer, e))
                res[tref] = {"error": 1}
        resp = jsonResponse(res, cb)
        resp['Access-Control-Allow-Origin'] = '*'
        return resp
Example #39
0
def profile_spam_dashboard(request):

    from django.contrib.auth.models import User

    if request.method == 'POST':
        return jsonResponse({"error": "Unsupported Method: {}".format(request.method)})

    else:
        date = request.GET.get("date", None)

        if date:
            date = datetime.strptime(date, '%Y-%m-%d')

        else:
            date = request.GET.get("date", datetime.now() - timedelta(days=30))

        earliest_new_user_id = User.objects.filter(date_joined__gte=date).order_by('date_joined')[0].id

        regex = r'.*(?!href=[\'"](\/|http(s)?:\/\/(www\.)?sefaria).+[\'"])(href).*'

        users_to_check = db.profiles.find(
            {'$or': [
                {'website': {"$ne": ""}, 'bio': {"$ne": ""}, "id": {"$gt": earliest_new_user_id},
                      "reviewed": {"$ne": True}},
                {'bio': {"$regex": regex}, "id": {"$gt": earliest_new_user_id}, "reviewed": {"$ne": True}}
            ]
        })



        profiles_list = []

        for user in users_to_check:
            history_count = db.user_history.find({'uid': user['id']}).count()
            if history_count < 10:
                profiles_list.append({"id": user["id"], "slug": user["slug"], "bio": strip_tags(user["bio"][0:250]), "website": user["website"][0:50]})

        return render_template(request, 'spam_dashboard.html', None, {
            "title": "Potential Spam Profiles since %s" % date.strftime("%Y-%m-%d"),
            "profiles": profiles_list,
            "type": "profile",
        })
Example #40
0
def sheets_by_tag_api(request, tag):
    """
	API to retrieve the list of peopke who like sheet_id.
	"""
    sheets = get_sheets_by_tag(tag, public=True)
    sheets = [{
        "title": s["title"],
        "id": s["id"],
        "owner": s["owner"],
        "views": s["views"]
    } for s in sheets]
    for sheet in sheets:
        profile = UserProfile(id=sheet["owner"])
        sheet["ownerName"] = profile.full_name
        sheet["ownerImageUrl"] = profile.gravatar_url_small
    response = {"tag": tag, "sheets": sheets}
    response = jsonResponse(response,
                            callback=request.GET.get("callback", None))
    response["Cache-Control"] = "max-age=3600"
    return response
Example #41
0
def sheet_list_api(request):
	"""
	API for listing available sheets
	"""
	if request.method == "GET":
		return jsonResponse(sheet_list(), callback=request.GET.get("callback", None))

	# Save a sheet
	if request.method == "POST":
		if not request.user.is_authenticated():
			key = request.POST.get("apikey")
			if not key:
				return jsonResponse({"error": "You must be logged in or use an API key to save."})
			apikey = db.apikeys.find_one({"key": key})
			if not apikey:
				return jsonResponse({"error": "Unrecognized API key."})
		else:
			apikey = None

		j = request.POST.get("json")
		if not j:
			return jsonResponse({"error": "No JSON given in post data."})
		sheet = json.loads(j)

		if apikey:
			if "id" in sheet:
				sheet["lastModified"] = get_sheet(sheet["id"])["dateModified"] # Usually lastModified gets set on the frontend, so we need to set it here to match with the previous dateModified so that the check in `save_sheet` returns properly
			user = User.objects.get(id=apikey["uid"])
		else:
			user = request.user

		if "id" in sheet:
			existing = get_sheet(sheet["id"])
			if "error" not in existing  and \
				not can_edit(user, existing) and \
				not can_add(request.user, existing):

				return jsonResponse({"error": "You don't have permission to edit this sheet."})

		if "group" in sheet:
			if sheet["group"] not in [group.name for group in user.groups.all()]:
				sheet["group"] = None

		responseSheet = save_sheet(sheet, user.id)
		if "rebuild" in responseSheet and responseSheet["rebuild"]:
			# Don't bother adding user links if this data won't be used to rebuild the sheet
			responseSheet["sources"] = annotate_user_links(responseSheet["sources"])

		return jsonResponse(responseSheet)
Example #42
0
def collections_inclusion_api(request, slug, action, sheet_id):
    """
    API for adding or removing a sheet from a collection
    """
    if request.method != "POST":
        return jsonResponse({"error": "Unsupported HTTP method."})
    collection = Collection().load({"slug": slug})
    if not collection:
        return jsonResponse({"error": "No collection with slug `{}`.".format(slug)})
    if not collection.is_member(request.user.id):
        return jsonResponse({"error": "Only members of this collection my change its contents."})
    sheet_id = int(sheet_id)
    sheet = db.sheets.find_one({"id": sheet_id})
    if not sheet:
        return jsonResponse({"error": "No sheet with id {}.".format(sheet_id)})

    if action == "remove":
        if sheet_id in collection.sheets:
            collection.sheets.remove(sheet_id)
            if request.user.id == sheet["owner"] and sheet.get("displayedCollection", None) == collection.slug:
                sheet["displayedCollection"] = None
                db.sheets.find_one_and_replace({"id": sheet["id"]}, sheet)
        else:
            return jsonResponse({"error": "Sheet with id {} is not in this collection.".format(sheet_id)})
    if action == "add":
        if sheet_id not in collection.sheets:
            collection.sheets.append(sheet_id)
            # If a sheet's owner adds it to a collection, and the sheet is not highlighted
            # in another collection, set it to highlight this collection.
            if request.user.id == sheet["owner"] and not sheet.get("displayedCollection", None):
                sheet["displayedCollection"] = collection.slug
                db.sheets.find_one_and_replace({"id": sheet["id"]}, sheet)

    collection.save()
    is_member = request.user.is_authenticated and collection.is_member(request.user.id)
    sheet = get_sheet_for_panel(int(sheet_id))
    sheet_listing = annotate_user_collections([sheet_to_dict(sheet)], request.user.id)[0]
    return jsonResponse({
        "status": "ok",
        "action": action,
        "collectionListing": collection.listing_contents(request.user.id),
        "collection": collection.contents(with_content=True, authenticated=is_member),
        "sheet": sheet,
        "sheetListing": sheet_listing,
    })
Example #43
0
def collections_role_api(request, slug, uid, role):
    """
    API for setting a collection members role, or removing them from a collection.
    """
    if request.method != "POST":
        return jsonResponse({"error": "Unsupported HTTP method."})
    collection = Collection().load({"slug": slug})
    if not collection:
        return jsonResponse(
            {"error": "No collection with slug `{}`.".format(slug)})
    uid = int(uid)
    if request.user.id not in collection.admins:
        if not (uid == request.user.id
                and role == "remove"):  # non admins can remove themselves
            return jsonResponse({
                "error":
                "You must be a collection owner to change contributor roles."
            })
    user = UserProfile(id=uid)
    if not user.exists():
        return jsonResponse({"error": "No user with the specified ID exists."})
    if role not in ("member", "publisher", "admin", "remove"):
        return jsonResponse({"error": "Unknown collection contributor role."})
    if uid == request.user.id and collection.admins == [request.user.id
                                                        ] and role != "admin":
        return jsonResponse({
            "error":
            _("Leaving this collection would leave it without any owners. Please appoint another owner before leaving, or delete the collection."
              )
        })
    if role == "remove":
        collection.remove_member(uid)
    else:
        collection.add_member(uid, role)

    collection_content = collection.contents(with_content=True,
                                             authenticated=True)
    return jsonResponse(collection_content)
Example #44
0
def sheet_list_api(request):
    """
	API for listing available sheets
	"""
    if request.method == "GET":
        return jsonResponse(sheet_list(),
                            callback=request.GET.get("callback", None))

    # Save a sheet
    if request.method == "POST":
        if not request.user.is_authenticated():
            return jsonResponse({"error": "You must be logged in to save."})

        j = request.POST.get("json")
        if not j:
            return jsonResponse({"error": "No JSON given in post data."})
        sheet = json.loads(j)

        #Temp code to throw error in case someone has old sourcesheet code running in browser when backend migration from subsources to indent occurs
        #Todo remove me by 3/21/16
        if "sources" in sheet:
            if "subsources" in sheet["sources"]:
                return jsonResponse({
                    "error":
                    "There's been an error. Please refresh the page."
                })

        if "id" in sheet:
            existing = get_sheet(sheet["id"])
            if "error" not in existing  and \
             not can_edit(request.user, existing) and \
             not can_add(request.user, existing):

                return jsonResponse(
                    {"error": "You don't have permission to edit this sheet."})

        responseSheet = save_sheet(sheet, request.user.id)
        if "rebuild" in responseSheet and responseSheet["rebuild"]:
            # Don't bother adding user links if this data won't be used to rebuild the sheet
            responseSheet["sources"] = annotate_user_links(
                responseSheet["sources"])

        return jsonResponse(responseSheet)
Example #45
0
def cache_dump(request):
    resp = {'ref_cache_dump': model.Ref.cache_dump()}
    return jsonResponse(resp)
Example #46
0
@staff_member_required
def cache_dump(request):
    resp = {'ref_cache_dump': model.Ref.cache_dump()}
    return jsonResponse(resp)


@staff_member_required
def export_all(request):
    start = datetime.now()
    try:
        start_export_all()
        resp = {"status": "ok"}
    except Exception, e:
        resp = {"error": str(e)}
    resp["time"] = (datetime.now() - start).seconds
    return jsonResponse(resp)


@staff_member_required
def cause_error(request):
    resp = {}
    logger.error(u"This is a simple error")
    try:
        erorr = excepting
    except Exception as e:
        logger.exception('An Exception has ocurred in the code')
    erorr = error
    return jsonResponse(resp)


@staff_member_required
Example #47
0
def register_api(request):
    errors, token_dict, _ = process_register_form(request, auth_method='jwt')
    if len(errors) == 0:
        return jsonResponse(token_dict)

    return jsonResponse(errors)
Example #48
0
def subscribe(request, email):
    if subscribe_to_announce(email):
        return jsonResponse({"status": "ok"})
    else:
        return jsonResponse({"error": "Something went wrong."})
Example #49
0
def cache_stats(request):
    resp = {
        'ref_cache_size': model.Ref.cache_size()
    }
    return jsonResponse(resp)
Example #50
0
def subscribe(request, email):
    if subscribe_to_announce(email):
        return jsonResponse({"status": "ok"})
    else:
        return jsonResponse({"error": "Sorry, there was an error."})
Example #51
0
def subscribe_educators(request, email):
    if subscribe_to_list(["Announcements_General", "Announcements_Edu"], email, direct_sign_up=True):
        return jsonResponse({"status": "ok"})
    else:
        return jsonResponse({"error": "Sorry, there was an error."})
Example #52
0
 def decorator(request, *args, **kwargs):
     return jsonResponse(func(request, *args, **kwargs),
                         callback=request.GET.get("callback", None))
Example #53
0
def cause_error(request):
    resp = {}
    erorr = error
    return jsonResponse(resp)
Example #54
0
def save_sheet_api(request):
	"""
	API for listing available sheets
	"""
	if request.method == "GET":
		return jsonResponse({"error": "Unsupported HTTP method."})

	# Save a sheet
	if request.method == "POST":
		if not request.user.is_authenticated:
			key = request.POST.get("apikey")
			if not key:
				return jsonResponse({"error": "You must be logged in or use an API key to save."})
			apikey = db.apikeys.find_one({"key": key})
			if not apikey:
				return jsonResponse({"error": "Unrecognized API key."})
		else:
			apikey = None

		j = request.POST.get("json")
		if not j:
			return jsonResponse({"error": "No JSON given in post data."})
		sheet = json.loads(j)

		if apikey:
			if "id" in sheet:
				sheet["lastModified"] = get_sheet(sheet["id"])["dateModified"] # Usually lastModified gets set on the frontend, so we need to set it here to match with the previous dateModified so that the check in `save_sheet` returns properly
			user = User.objects.get(id=apikey["uid"])
		else:
			user = request.user

		if "id" in sheet:
			existing = get_sheet(sheet["id"])
			if "error" not in existing  and \
				not can_edit(user, existing) and \
				not can_add(request.user, existing) and \
				not can_publish(request.user, existing):

				return jsonResponse({"error": "You don't have permission to edit this sheet."})
		else:
			existing = None

		cleaned_sources = []
		for source in sheet["sources"]:
			cleaned_sources.append(clean_source(source))
		sheet["sources"] = cleaned_sources

		sheet["title"] = bleach_text(sheet["title"])

		if "summary" in sheet:
			sheet["summary"] = bleach_text(sheet["summary"])

		if sheet.get("group", None):
			# Quietly enforce group permissions
			if sheet["group"] not in [g["name"] for g in get_user_groups(user.id)]:
				# Don't allow non Group members to add a sheet to a group
				sheet["group"] = None

			if not can_publish(user, sheet):
				if not existing:
					sheet["status"] = "unlisted"
				else:
					if existing.get("group", None) != sheet["group"]:
						# Don't allow non Group publishers to add a new public sheet
						sheet["status"] = "unlisted"
					elif existing["status"] != sheet["status"]:
						# Don't allow non Group publishers from changing status of an existing sheet
						sheet["status"] = existing["status"]

		rebuild_nodes = request.POST.get('rebuildNodes', False)
		responseSheet = save_sheet(sheet, user.id, rebuild_nodes=rebuild_nodes)
		if "rebuild" in responseSheet and responseSheet["rebuild"]:
			# Don't bother adding user links if this data won't be used to rebuild the sheet
			responseSheet["sources"] = annotate_user_links(responseSheet["sources"])

		return jsonResponse(responseSheet)
Example #55
0
def user_groups_api(request, user_id):
	if request.method == "GET":
		is_me = request.user.id == int(user_id)
		groups_serialized = get_user_groups(int(user_id), is_me)
		return jsonResponse(groups_serialized)
	return jsonResponse({"error": "Unsupported HTTP method."})
Example #56
0
def user_sheet_list_api_with_sort(request, user_id, sort_by="date", limiter=0, offset=0):
	limiter  = int(limiter)
	offset   = int(offset)
	private = int(user_id) == request.user.id
	return jsonResponse(user_sheets(user_id, sort_by, private=private, limit=limiter, skip=offset), callback=request.GET.get("callback", None))
Example #57
0
def add_source_to_sheet_api(request, sheet_id):
	"""
	API to add a fully formed source (posted as JSON) to sheet_id.

	The contents of the "source" field will be a dictionary.
	The input format is similar to, but differs slightly from, the internal format for sources on source sheets.
	This method reformats the source to the format expected by add_source_to_sheet().

	Fields of input dictionary:
		either `refs` - an array of string refs, indicating a range
			or `ref` - a string ref
			or `outsideText` - a string
			or `outsideBiText` - a dictionary with string fields "he" and "en"
			or `comment` - a string
			or `media` - a URL string

		If the `ref` or `refs` fields are present, the `version`, `he` or `en` fields
		can further specify the origin or content of text for that ref.

	"""
	source = json.loads(request.POST.get("source"))
	if not source:
		return jsonResponse({"error": "No source to copy given."})

	if "refs" in source and source["refs"]:
		ref = Ref(source["refs"][0]).to(Ref(source["refs"][-1]))
		source["ref"] = ref.normal()
		del source["refs"]

	if "ref" in source and source["ref"]:
		ref = Ref(source["ref"])
		source["heRef"] = ref.he_normal()

		if "version" in source or "en" in source or "he" in source:
			text = {}
			if "en" in source:
				text["en"] = source["en"]
				tc = TextChunk(ref, "he", source["version"]) if source.get("versionLanguage") == "he" else TextChunk(ref, "he")
				text["he"] = tc.ja().flatten_to_string()
				del source["en"]
			elif "he" in source:
				text["he"] = source["he"]
				tc = TextChunk(ref, "en", source["version"]) if source.get("versionLanguage") == "en" else TextChunk(ref, "en")
				text["en"] = tc.ja().flatten_to_string()
				del source["he"]
			else:  # "version" in source
				text[source["versionLanguage"]] = TextChunk(ref, source["versionLanguage"], source["version"]).ja().flatten_to_string()
				other = "he" if source["versionLanguage"] == "en" else "en"
				text[other] = TextChunk(ref, other).ja().flatten_to_string()
			source.pop("version", None)
			source.pop("versionLanguage", None)
			source["text"] = text

		else:
			text = {}
			tc_eng = TextChunk(ref, "en")
			tc_heb = TextChunk(ref, "he")


			if tc_eng:
				text["en"] = tc_eng.ja().flatten_to_string() if tc_eng.ja().flatten_to_string() != "" else "..."
			if tc_heb:
				text["he"] = tc_heb.ja().flatten_to_string() if tc_heb.ja().flatten_to_string() != "" else "..."
			source["text"] = text
	note = request.POST.get("note", None)
	source.pop("node", None)
	response = add_source_to_sheet(int(sheet_id), source, note=note)

	return jsonResponse(response)
Example #58
0
def update_sheet_tags_api(request, sheet_id):
	"""
	API to update tags for sheet_id.
	"""
	tags = json.loads(request.POST.get("tags"))
	return jsonResponse(update_sheet_tags(int(sheet_id), tags))
Example #59
0
def sheet_likers_api(request, sheet_id):
	"""
	API to retrieve the list of people who like sheet_id.
	"""
	response = {"likers": likers_list_for_sheet(sheet_id)}
	return jsonResponse(response, callback=request.GET.get("callback", None))
Example #60
0
def sheets_by_ref_api(request, ref):
	"""
	API to get public sheets by ref. 
	"""
	return jsonResponse(get_sheets_for_ref(ref))