69 lines
1.9 KiB
Python
69 lines
1.9 KiB
Python
from .db_logging import log_change
|
|
from .entity import ensure_entity_active
|
|
|
|
|
|
def _get_entity_type(cursor, entity_id):
|
|
cursor.execute("SELECT type FROM entity WHERE id = %s", (entity_id,))
|
|
row = cursor.fetchone()
|
|
return row["type"] if row else None
|
|
|
|
|
|
def _validate_role(role):
|
|
if not isinstance(role, str):
|
|
raise TypeError("role must be a string")
|
|
r = role.strip()
|
|
if not r:
|
|
raise ValueError("role must be a non-empty string")
|
|
if len(r) > 10:
|
|
raise ValueError("role must be at most 10 characters")
|
|
return r
|
|
|
|
|
|
def add_group_member(cursor, group_id, member_id, role):
|
|
"""Add a member to a group.
|
|
|
|
Rules:
|
|
- group_id must reference an active entity of type 'group'
|
|
- member_id must reference an active entity (person/device/group)
|
|
- role must be a non-empty string with max length 10
|
|
- duplicates are rejected
|
|
"""
|
|
ensure_entity_active(cursor, group_id)
|
|
ensure_entity_active(cursor, member_id)
|
|
|
|
if _get_entity_type(cursor, group_id) != "group":
|
|
raise ValueError("group_id must reference an entity of type 'group'")
|
|
|
|
r = _validate_role(role)
|
|
|
|
cursor.execute(
|
|
"SELECT 1 FROM group_member WHERE group_id = %s AND member_id = %s",
|
|
(group_id, member_id),
|
|
)
|
|
if cursor.fetchone() is not None:
|
|
raise ValueError("Member is already in the group")
|
|
|
|
cursor.execute(
|
|
"""
|
|
INSERT INTO group_member (group_id, member_id, role)
|
|
VALUES (%s, %s, %s)
|
|
""",
|
|
(group_id, member_id, r),
|
|
)
|
|
|
|
log_change(cursor, f"Added member {member_id} to group {group_id} as {r}")
|
|
|
|
|
|
def get_members_of_group(cursor, group_id):
|
|
ensure_entity_active(cursor, group_id)
|
|
cursor.execute(
|
|
"""
|
|
SELECT member_id, role
|
|
FROM group_member
|
|
WHERE group_id = %s
|
|
ORDER BY member_id
|
|
""",
|
|
(group_id,),
|
|
)
|
|
return cursor.fetchall()
|