Пример #1
0
def manage(uid):

    has_directory_page = current_app.config["HAS_DIRECTORY_PAGE"]

    society = Society.query.filter_by(uid=uid).first()

    if not society:
        abort(404)

    crsid = auth_decorator.principal
    user = User.query.filter_by(crsid=crsid).first()

    if society not in user.societies:
        abort(403)

    sessions_data = {"days": current_app.config["NUMBER_OF_DAYS"]}

    if request.method == "POST":

        is_new_owner = False
        is_new_session = False

        # Input validation from https://github.com/SRCF/control-panel/blob/master/control/webapp/signup.py#L37

        values = {}

        for key in (
            "soc_name",
            "website",
            "description",
            "short_description",
            "welcome_text",
            "logo",
            "banner_text",
            "banner_color",
            "new_owner_crsid",
            "new_session_day",
            "new_session_start",
            "new_session_end",
        ):
            values[key] = request.form.get(key, "").strip()

        for key in ("mute_on_start", "disable_private_chat"):
            values[key] = bool(request.form.get(key, False))

        errors = {}

        if len(values["soc_name"]) <= 1:
            errors["soc_name"] = _("Society name is too short.")

        if len(values["short_description"]) > 200:
            errors["short_description"] = _("This description is too long.")

        if "logo" in request.files:
            logo = request.files["logo"]
            bbb_logo = request.files["bbb_logo"]

            logo_filename, logo_extension = os.path.splitext(logo.filename)
            bbb_logo_filename, bbb_logo_extension = os.path.splitext(bbb_logo.filename)

            images_dir = current_app.config["IMAGES_DIR"]

            if logo and logo_filename != "":
                if logo_extension in current_app.config["LOGO_ALLOWED_EXTENSIONS"]:

                    # Delete the old logo if it's not the default
                    delete_society_logo(uid)

                    static_filename = (
                        society.uid + "_" + gen_unique_string() + logo_extension
                    )
                    path = os.path.join(images_dir, static_filename)

                    current_app.logger.info(
                        f"For user { crsid }, society uid='{ society.uid }': changing logo..."
                    )
                    if not os.path.isdir(images_dir):
                        current_app.logger.error(
                            f"'{ images_dir }':  no such directory."
                        )
                        abort(500)

                    maxwidth, maxheight = current_app.config["MAX_LOGO_SIZE"]
                    logo_img = Image.open(logo)
                    ratio = min(maxwidth / logo_img.width, maxheight / logo_img.height)
                    # possible optimization with reduce here?
                    logo_resized = logo_img.resize(
                        (round(logo_img.width * ratio), round(logo_img.height * ratio))
                    )
                    logo_resized.save(path)

                    current_app.logger.info(
                        f"For uid='{ society.uid }': saved new logo '{ path }'"
                    )

                    society.logo = static_filename
                    db.session.commit()
                    current_app.logger.info(f"For uid='{ society.uid }': updated logo.")
                else:
                    errors["logo"] = "Invalid file."

            if bbb_logo and bbb_logo_filename != "":
                if bbb_logo_extension in current_app.config["LOGO_ALLOWED_EXTENSIONS"]:

                    # Delete the old logo if it's not the default
                    delete_society_bbb_logo(uid)

                    static_filename = (
                        society.uid + "_bbb_" + gen_unique_string() + bbb_logo_extension
                    )
                    path = os.path.join(images_dir, static_filename)

                    current_app.logger.info(
                        f"For user { crsid }, society uid='{ society.uid }': changing bbb_logo..."
                    )
                    if not os.path.isdir(images_dir):
                        current_app.logger.error(
                            f"'{ images_dir }':  no such directory."
                        )
                        abort(500)

                    bbb_logo_img = Image.open(bbb_logo)
                    bbb_logo_resized = bbb_logo_img.resize((100, 30))
                    bbb_logo_resized.save(path)

                    current_app.logger.info(
                        f"For uid='{ society.uid }': saved new bbb_logo to '{ path }'"
                    )

                    society.bbb_logo = static_filename
                    db.session.commit()
                    current_app.logger.info(
                        f"For uid='{ society.uid }': updated bbb_logo."
                    )
                else:
                    errors["bbb_logo"] = "Invalid file."

        # TODO: tweak these values when their ideal maximum lengths become apparent
        if len(values["welcome_text"]) > 100:
            errors["welcome_text"] = "Welcome text is too long."
        if len(values["banner_text"]) > 100:
            errors["banner_text"] = "Banner text is too long."

        # Adding a new owner
        if values["new_owner_crsid"] != "":

            current_app.logger.info(
                f"For uid='{ society.uid }': { crsid } is adding new owner { values['new_owner_crsid'] }..."
            )
            new_owner = User.query.filter_by(crsid=values["new_owner_crsid"]).first()
            if not new_owner:
                errors[
                    "new_owner_crsid"
                ] = "That user is not registered yet. Users must register before being added as administrators."
            is_new_owner = True

        # Add a new session
        if values["new_session_start"] and values["new_session_end"]:

            start_time = [int(nstr) for nstr in values["new_session_start"].split(":")]
            end_time = [int(nstr) for nstr in values["new_session_end"].split(":")]

            # Check that start is before end
            t1 = time(hour=start_time[0], minute=start_time[1])
            t2 = time(hour=end_time[0], minute=end_time[1])

            if t1 > t2:
                errors[
                    "new_session_start"
                ] = "Unfortunately, time travel is not possible."

            is_new_session = True

        elif values["new_session_start"]:
            errors["new_session_end"] = "No end time specified."
        elif values["new_session_end"]:
            errors["new_session_start"] = "No start time specified."

        if errors:
            flash("There are errors with the information you provided.")
            return render_template(
                "rooms/manage.html",
                page_title=f"Stall administration for { society.name }",
                society=society,
                crsid=crsid,
                errors=errors,
                sessions_data=sessions_data,
                page_parent=url_for("home.home"),
                has_directory_page=has_directory_page,
                **values,
            )
        else:
            society.name = values["soc_name"]
            society.website = values["website"] if values["website"] != "" else None

            # fetch all social fields from values, as we generate the uid in jinja
            social_forms = {k: v for (k, v) in request.form.items() if ("social-" in k)}
            for id, value in social_forms.items():
                index, found_social = get_social_by_id(id, society.socials)
                # do we have this social already?
                if found_social:
                    if found_social["url"] != value:
                        if value == "":
                            del society.socials[index]
                        else:
                            found_social["url"] = value
                            found_social["type"] = match_social(value)
                    flag_modified(society, "socials")
                else:
                    # create a new social field
                    # and check if its empty
                    if value:
                        social_type = match_social(value)
                        social_data = {"id": id, "url": value, "type": social_type}
                        society.socials.append(social_data)
                        flag_modified(society, "socials")

            society.description = values["description"] if values["description"] != "" else None
            society.short_description = values["short_description"] if values["short_description"] != "" else None
            society.welcome_text = values["welcome_text"] if values["welcome_text"] != "" else None
            society.banner_text = values["banner_text"] if values["banner_text"] != "" else None
            society.banner_color = values["banner_color"]
            society.mute_on_start = values["mute_on_start"]
            society.disable_private_chat = values["disable_private_chat"]

            if is_new_owner:
                society.owners.append(new_owner)

            if is_new_session:
                society.sessions.append(
                    {
                        "id": gen_unique_string(),
                        "day": values["new_session_day"],
                        "start": values["new_session_start"],
                        "end": values["new_session_end"],
                    }
                )
                # we need this to ensure that sqlalchemy updates the val
                flag_modified(society, "sessions")

            db.session.commit()

            if is_new_owner:
                current_app.logger.info(
                    f"For uid='{ society.uid }': added new owner { new_owner }."
                )

            if is_new_session:
                current_app.logger.info(
                    f"For uid='{ society.uid }': { crsid } added new session [ day: { values['new_session_day'] }, start: { values['new_session_start'] }, end: { values['new_session_end'] } ]"
                )

            flash("Settings saved.")

            return redirect(url_for("rooms.manage", uid=society.uid))

    else:
        # defaults
        values = {
            "soc_name": society.name,
            "website": society.website,
            "description": society.description,
            "short_description": society.short_description,
            "welcome_text": society.welcome_text,
            "banner_text": society.banner_text,
            "banner_color": society.banner_color,
            "logo": society.logo,
            "mute_on_start": society.mute_on_start,
            "disable_private_chat": society.disable_private_chat,
        }

    return render_template(
        "rooms/manage.html",
        page_title=f"Stall administration for { society.name }",
        society=society,
        crsid=crsid,
        errors={},
        sessions_data=sessions_data,
        page_parent=url_for("home.home"),
        has_directory_page=has_directory_page,
        **values,
    )
Пример #2
0
def register_soc():
    crsid = auth_decorator.principal

    user = User.query.filter_by(crsid=crsid).first()

    # Check the user is registered with us, if not redirect to the user reg page
    if not user:
        return redirect(url_for("home.register"))

    if request.method == "POST":

        values = {}
        for key in ("soc_name", "soc_short_name"):
            values[key] = request.form.get(key, "").strip()

        errors = {}

        values["uid"] = values["soc_short_name"].lower()
        values["bbb_id"] = gen_unique_string()
        values["moderator_pw"] = gen_unique_string()[0:12]
        values["attendee_pw"] = gen_unique_string()[0:12]

        # TODO: What's the best way of handling the (unlikely) event
        #       that the passwords are:
        #    a) non-unique across registered societies
        #    b) the same
        #       Currently we abort(500)
        if values["moderator_pw"] == values["attendee_pw"]:
            abort(500)
        elif (Society.query.filter_by(
                attendee_pw=values["attendee_pw"]).first()
              or Society.query.filter_by(
                  moderator_pw=values["moderator_pw"]).first()
              or Society.query.filter_by(bbb_id=values["bbb_id"]).first()):
            abort(500)

        if Society.query.filter_by(uid=values["uid"]).first():
            errors[
                "soc_short_name"] = "That society short name is already in use."

        if " " in values["soc_short_name"]:
            errors[
                "soc_short_name"] = "Your society short name must not contain spaces."

        if errors:
            return render_template("home/register_soc.html",
                                   page_title="Register a society",
                                   crsid=crsid,
                                   errors=errors,
                                   **values)
        else:
            society = Society(short_name=values["soc_short_name"],
                              name=values["soc_name"],
                              attendee_pw=values["attendee_pw"],
                              moderator_pw=values["moderator_pw"],
                              uid=values["uid"],
                              bbb_id=values["bbb_id"])

            db.session.add(society)
            db.session.commit()

            user.societies.append(society)
            db.session.commit()

            current_app.logger.info(f"Registered society {values['uid']}")

            return redirect(url_for("home.register_soc_success"))

    else:
        return render_template("home/register_soc.html",
                               page_title="Register a society",
                               crsid=crsid,
                               errors={})
