예제 #1
0
def handleCreateRelease(token, package, title, ref):
    if not token.canOperateOnPackage(package):
        return error(403, "API token does not have access to the package")

    if not package.checkPerm(token.owner, Permission.MAKE_RELEASE):
        return error(403, "Permission denied. Missing MAKE_RELEASE permission")

    five_minutes_ago = datetime.datetime.now() - datetime.timedelta(minutes=5)
    count = package.releases.filter(
        PackageRelease.releaseDate > five_minutes_ago).count()
    if count >= 2:
        return error(429, "Too many requests, please wait before trying again")

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

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

    return jsonify({
        "success": True,
        "task": url_for("tasks.check", id=rel.task_id),
        "release": rel.getAsDictionary()
    })
예제 #2
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
예제 #3
0
def create_release_page(package):
    if not package.checkPerm(current_user, Permission.MAKE_RELEASE):
        return redirect(package.getDetailsURL())

    # Initial form class from post data and default data
    form = CreatePackageReleaseForm()
    if package.repo is not None:
        form["uploadOpt"].choices = [("vcs", "From Git Commit or Branch"),
                                     ("upload", "File Upload")]
        if request.method != "POST":
            form["uploadOpt"].data = "vcs"

    if request.method == "POST" and form.validate():
        if form["uploadOpt"].data == "vcs":
            rel = PackageRelease()
            rel.package = package
            rel.title = form["title"].data
            rel.url = ""
            rel.task_id = uuid()
            rel.min_rel = form["min_rel"].data.getActual()
            rel.max_rel = form["max_rel"].data.getActual()
            db.session.add(rel)
            db.session.commit()

            makeVCSRelease.apply_async((rel.id, form["vcsLabel"].data),
                                       task_id=rel.task_id)

            msg = "{}: Release {} created".format(package.title, rel.title)
            triggerNotif(package.author, current_user, msg, rel.getEditURL())
            db.session.commit()

            return redirect(
                url_for("check_task", id=rel.task_id, r=rel.getEditURL()))
        else:
            uploadedPath = doFileUpload(form.fileUpload.data, "zip",
                                        "a zip file")
            if uploadedPath is not None:
                rel = PackageRelease()
                rel.package = package
                rel.title = form["title"].data
                rel.url = uploadedPath
                rel.min_rel = form["min_rel"].data.getActual()
                rel.max_rel = form["max_rel"].data.getActual()
                rel.approve(current_user)
                db.session.add(rel)
                db.session.commit()

                msg = "{}: Release {} created".format(package.title, rel.title)
                triggerNotif(package.author, current_user, msg,
                             rel.getEditURL())
                db.session.commit()
                return redirect(package.getDetailsURL())

    return render_template("packages/release_new.html",
                           package=package,
                           form=form)
예제 #4
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))
예제 #5
0
def admin_page():
    if request.method == "POST":
        action = request.form["action"]
        if action == "delstuckreleases":
            PackageRelease.query.filter(
                PackageRelease.task_id != None).delete()
            db.session.commit()
            return redirect(url_for("admin.admin_page"))
        elif action == "checkreleases":
            releases = PackageRelease.query.filter(
                PackageRelease.url.like("/uploads/%")).all()

            tasks = []
            for release in releases:
                zippath = release.url.replace("/uploads/",
                                              app.config["UPLOAD_DIR"])
                tasks.append(checkZipRelease.s(release.id, zippath))

            result = group(tasks).apply_async()

            while not result.ready():
                import time
                time.sleep(0.1)

            return redirect(url_for("todo.view"))
        elif action == "importmodlist":
            task = importTopicList.delay()
            return redirect(
                url_for("tasks.check", id=task.id, r=url_for("todo.topics")))
        elif action == "checkusers":
            task = checkAllForumAccounts.delay()
            return redirect(
                url_for("tasks.check",
                        id=task.id,
                        r=url_for("admin.admin_page")))
        elif action == "importscreenshots":
            packages = Package.query \
             .filter_by(soft_deleted=False) \
             .outerjoin(PackageScreenshot, Package.id==PackageScreenshot.package_id) \
             .filter(PackageScreenshot.id==None) \
             .all()
            for package in packages:
                importRepoScreenshot.delay(package.id)

            return redirect(url_for("admin.admin_page"))
        elif action == "restore":
            package = Package.query.get(request.form["package"])
            if package is None:
                flash("Unknown package", "danger")
            else:
                package.soft_deleted = False
                db.session.commit()
                return redirect(url_for("admin.admin_page"))
        elif action == "importdepends":
            task = importAllDependencies.delay()
            return redirect(
                url_for("tasks.check",
                        id=task.id,
                        r=url_for("admin.admin_page")))
        elif action == "modprovides":
            packages = Package.query.filter_by(type=PackageType.MOD).all()
            mpackage_cache = {}
            for p in packages:
                if len(p.provides) == 0:
                    p.provides.append(
                        MetaPackage.GetOrCreate(p.name, mpackage_cache))

            db.session.commit()
            return redirect(url_for("admin.admin_page"))
        elif action == "recalcscores":
            for p in Package.query.all():
                p.setStartScore()

            db.session.commit()
            return redirect(url_for("admin.admin_page"))
        elif action == "vcsrelease":
            for package in Package.query.filter(
                    Package.repo.isnot(None)).all():
                if package.releases.count() != 0:
                    continue

                rel = PackageRelease()
                rel.package = package
                rel.title = datetime.date.today().isoformat()
                rel.url = ""
                rel.task_id = uuid()
                rel.approved = True
                db.session.add(rel)
                db.session.commit()

                makeVCSRelease.apply_async((rel.id, "master"),
                                           task_id=rel.task_id)

                msg = "{}: Release {} created".format(package.title, rel.title)
                triggerNotif(package.author, current_user, msg,
                             rel.getEditURL())
                db.session.commit()

        else:
            flash("Unknown action: " + action, "danger")

    deleted_packages = Package.query.filter_by(soft_deleted=True).all()
    return render_template("admin/list.html",
                           deleted_packages=deleted_packages)
