8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-23 11:53:12 +00:00

Merge branch '210-use-black-for-formatting' into 'dev'

Resolve "Use black for formatting"

See merge request federez/re2o!468
This commit is contained in:
chirac 2019-11-04 23:16:57 +01:00
commit 540a8d0531
515 changed files with 16814 additions and 13681 deletions

View file

@ -40,14 +40,14 @@ def _create_api_permission():
"""
api_content_type, created = ContentType.objects.get_or_create(
app_label=settings.API_CONTENT_TYPE_APP_LABEL,
model=settings.API_CONTENT_TYPE_MODEL
model=settings.API_CONTENT_TYPE_MODEL,
)
if created:
api_content_type.save()
api_permission, created = Permission.objects.get_or_create(
name=settings.API_PERMISSION_NAME,
content_type=api_content_type,
codename=settings.API_PERMISSION_CODENAME
codename=settings.API_PERMISSION_CODENAME,
)
if created:
api_permission.save()
@ -67,10 +67,13 @@ def can_view(user):
viewing is granted and msg is a message (can be None).
"""
kwargs = {
'app_label': settings.API_CONTENT_TYPE_APP_LABEL,
'codename': settings.API_PERMISSION_CODENAME
"app_label": settings.API_CONTENT_TYPE_APP_LABEL,
"codename": settings.API_PERMISSION_CODENAME,
}
permission = '%(app_label)s.%(codename)s' % kwargs
permission = "%(app_label)s.%(codename)s" % kwargs
can = user.has_perm(permission)
return can, None if can else _("You don't have the right to see this"
" application."), (permission,)
return (
can,
None if can else _("You don't have the right to see this" " application."),
(permission,),
)

View file

@ -41,9 +41,7 @@ class ExpiringTokenAuthentication(TokenAuthentication):
user, token = base.authenticate_credentials(key)
# Check that the genration time of the token is not too old
token_duration = datetime.timedelta(
seconds=settings.API_TOKEN_DURATION
)
token_duration = datetime.timedelta(seconds=settings.API_TOKEN_DURATION)
utc_now = datetime.datetime.now(datetime.timezone.utc)
if token.created < utc_now - token_duration:
raise exceptions.AuthenticationFailed(_("The token has expired."))

View file

