policies/reputation: save username instead of user object

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-05-29 22:49:58 +02:00
parent d52cc30341
commit 05b3c4ddb3
5 changed files with 86 additions and 272 deletions

View File

@ -1,5 +1,7 @@
"""Source API Views""" """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.api.policies import PolicySerializer
from authentik.policies.reputation.models import ( from authentik.policies.reputation.models import (
@ -28,7 +30,7 @@ class ReputationPolicyViewSet(ModelViewSet):
serializer_class = ReputationPolicySerializer serializer_class = ReputationPolicySerializer
class IPReputationSerializer(PolicySerializer): class IPReputationSerializer(ModelSerializer):
"""IPReputation Serializer""" """IPReputation Serializer"""
class Meta: class Meta:
@ -41,28 +43,44 @@ class IPReputationSerializer(PolicySerializer):
] ]
class IPReputationViewSet(ModelViewSet): class IPReputationViewSet(
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""IPReputation Viewset""" """IPReputation Viewset"""
queryset = IPReputation.objects.all() queryset = IPReputation.objects.all()
serializer_class = IPReputationSerializer serializer_class = IPReputationSerializer
search_fields = ["ip", "score"]
filterset_fields = ["ip", "score"]
ordering = ["ip"]
class UserReputationSerializer(PolicySerializer): class UserReputationSerializer(ModelSerializer):
"""UserReputation Serializer""" """UserReputation Serializer"""
class Meta: class Meta:
model = UserReputation model = UserReputation
fields = [ fields = [
"pk", "pk",
"user", "username",
"score", "score",
"updated", "updated",
] ]
class UserReputationViewSet(ModelViewSet): class UserReputationViewSet(
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""UserReputation Viewset""" """UserReputation Viewset"""
queryset = UserReputation.objects.all() queryset = UserReputation.objects.all()
serializer_class = UserReputationSerializer serializer_class = UserReputationSerializer
search_fields = ["username", "score"]
filterset_fields = ["username", "score"]
ordering = ["username"]

View File

@ -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(),
),
]

View File

@ -61,9 +61,9 @@ class IPReputation(models.Model):
class UserReputation(models.Model): class UserReputation(models.Model):
"""Store score attempting to log in as the same username""" """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) score = models.IntegerField(default=0)
updated = models.DateTimeField(auto_now=True) updated = models.DateTimeField(auto_now=True)
def __str__(self): def __str__(self):
return f"UserReputation for {self.user} @ {self.score}" return f"UserReputation for {self.username} @ {self.score}"

View File

