mirror of https://gitlab.com/litecord/litecord.git
Merge branch 'permission-refactor' into 'master'
Permission refactor Closes #115 See merge request litecord/litecord!68
This commit is contained in:
commit
bdf7d875ba
|
|
@ -46,6 +46,7 @@ from litecord.embed.messages import process_url_embed, msg_update_embeds
|
||||||
from litecord.common.channels import channel_ack
|
from litecord.common.channels import channel_ack
|
||||||
from litecord.pubsub.user import dispatch_user
|
from litecord.pubsub.user import dispatch_user
|
||||||
from litecord.permissions import get_permissions, Permissions
|
from litecord.permissions import get_permissions, Permissions
|
||||||
|
from litecord.errors import GuildNotFound
|
||||||
|
|
||||||
log = Logger(__name__)
|
log = Logger(__name__)
|
||||||
bp = Blueprint("channels", __name__)
|
bp = Blueprint("channels", __name__)
|
||||||
|
|
@ -397,13 +398,16 @@ async def _process_overwrites(guild_id: int, channel_id: int, overwrites: list)
|
||||||
|
|
||||||
if target.is_user:
|
if target.is_user:
|
||||||
perms = Permissions(overwrite["allow"] & ~overwrite["deny"])
|
perms = Permissions(overwrite["allow"] & ~overwrite["deny"])
|
||||||
|
assert target.user_id is not None
|
||||||
await _dispatch_action(guild_id, channel_id, target.user_id, perms)
|
await _dispatch_action(guild_id, channel_id, target.user_id, perms)
|
||||||
|
|
||||||
elif target.is_role:
|
elif target.is_role:
|
||||||
|
assert target.role_id is not None
|
||||||
user_ids.extend(await app.storage.get_role_members(target.role_id))
|
user_ids.extend(await app.storage.get_role_members(target.role_id))
|
||||||
|
|
||||||
for user_id in user_ids:
|
for user_id in user_ids:
|
||||||
perms = await get_permissions(user_id, channel_id)
|
perms = await get_permissions(user_id, channel_id)
|
||||||
|
assert target.user_id is not None
|
||||||
await _dispatch_action(guild_id, channel_id, target.user_id, perms)
|
await _dispatch_action(guild_id, channel_id, target.user_id, perms)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -675,7 +679,12 @@ async def ack_channel(channel_id, message_id):
|
||||||
async def delete_read_state(channel_id):
|
async def delete_read_state(channel_id):
|
||||||
"""Delete the read state of a channel."""
|
"""Delete the read state of a channel."""
|
||||||
user_id = await token_check()
|
user_id = await token_check()
|
||||||
|
try:
|
||||||
await channel_check(user_id, channel_id)
|
await channel_check(user_id, channel_id)
|
||||||
|
except GuildNotFound:
|
||||||
|
# ignore when guild isn't found because we're deleting the
|
||||||
|
# read state regardless.
|
||||||
|
pass
|
||||||
|
|
||||||
await app.db.execute(
|
await app.db.execute(
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ from litecord.auth import token_check
|
||||||
from litecord.schemas import validate, USER_SETTINGS, GUILD_SETTINGS
|
from litecord.schemas import validate, USER_SETTINGS, GUILD_SETTINGS
|
||||||
from litecord.blueprints.checks import guild_check
|
from litecord.blueprints.checks import guild_check
|
||||||
from litecord.pubsub.user import dispatch_user
|
from litecord.pubsub.user import dispatch_user
|
||||||
|
from litecord.errors import UserNotFound
|
||||||
|
|
||||||
bp = Blueprint("users_settings", __name__)
|
bp = Blueprint("users_settings", __name__)
|
||||||
|
|
||||||
|
|
@ -129,6 +130,26 @@ async def patch_guild_settings(guild_id: int):
|
||||||
return jsonify(settings)
|
return jsonify(settings)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/@me/notes/<int:target_id>", methods=["GET"])
|
||||||
|
async def get_note(target_id: int):
|
||||||
|
"""Get a single note from a user."""
|
||||||
|
user_id = await token_check()
|
||||||
|
note = await app.db.fetchval(
|
||||||
|
"""
|
||||||
|
SELECT note
|
||||||
|
FROM notes
|
||||||
|
WHERE user_id = $1 AND target_id = $2
|
||||||
|
""",
|
||||||
|
user_id,
|
||||||
|
target_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
if note is None:
|
||||||
|
raise UserNotFound()
|
||||||
|
|
||||||
|
return jsonify({"user_id": user_id, "note_user_id": target_id, "note": note})
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/@me/notes/<int:target_id>", methods=["PUT"])
|
@bp.route("/@me/notes/<int:target_id>", methods=["PUT"])
|
||||||
async def put_note(target_id: int):
|
async def put_note(target_id: int):
|
||||||
"""Put a note to a user.
|
"""Put a note to a user.
|
||||||
|
|
|
||||||
|
|
@ -104,9 +104,7 @@ async def majority_region(user_id: int) -> Optional[str]:
|
||||||
return _majority_region_count(regions)
|
return _majority_region_count(regions)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/regions", methods=["GET"])
|
async def _all_regions():
|
||||||
async def voice_regions():
|
|
||||||
"""Return voice regions."""
|
|
||||||
user_id = await token_check()
|
user_id = await token_check()
|
||||||
|
|
||||||
best_region = await majority_region(user_id)
|
best_region = await majority_region(user_id)
|
||||||
|
|
@ -116,3 +114,16 @@ async def voice_regions():
|
||||||
region["optimal"] = region["id"] == best_region
|
region["optimal"] = region["id"] == best_region
|
||||||
|
|
||||||
return jsonify(regions)
|
return jsonify(regions)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/regions", methods=["GET"])
|
||||||
|
async def voice_regions():
|
||||||
|
"""Return voice regions."""
|
||||||
|
return await _all_regions()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/guilds/<int:guild_id>/regions", methods=["GET"])
|
||||||
|
async def guild_voice_regions():
|
||||||
|
"""Return voice regions."""
|
||||||
|
# we return the same list as the normal /regions route on purpose.
|
||||||
|
return await _all_regions()
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,10 @@ class WebhookNotFound(NotFound):
|
||||||
error_code = 10015
|
error_code = 10015
|
||||||
|
|
||||||
|
|
||||||
|
class UserNotFound(NotFound):
|
||||||
|
error_code = 10013
|
||||||
|
|
||||||
|
|
||||||
class Ratelimited(LitecordError):
|
class Ratelimited(LitecordError):
|
||||||
status_code = 429
|
status_code = 429
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
|
|
||||||
from quart import current_app as app
|
from quart import current_app as app
|
||||||
|
|
||||||
|
|
@ -77,8 +77,10 @@ class Permissions(ctypes.Union):
|
||||||
|
|
||||||
_fields_ = [("bits", _RawPermsBits), ("binary", ctypes.c_uint64)]
|
_fields_ = [("bits", _RawPermsBits), ("binary", ctypes.c_uint64)]
|
||||||
|
|
||||||
def __init__(self, val: int):
|
def __init__(self, val: Union[str, int]):
|
||||||
self.binary = val
|
# always coerce to int, even when the user gives us a str, because
|
||||||
|
# python ints are infinity-sized (yes, yes, the memory concerns, yes)
|
||||||
|
self.binary = int(val)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Permissions binary={self.binary}>"
|
return f"<Permissions binary={self.binary}>"
|
||||||
|
|
@ -87,7 +89,7 @@ class Permissions(ctypes.Union):
|
||||||
return self.binary
|
return self.binary
|
||||||
|
|
||||||
|
|
||||||
ALL_PERMISSIONS = Permissions(0b01111111111101111111110111111111)
|
ALL_PERMISSIONS = Permissions(0b01111111111111111111111111111111)
|
||||||
EMPTY_PERMISSIONS = Permissions(0)
|
EMPTY_PERMISSIONS = Permissions(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -469,6 +469,10 @@ class Storage:
|
||||||
|
|
||||||
def _overwrite_convert(row):
|
def _overwrite_convert(row):
|
||||||
drow = dict(row)
|
drow = dict(row)
|
||||||
|
drow["allow_new"] = str(drow["allow"])
|
||||||
|
drow["deny_new"] = str(drow["deny"])
|
||||||
|
drow["allow"] = drow["allow"] & ((2 << 31) - 1)
|
||||||
|
drow["deny"] = drow["deny"] & ((2 << 31) - 1)
|
||||||
|
|
||||||
target_type = drow["target_type"]
|
target_type = drow["target_type"]
|
||||||
drow["type"] = "member" if target_type == 0 else "role"
|
drow["type"] = "member" if target_type == 0 else "role"
|
||||||
|
|
@ -673,7 +677,12 @@ class Storage:
|
||||||
if not row:
|
if not row:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return dict(row)
|
drow = dict(row)
|
||||||
|
|
||||||
|
drow["permissions_new"] = str(drow["permissions"])
|
||||||
|
drow["permissions"] = drow["permissions"] & ((2 << 31) - 1)
|
||||||
|
|
||||||
|
return drow
|
||||||
|
|
||||||
async def get_role_data(self, guild_id: int) -> List[Dict[str, Any]]:
|
async def get_role_data(self, guild_id: int) -> List[Dict[str, Any]]:
|
||||||
"""Get role list information on a guild."""
|
"""Get role list information on a guild."""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- channel_overwrites table already has allow and deny as bigints.
|
||||||
|
alter table roles
|
||||||
|
alter column permissions type bigint;
|
||||||
Loading…
Reference in New Issue