예제 #6
0
def admin_page():
	if request.method == "POST":
		action = request.form["action"]
		if action == "delstuckreleases":
			PackageRelease.query.filter(PackageRelease.task_id != None).delete()
			db.session.commit()
			return redirect(url_for("admin.admin_page"))
		elif action == "checkreleases":
			releases = PackageRelease.query.filter(PackageRelease.url.like("/uploads/%")).all()

			tasks = []
			for release in releases:
				zippath = release.url.replace("/uploads/", app.config["UPLOAD_DIR"])
				tasks.append(checkZipRelease.s(release.id, zippath))

			result = group(tasks).apply_async()

			while not result.ready():
				import time
				time.sleep(0.1)

			return redirect(url_for("todo.view"))
		elif action == "importmodlist":
			task = importTopicList.delay()
			return redirect(url_for("tasks.check", id=task.id, r=url_for("todo.topics")))
		elif action == "checkusers":
			task = checkAllForumAccounts.delay()
			return redirect(url_for("tasks.check", id=task.id, r=url_for("admin.admin_page")))
		elif action == "importscreenshots":
			packages = Package.query \
				.filter_by(soft_deleted=False) \
				.outerjoin(PackageScreenshot, Package.id==PackageScreenshot.package_id) \
				.filter(PackageScreenshot.id==None) \
				.all()
			for package in packages:
				importRepoScreenshot.delay(package.id)

			return redirect(url_for("admin.admin_page"))
		elif action == "restore":
			package = Package.query.get(request.form["package"])
			if package is None:
				flash("Unknown package", "danger")
			else:
				package.soft_deleted = False
				db.session.commit()
				return redirect(url_for("admin.admin_page"))
		elif action == "modprovides":
			packages = Package.query.filter_by(type=PackageType.MOD).all()
			mpackage_cache = {}
			for p in packages:
				if len(p.provides) == 0:
					p.provides.append(MetaPackage.GetOrCreate(p.name, mpackage_cache))

			db.session.commit()
			return redirect(url_for("admin.admin_page"))
		elif action == "recalcscores":
			for p in Package.query.all():
				p.setStartScore()

			db.session.commit()
			return redirect(url_for("admin.admin_page"))
		elif action == "vcsrelease":
			for package in Package.query.filter(Package.repo.isnot(None)).all():
				if package.releases.count() != 0:
					continue

				rel = PackageRelease()
				rel.package  = package
				rel.title    = datetime.date.today().isoformat()
				rel.url      = ""
				rel.task_id  = uuid()
				rel.approved = True
				db.session.add(rel)
				db.session.commit()

				makeVCSRelease.apply_async((rel.id, "master"), task_id=rel.task_id)

				msg = "{}: Release {} created".format(package.title, rel.title)
				triggerNotif(package.author, current_user, msg, rel.getEditURL())
				db.session.commit()

		elif action == "cleanuploads":
			upload_dir = app.config['UPLOAD_DIR']

			(_, _, filenames) = next(os.walk(upload_dir))
			existing_uploads = set(filenames)

			if len(existing_uploads) != 0:
				def getURLsFromDB(column):
					results = db.session.query(column).filter(column != None, column != "").all()
					return set([os.path.basename(x[0]) for x in results])

				release_urls = getURLsFromDB(PackageRelease.url)
				screenshot_urls = getURLsFromDB(PackageScreenshot.url)

				db_urls = release_urls.union(screenshot_urls)
				unreachable = existing_uploads.difference(db_urls)

				import sys
				print("On Disk: ", existing_uploads, file=sys.stderr)
				print("In DB: ", db_urls, file=sys.stderr)
				print("Unreachable: ", unreachable, file=sys.stderr)

				for filename in unreachable:
					os.remove(os.path.join(upload_dir, filename))

				flash("Deleted " + str(len(unreachable)) + " unreachable uploads", "success")
			else:
				flash("No downloads to create", "danger")

		else:
			flash("Unknown action: " + action, "danger")

	deleted_packages = Package.query.filter_by(soft_deleted=True).all()
	return render_template("admin/list.html", deleted_packages=deleted_packages)
예제 #7
0
def create_release(package):
    if not package.checkPerm(current_user, Permission.MAKE_RELEASE):
        return redirect(package.getDetailsURL())

    # Initial form class from post data and default data
    form = CreatePackageReleaseForm()
    if package.repo is not None:
        form["uploadOpt"].choices = [("vcs", "Import from Git"),
                                     ("upload", "Upload .zip file")]
        if request.method != "POST":
            form["uploadOpt"].data = "vcs"

    if form.validate_on_submit():
        if form["uploadOpt"].data == "vcs":
            rel = PackageRelease()
            rel.package = package
            rel.title = form["title"].data
            rel.url = ""
            rel.task_id = uuid()
            rel.min_rel = form["min_rel"].data.getActual()
            rel.max_rel = form["max_rel"].data.getActual()
            db.session.add(rel)
            db.session.commit()

            makeVCSRelease.apply_async(
                (rel.id, nonEmptyOrNone(form.vcsLabel.data)),
                task_id=rel.task_id)

            msg = "Release {} created".format(rel.title)
            addNotification(package.maintainers,
                            current_user, NotificationType.PACKAGE_EDIT, msg,
                            rel.getEditURL(), package)
            db.session.commit()

            return redirect(
                url_for("tasks.check", id=rel.task_id, r=rel.getEditURL()))
        else:
            uploadedUrl, uploadedPath = doFileUpload(form.fileUpload.data,
                                                     "zip", "a zip file")
            if uploadedUrl is not None:
                rel = PackageRelease()
                rel.package = package
                rel.title = form["title"].data
                rel.url = uploadedUrl
                rel.task_id = uuid()
                rel.min_rel = form["min_rel"].data.getActual()
                rel.max_rel = form["max_rel"].data.getActual()
                db.session.add(rel)
                db.session.commit()

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

                msg = "Release {} created".format(rel.title)
                addNotification(package.maintainers, current_user,
                                NotificationType.PACKAGE_EDIT, msg,
                                rel.getEditURL(), package)
                db.session.commit()

                return redirect(
                    url_for("tasks.check", id=rel.task_id, r=rel.getEditURL()))

    return render_template("packages/release_new.html",
                           package=package,
                           form=form)
예제 #8
0
def admin_page():
    if request.method == "POST":
        action = request.form["action"]
        if action == "importmodlist":
            task = importTopicList.delay()
            return redirect(
                url_for("check_task",
                        id=task.id,
                        r=url_for("todo_topics_page")))
        elif action == "importscreenshots":
            packages = Package.query \
             .filter_by(soft_deleted=False) \
             .outerjoin(PackageScreenshot, Package.id==PackageScreenshot.package_id) \
             .filter(PackageScreenshot.id==None) \
             .all()
            for package in packages:
                importRepoScreenshot.delay(package.id)

            return redirect(url_for("admin_page"))
        elif action == "restore":
            package = Package.query.get(request.form["package"])
            if package is None:
                flash("Unknown package", "error")
            else:
                package.soft_deleted = False
                db.session.commit()
                return redirect(url_for("admin_page"))
        elif action == "importdepends":
            task = importAllDependencies.delay()
            return redirect(
                url_for("check_task", id=task.id, r=url_for("admin_page")))
        elif action == "modprovides":
            packages = Package.query.filter_by(type=PackageType.MOD).all()
            mpackage_cache = {}
            for p in packages:
                if len(p.provides) == 0:
                    p.provides.append(
                        MetaPackage.GetOrCreate(p.name, mpackage_cache))

            db.session.commit()
            return redirect(url_for("admin_page"))
        elif action == "recalcscores":
            for p in Package.query.all():
                p.recalcScore()

            db.session.commit()
            return redirect(url_for("admin_page"))
        elif action == "vcsrelease":
            for package in Package.query.filter(
                    Package.repo.isnot(None)).all():
                if package.releases.count() != 0:
                    continue

                rel = PackageRelease()
                rel.package = package
                rel.title = datetime.date.today().isoformat()
                rel.url = ""
                rel.task_id = uuid()
                rel.approved = True
                db.session.add(rel)
                db.session.commit()

                makeVCSRelease.apply_async((rel.id, "master"),
                                           task_id=rel.task_id)

                msg = "{}: Release {} created".format(package.title, rel.title)
                triggerNotif(package.author, current_user, msg,
                             rel.getEditURL())
                db.session.commit()

        else:
            flash("Unknown action: " + action, "error")

    deleted_packages = Package.query.filter_by(soft_deleted=True).all()
    return render_template("admin/list.html",
                           deleted_packages=deleted_packages)