mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-12-19 07:15:04 +01:00
BS5 Theme
This commit is contained in:
@@ -4,13 +4,13 @@ The documentation for Alliance Auth uses [Sphinx](http://www.sphinx-doc.org/) to
|
||||
to specific branches is made (master, primarily), the repository is automatically pulled, docs built and deployed on
|
||||
[readthedocs.org](https://readthedocs.org/).
|
||||
|
||||
|
||||
Documentation was migrated from the GitHub wiki pages and into the repository to allow documentation changes to be
|
||||
included with pull requests. This means that documentation can be guaranteed to be updated when a pull request is
|
||||
accepted rather than hoping documentation is updated afterwards or relying on maintainers to do the work. It also
|
||||
allows for documentation to be maintained at different versions more easily.
|
||||
|
||||
## Building Documentation
|
||||
|
||||
If you're developing new documentation, its likely you'll want or need to test build it before committing to your
|
||||
branch. To achieve this you can use Sphinx to build the documentation locally as it appears on Read the Docs.
|
||||
|
||||
@@ -24,7 +24,6 @@ build in the `/docs/_build/` directory.
|
||||
Occasionally you may need to fully rebuild the documents by running `make clean` first, usually when you add or
|
||||
rearrange toctrees.
|
||||
|
||||
|
||||
## Documentation Format
|
||||
|
||||
CommonMark Markdown is the current preferred format, via [recommonmark](https://github.com/rtfd/recommonmark).
|
||||
|
||||
19
docs/development/custom/custom-themes.md
Normal file
19
docs/development/custom/custom-themes.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Theme Hooks
|
||||
|
||||
The theme hook allows custom themes to be loaded dynamically by AAs CSS/JS Bundles, as selected by Users.
|
||||
|
||||
To register a ThemeHook class you would do the following:
|
||||
|
||||
```Python
|
||||
@hooks.register('theme_hook')
|
||||
def register_darkly_hook():
|
||||
return ThemeHook()
|
||||
```
|
||||
|
||||
The `ThemeHook` class specifies some parameters/instance variables required.
|
||||
|
||||
```eval_rst
|
||||
.. autoclass:: allianceauth.theme.hooks.ThemeHook
|
||||
:members: __init__
|
||||
:undoc-members:
|
||||
```
|
||||
@@ -1,12 +1,13 @@
|
||||
# Custom apps and services
|
||||
|
||||
This section describes how to extend **Alliance Auth** with custom apps and services.
|
||||
This section describes how to extend **Alliance Auth** with custom apps, services and themes.
|
||||
|
||||
```eval_rst
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
integrating-services
|
||||
custom-themes
|
||||
menu-hooks
|
||||
url-hooks
|
||||
logging
|
||||
|
||||
@@ -20,19 +20,21 @@ Typically a service will contain 5 key components:
|
||||
|
||||
The architecture looks something like this:
|
||||
|
||||
urls -------▶ Views
|
||||
▲ |
|
||||
| |
|
||||
| ▼
|
||||
ServiceHook ----▶ Tasks ----▶ Manager
|
||||
▲
|
||||
|
|
||||
|
|
||||
AllianceAuth
|
||||
```none
|
||||
urls -------▶ Views
|
||||
▲ |
|
||||
| |
|
||||
| ▼
|
||||
ServiceHook ----▶ Tasks ----▶ Manager
|
||||
▲
|
||||
|
|
||||
|
|
||||
AllianceAuth
|
||||
|
||||
|
||||
Where:
|
||||
Module --▶ Dependency/Import
|
||||
Where:
|
||||
Module --▶ Dependency/Import
|
||||
```
|
||||
|
||||
While this is the typical structure of the existing services modules, there is no enforcement of this structure and you are, effectively, free to create whatever architecture may be necessary. A service module need not even communicate with an external service, for example, if similar triggers such as validate_user, delete_user are required for a module it may be convenient to masquerade as a service. Ideally though, using the common structure improves the maintainability for other developers.
|
||||
|
||||
@@ -40,9 +42,11 @@ While this is the typical structure of the existing services modules, there is n
|
||||
|
||||
In order to integrate with Alliance Auth service modules must provide a `services_hook`. This hook will be a function that returns an instance of the `services.hooks.ServiceHook` class and decorated with the `@hooks.registerhook` decorator. For example:
|
||||
|
||||
@hooks.register('services_hook')
|
||||
def register_service():
|
||||
return ExampleService()
|
||||
```python
|
||||
@hooks.register('services_hook')
|
||||
def register_service():
|
||||
return ExampleService()
|
||||
```
|
||||
|
||||
This would register the ExampleService class which would need to be a subclass of `services.hooks.ServiceHook`.
|
||||
|
||||
@@ -53,15 +57,17 @@ This would register the ExampleService class which would need to be a subclass o
|
||||
|
||||
A subclassed `ServiceHook` might look like this:
|
||||
|
||||
class ExampleService(ServicesHook):
|
||||
def __init__(self):
|
||||
ServicesHook.__init__(self)
|
||||
self.urlpatterns = urlpatterns
|
||||
self.service_url = 'http://exampleservice.example.com'
|
||||
```python
|
||||
class ExampleService(ServicesHook):
|
||||
def __init__(self):
|
||||
ServicesHook.__init__(self)
|
||||
self.urlpatterns = urlpatterns
|
||||
self.service_url = 'http://exampleservice.example.com'
|
||||
|
||||
"""
|
||||
Overload base methods here to implement functionality
|
||||
"""
|
||||
```
|
||||
|
||||
### The ServiceHook class
|
||||
|
||||
@@ -71,9 +77,9 @@ You will need to subclass `services.hooks.ServiceHook` in order to provide imple
|
||||
|
||||
Instance Variables:
|
||||
|
||||
- [self.name](#self-name)
|
||||
- [self.urlpatterns](#self-url-patterns)
|
||||
- [self.service_ctrl_template](#self-service-ctrl-template)
|
||||
- [self.name](#selfname)
|
||||
- [self.urlpatterns](#selfurlpatterns)
|
||||
- [self.service_ctrl_template](#selfservice-ctrl-template)
|
||||
|
||||
Properties:
|
||||
|
||||
@@ -88,37 +94,47 @@ Functions:
|
||||
- [update_groups](#update_groups)
|
||||
- [update_groups_bulk](#update_groups_bulk)
|
||||
- [update_all_groups](#update_all_groups)
|
||||
- [service_enabled_members](#service_enabled_members)
|
||||
- [service_enabled_blues](#service_enabled_blues)
|
||||
- [service_active_for_user](#service_active_for_user)
|
||||
- [show_service_ctrl](#show_service_ctrl)
|
||||
- [render_service_ctrl](#render_service_ctrl)
|
||||
|
||||
### Variables
|
||||
|
||||
#### self.name
|
||||
|
||||
Internal name of the module, should be unique amongst modules.
|
||||
|
||||
#### self.service-ctrl-template
|
||||
|
||||
The template used to render
|
||||
|
||||
#### self.urlpatterns
|
||||
|
||||
You should define all of your service URLs internally, usually in `urls.py`. Then you can import them and set `self.urlpatterns` to your defined urlpatterns.
|
||||
|
||||
from . import urls
|
||||
...
|
||||
class MyService(ServiceHook):
|
||||
def __init__(self):
|
||||
...
|
||||
self.urlpatterns = urls.urlpatterns
|
||||
```python
|
||||
from . import urls
|
||||
...
|
||||
class MyService(ServiceHook):
|
||||
def __init__(self):
|
||||
...
|
||||
self.urlpatterns = urls.urlpatterns
|
||||
```
|
||||
|
||||
All of your apps defined urlpatterns will then be included in the `URLconf` when the core application starts.
|
||||
|
||||
#### self.service_ctrl_template
|
||||
|
||||
This is provided as a courtesy and defines the default template to be used with [render_service_ctrl](#render-service-ctrl). You are free to redefine or not use this variable at all.
|
||||
### Properties
|
||||
|
||||
#### title
|
||||
|
||||
This is a property which provides a user friendly display of your service's name. It will usually do a reasonably good job unless your service name has punctuation or odd capitalization. If this is the case you should override this method and return a string.
|
||||
|
||||
### Functions
|
||||
|
||||
#### self.service_ctrl_template
|
||||
|
||||
This is provided as a courtesy and defines the default template to be used with [render_service_ctrl](#render-service-ctrl). You are free to redefine or not use this variable at all.
|
||||
|
||||
#### delete_user
|
||||
|
||||
`def delete_user(self, user, notify_user=False):`
|
||||
@@ -134,12 +150,12 @@ The function should return a boolean, `True` if successfully disabled, `False` o
|
||||
Validate the users service account, deleting it if they should no longer have access. The `user` parameter should be a Django User object.
|
||||
|
||||
An implementation will probably look like the following:
|
||||
|
||||
def validate_user(self, user):
|
||||
logger.debug('Validating user %s %s account' % (user, self.name))
|
||||
if ExampleTasks.has_account(user) and not self.service_active_for_user(user):
|
||||
self.delete_user(user, notify_user=True)
|
||||
|
||||
```python
|
||||
def validate_user(self, user):
|
||||
logger.debug('Validating user %s %s account' % (user, self.name))
|
||||
if ExampleTasks.has_account(user) and not self.service_active_for_user(user):
|
||||
self.delete_user(user, notify_user=True)
|
||||
```
|
||||
No return value is expected.
|
||||
|
||||
This function will be called periodically on all users to validate that the given user should have their current service accounts.
|
||||
@@ -207,37 +223,39 @@ Should the service be shown for the given `user` with the given `state`? The `us
|
||||
|
||||
Usually you wont need to override this function.
|
||||
|
||||
For more information see the [render_service_ctrl](#render-service-ctrl) section.
|
||||
For more information see the [render_service_ctrl](#render_service_ctrl) section.
|
||||
|
||||
#### render_service_ctrl
|
||||
|
||||
`def render_services_ctrl(self, request):`
|
||||
|
||||
Render the services control row. This will be called for all active services when a user visits the `/services/` page and [show_service_ctrl](#show-service-ctrl) returns `True` for the given user.
|
||||
Render the services control row. This will be called for all active services when a user visits the `/services/` page and [show_service_ctrl](#show_service_ctrl) returns `True` for the given user.
|
||||
|
||||
It should return a string (usually from `render_to_string`) of a table row (`<tr>`) with 4 columns (`<td>`). Column #1 is the service name, column #2 is the users username for this service, column #3 is the services URL, and column #4 is the action buttons.
|
||||
|
||||
You may either define your own service template or use the default one provided. The default can be used like this example:
|
||||
|
||||
def render_services_ctrl(self, request):
|
||||
"""
|
||||
Example for rendering the service control panel row
|
||||
You can override the default template and create a
|
||||
custom one if you wish.
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
urls = self.Urls()
|
||||
urls.auth_activate = 'auth_example_activate'
|
||||
urls.auth_deactivate = 'auth_example_deactivate'
|
||||
urls.auth_reset_password = 'auth_example_reset_password'
|
||||
urls.auth_set_password = 'auth_example_set_password'
|
||||
return render_to_string(self.service_ctrl_template, {
|
||||
'service_name': self.title,
|
||||
'urls': urls,
|
||||
'service_url': self.service_url,
|
||||
'username': 'example username'
|
||||
}, request=request)
|
||||
```python
|
||||
def render_services_ctrl(self, request):
|
||||
"""
|
||||
Example for rendering the service control panel row
|
||||
You can override the default template and create a
|
||||
custom one if you wish.
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
urls = self.Urls()
|
||||
urls.auth_activate = 'auth_example_activate'
|
||||
urls.auth_deactivate = 'auth_example_deactivate'
|
||||
urls.auth_reset_password = 'auth_example_reset_password'
|
||||
urls.auth_set_password = 'auth_example_set_password'
|
||||
return render_to_string(self.service_ctrl_template, {
|
||||
'service_name': self.title,
|
||||
'urls': urls,
|
||||
'service_url': self.service_url,
|
||||
'username': 'example username'
|
||||
}, request=request)
|
||||
```
|
||||
|
||||
the `Urls` class defines the available URL names for the 4 actions available in the default template:
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Logging from Custom Apps
|
||||
|
||||
Alliance Auth provides a logger for use with custom apps to make everyone's life a little easier.
|
||||
|
||||
## Using the Extensions Logger
|
||||
|
||||
AllianceAuth provides a helper function to get the logger for the current module to reduce the amount of
|
||||
code you need to write.
|
||||
|
||||
@@ -15,17 +17,20 @@ This works by creating a child logger of the extension logger which propagates a
|
||||
to the parent (extensions) logger.
|
||||
|
||||
## Changing the Logging Level
|
||||
|
||||
By default, the extension logger's level is set to `DEBUG`.
|
||||
To change this, uncomment (or add) the following line in `local.py`.
|
||||
|
||||
```python
|
||||
LOGGING['handlers']['extension_file']['level'] = 'INFO'
|
||||
```
|
||||
|
||||
*(Remember to restart your supervisor workers after changes to `local.py`)*
|
||||
|
||||
This will change the logger's level to the level you define.
|
||||
|
||||
Options are: *(all options accept entries of levels listed below them)*
|
||||
|
||||
* `DEBUG`
|
||||
* `INFO`
|
||||
* `WARNING`
|
||||
|
||||
@@ -4,37 +4,21 @@ The menu hooks allow you to dynamically specify menu items from your plugin app
|
||||
|
||||
To register a MenuItemHook class you would do the following:
|
||||
|
||||
```Python
|
||||
```python
|
||||
@hooks.register('menu_item_hook')
|
||||
def register_menu():
|
||||
return MenuItemHook('Example Item', 'glyphicon glyphicon-heart', 'example_url_name',150)
|
||||
return MenuItemHook('Example Item', 'fas fa-user fa-fw"', 'example_url_name', 150)
|
||||
```
|
||||
|
||||
The `MenuItemHook` class specifies some parameters/instance variables required for menu item display.
|
||||
|
||||
## MenuItemHook(text, classes, url_name, order=None)
|
||||
```eval_rst
|
||||
.. autoclass:: allianceauth.services.hooks.MenuItemHook
|
||||
:members: __init__
|
||||
:undoc-members:
|
||||
```
|
||||
|
||||
### text
|
||||
|
||||
The text shown as menu item, e.g. usually the name of the app.
|
||||
|
||||
### classes
|
||||
|
||||
The classes that should be applied to the bootstrap menu item icon
|
||||
|
||||
### url_name
|
||||
|
||||
The name of the Django URL to use
|
||||
|
||||
### order
|
||||
|
||||
An integer which specifies the order of the menu item, lowest to highest. Community apps are free ot use an oder above `1000`. Numbers below are served for Auth.
|
||||
|
||||
### navactive
|
||||
|
||||
A list of views or namespaces the link should be highlighted on. See [django-navhelper](https://github.com/geelweb/django-navhelper#navactive) for usage. Defaults to the supplied `url_name`.
|
||||
|
||||
### count
|
||||
## count
|
||||
|
||||
`count` is an integer shown next to the menu item as badge when `count` is not `None`.
|
||||
|
||||
@@ -49,10 +33,18 @@ This is a great feature to signal the user, that he has some open issues to take
|
||||
|
||||
To use it set count the `render()` function of your subclass in accordance to the current user. Here is an example:
|
||||
|
||||
```eval_rst
|
||||
.. automodule:: allianceauth.services.hooks.MenuItemHook
|
||||
:members: render
|
||||
:noindex:
|
||||
:undoc-members:
|
||||
```
|
||||
|
||||
```Python
|
||||
def render(self, request):
|
||||
# ...
|
||||
self.count = calculate_count_for_user(request.user)
|
||||
return MenuItemHook.render(self, request)
|
||||
# ...
|
||||
```
|
||||
|
||||
|
||||
@@ -12,6 +12,18 @@ def register_urls():
|
||||
return UrlHook(app_name.urls, 'app_name', r^'app_name/')
|
||||
```
|
||||
|
||||
#### urls
|
||||
|
||||
The urls module to include. See [the Django docs](https://docs.djangoproject.com/en/dev/topics/http/urls/#example) for designing urlpatterns.
|
||||
|
||||
#### namespace
|
||||
|
||||
The URL namespace to apply. This is usually just the app name.
|
||||
|
||||
#### base_url
|
||||
|
||||
The URL prefix to match against in regex form. Example `r'^app_name/'`. This prefix will be applied in front of all URL patterns included. It is possible to use the same prefix as existing apps (or no prefix at all) but [standard URL resolution](https://docs.djangoproject.com/en/dev/topics/http/urls/#how-django-processes-a-request) ordering applies (hook URLs are the last ones registered).
|
||||
|
||||
### Public views
|
||||
|
||||
In addition is it possible to make views public. Normally, all views are automatically decorated with the `main_character_required` decorator. That decorator ensures a user needs to be logged in and have a main before he can access that view. This feature protects against a community app sneaking in a public view without the administrator knowing about it.
|
||||
@@ -22,7 +34,6 @@ An app can opt-out of this feature by adding a list of views to be excluded when
|
||||
.. note::
|
||||
Note that for a public view to work, administrators need to also explicitly allow apps to have public views in their AA installation, by adding the apps label to ``APPS_WITH_PUBLIC_VIEWS`` setting.
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
An app called `plugin` provides a single view:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
```eval_rst
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:maxdepth: 2
|
||||
|
||||
custom/index
|
||||
aa_core/index
|
||||
|
||||
Reference in New Issue
Block a user