mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-23 14:32:25 +01:00
parent
ecb3d83c57
commit
a72b9a174a
@ -382,3 +382,37 @@ def remove(package):
|
|||||||
return redirect(package.getDetailsURL())
|
return redirect(package.getDetailsURL())
|
||||||
else:
|
else:
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PackageMaintainersForm(FlaskForm):
|
||||||
|
maintainers_str = StringField("Maintainers (Comma-separated)", [Optional()])
|
||||||
|
submit = SubmitField("Save")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/packages/<author>/<name>/edit-maintainers/", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
|
@is_package_page
|
||||||
|
def edit_maintainers(package):
|
||||||
|
if not package.checkPerm(current_user, Permission.EDIT_MAINTAINERS):
|
||||||
|
flash("You do not have permission to edit maintainers", "danger")
|
||||||
|
return redirect(package.getDetailsURL())
|
||||||
|
|
||||||
|
form = PackageMaintainersForm(formdata=request.form)
|
||||||
|
if request.method == "GET":
|
||||||
|
form.maintainers_str.data = ", ".join([ x.username for x in package.maintainers ])
|
||||||
|
|
||||||
|
if request.method == "POST" and form.validate():
|
||||||
|
usernames = [x.strip() for x in form.maintainers_str.data.split(",")]
|
||||||
|
users = User.query.filter(func.lower(User.username).in_(usernames)).all()
|
||||||
|
package.maintainers.clear()
|
||||||
|
package.maintainers.extend(users)
|
||||||
|
package.maintainers.append(package.author)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return redirect(package.getDetailsURL())
|
||||||
|
|
||||||
|
users = User.query.filter(User.rank >= UserRank.NEW_MEMBER).order_by(db.asc(User.username)).all()
|
||||||
|
|
||||||
|
return render_template("packages/edit_maintainers.html", \
|
||||||
|
package=package, form=form, users=users)
|
||||||
|
@ -11,7 +11,7 @@ title: Ranks and Permissions
|
|||||||
|
|
||||||
## Breakdown
|
## Breakdown
|
||||||
|
|
||||||
<table class="fancyTable">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Rank</th>
|
<th>Rank</th>
|
||||||
@ -84,6 +84,21 @@ title: Ranks and Permissions
|
|||||||
<th>✓</th> <!-- admin -->
|
<th>✓</th> <!-- admin -->
|
||||||
<th>✓</th>
|
<th>✓</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Edit Maintainers</td>
|
||||||
|
<th>✓</th> <!-- new -->
|
||||||
|
<th></th>
|
||||||
|
<th>✓</th> <!-- member -->
|
||||||
|
<th></th>
|
||||||
|
<th>✓</th> <!-- trusted member -->
|
||||||
|
<th></th>
|
||||||
|
<th>✓</th> <!-- editor -->
|
||||||
|
<th></th>
|
||||||
|
<th>✓</th> <!-- moderator -->
|
||||||
|
<th>✓</th>
|
||||||
|
<th>✓</th> <!-- admin -->
|
||||||
|
<th>✓</th>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Add/Delete Screenshot</td>
|
<td>Add/Delete Screenshot</td>
|
||||||
<th>✓</th> <!-- new -->
|
<th>✓</th> <!-- new -->
|
||||||
@ -114,36 +129,6 @@ title: Ranks and Permissions
|
|||||||
<th>✓</th> <!-- admin -->
|
<th>✓</th> <!-- admin -->
|
||||||
<th>✓</th>
|
<th>✓</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>Approve EditRequest</td>
|
|
||||||
<th></th> <!-- new -->
|
|
||||||
<th></th>
|
|
||||||
<th>✓</th> <!-- member -->
|
|
||||||
<th></th>
|
|
||||||
<th>✓</th> <!-- trusted member -->
|
|
||||||
<th></th>
|
|
||||||
<th>✓</th> <!-- editor -->
|
|
||||||
<th>✓</th>
|
|
||||||
<th>✓</th> <!-- moderator -->
|
|
||||||
<th>✓</th>
|
|
||||||
<th>✓</th> <!-- admin -->
|
|
||||||
<th>✓</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Edit EditRequest</td>
|
|
||||||
<th>✓<sup>1</sup></th> <!-- new -->
|
|
||||||
<th></th>
|
|
||||||
<th>✓</th> <!-- member -->
|
|
||||||
<th></th>
|
|
||||||
<th>✓</th> <!-- trusted member -->
|
|
||||||
<th></th>
|
|
||||||
<th>✓</th> <!-- editor -->
|
|
||||||
<th>✓</th>
|
|
||||||
<th>✓</th> <!-- moderator -->
|
|
||||||
<th>✓</th>
|
|
||||||
<th>✓</th> <!-- admin -->
|
|
||||||
<th>✓</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Make Release</td>
|
<td>Make Release</td>
|
||||||
<th>✓</th> <!-- new -->
|
<th>✓</th> <!-- new -->
|
||||||
|
@ -93,6 +93,7 @@ class Permission(enum.Enum):
|
|||||||
UNAPPROVE_PACKAGE = "UNAPPROVE_PACKAGE"
|
UNAPPROVE_PACKAGE = "UNAPPROVE_PACKAGE"
|
||||||
TOPIC_DISCARD = "TOPIC_DISCARD"
|
TOPIC_DISCARD = "TOPIC_DISCARD"
|
||||||
CREATE_TOKEN = "CREATE_TOKEN"
|
CREATE_TOKEN = "CREATE_TOKEN"
|
||||||
|
EDIT_MAINTAINERS = "EDIT_MAINTAINERS"
|
||||||
CHANGE_PROFILE_URLS = "CHANGE_PROFILE_URLS"
|
CHANGE_PROFILE_URLS = "CHANGE_PROFILE_URLS"
|
||||||
|
|
||||||
# Only return true if the permission is valid for *all* contexts
|
# Only return true if the permission is valid for *all* contexts
|
||||||
@ -323,6 +324,11 @@ tags = db.Table("tags",
|
|||||||
db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True)
|
db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
maintainers = db.Table("maintainers",
|
||||||
|
db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True),
|
||||||
|
db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True)
|
||||||
|
)
|
||||||
|
|
||||||
class Dependency(db.Model):
|
class Dependency(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
depender_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True)
|
depender_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True)
|
||||||
@ -454,6 +460,8 @@ class Package(db.Model):
|
|||||||
requests = db.relationship("EditRequest", backref="package",
|
requests = db.relationship("EditRequest", backref="package",
|
||||||
lazy="dynamic")
|
lazy="dynamic")
|
||||||
|
|
||||||
|
maintainers = db.relationship("User", secondary=maintainers, lazy="subquery")
|
||||||
|
|
||||||
def __init__(self, package=None):
|
def __init__(self, package=None):
|
||||||
if package is None:
|
if package is None:
|
||||||
return
|
return
|
||||||
@ -633,6 +641,10 @@ class Package(db.Model):
|
|||||||
return url_for("packages.download",
|
return url_for("packages.download",
|
||||||
author=self.author.username, name=self.name)
|
author=self.author.username, name=self.name)
|
||||||
|
|
||||||
|
def getEditMaintainersURL(self):
|
||||||
|
return url_for("packages.edit_maintainers",
|
||||||
|
author=self.author.username, name=self.name)
|
||||||
|
|
||||||
def getDownloadRelease(self, version=None):
|
def getDownloadRelease(self, version=None):
|
||||||
for rel in self.releases:
|
for rel in self.releases:
|
||||||
if rel.approved and (version is None or
|
if rel.approved and (version is None or
|
||||||
@ -658,19 +670,17 @@ class Package(db.Model):
|
|||||||
raise Exception("Unknown permission given to Package.checkPerm()")
|
raise Exception("Unknown permission given to Package.checkPerm()")
|
||||||
|
|
||||||
isOwner = user == self.author
|
isOwner = user == self.author
|
||||||
|
isMaintainer = isOwner or user.rank.atLeast(UserRank.EDITOR) or user in self.maintainers
|
||||||
|
|
||||||
if perm == Permission.CREATE_THREAD:
|
if perm == Permission.CREATE_THREAD:
|
||||||
return user.rank.atLeast(UserRank.MEMBER)
|
return user.rank.atLeast(UserRank.MEMBER)
|
||||||
|
|
||||||
# Members can edit their own packages, and editors can edit any packages
|
# Members can edit their own packages, and editors can edit any packages
|
||||||
if perm == Permission.MAKE_RELEASE or perm == Permission.ADD_SCREENSHOTS:
|
elif perm == Permission.MAKE_RELEASE or perm == Permission.ADD_SCREENSHOTS:
|
||||||
return isOwner or user.rank.atLeast(UserRank.EDITOR)
|
return isMaintainer
|
||||||
|
|
||||||
if perm == Permission.EDIT_PACKAGE or perm == Permission.APPROVE_CHANGES or perm == Permission.APPROVE_RELEASE:
|
elif perm == Permission.EDIT_PACKAGE or perm == Permission.APPROVE_CHANGES or perm == Permission.APPROVE_RELEASE:
|
||||||
if isOwner:
|
return isMaintainer and user.rank.atLeast(UserRank.MEMBER if self.approved else UserRank.NEW_MEMBER)
|
||||||
return user.rank.atLeast(UserRank.MEMBER if self.approved else UserRank.NEW_MEMBER)
|
|
||||||
else:
|
|
||||||
return user.rank.atLeast(UserRank.EDITOR)
|
|
||||||
|
|
||||||
# Anyone can change the package name when not approved, but only editors when approved
|
# Anyone can change the package name when not approved, but only editors when approved
|
||||||
elif perm == Permission.CHANGE_NAME:
|
elif perm == Permission.CHANGE_NAME:
|
||||||
@ -681,10 +691,10 @@ class Package(db.Model):
|
|||||||
return user.rank.atLeast(UserRank.EDITOR)
|
return user.rank.atLeast(UserRank.EDITOR)
|
||||||
|
|
||||||
elif perm == Permission.APPROVE_SCREENSHOT:
|
elif perm == Permission.APPROVE_SCREENSHOT:
|
||||||
if isOwner:
|
return isMaintainer and user.rank.atLeast(UserRank.TRUSTED_MEMBER if self.approved else UserRank.NEW_MEMBER)
|
||||||
return user.rank.atLeast(UserRank.TRUSTED_MEMBER if self.approved else UserRank.NEW_MEMBER)
|
|
||||||
else:
|
elif perm == Permission.EDIT_MAINTAINERS:
|
||||||
return user.rank.atLeast(UserRank.EDITOR)
|
return isOwner or user.rank.atLeast(UserRank.MODERATOR)
|
||||||
|
|
||||||
# Moderators can delete packages
|
# Moderators can delete packages
|
||||||
elif perm == Permission.DELETE_PACKAGE or perm == Permission.UNAPPROVE_PACKAGE \
|
elif perm == Permission.DELETE_PACKAGE or perm == Permission.UNAPPROVE_PACKAGE \
|
||||||
@ -1077,10 +1087,12 @@ class Thread(db.Model):
|
|||||||
elif type(perm) != Permission:
|
elif type(perm) != Permission:
|
||||||
raise Exception("Unknown permission given to Thread.checkPerm()")
|
raise Exception("Unknown permission given to Thread.checkPerm()")
|
||||||
|
|
||||||
isOwner = user == self.author or (self.package is not None and self.package.author == user)
|
isMaintainer = user == self.author or (self.package is not None and self.package.author == user)
|
||||||
|
if self.package:
|
||||||
|
isMaintainer = isMaintainer or user in self.package.maintainers
|
||||||
|
|
||||||
if perm == Permission.SEE_THREAD:
|
if perm == Permission.SEE_THREAD:
|
||||||
return not self.private or isOwner or user.rank.atLeast(UserRank.EDITOR)
|
return not self.private or isMaintainer or user.rank.atLeast(UserRank.EDITOR)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Permission {} is not related to threads".format(perm.name))
|
raise Exception("Permission {} is not related to threads".format(perm.name))
|
||||||
|
19
app/templates/packages/edit_maintainers.html
Normal file
19
app/templates/packages/edit_maintainers.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{{ _("Edit Maintainers") }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% from "macros/forms.html" import render_submit_field, render_field %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ _("Edit Maintainers") }}</h1>
|
||||||
|
|
||||||
|
<form method="POST" action="" class="tableform">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
|
{{ render_field(form.maintainers_str) }}
|
||||||
|
|
||||||
|
<div>{{ render_submit_field(form.submit) }}</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
@ -259,6 +259,21 @@
|
|||||||
<td>Added</td>
|
<td>Added</td>
|
||||||
<td>{{ package.created_at | datetime }}</td>
|
<td>{{ package.created_at | datetime }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Maintainers</td>
|
||||||
|
<td>
|
||||||
|
{% if package.checkPerm(current_user, "EDIT_MAINTAINERS") %}
|
||||||
|
<a class="btn btn-primary btn-sm ml-1 float-right" href="{{ package.getEditMaintainersURL() }}"><i class="fas fa-edit"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for user in package.maintainers %}
|
||||||
|
<a class="badge badge-primary"
|
||||||
|
href="{{ url_for('users.profile', username=package.author.username) }}">
|
||||||
|
{{ user.display_name }}
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
45
migrations/versions/cb6ab141c522_.py
Normal file
45
migrations/versions/cb6ab141c522_.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: cb6ab141c522
|
||||||
|
Revises: 7a48dbd05780
|
||||||
|
Create Date: 2020-07-08 21:03:51.856561
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy import orm
|
||||||
|
from app.models import Package
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'cb6ab141c522'
|
||||||
|
down_revision = '7a48dbd05780'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('maintainers',
|
||||||
|
sa.Column('user_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('package_id', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['package_id'], ['package.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('user_id', 'package_id')
|
||||||
|
)
|
||||||
|
|
||||||
|
bind = op.get_bind()
|
||||||
|
session = orm.Session(bind=bind)
|
||||||
|
|
||||||
|
for package in session.query(Package).all():
|
||||||
|
package.maintainers.append(package.author)
|
||||||
|
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('maintainers')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user