Add filter for aliases and permissions
This commit is contained in:
parent
e687f63ab7
commit
c83567c95e
3 changed files with 57 additions and 18 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
# Evennia API
|
# Evennia API
|
||||||
|
|
||||||
## What's an API?
|
## Synopsis
|
||||||
An API, or [Application Programming Interface][wiki-api], is a way of establishing rules
|
An API, or [Application Programming Interface][wiki-api], is a way of establishing rules
|
||||||
through which external services can use your program. In web development, it's
|
through which external services can use your program. In web development, it's
|
||||||
often that case that the 'frontend' of a web app is written in HTML and Javascript
|
often that case that the 'frontend' of a web app is written in HTML and Javascript
|
||||||
|
|
@ -8,7 +8,6 @@ and communicates with the 'backend' server through an API so that it can retriev
|
||||||
information to populate web pages or process actions when users click buttons on
|
information to populate web pages or process actions when users click buttons on
|
||||||
a web page.
|
a web page.
|
||||||
|
|
||||||
|
|
||||||
The API contained within the web/api/ package is an implementation of the
|
The API contained within the web/api/ package is an implementation of the
|
||||||
[Django Rest Framework][drf]. It provides tools to allow you to quickly process
|
[Django Rest Framework][drf]. It provides tools to allow you to quickly process
|
||||||
requests for resources and generate responses. URLs, called endpoints, are
|
requests for resources and generate responses. URLs, called endpoints, are
|
||||||
|
|
@ -24,7 +23,7 @@ that largely automate the process of serializing your in-game objects into
|
||||||
JSON representations for sending them to a client, or for turning a JSON string
|
JSON representations for sending them to a client, or for turning a JSON string
|
||||||
into a model for updating or creating it.
|
into a model for updating or creating it.
|
||||||
|
|
||||||
## What is it for?
|
## Motivations For Using An API
|
||||||
|
|
||||||
Having an API can allow you to have richer interactions with client applications. For
|
Having an API can allow you to have richer interactions with client applications. For
|
||||||
example, suppose you want to allow players to send and receive in-game messages from
|
example, suppose you want to allow players to send and receive in-game messages from
|
||||||
|
|
@ -35,7 +34,7 @@ displays it on the page. You also provide a form to let them send messages, wher
|
||||||
submit button uses AJAX to make a POST request to that endpoint, sending along the
|
submit button uses AJAX to make a POST request to that endpoint, sending along the
|
||||||
JSON data from the form, and then returns the response of the results. This works,
|
JSON data from the form, and then returns the response of the results. This works,
|
||||||
but then a tech-savvy player might ask if they can have their own application that
|
but then a tech-savvy player might ask if they can have their own application that
|
||||||
will retrieve messages periodically for their own computer. By having a [REST][REST] API that
|
will retrieve messages periodically for their own computer. By having a [REST][rest] API that
|
||||||
they can use, they can create client applications of their own to retrieve or change
|
they can use, they can create client applications of their own to retrieve or change
|
||||||
data.
|
data.
|
||||||
|
|
||||||
|
|
@ -88,8 +87,8 @@ a request to update the object with the specified data you pass along.
|
||||||
In most cases, you won't be making API requests to the backend with python,
|
In most cases, you won't be making API requests to the backend with python,
|
||||||
but with Javascript from your frontend application.
|
but with Javascript from your frontend application.
|
||||||
There are many Javascript libraries which are meant to make this process
|
There are many Javascript libraries which are meant to make this process
|
||||||
easier for requests from the frontend, such as [AXIOS][AXIOS], or using
|
easier for requests from the frontend, such as [AXIOS][axios], or using
|
||||||
the native [Fetch][Fetch].
|
the native [Fetch][fetch].
|
||||||
|
|
||||||
[wiki-api]: https://en.wikipedia.org/wiki/Application_programming_interface
|
[wiki-api]: https://en.wikipedia.org/wiki/Application_programming_interface
|
||||||
[drf]: https://www.django-rest-framework.org/
|
[drf]: https://www.django-rest-framework.org/
|
||||||
|
|
@ -97,7 +96,7 @@ the native [Fetch][Fetch].
|
||||||
[crud]: https://en.wikipedia.org/wiki/Create,_read,_update_and_delete
|
[crud]: https://en.wikipedia.org/wiki/Create,_read,_update_and_delete
|
||||||
[serializers]: https://www.django-rest-framework.org/api-guide/serializers/
|
[serializers]: https://www.django-rest-framework.org/api-guide/serializers/
|
||||||
[ajax]: https://en.wikipedia.org/wiki/Ajax_(programming)
|
[ajax]: https://en.wikipedia.org/wiki/Ajax_(programming)
|
||||||
[REST]: https://en.wikipedia.org/wiki/Representational_state_transfer
|
[rest]: https://en.wikipedia.org/wiki/Representational_state_transfer
|
||||||
[requests]: https://requests.readthedocs.io/en/master/
|
[requests]: https://requests.readthedocs.io/en/master/
|
||||||
[AXIOS]: https://github.com/axios/axios
|
[axios]: https://github.com/axios/axios
|
||||||
[Fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
||||||
|
|
@ -1,27 +1,67 @@
|
||||||
|
"""
|
||||||
|
FilterSets allow clients to specify querystrings that will determine the data
|
||||||
|
that is retrieved in GET requests. By default, Django Rest Framework uses the
|
||||||
|
'django-filter' package as its backend. Django-filter also has a section in its
|
||||||
|
documentation specifically regarding DRF integration.
|
||||||
|
|
||||||
|
https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html
|
||||||
|
"""
|
||||||
|
from django.db.models import Q
|
||||||
from django_filters.rest_framework.filterset import FilterSet
|
from django_filters.rest_framework.filterset import FilterSet
|
||||||
|
from django_filters.filters import CharFilter
|
||||||
|
|
||||||
from evennia.objects.models import ObjectDB
|
from evennia.objects.models import ObjectDB
|
||||||
from evennia.accounts.models import AccountDB
|
from evennia.accounts.models import AccountDB
|
||||||
from evennia.scripts.models import ScriptDB
|
from evennia.scripts.models import ScriptDB
|
||||||
|
|
||||||
|
|
||||||
|
class TagTypeFilter(CharFilter):
|
||||||
|
"""
|
||||||
|
This class lets you create different filters for tags of a specified db_tagtype.
|
||||||
|
"""
|
||||||
|
tag_type = None
|
||||||
|
|
||||||
|
def filter(self, qs, value):
|
||||||
|
return qs.filter(Q(db_tags__db_tagtype=self.tag_type) & Q(db_tags__db_key=value))
|
||||||
|
|
||||||
|
|
||||||
|
class AliasFilter(TagTypeFilter):
|
||||||
|
"""A filter for objects by their aliases (tags with a tagtype of 'alias'"""
|
||||||
|
tag_type = "alias"
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionFilter(TagTypeFilter):
|
||||||
|
"""A filter for objects by their permissions (tags with a tagtype of 'permission'"""
|
||||||
|
tag_type = "permission"
|
||||||
|
|
||||||
|
|
||||||
SHARED_FIELDS = ["db_key", "db_typeclass_path", "db_tags__db_key", "db_tags__db_category"]
|
SHARED_FIELDS = ["db_key", "db_typeclass_path", "db_tags__db_key", "db_tags__db_category"]
|
||||||
|
|
||||||
|
|
||||||
class ObjectDBFilterSet(FilterSet):
|
class BaseTypeclassFilterSet(FilterSet):
|
||||||
|
"""A parent class with filters for aliases and permissions"""
|
||||||
|
alias = AliasFilter(lookup_expr="iexact")
|
||||||
|
permission = PermissionFilter(lookup_expr="iexact")
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectDBFilterSet(BaseTypeclassFilterSet):
|
||||||
|
"""This adds filters for ObjectDB instances - characters, rooms, exits, etc"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ObjectDB
|
model = ObjectDB
|
||||||
fields = SHARED_FIELDS + ["db_location__db_key", "db_home__db_key", "db_location__id",
|
fields = SHARED_FIELDS + ["db_location__db_key", "db_home__db_key", "db_location__id",
|
||||||
"db_home__id"]
|
"db_home__id"]
|
||||||
|
|
||||||
|
|
||||||
class AccountDBFilterSet(FilterSet):
|
class AccountDBFilterSet(BaseTypeclassFilterSet):
|
||||||
|
"""This adds filters for Account objects"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = AccountDB
|
model = AccountDB
|
||||||
fields = SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"]
|
fields = SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"]
|
||||||
|
|
||||||
|
|
||||||
class ScriptDBFilterSet(FilterSet):
|
class ScriptDBFilterSet(BaseTypeclassFilterSet):
|
||||||
|
"""This adds filters for Script objects"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ScriptDB
|
model = ScriptDB
|
||||||
fields = SHARED_FIELDS + ["db_desc", "db_obj__db_key", "db_obj__id", "db_account__id",
|
fields = SHARED_FIELDS + ["db_desc", "db_obj__db_key", "db_obj__id", "db_account__id",
|
||||||
"db_account__username", "db_is_active", "db_persistent"]
|
"db_account__username", "db_is_active", "db_persistent", "db_interval"]
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@ class EvenniaPermission(permissions.BasePermission):
|
||||||
view, we'll check a corresponding Evennia access/lock check.
|
view, we'll check a corresponding Evennia access/lock check.
|
||||||
"""
|
"""
|
||||||
# subclass this to change these permissions
|
# subclass this to change these permissions
|
||||||
MINIMUM_LIST_PERMISSION = settings.REST_FRAMEWORK["DEFAULT_LIST_PERMISSION"]
|
MINIMUM_LIST_PERMISSION = settings.REST_FRAMEWORK.get("DEFAULT_LIST_PERMISSION", "builder")
|
||||||
MINIMUM_CREATE_PERMISSION = settings.REST_FRAMEWORK["DEFAULT_CREATE_PERMISSION"]
|
MINIMUM_CREATE_PERMISSION = settings.REST_FRAMEWORK.get("DEFAULT_CREATE_PERMISSION", "builder")
|
||||||
view_locks = settings.REST_FRAMEWORK["DEFAULT_VIEW_LOCKS"]
|
view_locks = settings.REST_FRAMEWORK.get("DEFAULT_VIEW_LOCKS", ["examine"])
|
||||||
destroy_locks = settings.REST_FRAMEWORK["DEFAULT_DESTROY_LOCKS"]
|
destroy_locks = settings.REST_FRAMEWORK.get("DEFAULT_DESTROY_LOCKS", ["delete"])
|
||||||
update_locks = settings.REST_FRAMEWORK["DEFAULT_UPDATE_LOCKS"]
|
update_locks = settings.REST_FRAMEWORK.get("DEFAULT_UPDATE_LOCKS", ["control", "edit"])
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue