pull/182/head
parent
8b1f7baa74
commit
6e02ea8abb
|
@ -7321,6 +7321,10 @@ input[type=number] {
|
|||
height: 50px;
|
||||
}
|
||||
|
||||
.group-mod {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.award-tab {
|
||||
font-size: 10px !important;
|
||||
|
@ -7343,6 +7347,10 @@ input[type=number] {
|
|||
.group-owner {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.group-mod {
|
||||
height: 23px;
|
||||
}
|
||||
}
|
||||
|
||||
#input-message, #input-message-mobile {
|
||||
|
|
|
@ -6,6 +6,8 @@ function approve_membership(t, group, uid) {
|
|||
{
|
||||
},
|
||||
() => {
|
||||
const mod = document.getElementById(`mod-${uid}`)
|
||||
if (mod) mod.classList.remove('d-none')
|
||||
document.getElementById(`kick-${uid}`).classList.remove('d-none')
|
||||
document.getElementById(`time-${uid}`).innerHTML = formatDate(new Date());
|
||||
document.getElementById(`counter-${uid}`).innerHTML = parseInt(members_tbody.lastElementChild.firstElementChild.innerHTML) + 1
|
||||
|
|
|
@ -2,7 +2,7 @@ import time
|
|||
|
||||
from sqlalchemy import Column, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.types import Integer, String
|
||||
from sqlalchemy.types import Integer, String, Boolean
|
||||
|
||||
from files.classes import Base
|
||||
|
||||
|
@ -12,6 +12,7 @@ class GroupMembership(Base):
|
|||
group_name = Column(String, ForeignKey("groups.name"), primary_key=True)
|
||||
created_utc = Column(Integer)
|
||||
approved_utc = Column(Integer)
|
||||
is_mod = Column(Boolean, default=False)
|
||||
|
||||
user = relationship("User", uselist=False)
|
||||
|
||||
|
|
|
@ -393,6 +393,13 @@ class User(Base):
|
|||
except:
|
||||
return bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
|
||||
|
||||
@lazy
|
||||
def mods_group(self, group):
|
||||
if self.is_permabanned or self.shadowbanned: return False
|
||||
if self.id == group.owner.id: return True
|
||||
if self.admin_level >= PERMS['MODS_EVERY_GROUP']: return True
|
||||
return bool(g.db.query(GroupMembership.user_id).filter_by(user_id=self.id, group_name=group.name, is_mod=True).one_or_none())
|
||||
|
||||
@lazy
|
||||
def exiler_username(self, sub):
|
||||
exile = g.db.query(Exile).options(load_only(Exile.exiler_id)).filter_by(user_id=self.id, sub=sub).one_or_none()
|
||||
|
|
|
@ -152,8 +152,8 @@ def group_approve(v, group_name, user_id):
|
|||
group = g.db.get(Group, group_name)
|
||||
if not group: abort(404)
|
||||
|
||||
if v.id != group.owner.id and v.admin_level < PERMS['MODS_EVERY_GROUP']:
|
||||
abort(403, f"Only the group owner (@{group.owner.username}) can approve applications!")
|
||||
if not v.mods_group(group):
|
||||
abort(403, f"Only the group owner and its mods can approve applications!")
|
||||
|
||||
application = g.db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
|
||||
if not application:
|
||||
|
@ -178,8 +178,8 @@ def group_reject(v, group_name, user_id):
|
|||
group = g.db.get(Group, group_name)
|
||||
if not group: abort(404)
|
||||
|
||||
if v.id != group.owner.id and v.admin_level < PERMS['MODS_EVERY_GROUP']:
|
||||
abort(403, f"Only the group owner (@{group.owner.username}) can reject memberships!")
|
||||
if not v.mods_group(group):
|
||||
abort(403, f"Only the group owner and its mods can reject memberships!")
|
||||
|
||||
membership = g.db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
|
||||
if not membership:
|
||||
|
@ -204,3 +204,55 @@ def group_reject(v, group_name, user_id):
|
|||
g.db.delete(group)
|
||||
|
||||
return {"message": msg}
|
||||
|
||||
@app.post("/!<group_name>/<user_id>/add_mod")
|
||||
@limiter.limit('1/second', scope=rpath)
|
||||
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||
@auth_required
|
||||
def group_add_mod(v, group_name, user_id):
|
||||
group_name = group_name.strip().lower()
|
||||
|
||||
group = g.db.get(Group, group_name)
|
||||
if not group: abort(404)
|
||||
|
||||
if v.id != group.owner.id:
|
||||
abort(403, f"Only the group owner (@{group.owner.username}) can add mods!")
|
||||
|
||||
membership = g.db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
|
||||
if not membership:
|
||||
abort(404, "The user is not a member of the group!")
|
||||
|
||||
membership.is_mod = True
|
||||
g.db.add(membership)
|
||||
|
||||
send_repeatable_notification(membership.user_id, f"@{v.username} (!{group}'s owner) has added you as a mod!")
|
||||
|
||||
return {"message": f'You have added @{membership.user.username} as a mod successfully!'}
|
||||
|
||||
@app.post("/!<group_name>/<user_id>/remove_mod")
|
||||
@limiter.limit('1/second', scope=rpath)
|
||||
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||
@auth_required
|
||||
def group_remove_mod(v, group_name, user_id):
|
||||
group_name = group_name.strip().lower()
|
||||
|
||||
group = g.db.get(Group, group_name)
|
||||
if not group: abort(404)
|
||||
|
||||
if v.id != group.owner.id:
|
||||
abort(403, f"Only the group owner (@{group.owner.username}) can remove mods!")
|
||||
|
||||
membership = g.db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
|
||||
if not membership:
|
||||
abort(404, "The user is not a member of the group!")
|
||||
|
||||
membership.is_mod = False
|
||||
g.db.add(membership)
|
||||
|
||||
send_repeatable_notification(membership.user_id, f"@{v.username} (!{group}'s owner) has removed you as a mod!")
|
||||
|
||||
return {"message": f'You have removed @{membership.user.username} as a mod successfully!'}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<th>Applied on</th>
|
||||
{% endif %}
|
||||
|
||||
{% if v.id == group.owner.id or v.admin_level >= PERMS['MODS_EVERY_GROUP'] %}
|
||||
{% if v.mods_group(group) %}
|
||||
<th class="disable-sort-click"></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
@ -47,6 +47,8 @@
|
|||
{% endwith %}
|
||||
{% if owner %}
|
||||
<img class="mx-2 group-owner" data-bs-toggle="tooltip" alt="Owner" title="Owner" src="{{SITE_FULL_IMAGES}}/e/marseykingretard.webp">
|
||||
{% elif membership.is_mod %}
|
||||
<img class="mx-2 group-mod" data-bs-toggle="tooltip" alt="Mod" title="Mod" src="{{SITE_FULL_IMAGES}}/e/marseyjanny.webp">
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
|
@ -56,8 +58,15 @@
|
|||
<td id="time-{{membership.user_id}}" data-time="{{membership.created_utc}}"></td>
|
||||
{% endif %}
|
||||
|
||||
{% if v.id == group.owner.id or v.admin_level >= PERMS['MODS_EVERY_GROUP'] %}
|
||||
{% if v.mods_group(group) %}
|
||||
<td>
|
||||
{% if v.id == group.owner.id and v.id != membership.user_id %}
|
||||
<div id="mod-{{membership.user_id}}" class="mb-2 {% if name == 'applications' %}d-none{% endif %}">
|
||||
<button id="add-mod-{{membership.user_id}}" type="button" class="btn btn-success btn-block {% if membership.is_mod %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/!{{group.name}}/{{membership.user_id}}/add_mod','add-mod-{{membership.user_id}}','remove-mod-{{membership.user_id}}','d-none')">Add as Mod</button>
|
||||
<button id="remove-mod-{{membership.user_id}}" type="button" class="btn btn-danger btn-block {% if not membership.is_mod %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/!{{group.name}}/{{membership.user_id}}/remove_mod','add-mod-{{membership.user_id}}','remove-mod-{{membership.user_id}}','d-none')">Remove as Mod</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="kick-{{membership.user_id}}" {% if name == 'applications' %}class="d-none"{% endif %}>
|
||||
<button type="button" class="btn btn-primary btn-block" data-nonce="{{g.nonce}}" data-onclick="reject_membership(this,'{{group}}','{{membership.user_id}}')">{% if v.id == membership.user_id %}Leave{% else %}Kick{% endif %}</button>
|
||||
</div>
|
||||
|
@ -75,7 +84,7 @@
|
|||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% if v.id == group.owner.id or v.admin_level >= PERMS['MODS_EVERY_GROUP'] %}
|
||||
{% if v.mods_group(group) %}
|
||||
{{process_memberships(applications, 'applications')}}
|
||||
{{process_memberships(members, 'members')}}
|
||||
<script defer src="{{'js/group_members_owner.js' | asset}}"></script>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
alter table group_memberships add column is_mod bool not null default false;
|
||||
alter table group_memberships alter column is_mod drop default;
|
Loading…
Reference in New Issue