@ -38,8 +38,9 @@ class PageSizedPagination(pagination.PageNumberPagination):
max_page_size: The maximum number of results a page can output no
matter what is requested.
"""
page_size_query_param = 'page_size'
all_pages_strings = ('all',)
page_size_query_param = "page_size"
all_pages_strings = ("all",)
max_page_size = 10000
def get_page_size(self, request):

View file

@ -55,17 +55,21 @@ def _get_param_in_view(view, param_name):
AssertionError: None of the getter function or the attribute are
defined in the view.
"""
assert hasattr(view, 'get_' + param_name) \
or getattr(view, param_name, None) is not None, (
'cannot apply {} on a view that does not set '
'`.{}` or have a `.get_{}()` method.'
).format(self.__class__.__name__, param_name, param_name)
assert (
hasattr(view, "get_" + param_name)
or getattr(view, param_name, None) is not None
), (
"cannot apply {} on a view that does not set "
"`.{}` or have a `.get_{}()` method."
).format(
self.__class__.__name__, param_name, param_name
)
if hasattr(view, 'get_' + param_name):
param = getattr(view, 'get_' + param_name)()
assert param is not None, (
'{}.get_{}() returned None'
).format(view.__class__.__name__, param_name)
if hasattr(view, "get_" + param_name):
param = getattr(view, "get_" + param_name)()
assert param is not None, ("{}.get_{}() returned None").format(
view.__class__.__name__, param_name
)
return param
return getattr(view, param_name)
@ -97,7 +101,7 @@ class ACLPermission(permissions.BasePermission):
rest_framework.exception.MethodNotAllowed: The requested method
is not allowed for this view.
"""
perms_map = _get_param_in_view(view, 'perms_map')
perms_map = _get_param_in_view(view, "perms_map")
if method not in perms_map:
raise exceptions.MethodNotAllowed(method)
@ -123,7 +127,7 @@ class ACLPermission(permissions.BasePermission):
"""
# Workaround to ensure ACLPermissions are not applied
# to the root view when using DefaultRouter.
if getattr(view, '_ignore_model_permissions', False):
if getattr(view, "_ignore_model_permissions", False):
return True
if not request.user or not request.user.is_authenticated:
@ -148,22 +152,22 @@ class AutodetectACLPermission(permissions.BasePermission):
"""
perms_map = {
'GET': [can_see_api, lambda model: model.can_view_all],
'OPTIONS': [can_see_api, lambda model: model.can_view_all],
'HEAD': [can_see_api, lambda model: model.can_view_all],
'POST': [can_see_api, lambda model: model.can_create],
'PUT': [], # No restrictions, apply to objects
'PATCH': [], # No restrictions, apply to objects
'DELETE': [], # No restrictions, apply to objects
"GET": [can_see_api, lambda model: model.can_view_all],
"OPTIONS": [can_see_api, lambda model: model.can_view_all],
"HEAD": [can_see_api, lambda model: model.can_view_all],
"POST": [can_see_api, lambda model: model.can_create],
"PUT": [], # No restrictions, apply to objects
"PATCH": [], # No restrictions, apply to objects
"DELETE": [], # No restrictions, apply to objects
}
perms_obj_map = {
'GET': [can_see_api, lambda obj: obj.can_view],
'OPTIONS': [can_see_api, lambda obj: obj.can_view],
'HEAD': [can_see_api, lambda obj: obj.can_view],
'POST': [], # No restrictions, apply to models
'PUT': [can_see_api, lambda obj: obj.can_edit],
'PATCH': [can_see_api, lambda obj: obj.can_edit],
'DELETE': [can_see_api, lambda obj: obj.can_delete],
"GET": [can_see_api, lambda obj: obj.can_view],
"OPTIONS": [can_see_api, lambda obj: obj.can_view],
"HEAD": [can_see_api, lambda obj: obj.can_view],
"POST": [], # No restrictions, apply to models
"PUT": [can_see_api, lambda obj: obj.can_edit],
"PATCH": [can_see_api, lambda obj: obj.can_edit],
"DELETE": [can_see_api, lambda obj: obj.can_delete],
}
def get_required_permissions(self, method, model):
@ -210,7 +214,7 @@ class AutodetectACLPermission(permissions.BasePermission):
@staticmethod
def _queryset(view):
return _get_param_in_view(view, 'queryset')
return _get_param_in_view(view, "queryset")
def has_permission(self, request, view):
"""Check that the user has the model-based permissions to perform
@ -232,7 +236,7 @@ class AutodetectACLPermission(permissions.BasePermission):
"""
# Workaround to ensure ACLPermissions are not applied
# to the root view when using DefaultRouter.
if getattr(view, '_ignore_model_permissions', False):
if getattr(view, "_ignore_model_permissions", False):
return True
if not request.user or not request.user.is_authenticated:
@ -274,7 +278,7 @@ class AutodetectACLPermission(permissions.BasePermission):
# to make another lookup.
raise Http404
read_perms = self.get_required_object_permissions('GET', obj)
read_perms = self.get_required_object_permissions("GET", obj)
if not read_perms(request.user)[0]:
raise Http404

View file

@ -74,7 +74,7 @@ class AllViewsRouter(DefaultRouter):
Returns:
The name to use for this route.
"""
return pattern.split('/')[-1]
return pattern.split("/")[-1]
def get_api_root_view(self, schema_urls=None, api_urls=None):
"""Create a class-based view to use as the API root.
@ -102,12 +102,10 @@ class AllViewsRouter(DefaultRouter):
if schema_urls and self.schema_title:
view_renderers += list(self.schema_renderers)
schema_generator = SchemaGenerator(
title=self.schema_title,
patterns=schema_urls
title=self.schema_title, patterns=schema_urls
)
schema_media_types = [
renderer.media_type
for renderer in self.schema_renderers
renderer.media_type for renderer in self.schema_renderers
]
class APIRoot(views.APIView):
@ -128,14 +126,14 @@ class AllViewsRouter(DefaultRouter):
namespace = request.resolver_match.namespace
for key, url_name in api_root_dict.items():
if namespace:
url_name = namespace + ':' + url_name
url_name = namespace + ":" + url_name
try:
ret[key] = reverse(
url_name,
args=args,
kwargs=kwargs,
request=request,
format=kwargs.get('format', None)
format=kwargs.get("format", None),
)
except NoReverseMatch:
# Don't bail out if eg. no list routes exist, only detail routes.

File diff suppressed because it is too large Load diff

View file

@ -24,28 +24,24 @@
# RestFramework config for API
REST_FRAMEWORK = {
'URL_FIELD_NAME': 'api_url',
'DEFAULT_AUTHENTICATION_CLASSES': (
'api.authentication.ExpiringTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
"URL_FIELD_NAME": "api_url",
"DEFAULT_AUTHENTICATION_CLASSES": (
"api.authentication.ExpiringTokenAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
'DEFAULT_PERMISSION_CLASSES': (
'api.permissions.AutodetectACLPermission',
),
'DEFAULT_PAGINATION_CLASS': 'api.pagination.PageSizedPagination',
'PAGE_SIZE': 100
"DEFAULT_PERMISSION_CLASSES": ("api.permissions.AutodetectACLPermission",),
"DEFAULT_PAGINATION_CLASS": "api.pagination.PageSizedPagination",
"PAGE_SIZE": 100,
}
# API permission settings
API_CONTENT_TYPE_APP_LABEL = 'api'
API_CONTENT_TYPE_MODEL = 'api'
API_PERMISSION_NAME = 'Can use the API'
API_PERMISSION_CODENAME = 'use_api'
API_CONTENT_TYPE_APP_LABEL = "api"
API_CONTENT_TYPE_MODEL = "api"
API_PERMISSION_NAME = "Can use the API"
API_PERMISSION_CODENAME = "use_api"
# Activate token authentication
API_APPS = (
'rest_framework.authtoken',
)
API_APPS = ("rest_framework.authtoken",)
# The expiration time for an authentication token
API_TOKEN_DURATION = 86400 # 24 hours

View file

@ -50,171 +50,170 @@ class APIEndpointsTestCase(APITestCase):
superuser: A superuser (with all permissions) used for the tests and
initialized at the beggining of this test case.
"""
no_auth_endpoints = [
'/api/'
]
no_auth_endpoints = ["/api/"]
auth_no_perm_endpoints = []
auth_perm_endpoints = [
'/api/cotisations/article/',
'/api/cotisations/article/1/',
'/api/cotisations/banque/',
'/api/cotisations/banque/1/',
'/api/cotisations/cotisation/',
'/api/cotisations/cotisation/1/',
'/api/cotisations/facture/',
'/api/cotisations/facture/1/',
'/api/cotisations/paiement/',
'/api/cotisations/paiement/1/',
'/api/cotisations/vente/',
'/api/cotisations/vente/1/',
'/api/machines/domain/',
'/api/machines/domain/1/',
'/api/machines/extension/',
'/api/machines/extension/1/',
'/api/machines/interface/',
'/api/machines/interface/1/',
'/api/machines/iplist/',
'/api/machines/iplist/1/',
'/api/machines/iptype/',
'/api/machines/iptype/1/',
'/api/machines/ipv6list/',
'/api/machines/ipv6list/1/',
'/api/machines/machine/',
'/api/machines/machine/1/',
'/api/machines/machinetype/',
'/api/machines/machinetype/1/',
'/api/machines/mx/',
'/api/machines/mx/1/',
'/api/machines/nas/',
'/api/machines/nas/1/',
'/api/machines/ns/',
'/api/machines/ns/1/',
'/api/machines/ouvertureportlist/',
'/api/machines/ouvertureportlist/1/',
'/api/machines/ouvertureport/',
'/api/machines/ouvertureport/1/',
'/api/machines/servicelink/',
'/api/machines/servicelink/1/',
'/api/machines/service/',
'/api/machines/service/1/',
'/api/machines/soa/',
'/api/machines/soa/1/',
'/api/machines/srv/',
'/api/machines/srv/1/',
'/api/machines/txt/',
'/api/machines/txt/1/',
'/api/machines/vlan/',
'/api/machines/vlan/1/',
'/api/preferences/optionaluser/',
'/api/preferences/optionalmachine/',
'/api/preferences/optionaltopologie/',
'/api/preferences/generaloption/',
'/api/preferences/service/',
'/api/preferences/service/1/',
'/api/preferences/assooption/',
'/api/preferences/homeoption/',
'/api/preferences/mailmessageoption/',
'/api/topologie/acesspoint/',
"/api/cotisations/article/",
"/api/cotisations/article/1/",
"/api/cotisations/banque/",
"/api/cotisations/banque/1/",
"/api/cotisations/cotisation/",
"/api/cotisations/cotisation/1/",
"/api/cotisations/facture/",
"/api/cotisations/facture/1/",
"/api/cotisations/paiement/",
"/api/cotisations/paiement/1/",
"/api/cotisations/vente/",
"/api/cotisations/vente/1/",
"/api/machines/domain/",
"/api/machines/domain/1/",
"/api/machines/extension/",
"/api/machines/extension/1/",
"/api/machines/interface/",
"/api/machines/interface/1/",
"/api/machines/iplist/",
"/api/machines/iplist/1/",
"/api/machines/iptype/",
"/api/machines/iptype/1/",
"/api/machines/ipv6list/",
"/api/machines/ipv6list/1/",
"/api/machines/machine/",
"/api/machines/machine/1/",
"/api/machines/machinetype/",
"/api/machines/machinetype/1/",
"/api/machines/mx/",
"/api/machines/mx/1/",
"/api/machines/nas/",
"/api/machines/nas/1/",
"/api/machines/ns/",
"/api/machines/ns/1/",
"/api/machines/ouvertureportlist/",
"/api/machines/ouvertureportlist/1/",
"/api/machines/ouvertureport/",
"/api/machines/ouvertureport/1/",
"/api/machines/servicelink/",
"/api/machines/servicelink/1/",
"/api/machines/service/",
"/api/machines/service/1/",
"/api/machines/soa/",
"/api/machines/soa/1/",
"/api/machines/srv/",
"/api/machines/srv/1/",
"/api/machines/txt/",
"/api/machines/txt/1/",
"/api/machines/vlan/",
"/api/machines/vlan/1/",
"/api/preferences/optionaluser/",
"/api/preferences/optionalmachine/",
"/api/preferences/optionaltopologie/",
"/api/preferences/generaloption/",
"/api/preferences/service/",
"/api/preferences/service/1/",
"/api/preferences/assooption/",
"/api/preferences/homeoption/",
"/api/preferences/mailmessageoption/",
"/api/topologie/acesspoint/",
# 2nd machine to be create (machines_machine_1, topologie_accesspoint_1)
'/api/topologie/acesspoint/2/',
'/api/topologie/building/',
'/api/topologie/building/1/',
'/api/topologie/constructorswitch/',
'/api/topologie/constructorswitch/1/',
'/api/topologie/modelswitch/',
'/api/topologie/modelswitch/1/',
'/api/topologie/room/',
'/api/topologie/room/1/',
'/api/topologie/server/',
"/api/topologie/acesspoint/2/",
"/api/topologie/building/",
"/api/topologie/building/1/",
"/api/topologie/constructorswitch/",
"/api/topologie/constructorswitch/1/",
"/api/topologie/modelswitch/",
"/api/topologie/modelswitch/1/",
"/api/topologie/room/",
"/api/topologie/room/1/",
"/api/topologie/server/",
# 3rd machine to be create (machines_machine_1, topologie_accesspoint_1,
# topologie_server_1)
'/api/topologie/server/3/',
'/api/topologie/stack/',
'/api/topologie/stack/1/',
'/api/topologie/switch/',
"/api/topologie/server/3/",
"/api/topologie/stack/",
"/api/topologie/stack/1/",
"/api/topologie/switch/",
# 4th machine to be create (machines_machine_1, topologie_accesspoint_1,
# topologie_server_1, topologie_switch_1)
'/api/topologie/switch/4/',
'/api/topologie/switchbay/',
'/api/topologie/switchbay/1/',
'/api/topologie/switchport/',
'/api/topologie/switchport/1/',
'/api/topologie/switchport/2/',
'/api/topologie/switchport/3/',
'/api/users/adherent/',
"/api/topologie/switch/4/",
"/api/topologie/switchbay/",
"/api/topologie/switchbay/1/",
"/api/topologie/switchport/",
"/api/topologie/switchport/1/",
"/api/topologie/switchport/2/",
"/api/topologie/switchport/3/",
"/api/users/adherent/",
# 3rd user to be create (stduser, superuser, users_adherent_1)
'/api/users/adherent/3/',
'/api/users/ban/',
'/api/users/ban/1/',
'/api/users/club/',
"/api/users/adherent/3/",
"/api/users/ban/",
"/api/users/ban/1/",
"/api/users/club/",
# 4th user to be create (stduser, superuser, users_adherent_1,
# users_club_1)
'/api/users/club/4/',
'/api/users/listright/',
"/api/users/club/4/",
"/api/users/listright/",
# TODO: Merge !145
# '/api/users/listright/1/',
'/api/users/school/',
'/api/users/school/1/',
'/api/users/serviceuser/',
'/api/users/serviceuser/1/',
'/api/users/shell/',
'/api/users/shell/1/',
'/api/users/user/',
'/api/users/user/1/',
'/api/users/whitelist/',
'/api/users/whitelist/1/',
'/api/dns/zones/',
'/api/dhcp/hostmacip/',
'/api/mailing/standard',
'/api/mailing/club',
'/api/services/regen/',
"/api/users/school/",
"/api/users/school/1/",
"/api/users/serviceuser/",
"/api/users/serviceuser/1/",
"/api/users/shell/",
"/api/users/shell/1/",
"/api/users/user/",
"/api/users/user/1/",
"/api/users/whitelist/",
"/api/users/whitelist/1/",
"/api/dns/zones/",
"/api/dhcp/hostmacip/",
"/api/mailing/standard",
"/api/mailing/club",
"/api/services/regen/",
]
not_found_endpoints = [
'/api/cotisations/article/4242/',
'/api/cotisations/banque/4242/',
'/api/cotisations/cotisation/4242/',
'/api/cotisations/facture/4242/',
'/api/cotisations/paiement/4242/',
'/api/cotisations/vente/4242/',
'/api/machines/domain/4242/',
'/api/machines/extension/4242/',
'/api/machines/interface/4242/',
'/api/machines/iplist/4242/',
'/api/machines/iptype/4242/',
'/api/machines/ipv6list/4242/',
'/api/machines/machine/4242/',
'/api/machines/machinetype/4242/',
'/api/machines/mx/4242/',
'/api/machines/nas/4242/',
'/api/machines/ns/4242/',
'/api/machines/ouvertureportlist/4242/',
'/api/machines/ouvertureport/4242/',
'/api/machines/servicelink/4242/',
'/api/machines/service/4242/',
'/api/machines/soa/4242/',
'/api/machines/srv/4242/',
'/api/machines/txt/4242/',
'/api/machines/vlan/4242/',
'/api/preferences/service/4242/',
'/api/topologie/acesspoint/4242/',
'/api/topologie/building/4242/',
'/api/topologie/constructorswitch/4242/',
'/api/topologie/modelswitch/4242/',
'/api/topologie/room/4242/',
'/api/topologie/server/4242/',
'/api/topologie/stack/4242/',
'/api/topologie/switch/4242/',
'/api/topologie/switchbay/4242/',
'/api/topologie/switchport/4242/',
'/api/users/adherent/4242/',
'/api/users/ban/4242/',
'/api/users/club/4242/',
'/api/users/listright/4242/',
'/api/users/school/4242/',
'/api/users/serviceuser/4242/',
'/api/users/shell/4242/',
'/api/users/user/4242/',
'/api/users/whitelist/4242/',
"/api/cotisations/article/4242/",
"/api/cotisations/banque/4242/",
"/api/cotisations/cotisation/4242/",
"/api/cotisations/facture/4242/",
"/api/cotisations/paiement/4242/",
"/api/cotisations/vente/4242/",
"/api/machines/domain/4242/",
"/api/machines/extension/4242/",
"/api/machines/interface/4242/",
"/api/machines/iplist/4242/",
"/api/machines/iptype/4242/",
"/api/machines/ipv6list/4242/",
"/api/machines/machine/4242/",
"/api/machines/machinetype/4242/",
"/api/machines/mx/4242/",
"/api/machines/nas/4242/",
"/api/machines/ns/4242/",
"/api/machines/ouvertureportlist/4242/",
"/api/machines/ouvertureport/4242/",
"/api/machines/servicelink/4242/",
"/api/machines/service/4242/",
"/api/machines/soa/4242/",
"/api/machines/srv/4242/",
"/api/machines/txt/4242/",
"/api/machines/vlan/4242/",
"/api/preferences/service/4242/",
"/api/topologie/acesspoint/4242/",
"/api/topologie/building/4242/",
"/api/topologie/constructorswitch/4242/",
"/api/topologie/modelswitch/4242/",
"/api/topologie/room/4242/",
"/api/topologie/server/4242/",
"/api/topologie/stack/4242/",
"/api/topologie/switch/4242/",
"/api/topologie/switchbay/4242/",
"/api/topologie/switchport/4242/",
"/api/users/adherent/4242/",
"/api/users/ban/4242/",
"/api/users/club/4242/",
"/api/users/listright/4242/",
"/api/users/school/4242/",
"/api/users/serviceuser/4242/",
"/api/users/shell/4242/",
"/api/users/user/4242/",
"/api/users/whitelist/4242/",
]
stduser = None
@ -232,26 +231,18 @@ class APIEndpointsTestCase(APITestCase):
# A user with no rights
cls.stduser = users.User.objects.create_user(
"apistduser",
"apistduser",
"apistduser@example.net",
"apistduser"
"apistduser", "apistduser", "apistduser@example.net", "apistduser"
)
# A user with all the rights
cls.superuser = users.User.objects.create_superuser(
"apisuperuser",
"apisuperuser",
"apisuperuser@example.net",
"apisuperuser"
"apisuperuser", "apisuperuser", "apisuperuser@example.net", "apisuperuser"
)
# Creates 1 instance for each object so the "details" endpoints
# can be tested too. Objects need to be created in the right order.
# Dependencies (relatedFields, ...) are highlighted by a comment at
# the end of the concerned line (# Dep <model>).
cls.users_school_1 = users.School.objects.create(
name="users_school_1"
)
cls.users_school_1 = users.School.objects.create(name="users_school_1")
cls.users_school_1.save()
cls.users_listshell_1 = users.ListShell.objects.create(
shell="users_listshell_1"
@ -270,7 +261,7 @@ class APIEndpointsTestCase(APITestCase):
registered=datetime.datetime.now(datetime.timezone.utc),
telephone="0123456789",
uid_number=21102,
rezo_rez_uid=21102
rezo_rez_uid=21102,
)
cls.users_user_1 = cls.users_adherent_1
cls.cotisations_article_1 = cotisations.Article.objects.create(
@ -278,14 +269,14 @@ class APIEndpointsTestCase(APITestCase):
prix=10,
duration=1,
type_user=cotisations.Article.USER_TYPES[0][0],
type_cotisation=cotisations.Article.COTISATION_TYPE[0][0]
type_cotisation=cotisations.Article.COTISATION_TYPE[0][0],
)
cls.cotisations_banque_1 = cotisations.Banque.objects.create(
name="cotisations_banque_1"
)
cls.cotisations_paiement_1 = cotisations.Paiement.objects.create(
moyen="cotisations_paiement_1",
type_paiement=cotisations.Paiement.PAYMENT_TYPES[0][0]
type_paiement=cotisations.Paiement.PAYMENT_TYPES[0][0],
)
cls.cotisations_facture_1 = cotisations.Facture.objects.create(
user=cls.users_user_1, # Dep users.User
@ -294,7 +285,7 @@ class APIEndpointsTestCase(APITestCase):
cheque="1234567890",
date=datetime.datetime.now(datetime.timezone.utc),
valid=True,
control=False
control=False,
)
cls.cotisations_vente_1 = cotisations.Vente.objects.create(
facture=cls.cotisations_facture_1, # Dep cotisations.Facture
@ -302,18 +293,18 @@ class APIEndpointsTestCase(APITestCase):
name="cotisations_vente_1",
prix=10,
duration=1,
type_cotisation=cotisations.Vente.COTISATION_TYPE[0][0]
type_cotisation=cotisations.Vente.COTISATION_TYPE[0][0],
)
# A cotisation is automatically created by the Vente object and
# trying to create another cotisation associated with this vente
# will fail so we simply retrieve it so it can be used in the tests
cls.cotisations_cotisation_1 = cotisations.Cotisation.objects.get(
vente=cls.cotisations_vente_1, # Dep cotisations.Vente
vente=cls.cotisations_vente_1 # Dep cotisations.Vente
)
cls.machines_machine_1 = machines.Machine.objects.create(
user=cls.users_user_1, # Dep users.User
name="machines_machine_1",
active=True
active=True,
)
cls.machines_ouvertureportlist_1 = machines.OuverturePortList.objects.create(
name="machines_ouvertureportlist_1"
@ -324,19 +315,17 @@ class APIEndpointsTestCase(APITestCase):
refresh=86400,
retry=7200,
expire=3600000,
ttl=172800
ttl=172800,
)
cls.machines_extension_1 = machines.Extension.objects.create(
name="machines_extension_1",
need_infra=False,
# Do not set origin because of circular dependency
origin_v6="2001:db8:1234::",
soa=cls.machines_soa_1 # Dep machines.SOA
soa=cls.machines_soa_1, # Dep machines.SOA
)
cls.machines_vlan_1 = machines.Vlan.objects.create(
vlan_id=0,
name="machines_vlan_1",
comment="machines Vlan 1"
vlan_id=0, name="machines_vlan_1", comment="machines Vlan 1"
)
cls.machines_iptype_1 = machines.IpType.objects.create(
type="machines_iptype_1",
@ -346,13 +335,12 @@ class APIEndpointsTestCase(APITestCase):
domaine_ip_stop="10.0.0.255",
prefix_v6="2001:db8:1234::",
vlan=cls.machines_vlan_1, # Dep machines.Vlan
ouverture_ports=cls.machines_ouvertureportlist_1 # Dep machines.OuverturePortList
ouverture_ports=cls.machines_ouvertureportlist_1, # Dep machines.OuverturePortList
)
# All IPs in the IpType range are autocreated so we can't create
# new ones and thus we only retrieve it if needed in the tests
cls.machines_iplist_1 = machines.IpList.objects.get(
ipv4="10.0.0.1",
ip_type=cls.machines_iptype_1, # Dep machines.IpType
ipv4="10.0.0.1", ip_type=cls.machines_iptype_1 # Dep machines.IpType
)
cls.machines_machinetype_1 = machines.MachineType.objects.create(
type="machines_machinetype_1",
@ -375,16 +363,16 @@ class APIEndpointsTestCase(APITestCase):
cls.machines_mx_1 = machines.Mx.objects.create(
zone=cls.machines_extension_1, # Dep machines.Extension
priority=10,
name=cls.machines_domain_1 # Dep machines.Domain
name=cls.machines_domain_1, # Dep machines.Domain
)
cls.machines_ns_1 = machines.Ns.objects.create(
zone=cls.machines_extension_1, # Dep machines.Extension
ns=cls.machines_domain_1 # Dep machines.Domain
ns=cls.machines_domain_1, # Dep machines.Domain
)
cls.machines_txt_1 = machines.Txt.objects.create(
zone=cls.machines_extension_1, # Dep machines.Extension
field1="machines_txt_1",
field2="machies Txt 1"
field2="machies Txt 1",
)
cls.machines_srv_1 = machines.Srv.objects.create(
service="machines_srv_1",
@ -398,7 +386,7 @@ class APIEndpointsTestCase(APITestCase):
cls.machines_ipv6list_1 = machines.Ipv6List.objects.create(
ipv6="2001:db8:1234::",
interface=cls.machines_interface_1, # Dep machines.Interface
slaac_ip=False
slaac_ip=False,
)
cls.machines_service_1 = machines.Service.objects.create(
service_type="machines_service_1",
@ -410,45 +398,45 @@ class APIEndpointsTestCase(APITestCase):
service=cls.machines_service_1, # Dep machines.Service
server=cls.machines_interface_1, # Dep machines.Interface
last_regen=datetime.datetime.now(datetime.timezone.utc),
asked_regen=False
asked_regen=False,
)
cls.machines_ouvertureport_1 = machines.OuverturePort.objects.create(
begin=1,
end=2,
port_list=cls.machines_ouvertureportlist_1, # Dep machines.OuverturePortList
protocole=machines.OuverturePort.TCP,
io=machines.OuverturePort.OUT
io=machines.OuverturePort.OUT,
)
cls.machines_nas_1 = machines.Nas.objects.create(
name="machines_nas_1",
nas_type=cls.machines_machinetype_1, # Dep machines.MachineType
machine_type=cls.machines_machinetype_1, # Dep machines.MachineType
port_access_mode=machines.Nas.AUTH[0][0],
autocapture_mac=False
autocapture_mac=False,
)
cls.preferences_service_1 = preferences.Service.objects.create(
name="preferences_service_1",
url="https://example.net",
description="preferences Service 1",
image="/media/logo/none.png"
image="/media/logo/none.png",
)
cls.topologie_stack_1 = topologie.Stack.objects.create(
name="topologie_stack_1",
stack_id="1",
details="topologie Stack 1",
member_id_min=1,
member_id_max=10
member_id_max=10,
)
cls.topologie_accespoint_1 = topologie.AccessPoint.objects.create(
user=cls.users_user_1, # Dep users.User
name="machines_machine_1",
active=True,
location="topologie AccessPoint 1"
location="topologie AccessPoint 1",
)
cls.topologie_server_1 = topologie.Server.objects.create(
user=cls.users_user_1, # Dep users.User
name="machines_machine_1",
active=True
active=True,
)
cls.topologie_building_1 = topologie.Building.objects.create(
name="topologie_building_1"
@ -456,14 +444,14 @@ class APIEndpointsTestCase(APITestCase):
cls.topologie_switchbay_1 = topologie.SwitchBay.objects.create(
name="topologie_switchbay_1",
building=cls.topologie_building_1, # Dep topologie.Building
info="topologie SwitchBay 1"
info="topologie SwitchBay 1",
)
cls.topologie_constructorswitch_1 = topologie.ConstructorSwitch.objects.create(
name="topologie_constructorswitch_1"
)
cls.topologie_modelswitch_1 = topologie.ModelSwitch.objects.create(
reference="topologie_modelswitch_1",
constructor=cls.topologie_constructorswitch_1 # Dep topologie.ConstructorSwitch
constructor=cls.topologie_constructorswitch_1, # Dep topologie.ConstructorSwitch
)
cls.topologie_switch_1 = topologie.Switch.objects.create(
user=cls.users_user_1, # Dep users.User
@ -473,11 +461,10 @@ class APIEndpointsTestCase(APITestCase):
stack=cls.topologie_stack_1, # Dep topologie.Stack
stack_member_id=1,
model=cls.topologie_modelswitch_1, # Dep topologie.ModelSwitch
switchbay=cls.topologie_switchbay_1 # Dep topologie.SwitchBay
switchbay=cls.topologie_switchbay_1, # Dep topologie.SwitchBay
)
cls.topologie_room_1 = topologie.Room.objects.create(
name="topologie_romm_1",
details="topologie Room 1"
name="topologie_romm_1", details="topologie Room 1"
)
cls.topologie_port_1 = topologie.Port.objects.create(
switch=cls.topologie_switch_1, # Dep topologie.Switch
@ -485,7 +472,7 @@ class APIEndpointsTestCase(APITestCase):
room=cls.topologie_room_1, # Dep topologie.Room
radius=topologie.Port.STATES[0][0],
vlan_force=cls.machines_vlan_1, # Dep machines.Vlan
details="topologie_switch_1"
details="topologie_switch_1",
)
cls.topologie_port_2 = topologie.Port.objects.create(
switch=cls.topologie_switch_1, # Dep topologie.Switch
@ -493,7 +480,7 @@ class APIEndpointsTestCase(APITestCase):
machine_interface=cls.machines_interface_1, # Dep machines.Interface
radius=topologie.Port.STATES[0][0],
vlan_force=cls.machines_vlan_1, # Dep machines.Vlan
details="topologie_switch_1"
details="topologie_switch_1",
)
cls.topologie_port_3 = topologie.Port.objects.create(
switch=cls.topologie_switch_1, # Dep topologie.Switch
@ -501,14 +488,15 @@ class APIEndpointsTestCase(APITestCase):
room=cls.topologie_room_1, # Dep topologie.Room
radius=topologie.Port.STATES[0][0],
# Do not defines related because circular dependency # Dep machines.Vlan
details="topologie_switch_1"
details="topologie_switch_1",
)
cls.users_ban_1 = users.Ban.objects.create(
user=cls.users_user_1, # Dep users.User
raison="users Ban 1",
date_start=datetime.datetime.now(datetime.timezone.utc),
date_end=datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1),
state=users.Ban.STATES[0][0]
date_end=datetime.datetime.now(datetime.timezone.utc)
+ datetime.timedelta(days=1),
state=users.Ban.STATES[0][0],
)
cls.users_club_1 = users.Club.objects.create(
password="password",
@ -524,7 +512,7 @@ class APIEndpointsTestCase(APITestCase):
registered=datetime.datetime.now(datetime.timezone.utc),
telephone="0123456789",
uid_number=21103,
rezo_rez_uid=21103
rezo_rez_uid=21103,
)
# Need merge of MR145 to work
# TODO: Merge !145
@ -539,17 +527,17 @@ class APIEndpointsTestCase(APITestCase):
last_login=datetime.datetime.now(datetime.timezone.utc),
pseudo="usersserviceuser1",
access_group=users.ServiceUser.ACCESS[0][0],
comment="users ServiceUser 1"
comment="users ServiceUser 1",
)
cls.users_whitelist_1 = users.Whitelist.objects.create(
user=cls.users_user_1,
raison="users Whitelist 1",
date_start=datetime.datetime.now(datetime.timezone.utc),
date_end=datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1)
date_end=datetime.datetime.now(datetime.timezone.utc)
+ datetime.timedelta(days=1),
)
def check_responses_code(self, urls, expected_code, formats=None,
assert_more=None):
def check_responses_code(self, urls, expected_code, formats=None, assert_more=None):
"""Utility function to test if a list of urls answer an expected code.
Args:
@ -665,17 +653,20 @@ class APIEndpointsTestCase(APITestCase):
"""
self.client.force_authenticate(user=self.superuser)
urls = self.no_auth_endpoints + self.auth_no_perm_endpoints + \
self.auth_perm_endpoints
urls = (
self.no_auth_endpoints
+ self.auth_no_perm_endpoints
+ self.auth_perm_endpoints
)
def assert_more(response, url, format):
"""Assert the response is valid json when format is json"""
if format is 'json':
if format is "json":
json.loads(response.content.decode())
self.check_responses_code(urls, codes.ok,
formats=[None, 'json', 'api'],
assert_more=assert_more)
self.check_responses_code(
urls, codes.ok, formats=[None, "json", "api"], assert_more=assert_more
)
class APIPaginationTestCase(APITestCase):
@ -688,56 +679,56 @@ class APIPaginationTestCase(APITestCase):
"""
endpoints = [
'/api/cotisations/article/',
'/api/cotisations/banque/',
'/api/cotisations/cotisation/',
'/api/cotisations/facture/',
'/api/cotisations/paiement/',
'/api/cotisations/vente/',
'/api/machines/domain/',
'/api/machines/extension/',
'/api/machines/interface/',
'/api/machines/iplist/',
'/api/machines/iptype/',
'/api/machines/ipv6list/',
'/api/machines/machine/',
'/api/machines/machinetype/',
'/api/machines/mx/',
'/api/machines/nas/',
'/api/machines/ns/',
'/api/machines/ouvertureportlist/',
'/api/machines/ouvertureport/',
'/api/machines/servicelink/',
'/api/machines/service/',
'/api/machines/soa/',
'/api/machines/srv/',
'/api/machines/txt/',
'/api/machines/vlan/',
'/api/preferences/service/',
'/api/topologie/acesspoint/',
'/api/topologie/building/',
'/api/topologie/constructorswitch/',
'/api/topologie/modelswitch/',
'/api/topologie/room/',
'/api/topologie/server/',
'/api/topologie/stack/',
'/api/topologie/switch/',
'/api/topologie/switchbay/',
'/api/topologie/switchport/',
'/api/users/adherent/',
'/api/users/ban/',
'/api/users/club/',
'/api/users/listright/',
'/api/users/school/',
'/api/users/serviceuser/',
'/api/users/shell/',
'/api/users/user/',
'/api/users/whitelist/',
'/api/dns/zones/',
'/api/dhcp/hostmacip/',
'/api/mailing/standard',
'/api/mailing/club',
'/api/services/regen/',
"/api/cotisations/article/",
"/api/cotisations/banque/",
"/api/cotisations/cotisation/",
"/api/cotisations/facture/",
"/api/cotisations/paiement/",
"/api/cotisations/vente/",
"/api/machines/domain/",
"/api/machines/extension/",
"/api/machines/interface/",
"/api/machines/iplist/",
"/api/machines/iptype/",
"/api/machines/ipv6list/",
"/api/machines/machine/",
"/api/machines/machinetype/",
"/api/machines/mx/",
"/api/machines/nas/",
"/api/machines/ns/",
"/api/machines/ouvertureportlist/",
"/api/machines/ouvertureport/",
"/api/machines/servicelink/",
"/api/machines/service/",
"/api/machines/soa/",
"/api/machines/srv/",
"/api/machines/txt/",
"/api/machines/vlan/",
"/api/preferences/service/",
"/api/topologie/acesspoint/",
"/api/topologie/building/",
"/api/topologie/constructorswitch/",
"/api/topologie/modelswitch/",
"/api/topologie/room/",
"/api/topologie/server/",
"/api/topologie/stack/",
"/api/topologie/switch/",
"/api/topologie/switchbay/",
"/api/topologie/switchport/",
"/api/users/adherent/",
"/api/users/ban/",
"/api/users/club/",
"/api/users/listright/",
"/api/users/school/",
"/api/users/serviceuser/",
"/api/users/shell/",
"/api/users/user/",
"/api/users/whitelist/",
"/api/dns/zones/",
"/api/dhcp/hostmacip/",
"/api/mailing/standard",
"/api/mailing/club",
"/api/services/regen/",
]
superuser = None
@ -752,7 +743,7 @@ class APIPaginationTestCase(APITestCase):
"apisuperuser2",
"apisuperuser2",
"apisuperuser2@example.net",
"apisuperuser2"
"apisuperuser2",
)
@classmethod
@ -771,10 +762,10 @@ class APIPaginationTestCase(APITestCase):
self.client.force_authenticate(self.superuser)
for url in self.endpoints:
with self.subTest(url=url):
response = self.client.get(url, format='json')
response = self.client.get(url, format="json")
res_json = json.loads(response.content.decode())
assert 'count' in res_json.keys()
assert 'next' in res_json.keys()
assert 'previous' in res_json.keys()
assert 'results' in res_json.keys()
assert not len('results') > 100
assert "count" in res_json.keys()
assert "next" in res_json.keys()
assert "previous" in res_json.keys()
assert "results" in res_json.keys()
assert not len("results") > 100

View file

@ -34,95 +34,109 @@ from .routers import AllViewsRouter
router = AllViewsRouter()
# COTISATIONS
router.register_viewset(r'cotisations/facture', views.FactureViewSet)
router.register_viewset(r'cotisations/vente', views.VenteViewSet)
router.register_viewset(r'cotisations/article', views.ArticleViewSet)
router.register_viewset(r'cotisations/banque', views.BanqueViewSet)
router.register_viewset(r'cotisations/paiement', views.PaiementViewSet)
router.register_viewset(r'cotisations/cotisation', views.CotisationViewSet)
router.register_viewset(r"cotisations/facture", views.FactureViewSet)
router.register_viewset(r"cotisations/vente", views.VenteViewSet)
router.register_viewset(r"cotisations/article", views.ArticleViewSet)
router.register_viewset(r"cotisations/banque", views.BanqueViewSet)
router.register_viewset(r"cotisations/paiement", views.PaiementViewSet)
router.register_viewset(r"cotisations/cotisation", views.CotisationViewSet)
# MACHINES
router.register_viewset(r'machines/machine', views.MachineViewSet)
router.register_viewset(r'machines/machinetype', views.MachineTypeViewSet)
router.register_viewset(r'machines/iptype', views.IpTypeViewSet)
router.register_viewset(r'machines/vlan', views.VlanViewSet)
router.register_viewset(r'machines/nas', views.NasViewSet)
router.register_viewset(r'machines/soa', views.SOAViewSet)
router.register_viewset(r'machines/extension', views.ExtensionViewSet)
router.register_viewset(r'machines/mx', views.MxViewSet)
router.register_viewset(r'machines/ns', views.NsViewSet)
router.register_viewset(r'machines/txt', views.TxtViewSet)
router.register_viewset(r'machines/dname', views.DNameViewSet)
router.register_viewset(r'machines/srv', views.SrvViewSet)
router.register_viewset(r'machines/sshfp', views.SshFpViewSet)
router.register_viewset(r'machines/interface', views.InterfaceViewSet)
router.register_viewset(r'machines/ipv6list', views.Ipv6ListViewSet)
router.register_viewset(r'machines/domain', views.DomainViewSet)
router.register_viewset(r'machines/iplist', views.IpListViewSet)
router.register_viewset(r'machines/service', views.ServiceViewSet)
router.register_viewset(r'machines/servicelink', views.ServiceLinkViewSet, base_name='servicelink')
router.register_viewset(r'machines/ouvertureportlist', views.OuverturePortListViewSet)
router.register_viewset(r'machines/ouvertureport', views.OuverturePortViewSet)
router.register_viewset(r'machines/role', views.RoleViewSet)
router.register_viewset(r"machines/machine", views.MachineViewSet)
router.register_viewset(r"machines/machinetype", views.MachineTypeViewSet)
router.register_viewset(r"machines/iptype", views.IpTypeViewSet)
router.register_viewset(r"machines/vlan", views.VlanViewSet)
router.register_viewset(r"machines/nas", views.NasViewSet)
router.register_viewset(r"machines/soa", views.SOAViewSet)
router.register_viewset(r"machines/extension", views.ExtensionViewSet)
router.register_viewset(r"machines/mx", views.MxViewSet)
router.register_viewset(r"machines/ns", views.NsViewSet)
router.register_viewset(r"machines/txt", views.TxtViewSet)
router.register_viewset(r"machines/dname", views.DNameViewSet)
router.register_viewset(r"machines/srv", views.SrvViewSet)
router.register_viewset(r"machines/sshfp", views.SshFpViewSet)
router.register_viewset(r"machines/interface", views.InterfaceViewSet)
router.register_viewset(r"machines/ipv6list", views.Ipv6ListViewSet)
router.register_viewset(r"machines/domain", views.DomainViewSet)
router.register_viewset(r"machines/iplist", views.IpListViewSet)
router.register_viewset(r"machines/service", views.ServiceViewSet)
router.register_viewset(
r"machines/servicelink", views.ServiceLinkViewSet, base_name="servicelink"
)
router.register_viewset(r"machines/ouvertureportlist", views.OuverturePortListViewSet)
router.register_viewset(r"machines/ouvertureport", views.OuverturePortViewSet)
router.register_viewset(r"machines/role", views.RoleViewSet)
# PREFERENCES
router.register_view(r'preferences/optionaluser', views.OptionalUserView),
router.register_view(r'preferences/optionalmachine', views.OptionalMachineView),
router.register_view(r'preferences/optionaltopologie', views.OptionalTopologieView),
router.register_view(r'preferences/radiusoption', views.RadiusOptionView),
router.register_view(r'preferences/generaloption', views.GeneralOptionView),
router.register_viewset(r'preferences/service', views.HomeServiceViewSet, base_name='homeservice'),
router.register_view(r'preferences/assooption', views.AssoOptionView),
router.register_view(r'preferences/homeoption', views.HomeOptionView),
router.register_view(r'preferences/mailmessageoption', views.MailMessageOptionView),
router.register_view(r"preferences/optionaluser", views.OptionalUserView),
router.register_view(r"preferences/optionalmachine", views.OptionalMachineView),
router.register_view(r"preferences/optionaltopologie", views.OptionalTopologieView),
router.register_view(r"preferences/radiusoption", views.RadiusOptionView),
router.register_view(r"preferences/generaloption", views.GeneralOptionView),
router.register_viewset(
r"preferences/service", views.HomeServiceViewSet, base_name="homeservice"
),
router.register_view(r"preferences/assooption", views.AssoOptionView),
router.register_view(r"preferences/homeoption", views.HomeOptionView),
router.register_view(r"preferences/mailmessageoption", views.MailMessageOptionView),
# TOPOLOGIE
router.register_viewset(r'topologie/stack', views.StackViewSet)
router.register_viewset(r'topologie/acesspoint', views.AccessPointViewSet)
router.register_viewset(r'topologie/switch', views.SwitchViewSet)
router.register_viewset(r'topologie/server', views.ServerViewSet)
router.register_viewset(r'topologie/modelswitch', views.ModelSwitchViewSet)
router.register_viewset(r'topologie/constructorswitch', views.ConstructorSwitchViewSet)
router.register_viewset(r'topologie/switchbay', views.SwitchBayViewSet)
router.register_viewset(r'topologie/building', views.BuildingViewSet)
router.register_viewset(r'topologie/switchport', views.SwitchPortViewSet, base_name='switchport')
router.register_viewset(r'topologie/portprofile', views.PortProfileViewSet, base_name='portprofile')
router.register_viewset(r'topologie/room', views.RoomViewSet)
router.register(r'topologie/portprofile', views.PortProfileViewSet)
router.register_viewset(r"topologie/stack", views.StackViewSet)
router.register_viewset(r"topologie/acesspoint", views.AccessPointViewSet)
router.register_viewset(r"topologie/switch", views.SwitchViewSet)
router.register_viewset(r"topologie/server", views.ServerViewSet)
router.register_viewset(r"topologie/modelswitch", views.ModelSwitchViewSet)
router.register_viewset(r"topologie/constructorswitch", views.ConstructorSwitchViewSet)
router.register_viewset(r"topologie/switchbay", views.SwitchBayViewSet)
router.register_viewset(r"topologie/building", views.BuildingViewSet)
router.register_viewset(
r"topologie/switchport", views.SwitchPortViewSet, base_name="switchport"
)
router.register_viewset(
r"topologie/portprofile", views.PortProfileViewSet, base_name="portprofile"
)
router.register_viewset(r"topologie/room", views.RoomViewSet)
router.register(r"topologie/portprofile", views.PortProfileViewSet)
# USERS
router.register_viewset(r'users/user', views.UserViewSet, base_name='user')
router.register_viewset(r'users/homecreation', views.HomeCreationViewSet, base_name='homecreation')
router.register_viewset(r'users/normaluser', views.NormalUserViewSet, base_name='normaluser')
router.register_viewset(r'users/criticaluser', views.CriticalUserViewSet, base_name='criticaluser')
router.register_viewset(r'users/club', views.ClubViewSet)
router.register_viewset(r'users/adherent', views.AdherentViewSet)
router.register_viewset(r'users/serviceuser', views.ServiceUserViewSet)
router.register_viewset(r'users/school', views.SchoolViewSet)
router.register_viewset(r'users/listright', views.ListRightViewSet)
router.register_viewset(r'users/shell', views.ShellViewSet, base_name='shell')
router.register_viewset(r'users/ban', views.BanViewSet)
router.register_viewset(r'users/whitelist', views.WhitelistViewSet)
router.register_viewset(r'users/emailaddress', views.EMailAddressViewSet)
router.register_viewset(r"users/user", views.UserViewSet, base_name="user")
router.register_viewset(
r"users/homecreation", views.HomeCreationViewSet, base_name="homecreation"
)
router.register_viewset(
r"users/normaluser", views.NormalUserViewSet, base_name="normaluser"
)
router.register_viewset(
r"users/criticaluser", views.CriticalUserViewSet, base_name="criticaluser"
)
router.register_viewset(r"users/club", views.ClubViewSet)
router.register_viewset(r"users/adherent", views.AdherentViewSet)
router.register_viewset(r"users/serviceuser", views.ServiceUserViewSet)
router.register_viewset(r"users/school", views.SchoolViewSet)
router.register_viewset(r"users/listright", views.ListRightViewSet)
router.register_viewset(r"users/shell", views.ShellViewSet, base_name="shell")
router.register_viewset(r"users/ban", views.BanViewSet)
router.register_viewset(r"users/whitelist", views.WhitelistViewSet)
router.register_viewset(r"users/emailaddress", views.EMailAddressViewSet)
# SERVICE REGEN
router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen')
router.register_viewset(
r"services/regen", views.ServiceRegenViewSet, base_name="serviceregen"
)
# DHCP
router.register_view(r'dhcp/hostmacip', views.HostMacIpView),
router.register_view(r"dhcp/hostmacip", views.HostMacIpView),
# LOCAL EMAILS
router.register_view(r'localemail/users', views.LocalEmailUsersView),
router.register_view(r"localemail/users", views.LocalEmailUsersView),
# Firewall
router.register_view(r'firewall/subnet-ports', views.SubnetPortsOpenView),
router.register_view(r'firewall/interface-ports', views.InterfacePortsOpenView),
router.register_view(r"firewall/subnet-ports", views.SubnetPortsOpenView),
router.register_view(r"firewall/interface-ports", views.InterfacePortsOpenView),
# Switches config
router.register_view(r'switchs/ports-config', views.SwitchPortView),
router.register_view(r'switchs/role', views.RoleView),
router.register_view(r"switchs/ports-config", views.SwitchPortView),
router.register_view(r"switchs/role", views.RoleView),
# Reminder
router.register_view(r'reminder/get-users', views.ReminderView),
router.register_view(r"reminder/get-users", views.ReminderView),
# DNS
router.register_view(r'dns/zones', views.DNSZonesView),
router.register_view(r'dns/reverse-zones', views.DNSReverseZonesView),
router.register_view(r"dns/zones", views.DNSZonesView),
router.register_view(r"dns/reverse-zones", views.DNSReverseZonesView),
# MAILING
router.register_view(r'mailing/standard', views.StandardMailingView),
router.register_view(r'mailing/club', views.ClubMailingView),
router.register_view(r"mailing/standard", views.StandardMailingView),
router.register_view(r"mailing/club", views.ClubMailingView),
# TOKEN AUTHENTICATION
router.register_view(r'token-auth', views.ObtainExpiringAuthToken)
router.register_view(r"token-auth", views.ObtainExpiringAuthToken)
urlpatterns = [
url(r'^', include(router.urls)),
]
urlpatterns = [url(r"^", include(router.urls))]

View file

@ -52,12 +52,15 @@ from .permissions import ACLPermission
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Facture` objects.
"""
queryset = cotisations.Facture.objects.all()
serializer_class = serializers.FactureSerializer
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Facture` objects.
"""
queryset = cotisations.BaseInvoice.objects.all()
serializer_class = serializers.BaseInvoiceSerializer
@ -65,6 +68,7 @@ class FactureViewSet(viewsets.ReadOnlyModelViewSet):
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Vente` objects.
"""
queryset = cotisations.Vente.objects.all()
serializer_class = serializers.VenteSerializer
@ -72,6 +76,7 @@ class VenteViewSet(viewsets.ReadOnlyModelViewSet):
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Article` objects.
"""
queryset = cotisations.Article.objects.all()
serializer_class = serializers.ArticleSerializer
@ -79,6 +84,7 @@ class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Banque` objects.
"""
queryset = cotisations.Banque.objects.all()
serializer_class = serializers.BanqueSerializer
@ -86,6 +92,7 @@ class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Paiement` objects.
"""
queryset = cotisations.Paiement.objects.all()
serializer_class = serializers.PaiementSerializer
@ -93,6 +100,7 @@ class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `cotisations.models.Cotisation` objects.
"""
queryset = cotisations.Cotisation.objects.all()
serializer_class = serializers.CotisationSerializer
@ -103,6 +111,7 @@ class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Machine` objects.
"""
queryset = machines.Machine.objects.all()
serializer_class = serializers.MachineSerializer
@ -110,6 +119,7 @@ class MachineViewSet(viewsets.ReadOnlyModelViewSet):
class MachineTypeViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.MachineType` objects.
"""
queryset = machines.MachineType.objects.all()
serializer_class = serializers.MachineTypeSerializer
@ -117,6 +127,7 @@ class MachineTypeViewSet(viewsets.ReadOnlyModelViewSet):
class IpTypeViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.IpType` objects.
"""
queryset = machines.IpType.objects.all()
serializer_class = serializers.IpTypeSerializer
@ -124,6 +135,7 @@ class IpTypeViewSet(viewsets.ReadOnlyModelViewSet):
class VlanViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Vlan` objects.
"""
queryset = machines.Vlan.objects.all()
serializer_class = serializers.VlanSerializer
@ -131,6 +143,7 @@ class VlanViewSet(viewsets.ReadOnlyModelViewSet):
class NasViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Nas` objects.
"""
queryset = machines.Nas.objects.all()
serializer_class = serializers.NasSerializer
@ -138,6 +151,7 @@ class NasViewSet(viewsets.ReadOnlyModelViewSet):
class SOAViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.SOA` objects.
"""
queryset = machines.SOA.objects.all()
serializer_class = serializers.SOASerializer
@ -145,6 +159,7 @@ class SOAViewSet(viewsets.ReadOnlyModelViewSet):
class ExtensionViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Extension` objects.
"""
queryset = machines.Extension.objects.all()
serializer_class = serializers.ExtensionSerializer
@ -152,6 +167,7 @@ class ExtensionViewSet(viewsets.ReadOnlyModelViewSet):
class MxViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Mx` objects.
"""
queryset = machines.Mx.objects.all()
serializer_class = serializers.MxSerializer
@ -159,6 +175,7 @@ class MxViewSet(viewsets.ReadOnlyModelViewSet):
class NsViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Ns` objects.
"""
queryset = machines.Ns.objects.all()
serializer_class = serializers.NsSerializer
@ -166,6 +183,7 @@ class NsViewSet(viewsets.ReadOnlyModelViewSet):
class TxtViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Txt` objects.
"""
queryset = machines.Txt.objects.all()
serializer_class = serializers.TxtSerializer
@ -173,6 +191,7 @@ class TxtViewSet(viewsets.ReadOnlyModelViewSet):
class DNameViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.DName` objects.
"""
queryset = machines.DName.objects.all()
serializer_class = serializers.DNameSerializer
@ -180,6 +199,7 @@ class DNameViewSet(viewsets.ReadOnlyModelViewSet):
class SrvViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Srv` objects.
"""
queryset = machines.Srv.objects.all()
serializer_class = serializers.SrvSerializer
@ -187,6 +207,7 @@ class SrvViewSet(viewsets.ReadOnlyModelViewSet):
class SshFpViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.SshFp` objects.
"""
queryset = machines.SshFp.objects.all()
serializer_class = serializers.SshFpSerializer
@ -194,6 +215,7 @@ class SshFpViewSet(viewsets.ReadOnlyModelViewSet):
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Interface` objects.
"""
queryset = machines.Interface.objects.all()
serializer_class = serializers.InterfaceSerializer
@ -201,6 +223,7 @@ class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
class Ipv6ListViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Ipv6List` objects.
"""
queryset = machines.Ipv6List.objects.all()
serializer_class = serializers.Ipv6ListSerializer
@ -208,6 +231,7 @@ class Ipv6ListViewSet(viewsets.ReadOnlyModelViewSet):
class DomainViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Domain` objects.
"""
queryset = machines.Domain.objects.all()
serializer_class = serializers.DomainSerializer
@ -215,6 +239,7 @@ class DomainViewSet(viewsets.ReadOnlyModelViewSet):
class IpListViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.IpList` objects.
"""
queryset = machines.IpList.objects.all()
serializer_class = serializers.IpListSerializer
@ -222,6 +247,7 @@ class IpListViewSet(viewsets.ReadOnlyModelViewSet):
class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Service` objects.
"""
queryset = machines.Service.objects.all()
serializer_class = serializers.ServiceSerializer
@ -229,6 +255,7 @@ class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
class ServiceLinkViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Service_link` objects.
"""
queryset = machines.Service_link.objects.all()
serializer_class = serializers.ServiceLinkSerializer
@ -237,6 +264,7 @@ class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.OuverturePortList`
objects.
"""
queryset = machines.OuverturePortList.objects.all()
serializer_class = serializers.OuverturePortListSerializer
@ -244,6 +272,7 @@ class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.OuverturePort` objects.
"""
queryset = machines.OuverturePort.objects.all()
serializer_class = serializers.OuverturePortSerializer
@ -251,6 +280,7 @@ class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
class RoleViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `machines.models.Machine` objects.
"""
queryset = machines.Role.objects.all()
serializer_class = serializers.RoleSerializer
@ -259,11 +289,13 @@ class RoleViewSet(viewsets.ReadOnlyModelViewSet):
# Those views differ a bit because there is only one object
# to display, so we don't bother with the listing part
class OptionalUserView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.OptionalUser.can_view_all]}
perms_map = {"GET": [preferences.OptionalUser.can_view_all]}
serializer_class = serializers.OptionalUserSerializer
def get_object(self):
@ -273,8 +305,9 @@ class OptionalUserView(generics.RetrieveAPIView):
class OptionalMachineView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.OptionalMachine` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.OptionalMachine.can_view_all]}
perms_map = {"GET": [preferences.OptionalMachine.can_view_all]}
serializer_class = serializers.OptionalMachineSerializer
def get_object(self):
@ -284,8 +317,9 @@ class OptionalMachineView(generics.RetrieveAPIView):
class OptionalTopologieView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.OptionalTopologie` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.OptionalTopologie.can_view_all]}
perms_map = {"GET": [preferences.OptionalTopologie.can_view_all]}
serializer_class = serializers.OptionalTopologieSerializer
def get_object(self):
@ -295,8 +329,9 @@ class OptionalTopologieView(generics.RetrieveAPIView):
class RadiusOptionView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.OptionalTopologie` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.RadiusOption.can_view_all]}
perms_map = {"GET": [preferences.RadiusOption.can_view_all]}
serializer_class = serializers.RadiusOptionSerializer
def get_object(self):
@ -306,8 +341,9 @@ class RadiusOptionView(generics.RetrieveAPIView):
class GeneralOptionView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.GeneralOption` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.GeneralOption.can_view_all]}
perms_map = {"GET": [preferences.GeneralOption.can_view_all]}
serializer_class = serializers.GeneralOptionSerializer
def get_object(self):
@ -317,6 +353,7 @@ class GeneralOptionView(generics.RetrieveAPIView):
class HomeServiceViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `preferences.models.Service` objects.
"""
queryset = preferences.Service.objects.all()
serializer_class = serializers.HomeServiceSerializer
@ -324,8 +361,9 @@ class HomeServiceViewSet(viewsets.ReadOnlyModelViewSet):
class AssoOptionView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.AssoOption` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.AssoOption.can_view_all]}
perms_map = {"GET": [preferences.AssoOption.can_view_all]}
serializer_class = serializers.AssoOptionSerializer
def get_object(self):
@ -335,8 +373,9 @@ class AssoOptionView(generics.RetrieveAPIView):
class HomeOptionView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.HomeOption` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.HomeOption.can_view_all]}
perms_map = {"GET": [preferences.HomeOption.can_view_all]}
serializer_class = serializers.HomeOptionSerializer
def get_object(self):
@ -346,8 +385,9 @@ class HomeOptionView(generics.RetrieveAPIView):
class MailMessageOptionView(generics.RetrieveAPIView):
"""Exposes details of `preferences.models.MailMessageOption` settings.
"""
permission_classes = (ACLPermission,)
perms_map = {'GET': [preferences.MailMessageOption.can_view_all]}
perms_map = {"GET": [preferences.MailMessageOption.can_view_all]}
serializer_class = serializers.MailMessageOptionSerializer
def get_object(self):
@ -360,6 +400,7 @@ class MailMessageOptionView(generics.RetrieveAPIView):
class StackViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.Stack` objects.
"""
queryset = topologie.Stack.objects.all()
serializer_class = serializers.StackSerializer
@ -367,6 +408,7 @@ class StackViewSet(viewsets.ReadOnlyModelViewSet):
class AccessPointViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.AccessPoint` objects.
"""
queryset = topologie.AccessPoint.objects.all()
serializer_class = serializers.AccessPointSerializer
@ -374,6 +416,7 @@ class AccessPointViewSet(viewsets.ReadOnlyModelViewSet):
class SwitchViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.Switch` objects.
"""
queryset = topologie.Switch.objects.all()
serializer_class = serializers.SwitchSerializer
@ -381,6 +424,7 @@ class SwitchViewSet(viewsets.ReadOnlyModelViewSet):
class ServerViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.Server` objects.
"""
queryset = topologie.Server.objects.all()
serializer_class = serializers.ServerSerializer
@ -388,6 +432,7 @@ class ServerViewSet(viewsets.ReadOnlyModelViewSet):
class ModelSwitchViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.ModelSwitch` objects.
"""
queryset = topologie.ModelSwitch.objects.all()
serializer_class = serializers.ModelSwitchSerializer
@ -396,6 +441,7 @@ class ConstructorSwitchViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.ConstructorSwitch`
objects.
"""
queryset = topologie.ConstructorSwitch.objects.all()
serializer_class = serializers.ConstructorSwitchSerializer
@ -403,6 +449,7 @@ class ConstructorSwitchViewSet(viewsets.ReadOnlyModelViewSet):
class SwitchBayViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.SwitchBay` objects.
"""
queryset = topologie.SwitchBay.objects.all()
serializer_class = serializers.SwitchBaySerializer
@ -410,6 +457,7 @@ class SwitchBayViewSet(viewsets.ReadOnlyModelViewSet):
class BuildingViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.Building` objects.
"""
queryset = topologie.Building.objects.all()
serializer_class = serializers.BuildingSerializer
@ -417,6 +465,7 @@ class BuildingViewSet(viewsets.ReadOnlyModelViewSet):
class SwitchPortViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.Port` objects.
"""
queryset = topologie.Port.objects.all()
serializer_class = serializers.SwitchPortSerializer
@ -424,6 +473,7 @@ class SwitchPortViewSet(viewsets.ReadOnlyModelViewSet):
class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.PortProfile` objects.
"""
queryset = topologie.PortProfile.objects.all()
serializer_class = serializers.PortProfileSerializer
@ -431,6 +481,7 @@ class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
class RoomViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.Room` objects.
"""
queryset = topologie.Room.objects.all()
serializer_class = serializers.RoomSerializer
@ -438,6 +489,7 @@ class RoomViewSet(viewsets.ReadOnlyModelViewSet):
class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `topologie.models.PortProfile` objects.
"""
queryset = topologie.PortProfile.objects.all()
serializer_class = serializers.PortProfileSerializer
@ -448,6 +500,7 @@ class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.Users` objects.
"""
queryset = users.User.objects.all()
serializer_class = serializers.UserSerializer
@ -455,18 +508,25 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
class HomeCreationViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes infos of `users.models.Users` objects to create homes.
"""
queryset = users.User.objects.exclude(Q(state=users.User.STATE_DISABLED) | Q(state=users.User.STATE_NOT_YET_ACTIVE) | Q(state=users.User.STATE_FULL_ARCHIVE))
queryset = users.User.objects.exclude(
Q(state=users.User.STATE_DISABLED)
| Q(state=users.User.STATE_NOT_YET_ACTIVE)
| Q(state=users.User.STATE_FULL_ARCHIVE)
)
serializer_class = serializers.BasicUserSerializer
class NormalUserViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes infos of `users.models.Users`without specific rights objects."""
queryset = users.User.objects.exclude(groups__listright__critical=True).distinct()
serializer_class = serializers.BasicUserSerializer
class CriticalUserViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes infos of `users.models.Users`without specific rights objects."""
queryset = users.User.objects.filter(groups__listright__critical=True).distinct()
serializer_class = serializers.BasicUserSerializer
@ -474,6 +534,7 @@ class CriticalUserViewSet(viewsets.ReadOnlyModelViewSet):
class ClubViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.Club` objects.
"""
queryset = users.Club.objects.all()
serializer_class = serializers.ClubSerializer
@ -481,6 +542,7 @@ class ClubViewSet(viewsets.ReadOnlyModelViewSet):
class AdherentViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.Adherent` objects.
"""
queryset = users.Adherent.objects.all()
serializer_class = serializers.AdherentSerializer
@ -488,6 +550,7 @@ class AdherentViewSet(viewsets.ReadOnlyModelViewSet):
class ServiceUserViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.ServiceUser` objects.
"""
queryset = users.ServiceUser.objects.all()
serializer_class = serializers.ServiceUserSerializer
@ -495,6 +558,7 @@ class ServiceUserViewSet(viewsets.ReadOnlyModelViewSet):
class SchoolViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.School` objects.
"""
queryset = users.School.objects.all()
serializer_class = serializers.SchoolSerializer
@ -502,6 +566,7 @@ class SchoolViewSet(viewsets.ReadOnlyModelViewSet):
class ListRightViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.ListRight` objects.
"""
queryset = users.ListRight.objects.all()
serializer_class = serializers.ListRightSerializer
@ -509,6 +574,7 @@ class ListRightViewSet(viewsets.ReadOnlyModelViewSet):
class ShellViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.ListShell` objects.
"""
queryset = users.ListShell.objects.all()
serializer_class = serializers.ShellSerializer
@ -516,6 +582,7 @@ class ShellViewSet(viewsets.ReadOnlyModelViewSet):
class BanViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.Ban` objects.
"""
queryset = users.Ban.objects.all()
serializer_class = serializers.BanSerializer
@ -523,6 +590,7 @@ class BanViewSet(viewsets.ReadOnlyModelViewSet):
class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.Whitelist` objects.
"""
queryset = users.Whitelist.objects.all()
serializer_class = serializers.WhitelistSerializer
@ -530,14 +598,13 @@ class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes list and details of `users.models.EMailAddress` objects.
"""
serializer_class = serializers.EMailAddressSerializer
queryset = users.EMailAddress.objects.none()
def get_queryset(self):
if preferences.OptionalUser.get_cached_value(
'local_email_accounts_enabled'):
return (users.EMailAddress.objects
.filter(user__local_email_enabled=True))
if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"):
return users.EMailAddress.objects.filter(user__local_email_enabled=True)
else:
return users.EMailAddress.objects.none()
@ -548,34 +615,47 @@ class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet):
class ServiceRegenViewSet(viewsets.ModelViewSet):
"""Exposes list and details of the services to regen
"""
serializer_class = serializers.ServiceRegenSerializer
def get_queryset(self):
queryset = machines.Service_link.objects.select_related(
'server__domain'
).select_related(
'service'
)
if 'hostname' in self.request.GET:
hostname = self.request.GET['hostname']
"server__domain"
).select_related("service")
if "hostname" in self.request.GET:
hostname = self.request.GET["hostname"]
queryset = queryset.filter(server__domain__name__iexact=hostname)
return queryset
# Config des switches
class SwitchPortView(generics.ListAPIView):
"""Output each port of a switch, to be serialized with
additionnal informations (profiles etc)
"""
queryset = topologie.Switch.objects.all().select_related("switchbay").select_related("model__constructor").prefetch_related("ports__custom_profile__vlan_tagged").prefetch_related("ports__custom_profile__vlan_untagged").prefetch_related("ports__machine_interface__domain__extension").prefetch_related("ports__room")
queryset = (
topologie.Switch.objects.all()
.select_related("switchbay")
.select_related("model__constructor")
.prefetch_related("ports__custom_profile__vlan_tagged")
.prefetch_related("ports__custom_profile__vlan_untagged")
.prefetch_related("ports__machine_interface__domain__extension")
.prefetch_related("ports__room")
)
serializer_class = serializers.SwitchPortSerializer
# Rappel fin adhésion
class ReminderView(generics.ListAPIView):
"""Output for users to remind an end of their subscription.
"""
queryset = preferences.Reminder.objects.all()
serializer_class = serializers.ReminderSerializer
@ -583,7 +663,8 @@ class ReminderView(generics.ListAPIView):
class RoleView(generics.ListAPIView):
"""Output of roles for each server
"""
queryset = machines.Role.objects.all().prefetch_related('servers')
queryset = machines.Role.objects.all().prefetch_related("servers")
serializer_class = serializers.RoleSerializer
@ -593,13 +674,12 @@ class RoleView(generics.ListAPIView):
class LocalEmailUsersView(generics.ListAPIView):
"""Exposes all the aliases of the users that activated the internal address
"""
serializer_class = serializers.LocalEmailUsersSerializer
def get_queryset(self):
if preferences.OptionalUser.get_cached_value(
'local_email_accounts_enabled'):
return (users.User.objects
.filter(local_email_enabled=True))
if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"):
return users.User.objects.filter(local_email_enabled=True)
else:
return users.User.objects.none()
@ -611,6 +691,7 @@ class HostMacIpView(generics.ListAPIView):
"""Exposes the associations between hostname, mac address and IPv4 in
order to build the DHCP lease files.
"""
serializer_class = serializers.HostMacIpSerializer
def get_queryset(self):
@ -619,6 +700,7 @@ class HostMacIpView(generics.ListAPIView):
# Firewall
class SubnetPortsOpenView(generics.ListAPIView):
queryset = machines.IpType.objects.all()
serializer_class = serializers.SubnetPortsOpenSerializer
@ -636,14 +718,19 @@ class DNSZonesView(generics.ListAPIView):
"""Exposes the detailed information about each extension (hostnames,
IPs, DNS records, etc.) in order to build the DNS zone files.
"""
queryset = (machines.Extension.objects
.prefetch_related('soa')
.prefetch_related('ns_set').prefetch_related('ns_set__ns')
.prefetch_related('origin')
.prefetch_related('mx_set').prefetch_related('mx_set__name')
.prefetch_related('txt_set')
.prefetch_related('srv_set').prefetch_related('srv_set__target')
.all())
queryset = (
machines.Extension.objects.prefetch_related("soa")
.prefetch_related("ns_set")
.prefetch_related("ns_set__ns")
.prefetch_related("origin")
.prefetch_related("mx_set")
.prefetch_related("mx_set__name")
.prefetch_related("txt_set")
.prefetch_related("srv_set")
.prefetch_related("srv_set__target")
.all()
)
serializer_class = serializers.DNSZonesSerializer
@ -651,7 +738,8 @@ class DNSReverseZonesView(generics.ListAPIView):
"""Exposes the detailed information about each extension (hostnames,
IPs, DNS records, etc.) in order to build the DNS zone files.
"""
queryset = (machines.IpType.objects.all())
queryset = machines.IpType.objects.all()
serializer_class = serializers.DNSReverseZonesSerializer
@ -662,13 +750,16 @@ class StandardMailingView(views.APIView):
"""Exposes list and details of standard mailings (name and members) in
order to building the corresponding mailing lists.
"""
pagination_class = PageSizedPagination
permission_classes = (ACLPermission,)
perms_map = {'GET': [users.User.can_view_all]}
perms_map = {"GET": [users.User.can_view_all]}
def get(self, request, format=None):
adherents_data = serializers.MailingMemberSerializer(all_has_access(), many=True).data
data = [{'name': 'adherents', 'members': adherents_data}]
adherents_data = serializers.MailingMemberSerializer(
all_has_access(), many=True
).data
data = [{"name": "adherents", "members": adherents_data}]
paginator = self.pagination_class()
paginator.paginate_queryset(data, request)
return paginator.get_paginated_response(data)
@ -678,6 +769,7 @@ class ClubMailingView(generics.ListAPIView):
"""Exposes list and details of club mailings (name, members and admins) in
order to build the corresponding mailing lists.
"""
queryset = users.Club.objects.all()
serializer_class = serializers.MailingSerializer
@ -696,12 +788,10 @@ class ObtainExpiringAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
user = serializer.validated_data["user"]
token, created = Token.objects.get_or_create(user=user)
token_duration = datetime.timedelta(
seconds=settings.API_TOKEN_DURATION
)
token_duration = datetime.timedelta(seconds=settings.API_TOKEN_DURATION)
utc_now = datetime.datetime.now(datetime.timezone.utc)
if not created and token.created < utc_now - token_duration:
token.delete()
@ -709,7 +799,6 @@ class ObtainExpiringAuthToken(ObtainAuthToken):
token.created = datetime.datetime.utcnow()
token.save()
return Response({
'token': token.key,
'expiration': token.created + token_duration
})
return Response(
{"token": token.key, "expiration": token.created + token_duration}
)

View file

@ -38,13 +38,12 @@ def can_view(user):
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_module_perms('cotisations')
can = user.has_module_perms("cotisations")
if can:
return can, None, ('cotisations',)
return can, None, ("cotisations",)
else:
return (
can,
_("You don't have the right to view this application."),
('cotisations',)
("cotisations",),
)

View file

@ -35,42 +35,50 @@ from .models import CustomInvoice, CostEstimate
class FactureAdmin(VersionAdmin):
"""Class admin d'une facture, tous les champs"""
pass
class CostEstimateAdmin(VersionAdmin):
"""Admin class for cost estimates."""
pass
class CustomInvoiceAdmin(VersionAdmin):
"""Admin class for custom invoices."""
pass
class VenteAdmin(VersionAdmin):
"""Class admin d'une vente, tous les champs (facture related)"""
pass
class ArticleAdmin(VersionAdmin):
"""Class admin d'un article en vente"""
pass
class BanqueAdmin(VersionAdmin):
"""Class admin de la liste des banques (facture related)"""
pass
class PaiementAdmin(VersionAdmin):
"""Class admin d'un moyen de paiement (facture related"""
pass
class CotisationAdmin(VersionAdmin):
"""Class admin d'une cotisation (date de debut et de fin),
Vente related"""
pass

View file

@ -47,8 +47,13 @@ from django.shortcuts import get_object_or_404
from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin
from .models import (
Article, Paiement, Facture, Banque,
CustomInvoice, Vente, CostEstimate,
Article,
Paiement,
Facture,
Banque,
CustomInvoice,
Vente,
CostEstimate,
)
from .payment_methods import balance
@ -59,31 +64,27 @@ class FactureForm(FieldPermissionFormMixin, FormRevMixin, ModelForm):
"""
def __init__(self, *args, creation=False, **kwargs):
user = kwargs['user']
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
user = kwargs["user"]
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(FactureForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['paiement'].empty_label = \
_("Select a payment method")
self.fields['paiement'].queryset = Paiement.find_allowed_payments(user)
self.fields["paiement"].empty_label = _("Select a payment method")
self.fields["paiement"].queryset = Paiement.find_allowed_payments(user)
if not creation:
self.fields['user'].label = _("Member")
self.fields['user'].empty_label = \
_("Select the proprietary member")
self.fields['valid'].label = _("Validated invoice")
self.fields["user"].label = _("Member")
self.fields["user"].empty_label = _("Select the proprietary member")
self.fields["valid"].label = _("Validated invoice")
else:
self.fields = {'paiement': self.fields['paiement']}
self.fields = {"paiement": self.fields["paiement"]}
class Meta:
model = Facture
fields = '__all__'
fields = "__all__"
def clean(self):
cleaned_data = super(FactureForm, self).clean()
paiement = cleaned_data.get('paiement')
paiement = cleaned_data.get("paiement")
if not paiement:
raise forms.ValidationError(
_("A payment method must be specified.")
)
raise forms.ValidationError(_("A payment method must be specified."))
return cleaned_data
@ -92,32 +93,30 @@ class SelectArticleForm(FormRevMixin, Form):
Form used to select an article during the creation of an invoice for a
member.
"""
article = forms.ModelChoiceField(
queryset=Article.objects.none(),
label=_("Article"),
required=True
queryset=Article.objects.none(), label=_("Article"), required=True
)
quantity = forms.IntegerField(
label=_("Quantity"),
validators=[MinValueValidator(1)],
required=True
label=_("Quantity"), validators=[MinValueValidator(1)], required=True
)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
target_user = kwargs.pop('target_user', None)
user = kwargs.pop("user")
target_user = kwargs.pop("target_user", None)
super(SelectArticleForm, self).__init__(*args, **kwargs)
self.fields['article'].queryset = Article.find_allowed_articles(
user, target_user)
self.fields["article"].queryset = Article.find_allowed_articles(
user, target_user
)
class DiscountForm(Form):
"""
Form used in oder to create a discount on an invoice.
"""
is_relative = forms.BooleanField(
label=_("Discount is on percentage."),
required=False,
label=_("Discount is on percentage."), required=False
)
discount = forms.DecimalField(
label=_("Discount"),
@ -130,53 +129,51 @@ class DiscountForm(Form):
def apply_to_invoice(self, invoice):
invoice_price = invoice.prix_total()
discount = self.cleaned_data['discount']
is_relative = self.cleaned_data['is_relative']
discount = self.cleaned_data["discount"]
is_relative = self.cleaned_data["is_relative"]
if is_relative:
amount = discount/100 * invoice_price
amount = discount / 100 * invoice_price
else:
amount = discount
if amount:
name = _("{}% discount") if is_relative else _("{}€ discount")
name = name.format(discount)
Vente.objects.create(
facture=invoice,
name=name,
prix=-amount,
number=1
)
Vente.objects.create(facture=invoice, name=name, prix=-amount, number=1)
class CustomInvoiceForm(FormRevMixin, ModelForm):
"""
Form used to create a custom invoice.
"""
class Meta:
model = CustomInvoice
fields = '__all__'
fields = "__all__"
class CostEstimateForm(FormRevMixin, ModelForm):
"""
Form used to create a cost estimate.
"""
class Meta:
model = CostEstimate
exclude = ['paid', 'final_invoice']
exclude = ["paid", "final_invoice"]
class ArticleForm(FormRevMixin, ModelForm):
"""
Form used to create an article.
"""
class Meta:
model = Article
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ArticleForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = _("Article name")
self.fields["name"].label = _("Article name")
class DelArticleForm(FormRevMixin, Form):
@ -184,19 +181,20 @@ class DelArticleForm(FormRevMixin, Form):
Form used to delete one or more of the currently available articles.
The user must choose the one to delete by checking the boxes.
"""
articles = forms.ModelMultipleChoiceField(
queryset=Article.objects.none(),
label=_("Available articles"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelArticleForm, self).__init__(*args, **kwargs)
if instances:
self.fields['articles'].queryset = instances
self.fields["articles"].queryset = instances
else:
self.fields['articles'].queryset = Article.objects.all()
self.fields["articles"].queryset = Article.objects.all()
# TODO : change Paiement to Payment
@ -206,15 +204,16 @@ class PaiementForm(FormRevMixin, ModelForm):
The 'cheque' type is used to associate a specific behaviour requiring
a cheque number and a bank.
"""
class Meta:
model = Paiement
# TODO : change moyen to method and type_paiement to payment_type
fields = ['moyen', 'available_for_everyone']
fields = ["moyen", "available_for_everyone"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(PaiementForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['moyen'].label = _("Payment method name")
self.fields["moyen"].label = _("Payment method name")
# TODO : change paiement to payment
@ -223,20 +222,21 @@ class DelPaiementForm(FormRevMixin, Form):
Form used to delete one or more payment methods.
The user must choose the one to delete by checking the boxes.
"""
# TODO : change paiement to payment
paiements = forms.ModelMultipleChoiceField(
queryset=Paiement.objects.none(),
label=_("Available payment methods"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelPaiementForm, self).__init__(*args, **kwargs)
if instances:
self.fields['paiements'].queryset = instances
self.fields["paiements"].queryset = instances
else:
self.fields['paiements'].queryset = Paiement.objects.all()
self.fields["paiements"].queryset = Paiement.objects.all()
# TODO : change banque to bank
@ -244,15 +244,16 @@ class BanqueForm(FormRevMixin, ModelForm):
"""
Form used to create a bank.
"""
class Meta:
# TODO : change banque to bank
model = Banque
fields = ['name']
fields = ["name"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(BanqueForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = _("Bank name")
self.fields["name"].label = _("Bank name")
# TODO : change banque to bank
@ -261,20 +262,21 @@ class DelBanqueForm(FormRevMixin, Form):
Form used to delete one or more banks.
The use must choose the one to delete by checking the boxes.
"""
# TODO : change banque to bank
banques = forms.ModelMultipleChoiceField(
queryset=Banque.objects.none(),
label=_("Available banks"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelBanqueForm, self).__init__(*args, **kwargs)
if instances:
self.fields['banques'].queryset = instances
self.fields["banques"].queryset = instances
else:
self.fields['banques'].queryset = Banque.objects.all()
self.fields["banques"].queryset = Banque.objects.all()
# TODO : Better name and docstring
@ -282,36 +284,36 @@ class RechargeForm(FormRevMixin, Form):
"""
Form used to refill a user's balance
"""
value = forms.DecimalField(
label=_("Amount"),
decimal_places=2,
)
value = forms.DecimalField(label=_("Amount"), decimal_places=2)
payment = forms.ModelChoiceField(
queryset=Paiement.objects.none(),
label=_("Payment method")
queryset=Paiement.objects.none(), label=_("Payment method")
)
def __init__(self, *args, user=None, user_source=None, **kwargs):
self.user = user
super(RechargeForm, self).__init__(*args, **kwargs)
self.fields['payment'].empty_label = \
_("Select a payment method")
self.fields['payment'].queryset = Paiement.find_allowed_payments(
user_source).exclude(is_balance=True)
self.fields["payment"].empty_label = _("Select a payment method")
self.fields["payment"].queryset = Paiement.find_allowed_payments(
user_source
).exclude(is_balance=True)
def clean(self):
"""
Returns a cleaned value from the received form by validating
the value is well inside the possible limits
"""
value = self.cleaned_data['value']
value = self.cleaned_data["value"]
balance_method = get_object_or_404(balance.PaymentMethod)
if balance_method.maximum_balance is not None and \
value + self.user.solde > balance_method.maximum_balance:
if (
balance_method.maximum_balance is not None
and value + self.user.solde > balance_method.maximum_balance
):
raise forms.ValidationError(
_("Requested amount is too high. Your balance can't exceed"
" %(max_online_balance)s €.") % {
'max_online_balance': balance_method.maximum_balance
}
_(
"Requested amount is too high. Your balance can't exceed"
" %(max_online_balance)s €."
)
% {"max_online_balance": balance_method.maximum_balance}
)
return self.cleaned_data

View file

@ -29,54 +29,100 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0005_auto_20160702_0006'),
]
dependencies = [("users", "0005_auto_20160702_0006")]
operations = [
migrations.CreateModel(
name='Article',
name="Article",
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
('name', models.CharField(max_length=255)),
('prix', models.DecimalField(decimal_places=2, max_digits=5)),
(
"id",
models.AutoField(
verbose_name="ID",
auto_created=True,
primary_key=True,
serialize=False,
),
),
("name", models.CharField(max_length=255)),
("prix", models.DecimalField(decimal_places=2, max_digits=5)),
],
),
migrations.CreateModel(
name='Banque',
name="Banque",
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
('name', models.CharField(max_length=255)),
(
"id",
models.AutoField(
verbose_name="ID",
auto_created=True,
primary_key=True,
serialize=False,
),
),
("name", models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='Facture',
name="Facture",
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
('cheque', models.CharField(max_length=255)),
('number', models.IntegerField()),
('date', models.DateTimeField(auto_now_add=True)),
('name', models.CharField(max_length=255)),
('prix', models.DecimalField(decimal_places=2, max_digits=5)),
('article', models.ForeignKey(to='cotisations.Article', on_delete=django.db.models.deletion.PROTECT)),
('banque', models.ForeignKey(to='cotisations.Banque', on_delete=django.db.models.deletion.PROTECT)),
(
"id",
models.AutoField(
verbose_name="ID",
auto_created=True,
primary_key=True,
serialize=False,
),
),
("cheque", models.CharField(max_length=255)),
("number", models.IntegerField()),
("date", models.DateTimeField(auto_now_add=True)),
("name", models.CharField(max_length=255)),
("prix", models.DecimalField(decimal_places=2, max_digits=5)),
(
"article",
models.ForeignKey(
to="cotisations.Article",
on_delete=django.db.models.deletion.PROTECT,
),
),
(
"banque",
models.ForeignKey(
to="cotisations.Banque",
on_delete=django.db.models.deletion.PROTECT,
),
),
],
),
migrations.CreateModel(
name='Paiement',
name="Paiement",
fields=[
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
('moyen', models.CharField(max_length=255)),
(
"id",
models.AutoField(
verbose_name="ID",
auto_created=True,
primary_key=True,
serialize=False,
),
),
("moyen", models.CharField(max_length=255)),
],
),
migrations.AddField(
model_name='facture',
name='paiement',
field=models.ForeignKey(to='cotisations.Paiement', on_delete=django.db.models.deletion.PROTECT),
model_name="facture",
name="paiement",
field=models.ForeignKey(
to="cotisations.Paiement", on_delete=django.db.models.deletion.PROTECT
),
),
migrations.AddField(
model_name='facture',
name='user',
field=models.ForeignKey(to='users.User', on_delete=django.db.models.deletion.PROTECT),
model_name="facture",
name="user",
field=models.ForeignKey(
to="users.User", on_delete=django.db.models.deletion.PROTECT
),
),
]

View file

@ -28,13 +28,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0001_initial'),
]
dependencies = [("cotisations", "0001_initial")]
operations = [
migrations.RemoveField(
model_name='facture',
name='article',
),
]
operations = [migrations.RemoveField(model_name="facture", name="article")]

View file

@ -29,14 +29,17 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0002_remove_facture_article'),
]
dependencies = [("cotisations", "0002_remove_facture_article")]
operations = [
migrations.AlterField(
model_name='facture',
name='banque',
field=models.ForeignKey(blank=True, to='cotisations.Banque', on_delete=django.db.models.deletion.PROTECT, null=True),
model_name="facture",
name="banque",
field=models.ForeignKey(
blank=True,
to="cotisations.Banque",
on_delete=django.db.models.deletion.PROTECT,
null=True,
),
)
]

View file

@ -28,19 +28,17 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0003_auto_20160702_1448'),
]
dependencies = [("cotisations", "0003_auto_20160702_1448")]
operations = [
migrations.AlterField(
model_name='facture',
name='name',
model_name="facture",
name="name",
field=models.CharField(null=True, max_length=255),
),
migrations.AlterField(
model_name='facture',
name='prix',
model_name="facture",
name="prix",
field=models.DecimalField(max_digits=5, null=True, decimal_places=2),
),
]

View file

@ -28,14 +28,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0004_auto_20160702_1528'),
]
dependencies = [("cotisations", "0004_auto_20160702_1528")]
operations = [
migrations.AlterField(
model_name='facture',
name='cheque',
model_name="facture",
name="cheque",
field=models.CharField(max_length=255, blank=True),
),
)
]

View file

@ -28,19 +28,19 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0005_auto_20160702_1532'),
]
dependencies = [("cotisations", "0005_auto_20160702_1532")]
operations = [
migrations.AlterField(
model_name='facture',
name='name',
field=models.CharField(null=True, default='plop', max_length=255),
model_name="facture",
name="name",
field=models.CharField(null=True, default="plop", max_length=255),
),
migrations.AlterField(
model_name='facture',
name='prix',
field=models.DecimalField(null=True, decimal_places=2, default=1, max_digits=5),
model_name="facture",
name="prix",
field=models.DecimalField(
null=True, decimal_places=2, default=1, max_digits=5
),
),
]

View file

@ -28,20 +28,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0006_auto_20160702_1534'),
]
dependencies = [("cotisations", "0006_auto_20160702_1534")]
operations = [
migrations.AlterField(
model_name='facture',
name='name',
field=models.CharField(default='plop', max_length=255),
model_name="facture",
name="name",
field=models.CharField(default="plop", max_length=255),
preserve_default=False,
),
migrations.AlterField(
model_name='facture',
name='prix',
model_name="facture",
name="prix",
field=models.DecimalField(default=1, max_digits=5, decimal_places=2),
preserve_default=False,
),

View file

@ -30,43 +30,53 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0005_auto_20160702_0006'),
('cotisations', '0007_auto_20160702_1543'),
("users", "0005_auto_20160702_0006"),
("cotisations", "0007_auto_20160702_1543"),
]
operations = [
migrations.CreateModel(
name='Cotisation',
name="Cotisation",
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('date_start', models.DateTimeField(auto_now_add=True)),
('date_end', models.DateTimeField()),
(
"id",
models.AutoField(
verbose_name="ID",
primary_key=True,
serialize=False,
auto_created=True,
),
),
("date_start", models.DateTimeField(auto_now_add=True)),
("date_end", models.DateTimeField()),
],
),
migrations.AddField(
model_name='article',
name='cotisation',
model_name="article",
name="cotisation",
field=models.BooleanField(default=True),
preserve_default=False,
),
migrations.AddField(
model_name='article',
name='duration',
model_name="article",
name="duration",
field=models.DurationField(blank=True, null=True),
),
migrations.AddField(
model_name='facture',
name='valid',
field=models.BooleanField(default=True),
model_name="facture", name="valid", field=models.BooleanField(default=True)
),
migrations.AddField(
model_name='cotisation',
name='facture',
field=models.ForeignKey(to='cotisations.Facture', on_delete=django.db.models.deletion.PROTECT),
model_name="cotisation",
name="facture",
field=models.ForeignKey(
to="cotisations.Facture", on_delete=django.db.models.deletion.PROTECT
),
),
migrations.AddField(
model_name='cotisation',
name='user',
field=models.ForeignKey(to='users.User', on_delete=django.db.models.deletion.PROTECT),
model_name="cotisation",
name="user",
field=models.ForeignKey(
to="users.User", on_delete=django.db.models.deletion.PROTECT
),
),
]

View file

@ -28,13 +28,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0008_auto_20160702_1614'),
]
dependencies = [("cotisations", "0008_auto_20160702_1614")]
operations = [
migrations.RemoveField(
model_name='cotisation',
name='user',
),
]
operations = [migrations.RemoveField(model_name="cotisation", name="user")]

View file

@ -28,18 +28,15 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0009_remove_cotisation_user'),
]
dependencies = [("cotisations", "0009_remove_cotisation_user")]
operations = [
migrations.RemoveField(
model_name='article',
name='duration',
),
migrations.RemoveField(model_name="article", name="duration"),
migrations.AddField(
model_name='article',
name='duration',
field=models.IntegerField(null=True, help_text='Durée exprimée en mois entiers', blank=True),
model_name="article",
name="duration",
field=models.IntegerField(
null=True, help_text="Durée exprimée en mois entiers", blank=True
),
),
]

View file

@ -28,14 +28,10 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0010_auto_20160702_1840'),
]
dependencies = [("cotisations", "0010_auto_20160702_1840")]
operations = [
migrations.AlterField(
model_name='cotisation',
name='date_start',
field=models.DateTimeField(),
),
model_name="cotisation", name="date_start", field=models.DateTimeField()
)
]

View file

@ -29,14 +29,14 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0011_auto_20160702_1911'),
]
dependencies = [("cotisations", "0011_auto_20160702_1911")]
operations = [
migrations.AlterField(
model_name='cotisation',
name='facture',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='cotisations.Facture'),
model_name="cotisation",
name="facture",
field=models.OneToOneField(
on_delete=django.db.models.deletion.PROTECT, to="cotisations.Facture"
),
)
]

View file

@ -29,32 +29,41 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0012_auto_20160704_0118'),
]
dependencies = [("cotisations", "0012_auto_20160704_0118")]
operations = [
migrations.CreateModel(
name='Vente',
name="Vente",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('prix', models.DecimalField(decimal_places=2, max_digits=5)),
('cotisation', models.BooleanField()),
('duration', models.IntegerField(null=True, blank=True, help_text='Durée exprimée en mois entiers')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255)),
("prix", models.DecimalField(decimal_places=2, max_digits=5)),
("cotisation", models.BooleanField()),
(
"duration",
models.IntegerField(
null=True,
blank=True,
help_text="Durée exprimée en mois entiers",
),
),
],
),
migrations.RemoveField(
model_name='facture',
name='name',
),
migrations.RemoveField(
model_name='facture',
name='prix',
),
migrations.RemoveField(model_name="facture", name="name"),
migrations.RemoveField(model_name="facture", name="prix"),
migrations.AddField(
model_name='vente',
name='facture',
field=models.ForeignKey(to='cotisations.Facture', on_delete=django.db.models.deletion.PROTECT),
model_name="vente",
name="facture",
field=models.ForeignKey(
to="cotisations.Facture", on_delete=django.db.models.deletion.PROTECT
),
),
]

View file

@ -28,18 +28,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0013_auto_20160711_2240'),
]
dependencies = [("cotisations", "0013_auto_20160711_2240")]
operations = [
migrations.RemoveField(
model_name='facture',
name='number',
),
migrations.RemoveField(model_name="facture", name="number"),
migrations.AddField(
model_name='vente',
name='number',
model_name="vente",
name="number",
field=models.IntegerField(default=1),
preserve_default=False,
),

View file

@ -29,29 +29,29 @@ import django.core.validators
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0014_auto_20160712_0245'),
]
dependencies = [("cotisations", "0014_auto_20160712_0245")]
operations = [
migrations.AddField(
model_name='facture',
name='control',
model_name="facture",
name="control",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='cotisation',
name='facture',
field=models.OneToOneField(to='cotisations.Facture'),
model_name="cotisation",
name="facture",
field=models.OneToOneField(to="cotisations.Facture"),
),
migrations.AlterField(
model_name='vente',
name='facture',
field=models.ForeignKey(to='cotisations.Facture'),
model_name="vente",
name="facture",
field=models.ForeignKey(to="cotisations.Facture"),
),
migrations.AlterField(
model_name='vente',
name='number',
field=models.IntegerField(validators=[django.core.validators.MinValueValidator(1)]),
model_name="vente",
name="number",
field=models.IntegerField(
validators=[django.core.validators.MinValueValidator(1)]
),
),
]

View file

@ -28,29 +28,20 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0015_auto_20160714_2142'),
]
dependencies = [("cotisations", "0015_auto_20160714_2142")]
operations = [
migrations.RenameField(
model_name='article',
old_name='cotisation',
new_name='iscotisation',
model_name="article", old_name="cotisation", new_name="iscotisation"
),
migrations.RenameField(
model_name='vente',
old_name='cotisation',
new_name='iscotisation',
),
migrations.RemoveField(
model_name='cotisation',
name='facture',
model_name="vente", old_name="cotisation", new_name="iscotisation"
),
migrations.RemoveField(model_name="cotisation", name="facture"),
migrations.AddField(
model_name='cotisation',
name='vente',
field=models.OneToOneField(to='cotisations.Vente', null=True),
model_name="cotisation",
name="vente",
field=models.OneToOneField(to="cotisations.Vente", null=True),
preserve_default=False,
),
]

View file

@ -8,19 +8,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0016_auto_20160715_0110'),
]
dependencies = [("cotisations", "0016_auto_20160715_0110")]
operations = [
migrations.AlterField(
model_name='article',
name='duration',
field=models.IntegerField(blank=True, help_text='Durée exprimée en mois entiers', null=True, validators=[django.core.validators.MinValueValidator(0)]),
model_name="article",
name="duration",
field=models.IntegerField(
blank=True,
help_text="Durée exprimée en mois entiers",
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
migrations.AlterField(
model_name='article',
name='name',
model_name="article",
name="name",
field=models.CharField(max_length=255, unique=True),
),
]

View file

@ -7,15 +7,17 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0017_auto_20170718_2329'),
]
dependencies = [("cotisations", "0017_auto_20170718_2329")]
operations = [
migrations.AddField(
model_name='paiement',
name='type_paiement',
field=models.CharField(choices=[('check', 'Chèque'), (None, 'Autre')], default=None, max_length=255),
preserve_default=False,
model_name="paiement",
name="type_paiement",
field=models.CharField(
choices=[("check", "Chèque"), (None, "Autre")],
default=None,
max_length=255,
),
preserve_default=False,
)
]

View file

@ -7,14 +7,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0018_paiement_type_paiement'),
]
dependencies = [("cotisations", "0018_paiement_type_paiement")]
operations = [
migrations.AlterField(
model_name='paiement',
name='type_paiement',
field=models.CharField(choices=[(0, 'Autre'), (1, 'Chèque')], default=0, max_length=255),
model_name="paiement",
name="type_paiement",
field=models.CharField(
choices=[(0, "Autre"), (1, "Chèque")], default=0, max_length=255
),
)
]

View file

@ -7,14 +7,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0019_auto_20170819_0055'),
]
dependencies = [("cotisations", "0019_auto_20170819_0055")]
operations = [
migrations.AlterField(
model_name='paiement',
name='type_paiement',
field=models.IntegerField(choices=[(0, 'Autre'), (1, 'Chèque')], default=0, max_length=255),
model_name="paiement",
name="type_paiement",
field=models.IntegerField(
choices=[(0, "Autre"), (1, "Chèque")], default=0, max_length=255
),
)
]

View file

@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0020_auto_20170819_0057'),
]
dependencies = [("cotisations", "0020_auto_20170819_0057")]
operations = [
migrations.AlterField(
model_name='paiement',
name='type_paiement',
field=models.IntegerField(choices=[(0, 'Autre'), (1, 'Chèque')], default=0),
),
model_name="paiement",
name="type_paiement",
field=models.IntegerField(choices=[(0, "Autre"), (1, "Chèque")], default=0),
)
]

View file

@ -7,14 +7,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0021_auto_20170819_0104'),
]
dependencies = [("cotisations", "0021_auto_20170819_0104")]
operations = [
migrations.AlterField(
model_name='paiement',
name='type_paiement',
field=models.IntegerField(choices=[(0, 'Autre'), (1, 'Chèque')], default=0, max_length=255),
model_name="paiement",
name="type_paiement",
field=models.IntegerField(
choices=[(0, "Autre"), (1, "Chèque")], default=0, max_length=255
),
)
]

View file

@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0022_auto_20170824_0128'),
]
dependencies = [("cotisations", "0022_auto_20170824_0128")]
operations = [
migrations.AlterField(
model_name='paiement',
name='type_paiement',
field=models.IntegerField(choices=[(0, 'Autre'), (1, 'Chèque')], default=0),
),
model_name="paiement",
name="type_paiement",
field=models.IntegerField(choices=[(0, "Autre"), (1, "Chèque")], default=0),
)
]

View file

@ -8,19 +8,24 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0023_auto_20170902_1303'),
]
dependencies = [("cotisations", "0023_auto_20170902_1303")]
operations = [
migrations.AlterField(
model_name='article',
name='duration',
field=models.PositiveIntegerField(blank=True, help_text='Durée exprimée en mois entiers', null=True, validators=[django.core.validators.MinValueValidator(0)]),
model_name="article",
name="duration",
field=models.PositiveIntegerField(
blank=True,
help_text="Durée exprimée en mois entiers",
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
migrations.AlterField(
model_name='vente',
name='duration',
field=models.PositiveIntegerField(blank=True, help_text='Durée exprimée en mois entiers', null=True),
model_name="vente",
name="duration",
field=models.PositiveIntegerField(
blank=True, help_text="Durée exprimée en mois entiers", null=True
),
),
]

View file

@ -7,14 +7,16 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0024_auto_20171015_2033'),
]
dependencies = [("cotisations", "0024_auto_20171015_2033")]
operations = [
migrations.AddField(
model_name='article',
name='type_user',
field=models.CharField(choices=[('Adherent', 'Adherent'), ('Club', 'Club'), ('All', 'All')], default='All', max_length=255),
model_name="article",
name="type_user",
field=models.CharField(
choices=[("Adherent", "Adherent"), ("Club", "Club"), ("All", "All")],
default="All",
max_length=255,
),
)
]

View file

@ -6,73 +6,94 @@ from django.db import migrations, models
def create_type(apps, schema_editor):
Cotisation = apps.get_model('cotisations', 'Cotisation')
Vente = apps.get_model('cotisations', 'Vente')
Article = apps.get_model('cotisations', 'Article')
Cotisation = apps.get_model("cotisations", "Cotisation")
Vente = apps.get_model("cotisations", "Vente")
Article = apps.get_model("cotisations", "Article")
db_alias = schema_editor.connection.alias
articles = Article.objects.using(db_alias).all()
ventes = Vente.objects.using(db_alias).all()
cotisations = Cotisation.objects.using(db_alias).all()
for article in articles:
if article.iscotisation:
article.type_cotisation='All'
article.type_cotisation = "All"
article.save(using=db_alias)
for vente in ventes:
if vente.iscotisation:
vente.type_cotisation='All'
vente.type_cotisation = "All"
vente.save(using=db_alias)
for cotisation in cotisations:
cotisation.type_cotisation='All'
cotisation.type_cotisation = "All"
cotisation.save(using=db_alias)
def delete_type(apps, schema_editor):
Vente = apps.get_model('cotisations', 'Vente')
Article = apps.get_model('cotisations', 'Article')
Vente = apps.get_model("cotisations", "Vente")
Article = apps.get_model("cotisations", "Article")
db_alias = schema_editor.connection.alias
articles = Article.objects.using(db_alias).all()
ventes = Vente.objects.using(db_alias).all()
for article in articles:
if article.type_cotisation:
article.iscotisation=True
article.iscotisation = True
else:
article.iscotisation=False
article.iscotisation = False
article.save(using=db_alias)
for vente in ventes:
if vente.iscotisation:
vente.iscotisation=True
vente.iscotisation = True
else:
vente.iscotisation=False
vente.iscotisation = False
vente.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0025_article_type_user'),
]
dependencies = [("cotisations", "0025_article_type_user")]
operations = [
migrations.AddField(
model_name='article',
name='type_cotisation',
field=models.CharField(blank=True, choices=[('Connexion', 'Connexion'), ('Adhesion', 'Adhesion'), ('All', 'All')], default=None, max_length=255, null=True),
model_name="article",
name="type_cotisation",
field=models.CharField(
blank=True,
choices=[
("Connexion", "Connexion"),
("Adhesion", "Adhesion"),
("All", "All"),
],
default=None,
max_length=255,
null=True,
),
),
migrations.AddField(
model_name='cotisation',
name='type_cotisation',
field=models.CharField(choices=[('Connexion', 'Connexion'), ('Adhesion', 'Adhesion'), ('All', 'All')], max_length=255, default='All'),
model_name="cotisation",
name="type_cotisation",
field=models.CharField(
choices=[
("Connexion", "Connexion"),
("Adhesion", "Adhesion"),
("All", "All"),
],
max_length=255,
default="All",
),
),
migrations.AddField(
model_name='vente',
name='type_cotisation',
field=models.CharField(blank=True, choices=[('Connexion', 'Connexion'), ('Adhesion', 'Adhesion'), ('All', 'All')], max_length=255, null=True),
model_name="vente",
name="type_cotisation",
field=models.CharField(
blank=True,
choices=[
("Connexion", "Connexion"),
("Adhesion", "Adhesion"),
("All", "All"),
],
max_length=255,
null=True,
),
),
migrations.RunPython(create_type, delete_type),
migrations.RemoveField(
model_name='article',
name='iscotisation',
),
migrations.RemoveField(
model_name='vente',
name='iscotisation',
),
migrations.RemoveField(model_name="article", name="iscotisation"),
migrations.RemoveField(model_name="vente", name="iscotisation"),
]

View file

@ -7,14 +7,10 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0026_auto_20171028_0126'),
]
dependencies = [("cotisations", "0026_auto_20171028_0126")]
operations = [
migrations.AlterField(
model_name='article',
name='name',
field=models.CharField(max_length=255),
),
model_name="article", name="name", field=models.CharField(max_length=255)
)
]

View file

@ -7,33 +7,56 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0027_auto_20171029_1156'),
]
dependencies = [("cotisations", "0027_auto_20171029_1156")]
operations = [
migrations.AlterModelOptions(
name='article',
options={'permissions': (('view_article', 'Peut voir un objet article'),)},
name="article",
options={"permissions": (("view_article", "Peut voir un objet article"),)},
),
migrations.AlterModelOptions(
name='banque',
options={'permissions': (('view_banque', 'Peut voir un objet banque'),)},
name="banque",
options={"permissions": (("view_banque", "Peut voir un objet banque"),)},
),
migrations.AlterModelOptions(
name='cotisation',
options={'permissions': (('view_cotisation', 'Peut voir un objet cotisation'), ('change_all_cotisation', 'Superdroit, peut modifier toutes les cotisations'))},
name="cotisation",
options={
"permissions": (
("view_cotisation", "Peut voir un objet cotisation"),
(
"change_all_cotisation",
"Superdroit, peut modifier toutes les cotisations",
),
)
},
),
migrations.AlterModelOptions(
name='facture',
options={'permissions': (('change_facture_control', "Peut changer l'etat de controle"), ('change_facture_pdf', 'Peut éditer une facture pdf'), ('view_facture', 'Peut voir un objet facture'), ('change_all_facture', 'Superdroit, peut modifier toutes les factures'))},
name="facture",
options={
"permissions": (
("change_facture_control", "Peut changer l'etat de controle"),
("change_facture_pdf", "Peut éditer une facture pdf"),
("view_facture", "Peut voir un objet facture"),
(
"change_all_facture",
"Superdroit, peut modifier toutes les factures",
),
)
},
),
migrations.AlterModelOptions(
name='paiement',
options={'permissions': (('view_paiement', 'Peut voir un objet paiement'),)},
name="paiement",
options={
"permissions": (("view_paiement", "Peut voir un objet paiement"),)
},
),
migrations.AlterModelOptions(
name='vente',
options={'permissions': (('view_vente', 'Peut voir un objet vente'), ('change_all_vente', 'Superdroit, peut modifier toutes les ventes'))},
name="vente",
options={
"permissions": (
("view_vente", "Peut voir un objet vente"),
("change_all_vente", "Superdroit, peut modifier toutes les ventes"),
)
},
),
]

View file

@ -9,143 +9,242 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0028_auto_20171231_0007'),
]
dependencies = [("cotisations", "0028_auto_20171231_0007")]
operations = [
migrations.AlterModelOptions(
name='article',
options={'permissions': (('view_article', "Can see an article's details"),), 'verbose_name': 'Article', 'verbose_name_plural': 'Articles'},
name="article",
options={
"permissions": (("view_article", "Can see an article's details"),),
"verbose_name": "Article",
"verbose_name_plural": "Articles",
},
),
migrations.AlterModelOptions(
name='banque',
options={'permissions': (('view_banque', "Can see a bank's details"),), 'verbose_name': 'Bank', 'verbose_name_plural': 'Banks'},
name="banque",
options={
"permissions": (("view_banque", "Can see a bank's details"),),
"verbose_name": "Bank",
"verbose_name_plural": "Banks",
},
),
migrations.AlterModelOptions(
name='cotisation',
options={'permissions': (('view_cotisation', "Can see a cotisation's details"), ('change_all_cotisation', 'Can edit the previous cotisations'))},
name="cotisation",
options={
"permissions": (
("view_cotisation", "Can see a cotisation's details"),
("change_all_cotisation", "Can edit the previous cotisations"),
)
},
),
migrations.AlterModelOptions(
name='facture',
options={'permissions': (('change_facture_control', 'Can change the "controlled" state'), ('change_facture_pdf', 'Can create a custom PDF invoice'), ('view_facture', "Can see an invoice's details"), ('change_all_facture', 'Can edit all the previous invoices')), 'verbose_name': 'Invoice', 'verbose_name_plural': 'Invoices'},
name="facture",
options={
"permissions": (
("change_facture_control", 'Can change the "controlled" state'),
("change_facture_pdf", "Can create a custom PDF invoice"),
("view_facture", "Can see an invoice's details"),
("change_all_facture", "Can edit all the previous invoices"),
),
"verbose_name": "Invoice",
"verbose_name_plural": "Invoices",
},
),
migrations.AlterModelOptions(
name='paiement',
options={'permissions': (('view_paiement', "Can see a payement's details"),), 'verbose_name': 'Payment method', 'verbose_name_plural': 'Payment methods'},
name="paiement",
options={
"permissions": (("view_paiement", "Can see a payement's details"),),
"verbose_name": "Payment method",
"verbose_name_plural": "Payment methods",
},
),
migrations.AlterModelOptions(
name='vente',
options={'permissions': (('view_vente', "Can see a purchase's details"), ('change_all_vente', 'Can edit all the previous purchases')), 'verbose_name': 'Purchase', 'verbose_name_plural': 'Purchases'},
name="vente",
options={
"permissions": (
("view_vente", "Can see a purchase's details"),
("change_all_vente", "Can edit all the previous purchases"),
),
"verbose_name": "Purchase",
"verbose_name_plural": "Purchases",
},
),
migrations.AlterField(
model_name='article',
name='duration',
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='Duration (in whole month)'),
model_name="article",
name="duration",
field=models.PositiveIntegerField(
blank=True,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
verbose_name="Duration (in whole month)",
),
),
migrations.AlterField(
model_name='article',
name='name',
field=models.CharField(max_length=255, verbose_name='Designation'),
model_name="article",
name="name",
field=models.CharField(max_length=255, verbose_name="Designation"),
),
migrations.AlterField(
model_name='article',
name='prix',
field=models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Unitary price'),
model_name="article",
name="prix",
field=models.DecimalField(
decimal_places=2, max_digits=5, verbose_name="Unitary price"
),
),
migrations.AlterField(
model_name='article',
name='type_cotisation',
field=models.CharField(blank=True, choices=[('Connexion', 'Connexion'), ('Adhesion', 'Membership'), ('All', 'Both of them')], default=None, max_length=255, null=True, verbose_name='Type of cotisation'),
model_name="article",
name="type_cotisation",
field=models.CharField(
blank=True,
choices=[
("Connexion", "Connexion"),
("Adhesion", "Membership"),
("All", "Both of them"),
],
default=None,
max_length=255,
null=True,
verbose_name="Type of cotisation",
),
),
migrations.AlterField(
model_name='article',
name='type_user',
field=models.CharField(choices=[('Adherent', 'Member'), ('Club', 'Club'), ('All', 'Both of them')], default='All', max_length=255, verbose_name='Type of users concerned'),
model_name="article",
name="type_user",
field=models.CharField(
choices=[
("Adherent", "Member"),
("Club", "Club"),
("All", "Both of them"),
],
default="All",
max_length=255,
verbose_name="Type of users concerned",
),
),
migrations.AlterField(
model_name='banque',
name='name',
field=models.CharField(max_length=255, verbose_name='Name'),
model_name="banque",
name="name",
field=models.CharField(max_length=255, verbose_name="Name"),
),
migrations.AlterField(
model_name='cotisation',
name='date_end',
field=models.DateTimeField(verbose_name='Ending date'),
model_name="cotisation",
name="date_end",
field=models.DateTimeField(verbose_name="Ending date"),
),
migrations.AlterField(
model_name='cotisation',
name='date_start',
field=models.DateTimeField(verbose_name='Starting date'),
model_name="cotisation",
name="date_start",
field=models.DateTimeField(verbose_name="Starting date"),
),
migrations.AlterField(
model_name='cotisation',
name='type_cotisation',
field=models.CharField(choices=[('Connexion', 'Connexion'), ('Adhesion', 'Membership'), ('All', 'Both of them')], default='All', max_length=255, verbose_name='Type of cotisation'),
model_name="cotisation",
name="type_cotisation",
field=models.CharField(
choices=[
("Connexion", "Connexion"),
("Adhesion", "Membership"),
("All", "Both of them"),
],
default="All",
max_length=255,
verbose_name="Type of cotisation",
),
),
migrations.AlterField(
model_name='cotisation',
name='vente',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='cotisations.Vente', verbose_name='Purchase'),
model_name="cotisation",
name="vente",
field=models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="cotisations.Vente",
verbose_name="Purchase",
),
),
migrations.AlterField(
model_name='facture',
name='cheque',
field=models.CharField(blank=True, max_length=255, verbose_name='Cheque number'),
model_name="facture",
name="cheque",
field=models.CharField(
blank=True, max_length=255, verbose_name="Cheque number"
),
),
migrations.AlterField(
model_name='facture',
name='control',
field=models.BooleanField(default=False, verbose_name='Controlled'),
model_name="facture",
name="control",
field=models.BooleanField(default=False, verbose_name="Controlled"),
),
migrations.AlterField(
model_name='facture',
name='date',
field=models.DateTimeField(auto_now_add=True, verbose_name='Date'),
model_name="facture",
name="date",
field=models.DateTimeField(auto_now_add=True, verbose_name="Date"),
),
migrations.AlterField(
model_name='facture',
name='valid',
field=models.BooleanField(default=True, verbose_name='Validated'),
model_name="facture",
name="valid",
field=models.BooleanField(default=True, verbose_name="Validated"),
),
migrations.AlterField(
model_name='paiement',
name='moyen',
field=models.CharField(max_length=255, verbose_name='Method'),
model_name="paiement",
name="moyen",
field=models.CharField(max_length=255, verbose_name="Method"),
),
migrations.AlterField(
model_name='paiement',
name='type_paiement',
field=models.IntegerField(choices=[(0, 'Standard'), (1, 'Cheque')], default=0, verbose_name='Payment type'),
model_name="paiement",
name="type_paiement",
field=models.IntegerField(
choices=[(0, "Standard"), (1, "Cheque")],
default=0,
verbose_name="Payment type",
),
),
migrations.AlterField(
model_name='vente',
name='duration',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Duration (in whole month)'),
model_name="vente",
name="duration",
field=models.PositiveIntegerField(
blank=True, null=True, verbose_name="Duration (in whole month)"
),
),
migrations.AlterField(
model_name='vente',
name='facture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cotisations.Facture', verbose_name='Invoice'),
model_name="vente",
name="facture",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="cotisations.Facture",
verbose_name="Invoice",
),
),
migrations.AlterField(
model_name='vente',
name='name',
field=models.CharField(max_length=255, verbose_name='Article'),
model_name="vente",
name="name",
field=models.CharField(max_length=255, verbose_name="Article"),
),
migrations.AlterField(
model_name='vente',
name='number',
field=models.IntegerField(validators=[django.core.validators.MinValueValidator(1)], verbose_name='Amount'),
model_name="vente",
name="number",
field=models.IntegerField(
validators=[django.core.validators.MinValueValidator(1)],
verbose_name="Amount",
),
),
migrations.AlterField(
model_name='vente',
name='prix',
field=models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Price'),
model_name="vente",
name="prix",
field=models.DecimalField(
decimal_places=2, max_digits=5, verbose_name="Price"
),
),
migrations.AlterField(
model_name='vente',
name='type_cotisation',
field=models.CharField(blank=True, choices=[('Connexion', 'Connexion'), ('Adhesion', 'Membership'), ('All', 'Both of them')], max_length=255, null=True, verbose_name='Type of cotisation'),
model_name="vente",
name="type_cotisation",
field=models.CharField(
blank=True,
choices=[
("Connexion", "Connexion"),
("Adhesion", "Membership"),
("All", "Both of them"),
],
max_length=255,
null=True,
verbose_name="Type of cotisation",
),
),
]

View file

@ -9,8 +9,8 @@ import django.db.models.deletion
def add_cheque(apps, schema_editor):
ChequePayment = apps.get_model('cotisations', 'ChequePayment')
Payment = apps.get_model('cotisations', 'Paiement')
ChequePayment = apps.get_model("cotisations", "ChequePayment")
Payment = apps.get_model("cotisations", "Paiement")
for p in Payment.objects.filter(type_paiement=1):
cheque = ChequePayment()
cheque.payment = p
@ -18,14 +18,12 @@ def add_cheque(apps, schema_editor):
def add_comnpay(apps, schema_editor):
ComnpayPayment = apps.get_model('cotisations', 'ComnpayPayment')
Payment = apps.get_model('cotisations', 'Paiement')
AssoOption = apps.get_model('preferences', 'AssoOption')
ComnpayPayment = apps.get_model("cotisations", "ComnpayPayment")
Payment = apps.get_model("cotisations", "Paiement")
AssoOption = apps.get_model("preferences", "AssoOption")
options, _created = AssoOption.objects.get_or_create()
try:
payment = Payment.objects.get(
moyen='Rechargement en ligne'
)
payment = Payment.objects.get(moyen="Rechargement en ligne")
except Payment.DoesNotExist:
return
comnpay = ComnpayPayment()
@ -38,11 +36,11 @@ def add_comnpay(apps, schema_editor):
def add_solde(apps, schema_editor):
OptionalUser = apps.get_model('preferences', 'OptionalUser')
OptionalUser = apps.get_model("preferences", "OptionalUser")
options, _created = OptionalUser.objects.get_or_create()
Payment = apps.get_model('cotisations', 'Paiement')
BalancePayment = apps.get_model('cotisations', 'BalancePayment')
Payment = apps.get_model("cotisations", "Paiement")
BalancePayment = apps.get_model("cotisations", "BalancePayment")
try:
solde = Payment.objects.get(moyen="solde")
@ -60,73 +58,191 @@ def add_solde(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [
('preferences', '0044_remove_payment_pass'),
('cotisations', '0029_auto_20180414_2056'),
("preferences", "0044_remove_payment_pass"),
("cotisations", "0029_auto_20180414_2056"),
]
operations = [
migrations.AlterModelOptions(
name='paiement',
options={'permissions': (('view_paiement', "Can see a payement's details"), ('use_every_payment', 'Can use every payement')), 'verbose_name': 'Payment method', 'verbose_name_plural': 'Payment methods'},
name="paiement",
options={
"permissions": (
("view_paiement", "Can see a payement's details"),
("use_every_payment", "Can use every payement"),
),
"verbose_name": "Payment method",
"verbose_name_plural": "Payment methods",
},
),
migrations.AlterModelOptions(
name='article',
options={'permissions': (('view_article', "Can see an article's details"), ('buy_every_article', 'Can buy every_article')), 'verbose_name': 'Article', 'verbose_name_plural': 'Articles'},
name="article",
options={
"permissions": (
("view_article", "Can see an article's details"),
("buy_every_article", "Can buy every_article"),
),
"verbose_name": "Article",
"verbose_name_plural": "Articles",
},
),
migrations.AddField(
model_name='paiement',
name='available_for_everyone',
field=models.BooleanField(default=False, verbose_name='Is available for every user'),
model_name="paiement",
name="available_for_everyone",
field=models.BooleanField(
default=False, verbose_name="Is available for every user"
),
),
migrations.AddField(
model_name='paiement',
name='is_balance',
field=models.BooleanField(default=False, editable=False, help_text='There should be only one balance payment method.', verbose_name='Is user balance', validators=[cotisations.models.check_no_balance]),
model_name="paiement",
name="is_balance",
field=models.BooleanField(
default=False,
editable=False,
help_text="There should be only one balance payment method.",
verbose_name="Is user balance",
validators=[cotisations.models.check_no_balance],
),
),
migrations.AddField(
model_name='article',
name='available_for_everyone',
field=models.BooleanField(default=False, verbose_name='Is available for every user'),
model_name="article",
name="available_for_everyone",
field=models.BooleanField(
default=False, verbose_name="Is available for every user"
),
),
migrations.CreateModel(
name='ChequePayment',
name="ChequePayment",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"payment",
models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method",
to="cotisations.Paiement",
),
),
],
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
options={'verbose_name': 'Cheque'},
options={"verbose_name": "Cheque"},
),
migrations.CreateModel(
name='ComnpayPayment',
name="ComnpayPayment",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('payment_credential', models.CharField(blank=True, default='', max_length=255, verbose_name='ComNpay VAD Number')),
('payment_pass', re2o.aes_field.AESEncryptedField(blank=True, max_length=255, null=True, verbose_name='ComNpay Secret Key')),
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
('minimum_payment', models.DecimalField(decimal_places=2, default=1, help_text='The minimal amount of money you have to use when paying with ComNpay', max_digits=5, verbose_name='Minimum payment')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"payment_credential",
models.CharField(
blank=True,
default="",
max_length=255,
verbose_name="ComNpay VAD Number",
),
),
(
"payment_pass",
re2o.aes_field.AESEncryptedField(
blank=True,
max_length=255,
null=True,
verbose_name="ComNpay Secret Key",
),
),
(
"payment",
models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method",
to="cotisations.Paiement",
),
),
(
"minimum_payment",
models.DecimalField(
decimal_places=2,
default=1,
help_text="The minimal amount of money you have to use when paying with ComNpay",
max_digits=5,
verbose_name="Minimum payment",
),
),
],
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
options={'verbose_name': 'ComNpay'},
options={"verbose_name": "ComNpay"},
),
migrations.CreateModel(
name='BalancePayment',
name="BalancePayment",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('minimum_balance', models.DecimalField(decimal_places=2, default=0, help_text='The minimal amount of money allowed for the balance at the end of a payment. You can specify negative amount.', max_digits=5, verbose_name='Minimum balance')),
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
('maximum_balance', models.DecimalField(decimal_places=2, default=50, help_text='The maximal amount of money allowed for the balance.', max_digits=5, verbose_name='Maximum balance', null=True, blank=True)),
('credit_balance_allowed', models.BooleanField(default=False, verbose_name='Allow user to credit their balance')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"minimum_balance",
models.DecimalField(
decimal_places=2,
default=0,
help_text="The minimal amount of money allowed for the balance at the end of a payment. You can specify negative amount.",
max_digits=5,
verbose_name="Minimum balance",
),
),
(
"payment",
models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method",
to="cotisations.Paiement",
),
),
(
"maximum_balance",
models.DecimalField(
decimal_places=2,
default=50,
help_text="The maximal amount of money allowed for the balance.",
max_digits=5,
verbose_name="Maximum balance",
null=True,
blank=True,
),
),
(
"credit_balance_allowed",
models.BooleanField(
default=False, verbose_name="Allow user to credit their balance"
),
),
],
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
options={'verbose_name': 'User Balance'},
options={"verbose_name": "User Balance"},
),
migrations.RunPython(add_comnpay),
migrations.RunPython(add_cheque),
migrations.RunPython(add_solde),
migrations.RemoveField(
model_name='paiement',
name='type_paiement',
),
migrations.RemoveField(model_name="paiement", name="type_paiement"),
]

View file

@ -7,14 +7,15 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0030_custom_payment'),
]
dependencies = [("cotisations", "0030_custom_payment")]
operations = [
migrations.AddField(
model_name='comnpaypayment',
name='production',
field=models.BooleanField(default=True, verbose_name='Production mode enabled (production url, instead of homologation)'),
model_name="comnpaypayment",
name="production",
field=models.BooleanField(
default=True,
verbose_name="Production mode enabled (production url, instead of homologation)",
),
)
]

View file

@ -10,8 +10,8 @@ import re2o.mixins
def reattribute_ids(apps, schema_editor):
Facture = apps.get_model('cotisations', 'Facture')
BaseInvoice = apps.get_model('cotisations', 'BaseInvoice')
Facture = apps.get_model("cotisations", "Facture")
BaseInvoice = apps.get_model("cotisations", "BaseInvoice")
for f in Facture.objects.all():
base = BaseInvoice.objects.create(id=f.pk)
@ -22,21 +22,23 @@ def reattribute_ids(apps, schema_editor):
def update_rights(apps, schema_editor):
Permission = apps.get_model('auth', 'Permission')
Permission = apps.get_model("auth", "Permission")
# creates needed permissions
app = apps.get_app_config('cotisations')
app = apps.get_app_config("cotisations")
app.models_module = True
create_permissions(app)
app.models_module = False
ContentType = apps.get_model("contenttypes", "ContentType")
content_type = ContentType.objects.get_for_model(Permission)
former, created = Permission.objects.get_or_create(codename='change_facture_pdf', content_type=content_type)
new_1 = Permission.objects.get(codename='add_custominvoice')
new_2 = Permission.objects.get(codename='change_custominvoice')
new_3 = Permission.objects.get(codename='view_custominvoice')
new_4 = Permission.objects.get(codename='delete_custominvoice')
former, created = Permission.objects.get_or_create(
codename="change_facture_pdf", content_type=content_type
)
new_1 = Permission.objects.get(codename="add_custominvoice")
new_2 = Permission.objects.get(codename="change_custominvoice")
new_3 = Permission.objects.get(codename="view_custominvoice")
new_4 = Permission.objects.get(codename="delete_custominvoice")
for group in former.group_set.all():
group.permissions.remove(former)
group.permissions.add(new_1)
@ -48,59 +50,105 @@ def update_rights(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0031_comnpaypayment_production'),
]
dependencies = [("cotisations", "0031_comnpaypayment_production")]
operations = [
migrations.CreateModel(
name='BaseInvoice',
name="BaseInvoice",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now_add=True, verbose_name='Date')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("date", models.DateTimeField(auto_now_add=True, verbose_name="Date")),
],
bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, re2o.field_permissions.FieldPermissionModelMixin, models.Model),
bases=(
re2o.mixins.RevMixin,
re2o.mixins.AclMixin,
re2o.field_permissions.FieldPermissionModelMixin,
models.Model,
),
),
migrations.CreateModel(
name='CustomInvoice',
name="CustomInvoice",
fields=[
('baseinvoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.BaseInvoice')),
('recipient', models.CharField(max_length=255, verbose_name='Recipient')),
('payment', models.CharField(max_length=255, verbose_name='Payment type')),
('address', models.CharField(max_length=255, verbose_name='Address')),
('paid', models.BooleanField(verbose_name='Paid')),
(
"baseinvoice_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="cotisations.BaseInvoice",
),
),
(
"recipient",
models.CharField(max_length=255, verbose_name="Recipient"),
),
(
"payment",
models.CharField(max_length=255, verbose_name="Payment type"),
),
("address", models.CharField(max_length=255, verbose_name="Address")),
("paid", models.BooleanField(verbose_name="Paid")),
],
bases=('cotisations.baseinvoice',),
options={'permissions': (('view_custominvoice', 'Can view a custom invoice'),)},
bases=("cotisations.baseinvoice",),
options={
"permissions": (("view_custominvoice", "Can view a custom invoice"),)
},
),
migrations.AddField(
model_name='facture',
name='baseinvoice_ptr',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='cotisations.BaseInvoice', null=True),
model_name="facture",
name="baseinvoice_ptr",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
to="cotisations.BaseInvoice",
null=True,
),
preserve_default=False,
),
migrations.RunPython(reattribute_ids),
migrations.AlterField(
model_name='vente',
name='facture',
field=models.ForeignKey(on_delete=models.CASCADE, verbose_name='Invoice', to='cotisations.BaseInvoice')
model_name="vente",
name="facture",
field=models.ForeignKey(
on_delete=models.CASCADE,
verbose_name="Invoice",
to="cotisations.BaseInvoice",
),
migrations.RemoveField(
model_name='facture',
name='id',
),
migrations.RemoveField(
model_name='facture',
name='date',
),
migrations.RemoveField(model_name="facture", name="id"),
migrations.RemoveField(model_name="facture", name="date"),
migrations.AlterField(
model_name='facture',
name='baseinvoice_ptr',
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.BaseInvoice'),
model_name="facture",
name="baseinvoice_ptr",
field=models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="cotisations.BaseInvoice",
),
),
migrations.RunPython(update_rights),
migrations.AlterModelOptions(
name='facture',
options={'permissions': (('change_facture_control', 'Can change the "controlled" state'), ('view_facture', "Can see an invoice's details"), ('change_all_facture', 'Can edit all the previous invoices')), 'verbose_name': 'Invoice', 'verbose_name_plural': 'Invoices'},
name="facture",
options={
"permissions": (
("change_facture_control", 'Can change the "controlled" state'),
("view_facture", "Can see an invoice's details"),
("change_all_facture", "Can edit all the previous invoices"),
),
"verbose_name": "Invoice",
"verbose_name_plural": "Invoices",
},
),
]

View file

@ -11,171 +11,294 @@ import re2o.aes_field
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0032_custom_invoice'),
]
dependencies = [("cotisations", "0032_custom_invoice")]
operations = [
migrations.AlterModelOptions(
name='article',
options={'permissions': (('view_article', 'Can view an article object'), ('buy_every_article', 'Can buy every article')), 'verbose_name': 'article', 'verbose_name_plural': 'articles'},
name="article",
options={
"permissions": (
("view_article", "Can view an article object"),
("buy_every_article", "Can buy every article"),
),
"verbose_name": "article",
"verbose_name_plural": "articles",
},
),
migrations.AlterModelOptions(
name='balancepayment',
options={'verbose_name': 'user balance'},
name="balancepayment", options={"verbose_name": "user balance"}
),
migrations.AlterModelOptions(
name='banque',
options={'permissions': (('view_banque', 'Can view a bank object'),), 'verbose_name': 'bank', 'verbose_name_plural': 'banks'},
name="banque",
options={
"permissions": (("view_banque", "Can view a bank object"),),
"verbose_name": "bank",
"verbose_name_plural": "banks",
},
),
migrations.AlterModelOptions(
name='cotisation',
options={'permissions': (('view_cotisation', 'Can view a subscription object'), ('change_all_cotisation', 'Can edit the previous subscriptions')), 'verbose_name': 'subscription', 'verbose_name_plural': 'subscriptions'},
name="cotisation",
options={
"permissions": (
("view_cotisation", "Can view a subscription object"),
("change_all_cotisation", "Can edit the previous subscriptions"),
),
"verbose_name": "subscription",
"verbose_name_plural": "subscriptions",
},
),
migrations.AlterModelOptions(
name='custominvoice',
options={'permissions': (('view_custominvoice', 'Can view a custom invoice object'),)},
name="custominvoice",
options={
"permissions": (
("view_custominvoice", "Can view a custom invoice object"),
)
},
),
migrations.AlterModelOptions(
name='facture',
options={'permissions': (('change_facture_control', 'Can edit the "controlled" state'), ('view_facture', 'Can view an invoice object'), ('change_all_facture', 'Can edit all the previous invoices')), 'verbose_name': 'invoice', 'verbose_name_plural': 'invoices'},
name="facture",
options={
"permissions": (
("change_facture_control", 'Can edit the "controlled" state'),
("view_facture", "Can view an invoice object"),
("change_all_facture", "Can edit all the previous invoices"),
),
"verbose_name": "invoice",
"verbose_name_plural": "invoices",
},
),
migrations.AlterModelOptions(
name='paiement',
options={'permissions': (('view_paiement', 'Can view a payment method object'), ('use_every_payment', 'Can use every payment method')), 'verbose_name': 'payment method', 'verbose_name_plural': 'payment methods'},
name="paiement",
options={
"permissions": (
("view_paiement", "Can view a payment method object"),
("use_every_payment", "Can use every payment method"),
),
"verbose_name": "payment method",
"verbose_name_plural": "payment methods",
},
),
migrations.AlterModelOptions(
name='vente',
options={'permissions': (('view_vente', 'Can view a purchase object'), ('change_all_vente', 'Can edit all the previous purchases')), 'verbose_name': 'purchase', 'verbose_name_plural': 'purchases'},
name="vente",
options={
"permissions": (
("view_vente", "Can view a purchase object"),
("change_all_vente", "Can edit all the previous purchases"),
),
"verbose_name": "purchase",
"verbose_name_plural": "purchases",
},
),
migrations.AlterField(
model_name='article',
name='available_for_everyone',
field=models.BooleanField(default=False, verbose_name='is available for every user'),
model_name="article",
name="available_for_everyone",
field=models.BooleanField(
default=False, verbose_name="is available for every user"
),
),
migrations.AlterField(
model_name='article',
name='duration',
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration (in months)'),
model_name="article",
name="duration",
field=models.PositiveIntegerField(
blank=True,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
verbose_name="duration (in months)",
),
),
migrations.AlterField(
model_name='article',
name='name',
field=models.CharField(max_length=255, verbose_name='designation'),
model_name="article",
name="name",
field=models.CharField(max_length=255, verbose_name="designation"),
),
migrations.AlterField(
model_name='article',
name='prix',
field=models.DecimalField(decimal_places=2, max_digits=5, verbose_name='unit price'),
model_name="article",
name="prix",
field=models.DecimalField(
decimal_places=2, max_digits=5, verbose_name="unit price"
),
),
migrations.AlterField(
model_name='article',
name='type_cotisation',
field=models.CharField(blank=True, choices=[('Connexion', 'Connection'), ('Adhesion', 'Membership'), ('All', 'Both of them')], default=None, max_length=255, null=True, verbose_name='subscription type'),
model_name="article",
name="type_cotisation",
field=models.CharField(
blank=True,
choices=[
("Connexion", "Connection"),
("Adhesion", "Membership"),
("All", "Both of them"),
],
default=None,
max_length=255,
null=True,
verbose_name="subscription type",
),
),
migrations.AlterField(
model_name='article',
name='type_user',
field=models.CharField(choices=[('Adherent', 'Member'), ('Club', 'Club'), ('All', 'Both of them')], default='All', max_length=255, verbose_name='type of users concerned'),
model_name="article",
name="type_user",
field=models.CharField(
choices=[
("Adherent", "Member"),
("Club", "Club"),
("All", "Both of them"),
],
default="All",
max_length=255,
verbose_name="type of users concerned",
),
),
migrations.AlterField(
model_name='banque',
name='name',
field=models.CharField(max_length=255),
model_name="banque", name="name", field=models.CharField(max_length=255)
),
migrations.AlterField(
model_name='comnpaypayment',
name='payment_credential',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='ComNpay VAT Number'),
model_name="comnpaypayment",
name="payment_credential",
field=models.CharField(
blank=True,
default="",
max_length=255,
verbose_name="ComNpay VAT Number",
),
),
migrations.AlterField(
model_name='comnpaypayment',
name='payment_pass',
field=re2o.aes_field.AESEncryptedField(blank=True, max_length=255, null=True, verbose_name='ComNpay secret key'),
model_name="comnpaypayment",
name="payment_pass",
field=re2o.aes_field.AESEncryptedField(
blank=True, max_length=255, null=True, verbose_name="ComNpay secret key"
),
),
migrations.AlterField(
model_name='comnpaypayment',
name='production',
field=models.BooleanField(default=True, verbose_name='Production mode enabled (production URL, instead of homologation)'),
model_name="comnpaypayment",
name="production",
field=models.BooleanField(
default=True,
verbose_name="Production mode enabled (production URL, instead of homologation)",
),
),
migrations.AlterField(
model_name='cotisation',
name='date_end',
field=models.DateTimeField(verbose_name='end date'),
model_name="cotisation",
name="date_end",
field=models.DateTimeField(verbose_name="end date"),
),
migrations.AlterField(
model_name='cotisation',
name='date_start',
field=models.DateTimeField(verbose_name='start date'),
model_name="cotisation",
name="date_start",
field=models.DateTimeField(verbose_name="start date"),
),
migrations.AlterField(
model_name='cotisation',
name='type_cotisation',
field=models.CharField(choices=[('Connexion', 'Connection'), ('Adhesion', 'Membership'), ('All', 'Both of them')], default='All', max_length=255, verbose_name='subscription type'),
model_name="cotisation",
name="type_cotisation",
field=models.CharField(
choices=[
("Connexion", "Connection"),
("Adhesion", "Membership"),
("All", "Both of them"),
],
default="All",
max_length=255,
verbose_name="subscription type",
),
),
migrations.AlterField(
model_name='cotisation',
name='vente',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='cotisations.Vente', verbose_name='purchase'),
model_name="cotisation",
name="vente",
field=models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="cotisations.Vente",
verbose_name="purchase",
),
),
migrations.AlterField(
model_name='facture',
name='cheque',
field=models.CharField(blank=True, max_length=255, verbose_name='cheque number'),
model_name="facture",
name="cheque",
field=models.CharField(
blank=True, max_length=255, verbose_name="cheque number"
),
),
migrations.AlterField(
model_name='facture',
name='control',
field=models.BooleanField(default=False, verbose_name='controlled'),
model_name="facture",
name="control",
field=models.BooleanField(default=False, verbose_name="controlled"),
),
migrations.AlterField(
model_name='facture',
name='valid',
field=models.BooleanField(default=True, verbose_name='validated'),
model_name="facture",
name="valid",
field=models.BooleanField(default=True, verbose_name="validated"),
),
migrations.AlterField(
model_name='paiement',
name='available_for_everyone',
field=models.BooleanField(default=False, verbose_name='is available for every user'),
model_name="paiement",
name="available_for_everyone",
field=models.BooleanField(
default=False, verbose_name="is available for every user"
),
),
migrations.AlterField(
model_name='paiement',
name='is_balance',
field=models.BooleanField(default=False, editable=False, help_text='There should be only one balance payment method.', validators=[cotisations.validators.check_no_balance], verbose_name='is user balance'),
model_name="paiement",
name="is_balance",
field=models.BooleanField(
default=False,
editable=False,
help_text="There should be only one balance payment method.",
validators=[cotisations.validators.check_no_balance],
verbose_name="is user balance",
),
),
migrations.AlterField(
model_name='paiement',
name='moyen',
field=models.CharField(max_length=255, verbose_name='method'),
model_name="paiement",
name="moyen",
field=models.CharField(max_length=255, verbose_name="method"),
),
migrations.AlterField(
model_name='vente',
name='duration',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='duration (in months)'),
model_name="vente",
name="duration",
field=models.PositiveIntegerField(
blank=True, null=True, verbose_name="duration (in months)"
),
),
migrations.AlterField(
model_name='vente',
name='facture',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cotisations.BaseInvoice', verbose_name='invoice'),
model_name="vente",
name="facture",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="cotisations.BaseInvoice",
verbose_name="invoice",
),
),
migrations.AlterField(
model_name='vente',
name='name',
field=models.CharField(max_length=255, verbose_name='article'),
model_name="vente",
name="name",
field=models.CharField(max_length=255, verbose_name="article"),
),
migrations.AlterField(
model_name='vente',
name='number',
field=models.IntegerField(validators=[django.core.validators.MinValueValidator(1)], verbose_name='amount'),
model_name="vente",
name="number",
field=models.IntegerField(
validators=[django.core.validators.MinValueValidator(1)],
verbose_name="amount",
),
),
migrations.AlterField(
model_name='vente',
name='prix',
field=models.DecimalField(decimal_places=2, max_digits=5, verbose_name='price'),
model_name="vente",
name="prix",
field=models.DecimalField(
decimal_places=2, max_digits=5, verbose_name="price"
),
),
migrations.AlterField(
model_name='vente',
name='type_cotisation',
field=models.CharField(blank=True, choices=[('Connexion', 'Connection'), ('Adhesion', 'Membership'), ('All', 'Both of them')], max_length=255, null=True, verbose_name='subscription type'),
model_name="vente",
name="type_cotisation",
field=models.CharField(
blank=True,
choices=[
("Connexion", "Connection"),
("Adhesion", "Membership"),
("All", "Both of them"),
],
max_length=255,
null=True,
verbose_name="subscription type",
),
),
]

View file

@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0033_auto_20180818_1319'),
]
dependencies = [("cotisations", "0033_auto_20180818_1319")]
operations = [
migrations.AlterField(
model_name='facture',
name='valid',
field=models.BooleanField(default=False, verbose_name='validated'),
),
model_name="facture",
name="valid",
field=models.BooleanField(default=False, verbose_name="validated"),
)
]

View file

@ -9,23 +9,35 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0034_auto_20180831_1532'),
]
dependencies = [("cotisations", "0034_auto_20180831_1532")]
operations = [
migrations.CreateModel(
name='NotePayment',
name="NotePayment",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('server', models.CharField(max_length=255, verbose_name='server')),
('port', models.PositiveIntegerField(blank=True, null=True)),
('id_note', models.PositiveIntegerField(blank=True, null=True)),
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
],
options={
'verbose_name': 'NoteKfet',
},
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("server", models.CharField(max_length=255, verbose_name="server")),
("port", models.PositiveIntegerField(blank=True, null=True)),
("id_note", models.PositiveIntegerField(blank=True, null=True)),
(
"payment",
models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method",
to="cotisations.Paiement",
),
),
],
options={"verbose_name": "NoteKfet"},
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
)
]

View file

@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0035_notepayment'),
]
dependencies = [("cotisations", "0035_notepayment")]
operations = [
migrations.AddField(
model_name='custominvoice',
name='remark',
field=models.TextField(blank=True, null=True, verbose_name='Remark'),
),
model_name="custominvoice",
name="remark",
field=models.TextField(blank=True, null=True, verbose_name="Remark"),
)
]

View file

@ -8,21 +8,40 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0036_custominvoice_remark'),
]
dependencies = [("cotisations", "0036_custominvoice_remark")]
operations = [
migrations.CreateModel(
name='CostEstimate',
name="CostEstimate",
fields=[
('custominvoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.CustomInvoice')),
('validity', models.DurationField(verbose_name='Period of validity')),
('final_invoice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='origin_cost_estimate', to='cotisations.CustomInvoice')),
(
"custominvoice_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="cotisations.CustomInvoice",
),
),
("validity", models.DurationField(verbose_name="Period of validity")),
(
"final_invoice",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="origin_cost_estimate",
to="cotisations.CustomInvoice",
),
),
],
options={
'permissions': (('view_costestimate', 'Can view a cost estimate object'),),
"permissions": (
("view_costestimate", "Can view a cost estimate object"),
)
},
bases=('cotisations.custominvoice',),
),
bases=("cotisations.custominvoice",),
)
]

View file

@ -8,24 +8,30 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0037_costestimate'),
]
dependencies = [("cotisations", "0037_costestimate")]
operations = [
migrations.AlterField(
model_name='costestimate',
name='final_invoice',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='origin_cost_estimate', to='cotisations.CustomInvoice'),
model_name="costestimate",
name="final_invoice",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="origin_cost_estimate",
to="cotisations.CustomInvoice",
),
),
migrations.AlterField(
model_name='costestimate',
name='validity',
field=models.DurationField(help_text='DD HH:MM:SS', verbose_name='Period of validity'),
model_name="costestimate",
name="validity",
field=models.DurationField(
help_text="DD HH:MM:SS", verbose_name="Period of validity"
),
),
migrations.AlterField(
model_name='custominvoice',
name='paid',
field=models.BooleanField(default=False, verbose_name='Paid'),
model_name="custominvoice",
name="paid",
field=models.BooleanField(default=False, verbose_name="Paid"),
),
]

View file

@ -9,20 +9,32 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0038_auto_20181231_1657'),
]
dependencies = [("cotisations", "0038_auto_20181231_1657")]
operations = [
migrations.CreateModel(
name='FreePayment',
name="FreePayment",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('payment', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method', to='cotisations.Paiement')),
],
options={
'verbose_name': 'Free payment',
},
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"payment",
models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method",
to="cotisations.Paiement",
),
),
],
options={"verbose_name": "Free payment"},
bases=(cotisations.payment_methods.mixins.PaymentMethodMixin, models.Model),
)
]

View file

@ -8,19 +8,27 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0039_freepayment'),
]
dependencies = [("cotisations", "0039_freepayment")]
operations = [
migrations.AddField(
model_name='article',
name='duration_days',
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration (in days, will be added to duration in months)'),
model_name="article",
name="duration_days",
field=models.PositiveIntegerField(
blank=True,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
verbose_name="duration (in days, will be added to duration in months)",
),
),
migrations.AddField(
model_name='vente',
name='duration_days',
field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0)], verbose_name='duration (in days, will be added to duration in months)'),
model_name="vente",
name="duration_days",
field=models.PositiveIntegerField(
blank=True,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
verbose_name="duration (in days, will be added to duration in months)",
),
),
]

View file

@ -8,34 +8,57 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cotisations', '0040_auto_20191002_2335'),
]
dependencies = [("cotisations", "0040_auto_20191002_2335")]
operations = [
migrations.AlterField(
model_name='balancepayment',
name='payment',
field=models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_balance', to='cotisations.Paiement'),
model_name="balancepayment",
name="payment",
field=models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method_balance",
to="cotisations.Paiement",
),
),
migrations.AlterField(
model_name='chequepayment',
name='payment',
field=models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_cheque', to='cotisations.Paiement'),
model_name="chequepayment",
name="payment",
field=models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method_cheque",
to="cotisations.Paiement",
),
),
migrations.AlterField(
model_name='comnpaypayment',
name='payment',
field=models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_comnpay', to='cotisations.Paiement'),
model_name="comnpaypayment",
name="payment",
field=models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method_comnpay",
to="cotisations.Paiement",
),
),
migrations.AlterField(
model_name='freepayment',
name='payment',
field=models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_free', to='cotisations.Paiement'),
model_name="freepayment",
name="payment",
field=models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method_free",
to="cotisations.Paiement",
),
),
migrations.AlterField(
model_name='notepayment',
name='payment',
field=models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='payment_method_note', to='cotisations.Paiement'),
model_name="notepayment",
name="payment",
field=models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
related_name="payment_method_note",
to="cotisations.Paiement",
),
),
]

View file

@ -19,4 +19,3 @@
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

File diff suppressed because it is too large Load diff

View file

@ -129,10 +129,4 @@ method to your model, where `form` is an instance of
from . import comnpay, cheque, balance, note_kfet, free, urls
PAYMENT_METHODS = [
comnpay,
cheque,
balance,
note_kfet,
free
]
PAYMENT_METHODS = [comnpay, cheque, balance, note_kfet, free]

View file

@ -22,6 +22,7 @@
This module contains a method to pay online using user balance.
"""
from . import models
NAME = "BALANCE"
PaymentMethod = models.BalancePayment

View file

@ -40,12 +40,13 @@ class BalancePayment(PaymentMethodMixin, models.Model):
payment = models.OneToOneField(
Paiement,
on_delete=models.CASCADE,
related_name='payment_method_balance',
editable=False
related_name="payment_method_balance",
editable=False,
)
minimum_balance = models.DecimalField(
verbose_name=_("Minimum balance"),
help_text=_("The minimal amount of money allowed for the balance"
help_text=_(
"The minimal amount of money allowed for the balance"
" at the end of a payment. You can specify negative "
"amount."
),
@ -63,8 +64,7 @@ class BalancePayment(PaymentMethodMixin, models.Model):
null=True,
)
credit_balance_allowed = models.BooleanField(
verbose_name=_("Allow user to credit their balance"),
default=False,
verbose_name=_("Allow user to credit their balance"), default=False
)
def end_payment(self, invoice, request):
@ -74,27 +74,17 @@ class BalancePayment(PaymentMethodMixin, models.Model):
user = invoice.user
total_price = invoice.prix_total()
if user.solde - total_price < self.minimum_balance:
messages.error(
request,
_("Your balance is too low for this operation.")
)
return redirect(reverse(
'users:profil',
kwargs={'userid': user.id}
))
return invoice.paiement.end_payment(
invoice,
request,
use_payment_method=False
)
messages.error(request, _("Your balance is too low for this operation."))
return redirect(reverse("users:profil", kwargs={"userid": user.id}))
return invoice.paiement.end_payment(invoice, request, use_payment_method=False)
def valid_form(self, form):
"""Checks that there is not already a balance payment method."""
p = Paiement.objects.filter(is_balance=True)
if len(p) > 0:
form.add_error(
'payment_method',
_("There is already a payment method for user balance.")
"payment_method",
_("There is already a payment method for user balance."),
)
def alter_payment(self, payment):
@ -107,12 +97,11 @@ class BalancePayment(PaymentMethodMixin, models.Model):
"""
return (
user.solde - price >= self.minimum_balance,
_("Your balance is too low for this operation.")
_("Your balance is too low for this operation."),
)
def can_credit_balance(self, user_request):
return (
len(Paiement.find_allowed_payments(user_request)
.exclude(is_balance=True)) > 0
len(Paiement.find_allowed_payments(user_request).exclude(is_balance=True))
> 0
) and self.credit_balance_allowed

View file

@ -22,6 +22,7 @@
This module contains a method to pay online using cheque.
"""
from . import models, urls, views
NAME = "CHEQUE"
PaymentMethod = models.ChequePayment

View file

@ -26,6 +26,7 @@ from cotisations.models import Facture as Invoice
class InvoiceForm(FormRevMixin, forms.ModelForm):
"""A simple form to get the bank a the cheque number."""
class Meta:
model = Invoice
fields = ['banque', 'cheque']
fields = ["banque", "cheque"]

View file

@ -38,16 +38,14 @@ class ChequePayment(PaymentMethodMixin, models.Model):
payment = models.OneToOneField(
Paiement,
on_delete=models.CASCADE,
related_name='payment_method_cheque',
editable=False
related_name="payment_method_cheque",
editable=False,
)
def end_payment(self, invoice, request):
"""Invalidates the invoice then redirect the user towards a view asking
for informations to add to the invoice before validating it.
"""
return redirect(reverse(
'cotisations:cheque:validate',
kwargs={'invoice_pk': invoice.pk}
))
return redirect(
reverse("cotisations:cheque:validate", kwargs={"invoice_pk": invoice.pk})
)

View file

@ -21,10 +21,4 @@
from django.conf.urls import url
from . import views
urlpatterns = [
url(
r'^validate/(?P<invoice_pk>[0-9]+)$',
views.cheque,
name='validate'
)
]
urlpatterns = [url(r"^validate/(?P<invoice_pk>[0-9]+)$", views.cheque, name="validate")]

View file

@ -42,29 +42,17 @@ def cheque(request, invoice_pk):
invoice = get_object_or_404(Invoice, pk=invoice_pk)
payment_method = find_payment_method(invoice.paiement)
if invoice.valid or not isinstance(payment_method, ChequePayment):
messages.error(
request,
_("You can't pay this invoice with a cheque.")
)
return redirect(reverse(
'users:profil',
kwargs={'userid': request.user.pk}
))
messages.error(request, _("You can't pay this invoice with a cheque."))
return redirect(reverse("users:profil", kwargs={"userid": request.user.pk}))
form = InvoiceForm(request.POST or None, instance=invoice)
if form.is_valid():
form.instance.valid = True
form.save()
return form.instance.paiement.end_payment(
form.instance,
request,
use_payment_method=False
form.instance, request, use_payment_method=False
)
return render(
request,
'cotisations/payment.html',
{
'form': form,
'amount': invoice.prix_total()
}
"cotisations/payment.html",
{"form": form, "amount": invoice.prix_total()},
)

View file

@ -22,5 +22,6 @@
This module contains a method to pay online using comnpay.
"""
from . import models, urls, views
NAME = "COMNPAY"
PaymentMethod = models.ComnpayPayment

View file

@ -10,13 +10,21 @@ import hashlib
from collections import OrderedDict
class Transaction():
class Transaction:
""" The class representing a transaction with all the functions
used during the negociation
"""
def __init__(self, vad_number="", secret_key="", urlRetourOK="",
urlRetourNOK="", urlIPN="", source="", typeTr="D"):
def __init__(
self,
vad_number="",
secret_key="",
urlRetourOK="",
urlRetourNOK="",
urlIPN="",
source="",
typeTr="D",
):
self.vad_number = vad_number
self.secret_key = secret_key
self.urlRetourOK = urlRetourOK
@ -26,8 +34,7 @@ class Transaction():
self.typeTr = typeTr
self.idTransaction = ""
def buildSecretHTML(self, produit="Produit", montant="0.00",
idTransaction=""):
def buildSecretHTML(self, produit="Produit", montant="0.00", idTransaction=""):
""" Build an HTML hidden form with the different parameters for the
transaction
"""
@ -43,30 +50,26 @@ class Transaction():
idTPE=self.vad_number,
idTransaction=self.idTransaction,
devise="EUR",
lang='fr',
lang="fr",
nom_produit=produit,
source=self.source,
urlRetourOK=self.urlRetourOK,
urlRetourNOK=self.urlRetourNOK,
typeTr=str(self.typeTr)
typeTr=str(self.typeTr),
)
if self.urlIPN != "":
array_tpe['urlIPN'] = self.urlIPN
array_tpe["urlIPN"] = self.urlIPN
array_tpe['key'] = self.secret_key
strWithKey = base64.b64encode(bytes(
'|'.join(array_tpe.values()),
'utf-8'
))
array_tpe["key"] = self.secret_key
strWithKey = base64.b64encode(bytes("|".join(array_tpe.values()), "utf-8"))
del array_tpe["key"]
array_tpe['sec'] = hashlib.sha512(strWithKey).hexdigest()
array_tpe["sec"] = hashlib.sha512(strWithKey).hexdigest()
ret = ""
for key in array_tpe:
ret += '<input type="hidden" name="{k}" value="{v}"/>'.format(
k=key,
v=array_tpe[key]
k=key, v=array_tpe[key]
)
return ret
@ -75,12 +78,13 @@ class Transaction():
def validSec(values, secret_key):
""" Check if the secret value is correct """
if "sec" in values:
sec = values['sec']
sec = values["sec"]
del values["sec"]
strWithKey = hashlib.sha512(base64.b64encode(bytes(
'|'.join(values.values()) + "|" + secret_key,
'utf-8'
))).hexdigest()
strWithKey = hashlib.sha512(
base64.b64encode(
bytes("|".join(values.values()) + "|" + secret_key, "utf-8")
)
).hexdigest()
return strWithKey.upper() == sec.upper()
else:
return False

View file

@ -41,39 +41,36 @@ class ComnpayPayment(PaymentMethodMixin, models.Model):
payment = models.OneToOneField(
Paiement,
on_delete=models.CASCADE,
related_name='payment_method_comnpay',
editable=False
related_name="payment_method_comnpay",
editable=False,
)
payment_credential = models.CharField(
max_length=255,
default='',
blank=True,
verbose_name=_("ComNpay VAT Number"),
max_length=255, default="", blank=True, verbose_name=_("ComNpay VAT Number")
)
payment_pass = AESEncryptedField(
max_length=255,
null=True,
blank=True,
verbose_name=_("ComNpay secret key"),
max_length=255, null=True, blank=True, verbose_name=_("ComNpay secret key")
)
minimum_payment = models.DecimalField(
verbose_name=_("Minimum payment"),
help_text=_("The minimal amount of money you have to use when paying"
" with ComNpay"),
help_text=_(
"The minimal amount of money you have to use when paying" " with ComNpay"
),
max_digits=5,
decimal_places=2,
default=1,
)
production = models.BooleanField(
default=True,
verbose_name=_("Production mode enabled (production URL, instead of homologation)"),
verbose_name=_(
"Production mode enabled (production URL, instead of homologation)"
),
)
def return_url_comnpay(self):
if self.production:
return 'https://secure.comnpay.com'
return "https://secure.comnpay.com"
else:
return 'https://secure.homologation.comnpay.com'
return "https://secure.homologation.comnpay.com"
def end_payment(self, invoice, request):
"""
@ -85,32 +82,36 @@ class ComnpayPayment(PaymentMethodMixin, models.Model):
p = Transaction(
str(self.payment_credential),
str(self.payment_pass),
'https://' + host + reverse(
'cotisations:comnpay:accept_payment',
kwargs={'factureid': invoice.id}
"https://"
+ host
+ reverse(
"cotisations:comnpay:accept_payment", kwargs={"factureid": invoice.id}
),
'https://' + host + reverse('cotisations:comnpay:refuse_payment'),
'https://' + host + reverse('cotisations:comnpay:ipn'),
"https://" + host + reverse("cotisations:comnpay:refuse_payment"),
"https://" + host + reverse("cotisations:comnpay:ipn"),
"",
"D"
"D",
)
r = {
'action': self.return_url_comnpay(),
'method': 'POST',
'content': p.buildSecretHTML(
_("Pay invoice number ")+str(invoice.id),
"action": self.return_url_comnpay(),
"method": "POST",
"content": p.buildSecretHTML(
_("Pay invoice number ") + str(invoice.id),
invoice.prix_total(),
idTransaction=str(invoice.id)
idTransaction=str(invoice.id),
),
'amount': invoice.prix_total(),
"amount": invoice.prix_total(),
}
return render(request, 'cotisations/payment.html', r)
return render(request, "cotisations/payment.html", r)
def check_price(self, price, *args, **kwargs):
"""Checks that the price meets the requirement to be paid with ComNpay.
"""
return ((price >= self.minimum_payment),
_("In order to pay your invoice with ComNpay, the price must"
" be greater than {} €.").format(self.minimum_payment))
return (
(price >= self.minimum_payment),
_(
"In order to pay your invoice with ComNpay, the price must"
" be greater than {} €."
).format(self.minimum_payment),
)

View file

@ -22,19 +22,7 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(
r'^accept/(?P<factureid>[0-9]+)$',
views.accept_payment,
name='accept_payment'
),
url(
r'^refuse/$',
views.refuse_payment,
name='refuse_payment'
),
url(
r'^ipn/$',
views.ipn,
name='ipn'
),
url(r"^accept/(?P<factureid>[0-9]+)$", views.accept_payment, name="accept_payment"),
url(r"^refuse/$", views.refuse_payment, name="refuse_payment"),
url(r"^ipn/$", views.ipn, name="ipn"),
]

View file

@ -50,26 +50,24 @@ def accept_payment(request, factureid):
if invoice.valid:
messages.success(
request,
_("The payment of %(amount)s € was accepted.") % {
'amount': invoice.prix_total()
}
_("The payment of %(amount)s € was accepted.")
% {"amount": invoice.prix_total()},
)
# In case a cotisation was bought, inform the user, the
# cotisation time has been extended too
if any(purchase.type_cotisation
for purchase in invoice.vente_set.all()):
if any(purchase.type_cotisation for purchase in invoice.vente_set.all()):
messages.success(
request,
_("The subscription of %(member_name)s was extended to"
" %(end_date)s.") % {
'member_name': invoice.user.pseudo,
'end_date': invoice.user.end_adhesion()
}
_(
"The subscription of %(member_name)s was extended to"
" %(end_date)s."
)
return redirect(reverse(
'users:profil',
kwargs={'userid': invoice.user.id}
))
% {
"member_name": invoice.user.pseudo,
"end_date": invoice.user.end_adhesion(),
},
)
return redirect(reverse("users:profil", kwargs={"userid": invoice.user.id}))
@csrf_exempt
@ -79,14 +77,8 @@ def refuse_payment(request):
The view where the user is redirected when a comnpay payment has been
refused.
"""
messages.error(
request,
_("The payment was refused.")
)
return redirect(reverse(
'users:profil',
kwargs={'userid': request.user.id}
))
messages.error(request, _("The payment was refused."))
return redirect(reverse("users:profil", kwargs={"userid": request.user.id}))
@csrf_exempt
@ -97,27 +89,26 @@ def ipn(request):
Comnpay with 400 response if not or with a 200 response if yes.
"""
p = Transaction()
order = ('idTpe', 'idTransaction', 'montant', 'result', 'sec', )
order = ("idTpe", "idTransaction", "montant", "result", "sec")
try:
data = OrderedDict([(f, request.POST[f]) for f in order])
except MultiValueDictKeyError:
return HttpResponseBadRequest("HTTP/1.1 400 Bad Request")
idTransaction = request.POST['idTransaction']
idTransaction = request.POST["idTransaction"]
try:
factureid = int(idTransaction)
except ValueError:
return HttpResponseBadRequest("HTTP/1.1 400 Bad Request")
facture = get_object_or_404(Facture, id=factureid)
payment_method = get_object_or_404(
ComnpayPayment, payment=facture.paiement)
payment_method = get_object_or_404(ComnpayPayment, payment=facture.paiement)
if not p.validSec(data, payment_method.payment_pass):
return HttpResponseBadRequest("HTTP/1.1 400 Bad Request")
result = True if (request.POST['result'] == 'OK') else False
idTpe = request.POST['idTpe']
result = True if (request.POST["result"] == "OK") else False
idTpe = request.POST["idTpe"]
# Checking that the payment is actually for us.
if not idTpe == payment_method.payment_credential:
@ -136,4 +127,3 @@ def ipn(request):
# Everything worked we send a reponse to Comnpay indicating that
# it's ok for them to proceed
return HttpResponse("HTTP/1.0 200 OK")

View file

@ -24,6 +24,7 @@ from django.utils.translation import ugettext_lazy as _
from . import PAYMENT_METHODS
from cotisations.utils import find_payment_method
def payment_method_factory(payment, *args, creation=True, **kwargs):
"""This function finds the right payment method form for a given payment.
@ -40,12 +41,10 @@ def payment_method_factory(payment, *args, creation=True, **kwargs):
Returns:
A form or None
"""
payment_method = kwargs.pop('instance', find_payment_method(payment))
payment_method = kwargs.pop("instance", find_payment_method(payment))
if payment_method is not None:
return forms.modelform_factory(type(payment_method), fields='__all__')(
*args,
instance=payment_method,
**kwargs
return forms.modelform_factory(type(payment_method), fields="__all__")(
*args, instance=payment_method, **kwargs
)
elif creation:
return PaymentMethodForm(*args, **kwargs)
@ -58,23 +57,24 @@ class PaymentMethodForm(forms.Form):
payment_method = forms.ChoiceField(
label=_("Special payment method"),
help_text=_("Warning: you will not be able to change the payment "
help_text=_(
"Warning: you will not be able to change the payment "
"method later. But you will be allowed to edit the other "
"options."
),
required=False
required=False,
)
def __init__(self, *args, **kwargs):
super(PaymentMethodForm, self).__init__(*args, **kwargs)
prefix = kwargs.get('prefix', None)
self.fields['payment_method'].choices = [(i,p.NAME) for (i,p) in enumerate(PAYMENT_METHODS)]
self.fields['payment_method'].choices.insert(0, ('', _('no')))
self.fields['payment_method'].widget.attrs = {
'id': 'paymentMethodSelect'
}
prefix = kwargs.get("prefix", None)
self.fields["payment_method"].choices = [
(i, p.NAME) for (i, p) in enumerate(PAYMENT_METHODS)
]
self.fields["payment_method"].choices.insert(0, ("", _("no")))
self.fields["payment_method"].widget.attrs = {"id": "paymentMethodSelect"}
self.templates = [
forms.modelform_factory(p.PaymentMethod, fields='__all__')(prefix=prefix)
forms.modelform_factory(p.PaymentMethod, fields="__all__")(prefix=prefix)
for p in PAYMENT_METHODS
]
@ -84,29 +84,29 @@ class PaymentMethodForm(forms.Form):
found. Tries to call `payment_method.valid_form` if it exists.
"""
super(PaymentMethodForm, self).clean()
choice = self.cleaned_data['payment_method']
if choice=='':
choice = self.cleaned_data["payment_method"]
if choice == "":
return
choice = int(choice)
model = PAYMENT_METHODS[choice].PaymentMethod
form = forms.modelform_factory(model, fields='__all__')(self.data, prefix=self.prefix)
form = forms.modelform_factory(model, fields="__all__")(
self.data, prefix=self.prefix
)
self.payment_method = form.save(commit=False)
if hasattr(self.payment_method, 'valid_form'):
if hasattr(self.payment_method, "valid_form"):
self.payment_method.valid_form(self)
return self.cleaned_data
def save(self, payment, *args, **kwargs):
"""Saves the payment method.
Tries to call `payment_method.alter_payment` if it exists.
"""
commit = kwargs.pop('commit', True)
if not hasattr(self, 'payment_method'):
commit = kwargs.pop("commit", True)
if not hasattr(self, "payment_method"):
return None
self.payment_method.payment = payment
if hasattr(self.payment_method, 'alter_payment'):
if hasattr(self.payment_method, "alter_payment"):
self.payment_method.alter_payment(payment)
if commit:
payment.save()

View file

@ -22,6 +22,7 @@
This module contains a method to pay online using user balance.
"""
from . import models
NAME = "FREE"
PaymentMethod = models.FreePayment

View file

@ -38,24 +38,17 @@ class FreePayment(PaymentMethodMixin, models.Model):
payment = models.OneToOneField(
Paiement,
on_delete=models.CASCADE,
related_name='payment_method_free',
editable=False
related_name="payment_method_free",
editable=False,
)
def end_payment(self, invoice, request):
"""Ends the payment normally.
"""
return invoice.paiement.end_payment(
invoice,
request,
use_payment_method=False
)
return invoice.paiement.end_payment(invoice, request, use_payment_method=False)
def check_price(self, price, user, *args, **kwargs):
"""Checks that the price meets the requirement to be paid with user
balance.
"""
return (
price == 0,
_("You cannot validate this invoice for free.")
)
return (price == 0, _("You cannot validate this invoice for free."))

View file

@ -29,5 +29,4 @@ class PaymentMethodMixin:
Must return a HttpResponse-like object.
"""
return self.payment.end_payment(
invoice, request, use_payment_method=False)
return self.payment.end_payment(invoice, request, use_payment_method=False)

View file

@ -22,5 +22,6 @@
This module contains a method to pay online using comnpay.
"""
from . import models, urls
NAME = "NOTE"
PaymentMethod = models.NotePayment

View file

@ -24,15 +24,11 @@ from django.utils.translation import ugettext_lazy as _
from cotisations.utils import find_payment_method
class NoteCredentialForm(forms.Form):
"""A special form to get credential to connect to a NoteKfet2015 server throught his API
object.
"""
login = forms.CharField(
label=_("pseudo note")
)
password = forms.CharField(
label=_("Password"),
widget=forms.PasswordInput
)
login = forms.CharField(label=_("pseudo note"))
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)

View file

@ -41,25 +41,17 @@ class NotePayment(PaymentMethodMixin, models.Model):
payment = models.OneToOneField(
Paiement,
on_delete = models.CASCADE,
related_name = 'payment_method_note',
editable = False
)
server = models.CharField(
max_length=255,
verbose_name=_("server")
)
port = models.PositiveIntegerField(
blank = True,
null = True
)
id_note = models.PositiveIntegerField(
blank = True,
null = True
on_delete=models.CASCADE,
related_name="payment_method_note",
editable=False,
)
server = models.CharField(max_length=255, verbose_name=_("server"))
port = models.PositiveIntegerField(blank=True, null=True)
id_note = models.PositiveIntegerField(blank=True, null=True)
def end_payment(self, invoice, request):
return redirect(reverse(
'cotisations:note_kfet:note_payment',
kwargs={'factureid': invoice.id}
))
return redirect(
reverse(
"cotisations:note_kfet:note_payment", kwargs={"factureid": invoice.id}
)
)

View file

@ -12,13 +12,14 @@ import traceback
def get_response(socket):
length_str = b''
length_str = b""
char = socket.recv(1)
while char != b'\n':
while char != b"\n":
length_str += char
char = socket.recv(1)
total = int(length_str)
return json.loads(socket.recv(total).decode('utf-8'))
return json.loads(socket.recv(total).decode("utf-8"))
def connect(server, port):
sock = socket.socket()
@ -35,7 +36,8 @@ def connect(server, port):
return (False, sock, "Serveur indisponible")
return (True, sock, "")
def login(server, port, username, password, masque = [[], [], True]):
def login(server, port, username, password, masque=[[], [], True]):
result, sock, err = connect(server, port)
if not result:
return (False, None, err)
@ -43,7 +45,7 @@ def login(server, port, username, password, masque = [[], [], True]):
commande = ["login", [username, password, "bdd", masque]]
sock.send(json.dumps(commande).encode("utf-8"))
response = get_response(sock)
retcode = response['retcode']
retcode = response["retcode"]
if retcode == 0:
return (True, sock, "")
elif retcode == 5:
@ -60,11 +62,28 @@ def don(sock, montant, id_note, facture):
Faire faire un don à l'id_note
"""
try:
sock.send(json.dumps(["dons", [[id_note], round(montant*100), "Facture : id=%s, designation=%s" % (facture.id, facture.name())]]).encode("utf-8"))
sock.send(
json.dumps(
[
"dons",
[
[id_note],
round(montant * 100),
"Facture : id=%s, designation=%s"
% (facture.id, facture.name()),
],
]
).encode("utf-8")
)
response = get_response(sock)
retcode = response['retcode']
retcode = response["retcode"]
transaction_retcode = response["msg"][0][0]
if 0 < retcode < 100 or 200 <= retcode or 0 < transaction_retcode < 100 or 200 <= transaction_retcode:
if (
0 < retcode < 100
or 200 <= retcode
or 0 < transaction_retcode < 100
or 200 <= transaction_retcode
):
return (False, "Transaction échouée. (Solde trop négatif ?)")
elif retcode == 0:
return (True, "")

View file

@ -23,8 +23,6 @@ from . import views
urlpatterns = [
url(
r'^note_payment/(?P<factureid>[0-9]+)$',
views.note_payment,
name='note_payment'
),
r"^note_payment/(?P<factureid>[0-9]+)$", views.note_payment, name="note_payment"
)
]

View file

@ -39,13 +39,11 @@ from cotisations.models import Facture
from cotisations.utils import find_payment_method
from .models import NotePayment
from re2o.views import form
from re2o.acl import (
can_create,
can_edit
)
from re2o.acl import can_create, can_edit
from .note import login, don
from .forms import NoteCredentialForm
@login_required
@can_edit(Facture)
def note_payment(request, facture, factureid):
@ -58,40 +56,38 @@ def note_payment(request, facture, factureid):
payment_method = find_payment_method(facture.paiement)
if not payment_method or not isinstance(payment_method, NotePayment):
messages.error(request, _("Unknown error."))
return redirect(reverse(
'users:profil',
kwargs={'userid': user.id}
))
return redirect(reverse("users:profil", kwargs={"userid": user.id}))
noteform = NoteCredentialForm(request.POST or None)
if noteform.is_valid():
pseudo = noteform.cleaned_data['login']
password = noteform.cleaned_data['password']
result, sock, err = login(payment_method.server, payment_method.port, pseudo, password)
pseudo = noteform.cleaned_data["login"]
password = noteform.cleaned_data["password"]
result, sock, err = login(
payment_method.server, payment_method.port, pseudo, password
)
if not result:
messages.error(request, err)
return form(
{'form': noteform, 'amount': facture.prix_total()},
{"form": noteform, "amount": facture.prix_total()},
"cotisations/payment.html",
request
request,
)
else:
result, err = don(sock, facture.prix_total(), payment_method.id_note, facture)
result, err = don(
sock, facture.prix_total(), payment_method.id_note, facture
)
if not result:
messages.error(request, err)
return form(
{'form': noteform, 'amount': facture.prix_total()},
{"form": noteform, "amount": facture.prix_total()},
"cotisations/payment.html",
request
request,
)
facture.valid = True
facture.save()
messages.success(request, _("The payment with note was done."))
return redirect(reverse(
'users:profil',
kwargs={'userid': user.id}
))
return redirect(reverse("users:profil", kwargs={"userid": user.id}))
return form(
{'form': noteform, 'amount': facture.prix_total()},
{"form": noteform, "amount": facture.prix_total()},
"cotisations/payment.html",
request
request,
)

View file

@ -22,7 +22,7 @@ from django.conf.urls import include, url
from . import comnpay, cheque, note_kfet
urlpatterns = [
url(r'^comnpay/', include(comnpay.urls, namespace='comnpay')),
url(r'^cheque/', include(cheque.urls, namespace='cheque')),
url(r'^note_kfet/', include(note_kfet.urls, namespace='note_kfet')),
url(r"^comnpay/", include(comnpay.urls, namespace="comnpay")),
url(r"^cheque/", include(cheque.urls, namespace="cheque")),
url(r"^note_kfet/", include(note_kfet.urls, namespace="note_kfet")),
]

View file

@ -7,19 +7,13 @@ from dateutil.relativedelta import relativedelta
from users.models import User
from .models import Vente, Facture, Cotisation, Paiement
class VenteModelTests(TestCase):
def setUp(self):
self.user = User.objects.create(
pseudo="testUser",
email="test@example.org"
)
self.paiement = Paiement.objects.create(
moyen="test payment"
)
self.user = User.objects.create(pseudo="testUser", email="test@example.org")
self.paiement = Paiement.objects.create(moyen="test payment")
self.f = Facture.objects.create(
user=self.user,
paiement=self.paiement,
valid=True
user=self.user, paiement=self.paiement, valid=True
)
def test_one_day_cotisation(self):
@ -39,7 +33,7 @@ class VenteModelTests(TestCase):
self.assertAlmostEqual(
self.user.end_connexion() - date,
datetime.timedelta(days=1),
delta=datetime.timedelta(seconds=1)
delta=datetime.timedelta(seconds=1),
)
def test_one_month_cotisation(self):
@ -57,11 +51,8 @@ class VenteModelTests(TestCase):
prix=0,
)
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds=0
self.assertEqual(
delta,
relativedelta(months=1),
)
delta.microseconds = 0
self.assertEqual(delta, relativedelta(months=1))
def test_one_month_and_one_week_cotisation(self):
"""
@ -78,15 +69,10 @@ class VenteModelTests(TestCase):
prix=0,
)
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds=0
self.assertEqual(
delta,
relativedelta(months=1, days=7),
)
delta.microseconds = 0
self.assertEqual(delta, relativedelta(months=1, days=7))
def tearDown(self):
self.f.delete()
self.user.delete()
self.paiement.delete()

View file

@ -9,6 +9,7 @@ from django.utils import timezone
from users.models import Adherent
from .models import Vente, Facture, Cotisation, Paiement, Article
class NewFactureTests(TestCase):
def tearDown(self):
self.user.facture_set.all().delete()
@ -19,51 +20,46 @@ class NewFactureTests(TestCase):
self.article_one_month_and_one_week.delete()
def setUp(self):
self.user = Adherent.objects.create(
pseudo="testUser",
email="test@example.org",
)
self.user.set_password('plopiplop')
self.user = Adherent.objects.create(pseudo="testUser", email="test@example.org")
self.user.set_password("plopiplop")
self.user.user_permissions.set(
[
Permission.objects.get_by_natural_key("add_facture", "cotisations", "Facture"),
Permission.objects.get_by_natural_key("use_every_payment", "cotisations", "Paiement"),
Permission.objects.get_by_natural_key(
"add_facture", "cotisations", "Facture"
),
Permission.objects.get_by_natural_key(
"use_every_payment", "cotisations", "Paiement"
),
]
)
self.user.save()
self.paiement = Paiement.objects.create(
moyen="test payment",
)
self.paiement = Paiement.objects.create(moyen="test payment")
self.article_one_day = Article.objects.create(
name="One day",
prix=0,
duration=0,
duration_days=1,
type_cotisation='All',
available_for_everyone=True
type_cotisation="All",
available_for_everyone=True,
)
self.article_one_month = Article.objects.create(
name="One day",
prix=0,
duration=1,
duration_days=0,
type_cotisation='All',
available_for_everyone=True
type_cotisation="All",
available_for_everyone=True,
)
self.article_one_month_and_one_week = Article.objects.create(
name="One day",
prix=0,
duration=1,
duration_days=7,
type_cotisation='All',
available_for_everyone=True
)
self.client.login(
username="testUser",
password="plopiplop"
type_cotisation="All",
available_for_everyone=True,
)
self.client.login(username="testUser", password="plopiplop")
def test_invoice_with_one_day(self):
data = {
@ -76,19 +72,15 @@ class NewFactureTests(TestCase):
"form-0-quantity": 1,
}
date = timezone.now()
response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data)
self.assertEqual(
response.status_code,
302
)
self.assertEqual(
response.url,
"/users/profil/%d"%self.user.pk
response = self.client.post(
reverse("cotisations:new-facture", kwargs={"userid": self.user.pk}), data
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/users/profil/%d" % self.user.pk)
self.assertAlmostEqual(
self.user.end_connexion() - date,
datetime.timedelta(days=1),
delta=datetime.timedelta(seconds=1)
delta=datetime.timedelta(seconds=1),
)
def test_invoice_with_one_month(self):
@ -102,21 +94,14 @@ class NewFactureTests(TestCase):
"form-0-quantity": 1,
}
date = timezone.now()
response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data)
self.assertEqual(
response.status_code,
302
)
self.assertEqual(
response.url,
"/users/profil/%d"%self.user.pk
response = self.client.post(
reverse("cotisations:new-facture", kwargs={"userid": self.user.pk}), data
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/users/profil/%d" % self.user.pk)
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds=0
self.assertEqual(
delta,
relativedelta(months=1),
)
delta.microseconds = 0
self.assertEqual(delta, relativedelta(months=1))
def test_invoice_with_one_month_and_one_week(self):
data = {
@ -131,23 +116,15 @@ class NewFactureTests(TestCase):
"form-1-quantity": 1,
}
date = timezone.now()
response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data)
self.assertEqual(
response.status_code,
302
)
self.assertEqual(
response.url,
"/users/profil/%d"%self.user.pk
response = self.client.post(
reverse("cotisations:new-facture", kwargs={"userid": self.user.pk}), data
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, "/users/profil/%d" % self.user.pk)
invoice = self.user.facture_set.first()
delta = relativedelta(self.user.end_connexion(), date)
delta.microseconds=0
self.assertEqual(
delta,
relativedelta(months=1, days=7),
)
delta.microseconds = 0
self.assertEqual(delta, relativedelta(months=1, days=7))
def test_several_articles_creates_several_purchases(self):
data = {
@ -161,6 +138,8 @@ class NewFactureTests(TestCase):
"form-1-article": 2,
"form-1-quantity": 1,
}
response = self.client.post(reverse('cotisations:new-facture', kwargs={'userid':self.user.pk}), data)
response = self.client.post(
reverse("cotisations:new-facture", kwargs={"userid": self.user.pk}), data
)
f = self.user.facture_set.first()
self.assertEqual(f.vente_set.count(), 2)

View file

@ -42,9 +42,9 @@ from re2o.mixins import AclMixin, RevMixin
from preferences.models import CotisationsOption
TEMP_PREFIX = getattr(settings, 'TEX_TEMP_PREFIX', 'render_tex-')
CACHE_PREFIX = getattr(settings, 'TEX_CACHE_PREFIX', 'render-tex')
CACHE_TIMEOUT = getattr(settings, 'TEX_CACHE_TIMEOUT', 86400) # 1 day
TEMP_PREFIX = getattr(settings, "TEX_TEMP_PREFIX", "render_tex-")
CACHE_PREFIX = getattr(settings, "TEX_CACHE_PREFIX", "render-tex")
CACHE_TIMEOUT = getattr(settings, "TEX_CACHE_TIMEOUT", 86400) # 1 day
def render_invoice(_request, ctx={}):
@ -53,20 +53,20 @@ def render_invoice(_request, ctx={}):
date, the user, the articles, the prices, ...
"""
options, _ = CotisationsOption.objects.get_or_create()
is_estimate = ctx.get('is_estimate', False)
filename = '_'.join([
'cost_estimate' if is_estimate else 'invoice',
slugify(ctx.get('asso_name', "")),
slugify(ctx.get('recipient_name', "")),
str(ctx.get('DATE', datetime.now()).year),
str(ctx.get('DATE', datetime.now()).month),
str(ctx.get('DATE', datetime.now()).day),
])
templatename = options.invoice_template.template.name.split('/')[-1]
r = render_tex(_request, templatename, ctx)
r['Content-Disposition'] = 'attachment; filename="{name}.pdf"'.format(
name=filename
is_estimate = ctx.get("is_estimate", False)
filename = "_".join(
[
"cost_estimate" if is_estimate else "invoice",
slugify(ctx.get("asso_name", "")),
slugify(ctx.get("recipient_name", "")),
str(ctx.get("DATE", datetime.now()).year),
str(ctx.get("DATE", datetime.now()).month),
str(ctx.get("DATE", datetime.now()).day),
]
)
templatename = options.invoice_template.template.name.split("/")[-1]
r = render_tex(_request, templatename, ctx)
r["Content-Disposition"] = 'attachment; filename="{name}.pdf"'.format(name=filename)
return r
@ -75,20 +75,20 @@ def render_voucher(_request, ctx={}):
Render a subscribtion voucher.
"""
options, _ = CotisationsOption.objects.get_or_create()
filename = '_'.join([
'voucher',
slugify(ctx.get('asso_name', "")),
slugify(ctx.get('firstname', "")),
slugify(ctx.get('lastname', "")),
str(ctx.get('date_begin', datetime.now()).year),
str(ctx.get('date_begin', datetime.now()).month),
str(ctx.get('date_begin', datetime.now()).day),
])
templatename = options.voucher_template.template.name.split('/')[-1]
r = render_tex(_request, templatename, ctx)
r['Content-Disposition'] = 'attachment; filename="{name}.pdf"'.format(
name=filename
filename = "_".join(
[
"voucher",
slugify(ctx.get("asso_name", "")),
slugify(ctx.get("firstname", "")),
slugify(ctx.get("lastname", "")),
str(ctx.get("date_begin", datetime.now()).year),
str(ctx.get("date_begin", datetime.now()).month),
str(ctx.get("date_begin", datetime.now()).day),
]
)
templatename = options.voucher_template.template.name.split("/")[-1]
r = render_tex(_request, templatename, ctx)
r["Content-Disposition"] = 'attachment; filename="{name}.pdf"'.format(name=filename)
return r
@ -106,18 +106,18 @@ def create_pdf(template, ctx={}):
"""
context = ctx
template = get_template(template)
rendered_tpl = template.render(context).encode('utf-8')
rendered_tpl = template.render(context).encode("utf-8")
with tempfile.TemporaryDirectory() as tempdir:
for _ in range(2):
with open("/var/www/re2o/out.log", "w") as f:
process = Popen(
['pdflatex', '-output-directory', tempdir],
["pdflatex", "-output-directory", tempdir],
stdin=PIPE,
stdout=f,#PIPE,
stdout=f, # PIPE,
)
process.communicate(rendered_tpl)
with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f:
with open(os.path.join(tempdir, "texput.pdf"), "rb") as f:
pdf = f.read()
return pdf
@ -127,10 +127,7 @@ def escape_chars(string):
"""Escape the '%' and the '' signs to avoid messing with LaTeX"""
if not isinstance(string, str):
return string
mapping = (
('', r'\euro'),
('%', r'\%'),
)
mapping = (("", r"\euro"), ("%", r"\%"))
r = str(string)
for k, v in mapping:
r = r.replace(k, v)
@ -152,6 +149,6 @@ def render_tex(_request, template, ctx={}):
An HttpResponse with type `application/pdf` containing the PDF file.
"""
pdf = create_pdf(template, ctx)
r = HttpResponse(content_type='application/pdf')
r = HttpResponse(content_type="application/pdf")
r.write(pdf)
return r

View file

@ -31,155 +31,77 @@ from . import views
from . import payment_methods
urlpatterns = [
url(r"^new_facture/(?P<userid>[0-9]+)$", views.new_facture, name="new-facture"),
url(
r'^new_facture/(?P<userid>[0-9]+)$',
views.new_facture,
name='new-facture'
r"^edit_facture/(?P<factureid>[0-9]+)$", views.edit_facture, name="edit-facture"
),
url(r"^del_facture/(?P<factureid>[0-9]+)$", views.del_facture, name="del-facture"),
url(r"^facture_pdf/(?P<factureid>[0-9]+)$", views.facture_pdf, name="facture-pdf"),
url(r"^voucher_pdf/(?P<factureid>[0-9]+)$", views.voucher_pdf, name="voucher-pdf"),
url(r"^new_cost_estimate/$", views.new_cost_estimate, name="new-cost-estimate"),
url(
r"^index_cost_estimate/$", views.index_cost_estimate, name="index-cost-estimate"
),
url(
r'^edit_facture/(?P<factureid>[0-9]+)$',
views.edit_facture,
name='edit-facture'
),
url(
r'^del_facture/(?P<factureid>[0-9]+)$',
views.del_facture,
name='del-facture'
),
url(
r'^facture_pdf/(?P<factureid>[0-9]+)$',
views.facture_pdf,
name='facture-pdf'
),
url(
r'^voucher_pdf/(?P<factureid>[0-9]+)$',
views.voucher_pdf,
name='voucher-pdf'
),
url(
r'^new_cost_estimate/$',
views.new_cost_estimate,
name='new-cost-estimate'
),
url(
r'^index_cost_estimate/$',
views.index_cost_estimate,
name='index-cost-estimate'
),
url(
r'^cost_estimate_pdf/(?P<costestimateid>[0-9]+)$',
r"^cost_estimate_pdf/(?P<costestimateid>[0-9]+)$",
views.cost_estimate_pdf,
name='cost-estimate-pdf',
name="cost-estimate-pdf",
),
url(
r'^index_custom_invoice/$',
r"^index_custom_invoice/$",
views.index_custom_invoice,
name='index-custom-invoice'
name="index-custom-invoice",
),
url(
r'^edit_cost_estimate/(?P<costestimateid>[0-9]+)$',
r"^edit_cost_estimate/(?P<costestimateid>[0-9]+)$",
views.edit_cost_estimate,
name='edit-cost-estimate'
name="edit-cost-estimate",
),
url(
r'^cost_estimate_to_invoice/(?P<costestimateid>[0-9]+)$',
r"^cost_estimate_to_invoice/(?P<costestimateid>[0-9]+)$",
views.cost_estimate_to_invoice,
name='cost-estimate-to-invoice'
name="cost-estimate-to-invoice",
),
url(
r'^del_cost_estimate/(?P<costestimateid>[0-9]+)$',
r"^del_cost_estimate/(?P<costestimateid>[0-9]+)$",
views.del_cost_estimate,
name='del-cost-estimate'
name="del-cost-estimate",
),
url(r"^new_custom_invoice/$", views.new_custom_invoice, name="new-custom-invoice"),
url(
r'^new_custom_invoice/$',
views.new_custom_invoice,
name='new-custom-invoice'
),
url(
r'^edit_custom_invoice/(?P<custominvoiceid>[0-9]+)$',
r"^edit_custom_invoice/(?P<custominvoiceid>[0-9]+)$",
views.edit_custom_invoice,
name='edit-custom-invoice'
name="edit-custom-invoice",
),
url(
r'^custom_invoice_pdf/(?P<custominvoiceid>[0-9]+)$',
r"^custom_invoice_pdf/(?P<custominvoiceid>[0-9]+)$",
views.custom_invoice_pdf,
name='custom-invoice-pdf',
name="custom-invoice-pdf",
),
url(
r'^del_custom_invoice/(?P<custominvoiceid>[0-9]+)$',
r"^del_custom_invoice/(?P<custominvoiceid>[0-9]+)$",
views.del_custom_invoice,
name='del-custom-invoice'
name="del-custom-invoice",
),
url(r"^credit_solde/(?P<userid>[0-9]+)$", views.credit_solde, name="credit-solde"),
url(r"^add_article/$", views.add_article, name="add-article"),
url(
r'^credit_solde/(?P<userid>[0-9]+)$',
views.credit_solde,
name='credit-solde'
r"^edit_article/(?P<articleid>[0-9]+)$", views.edit_article, name="edit-article"
),
url(r"^del_article/$", views.del_article, name="del-article"),
url(r"^add_paiement/$", views.add_paiement, name="add-paiement"),
url(
r'^add_article/$',
views.add_article,
name='add-article'
),
url(
r'^edit_article/(?P<articleid>[0-9]+)$',
views.edit_article,
name='edit-article'
),
url(
r'^del_article/$',
views.del_article,
name='del-article'
),
url(
r'^add_paiement/$',
views.add_paiement,
name='add-paiement'
),
url(
r'^edit_paiement/(?P<paiementid>[0-9]+)$',
r"^edit_paiement/(?P<paiementid>[0-9]+)$",
views.edit_paiement,
name='edit-paiement'
name="edit-paiement",
),
url(
r'^del_paiement/$',
views.del_paiement,
name='del-paiement'
),
url(
r'^add_banque/$',
views.add_banque,
name='add-banque'
),
url(
r'^edit_banque/(?P<banqueid>[0-9]+)$',
views.edit_banque,
name='edit-banque'
),
url(
r'^del_banque/$',
views.del_banque,
name='del-banque'
),
url(
r'^index_article/$',
views.index_article,
name='index-article'
),
url(
r'^index_banque/$',
views.index_banque,
name='index-banque'
),
url(
r'^index_paiement/$',
views.index_paiement,
name='index-paiement'
),
url(
r'^control/$',
views.control,
name='control'
),
url(r'^$', views.index, name='index'),
url(r"^del_paiement/$", views.del_paiement, name="del-paiement"),
url(r"^add_banque/$", views.add_banque, name="add-banque"),
url(r"^edit_banque/(?P<banqueid>[0-9]+)$", views.edit_banque, name="edit-banque"),
url(r"^del_banque/$", views.del_banque, name="del-banque"),
url(r"^index_article/$", views.index_article, name="index-article"),
url(r"^index_banque/$", views.index_banque, name="index-banque"),
url(r"^index_paiement/$", views.index_paiement, name="index-paiement"),
url(r"^control/$", views.control, name="control"),
url(r"^$", views.index, name="index"),
] + payment_methods.urls.urlpatterns

View file

@ -25,9 +25,7 @@ from django.template.loader import get_template
from django.core.mail import EmailMessage
from .tex import create_pdf
from preferences.models import (
AssoOption, GeneralOption, CotisationsOption, Mandate
)
from preferences.models import AssoOption, GeneralOption, CotisationsOption, Mandate
from re2o.settings import LOGO_PATH
from re2o import settings
@ -35,6 +33,7 @@ from re2o import settings
def find_payment_method(payment):
"""Finds the payment method associated to the payment if it exists."""
from cotisations.payment_methods import PAYMENT_METHODS
for method in PAYMENT_METHODS:
try:
o = method.PaymentMethod.objects.get(payment=payment)
@ -48,51 +47,47 @@ def send_mail_invoice(invoice):
"""Creates the pdf of the invoice and sends it by email to the client"""
purchases_info = []
for purchase in invoice.vente_set.all():
purchases_info.append({
'name': purchase.name,
'price': purchase.prix,
'quantity': purchase.number,
'total_price': purchase.prix_total
})
purchases_info.append(
{
"name": purchase.name,
"price": purchase.prix,
"quantity": purchase.number,
"total_price": purchase.prix_total,
}
)
ctx = {
'paid': True,
'fid': invoice.id,
'DATE': invoice.date,
'recipient_name': "{} {}".format(
invoice.user.name,
invoice.user.surname
),
'address': invoice.user.room,
'article': purchases_info,
'total': invoice.prix_total(),
'asso_name': AssoOption.get_cached_value('name'),
'line1': AssoOption.get_cached_value('adresse1'),
'line2': AssoOption.get_cached_value('adresse2'),
'siret': AssoOption.get_cached_value('siret'),
'email': AssoOption.get_cached_value('contact'),
'phone': AssoOption.get_cached_value('telephone'),
'tpl_path': os.path.join(settings.BASE_DIR, LOGO_PATH)
"paid": True,
"fid": invoice.id,
"DATE": invoice.date,
"recipient_name": "{} {}".format(invoice.user.name, invoice.user.surname),
"address": invoice.user.room,
"article": purchases_info,
"total": invoice.prix_total(),
"asso_name": AssoOption.get_cached_value("name"),
"line1": AssoOption.get_cached_value("adresse1"),
"line2": AssoOption.get_cached_value("adresse2"),
"siret": AssoOption.get_cached_value("siret"),
"email": AssoOption.get_cached_value("contact"),
"phone": AssoOption.get_cached_value("telephone"),
"tpl_path": os.path.join(settings.BASE_DIR, LOGO_PATH),
}
pdf = create_pdf('cotisations/factures.tex', ctx)
template = get_template('cotisations/email_invoice')
pdf = create_pdf("cotisations/factures.tex", ctx)
template = get_template("cotisations/email_invoice")
ctx = {
'name': "{} {}".format(
invoice.user.name,
invoice.user.surname
),
'contact_mail': AssoOption.get_cached_value('contact'),
'asso_name': AssoOption.get_cached_value('name')
"name": "{} {}".format(invoice.user.name, invoice.user.surname),
"contact_mail": AssoOption.get_cached_value("contact"),
"asso_name": AssoOption.get_cached_value("name"),
}
mail = EmailMessage(
'Votre facture / Your invoice',
"Votre facture / Your invoice",
template.render(ctx),
GeneralOption.get_cached_value('email_from'),
GeneralOption.get_cached_value("email_from"),
[invoice.user.get_mail],
attachments=[('invoice.pdf', pdf, 'application/pdf')]
attachments=[("invoice.pdf", pdf, "application/pdf")],
)
mail.send()
@ -101,34 +96,33 @@ def send_mail_voucher(invoice):
"""Creates a voucher from an invoice and sends it by email to the client"""
president = Mandate.get_mandate(invoice.date).president
ctx = {
'asso_name': AssoOption.get_cached_value('name'),
'pres_name': ' '.join([president.name, president.surname]),
'firstname': invoice.user.name,
'lastname': invoice.user.surname,
'email': invoice.user.email,
'phone': invoice.user.telephone,
'date_end': invoice.get_subscription().latest('date_end').date_end,
'date_begin': invoice.get_subscription().earliest('date_start').date_start
"asso_name": AssoOption.get_cached_value("name"),
"pres_name": " ".join([president.name, president.surname]),
"firstname": invoice.user.name,
"lastname": invoice.user.surname,
"email": invoice.user.email,
"phone": invoice.user.telephone,
"date_end": invoice.get_subscription().latest("date_end").date_end,
"date_begin": invoice.get_subscription().earliest("date_start").date_start,
}
templatename = CotisationsOption.get_cached_value('voucher_template').template.name.split('/')[-1]
templatename = CotisationsOption.get_cached_value(
"voucher_template"
).template.name.split("/")[-1]
pdf = create_pdf(templatename, ctx)
template = get_template('cotisations/email_subscription_accepted')
template = get_template("cotisations/email_subscription_accepted")
ctx = {
'name': "{} {}".format(
invoice.user.name,
invoice.user.surname
),
'asso_email': AssoOption.get_cached_value('contact'),
'asso_name': AssoOption.get_cached_value('name'),
'date_end': invoice.get_subscription().latest('date_end').date_end,
"name": "{} {}".format(invoice.user.name, invoice.user.surname),
"asso_email": AssoOption.get_cached_value("contact"),
"asso_name": AssoOption.get_cached_value("name"),
"date_end": invoice.get_subscription().latest("date_end").date_end,
}
mail = EmailMessage(
'Votre reçu / Your voucher',
"Votre reçu / Your voucher",
template.render(ctx),
GeneralOption.get_cached_value('email_from'),
GeneralOption.get_cached_value("email_from"),
[invoice.user.get_mail],
attachments=[('voucher.pdf', pdf, 'application/pdf')]
attachments=[("voucher.pdf", pdf, "application/pdf")],
)
mail.send()

View file

@ -12,11 +12,9 @@ def check_no_balance(is_balance):
ValidationError: if such a Paiement exists.
"""
from .models import Paiement
if not is_balance:
return
p = Paiement.objects.filter(is_balance=True)
if len(p) > 0:
raise ValidationError(
_("There is already a payment method for user balance.")
)
raise ValidationError(_("There is already a payment method for user balance."))

File diff suppressed because it is too large Load diff

View file

@ -62,7 +62,7 @@ from preferences.models import RadiusOption
#: Serveur radius de test (pas la prod)
TEST_SERVER = bool(os.getenv('DBG_FREERADIUS', False))
TEST_SERVER = bool(os.getenv("DBG_FREERADIUS", False))
# Logging
@ -77,13 +77,13 @@ class RadiusdHandler(logging.Handler):
rad_sig = radiusd.L_INFO
else:
rad_sig = radiusd.L_DBG
radiusd.radlog(rad_sig, record.msg.encode('utf-8'))
radiusd.radlog(rad_sig, record.msg.encode("utf-8"))
# Initialisation d'un logger (pour logguer unifié)
logger = logging.getLogger('auth.py')
logger = logging.getLogger("auth.py")
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)s: [%(levelname)s] %(message)s')
formatter = logging.Formatter("%(name)s: [%(levelname)s] %(message)s")
handler = RadiusdHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)
@ -111,17 +111,16 @@ def radius_event(fun):
for (key, value) in auth_data or []:
# Beware: les valeurs scalaires sont entre guillemets
# Ex: Calling-Station-Id: "une_adresse_mac"
data[key] = value.replace('"', '')
data[key] = value.replace('"', "")
try:
# TODO s'assurer ici que les tuples renvoyés sont bien des
# (str,str) : rlm_python ne digère PAS les unicodes
return fun(data)
except Exception as err:
exc_type, exc_instance, exc_traceback = sys.exc_info()
formatted_traceback = ''.join(traceback.format_tb(
exc_traceback))
logger.error('Failed %r on data %r' % (err, auth_data))
logger.error('Function %r, Traceback : %r' % (fun, formatted_traceback))
formatted_traceback = "".join(traceback.format_tb(exc_traceback))
logger.error("Failed %r on data %r" % (err, auth_data))
logger.error("Function %r, Traceback : %r" % (fun, formatted_traceback))
return radiusd.RLM_MODULE_FAIL
return new_f
@ -131,9 +130,9 @@ def radius_event(fun):
def instantiate(*_):
"""Utile pour initialiser les connexions ldap une première fois (otherwise,
do nothing)"""
logger.info('Instantiation')
logger.info("Instantiation")
if TEST_SERVER:
logger.info(u'DBG_FREERADIUS is enabled')
logger.info(u"DBG_FREERADIUS is enabled")
@radius_event
@ -146,23 +145,19 @@ def authorize(data):
accept en authorize
"""
# Pour les requetes proxifiees, on split
nas = data.get('NAS-IP-Address', data.get('NAS-Identifier', None))
nas = data.get("NAS-IP-Address", data.get("NAS-Identifier", None))
nas_instance = find_nas_from_request(nas)
# Toutes les reuquètes non proxifiées
nas_type = None
if nas_instance:
nas_type = Nas.objects.filter(nas_type=nas_instance.machine_type).first()
if not nas_type or nas_type.port_access_mode == '802.1X':
user = data.get('User-Name', '').decode('utf-8', errors='replace')
user = user.split('@', 1)[0]
mac = data.get('Calling-Station-Id', '')
result, log, password = check_user_machine_and_register(
nas_type,
user,
mac
)
logger.info(log.encode('utf-8'))
logger.info(user.encode('utf-8'))
if not nas_type or nas_type.port_access_mode == "802.1X":
user = data.get("User-Name", "").decode("utf-8", errors="replace")
user = user.split("@", 1)[0]
mac = data.get("Calling-Station-Id", "")
result, log, password = check_user_machine_and_register(nas_type, user, mac)
logger.info(log.encode("utf-8"))
logger.info(user.encode("utf-8"))
if not result:
return radiusd.RLM_MODULE_REJECT
@ -170,19 +165,11 @@ def authorize(data):
return (
radiusd.RLM_MODULE_UPDATED,
(),
(
(str("NT-Password"), str(password)),
),
((str("NT-Password"), str(password)),),
)
else:
return (
radiusd.RLM_MODULE_UPDATED,
(),
(
("Auth-Type", "Accept"),
),
)
return (radiusd.RLM_MODULE_UPDATED, (), (("Auth-Type", "Accept"),))
@radius_event
@ -190,52 +177,49 @@ def post_auth(data):
""" Function called after the user is authenticated
"""
nas = data.get('NAS-IP-Address', data.get('NAS-Identifier', None))
nas = data.get("NAS-IP-Address", data.get("NAS-Identifier", None))
nas_instance = find_nas_from_request(nas)
# Toutes les reuquètes non proxifiées
if not nas_instance:
logger.info(u"Requete proxifiee, nas inconnu".encode('utf-8'))
logger.info(u"Requete proxifiee, nas inconnu".encode("utf-8"))
return radiusd.RLM_MODULE_OK
nas_type = Nas.objects.filter(nas_type=nas_instance.machine_type).first()
if not nas_type:
logger.info(
u"Type de nas non enregistre dans la bdd!".encode('utf-8')
)
logger.info(u"Type de nas non enregistre dans la bdd!".encode("utf-8"))
return radiusd.RLM_MODULE_OK
mac = data.get('Calling-Station-Id', None)
mac = data.get("Calling-Station-Id", None)
# Switch et bornes héritent de machine et peuvent avoir plusieurs
# interfaces filles
nas_machine = nas_instance.machine
# Si il s'agit d'un switch
if hasattr(nas_machine, 'switch'):
port = data.get('NAS-Port-Id', data.get('NAS-Port', None))
if hasattr(nas_machine, "switch"):
port = data.get("NAS-Port-Id", data.get("NAS-Port", None))
# Pour les infrastructures possédant des switchs Juniper :
# On vérifie si le switch fait partie d'un stack Juniper
instance_stack = nas_machine.switch.stack
if instance_stack:
# Si c'est le cas, on resélectionne le bon switch dans la stack
id_stack_member = port.split("-")[1].split('/')[0]
nas_machine = (Switch.objects
.filter(stack=instance_stack)
id_stack_member = port.split("-")[1].split("/")[0]
nas_machine = (
Switch.objects.filter(stack=instance_stack)
.filter(stack_member_id=id_stack_member)
.prefetch_related(
'interface_set__domain__extension'
.prefetch_related("interface_set__domain__extension")
.first()
)
.first())
# On récupère le numéro du port sur l'output de freeradius.
# La ligne suivante fonctionne pour cisco, HP et Juniper
port = port.split(".")[0].split('/')[-1][-2:]
port = port.split(".")[0].split("/")[-1][-2:]
out = decide_vlan_switch(nas_machine, nas_type, port, mac)
sw_name, room, reason, vlan_id, decision, attributes = out
if decision:
log_message = '(fil) %s -> %s [%s%s]' % (
log_message = "(fil) %s -> %s [%s%s]" % (
sw_name + u":" + port + u"/" + str(room),
mac,
vlan_id,
(reason and u': ' + reason).encode('utf-8')
(reason and u": " + reason).encode("utf-8"),
)
logger.info(log_message)
@ -245,23 +229,20 @@ def post_auth(data):
(
("Tunnel-Type", "VLAN"),
("Tunnel-Medium-Type", "IEEE-802"),
("Tunnel-Private-Group-Id", '%d' % int(vlan_id)),
) + tuple(attributes),
()
("Tunnel-Private-Group-Id", "%d" % int(vlan_id)),
)
+ tuple(attributes),
(),
)
else:
log_message = '(fil) %s -> %s [Reject:%s]' % (
log_message = "(fil) %s -> %s [Reject:%s]" % (
sw_name + u":" + port + u"/" + str(room),
mac,
(reason and u': ' + reason).encode('utf-8')
(reason and u": " + reason).encode("utf-8"),
)
logger.info(log_message)
return (
radiusd.RLM_MODULE_REJECT,
tuple(attributes),
()
)
return (radiusd.RLM_MODULE_REJECT, tuple(attributes), ())
else:
return radiusd.RLM_MODULE_OK
@ -282,13 +263,14 @@ def detach(_=None):
def find_nas_from_request(nas_id):
""" Get the nas object from its ID """
nas = (Interface.objects
.filter(
Q(domain=Domain.objects.filter(name=nas_id)) |
Q(ipv4=IpList.objects.filter(ipv4=nas_id))
nas = (
Interface.objects.filter(
Q(domain=Domain.objects.filter(name=nas_id))
| Q(ipv4=IpList.objects.filter(ipv4=nas_id))
)
.select_related("machine_type")
.select_related("machine__switch__stack")
)
.select_related('machine_type')
.select_related('machine__switch__stack'))
return nas.first()
@ -300,17 +282,18 @@ def check_user_machine_and_register(nas_type, username, mac_address):
interface = Interface.objects.filter(mac_address=mac_address).first()
user = User.objects.filter(pseudo__iexact=username).first()
if not user:
return (False, u"User inconnu", '')
return (False, u"User inconnu", "")
if not user.has_access():
return (False, u"Adherent non cotisant", '')
return (False, u"Adherent non cotisant", "")
if interface:
if interface.machine.user != user:
return (False,
u"Machine enregistree sur le compte d'un autre "
"user...",
'')
return (
False,
u"Machine enregistree sur le compte d'un autre " "user...",
"",
)
elif not interface.is_active:
return (False, u"Machine desactivee", '')
return (False, u"Machine desactivee", "")
elif not interface.ipv4:
interface.assign_ipv4()
return (True, u"Ok, Reassignation de l'ipv4", user.pwd_ntlm)
@ -320,19 +303,16 @@ def check_user_machine_and_register(nas_type, username, mac_address):
if nas_type.autocapture_mac:
result, reason = user.autoregister_machine(mac_address, nas_type)
if result:
return (True,
u'Access Ok, Capture de la mac...',
user.pwd_ntlm)
return (True, u"Access Ok, Capture de la mac...", user.pwd_ntlm)
else:
return (False, u'Erreur dans le register mac %s' % reason, '')
return (False, u"Erreur dans le register mac %s" % reason, "")
else:
return (False, u'Machine inconnue', '')
return (False, u"Machine inconnue", "")
else:
return (False, u"Machine inconnue", '')
return (False, u"Machine inconnue", "")
def decide_vlan_switch(nas_machine, nas_type, port_number,
mac_address):
def decide_vlan_switch(nas_machine, nas_type, port_number, mac_address):
"""Fonction de placement vlan pour un switch en radius filaire auth par
mac.
Plusieurs modes :
@ -373,32 +353,27 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
- Attributs supplémentaires (attribut:str, operateur:str, valeur:str)
"""
attributes_kwargs = {
'client_mac' : str(mac_address),
'switch_port' : str(port_number),
"client_mac": str(mac_address),
"switch_port": str(port_number),
}
# Get port from switch and port number
extra_log = ""
# Si le NAS est inconnu, on place sur le vlan defaut
if not nas_machine:
return (
'?',
u'Chambre inconnue',
u'Nas inconnu',
RadiusOption.get_cached_value('vlan_decision_ok').vlan_id,
"?",
u"Chambre inconnue",
u"Nas inconnu",
RadiusOption.get_cached_value("vlan_decision_ok").vlan_id,
True,
RadiusOption.get_attributes('ok_attributes', attributes_kwargs)
RadiusOption.get_attributes("ok_attributes", attributes_kwargs),
)
sw_name = str(getattr(nas_machine, 'short_name', str(nas_machine)))
sw_name = str(getattr(nas_machine, "short_name", str(nas_machine)))
switch = Switch.objects.filter(machine_ptr=nas_machine).first()
attributes_kwargs['switch_ip'] = str(switch.ipv4)
port = (Port.objects
.filter(
switch=switch,
port=port_number
)
.first())
attributes_kwargs["switch_ip"] = str(switch.ipv4)
port = Port.objects.filter(switch=switch, port=port_number).first()
# Si le port est inconnu, on place sur le vlan defaut
# Aucune information particulière ne permet de déterminer quelle
@ -407,10 +382,12 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
return (
sw_name,
"Port inconnu",
u'Port inconnu',
getattr(RadiusOption.get_cached_value('unknown_port_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('unknown_port')!= RadiusOption.REJECT,
RadiusOption.get_attributes('unknown_port_attributes', attributes_kwargs)
u"Port inconnu",
getattr(
RadiusOption.get_cached_value("unknown_port_vlan"), "vlan_id", None
),
RadiusOption.get_cached_value("unknown_port") != RadiusOption.REJECT,
RadiusOption.get_attributes("unknown_port_attributes", attributes_kwargs),
)
# On récupère le profil du port
@ -423,35 +400,36 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
extra_log = u"Force sur vlan " + str(DECISION_VLAN)
attributes = ()
else:
DECISION_VLAN = RadiusOption.get_cached_value('vlan_decision_ok').vlan_id
attributes = RadiusOption.get_attributes('ok_attributes', attributes_kwargs)
DECISION_VLAN = RadiusOption.get_cached_value("vlan_decision_ok").vlan_id
attributes = RadiusOption.get_attributes("ok_attributes", attributes_kwargs)
# Si le port est désactivé, on rejette la connexion
if not port.state:
return (sw_name, port.room, u'Port desactive', None, False, ())
return (sw_name, port.room, u"Port desactive", None, False, ())
# Si radius est désactivé, on laisse passer
if port_profile.radius_type == 'NO':
return (sw_name,
if port_profile.radius_type == "NO":
return (
sw_name,
"",
u"Pas d'authentification sur ce port" + extra_log,
DECISION_VLAN,
True,
attributes
attributes,
)
# Si le 802.1X est activé sur ce port, cela veut dire que la personne a
# été accept précédemment
# Par conséquent, on laisse passer sur le bon vlan
if (nas_type.port_access_mode, port_profile.radius_type) == ('802.1X', '802.1X'):
if (nas_type.port_access_mode, port_profile.radius_type) == ("802.1X", "802.1X"):
room = port.room or "Chambre/local inconnu"
return (
sw_name,
room,
u'Acceptation authentification 802.1X',
u"Acceptation authentification 802.1X",
DECISION_VLAN,
True,
attributes
attributes,
)
# Sinon, cela veut dire qu'on fait de l'auth radius par mac
@ -460,16 +438,20 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
# (anti squattage)
# Il n'est pas possible de se connecter sur une prise strict sans adhérent
# à jour de cotis dedans
if port_profile.radius_mode == 'STRICT':
if port_profile.radius_mode == "STRICT":
room = port.room
if not room:
return (
sw_name,
"Inconnue",
u'Chambre inconnue',
getattr(RadiusOption.get_cached_value('unknown_room_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('unknown_room')!= RadiusOption.REJECT,
RadiusOption.get_attributes('unknown_room_attributes', attributes_kwargs),
u"Chambre inconnue",
getattr(
RadiusOption.get_cached_value("unknown_room_vlan"), "vlan_id", None
),
RadiusOption.get_cached_value("unknown_room") != RadiusOption.REJECT,
RadiusOption.get_attributes(
"unknown_room_attributes", attributes_kwargs
),
)
room_user = User.objects.filter(
@ -479,41 +461,52 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
return (
sw_name,
room,
u'Chambre non cotisante',
getattr(RadiusOption.get_cached_value('non_member_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('non_member')!= RadiusOption.REJECT,
RadiusOption.get_attributes('non_member_attributes', attributes_kwargs),
u"Chambre non cotisante",
getattr(
RadiusOption.get_cached_value("non_member_vlan"), "vlan_id", None
),
RadiusOption.get_cached_value("non_member") != RadiusOption.REJECT,
RadiusOption.get_attributes("non_member_attributes", attributes_kwargs),
)
for user in room_user:
if user.is_ban() or user.state != User.STATE_ACTIVE:
return (
sw_name,
room,
u'Utilisateur banni ou desactive',
getattr(RadiusOption.get_cached_value('banned_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('banned')!= RadiusOption.REJECT,
RadiusOption.get_attributes('banned_attributes', attributes_kwargs),
u"Utilisateur banni ou desactive",
getattr(
RadiusOption.get_cached_value("banned_vlan"), "vlan_id", None
),
RadiusOption.get_cached_value("banned") != RadiusOption.REJECT,
RadiusOption.get_attributes("banned_attributes", attributes_kwargs),
)
elif not (user.is_connected() or user.is_whitelisted()):
return (
sw_name,
room,
u'Utilisateur non cotisant',
getattr(RadiusOption.get_cached_value('non_member_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('non_member')!= RadiusOption.REJECT,
RadiusOption.get_attributes('non_member_attributes', attributes_kwargs),
u"Utilisateur non cotisant",
getattr(
RadiusOption.get_cached_value("non_member_vlan"),
"vlan_id",
None,
),
RadiusOption.get_cached_value("non_member") != RadiusOption.REJECT,
RadiusOption.get_attributes(
"non_member_attributes", attributes_kwargs
),
)
# else: user OK, on passe à la verif MAC
# Si on fait de l'auth par mac, on cherche l'interface
# via sa mac dans la bdd
if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT':
if port_profile.radius_mode == "COMMON" or port_profile.radius_mode == "STRICT":
# Authentification par mac
interface = (Interface.objects
.filter(mac_address=mac_address)
.select_related('machine__user')
.select_related('ipv4')
.first())
interface = (
Interface.objects.filter(mac_address=mac_address)
.select_related("machine__user")
.select_related("ipv4")
.first()
)
if not interface:
room = port.room
# On essaye de register la mac, si l'autocapture a été activée,
@ -522,10 +515,17 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
return (
sw_name,
room,
u'Machine Inconnue',
getattr(RadiusOption.get_cached_value('unknown_machine_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('unknown_machine')!= RadiusOption.REJECT,
RadiusOption.get_attributes('unknown_machine_attributes', attributes_kwargs),
u"Machine Inconnue",
getattr(
RadiusOption.get_cached_value("unknown_machine_vlan"),
"vlan_id",
None,
),
RadiusOption.get_cached_value("unknown_machine")
!= RadiusOption.REJECT,
RadiusOption.get_attributes(
"unknown_machine_attributes", attributes_kwargs
),
)
# Sinon on bascule sur la politique définie dans les options
# radius.
@ -533,10 +533,17 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
return (
sw_name,
"",
u'Machine inconnue',
getattr(RadiusOption.get_cached_value('unknown_machine_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('unknown_machine')!= RadiusOption.REJECT,
RadiusOption.get_attributes('unknown_machine_attributes', attributes_kwargs),
u"Machine inconnue",
getattr(
RadiusOption.get_cached_value("unknown_machine_vlan"),
"vlan_id",
None,
),
RadiusOption.get_cached_value("unknown_machine")
!= RadiusOption.REJECT,
RadiusOption.get_attributes(
"unknown_machine_attributes", attributes_kwargs
),
)
# L'interface a été trouvée, on vérifie qu'elle est active,
@ -549,23 +556,31 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
return (
sw_name,
room,
u'Adherent banni',
getattr(RadiusOption.get_cached_value('banned_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('banned')!= RadiusOption.REJECT,
RadiusOption.get_attributes('banned_attributes', attributes_kwargs),
u"Adherent banni",
getattr(
RadiusOption.get_cached_value("banned_vlan"), "vlan_id", None
),
RadiusOption.get_cached_value("banned") != RadiusOption.REJECT,
RadiusOption.get_attributes("banned_attributes", attributes_kwargs),
)
if not interface.is_active:
return (
sw_name,
room,
u'Machine non active / adherent non cotisant',
getattr(RadiusOption.get_cached_value('non_member_vlan'), 'vlan_id', None),
RadiusOption.get_cached_value('non_member')!= RadiusOption.REJECT,
RadiusOption.get_attributes('non_member_attributes', attributes_kwargs),
u"Machine non active / adherent non cotisant",
getattr(
RadiusOption.get_cached_value("non_member_vlan"),
"vlan_id",
None,
),
RadiusOption.get_cached_value("non_member") != RadiusOption.REJECT,
RadiusOption.get_attributes(
"non_member_attributes", attributes_kwargs
),
)
# Si on choisi de placer les machines sur le vlan
# correspondant à leur type :
if RadiusOption.get_cached_value('radius_general_policy') == 'MACHINE':
if RadiusOption.get_cached_value("radius_general_policy") == "MACHINE":
DECISION_VLAN = interface.machine_type.ip_type.vlan.vlan_id
if not interface.ipv4:
interface.assign_ipv4()
@ -575,14 +590,14 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
u"Ok, Reassignation de l'ipv4" + extra_log,
DECISION_VLAN,
True,
attributes
attributes,
)
else:
return (
sw_name,
room,
u'Machine OK' + extra_log,
u"Machine OK" + extra_log,
DECISION_VLAN,
True,
attributes
attributes,
)

View file

@ -38,11 +38,9 @@ def can_view(user):
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_module_perms('admin')
can = user.has_module_perms("admin")
return (
can,
None if can else _("You don't have the right to view this"
" application."),
'admin'
None if can else _("You don't have the right to view this" " application."),
"admin",
)

View file

@ -34,12 +34,14 @@ def classname(obj):
""" Returns the object class name """
return obj.__class__.__name__
@register.filter
def is_facture(baseinvoice):
"""Returns True if a baseinvoice has a `Facture` child."""
return hasattr(baseinvoice, 'facture')
return hasattr(baseinvoice, "facture")
@register.inclusion_tag('buttons/history.html')
@register.inclusion_tag("buttons/history.html")
def history_button(instance, text=False, html_class=True):
"""Creates the correct history button for an instance.
@ -51,9 +53,9 @@ def history_button(instance, text=False, html_class=True):
"""
return {
'application': instance._meta.app_label,
'name': instance._meta.model_name,
'id': instance.id,
'text': text,
'class': html_class,
"application": instance._meta.app_label,
"name": instance._meta.model_name,
"id": instance.id,
"text": text,
"class": html_class,
}

View file

@ -30,18 +30,20 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^stats_logs$', views.stats_logs, name='stats-logs'),
url(r'^revert_action/(?P<revision_id>[0-9]+)$',
views.revert_action,
name='revert-action'),
url(r'^stats_general/$', views.stats_general, name='stats-general'),
url(r'^stats_models/$', views.stats_models, name='stats-models'),
url(r'^stats_users/$', views.stats_users, name='stats-users'),
url(r'^stats_actions/$', views.stats_actions, name='stats-actions'),
url(r"^$", views.index, name="index"),
url(r"^stats_logs$", views.stats_logs, name="stats-logs"),
url(
r'(?P<application>\w+)/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$',
r"^revert_action/(?P<revision_id>[0-9]+)$",
views.revert_action,
name="revert-action",
),
url(r"^stats_general/$", views.stats_general, name="stats-general"),
url(r"^stats_models/$", views.stats_models, name="stats-models"),
url(r"^stats_users/$", views.stats_users, name="stats-users"),
url(r"^stats_actions/$", views.stats_actions, name="stats-actions"),
url(
r"(?P<application>\w+)/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$",
views.history,
name='history',
name="history",
),
]

View file

@ -60,16 +60,9 @@ from users.models import (
Ban,
Whitelist,
Adherent,
Club
)
from cotisations.models import (
Facture,
Vente,
Article,
Banque,
Paiement,
Cotisation
Club,
)
from cotisations.models import Facture, Vente, Article, Banque, Paiement, Cotisation
from machines.models import (
Machine,
MachineType,
@ -84,7 +77,7 @@ from machines.models import (
Nas,
SOA,
Mx,
Ns
Ns,
)
from topologie.models import (
Switch,
@ -93,7 +86,7 @@ from topologie.models import (
Stack,
ModelSwitch,
ConstructorSwitch,
AccessPoint
AccessPoint,
)
from preferences.models import GeneralOption
from re2o.views import form
@ -105,36 +98,24 @@ from re2o.utils import (
all_active_assigned_interfaces_count,
all_active_interfaces_count,
)
from re2o.base import (
re2o_paginator,
SortTable
)
from re2o.acl import (
can_view_all,
can_view_app,
can_edit_history,
)
from re2o.base import re2o_paginator, SortTable
from re2o.acl import can_view_all, can_view_app, can_edit_history
@login_required
@can_view_app('logs')
@can_view_app("logs")
def index(request):
"""Affiche les logs affinés, date reformatées, selectionne
les event importants (ajout de droits, ajout de ban/whitelist)"""
pagination_number = GeneralOption.get_cached_value('pagination_number')
pagination_number = GeneralOption.get_cached_value("pagination_number")
# The types of content kept for display
content_type_filter = ['ban', 'whitelist', 'vente', 'interface', 'user']
content_type_filter = ["ban", "whitelist", "vente", "interface", "user"]
# Select only wanted versions
versions = Version.objects.filter(
content_type__in=ContentType.objects.filter(
model__in=content_type_filter
)
).select_related('revision')
content_type__in=ContentType.objects.filter(model__in=content_type_filter)
).select_related("revision")
versions = SortTable.sort(
versions,
request.GET.get('col'),
request.GET.get('order'),
SortTable.LOGS_INDEX
versions, request.GET.get("col"), request.GET.get("order"), SortTable.LOGS_INDEX
)
versions = re2o_paginator(request, versions, pagination_number)
# Force to have a list instead of QuerySet
@ -146,20 +127,21 @@ def index(request):
if versions.object_list[i].object:
version = versions.object_list[i]
versions.object_list[i] = {
'rev_id': version.revision.id,
'comment': version.revision.comment,
'datetime': version.revision.date_created,
'username':
version.revision.user.get_username()
if version.revision.user else '?',
'user_id': version.revision.user_id,
'version': version}
"rev_id": version.revision.id,
"comment": version.revision.comment,
"datetime": version.revision.date_created,
"username": version.revision.user.get_username()
if version.revision.user
else "?",
"user_id": version.revision.user_id,
"version": version,
}
else:
to_remove.insert(0, i)
# Remove all tagged invalid items
for i in to_remove:
versions.object_list.pop(i)
return render(request, 'logs/index.html', {'versions_list': versions})
return render(request, "logs/index.html", {"versions_list": versions})
@login_required
@ -167,19 +149,20 @@ def index(request):
def stats_logs(request):
"""Affiche l'ensemble des logs et des modifications sur les objets,
classés par date croissante, en vrac"""
pagination_number = GeneralOption.get_cached_value('pagination_number')
revisions = Revision.objects.all().select_related('user')\
.prefetch_related('version_set__object')
pagination_number = GeneralOption.get_cached_value("pagination_number")
revisions = (
Revision.objects.all()
.select_related("user")
.prefetch_related("version_set__object")
)
revisions = SortTable.sort(
revisions,
request.GET.get('col'),
request.GET.get('order'),
SortTable.LOGS_STATS_LOGS
request.GET.get("col"),
request.GET.get("order"),
SortTable.LOGS_STATS_LOGS,
)
revisions = re2o_paginator(request, revisions, pagination_number)
return render(request, 'logs/stats_logs.html', {
'revisions_list': revisions
})
return render(request, "logs/stats_logs.html", {"revisions_list": revisions})
@login_required
@ -193,11 +176,12 @@ def revert_action(request, revision_id):
if request.method == "POST":
revision.revert()
messages.success(request, _("The action was deleted."))
return redirect(reverse('logs:index'))
return form({
'objet': revision,
'objet_name': revision.__class__.__name__
}, 'logs/delete.html', request)
return redirect(reverse("logs:index"))
return form(
{"objet": revision, "objet_name": revision.__class__.__name__},
"logs/delete.html",
request,
)
@login_required
@ -207,115 +191,128 @@ def stats_general(request):
range, et les statistiques générales sur les users : users actifs,
cotisants, activés, archivés, etc"""
ip_dict = dict()
for ip_range in IpType.objects.select_related('vlan').all():
for ip_range in IpType.objects.select_related("vlan").all():
all_ip = IpList.objects.filter(ip_type=ip_range)
used_ip = Interface.objects.filter(ipv4__in=all_ip).count()
active_ip = all_active_assigned_interfaces_count().filter(
ipv4__in=IpList.objects.filter(ip_type=ip_range)
).count()
ip_dict[ip_range] = [ip_range, ip_range.vlan, all_ip.count(),
used_ip, active_ip, all_ip.count()-used_ip]
active_ip = (
all_active_assigned_interfaces_count()
.filter(ipv4__in=IpList.objects.filter(ip_type=ip_range))
.count()
)
ip_dict[ip_range] = [
ip_range,
ip_range.vlan,
all_ip.count(),
used_ip,
active_ip,
all_ip.count() - used_ip,
]
_all_adherent = all_adherent(including_asso=False)
_all_has_access = all_has_access(including_asso=False)
_all_baned = all_baned()
_all_whitelisted = all_whitelisted()
_all_active_interfaces_count = all_active_interfaces_count()
_all_active_assigned_interfaces_count = \
all_active_assigned_interfaces_count()
_all_active_assigned_interfaces_count = all_active_assigned_interfaces_count()
stats = [
[ # First set of data (about users)
[ # Headers
_("Category"),
_("Number of users (members and clubs)"),
_("Number of members"),
_("Number of clubs")
_("Number of clubs"),
],
{ # Data
'active_users': [
"active_users": [
_("Activated users"),
User.objects.filter(state=User.STATE_ACTIVE).count(),
(Adherent.objects
.filter(state=Adherent.STATE_ACTIVE)
.count()),
Club.objects.filter(state=Club.STATE_ACTIVE).count()
(Adherent.objects.filter(state=Adherent.STATE_ACTIVE).count()),
Club.objects.filter(state=Club.STATE_ACTIVE).count(),
],
'inactive_users': [
"inactive_users": [
_("Disabled users"),
User.objects.filter(state=User.STATE_DISABLED).count(),
(Adherent.objects
.filter(state=Adherent.STATE_DISABLED)
.count()),
Club.objects.filter(state=Club.STATE_DISABLED).count()
(Adherent.objects.filter(state=Adherent.STATE_DISABLED).count()),
Club.objects.filter(state=Club.STATE_DISABLED).count(),
],
'archive_users': [
"archive_users": [
_("Archived users"),
User.objects.filter(state=User.STATE_ARCHIVE).count(),
(Adherent.objects
.filter(state=Adherent.STATE_ARCHIVE)
.count()),
Club.objects.filter(state=Club.STATE_ARCHIVE).count()
(Adherent.objects.filter(state=Adherent.STATE_ARCHIVE).count()),
Club.objects.filter(state=Club.STATE_ARCHIVE).count(),
],
'full_archive_users': [
"full_archive_users": [
_("Full Archived users"),
User.objects.filter(state=User.STATE_FULL_ARCHIVE).count(),
(Adherent.objects
.filter(state=Adherent.STATE_FULL_ARCHIVE)
.count()),
Club.objects.filter(state=Club.STATE_FULL_ARCHIVE).count()
(
Adherent.objects.filter(
state=Adherent.STATE_FULL_ARCHIVE
).count()
),
Club.objects.filter(state=Club.STATE_FULL_ARCHIVE).count(),
],
'not_active_users': [
"not_active_users": [
_("Not yet active users"),
User.objects.filter(state=User.STATE_NOT_YET_ACTIVE).count(),
(Adherent.objects
.filter(state=Adherent.STATE_NOT_YET_ACTIVE)
.count()),
Club.objects.filter(state=Club.STATE_NOT_YET_ACTIVE).count()
(
Adherent.objects.filter(
state=Adherent.STATE_NOT_YET_ACTIVE
).count()
),
Club.objects.filter(state=Club.STATE_NOT_YET_ACTIVE).count(),
],
'adherent_users': [
"adherent_users": [
_("Contributing members"),
_all_adherent.count(),
_all_adherent.exclude(adherent__isnull=True).count(),
_all_adherent.exclude(club__isnull=True).count()
_all_adherent.exclude(club__isnull=True).count(),
],
'connexion_users': [
"connexion_users": [
_("Users benefiting from a connection"),
_all_has_access.count(),
_all_has_access.exclude(adherent__isnull=True).count(),
_all_has_access.exclude(club__isnull=True).count()
_all_has_access.exclude(club__isnull=True).count(),
],
'ban_users': [
"ban_users": [
_("Banned users"),
_all_baned.count(),
_all_baned.exclude(adherent__isnull=True).count(),
_all_baned.exclude(club__isnull=True).count()
_all_baned.exclude(club__isnull=True).count(),
],
'whitelisted_user': [
"whitelisted_user": [
_("Users benefiting from a free connection"),
_all_whitelisted.count(),
_all_whitelisted.exclude(adherent__isnull=True).count(),
_all_whitelisted.exclude(club__isnull=True).count()
_all_whitelisted.exclude(club__isnull=True).count(),
],
'actives_interfaces': [
"actives_interfaces": [
_("Active interfaces (with access to the network)"),
_all_active_interfaces_count.count(),
(_all_active_interfaces_count
.exclude(machine__user__adherent__isnull=True)
.count()),
(_all_active_interfaces_count
.exclude(machine__user__club__isnull=True)
.count())
(
_all_active_interfaces_count.exclude(
machine__user__adherent__isnull=True
).count()
),
(
_all_active_interfaces_count.exclude(
machine__user__club__isnull=True
).count()
),
],
'actives_assigned_interfaces': [
"actives_assigned_interfaces": [
_("Active interfaces assigned IPv4"),
_all_active_assigned_interfaces_count.count(),
(_all_active_assigned_interfaces_count
.exclude(machine__user__adherent__isnull=True)
.count()),
(_all_active_assigned_interfaces_count
.exclude(machine__user__club__isnull=True)
.count())
]
}
(
_all_active_assigned_interfaces_count.exclude(
machine__user__adherent__isnull=True
).count()
),
(
_all_active_assigned_interfaces_count.exclude(
machine__user__club__isnull=True
).count()
),
],
},
],
[ # Second set of data (about ip adresses)
[ # Headers
@ -324,109 +321,91 @@ def stats_general(request):
_("Total number of IP addresses"),
_("Number of assigned IP addresses"),
_("Number of IP address assigned to an activated machine"),
_("Number of nonassigned IP addresses")
_("Number of nonassigned IP addresses"),
],
ip_dict, # Data already prepared
],
ip_dict # Data already prepared
]
]
return render(request, 'logs/stats_general.html', {'stats_list': stats})
return render(request, "logs/stats_general.html", {"stats_list": stats})
@login_required
@can_view_app('users', 'cotisations', 'machines', 'topologie')
@can_view_app("users", "cotisations", "machines", "topologie")
def stats_models(request):
"""Statistiques générales, affiche les comptages par models:
nombre d'users, d'écoles, de droits, de bannissements,
de factures, de ventes, de banque, de machines, etc"""
stats = {
_("Users"): {
'users': [User._meta.verbose_name, User.objects.count()],
'adherents': [Adherent._meta.verbose_name, Adherent.objects.count()],
'clubs': [Club._meta.verbose_name, Club.objects.count()],
'serviceuser': [ServiceUser._meta.verbose_name,
ServiceUser.objects.count()],
'school': [School._meta.verbose_name, School.objects.count()],
'listright': [ListRight._meta.verbose_name, ListRight.objects.count()],
'listshell': [ListShell._meta.verbose_name, ListShell.objects.count()],
'ban': [Ban._meta.verbose_name, Ban.objects.count()],
'whitelist': [Whitelist._meta.verbose_name, Whitelist.objects.count()]
"users": [User._meta.verbose_name, User.objects.count()],
"adherents": [Adherent._meta.verbose_name, Adherent.objects.count()],
"clubs": [Club._meta.verbose_name, Club.objects.count()],
"serviceuser": [
ServiceUser._meta.verbose_name,
ServiceUser.objects.count(),
],
"school": [School._meta.verbose_name, School.objects.count()],
"listright": [ListRight._meta.verbose_name, ListRight.objects.count()],
"listshell": [ListShell._meta.verbose_name, ListShell.objects.count()],
"ban": [Ban._meta.verbose_name, Ban.objects.count()],
"whitelist": [Whitelist._meta.verbose_name, Whitelist.objects.count()],
},
_("Subscriptions"): {
'factures': [
Facture._meta.verbose_name,
Facture.objects.count()
],
'vente': [
Vente._meta.verbose_name,
Vente.objects.count()
],
'cotisation': [
Cotisation._meta.verbose_name,
Cotisation.objects.count()
],
'article': [
Article._meta.verbose_name,
Article.objects.count()
],
'banque': [
Banque._meta.verbose_name,
Banque.objects.count()
],
"factures": [Facture._meta.verbose_name, Facture.objects.count()],
"vente": [Vente._meta.verbose_name, Vente.objects.count()],
"cotisation": [Cotisation._meta.verbose_name, Cotisation.objects.count()],
"article": [Article._meta.verbose_name, Article.objects.count()],
"banque": [Banque._meta.verbose_name, Banque.objects.count()],
},
_("Machines"): {
'machine': [Machine._meta.verbose_name,
Machine.objects.count()],
'typemachine': [MachineType._meta.verbose_name,
MachineType.objects.count()],
'typeip': [IpType._meta.verbose_name,
IpType.objects.count()],
'extension': [Extension._meta.verbose_name,
Extension.objects.count()],
'interface': [Interface._meta.verbose_name,
Interface.objects.count()],
'alias': [Domain._meta.verbose_name,
Domain.objects.exclude(cname=None).count()],
'iplist': [IpList._meta.verbose_name,
IpList.objects.count()],
'service': [Service._meta.verbose_name,
Service.objects.count()],
'ouvertureportlist': [
OuverturePortList._meta.verbose_name,
OuverturePortList.objects.count()
"machine": [Machine._meta.verbose_name, Machine.objects.count()],
"typemachine": [
MachineType._meta.verbose_name,
MachineType.objects.count(),
],
'vlan': [Vlan._meta.verbose_name, Vlan.objects.count()],
'SOA': [SOA._meta.verbose_name, SOA.objects.count()],
'Mx': [Mx._meta.verbose_name, Mx.objects.count()],
'Ns': [Ns._meta.verbose_name, Ns.objects.count()],
'nas': [Nas._meta.verbose_name, Nas.objects.count()],
"typeip": [IpType._meta.verbose_name, IpType.objects.count()],
"extension": [Extension._meta.verbose_name, Extension.objects.count()],
"interface": [Interface._meta.verbose_name, Interface.objects.count()],
"alias": [
Domain._meta.verbose_name,
Domain.objects.exclude(cname=None).count(),
],
"iplist": [IpList._meta.verbose_name, IpList.objects.count()],
"service": [Service._meta.verbose_name, Service.objects.count()],
"ouvertureportlist": [
OuverturePortList._meta.verbose_name,
OuverturePortList.objects.count(),
],
"vlan": [Vlan._meta.verbose_name, Vlan.objects.count()],
"SOA": [SOA._meta.verbose_name, SOA.objects.count()],
"Mx": [Mx._meta.verbose_name, Mx.objects.count()],
"Ns": [Ns._meta.verbose_name, Ns.objects.count()],
"nas": [Nas._meta.verbose_name, Nas.objects.count()],
},
_("Topology"): {
'switch': [Switch._meta.verbose_name,
Switch.objects.count()],
'bornes': [AccessPoint._meta.verbose_name,
AccessPoint.objects.count()],
'port': [Port._meta.verbose_name, Port.objects.count()],
'chambre': [Room._meta.verbose_name, Room.objects.count()],
'stack': [Stack._meta.verbose_name, Stack.objects.count()],
'modelswitch': [
"switch": [Switch._meta.verbose_name, Switch.objects.count()],
"bornes": [AccessPoint._meta.verbose_name, AccessPoint.objects.count()],
"port": [Port._meta.verbose_name, Port.objects.count()],
"chambre": [Room._meta.verbose_name, Room.objects.count()],
"stack": [Stack._meta.verbose_name, Stack.objects.count()],
"modelswitch": [
ModelSwitch._meta.verbose_name,
ModelSwitch.objects.count()
ModelSwitch.objects.count(),
],
'constructorswitch': [
"constructorswitch": [
ConstructorSwitch._meta.verbose_name,
ConstructorSwitch.objects.count()
ConstructorSwitch.objects.count(),
],
},
_("Actions performed"):
{
'revision': [_("Number of actions"), Revision.objects.count()],
_("Actions performed"): {
"revision": [_("Number of actions"), Revision.objects.count()]
},
}
return render(request, 'logs/stats_models.html', {'stats_list': stats})
return render(request, "logs/stats_models.html", {"stats_list": stats})
@login_required
@can_view_app('users')
@can_view_app("users")
def stats_users(request):
"""Affiche les statistiques base de données aggrégées par user :
nombre de machines par user, d'etablissements par user,
@ -434,55 +413,51 @@ def stats_users(request):
de bannissement par user, etc"""
stats = {
_("User"): {
_("Machines"): User.objects.annotate(
num=Count('machine')
).order_by('-num')[:10],
_("Invoice"): User.objects.annotate(
num=Count('facture')
).order_by('-num')[:10],
_("Ban"): User.objects.annotate(
num=Count('ban')
).order_by('-num')[:10],
_("Whitelist"): User.objects.annotate(
num=Count('whitelist')
).order_by('-num')[:10],
_("Rights"): User.objects.annotate(
num=Count('groups')
).order_by('-num')[:10],
_("Machines"): User.objects.annotate(num=Count("machine")).order_by("-num")[
:10
],
_("Invoice"): User.objects.annotate(num=Count("facture")).order_by("-num")[
:10
],
_("Ban"): User.objects.annotate(num=Count("ban")).order_by("-num")[:10],
_("Whitelist"): User.objects.annotate(num=Count("whitelist")).order_by(
"-num"
)[:10],
_("Rights"): User.objects.annotate(num=Count("groups")).order_by("-num")[
:10
],
},
_("School"): {
_("User"): School.objects.annotate(
num=Count('user')
).order_by('-num')[:10],
_("User"): School.objects.annotate(num=Count("user")).order_by("-num")[:10]
},
_("Payment method"): {
_("User"): Paiement.objects.annotate(
num=Count('facture')
).order_by('-num')[:10],
_("User"): Paiement.objects.annotate(num=Count("facture")).order_by("-num")[
:10
]
},
_("Bank"): {
_("User"): Banque.objects.annotate(
num=Count('facture')
).order_by('-num')[:10],
_("User"): Banque.objects.annotate(num=Count("facture")).order_by("-num")[
:10
]
},
}
return render(request, 'logs/stats_users.html', {'stats_list': stats})
return render(request, "logs/stats_users.html", {"stats_list": stats})
@login_required
@can_view_app('users')
@can_view_app("users")
def stats_actions(request):
"""Vue qui affiche les statistiques de modifications d'objets par
utilisateurs.
Affiche le nombre de modifications aggrégées par utilisateurs"""
stats = {
_("User"): {
_("Action"): User.objects.annotate(
num=Count('revision')
).order_by('-num')[:40],
},
_("Action"): User.objects.annotate(num=Count("revision")).order_by("-num")[
:40
]
}
return render(request, 'logs/stats_users.html', {'stats_list': stats})
}
return render(request, "logs/stats_users.html", {"stats_list": stats})
def history(request, application, object_name, object_id):
@ -509,33 +484,29 @@ def history(request, application, object_name, object_id):
model = apps.get_model(application, object_name)
except LookupError:
raise Http404(_("No model found."))
object_name_id = object_name + 'id'
object_name_id = object_name + "id"
kwargs = {object_name_id: object_id}
try:
instance = model.get_instance(**kwargs)
except model.DoesNotExist:
messages.error(request, _("Nonexistent entry."))
return redirect(reverse(
'users:profil',
kwargs={'userid': str(request.user.id)}
))
return redirect(
reverse("users:profil", kwargs={"userid": str(request.user.id)})
)
can, msg, _permissions = instance.can_view(request.user)
if not can:
messages.error(request, msg or _("You don't have the right to access this menu."))
return redirect(reverse(
'users:profil',
kwargs={'userid': str(request.user.id)}
))
pagination_number = GeneralOption.get_cached_value('pagination_number')
messages.error(
request, msg or _("You don't have the right to access this menu.")
)
return redirect(
reverse("users:profil", kwargs={"userid": str(request.user.id)})
)
pagination_number = GeneralOption.get_cached_value("pagination_number")
reversions = Version.objects.get_for_object(instance)
if hasattr(instance, 'linked_objects'):
if hasattr(instance, "linked_objects"):
for related_object in chain(instance.linked_objects()):
reversions = (reversions |
Version.objects.get_for_object(related_object))
reversions = reversions | Version.objects.get_for_object(related_object)
reversions = re2o_paginator(request, reversions, pagination_number)
return render(
request,
're2o/history.html',
{'reversions': reversions, 'object': instance}
request, "re2o/history.html", {"reversions": reversions, "object": instance}
)

View file

@ -38,11 +38,9 @@ def can_view(user):
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_module_perms('machines')
can = user.has_module_perms("machines")
return (
can,
None if can else _("You don't have the right to view this"
" application."),
('machines',)
None if can else _("You don't have the right to view this" " application."),
("machines",),
)

View file

@ -51,106 +51,127 @@ from .models import IpType, Machine, MachineType, Domain, IpList, Interface
class MachineAdmin(VersionAdmin):
""" Admin view of a Machine object """
pass
class Ipv6ListAdmin(VersionAdmin):
""" Admin view of a Ipv6List object """
pass
class IpTypeAdmin(VersionAdmin):
""" Admin view of a IpType object """
pass
class MachineTypeAdmin(VersionAdmin):
""" Admin view of a MachineType object """
pass
class VlanAdmin(VersionAdmin):
""" Admin view of a Vlan object """
pass
class ExtensionAdmin(VersionAdmin):
""" Admin view of a Extension object """
pass
class SOAAdmin(VersionAdmin):
""" Admin view of a SOA object """
pass
class MxAdmin(VersionAdmin):
""" Admin view of a MX object """
pass
class NsAdmin(VersionAdmin):
""" Admin view of a NS object """
pass
class TxtAdmin(VersionAdmin):
""" Admin view of a TXT object """
pass
class DNameAdmin(VersionAdmin):
""" Admin view of a DName object """
pass
class SrvAdmin(VersionAdmin):
""" Admin view of a SRV object """
pass
class SshFpAdmin(VersionAdmin):
""" Admin view of a SSHFP object """
pass
class NasAdmin(VersionAdmin):
""" Admin view of a Nas object """
pass
class IpListAdmin(VersionAdmin):
""" Admin view of a Ipv4List object """
pass
class OuverturePortAdmin(VersionAdmin):
""" Admin view of a OuverturePort object """
pass
class OuverturePortListAdmin(VersionAdmin):
""" Admin view of a OuverturePortList object """
pass
class InterfaceAdmin(VersionAdmin):
""" Admin view of a Interface object """
list_display = ('machine', 'machine_type', 'mac_address', 'ipv4', 'details')
list_display = ("machine", "machine_type", "mac_address", "ipv4", "details")
class DomainAdmin(VersionAdmin):
""" Admin view of a Domain object """
list_display = ('interface_parent', 'name', 'extension', 'cname')
list_display = ("interface_parent", "name", "extension", "cname")
class ServiceAdmin(VersionAdmin):
""" Admin view of a ServiceAdmin object """
list_display = ('service_type', 'min_time_regen', 'regular_time_regen')
list_display = ("service_type", "min_time_regen", "regular_time_regen")
class RoleAdmin(VersionAdmin):
""" Admin view of a RoleAdmin object """
pass

View file

@ -70,19 +70,19 @@ class EditMachineForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
class Meta:
model = Machine
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(EditMachineForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = _("Machine name")
self.fields["name"].label = _("Machine name")
class NewMachineForm(EditMachineForm):
"""Creation d'une machine, ne renseigne que le nom"""
class Meta(EditMachineForm.Meta):
fields = ['name']
fields = ["name"]
class EditInterfaceForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
@ -90,39 +90,38 @@ class EditInterfaceForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
class Meta:
model = Interface
fields = ['machine', 'machine_type', 'ipv4', 'mac_address', 'details']
fields = ["machine", "machine_type", "ipv4", "mac_address", "details"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
user = kwargs.get('user')
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
user = kwargs.get("user")
super(EditInterfaceForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['mac_address'].label = _("MAC address")
self.fields['machine_type'].label = _("Machine type")
self.fields['machine_type'].empty_label = _("Select a machine type")
self.fields["mac_address"].label = _("MAC address")
self.fields["machine_type"].label = _("Machine type")
self.fields["machine_type"].empty_label = _("Select a machine type")
if "ipv4" in self.fields:
self.fields['ipv4'].empty_label = _("Automatic IPv4 assignment")
self.fields['ipv4'].queryset = IpList.objects.filter(
interface__isnull=True
)
self.fields["ipv4"].empty_label = _("Automatic IPv4 assignment")
self.fields["ipv4"].queryset = IpList.objects.filter(interface__isnull=True)
can_use_all_iptype, _reason, _permissions = IpType.can_use_all(user)
if not can_use_all_iptype:
self.fields['ipv4'].queryset = IpList.objects.filter(
self.fields["ipv4"].queryset = IpList.objects.filter(
interface__isnull=True
).filter(ip_type__in=IpType.objects.filter(need_infra=False))
else:
self.fields['ipv4'].queryset = IpList.objects.filter(
self.fields["ipv4"].queryset = IpList.objects.filter(
interface__isnull=True
)
# Add it's own address
self.fields['ipv4'].queryset |= IpList.objects.filter(
self.fields["ipv4"].queryset |= IpList.objects.filter(
interface=self.instance
)
if "machine" in self.fields:
self.fields['machine'].queryset = Machine.objects.all() \
.select_related('user')
self.fields["machine"].queryset = Machine.objects.all().select_related(
"user"
)
can_use_all_machinetype, _reason, _permissions = MachineType.can_use_all(user)
if not can_use_all_machinetype:
self.fields['machine_type'].queryset = MachineType.objects.filter(
self.fields["machine_type"].queryset = MachineType.objects.filter(
ip_type__in=IpType.objects.filter(need_infra=False)
)
@ -132,7 +131,7 @@ class AddInterfaceForm(EditInterfaceForm):
affiche ou non l'ensemble des ip disponibles"""
class Meta(EditInterfaceForm.Meta):
fields = ['machine_type', 'ipv4', 'mac_address', 'details']
fields = ["machine_type", "ipv4", "mac_address", "details"]
class AliasForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
@ -140,15 +139,15 @@ class AliasForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
class Meta:
model = Domain
fields = ['name', 'extension', 'ttl']
fields = ["name", "extension", "ttl"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
user = kwargs['user']
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
user = kwargs["user"]
super(AliasForm, self).__init__(*args, prefix=prefix, **kwargs)
can_use_all, _reason, _permissions = Extension.can_use_all(user)
if not can_use_all:
self.fields['extension'].queryset = Extension.objects.filter(
self.fields["extension"].queryset = Extension.objects.filter(
need_infra=False
)
@ -158,30 +157,31 @@ class DomainForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
class Meta:
model = Domain
fields = ['name', 'ttl']
fields = ["name", "ttl"]
def __init__(self, *args, **kwargs):
if 'user' in kwargs:
user = kwargs['user']
initial = kwargs.get('initial', {})
initial['name'] = user.get_next_domain_name()
kwargs['initial'] = initial
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
if "user" in kwargs:
user = kwargs["user"]
initial = kwargs.get("initial", {})
initial["name"] = user.get_next_domain_name()
kwargs["initial"] = initial
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(DomainForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelAliasForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs objets alias"""
alias = forms.ModelMultipleChoiceField(
queryset=Domain.objects.all(),
label=_("Current aliases"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
interface = kwargs.pop('interface')
interface = kwargs.pop("interface")
super(DelAliasForm, self).__init__(*args, **kwargs)
self.fields['alias'].queryset = Domain.objects.filter(
self.fields["alias"].queryset = Domain.objects.filter(
cname__in=Domain.objects.filter(interface_parent=interface)
)
@ -191,30 +191,31 @@ class MachineTypeForm(FormRevMixin, ModelForm):
class Meta:
model = MachineType
fields = ['name', 'ip_type']
fields = ["name", "ip_type"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(MachineTypeForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = _("Machine type to add")
self.fields['ip_type'].label = _("Related IP type")
self.fields["name"].label = _("Machine type to add")
self.fields["ip_type"].label = _("Related IP type")
class DelMachineTypeForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs machinetype"""
machinetypes = forms.ModelMultipleChoiceField(
queryset=MachineType.objects.none(),
label=_("Current machine types"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelMachineTypeForm, self).__init__(*args, **kwargs)
if instances:
self.fields['machinetypes'].queryset = instances
self.fields["machinetypes"].queryset = instances
else:
self.fields['machinetypes'].queryset = MachineType.objects.all()
self.fields["machinetypes"].queryset = MachineType.objects.all()
class IpTypeForm(FormRevMixin, ModelForm):
@ -223,12 +224,12 @@ class IpTypeForm(FormRevMixin, ModelForm):
class Meta:
model = IpType
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(IpTypeForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = _("IP type to add")
self.fields["name"].label = _("IP type to add")
class EditIpTypeForm(IpTypeForm):
@ -236,27 +237,37 @@ class EditIpTypeForm(IpTypeForm):
synchroniser les objets iplist"""
class Meta(IpTypeForm.Meta):
fields = ['extension', 'name', 'need_infra', 'domaine_ip_network', 'domaine_ip_netmask',
'prefix_v6', 'prefix_v6_length',
'vlan', 'reverse_v4', 'reverse_v6',
'ouverture_ports']
fields = [
"extension",
"name",
"need_infra",
"domaine_ip_network",
"domaine_ip_netmask",
"prefix_v6",
"prefix_v6_length",
"vlan",
"reverse_v4",
"reverse_v6",
"ouverture_ports",
]
class DelIpTypeForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs iptype"""
iptypes = forms.ModelMultipleChoiceField(
queryset=IpType.objects.none(),
label=_("Current IP types"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelIpTypeForm, self).__init__(*args, **kwargs)
if instances:
self.fields['iptypes'].queryset = instances
self.fields["iptypes"].queryset = instances
else:
self.fields['iptypes'].queryset = IpType.objects.all()
self.fields["iptypes"].queryset = IpType.objects.all()
class ExtensionForm(FormRevMixin, ModelForm):
@ -264,33 +275,34 @@ class ExtensionForm(FormRevMixin, ModelForm):
class Meta:
model = Extension
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ExtensionForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = _("Extension to add")
self.fields['origin'].label = _("A record origin")
self.fields['origin_v6'].label = _("AAAA record origin")
self.fields['soa'].label = _("SOA record to use")
self.fields['dnssec'].label = _("Sign with DNSSEC")
self.fields["name"].label = _("Extension to add")
self.fields["origin"].label = _("A record origin")
self.fields["origin_v6"].label = _("AAAA record origin")
self.fields["soa"].label = _("SOA record to use")
self.fields["dnssec"].label = _("Sign with DNSSEC")
class DelExtensionForm(FormRevMixin, Form):
"""Suppression d'une ou plusieurs extensions"""
extensions = forms.ModelMultipleChoiceField(
queryset=Extension.objects.none(),
label=_("Current extensions"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelExtensionForm, self).__init__(*args, **kwargs)
if instances:
self.fields['extensions'].queryset = instances
self.fields["extensions"].queryset = instances
else:
self.fields['extensions'].queryset = Extension.objects.all()
self.fields["extensions"].queryset = Extension.objects.all()
class Ipv6ListForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
@ -298,10 +310,10 @@ class Ipv6ListForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
class Meta:
model = Ipv6List
fields = ['ipv6', 'slaac_ip']
fields = ["ipv6", "slaac_ip"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(Ipv6ListForm, self).__init__(*args, prefix=prefix, **kwargs)
@ -310,28 +322,29 @@ class SOAForm(FormRevMixin, ModelForm):
class Meta:
model = SOA
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(SOAForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelSOAForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs SOA"""
soa = forms.ModelMultipleChoiceField(
queryset=SOA.objects.none(),
label=_("Current SOA records"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelSOAForm, self).__init__(*args, **kwargs)
if instances:
self.fields['soa'].queryset = instances
self.fields["soa"].queryset = instances
else:
self.fields['soa'].queryset = SOA.objects.all()
self.fields["soa"].queryset = SOA.objects.all()
class MxForm(FormRevMixin, ModelForm):
@ -339,31 +352,32 @@ class MxForm(FormRevMixin, ModelForm):
class Meta:
model = Mx
fields = ['zone', 'priority', 'name', 'ttl']
fields = ["zone", "priority", "name", "ttl"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(MxForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].queryset = Domain.objects.exclude(
self.fields["name"].queryset = Domain.objects.exclude(
interface_parent=None
).select_related('extension')
).select_related("extension")
class DelMxForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs MX"""
mx = forms.ModelMultipleChoiceField(
queryset=Mx.objects.none(),
label=_("Current MX records"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelMxForm, self).__init__(*args, **kwargs)
if instances:
self.fields['mx'].queryset = instances
self.fields["mx"].queryset = instances
else:
self.fields['mx'].queryset = Mx.objects.all()
self.fields["mx"].queryset = Mx.objects.all()
class NsForm(FormRevMixin, ModelForm):
@ -373,31 +387,32 @@ class NsForm(FormRevMixin, ModelForm):
class Meta:
model = Ns
fields = ['zone', 'ns', 'ttl']
fields = ["zone", "ns", "ttl"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(NsForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['ns'].queryset = Domain.objects.exclude(
self.fields["ns"].queryset = Domain.objects.exclude(
interface_parent=None
).select_related('extension')
).select_related("extension")
class DelNsForm(FormRevMixin, Form):
"""Suppresion d'un ou plusieurs NS"""
ns = forms.ModelMultipleChoiceField(
queryset=Ns.objects.none(),
label=_("Current NS records"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelNsForm, self).__init__(*args, **kwargs)
if instances:
self.fields['ns'].queryset = instances
self.fields["ns"].queryset = instances
else:
self.fields['ns'].queryset = Ns.objects.all()
self.fields["ns"].queryset = Ns.objects.all()
class TxtForm(FormRevMixin, ModelForm):
@ -405,28 +420,29 @@ class TxtForm(FormRevMixin, ModelForm):
class Meta:
model = Txt
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(TxtForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelTxtForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs TXT"""
txt = forms.ModelMultipleChoiceField(
queryset=Txt.objects.none(),
label=_("Current TXT records"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelTxtForm, self).__init__(*args, **kwargs)
if instances:
self.fields['txt'].queryset = instances
self.fields["txt"].queryset = instances
else:
self.fields['txt'].queryset = Txt.objects.all()
self.fields["txt"].queryset = Txt.objects.all()
class DNameForm(FormRevMixin, ModelForm):
@ -434,28 +450,29 @@ class DNameForm(FormRevMixin, ModelForm):
class Meta:
model = DName
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(DNameForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelDNameForm(FormRevMixin, Form):
"""Delete a set of DNAME entries"""
dnames = forms.ModelMultipleChoiceField(
queryset=Txt.objects.none(),
label=_("Current DNAME records"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelDNameForm, self).__init__(*args, **kwargs)
if instances:
self.fields['dnames'].queryset = instances
self.fields["dnames"].queryset = instances
else:
self.fields['dnames'].queryset = DName.objects.all()
self.fields["dnames"].queryset = DName.objects.all()
class SrvForm(FormRevMixin, ModelForm):
@ -463,28 +480,29 @@ class SrvForm(FormRevMixin, ModelForm):
class Meta:
model = Srv
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(SrvForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelSrvForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs Srv"""
srv = forms.ModelMultipleChoiceField(
queryset=Srv.objects.none(),
label=_("Current SRV records"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelSrvForm, self).__init__(*args, **kwargs)
if instances:
self.fields['srv'].queryset = instances
self.fields["srv"].queryset = instances
else:
self.fields['srv'].queryset = Srv.objects.all()
self.fields["srv"].queryset = Srv.objects.all()
class NasForm(FormRevMixin, ModelForm):
@ -493,28 +511,29 @@ class NasForm(FormRevMixin, ModelForm):
class Meta:
model = Nas
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(NasForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelNasForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs nas"""
nas = forms.ModelMultipleChoiceField(
queryset=Nas.objects.none(),
label=_("Current NAS devices"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelNasForm, self).__init__(*args, **kwargs)
if instances:
self.fields['nas'].queryset = instances
self.fields["nas"].queryset = instances
else:
self.fields['nas'].queryset = Nas.objects.all()
self.fields["nas"].queryset = Nas.objects.all()
class RoleForm(FormRevMixin, ModelForm):
@ -522,32 +541,32 @@ class RoleForm(FormRevMixin, ModelForm):
class Meta:
model = Role
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(RoleForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['servers'].queryset = (Interface.objects.all()
.select_related(
'domain__extension'
))
self.fields["servers"].queryset = Interface.objects.all().select_related(
"domain__extension"
)
class DelRoleForm(FormRevMixin, Form):
"""Deletion of one or several roles."""
role = forms.ModelMultipleChoiceField(
queryset=Role.objects.none(),
label=_("Current roles"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelRoleForm, self).__init__(*args, **kwargs)
if instances:
self.fields['role'].queryset = instances
self.fields["role"].queryset = instances
else:
self.fields['role'].queryset = Role.objects.all()
self.fields["role"].queryset = Role.objects.all()
class ServiceForm(FormRevMixin, ModelForm):
@ -555,15 +574,14 @@ class ServiceForm(FormRevMixin, ModelForm):
class Meta:
model = Service
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ServiceForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['servers'].queryset = (Interface.objects.all()
.select_related(
'domain__extension'
))
self.fields["servers"].queryset = Interface.objects.all().select_related(
"domain__extension"
)
def save(self, commit=True):
# TODO : None of the parents of ServiceForm use the commit
@ -571,25 +589,26 @@ class ServiceForm(FormRevMixin, ModelForm):
instance = super(ServiceForm, self).save(commit=False)
if commit:
instance.save()
instance.process_link(self.cleaned_data.get('servers'))
instance.process_link(self.cleaned_data.get("servers"))
return instance
class DelServiceForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs service"""
service = forms.ModelMultipleChoiceField(
queryset=Service.objects.none(),
label=_("Current services"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelServiceForm, self).__init__(*args, **kwargs)
if instances:
self.fields['service'].queryset = instances
self.fields["service"].queryset = instances
else:
self.fields['service'].queryset = Service.objects.all()
self.fields["service"].queryset = Service.objects.all()
class VlanForm(FormRevMixin, ModelForm):
@ -597,39 +616,41 @@ class VlanForm(FormRevMixin, ModelForm):
class Meta:
model = Vlan
fields = ['vlan_id', 'name', 'comment']
fields = ["vlan_id", "name", "comment"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(VlanForm, self).__init__(*args, prefix=prefix, **kwargs)
class EditOptionVlanForm(FormRevMixin, ModelForm):
"""Ajout d'un vlan : id, nom"""
class Meta:
model = Vlan
fields = ['dhcp_snooping', 'dhcpv6_snooping', 'arp_protect', 'igmp', 'mld']
fields = ["dhcp_snooping", "dhcpv6_snooping", "arp_protect", "igmp", "mld"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(EditOptionVlanForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelVlanForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs vlans"""
vlan = forms.ModelMultipleChoiceField(
queryset=Vlan.objects.none(),
label=_("Current VLANs"),
widget=forms.CheckboxSelectMultiple
widget=forms.CheckboxSelectMultiple,
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
instances = kwargs.pop("instances", None)
super(DelVlanForm, self).__init__(*args, **kwargs)
if instances:
self.fields['vlan'].queryset = instances
self.fields["vlan"].queryset = instances
else:
self.fields['vlan'].queryset = Vlan.objects.all()
self.fields["vlan"].queryset = Vlan.objects.all()
class EditOuverturePortConfigForm(FormRevMixin, ModelForm):
@ -638,14 +659,12 @@ class EditOuverturePortConfigForm(FormRevMixin, ModelForm):
class Meta:
model = Interface
fields = ['port_lists']
fields = ["port_lists"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(EditOuverturePortConfigForm, self).__init__(
*args,
prefix=prefix,
**kwargs
*args, prefix=prefix, **kwargs
)
@ -655,15 +674,11 @@ class EditOuverturePortListForm(FormRevMixin, ModelForm):
class Meta:
model = OuverturePortList
fields = '__all__'
fields = "__all__"
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(EditOuverturePortListForm, self).__init__(
*args,
prefix=prefix,
**kwargs
)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(EditOuverturePortListForm, self).__init__(*args, prefix=prefix, **kwargs)
class SshFpForm(FormRevMixin, ModelForm):
@ -671,12 +686,8 @@ class SshFpForm(FormRevMixin, ModelForm):
class Meta:
model = SshFp
exclude = ('machine',)
exclude = ("machine",)
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(SshFpForm, self).__init__(
*args,
prefix=prefix,
**kwargs
)
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(SshFpForm, self).__init__(*args, prefix=prefix, **kwargs)

View file

@ -29,32 +29,50 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0005_auto_20160702_0006'),
]
dependencies = [("users", "0005_auto_20160702_0006")]
operations = [
migrations.CreateModel(
name='Machine',
name="Machine",
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
(
"id",
models.AutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
),
)
],
),
migrations.CreateModel(
name='MachineType',
name="MachineType",
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('type', models.CharField(max_length=255)),
(
"id",
models.AutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
),
),
("type", models.CharField(max_length=255)),
],
),
migrations.AddField(
model_name='machine',
name='type',
field=models.ForeignKey(to='machines.MachineType', on_delete=django.db.models.deletion.PROTECT),
model_name="machine",
name="type",
field=models.ForeignKey(
to="machines.MachineType", on_delete=django.db.models.deletion.PROTECT
),
),
migrations.AddField(
model_name='machine',
name='user',
field=models.ForeignKey(to='users.User', on_delete=django.db.models.deletion.PROTECT),
model_name="machine",
name="user",
field=models.ForeignKey(
to="users.User", on_delete=django.db.models.deletion.PROTECT
),
),
]

View file

@ -30,36 +30,57 @@ import macaddress.fields
class Migration(migrations.Migration):
dependencies = [
('machines', '0001_initial'),
]
dependencies = [("machines", "0001_initial")]
operations = [
migrations.CreateModel(
name='Interface',
name="Interface",
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('ipv6', models.GenericIPAddressField(protocol='IPv6')),
('mac_address', macaddress.fields.MACAddressField(integer=True)),
('details', models.CharField(max_length=255)),
('name', models.CharField(max_length=255, blank=True, unique=True)),
(
"id",
models.AutoField(
serialize=False,
verbose_name="ID",
auto_created=True,
primary_key=True,
),
),
("ipv6", models.GenericIPAddressField(protocol="IPv6")),
("mac_address", macaddress.fields.MACAddressField(integer=True)),
("details", models.CharField(max_length=255)),
("name", models.CharField(max_length=255, blank=True, unique=True)),
],
),
migrations.CreateModel(
name='IpList',
name="IpList",
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('ipv4', models.GenericIPAddressField(protocol='IPv4')),
(
"id",
models.AutoField(
serialize=False,
verbose_name="ID",
auto_created=True,
primary_key=True,
),
),
("ipv4", models.GenericIPAddressField(protocol="IPv4")),
],
),
migrations.AddField(
model_name='interface',
name='ipv4',
field=models.OneToOneField(null=True, to='machines.IpList', blank=True, on_delete=django.db.models.deletion.PROTECT),
model_name="interface",
name="ipv4",
field=models.OneToOneField(
null=True,
to="machines.IpList",
blank=True,
on_delete=django.db.models.deletion.PROTECT,
),
),
migrations.AddField(
model_name='interface',
name='machine',
field=models.ForeignKey(to='machines.Machine', on_delete=django.db.models.deletion.PROTECT),
model_name="interface",
name="machine",
field=models.ForeignKey(
to="machines.Machine", on_delete=django.db.models.deletion.PROTECT
),
),
]

View file

@ -29,14 +29,12 @@ import macaddress.fields
class Migration(migrations.Migration):
dependencies = [
('machines', '0002_auto_20160703_1444'),
]
dependencies = [("machines", "0002_auto_20160703_1444")]
operations = [
migrations.AlterField(
model_name='interface',
name='mac_address',
model_name="interface",
name="mac_address",
field=macaddress.fields.MACAddressField(integer=True, unique=True),
),
)
]

View file

@ -28,14 +28,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('machines', '0003_auto_20160703_1450'),
]
dependencies = [("machines", "0003_auto_20160703_1450")]
operations = [
migrations.AlterField(
model_name='iplist',
name='ipv4',
field=models.GenericIPAddressField(protocol='IPv4', unique=True),
),
model_name="iplist",
name="ipv4",
field=models.GenericIPAddressField(protocol="IPv4", unique=True),
)
]

View file

@ -28,19 +28,15 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('machines', '0004_auto_20160703_1451'),
]
dependencies = [("machines", "0004_auto_20160703_1451")]
operations = [
migrations.RenameField(
model_name='interface',
old_name='name',
new_name='dns',
),
migrations.RenameField(model_name="interface", old_name="name", new_name="dns"),
migrations.AddField(
model_name='machine',
name='name',
field=models.CharField(blank=True, unique=True, max_length=255, help_text='Optionnel'),
model_name="machine",
name="name",
field=models.CharField(
blank=True, unique=True, max_length=255, help_text="Optionnel"
),
),
]

Some files were not shown because too many files have changed in this diff Show more