From 05b3c4ddb3ee4baa1e8ccc2396e2157e5db91ed8 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Sat, 29 May 2021 22:49:58 +0200 Subject: [PATCH] policies/reputation: save username instead of user object Signed-off-by: Jens Langhammer --- authentik/policies/reputation/api.py | 30 +- .../migrations/0002_auto_20210529_2046.py | 40 +++ authentik/policies/reputation/models.py | 4 +- authentik/policies/reputation/tasks.py | 6 +- schema.yml | 278 ++---------------- 5 files changed, 86 insertions(+), 272 deletions(-) create mode 100644 authentik/policies/reputation/migrations/0002_auto_20210529_2046.py diff --git a/authentik/policies/reputation/api.py b/authentik/policies/reputation/api.py index ce3681972..f10d690e0 100644 --- a/authentik/policies/reputation/api.py +++ b/authentik/policies/reputation/api.py @@ -1,5 +1,7 @@ """Source API Views""" -from rest_framework.viewsets import ModelViewSet +from rest_framework import mixins +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.policies.api.policies import PolicySerializer from authentik.policies.reputation.models import ( @@ -28,7 +30,7 @@ class ReputationPolicyViewSet(ModelViewSet): serializer_class = ReputationPolicySerializer -class IPReputationSerializer(PolicySerializer): +class IPReputationSerializer(ModelSerializer): """IPReputation Serializer""" class Meta: @@ -41,28 +43,44 @@ class IPReputationSerializer(PolicySerializer): ] -class IPReputationViewSet(ModelViewSet): +class IPReputationViewSet( + mixins.RetrieveModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin, + GenericViewSet, +): """IPReputation Viewset""" queryset = IPReputation.objects.all() serializer_class = IPReputationSerializer + search_fields = ["ip", "score"] + filterset_fields = ["ip", "score"] + ordering = ["ip"] -class UserReputationSerializer(PolicySerializer): +class UserReputationSerializer(ModelSerializer): """UserReputation Serializer""" class Meta: model = UserReputation fields = [ "pk", - "user", + "username", "score", "updated", ] -class UserReputationViewSet(ModelViewSet): +class UserReputationViewSet( + mixins.RetrieveModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin, + GenericViewSet, +): """UserReputation Viewset""" queryset = UserReputation.objects.all() serializer_class = UserReputationSerializer + search_fields = ["username", "score"] + filterset_fields = ["username", "score"] + ordering = ["username"] diff --git a/authentik/policies/reputation/migrations/0002_auto_20210529_2046.py b/authentik/policies/reputation/migrations/0002_auto_20210529_2046.py new file mode 100644 index 000000000..e1a3cb247 --- /dev/null +++ b/authentik/policies/reputation/migrations/0002_auto_20210529_2046.py @@ -0,0 +1,40 @@ +# Generated by Django 3.2.3 on 2021-05-29 20:46 + +from django.apps.registry import Apps +from django.db import migrations, models +from django.db.backends.base.schema import BaseDatabaseSchemaEditor + + +def migrate_to_username(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): + db_alias = schema_editor.connection.alias + + UserReputation = apps.get_model("authentik_policies_reputation", "userreputation") + for rep in UserReputation.objects.using(db_alias).all(): + rep.username = rep.user.username + rep.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_policies_reputation", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="userreputation", + name="username", + field=models.TextField(default=""), + preserve_default=False, + ), + migrations.RunPython(migrate_to_username), + migrations.RemoveField( + model_name="userreputation", + name="user", + ), + migrations.AlterField( + model_name="userreputation", + name="username", + field=models.TextField(), + ), + ] diff --git a/authentik/policies/reputation/models.py b/authentik/policies/reputation/models.py index 4f8bfdc6b..a6a6bd7df 100644 --- a/authentik/policies/reputation/models.py +++ b/authentik/policies/reputation/models.py @@ -61,9 +61,9 @@ class IPReputation(models.Model): class UserReputation(models.Model): """Store score attempting to log in as the same username""" - user = models.OneToOneField(User, on_delete=models.CASCADE) + username = models.TextField() score = models.IntegerField(default=0) updated = models.DateTimeField(auto_now=True) def __str__(self): - return f"UserReputation for {self.user} @ {self.score}" + return f"UserReputation for {self.username} @ {self.score}" diff --git a/authentik/policies/reputation/tasks.py b/authentik/policies/reputation/tasks.py index a6fcf2b38..8904fb6c7 100644 --- a/authentik/policies/reputation/tasks.py +++ b/authentik/policies/reputation/tasks.py @@ -35,11 +35,7 @@ def save_user_reputation(self: MonitoredTask): objects_to_update = [] for key, score in cache.get_many(cache.keys(CACHE_KEY_USER_PREFIX + "*")).items(): username = key.replace(CACHE_KEY_USER_PREFIX, "") - users = User.objects.filter(username=username) - if not users.exists(): - LOGGER.info("User in cache does not exist, ignoring", username=username) - continue - rep, _ = UserReputation.objects.get_or_create(user=users.first()) + rep, _ = UserReputation.objects.get_or_create(username=username) rep.score = score objects_to_update.append(rep) UserReputation.objects.bulk_update(objects_to_update, ["score"]) diff --git a/schema.yml b/schema.yml index e583d1d34..db673fce4 100644 --- a/schema.yml +++ b/schema.yml @@ -7528,6 +7528,10 @@ paths: operationId: policies_reputation_ips_list description: IPReputation Viewset parameters: + - in: query + name: ip + schema: + type: string - name: ordering required: false in: query @@ -7546,6 +7550,10 @@ paths: description: Number of results to return per page. schema: type: integer + - in: query + name: score + schema: + type: integer - name: search required: false in: query @@ -7568,37 +7576,6 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' - post: - operationId: policies_reputation_ips_create - description: IPReputation Viewset - tags: - - policies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/IPReputationRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/IPReputationRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/IPReputationRequest' - required: true - security: - - authentik: [] - - cookieAuth: [] - responses: - '201': - content: - application/json: - schema: - $ref: '#/components/schemas/IPReputation' - description: '' - '400': - $ref: '#/components/schemas/ValidationError' - '403': - $ref: '#/components/schemas/GenericError' /api/v2beta/policies/reputation/ips/{id}/: get: operationId: policies_reputation_ips_retrieve @@ -7626,81 +7603,6 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' - put: - operationId: policies_reputation_ips_update - description: IPReputation Viewset - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this ip reputation. - required: true - tags: - - policies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/IPReputationRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/IPReputationRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/IPReputationRequest' - required: true - security: - - authentik: [] - - cookieAuth: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/IPReputation' - description: '' - '400': - $ref: '#/components/schemas/ValidationError' - '403': - $ref: '#/components/schemas/GenericError' - patch: - operationId: policies_reputation_ips_partial_update - description: IPReputation Viewset - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this ip reputation. - required: true - tags: - - policies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedIPReputationRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/PatchedIPReputationRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/PatchedIPReputationRequest' - security: - - authentik: [] - - cookieAuth: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/IPReputation' - description: '' - '400': - $ref: '#/components/schemas/ValidationError' - '403': - $ref: '#/components/schemas/GenericError' delete: operationId: policies_reputation_ips_destroy description: IPReputation Viewset @@ -7746,12 +7648,20 @@ paths: description: Number of results to return per page. schema: type: integer + - in: query + name: score + schema: + type: integer - name: search required: false in: query description: A search term. schema: type: string + - in: query + name: username + schema: + type: string tags: - policies security: @@ -7768,37 +7678,6 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' - post: - operationId: policies_reputation_users_create - description: UserReputation Viewset - tags: - - policies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserReputationRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/UserReputationRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/UserReputationRequest' - required: true - security: - - authentik: [] - - cookieAuth: [] - responses: - '201': - content: - application/json: - schema: - $ref: '#/components/schemas/UserReputation' - description: '' - '400': - $ref: '#/components/schemas/ValidationError' - '403': - $ref: '#/components/schemas/GenericError' /api/v2beta/policies/reputation/users/{id}/: get: operationId: policies_reputation_users_retrieve @@ -7826,81 +7705,6 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' - put: - operationId: policies_reputation_users_update - description: UserReputation Viewset - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this user reputation. - required: true - tags: - - policies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/UserReputationRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/UserReputationRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/UserReputationRequest' - required: true - security: - - authentik: [] - - cookieAuth: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/UserReputation' - description: '' - '400': - $ref: '#/components/schemas/ValidationError' - '403': - $ref: '#/components/schemas/GenericError' - patch: - operationId: policies_reputation_users_partial_update - description: UserReputation Viewset - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this user reputation. - required: true - tags: - - policies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PatchedUserReputationRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/PatchedUserReputationRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/PatchedUserReputationRequest' - security: - - authentik: [] - - cookieAuth: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/UserReputation' - description: '' - '400': - $ref: '#/components/schemas/ValidationError' - '403': - $ref: '#/components/schemas/GenericError' delete: operationId: policies_reputation_users_destroy description: UserReputation Viewset @@ -17637,18 +17441,6 @@ components: - ip - pk - updated - IPReputationRequest: - type: object - description: IPReputation Serializer - properties: - ip: - type: string - score: - type: integer - maximum: 2147483647 - minimum: -2147483648 - required: - - ip IdentificationChallenge: type: object description: Identification challenges with all UI elements @@ -22214,16 +22006,6 @@ components: type: integer maximum: 2147483647 minimum: -2147483648 - PatchedIPReputationRequest: - type: object - description: IPReputation Serializer - properties: - ip: - type: string - score: - type: integer - maximum: 2147483647 - minimum: -2147483648 PatchedIdentificationStageRequest: type: object description: IdentificationStage Serializer @@ -23207,16 +22989,6 @@ components: identifier: type: string maxLength: 255 - PatchedUserReputationRequest: - type: object - description: UserReputation Serializer - properties: - user: - type: integer - score: - type: integer - maximum: 2147483647 - minimum: -2147483648 PatchedUserRequest: type: object description: User Serializer @@ -25547,8 +25319,8 @@ components: type: integer readOnly: true title: ID - user: - type: integer + username: + type: string score: type: integer maximum: 2147483647 @@ -25560,19 +25332,7 @@ components: required: - pk - updated - - user - UserReputationRequest: - type: object - description: UserReputation Serializer - properties: - user: - type: integer - score: - type: integer - maximum: 2147483647 - minimum: -2147483648 - required: - - user + - username UserRequest: type: object description: User Serializer