Esempio n. 1
0
def undo_trash_res():
    res_id = request.form.get("res_id")
    user_id = session["user_id"]
    cur = conn.cursor()

    # Undo single resource
    if res_id != "*":

        cur.execute(
            ("""INSERT INTO resources SELECT * FROM trash WHERE user_id = %s and re_id = %s"""
             ),
            (user_id, res_id),
        )

        cur.execute(
            ("""DELETE FROM trash WHERE user_id = %s and re_id = %s"""),
            (user_id, res_id),
        )

    # Undo all resources
    else:

        cur.execute(
            ("""INSERT INTO RESOURCES SELECT * FROM trash WHERE user_id = %s"""
             ),
            (user_id, ),
        )

        cur.execute(("""DELETE FROM trash WHERE user_id = %s"""), (user_id, ))

    cur.close()
    conn.commit()

    return redirect(url_for("deleted_res"))
Esempio n. 2
0
def renametag():

    tag = request.form.get("tag")
    replacement = request.form.get("replacement")
    print(replacement)
    if tag:
        if helpers.characters_valid(
                replacement
        ) and not helpers.list_contains_duplicates(replacement):
            cur = conn.cursor()
            cur.execute(
                "UPDATE resources SET tags = array_replace(tags,%s,%s)",
                (tag, replacement),
            )

            cur.close()
            conn.commit()

            flash("Tag renamed successfully.", "success")
        else:
            flash(
                "Invalid tags were given. Check for invalid characters or duplicate tags.",
                "danger",
            )

    return redirect(url_for("options"))
Esempio n. 3
0
def fildel():
    # Check if user is logged in
    if helpers.logged_in():

        tags_to_del = request.form.get("tags")
        user_id = session["user_id"]

        tags_array = "{" + tags_to_del + "}"
        cur = conn.cursor()

        # Add to trash
        cur.execute(
            ("""INSERT INTO trash SELECT * FROM resources WHERE user_id = %s AND tags @> %s"""
             ),
            (user_id, tags_array),
        )

        # Then Delete
        cur.execute(
            ("""DELETE FROM resources WHERE user_id = %s AND tags @> %s"""),
            (user_id, tags_array),
        )

        cur.close()
        conn.commit()

        flash("Resources deleted successfully.", "danger")
        return redirect(url_for("options"))
    else:
        flash("You are not logged in.", "danger")
        return redirect(url_for("login"))
Esempio n. 4
0
def register():

    form = forms.RegisterForm(request.form)
    if request.method == "POST" and form.validate():
        username = form.username.data
        email = form.email.data

        # Encrypt the password using sha256
        password = sha256_crypt.encrypt(str(form.password.data))
        timestamp = datetime.datetime.fromtimestamp(
            time()).strftime("%Y-%m-%d %H:%M:%S")

        if not conn:
            flash("Could not connect to database.", "error")
        else:
            cur = conn.cursor()
            cur.execute(
                ("""INSERT INTO users(email,username,password,date_of_reg) VALUES (%s,%s,%s,%s)"""
                 ),
                (email, username, password, timestamp),
            )

            cur.close()
            conn.commit()
            flash("You are now registered.", "success")
            return redirect(url_for("login"))

    return render_template("register.html", form=form)
Esempio n. 5
0
def delacc():
    # Check if user is logged in
    if helpers.logged_in():
        # Extract user_id from the current session
        user_id = session["user_id"]

        cur = conn.cursor()
        try:
            # First delete from `resources` so as not to violate foreign key constraints
            cur.execute("DELETE FROM resources WHERE user_id = %s",
                        (user_id, ))

            # Delete from `trash` as not to violate foreign key constraints
            cur.execute("DELETE FROM trash WHERE user_id = %s", (user_id, ))

            # Finally, remove the user from `users`
            cur.execute("DELETE FROM users WHERE id = %s", (user_id, ))

            cur.close()
            conn.commit()

        except DatabaseError:
            cur.rollback()

        session.clear()
        flash("Account deleted. Sad to see you go :(", "danger")
        return redirect("/")
    else:
        flash("You are not logged in.", "danger")
        return redirect(url_for("login"))
