mirror of https://gitlab.com/litecord/litecord.git
channels: add PUT /api/v6/:chan_id/permissions/:overwrite_id
This finishes the basics on channel overwrites.
SQL for instances:
```sql
DROP TABLE channel_overwrites;
```
Then run `schema.sql`.
- channels: finish implementations for update_{text,voice}_channel
- storage: fix _overwrite_convert
- schema.sql: use unique constraint instead of primary key in
channel_overwrites
This commit is contained in:
parent
8ffa14d934
commit
7c274f0f70
|
|
@ -7,7 +7,7 @@ from litecord.auth import token_check
|
||||||
from litecord.enums import ChannelType, GUILD_CHANS
|
from litecord.enums import ChannelType, GUILD_CHANS
|
||||||
from litecord.errors import ChannelNotFound
|
from litecord.errors import ChannelNotFound
|
||||||
from litecord.schemas import (
|
from litecord.schemas import (
|
||||||
validate, CHAN_UPDATE
|
validate, CHAN_UPDATE, CHAN_OVERWRITE
|
||||||
)
|
)
|
||||||
|
|
||||||
from litecord.blueprints.checks import channel_check, channel_perm_check
|
from litecord.blueprints.checks import channel_check, channel_perm_check
|
||||||
|
|
@ -231,6 +231,63 @@ async def _mass_chan_update(guild_id, channel_ids: int):
|
||||||
'guild', guild_id, 'CHANNEL_UPDATE', chan)
|
'guild', guild_id, 'CHANNEL_UPDATE', chan)
|
||||||
|
|
||||||
|
|
||||||
|
async def _process_overwrites(channel_id: int, overwrites: list):
|
||||||
|
for overwrite in overwrites:
|
||||||
|
|
||||||
|
# 0 for user overwrite, 1 for role overwrite
|
||||||
|
target_type = 0 if overwrite['type'] == 'user' else 1
|
||||||
|
target_role = None if target_type == 0 else overwrite['id']
|
||||||
|
target_user = overwrite['id'] if target_type == 0 else None
|
||||||
|
|
||||||
|
await app.db.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO channel_overwrites
|
||||||
|
(channel_id, target_type, target_role,
|
||||||
|
target_user, allow, deny)
|
||||||
|
VALUES
|
||||||
|
($1, $2, $3, $4, $5, $6)
|
||||||
|
ON CONFLICT ON CONSTRAINT channel_overwrites_uniq
|
||||||
|
DO
|
||||||
|
UPDATE
|
||||||
|
SET allow = $5, deny = $6
|
||||||
|
WHERE channel_overwrites.channel_id = $1
|
||||||
|
AND channel_overwrites.target_type = $2
|
||||||
|
AND channel_overwrites.target_role = $3
|
||||||
|
AND channel_overwrites.target_user = $4
|
||||||
|
""",
|
||||||
|
channel_id, target_type,
|
||||||
|
target_role, target_user,
|
||||||
|
overwrite['allow'], overwrite['deny'])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<int:channel_id>/permissions/<int:overwrite_id>', methods=['PUT'])
|
||||||
|
async def put_channel_overwrite(channel_id: int, overwrite_id: int):
|
||||||
|
"""Insert or modify a channel overwrite."""
|
||||||
|
user_id = await token_check()
|
||||||
|
ctype, guild_id = await channel_check(user_id, channel_id)
|
||||||
|
|
||||||
|
if ctype not in GUILD_CHANS:
|
||||||
|
raise ChannelNotFound('Only usable for guild channels.')
|
||||||
|
|
||||||
|
await channel_perm_check(user_id, guild_id, 'manage_roles')
|
||||||
|
|
||||||
|
j = validate(
|
||||||
|
# inserting a fake id on the payload so validation passes through
|
||||||
|
{**await request.get_json(), **{'id': -1}},
|
||||||
|
CHAN_OVERWRITE
|
||||||
|
)
|
||||||
|
|
||||||
|
await _process_overwrites(channel_id, [{
|
||||||
|
'allow': j['allow'],
|
||||||
|
'deny': j['deny'],
|
||||||
|
'type': j['type'],
|
||||||
|
'id': overwrite_id
|
||||||
|
}])
|
||||||
|
|
||||||
|
await _mass_chan_update(guild_id, [channel_id])
|
||||||
|
return '', 204
|
||||||
|
|
||||||
|
|
||||||
async def _update_channel_common(channel_id, guild_id: int, j: dict):
|
async def _update_channel_common(channel_id, guild_id: int, j: dict):
|
||||||
if 'name' in j:
|
if 'name' in j:
|
||||||
await app.db.execute("""
|
await app.db.execute("""
|
||||||
|
|
@ -282,13 +339,47 @@ async def _update_channel_common(channel_id, guild_id: int, j: dict):
|
||||||
# since theres now an empty slot, move current channel to it
|
# since theres now an empty slot, move current channel to it
|
||||||
await _update_pos(channel_id, new_pos)
|
await _update_pos(channel_id, new_pos)
|
||||||
|
|
||||||
|
if 'channel_overwrites' in j:
|
||||||
|
overwrites = j['channel_overwrites']
|
||||||
|
await _process_overwrites(channel_id, overwrites)
|
||||||
|
|
||||||
|
|
||||||
|
async def _common_guild_chan(channel_id, j: dict):
|
||||||
|
# common updates to the guild_channels table
|
||||||
|
for field in [field for field in j.keys()
|
||||||
|
if field in ('nsfw', 'parent_id')]:
|
||||||
|
await app.db.execute(f"""
|
||||||
|
UPDATE guild_channels
|
||||||
|
SET {field} = $1
|
||||||
|
WHERE id = $2
|
||||||
|
""", j[field], channel_id)
|
||||||
|
|
||||||
|
|
||||||
async def _update_text_channel(channel_id: int, j: dict):
|
async def _update_text_channel(channel_id: int, j: dict):
|
||||||
pass
|
# first do the specific ones related to guild_text_channels
|
||||||
|
for field in [field for field in j.keys()
|
||||||
|
if field in ('topic', 'rate_limit_per_user')]:
|
||||||
|
await app.db.execute(f"""
|
||||||
|
UPDATE guild_text_channels
|
||||||
|
SET {field} = $1
|
||||||
|
WHERE id = $2
|
||||||
|
""", j[field], channel_id)
|
||||||
|
|
||||||
|
await _common_guild_chan(channel_id, j)
|
||||||
|
|
||||||
|
|
||||||
async def _update_voice_channel(channel_id: int, j: dict):
|
async def _update_voice_channel(channel_id: int, j: dict):
|
||||||
pass
|
# first do the specific ones in guild_voice_channels
|
||||||
|
for field in [field for field in j.keys()
|
||||||
|
if field in ('bitrate', 'user_limit')]:
|
||||||
|
await app.db.execute(f"""
|
||||||
|
UPDATE guild_voice_channels
|
||||||
|
SET {field} = $1
|
||||||
|
WHERE id = $2
|
||||||
|
""", j[field], channel_id)
|
||||||
|
|
||||||
|
# yes, i'm letting voice channels have nsfw, you cant stop me
|
||||||
|
await _common_guild_chan(channel_id, j)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/<int:channel_id>', methods=['PUT', 'PATCH'])
|
@bp.route('/<int:channel_id>', methods=['PUT', 'PATCH'])
|
||||||
|
|
|
||||||
|
|
@ -252,13 +252,10 @@ GUILD_UPDATE = {
|
||||||
|
|
||||||
|
|
||||||
CHAN_OVERWRITE = {
|
CHAN_OVERWRITE = {
|
||||||
'type': 'dict',
|
'id': {'coerce': int},
|
||||||
'schema': {
|
'type': {'type': 'string', 'allowed': ['role', 'member']},
|
||||||
'id': {'coerce': int},
|
'allow': {'coerce': Permissions},
|
||||||
'type': {'type': 'string', 'allowed': ['role', 'member']},
|
'deny': {'coerce': Permissions}
|
||||||
'allow': {'coerce': Permissions},
|
|
||||||
'deny': {'coerce': Permissions}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -292,7 +289,7 @@ CHAN_UPDATE = {
|
||||||
|
|
||||||
'permission_overwrites': {
|
'permission_overwrites': {
|
||||||
'type': 'list',
|
'type': 'list',
|
||||||
'schema': CHAN_OVERWRITE,
|
'schema': {'type': 'dict', 'schema': CHAN_OVERWRITE},
|
||||||
'required': False
|
'required': False
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -324,18 +324,20 @@ class Storage:
|
||||||
|
|
||||||
def _overwrite_convert(row):
|
def _overwrite_convert(row):
|
||||||
drow = dict(row)
|
drow = dict(row)
|
||||||
drow['type'] = drow['target_type']
|
|
||||||
|
target_type = drow['target_type']
|
||||||
|
drow['type'] = 'user' if target_type == 0 else 'role'
|
||||||
|
|
||||||
# if type is 0, the overwrite is for a user
|
# if type is 0, the overwrite is for a user
|
||||||
# if type is 1, the overwrite is for a role
|
# if type is 1, the overwrite is for a role
|
||||||
drow['id'] = {
|
drow['id'] = {
|
||||||
0: drow['target_user'],
|
0: drow['target_user'],
|
||||||
1: drow['target_role'],
|
1: drow['target_role'],
|
||||||
}[drow['type']]
|
}[target_type]
|
||||||
|
|
||||||
drow['id'] = str(drow['id'])
|
drow['id'] = str(drow['id'])
|
||||||
|
|
||||||
drow.pop('overwrite_type')
|
drow.pop('target_type')
|
||||||
drow.pop('target_user')
|
drow.pop('target_user')
|
||||||
drow.pop('target_role')
|
drow.pop('target_role')
|
||||||
|
|
||||||
|
|
|
||||||
10
schema.sql
10
schema.sql
|
|
@ -347,11 +347,15 @@ CREATE TABLE IF NOT EXISTS channel_overwrites (
|
||||||
-- they're bigints (64bits), discord,
|
-- they're bigints (64bits), discord,
|
||||||
-- for now, only needs 53.
|
-- for now, only needs 53.
|
||||||
allow bigint DEFAULT 0,
|
allow bigint DEFAULT 0,
|
||||||
deny bigint DEFAULT 0,
|
deny bigint DEFAULT 0
|
||||||
|
|
||||||
PRIMARY KEY (channel_id, target_role, target_user)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- columns in private keys can't have NULL values,
|
||||||
|
-- so instead we use a custom constraint with UNIQUE
|
||||||
|
|
||||||
|
ALTER TABLE channel_overwrites ADD CONSTRAINT channel_overwrites_uniq
|
||||||
|
UNIQUE (channel_id, target_role, target_user);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS features (
|
CREATE TABLE IF NOT EXISTS features (
|
||||||
id serial PRIMARY KEY,
|
id serial PRIMARY KEY,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue