예제 #1
0
def handle_login(form):
    def show_safe_err(err):
        if "@" in username:
            flash("Incorrect email or password", "danger")
        else:
            flash(err, "danger")

    username = form.username.data.strip()
    user = User.query.filter(
        or_(User.username == username, User.email == username)).first()
    if user is None:
        return show_safe_err("User {} does not exist".format(username))

    if not check_password_hash(user.password, form.password.data):
        return show_safe_err("Incorrect password. Did you set one?")

    if not user.is_active:
        flash("You need to confirm the registration email", "danger")
        return

    addAuditLog(AuditSeverity.USER, user, "Logged in using password",
                url_for("users.profile", username=user.username))
    db.session.commit()

    if not login_user(user, remember=form.remember_me.data):
        flash("Login failed", "danger")
        return

    return post_login(user, request.args.get("next"))
예제 #2
0
def handle_set_password(form):
    one = form.password.data
    two = form.password2.data
    if one != two:
        flash("Passwords do not much", "danger")
        return

    addAuditLog(AuditSeverity.USER, current_user, "Changed their password",
                url_for("users.profile", username=current_user.username))

    current_user.password = make_flask_login_password(form.password.data)

    if hasattr(form, "email"):
        newEmail = nonEmptyOrNone(form.email.data)
        if newEmail and newEmail != current_user.email:
            if EmailSubscription.query.filter_by(email=form.email.data,
                                                 blacklisted=True).count() > 0:
                flash(
                    "That email address has been unsubscribed/blacklisted, and cannot be used",
                    "danger")
                return

            token = randomString(32)

            ver = UserEmailVerification()
            ver.user = current_user
            ver.token = token
            ver.email = newEmail
            db.session.add(ver)

    db.session.commit()
    flash("Your password has been changed successfully.", "success")
    return redirect(url_for("homepage.home"))
예제 #3
0
def handle_profile_edit(form, user, username):
    severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION
    addAuditLog(severity, current_user,
                "Edited {}'s profile".format(user.display_name),
                url_for("users.profile", username=username))

    if user.checkPerm(current_user, Permission.CHANGE_DISPLAY_NAME) and \
      user.display_name != form.display_name.data:
        if User.query.filter(
                User.id != user.id,
                or_(User.username == form.display_name.data,
                    User.display_name.ilike(
                        form.display_name.data))).count() > 0:
            flash("A user already has that name", "danger")
            return None

        user.display_name = form.display_name.data

        severity = AuditSeverity.USER if current_user == user else AuditSeverity.MODERATION
        addAuditLog(
            severity, current_user,
            "Changed display name of {} to {}".format(user.username,
                                                      user.display_name),
            url_for("users.profile", username=username))

    if user.checkPerm(current_user, Permission.CHANGE_PROFILE_URLS):
        user.website_url = form["website_url"].data
        user.donate_url = form["donate_url"].data

    db.session.commit()

    return redirect(url_for("users.profile", username=username))
예제 #4
0
def forgot_password():
	form = ForgotPasswordForm(request.form)
	if form.validate_on_submit():
		email = form.email.data
		user = User.query.filter_by(email=email).first()
		if user:
			token = randomString(32)

			addAuditLog(AuditSeverity.USER, user, "(Anonymous) requested a password reset",
					url_for("users.profile", username=user.username), None)

			ver = UserEmailVerification()
			ver.user = user
			ver.token = token
			ver.email = email
			ver.is_password_reset = True
			db.session.add(ver)
			db.session.commit()

			send_verify_email.delay(form.email.data, token)
		else:
			send_anon_email.delay(email, "Unable to find account", """
					<p>
						We were unable to perform the password reset as we could not find an account
						associated with this email.
					</p>
					<p>
						If you weren't expecting to receive this email, then you can safely ignore it.
					</p>
			""")

		flash("Check your email address to continue the reset", "success")
		return redirect(url_for("homepage.home"))

	return render_template("users/forgot_password.html", form=form)
