Skip to content

Commit

Permalink
More CRUD views
Browse files Browse the repository at this point in the history
  • Loading branch information
fjsj committed Jun 14, 2024
1 parent 6848ae3 commit dcae388
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 18 deletions.
2 changes: 2 additions & 0 deletions django_ai_assistant/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
DEFAULTS = {
"CAN_CREATE_THREAD_FN": "django_ai_assistant.permissions.allow_all",
"CAN_VIEW_THREAD_FN": "django_ai_assistant.permissions.owns_thread",
"CAN_UPDATE_THREAD_FN": "django_ai_assistant.permissions.owns_thread",
"CAN_DELETE_THREAD_FN": "django_ai_assistant.permissions.owns_thread",
"CAN_CREATE_MESSAGE_FN": "django_ai_assistant.permissions.owns_thread",
"CAN_UPDATE_MESSAGE_FN": "django_ai_assistant.permissions.owns_thread",
"CAN_DELETE_MESSAGE_FN": "django_ai_assistant.permissions.owns_thread",
"CAN_RUN_ASSISTANT": "django_ai_assistant.permissions.allow_all",
}
Expand Down
14 changes: 14 additions & 0 deletions django_ai_assistant/helpers/assistants.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,20 @@ def get_threads(
return list(Thread.objects.filter(created_by=user))


def update_thread(
thread: Thread,
name: str,
user: Any,
request: HttpRequest | None = None,
):
if not can_delete_thread(thread=thread, user=user, request=request):
raise AIUserNotAllowedError("User is not allowed to update this thread")

thread.name = name
thread.save()
return thread


def delete_thread(
thread: Thread,
user: Any,
Expand Down
55 changes: 40 additions & 15 deletions django_ai_assistant/permissions.py
Original file line number Diff line number Diff line change
@@ -1,88 +1,113 @@
from typing import Any

from django.http import HttpRequest
from django.views import View

from django_ai_assistant.conf import app_settings
from django_ai_assistant.models import Message, Thread


def _get_default_kwargs(user: Any, request: HttpRequest | None, view: View | None):
if view and not request:
request = view.request
def _get_default_kwargs(user: Any, request: HttpRequest | None):
return {
"user": user,
"request": request,
"view": view if view else None,
}


def can_create_thread(
user: Any,
request: HttpRequest | None = None,
view: View | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_CREATE_THREAD_FN",
**_get_default_kwargs(user, request, view),
**_get_default_kwargs(user, request),
**kwargs,
)


def can_update_thread(
thread: Thread,
user: Any,
request: HttpRequest | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_UPDATE_THREAD_FN",
**_get_default_kwargs(user, request),
thread=thread,
**kwargs,
)


def can_delete_thread(
thread: Thread,
user: Any,
request: HttpRequest | None = None,
view: View | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_DELETE_THREAD_FN",
**_get_default_kwargs(user, request, view),
**_get_default_kwargs(user, request),
thread=thread,
**kwargs,
)


def can_create_message(
thread,
user: Any,
request: HttpRequest | None = None,
view: View | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_CREATE_MESSAGE_FN",
**_get_default_kwargs(user, request, view),
**_get_default_kwargs(user, request),
thread=thread,
**kwargs,
)


def can_update_message(
message: Message,
user: Any,
request: HttpRequest | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_UPDATE_MESSAGE_FN",
**_get_default_kwargs(user, request),
message=message,
thread=message.thread,
**kwargs,
)


def can_delete_message(
message: Message,
user: Any,
request: HttpRequest | None = None,
view: View | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_DELETE_MESSAGE_FN",
**_get_default_kwargs(user, request, view),
**_get_default_kwargs(user, request),
message=message,
thread=message.thread,
**kwargs,
)


def can_run_assistant(
assistant_cls,
user: Any,
request: HttpRequest | None = None,
view: View | None = None,
**kwargs,
) -> bool:
return app_settings.call_fn(
"CAN_RUN_ASSISTANT",
**_get_default_kwargs(user, request, view),
**_get_default_kwargs(user, request),
assistant_cls=assistant_cls,
**kwargs,
)


Expand Down
11 changes: 9 additions & 2 deletions django_ai_assistant/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,20 @@ def create_thread(request, payload: ThreadSchemaIn):
return assistants.create_thread(name=name, user=request.user, request=request)


@api.get("threads/{thread_id}/", response=ThreadSchema, url_name="thread_detail_delete")
@api.get("threads/{thread_id}/", response=ThreadSchema, url_name="thread_detail_update_delete")
def get_thread(request, thread_id: str):
thread = get_single_thread(thread_id=thread_id, user=request.user, request=request)
return thread


@api.delete("threads/{thread_id}/", response={204: None}, url_name="thread_detail_delete")
@api.patch("threads/{thread_id}/", response=ThreadSchema, url_name="thread_detail_update_delete")
def update_thread(request, thread_id: str, payload: ThreadSchemaIn):
thread = get_object_or_404(Thread, id=thread_id)
name = payload.name
return assistants.update_thread(thread=thread, name=name, user=request.user, request=request)


@api.delete("threads/{thread_id}/", response={204: None}, url_name="thread_detail_update_delete")
def delete_thread(request, thread_id: str):
thread = get_object_or_404(Thread, id=thread_id)
assistants.delete_thread(thread=thread, user=request.user, request=request)
Expand Down
2 changes: 2 additions & 0 deletions example/example/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
AI_ASSISTANT_CAN_CREATE_THREAD_FN = "django_ai_assistant.permissions.allow_all"
AI_ASSISTANT_CAN_VIEW_THREAD_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_UPDATE_THREAD_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_DELETE_THREAD_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_CREATE_MESSAGE_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_UPDATE_MESSAGE_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_DELETE_MESSAGE_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_RUN_ASSISTANT = "django_ai_assistant.permissions.allow_all"

Expand Down
37 changes: 37 additions & 0 deletions frontend/openapi_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,43 @@
}
}
},
"patch": {
"operationId": "django_ai_assistant_views_update_thread",
"summary": "Update Thread",
"parameters": [
{
"in": "path",
"name": "thread_id",
"schema": {
"title": "Thread Id",
"type": "string"
},
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ThreadSchema"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ThreadSchemaIn"
}
}
},
"required": true
}
},
"delete": {
"operationId": "django_ai_assistant_views_delete_thread",
"summary": "Delete Thread",
Expand Down
20 changes: 19 additions & 1 deletion frontend/src/client/services.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
import type { DjangoAiAssistantViewsListAssistantsResponse, DjangoAiAssistantViewsGetAssistantData, DjangoAiAssistantViewsGetAssistantResponse, DjangoAiAssistantViewsListThreadsResponse, DjangoAiAssistantViewsCreateThreadData, DjangoAiAssistantViewsCreateThreadResponse, DjangoAiAssistantViewsGetThreadData, DjangoAiAssistantViewsGetThreadResponse, DjangoAiAssistantViewsDeleteThreadData, DjangoAiAssistantViewsDeleteThreadResponse, DjangoAiAssistantViewsListThreadMessagesData, DjangoAiAssistantViewsListThreadMessagesResponse, DjangoAiAssistantViewsCreateThreadMessageData, DjangoAiAssistantViewsCreateThreadMessageResponse, DjangoAiAssistantViewsDeleteThreadMessageData, DjangoAiAssistantViewsDeleteThreadMessageResponse } from './types.gen';
import type { DjangoAiAssistantViewsListAssistantsResponse, DjangoAiAssistantViewsGetAssistantData, DjangoAiAssistantViewsGetAssistantResponse, DjangoAiAssistantViewsListThreadsResponse, DjangoAiAssistantViewsCreateThreadData, DjangoAiAssistantViewsCreateThreadResponse, DjangoAiAssistantViewsGetThreadData, DjangoAiAssistantViewsGetThreadResponse, DjangoAiAssistantViewsUpdateThreadData, DjangoAiAssistantViewsUpdateThreadResponse, DjangoAiAssistantViewsDeleteThreadData, DjangoAiAssistantViewsDeleteThreadResponse, DjangoAiAssistantViewsListThreadMessagesData, DjangoAiAssistantViewsListThreadMessagesResponse, DjangoAiAssistantViewsCreateThreadMessageData, DjangoAiAssistantViewsCreateThreadMessageResponse, DjangoAiAssistantViewsDeleteThreadMessageData, DjangoAiAssistantViewsDeleteThreadMessageResponse } from './types.gen';

/**
* List Assistants
Expand Down Expand Up @@ -69,6 +69,24 @@ export const djangoAiAssistantViewsGetThread = (data: DjangoAiAssistantViewsGetT
}
}); };

/**
* Update Thread
* @param data The data for the request.
* @param data.threadId
* @param data.requestBody
* @returns ThreadSchema OK
* @throws ApiError
*/
export const djangoAiAssistantViewsUpdateThread = (data: DjangoAiAssistantViewsUpdateThreadData): CancelablePromise<DjangoAiAssistantViewsUpdateThreadResponse> => { return __request(OpenAPI, {
method: 'PATCH',
url: '/threads/{thread_id}/',
path: {
thread_id: data.threadId
},
body: data.requestBody,
mediaType: 'application/json'
}); };

/**
* Delete Thread
* @param data The data for the request.
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ export type DjangoAiAssistantViewsGetThreadData = {

export type DjangoAiAssistantViewsGetThreadResponse = ThreadSchema;

export type DjangoAiAssistantViewsUpdateThreadData = {
requestBody: ThreadSchemaIn;
threadId: string;
};

export type DjangoAiAssistantViewsUpdateThreadResponse = ThreadSchema;

export type DjangoAiAssistantViewsDeleteThreadData = {
threadId: string;
};
Expand Down Expand Up @@ -128,6 +135,15 @@ export type $OpenApiTs = {
200: ThreadSchema;
};
};
patch: {
req: DjangoAiAssistantViewsUpdateThreadData;
res: {
/**
* OK
*/
200: ThreadSchema;
};
};
delete: {
req: DjangoAiAssistantViewsDeleteThreadData;
res: {
Expand Down
2 changes: 2 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@
OPENAI_API_KEY = "sk-fake-test-key-123"
AI_ASSISTANT_CAN_CREATE_THREAD_FN = "django_ai_assistant.permissions.allow_all"
AI_ASSISTANT_CAN_VIEW_THREAD_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_UPDATE_THREAD_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_DELETE_THREAD_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_CREATE_MESSAGE_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_UPDATE_MESSAGE_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_DELETE_MESSAGE_FN = "django_ai_assistant.permissions.owns_thread"
AI_ASSISTANT_CAN_RUN_ASSISTANT = "django_ai_assistant.permissions.allow_all"

0 comments on commit dcae388

Please sign in to comment.