Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ A Python example project for CMS-SDK.

This example uses docker images provided by [cms-docker-compose](https://github.com/ridi/cms-docker-compose). Learn more details about the docker images in the link.

> If you need Django rest framework exmaple; [click here](sample_drf_middleware/README.md)

## Requirements

- composer
Expand Down
70 changes: 70 additions & 0 deletions sample_drf_middleware/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# CMS Bootstrap for DRF(django rest framework) Middleware

This template is designed for more ease of use when using django rest framework authentication with CMS-RPC

You will see three files in the current directory.
- cms.py
- permissions.py
- authentication.py

**What is cms.py**
The cms.py file preconfigures cms-sdk with RPC url.

**What is permissions.py and authentication.py?**
These files are responsible for authentication and permissions based on the cms-sdk by preconfigured cms.py.

If you want to understand this more, check out the [basic drf authentication and permissions](https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/).


# How to use
1. Save the files to the appropriate path in the project.
- cms.py
- permissions.py
- authentication.py

2. Override the hardcorded string in the files.

```python
# permissions.py
from ${PROJECT_PATH}.cms import admin_auth

# authentication.py
from ${PROJECT_PATH}.cms import admin_user, admin_auth

# cms.py
config.RPC_URL = 'https://YOUR_CMS_RPC_HTTPS_DOMAIN'
```

3. Defines the variables to use for authentication

```python
# settings.py

...

REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
'PROJECT_PATH.authentication.CmsOpenAuthentication',
),
...
}

...

CMS_TEST_ID = os.getenv('TEST_ID', 'admin')
CMS_RPC_URL = os.getenv('CMS_RPC_URL', 'http://localhost')
CMS_AUTH_DISABLE = os.environ.get('CMS_AUTH_DISABLE', False)
...

```

4. Enjoy it! example

```python
class UserListCreateAPIView(generics.ListCreateAPIView):
required_tags = ["example",] # Minimum permissions to access this API View
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes=(IsAuthenticated,)
```
41 changes: 41 additions & 0 deletions sample_drf_middleware/authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import json
import logging

from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.contrib.auth.hashers import check_password
from django.contrib.auth import authenticate, login, get_user_model
from django.contrib.auth.backends import ModelBackend
from django.shortcuts import redirect

from rest_framework import authentication
from rest_framework import exceptions

from ridi.cms.login_session import COOKIE_CMS_TOKEN, COOKIE_ADMIN_ID
from ridi.cms.thrift.Errors.ttypes import *

from ${PROJECT_PATH}.cms import admin_user, admin_auth

User = get_user_model()
logger = logging.getLogger(__name__)

class CmsOpenAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
username = self.__get_username(request)
if not username:
return None

try:
user = User.objects.get(id=username)
except User.DoesNotExist:
raise exceptions.AuthenticationFailed('No such user')

return (user, None)

def __get_username(self, request):
if settings.DEBUG and settings.CMS_TEST_ID:
username = settings.CMS_TEST_ID
logger.debug('you have been permitted as ' + username)
return username

return request.COOKIES.get(COOKIE_ADMIN_ID, None)
27 changes: 27 additions & 0 deletions sample_drf_middleware/cms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
from ridi.cms.cms_client import AdminUser, AdminAuth, AdminMenu
from ridi.cms.config import Config as CmsConfig

from django.conf import settings

config = CmsConfig()

if settings.DEBUG:
config.RPC_URL = settings.CMS_RPC_URL
else:
import ssl

try:
_create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
# Legacy Python that doesn't verify HTTPS certificates by default
pass
else:
# Handle target environment that doesn't support HTTPS verification
ssl._create_default_https_context = _create_unverified_https_context

config.RPC_URL = 'https://YOUR_CMS_RPC_HTTPS_DOMAIN'

admin_user = AdminUser(config)
admin_auth = AdminAuth(config)
admin_menu = AdminMenu(config)
40 changes: 40 additions & 0 deletions sample_drf_middleware/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

from django.conf import settings
from django.shortcuts import redirect

from rest_framework import permissions
from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS

from ridi.cms.login_session import COOKIE_CMS_TOKEN, COOKIE_ADMIN_ID
from ridi.cms.thrift.Errors.ttypes import NoTokenException, MalformedTokenException, ExpiredTokenException, UnauthorizedException, TException

from ${PROJECT_PATH}.cms import admin_auth

class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Read only method, or owners with write permission.
"""
def has_permission(self, request, view):
if settings.DEBUG and settings.CMS_AUTH_DISABLE:
return True # Bypass at Debugging

if request.method in permissions.SAFE_METHODS:
return True # Allow readonly access

token = request.COOKIES.get(COOKIE_CMS_TOKEN, None)
try:
required_tags = self.__get_required_tags(view)
token = request.COOKIES.get(COOKIE_CMS_TOKEN, None)
admin_auth.authorizeByTag(token, required_tags)
except (NoTokenException, MalformedTokenException, ExpiredTokenException, UnauthorizedException) as e:
raise e
except (TException) as e:
return False

return True

def __get_required_tags(self, view, tags=[]):
if hasattr(view, 'required_tags'):
tags = views.required_tags
return tags