예제 #5
0
def do_create_vcs_release(user: User,
                          package: Package,
                          title: str,
                          ref: str,
                          min_v: MinetestRelease = None,
                          max_v: MinetestRelease = None,
                          reason: str = None):
    check_can_create_release(user, package)

    rel = PackageRelease()
    rel.package = package
    rel.title = title
    rel.url = ""
    rel.task_id = uuid()
    rel.min_rel = min_v
    rel.max_rel = max_v
    db.session.add(rel)

    if reason is None:
        msg = "Created release {}".format(rel.title)
    else:
        msg = "Created release {} ({})".format(rel.title, reason)
    addAuditLog(AuditSeverity.NORMAL, user, msg,
                package.getURL("packages.view"), package)

    db.session.commit()

    makeVCSRelease.apply_async((rel.id, nonEmptyOrNone(ref)),
                               task_id=rel.task_id)

    return rel
예제 #6
0
def delete_reply(id):
    thread = Thread.query.get(id)
    if thread is None:
        abort(404)

    reply_id = request.args.get("reply")
    if reply_id is None:
        abort(404)

    reply = ThreadReply.query.get(reply_id)
    if reply is None or reply.thread != thread:
        abort(404)

    if thread.replies[0] == reply:
        flash("Cannot delete thread opening post!", "danger")
        return redirect(thread.getViewURL())

    if not reply.checkPerm(current_user, Permission.DELETE_REPLY):
        abort(403)

    if request.method == "GET":
        return render_template("threads/delete_reply.html",
                               thread=thread,
                               reply=reply)

    msg = "Deleted reply by {}".format(reply.author.display_name)
    addAuditLog(AuditSeverity.MODERATION, current_user, msg,
                thread.getViewURL(), thread.package, reply.comment)

    db.session.delete(reply)
    db.session.commit()

    return redirect(thread.getViewURL())
예제 #7
0
def delete(username):
	user: User = User.query.filter_by(username=username).first()
	if not user:
		abort(404)

	if request.method == "GET":
		return render_template("users/delete.html", user=user, can_delete=user.can_delete())

	if user.can_delete():
		msg = "Deleted user {}".format(user.username)
		flash(msg, "success")
		addAuditLog(AuditSeverity.MODERATION, current_user, msg, None)

		db.session.delete(user)
	else:
		user.replies.delete()
		for thread in user.threads.all():
			db.session.delete(thread)
		user.email = None
		user.rank = UserRank.NOT_JOINED

		msg = "Deactivated user {}".format(user.username)
		flash(msg, "success")
		addAuditLog(AuditSeverity.MODERATION, current_user, msg, None)

	db.session.commit()

	if user == current_user:
		logout_user()

	return redirect(url_for("homepage.home"))
예제 #8
0
파일: account.py 프로젝트: shanql/contentdb
def handle_register(form):
    user_by_name = User.query.filter(
        or_(User.username == form.username.data,
            User.username == form.display_name.data,
            User.display_name == form.display_name.data,
            User.forums_username == form.username.data,
            User.github_username == form.username.data)).first()
    if user_by_name:
        if user_by_name.rank == UserRank.NOT_JOINED and user_by_name.forums_username:
            flash(
                "An account already exists for that username but hasn't been claimed yet.",
                "danger")
            return redirect(
                url_for("users.claim_forums",
                        username=user_by_name.forums_username))
        else:
            flash(
                "That username/display name is already in use, please choose another.",
                "danger")
            return

    user_by_email = User.query.filter_by(email=form.email.data).first()
    if user_by_email:
        send_anon_email.delay(
            form.email.data, "Email already in use",
            "We were unable to create the account as the email is already in use by {}. Try a different email address."
            .format(user_by_email.display_name))
        flash("Check your email address to verify your account", "success")
        return redirect(url_for("homepage.home"))
    elif EmailSubscription.query.filter_by(email=form.email.data,
                                           blacklisted=True).count() > 0:
        flash(
            "That email address has been unsubscribed/blacklisted, and cannot be used",
            "danger")
        return

    user = User(form.username.data, False, form.email.data,
                make_flask_login_password(form.password.data))
    user.notification_preferences = UserNotificationPreferences(user)
    if form.display_name.data:
        user.display_name = form.display_name.data
    db.session.add(user)

    addAuditLog(AuditSeverity.USER, user,
                "Registered with email, display name=" + user.display_name,
                url_for("users.profile", username=user.username))

    token = randomString(32)

    ver = UserEmailVerification()
    ver.user = user
    ver.token = token
    ver.email = form.email.data
    db.session.add(ver)
    db.session.commit()

    send_verify_email.delay(form.email.data, token)

    flash("Check your email address to verify your account", "success")
    return redirect(url_for("homepage.home"))
예제 #9
0
def do_create_screenshot(user: User, package: Package, title: str, file, reason: str = None):
	thirty_minutes_ago = datetime.datetime.now() - datetime.timedelta(minutes=30)
	count = package.screenshots.filter(PackageScreenshot.created_at > thirty_minutes_ago).count()
	if count >= 20:
		raise LogicError(429, "Too many requests, please wait before trying again")

	uploaded_url, uploaded_path = upload_file(file, "image", "a PNG or JPG image file")

	counter = 1
	for screenshot in package.screenshots.all():
		screenshot.order = counter
		counter += 1

	ss = PackageScreenshot()
	ss.package  = package
	ss.title    = title or "Untitled"
	ss.url      = uploaded_url
	ss.approved = package.checkPerm(user, Permission.APPROVE_SCREENSHOT)
	ss.order    = counter
	db.session.add(ss)

	if reason is None:
		msg = "Created screenshot {}".format(ss.title)
	else:
		msg = "Created screenshot {} ({})".format(ss.title, reason)

	addNotification(package.maintainers, user, NotificationType.PACKAGE_EDIT, msg, package.getURL("packages.view"), package)
	addAuditLog(AuditSeverity.NORMAL, user, msg, package.getURL("packages.view"), package)

	db.session.commit()

	return ss
예제 #10
0
def set_lock(id):
    thread = Thread.query.get(id)
    if thread is None or not thread.checkPerm(current_user,
                                              Permission.LOCK_THREAD):
        abort(404)

    thread.locked = isYes(request.args.get("lock"))
    if thread.locked is None:
        abort(400)

    msg = None
    if thread.locked:
        msg = "Locked thread '{}'".format(thread.title)
        flash("Locked thread", "success")
    else:
        msg = "Unlocked thread '{}'".format(thread.title)
        flash("Unlocked thread", "success")

    addNotification(thread.watchers, current_user, NotificationType.OTHER, msg,
                    thread.getViewURL(), thread.package)
    addAuditLog(AuditSeverity.MODERATION, current_user, NotificationType.OTHER,
                msg, thread.getViewURL(), thread.package)

    db.session.commit()

    return redirect(thread.getViewURL())
예제 #11
0
def account(username):
    user: User = User.query.filter_by(username=username).first()
    if not user:
        abort(404)

    if not user.can_see_edit_profile(current_user):
        flash("Permission denied", "danger")
        return redirect(url_for("users.profile", username=username))

    can_edit_account_settings = user.checkPerm(current_user, Permission.CHANGE_USERNAMES) or \
      user.checkPerm(current_user, Permission.CHANGE_RANK)
    form = UserAccountForm(obj=user) if can_edit_account_settings else None
    if form and form.validate_on_submit():
        severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION
        addAuditLog(severity, current_user,
                    "Edited {}'s profile".format(user.display_name),
                    url_for("users.profile", username=username))

        # Copy form fields to user_profile fields
        if user.checkPerm(current_user, Permission.CHANGE_USERNAMES):
            if user.username != form.username.data:
                for package in user.packages:
                    alias = PackageAlias(user.username, package.name)
                    package.aliases.append(alias)
                    db.session.add(alias)

                user.username = form.username.data

            user.display_name = form.display_name.data
            user.forums_username = nonEmptyOrNone(form.forums_username.data)
            user.github_username = nonEmptyOrNone(form.github_username.data)

        if user.checkPerm(current_user, Permission.CHANGE_RANK):
            newRank = form["rank"].data
            if current_user.rank.atLeast(newRank):
                if newRank != user.rank:
                    user.rank = form["rank"].data
                    msg = "Set rank of {} to {}".format(
                        user.display_name, user.rank.getTitle())
                    addAuditLog(AuditSeverity.MODERATION, current_user, msg,
                                url_for("users.profile", username=username))
            else:
                flash("Can't promote a user to a rank higher than yourself!",
                      "danger")

        db.session.commit()

        return redirect(url_for("users.account", username=username))

    return render_template("users/account.html",
                           user=user,
                           form=form,
                           tabs=get_setting_tabs(user),
                           current_tab="account")
예제 #12
0
def send_bulk_email():
    form = SendEmailForm(request.form)
    if form.validate_on_submit():
        addAuditLog(AuditSeverity.MODERATION, current_user, "Sent bulk email",
                    None, None, form.text.data)

        text = form.text.data
        html = render_markdown(text)
        for user in User.query.filter(User.email != None).all():
            send_user_email.delay(user.email, form.subject.data, text, html)

        return redirect(url_for("admin.admin_page"))

    return render_template("admin/send_bulk_email.html", form=form)
예제 #13
0
파일: admin.py 프로젝트: Warr1024/contentdb
def send_bulk_notification():
    form = SendNotificationForm(request.form)
    if form.validate_on_submit():
        addAuditLog(AuditSeverity.MODERATION, current_user,
                    "Sent bulk notification", None, None, form.title.data)

        users = User.query.filter(User.rank >= UserRank.NEW_MEMBER).all()
        addNotification(users, current_user, NotificationType.OTHER,
                        form.title.data, form.url.data, None)
        db.session.commit()

        return redirect(url_for("admin.admin_page"))

    return render_template("admin/send_bulk_notification.html", form=form)
예제 #14
0
def verify_email():
    token = request.args.get("token")
    ver: UserEmailVerification = UserEmailVerification.query.filter_by(
        token=token).first()
    if ver is None:
        flash("Unknown verification token!", "danger")
        return redirect(url_for("homepage.home"))

    user = ver.user

    addAuditLog(AuditSeverity.USER, user, "Confirmed their email",
                url_for("users.profile", username=user.username))

    was_activating = not user.is_active

    if ver.email and user.email != ver.email:
        if User.query.filter_by(email=ver.email).count() > 0:
            flash("Another user is already using that email", "danger")
            return redirect(url_for("homepage.home"))

        flash("Confirmed email change", "success")

        if user.email:
            send_user_email.delay(
                user.email, "Email address changed",
                "Your email address has changed. If you didn't request this, please contact an administrator."
            )

    user.is_active = True
    user.email = ver.email

    db.session.delete(ver)
    db.session.commit()

    if ver.is_password_reset:
        login_user(user)
        user.password = None
        db.session.commit()

        return redirect(url_for("users.set_password"))

    if current_user.is_authenticated:
        return redirect(
            url_for("users.profile", username=current_user.username))
    elif was_activating:
        flash("You may now log in", "success")
        return redirect(url_for("users.login"))
    else:
        return redirect(url_for("homepage.home"))
예제 #15
0
def apply_all_updates(username):
    user: User = User.query.filter_by(username=username).first()
    if not user:
        abort(404)

    if current_user != user and not current_user.rank.atLeast(UserRank.EDITOR):
        abort(403)

    outdated_packages = user.maintained_packages \
     .filter(Package.state != PackageState.DELETED,
      Package.update_config.has(PackageUpdateConfig.outdated_at.isnot(None))) \
     .order_by(db.asc(Package.title)).all()

    for package in outdated_packages:
        if not package.checkPerm(current_user, Permission.MAKE_RELEASE):
            continue

        if package.releases.filter(
                or_(
                    PackageRelease.task_id.isnot(None),
                    PackageRelease.commit_hash
                    == package.update_config.last_commit)).count() > 0:
            continue

        title = package.update_config.get_title()
        ref = package.update_config.get_ref()

        rel = PackageRelease()
        rel.package = package
        rel.title = title
        rel.url = ""
        rel.task_id = uuid()
        db.session.add(rel)
        db.session.commit()

        makeVCSRelease.apply_async((rel.id, ref), task_id=rel.task_id)

        msg = "Created release {} (Applied all Git Update Detection)".format(
            rel.title)
        addNotification(package.maintainers,
                        current_user, NotificationType.PACKAGE_EDIT, msg,
                        rel.getEditURL(), package)
        addAuditLog(AuditSeverity.NORMAL, current_user, msg,
                    package.getDetailsURL(), package)
        db.session.commit()

    return redirect(url_for("todo.view_user", username=username))
예제 #16
0
def callback(oauth_token):
    next_url = request.args.get("next")
    if oauth_token is None:
        flash("Authorization failed [err=gh-oauth-login-failed]", "danger")
        return redirect(url_for("users.login"))

    # Get Github username
    url = "https://api.github.com/user"
    r = requests.get(url, headers={"Authorization": "token " + oauth_token})
    username = r.json()["login"]

    # Get user by github username
    userByGithub = User.query.filter(
        func.lower(User.github_username) == func.lower(username)).first()

    # If logged in, connect
    if current_user and current_user.is_authenticated:
        if userByGithub is None:
            current_user.github_username = username
            db.session.commit()
            flash("Linked github to account", "success")
            return redirect(url_for("homepage.home"))
        else:
            flash("Github account is already associated with another user",
                  "danger")
            return redirect(url_for("homepage.home"))

    # If not logged in, log in
    else:
        if userByGithub is None:
            flash("Unable to find an account for that Github user", "danger")
            return redirect(url_for("users.claim_forums"))
        elif login_user_set_active(userByGithub, remember=True):
            addAuditLog(
                AuditSeverity.USER, userByGithub,
                "Logged in using GitHub OAuth",
                url_for("users.profile", username=userByGithub.username))
            db.session.commit()

            if not current_user.password:
                return redirect(
                    next_url or url_for("users.set_password", optional=True))
            else:
                return redirect(next_url or url_for("homepage.home"))
        else:
            flash("Authorization failed [err=gh-login-failed]", "danger")
            return redirect(url_for("users.login"))
예제 #17
0
def handle_email_notifications(user, prefs: UserNotificationPreferences,
                               is_new, form):
    for notificationType in NotificationType:
        field_email = getattr(form, "pref_" + notificationType.toName()).data
        field_digest = getattr(form, "pref_" + notificationType.toName() +
                               "_digest").data or field_email
        prefs.set_can_email(notificationType, field_email)
        prefs.set_can_digest(notificationType, field_digest)

    if is_new:
        db.session.add(prefs)

    if user.checkPerm(current_user, Permission.CHANGE_EMAIL):
        newEmail = form.email.data
        if newEmail and newEmail != user.email and newEmail.strip() != "":
            if EmailSubscription.query.filter_by(email=form.email.data,
                                                 blacklisted=True).count() > 0:
                flash(
                    "That email address has been unsubscribed/blacklisted, and cannot be used",
                    "danger")
                return

            token = randomString(32)

            severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION

            msg = "Changed email of {}".format(user.display_name)
            addAuditLog(severity, current_user, msg,
                        url_for("users.profile", username=user.username))

            ver = UserEmailVerification()
            ver.user = user
            ver.token = token
            ver.email = newEmail
            db.session.add(ver)
            db.session.commit()

            flash("Check your email to confirm it", "success")

            send_verify_email.delay(newEmail, token)
            return redirect(
                url_for("users.email_notifications", username=user.username))

    db.session.commit()
    return redirect(
        url_for("users.email_notifications", username=user.username))