Esempio n. 6
0
def add_resource():

    form = forms.ResourceForm(request.form)
    if request.method == "POST" and form.validate():
        # Escape user input using Markup
        title = Markup.escape(form.title.data)
        link = urllib.parse.unquote(Markup.escape(form.link.data))
        note = Markup.escape(form.note.data)
        timestamp = datetime.datetime.fromtimestamp(
            time()).strftime("%Y-%m-%d %H:%M:%S")

        tags = Markup.escape(form.tags.data)
        # If not empty format for proper insertion into postgresql
        if tags:
            tags = "{" + str(tags).lower() + "}"
        else:
            tags = None

        user_id = session["user_id"]

        cur = conn.cursor()
        cur.execute(
            ("""INSERT INTO resources(user_id,title,link,note,tags,date_of_posting) VALUES (%s,%s,%s,%s,%s,%s)"""
             ),
            (user_id, title, link, note, tags, timestamp),
        )
        cur.close()
        conn.commit()

        flash("Resource created successfully.", "success")
        return redirect(url_for("resources"))
    else:
        user_id = session["user_id"]
        cur = conn.cursor()
        cur.execute(
            ("""SELECT DISTINCT unnest(tags) FROM resources WHERE user_id = %s"""
             ),
            (user_id, ),
        )

        tags_raw = cur.fetchall()

        # 'Unpack' tags_raw into one array
        all_tags = []
        for tag_arr in tags_raw:
            all_tags.append(tag_arr[0])

        cur.close()
        return render_template("add_resource.html", form=form, tags=all_tags)
Esempio n. 7
0
def remtag():

    tags = request.form.get("tags")

    if tags:
        tags_to_rem = tags.split(",")

        for tag in tags_to_rem:
            cur = conn.cursor()
            cur.execute("UPDATE resources SET tags = array_remove(tags, %s )",
                        (tag, ))

        cur.close()
        conn.commit()

    flash("Tag(s) removed successfully.", "danger")
    return redirect(url_for("options"))
Esempio n. 8
0
def chpass():

    form = forms.ChangePassForm(request.form)
    if request.method == "POST" and form.validate():
        new_password = sha256_crypt.encrypt(str(form.password.data))
        user_id = session["user_id"]

        cur = conn.cursor()
        cur.execute(
            ("""UPDATE users SET password = %s WHERE id = %s"""),
            (new_password, user_id),
        )

        cur.close()
        conn.commit()

        flash("Password changed successfully.", "success")
        return redirect(url_for("options"))
    return render_template("chng_password.html", form=form)
Esempio n. 9
0
def delete_res(user_id, re_id):

    if helpers.logged_in(user_id):
        cur = conn.cursor()

        # First add resource to trash bin
        cur.execute(
            ("""INSERT INTO trash SELECT * FROM resources WHERE user_id = %s and re_id = %s"""
             ),
            (user_id, re_id),
        )

        # And then delete it
        cur.execute(
            ("""DELETE FROM resources WHERE user_id = %s and re_id = %s"""),
            (user_id, re_id),
        )

        cur.close()
        conn.commit()
    return redirect(url_for("resources"))
Esempio n. 10
0
def reset_w_token(token):

    # Get email from token
    try:
        pwd_reset_serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"])
        email = pwd_reset_serializer.loads(token,
                                           salt="password-reset-salt",
                                           max_age=3600)
    except:
        flash("The password reset link is invalid or has expired.", "danger")
        return redirect(url_for("login"))

    form = forms.ChangePassForm(request.form)
    if request.method == "POST" and form.validate():

        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        cur.execute(("""SELECT * FROM users WHERE email=%s"""), (email, ))

        user = cur.fetchall()[0]

        if not user:
            flash("Invalid email address!", "danger")
            return redirect(url_for("login"))

        new_password = sha256_crypt.encrypt(str(form.password.data))

        cur.execute(
            ("""UPDATE users SET password = %s WHERE email = %s"""),
            (new_password, email),
        )

        cur.close()
        conn.commit()

        flash("Password changed successfully.", "success")
        return redirect(url_for("login"))

    return render_template("chng_password.html", form=form)