@ -35,11 +35,7 @@ def save_user_reputation(self: MonitoredTask):
objects_to_update = [] objects_to_update = []
for key, score in cache.get_many(cache.keys(CACHE_KEY_USER_PREFIX + "*")).items(): for key, score in cache.get_many(cache.keys(CACHE_KEY_USER_PREFIX + "*")).items():
username = key.replace(CACHE_KEY_USER_PREFIX, "") username = key.replace(CACHE_KEY_USER_PREFIX, "")
users = User.objects.filter(username=username) rep, _ = UserReputation.objects.get_or_create(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.score = score rep.score = score
objects_to_update.append(rep) objects_to_update.append(rep)
UserReputation.objects.bulk_update(objects_to_update, ["score"]) UserReputation.objects.bulk_update(objects_to_update, ["score"])

View File

@ -7528,6 +7528,10 @@ paths:
operationId: policies_reputation_ips_list operationId: policies_reputation_ips_list
description: IPReputation Viewset description: IPReputation Viewset
parameters: parameters:
- in: query
name: ip
schema:
type: string
- name: ordering - name: ordering
required: false required: false
in: query in: query
@ -7546,6 +7550,10 @@ paths:
description: Number of results to return per page. description: Number of results to return per page.
schema: schema:
type: integer type: integer
- in: query
name: score
schema:
type: integer
- name: search - name: search
required: false required: false
in: query in: query
@ -7568,37 +7576,6 @@ paths:
$ref: '#/components/schemas/ValidationError' $ref: '#/components/schemas/ValidationError'
'403': '403':
$ref: '#/components/schemas/GenericError' $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}/: /api/v2beta/policies/reputation/ips/{id}/:
get: get:
operationId: policies_reputation_ips_retrieve operationId: policies_reputation_ips_retrieve
@ -7626,81 +7603,6 @@ paths:
$ref: '#/components/schemas/ValidationError' $ref: '#/components/schemas/ValidationError'
'403': '403':
$ref: '#/components/schemas/GenericError' $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: delete:
operationId: policies_reputation_ips_destroy operationId: policies_reputation_ips_destroy
description: IPReputation Viewset description: IPReputation Viewset
@ -7746,12 +7648,20 @@ paths:
description: Number of results to return per page. description: Number of results to return per page.
schema: schema:
type: integer type: integer
- in: query
name: score
schema:
type: integer
- name: search - name: search
required: false required: false
in: query in: query
description: A search term. description: A search term.
schema: schema:
type: string type: string
- in: query
name: username
schema:
type: string
tags: tags:
- policies - policies
security: security:
@ -7768,37 +7678,6 @@ paths:
$ref: '#/components/schemas/ValidationError' $ref: '#/components/schemas/ValidationError'
'403': '403':
$ref: '#/components/schemas/GenericError' $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}/: /api/v2beta/policies/reputation/users/{id}/:
get: get:
operationId: policies_reputation_users_retrieve operationId: policies_reputation_users_retrieve
@ -7826,81 +7705,6 @@ paths:
$ref: '#/components/schemas/ValidationError' $ref: '#/components/schemas/ValidationError'
'403': '403':
$ref: '#/components/schemas/GenericError' $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: delete:
operationId: policies_reputation_users_destroy operationId: policies_reputation_users_destroy
description: UserReputation Viewset description: UserReputation Viewset
@ -17637,18 +17441,6 @@ components:
- ip - ip
- pk - pk
- updated - updated
IPReputationRequest:
type: object
description: IPReputation Serializer
properties:
ip:
type: string
score:
type: integer
maximum: 2147483647
minimum: -2147483648
required:
- ip
IdentificationChallenge: IdentificationChallenge:
type: object type: object
description: Identification challenges with all UI elements description: Identification challenges with all UI elements
@ -22214,16 +22006,6 @@ components:
type: integer type: integer
maximum: 2147483647 maximum: 2147483647
minimum: -2147483648 minimum: -2147483648
PatchedIPReputationRequest:
type: object
description: IPReputation Serializer
properties:
ip:
type: string
score:
type: integer
maximum: 2147483647
minimum: -2147483648
PatchedIdentificationStageRequest: PatchedIdentificationStageRequest:
type: object type: object
description: IdentificationStage Serializer description: IdentificationStage Serializer
@ -23207,16 +22989,6 @@ components:
identifier: identifier:
type: string type: string
maxLength: 255 maxLength: 255
PatchedUserReputationRequest:
type: object
description: UserReputation Serializer
properties:
user:
type: integer
score:
type: integer
maximum: 2147483647
minimum: -2147483648
PatchedUserRequest: PatchedUserRequest:
type: object type: object
description: User Serializer description: User Serializer
@ -25547,8 +25319,8 @@ components:
type: integer type: integer
readOnly: true readOnly: true
title: ID title: ID
user: username:
type: integer type: string
score: score:
type: integer type: integer
maximum: 2147483647 maximum: 2147483647
@ -25560,19 +25332,7 @@ components:
required: required:
- pk - pk
- updated - updated
- user - username
UserReputationRequest:
type: object
description: UserReputation Serializer
properties:
user:
type: integer
score:
type: integer
maximum: 2147483647
minimum: -2147483648
required:
- user
UserRequest: UserRequest:
type: object type: object
description: User Serializer description: User Serializer