예제 #18
0
def profile_edit(username):
	user : User = User.query.filter_by(username=username).first()
	if not user:
		abort(404)

	if not user.can_see_edit_profile(current_user):
		flash("Permission denied", "danger")
		return redirect(url_for("users.profile", username=username))


	form = UserProfileForm(formdata=request.form, obj=user)

	# Process valid POST
	if request.method=="POST" and form.validate():
		severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION
		addAuditLog(severity, current_user, "Edited {}'s profile".format(user.display_name),
				url_for("users.profile", username=username))

		# Copy form fields to user_profile fields
		if user.checkPerm(current_user, Permission.CHANGE_USERNAMES):
			user.display_name = form.display_name.data
			user.forums_username = nonEmptyOrNone(form.forums_username.data)
			user.github_username = nonEmptyOrNone(form.github_username.data)

		if user.checkPerm(current_user, Permission.CHANGE_PROFILE_URLS):
			user.website_url  = form["website_url"].data
			user.donate_url   = form["donate_url"].data

		if user.checkPerm(current_user, Permission.CHANGE_RANK):
			newRank = form["rank"].data
			if current_user.rank.atLeast(newRank):
				if newRank != user.rank:
					user.rank = form["rank"].data
					msg = "Set rank of {} to {}".format(user.display_name, user.rank.getTitle())
					addAuditLog(AuditSeverity.MODERATION, current_user, msg, url_for("users.profile", username=username))
			else:
				flash("Can't promote a user to a rank higher than yourself!", "danger")

		# Save user_profile
		db.session.commit()

		return redirect(url_for("users.profile", username=username))

	# Process GET or invalid POST
	return render_template("users/profile_edit.html", user=user, form=form, tabs=get_setting_tabs(user), current_tab="edit_profile")
예제 #19
0
def do_create_zip_release(user: User,
                          package: Package,
                          title: str,
                          file,
                          min_v: MinetestRelease = None,
                          max_v: MinetestRelease = None,
                          reason: str = None,
                          commit_hash: str = None):
    check_can_create_release(user, package)

    if commit_hash:
        commit_hash = commit_hash.lower()
        if not (len(commit_hash) == 40
                and re.match(r"^[0-9a-f]+$", commit_hash)):
            raise LogicError(
                400,
                "Invalid commit hash; it must be a 40 character long base16 string"
            )

    uploaded_url, uploaded_path = upload_file(file, "zip", "a zip file")

    rel = PackageRelease()
    rel.package = package
    rel.title = title
    rel.url = uploaded_url
    rel.task_id = uuid()
    rel.commit_hash = commit_hash
    rel.min_rel = min_v
    rel.max_rel = max_v
    db.session.add(rel)

    if reason is None:
        msg = "Created release {}".format(rel.title)
    else:
        msg = "Created release {} ({})".format(rel.title, reason)
    addAuditLog(AuditSeverity.NORMAL, user, msg,
                package.getURL("packages.view"), package)

    db.session.commit()

    checkZipRelease.apply_async((rel.id, uploaded_path), task_id=rel.task_id)

    return rel
예제 #20
0
def send_email(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        abort(404)

    next_url = url_for("users.profile", username=user.username)

    if user.email is None:
        flash("User has no email address!", "danger")
        return redirect(next_url)

    form = SendEmailForm(request.form)
    if form.validate_on_submit():
        addAuditLog(AuditSeverity.MODERATION, current_user,
                    "Sent email to {}".format(user.display_name),
                    url_for("users.profile", username=username))

        text = form.text.data
        html = render_markdown(text)
        task = sendEmailRaw.delay([user.email], form.subject.data, text, html)
        return redirect(url_for("tasks.check", id=task.id, r=next_url))

    return render_template("users/send_email.html", form=form)
예제 #21
0
def edit_reply(id):
    thread = Thread.query.get(id)
    if thread is None:
        abort(404)

    reply_id = request.args.get("reply")
    if reply_id is None:
        abort(404)

    reply = ThreadReply.query.get(reply_id)
    if reply is None or reply.thread != thread:
        abort(404)

    if not reply.checkPerm(current_user, Permission.EDIT_REPLY):
        abort(403)

    form = CommentForm(formdata=request.form, obj=reply)
    if form.validate_on_submit():
        comment = form.comment.data

        msg = "Edited reply by {}".format(reply.author.display_name)
        severity = AuditSeverity.NORMAL if current_user == reply.author else AuditSeverity.MODERATION
        addNotification(reply.author, current_user, NotificationType.OTHER,
                        msg, thread.getViewURL(), thread.package)
        addAuditLog(severity, current_user, msg, thread.getViewURL(),
                    thread.package, reply.comment)

        reply.comment = comment

        db.session.commit()

        return redirect(thread.getViewURL())

    return render_template("threads/edit_reply.html",
                           thread=thread,
                           reply=reply,
                           form=form)
예제 #22
0
def delete_thread(id):
    thread = Thread.query.get(id)
    if thread is None or not thread.checkPerm(current_user,
                                              Permission.DELETE_THREAD):
        abort(404)

    if request.method == "GET":
        return render_template("threads/delete_thread.html", thread=thread)

    summary = "\n\n".join([("<{}> {}".format(reply.author.display_name,
                                             reply.comment))
                           for reply in thread.replies])

    msg = "Deleted thread {} by {}".format(thread.title,
                                           thread.author.display_name)

    db.session.delete(thread)

    addAuditLog(AuditSeverity.MODERATION, current_user, msg, None,
                thread.package, summary)

    db.session.commit()

    return redirect(url_for("homepage.home"))
예제 #23
0
def profile(username):
    user = User.query.filter_by(username=username).first()
    if not user:
        abort(404)

    form = None
    if user.checkPerm(current_user, Permission.CHANGE_USERNAMES) or \
      user.checkPerm(current_user, Permission.CHANGE_EMAIL) or \
      user.checkPerm(current_user, Permission.CHANGE_RANK):
        # Initialize form
        form = UserProfileForm(formdata=request.form, obj=user)

        # Process valid POST
        if request.method == "POST" and form.validate():
            severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION
            addAuditLog(severity, current_user,
                        "Edited {}'s profile".format(user.display_name),
                        url_for("users.profile", username=username))

            # Copy form fields to user_profile fields
            if user.checkPerm(current_user, Permission.CHANGE_USERNAMES):
                user.display_name = form.display_name.data
                user.forums_username = nonEmptyOrNone(
                    form.forums_username.data)
                user.github_username = nonEmptyOrNone(
                    form.github_username.data)

            if user.checkPerm(current_user, Permission.CHANGE_PROFILE_URLS):
                user.website_url = form["website_url"].data
                user.donate_url = form["donate_url"].data

            if user.checkPerm(current_user, Permission.CHANGE_RANK):
                newRank = form["rank"].data
                if current_user.rank.atLeast(newRank):
                    if newRank != user.rank:
                        user.rank = form["rank"].data
                        msg = "Set rank of {} to {}".format(
                            user.display_name, user.rank.getTitle())
                        addAuditLog(
                            AuditSeverity.MODERATION, current_user, msg,
                            url_for("users.profile", username=username))
                else:
                    flash(
                        "Can't promote a user to a rank higher than yourself!",
                        "danger")

            if user.checkPerm(current_user, Permission.CHANGE_EMAIL):
                newEmail = form["email"].data
                if newEmail != user.email and newEmail.strip() != "":
                    token = randomString(32)

                    msg = "Changed email of {}".format(user.display_name)
                    addAuditLog(severity, current_user, msg,
                                url_for("users.profile", username=username))

                    ver = UserEmailVerification()
                    ver.user = user
                    ver.token = token
                    ver.email = newEmail
                    db.session.add(ver)
                    db.session.commit()

                    task = sendVerifyEmail.delay(newEmail, token)
                    return redirect(
                        url_for("tasks.check",
                                id=task.id,
                                r=url_for("users.profile", username=username)))

            # Save user_profile
            db.session.commit()

            # Redirect to home page
            return redirect(url_for("users.profile", username=username))

    packages = user.packages.filter(Package.state != PackageState.DELETED)
    if not current_user.is_authenticated or (
            user != current_user and not current_user.canAccessTodoList()):
        packages = packages.filter_by(state=PackageState.APPROVED)
    packages = packages.order_by(db.asc(Package.title))

    topics_to_add = None
    if current_user == user or user.checkPerm(current_user,
                                              Permission.CHANGE_AUTHOR):
        topics_to_add = ForumTopic.query \
           .filter_by(author_id=user.id) \
           .filter(~ db.exists().where(Package.forums==ForumTopic.topic_id)) \
           .order_by(db.asc(ForumTopic.name), db.asc(ForumTopic.title)) \
           .all()

    # Process GET or invalid POST
    return render_template("users/profile.html",
                           user=user,
                           form=form,
                           packages=packages,
                           topics_to_add=topics_to_add)
예제 #24
0
def do_edit_package(user: User,
                    package: Package,
                    was_new: bool,
                    data: dict,
                    reason: str = None):
    if not package.checkPerm(user, Permission.EDIT_PACKAGE):
        raise LogicError(403,
                         "You do not have permission to edit this package")

    if "name" in data and package.name != data["name"] and \
      not package.checkPerm(user, Permission.CHANGE_NAME):
        raise LogicError(
            403, "You do not have permission to change the package name")

    for alias, to in ALIASES.items():
        if alias in data:
            data[to] = data[alias]

    validate(data)

    if "type" in data:
        data["type"] = PackageType.coerce(data["type"])

    if "license" in data:
        data["license"] = get_license(data["license"])

    if "media_license" in data:
        data["media_license"] = get_license(data["media_license"])

    for key in [
            "name", "title", "short_desc", "desc", "type", "license",
            "media_license", "repo", "website", "issueTracker", "forums"
    ]:
        if key in data:
            setattr(package, key, data[key])

    if package.type == PackageType.TXP:
        package.license = package.media_license

    if was_new and package.type == PackageType.MOD:
        m = MetaPackage.GetOrCreate(package.name, {})
        package.provides.append(m)

    if "tags" in data:
        package.tags.clear()
        for tag_id in data["tags"]:
            if is_int(tag_id):
                package.tags.append(Tag.query.get(tag_id))
            else:
                tag = Tag.query.filter_by(name=tag_id).first()
                if tag is None:
                    raise LogicError(400, "Unknown tag: " + tag_id)
                package.tags.append(tag)

    if "content_warnings" in data:
        package.content_warnings.clear()
        for warning_id in data["content_warnings"]:
            if is_int(warning_id):
                package.content_warnings.append(
                    ContentWarning.query.get(warning_id))
            else:
                warning = ContentWarning.query.filter_by(
                    name=warning_id).first()
                if warning is None:
                    raise LogicError(400, "Unknown warning: " + warning_id)
                package.content_warnings.append(warning)

    if not was_new:
        if reason is None:
            msg = "Edited {}".format(package.title)
        else:
            msg = "Edited {} ({})".format(package.title, reason)

        severity = AuditSeverity.NORMAL if user in package.maintainers else AuditSeverity.EDITOR
        addAuditLog(severity, user, msg, package.getDetailsURL(), package)

    db.session.commit()

    return package