Esempio n. 11
0
def delall():
    # Check if user is logged in
    if helpers.logged_in():
        user_id = session.get("user_id")
        cur = conn.cursor()

        # Add to trash
        cur.execute(
            """INSERT INTO trash SELECT * FROM resources WHERE user_id = %s""",
            ([user_id]),
        )

        # Then Delete
        cur.execute("""DELETE FROM resources WHERE user_id = %s""",
                    ([user_id]))

        cur.close()
        conn.commit()

        flash("All resources were deleted successfully.", "danger")
        return redirect(url_for("resources"))
    else:
        flash("You are not logged in.", "danger")
        return redirect(url_for("login"))
Esempio n. 12
0
def import_resources():
    cur = conn.cursor()

    # res = cc.BaseResource
    def add_res_to_db(res):

        # Transform tags to all lowercase
        tags = [tag.lower() for tag in res.tags]

        link = urllib.parse.unquote(res.link)

        if res.title:
            title = res.title[0:99]
        else:
            title = res.link[0:50] + "..."

        timestamp = datetime.datetime.fromtimestamp(
            time()).strftime("%Y-%m-%d %H:%M:%S")
        user_id = session["user_id"]

        try:
            cur.execute(
                ("""INSERT INTO resources(user_id,title,link,tags,date_of_posting) VALUES (%s,%s,%s,%s,%s)"""
                 ),
                (user_id, title, link, tags, timestamp),
            )
        except DatabaseError:
            conn.rollback()

    def search_and_insert(filters=None, incl=None):

        tags = []
        prev_was_res = False

        if filters:
            filters = [f.lower()
                       for f in filters]  # Transform into all lowercase

        for cur_el in soup.find_all():

            # Detect folders, aka <DT><H3> {folder name} </H3>
            if cur_el.name == "h3":

                if prev_was_res and tags:
                    tags.pop()
                tags.append(cur_el.string.lower())

            # Detect resources/links aka <DT><A {href}> {title} </A>
            if cur_el.name == "a":
                new_resource = cc.BaseResource(cur_el.string,
                                               cur_el.get("href"), tags)

                if ((not incl and not filters)
                        or (incl and any(f in tags for f in filters))
                        or (not incl and all(f not in tags for f in filters))):
                    add_res_to_db(new_resource)

                if not prev_was_res:
                    prev_was_res = True

    if request.method == "POST":

        if "file" not in request.files:
            flash("No file selected.", "warning")
            return redirect(request.url)
        else:

            file = request.files["file"]
            if file.filename == "":
                flash("No file selected.", "warning")
                return redirect(request.url)

            if file:

                soup = BeautifulSoup(file, "html.parser")

                incl = request.form.get("incl")
                excl = request.form.get("excl")

                if not incl and not excl:  # Default import
                    search_and_insert()

                elif incl and not excl:  # Include only
                    incl_items = incl.split(",")
                    search_and_insert(incl_items, incl=True)

                elif not incl and excl:  # Exclude only
                    excl_items = excl.split(",")
                    search_and_insert(excl_items, incl=False)

                cur.close()
                conn.commit()
                flash("Resources imported successfully.", "success")

    return redirect(url_for("resources"))
Esempio n. 13
0
def edit_res(user_id, re_id):

    if request.method == "GET":
        if helpers.logged_in(user_id):

            # Fetch the data we want to edit
            cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
            cur.execute(
                ("""SELECT * FROM resources WHERE user_id = %s and re_id = %s"""
                 ),
                (user_id, re_id),
            )

            data = cur.fetchall()

            # Get the tags to suggest to the user
            cur.execute(
                ("""SELECT DISTINCT unnest(tags) FROM resources WHERE user_id = %s"""
                 ),
                (user_id, ),
            )

            tags_raw = cur.fetchall()

            # 'Unpack' tags_raw into one array
            all_tags = []
            for tag_arr in tags_raw:
                all_tags.append(Markup.escape(tag_arr[0]))

            cur.close()
            conn.commit()

            # Paranoid Mode: On. Escape user input even after we retrieve it from the database.
            # Fill the form with the data
            form = forms.ResourceForm()
            form.title.data = Markup.escape(data[0]["title"])
            form.link.data = Markup.escape(data[0]["link"])
            form.note.data = Markup.escape(data[0]["note"])
            if form.note.data:
                form.note.data = form.note.data.replace(
                    "</br>", "\n")  # Else the </br> tags will display as text

            if data[0]["tags"]:
                form.tags.data = ",".join(data[0]["tags"])  # Array to string
                form.tags.data = Markup.escape(form.tags.data.lower())
            else:
                form.tags.data = ""

            return render_template("edit_resource.html",
                                   title=data[0]["title"],
                                   form=form,
                                   tags=all_tags)

    elif request.method == "POST":

        form = forms.ResourceForm(request.form)
        if form.validate():

            # Grab the new form and its data
            title = form.title.data
            link = Markup.escape(form.link.data)
            note = Markup.escape(form.note.data)
            tags = Markup.escape(form.tags.data)

            # If not empty format for proper insertion into postgresql
            if tags:
                tags = "{" + str(tags).lower() + "}"
            else:
                tags = None

            # Update the row - keep date_of_posting, re_id and user_id the same
            cur = conn.cursor()
            cur.execute(
                ("""UPDATE resources SET title=%s,link=%s,note=%s,tags=%s WHERE user_id=%s AND re_id=%s"""
                 ),
                (title, link, note, tags, user_id, re_id),
            )
            cur.close()
            conn.commit()

            flash("Resource edited successfully.", "success")
            return redirect(url_for("resources"))
        else:
            return render_template("edit_resource.html", form=form)
    return redirect(url_for("resources"))
Esempio n. 14
0
def resources():

    if not helpers.logged_in():
        flash("You must be logged in to access your resources page.",
              "warning")
        return redirect(url_for("login"))
    else:
        user_id = session["user_id"]

        cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

        sort = request.cookies.get("sort")
        criteria = request.cookies.get("criteria")
        if criteria == "title":
            if sort == "asc" or not sort:
                cur.execute(
                    ("""SELECT * FROM resources WHERE user_id = %s ORDER BY title ASC"""
                     ),
                    (user_id, ),
                )
            else:
                cur.execute(
                    ("""SELECT * FROM resources WHERE user_id = %s ORDER BY title DESC"""
                     ),
                    (user_id, ),
                )
        elif criteria == "time" or not criteria:
            if sort == "asc" or not sort:
                cur.execute(
                    ("""SELECT * FROM resources WHERE user_id = %s ORDER BY date_of_posting ASC"""
                     ),
                    (user_id, ),
                )
            else:
                cur.execute(
                    ("""SELECT * FROM resources WHERE user_id = %s ORDER BY date_of_posting DESC"""
                     ),
                    (user_id, ),
                )

        data = cur.fetchall()

        try:
            cur.execute(
                ("""SELECT DISTINCT unnest(tags) FROM resources WHERE user_id = %s"""
                 ),
                (user_id, ),
            )
        except DatabaseError:
            conn.rollbal()

        tags_raw = cur.fetchall()

        # 'Unpack' tags_raw into one array
        all_tags = []
        for tag_arr in tags_raw:
            all_tags.append(tag_arr[0])

        cur.close()
        conn.commit()

        for res in data:
            res["title"] = unescape(res["title"])

        view = request.cookies.get("view")
        if view == "full":
            return render_template(
                "resources.html", resources=data, tags=all_tags, view=view
            )  # Pass 'view' attribute to use the correct .css file
        else:
            return render_template("resources_cmpct.html",
                                   resources=data,
                                   tags=all_tags,
                                   view=view)

    return render_template("resources.html")
Esempio n. 15
0
def open_share(token):

    use_filters = False
    all_tags = False
    try:
        serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"])
        data = serializer.loads(token, salt="share-salt",
                                max_age=259200)  # 3 days
        user_id = data[0]

        if data[1] == "*":
            all_tags = True
            tags = "*"
        else:
            tags = "{" + data[1] + "}"

        if data[2]:
            use_filters = True
            filters = "{" + data[2] + "}"

    except:
        flash("The share  link is invalid or has expired.", "danger")
        return render_template("home.html")

    cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    if use_filters:
        if all_tags:
            cur.execute(
                """SELECT * FROM resources
                        WHERE user_id= %s
                            AND NOT tags @> %s
                            AND tags IS NOT NULL
                        ORDER BY date_of_posting DESC""",
                (user_id, filters),
            )
        else:
            cur.execute(
                """SELECT * FROM resources
                        WHERE user_id= %s
                            AND tags @> %s
                            AND NOT tags @> %s
                            AND tags IS NOT NULL
                        ORDER BY date_of_posting DESC""",
                (user_id, tags, filters),
            )

    else:
        if all_tags:
            cur.execute(
                """SELECT * FROM resources
                        WHERE user_id= %s
                        ORDER BY date_of_posting DESC""",
                (user_id, ),
            )
        else:
            cur.execute(
                """SELECT * FROM resources
                        WHERE user_id= %s
                            AND tags @> %s
                        ORDER BY date_of_posting DESC""",
                (user_id, tags),
            )

    resources = cur.fetchall()

    cur.close()
    conn.commit()

    return render_template("resources_public.html",
                           resources=resources,
                           tags=tags,
                           view="full")
Esempio n. 16
0
def share():

    if request.method == "POST":
        search_str = request.form.get("tags")
        search_str = search_str.lower()

        filters = []
        filters_str = ""

        use_filters = False

        # Assuming standard form <tag1,tag2 -tag4,tag6> we separate filters from tags
        if "-" in search_str:
            use_filters = True
            filters_str = search_str[search_str.find("-") + 1:].strip()
            filters = [f.lower() for f in filters_str.split(",")]

            tags = [
                t.lower()
                for t in search_str[:search_str.find("-") - 1].split(",")
            ]

        else:
            tags = [t.lower() for t in search_str.split(",")]

        tags_str = ",".join(tags).strip()

        if not tags or not tags_str or tags_str == "":
            flash(f"No tags selected. Can't share.", "danger")
            return redirect(url_for("resources"))

        if use_filters and (filters == tags or all(fil in tags
                                                   for fil in filters)):
            flash("Tags and filters are the same. Can't share.", "danger")
            return redirect(url_for("resources"))

        cur = conn.cursor()
        cur.execute(
            ("""SELECT DISTINCT unnest(tags) FROM resources WHERE user_id = %s"""
             ),
            (session["user_id"], ),
        )

        tags_used = cur.fetchall()
        # 'Unpack' tags_raw into one array
        tags_used_clean = ["*"]
        for tag_arr in tags_used:
            tags_used_clean.append(tag_arr[0])

        cur.close()
        conn.commit()

        # If filters or search tags don't contain any actually used (aka existing) tags
        if any(tag not in tags_used_clean or fil not in tags_used_clean
               for tag in tags for fil in filters):

            flash("No such tag exists. Can't share.", "danger")
            return redirect(url_for("resources"))

        serializer = URLSafeTimedSerializer(app.config["SECRET_KEY"])

        share_url = url_for(
            "open_share",
            token=serializer.dumps([session["user_id"], tags_str, filters_str],
                                   salt="share-salt"),
            _external=True,
        )

        if use_filters:
            message = Markup(" \
            Resources containing {" + tags_str + " -" + filters_str +
                             "} can be publicly accessed for 3 days via the \
            following link: <a href=" + share_url + ">Link</a>")
        else:
            message = Markup("Resources containing {" + tags_str +
                             "} can be publicly accessed for 3 days via the \
            following link: <a href=" + share_url + ">Link</a>")

        flash(message, "info")

        return redirect(url_for("resources"))
    return redirect(url_for("resources"))