Пример #3
0
def register():
    if request.method == "POST":
        name = request.form["name"]
        email_address = request.form["email_address"]
        soc_name = request.form["soc_name"]
        soc_short_name = request.form["soc_short_name"]
        uid = soc_short_name.lower()
        bbb_id = gen_unique_string()
        moderator_pw = gen_unique_string()[0:12]
        attendee_pw = gen_unique_string()[0:12]

        errors = []

        if not name:
            errors.append("A name is required.")
        if not email_address:
            errors.append("An email address is required.")
        if not "@" in email_address:
            errors.append("Enter a valid email address.")
        elif not "." in email_address:
            errors.append("Enter a valid email address.")
        if not soc_name:
            errors.append("A society name is required.")
        if not soc_short_name:
            errors.append("A short society name is required.")

        # TODO: What's the best way of handling the (unlikely) event
        #       that the passwords are:
        #    a) non-unique across registered societies
        #    b) the same
        #       Currently we flash the error:
        #       "An error occured. Please try again."

        if moderator_pw == attendee_pw:
            errors.append("An error occured. Please try again.")

        if User.query.filter_by(email=email_address):
            errors.append("That email address is already registered.")
        if Society.query.filter_by(uid=uid):
            errors.append("That society short name is already in use.")
        elif (Society.query.filter_by(attendee_pw=attendee_pw)
                or Society.query.filter_by(moderator_pw=moderator_pw)
                or Society.query.filter_by(bbb_id=bbb_id)):
            errors.append("An error occured. Please try again.")


        if not errors:

            # TODO: BBB create() API call goes here?

            admin = User(email=email_address,
                         name=name,
                         society_id=society.id,
                         crsid=auth_decorator.principal)

            society = Society(short_name=soc_short_name,
                              name=name,
                              attendee_pw=attendee_pw,
                              moderator_pw=moderator_pw,
                              uid=uid,
                              bbb_id=bbb_id,
                              admins=admin)

            db.session.add(society)
            db.session.add(admin)
            db.session.commit()

        else:
            for message in errors:
                flash(message)

    print(f"{auth_decorator.principal}")

    return render_template("home/register.html", page_title="Register a Society",
                           crsid=auth_decorator.principal)