Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip #188

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

wip #188

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/meet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ jobs:
DB_PASSWORD: pass
DB_PORT: 5432
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
AWS_S3_ENDPOINT_URL: http://localhost:9000
AWS_S3_ACCESS_KEY_ID: meet
AWS_S3_SECRET_ACCESS_KEY: password
LIVEKIT_API_SECRET: secret
LIVEKIT_API_KEY: devkey

Expand Down
26 changes: 26 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,30 @@ services:
ports:
- "1081:1080"

minio:
user: ${DOCKER_USER:-1000}
image: minio/minio
environment:
- MINIO_ROOT_USER=meet
- MINIO_ROOT_PASSWORD=password
ports:
- '9000:9000'
- '9001:9001'
entrypoint: ""
command: minio server --console-address :9001 /data
volumes:
- ./data/media:/data

createbuckets:
image: minio/mc
depends_on:
- minio
entrypoint: >
sh -c "
/usr/bin/mc alias set meet http://minio:9000 meet password && \
/usr/bin/mc mb meet/meet-media-storage && \
exit 0;"

app-dev:
build:
context: .
Expand All @@ -40,6 +64,7 @@ services:
- mailcatcher
- redis
- nginx
- createbuckets
- livekit

celery-dev:
Expand Down Expand Up @@ -73,6 +98,7 @@ services:
depends_on:
- postgresql
- redis
- createbuckets
- livekit

celery:
Expand Down
3 changes: 3 additions & 0 deletions env.d/development/common.dist
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ MEET_BASE_URL="http://localhost:8072"

# Media
STORAGES_STATICFILES_BACKEND=django.contrib.staticfiles.storage.StaticFilesStorage
AWS_S3_ENDPOINT_URL=http://minio:9000
AWS_S3_ACCESS_KEY_ID=meet
AWS_S3_SECRET_ACCESS_KEY=password

# OIDC
OIDC_OP_JWKS_ENDPOINT=http://nginx:8083/realms/meet/protocol/openid-connect/certs
Expand Down
2 changes: 1 addition & 1 deletion src/backend/.pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ max-branches=12
max-locals=15

# Maximum number of parents for a class (see R0901).
max-parents=7
max-parents=10

# Maximum number of public methods for a class (see R0904).
max-public-methods=20
Expand Down
47 changes: 29 additions & 18 deletions src/backend/core/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,30 @@ def has_object_permission(self, request, view, obj):
return obj == request.user


class RoomPermissions(permissions.BasePermission):
"""
Permissions applying to the room API endpoint.
"""
# class RoomPermissions(permissions.BasePermission):
# """
# Permissions applying to the room API endpoint.
# """

def has_permission(self, request, view):
"""Only allow authenticated users for unsafe methods."""
if request.method in permissions.SAFE_METHODS:
return True
# def has_permission(self, request, view):
# """Only allow authenticated users for unsafe methods."""
# if request.method in permissions.SAFE_METHODS:
# return True

return request.user.is_authenticated
# return request.user.is_authenticated

def has_object_permission(self, request, view, obj):
"""Object permissions are only given to administrators of the room."""
# def has_object_permission(self, request, view, obj):
# """Object permissions are only given to administrators of the room."""

if request.method in permissions.SAFE_METHODS:
return True
# if request.method in permissions.SAFE_METHODS:
# return True

user = request.user
# user = request.user

if request.method == "DELETE":
return obj.is_owner(user)
# if request.method == "DELETE":
# return obj.is_owner(user)

return obj.is_administrator(user)
# return obj.is_administrator(user)


class ResourceAccessPermission(permissions.BasePermission):
Expand All @@ -82,4 +82,15 @@ def has_object_permission(self, request, view, obj):
if request.method == "DELETE" and obj.role == RoleChoices.OWNER:
return obj.user == user

return obj.resource.is_administrator(user)
return RoleChoices.is_administrator(obj.resource.get_roles(user))


class AccessPermission(permissions.BasePermission):
"""Permission class for access objects."""

def has_permission(self, request, view):
return request.user.is_authenticated or view.action != "create"

def has_object_permission(self, request, view, obj):
"""Check permission for a given object."""
return obj.get_abilities(request.user).get(view.action, False)
32 changes: 26 additions & 6 deletions src/backend/core/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ class NestedResourceAccessSerializer(ResourceAccessSerializer):
user = UserSerializer(read_only=True)


class ListRoomSerializer(serializers.ModelSerializer):
"""Serialize Room model for a list API endpoint."""

class Meta:
model = models.Room
fields = ["id", "name", "slug", "is_public"]
read_only_fields = ["id", "slug"]


class RoomSerializer(serializers.ModelSerializer):
"""Serialize Room model for the API."""

Expand All @@ -106,21 +115,21 @@ def to_representation(self, instance):
if not request:
return output

role = instance.get_role(request.user)
is_admin = models.RoleChoices.check_administrator_role(role)
roles = instance.get_roles(request.user)
is_administrator = models.RoleChoices.is_administrator(roles)

if role is not None:
if roles:
access_serializer = NestedResourceAccessSerializer(
instance.accesses.select_related("resource", "user").all(),
context=self.context,
many=True,
)
output["accesses"] = access_serializer.data

if not is_admin:
if not is_administrator:
del output["configuration"]

if role is not None or instance.is_public:
if roles or instance.is_public:
slug = f"{instance.id!s}".replace("-", "")

username = request.query_params.get("username", None)
Expand All @@ -133,6 +142,17 @@ def to_representation(self, instance):
),
}

output["is_administrable"] = is_admin
output["is_administrable"] = is_administrator

return output


class RecordingSerializer(serializers.ModelSerializer):
"""Serialize Recording for the API."""

room = ListRoomSerializer(read_only=True)

class Meta:
model = models.Recording
fields = ["id", "room", "created_at", "updated_at", "stopped_at", "status"]
read_only_fields = fields
33 changes: 33 additions & 0 deletions src/backend/core/api/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Util to generate S3 authorization headers for object storage access control"""

from django.core.files.storage import default_storage

import botocore


def generate_s3_authorization_headers(key):
"""
Generate authorization headers for an s3 object.
These headers can be used as an alternative to signed urls with many benefits:
- the urls of our files never expire and can be stored in our documents' content
- we don't leak authorized urls that could be shared (file access can only be done
with cookies)
- access control is truly realtime
- the object storage service does not need to be exposed on internet
"""
url = default_storage.unsigned_connection.meta.client.generate_presigned_url(
"get_object",
ExpiresIn=0,
Params={"Bucket": default_storage.bucket_name, "Key": key},
)
request = botocore.awsrequest.AWSRequest(method="get", url=url)

s3_client = default_storage.connection.meta.client
# pylint: disable=protected-access
credentials = s3_client._request_signer._credentials # noqa: SLF001
frozen_credentials = credentials.get_frozen_credentials()
region = s3_client.meta.region_name
auth = botocore.auth.S3SigV4Auth(frozen_credentials, "s3", region)
auth.add_auth(request)

return request
Loading
Loading