BS5 Theme

This commit is contained in:
Aaron Kable
2023-10-07 08:20:22 +00:00
committed by Ariel Rin
parent 567d97f38a
commit 2e78aa5f26
161 changed files with 3198 additions and 1655 deletions

View File

@@ -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: