policies/reputation: rework reputation to use a single entry, include geo_ip data
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
e3be0f2550
commit
6e53f1689d
|
@ -95,7 +95,7 @@ class TaskViewSet(ViewSet):
|
|||
_("Successfully re-scheduled Task %(name)s!" % {"name": task.task_name}),
|
||||
)
|
||||
return Response(status=204)
|
||||
except ImportError: # pragma: no cover
|
||||
except (ImportError, AttributeError): # pragma: no cover
|
||||
# if we get an import error, the module path has probably changed
|
||||
task.delete()
|
||||
return Response(status=500)
|
||||
|
|
|
@ -46,11 +46,7 @@ from authentik.policies.expiry.api import PasswordExpiryPolicyViewSet
|
|||
from authentik.policies.expression.api import ExpressionPolicyViewSet
|
||||
from authentik.policies.hibp.api import HaveIBeenPwendPolicyViewSet
|
||||
from authentik.policies.password.api import PasswordPolicyViewSet
|
||||
from authentik.policies.reputation.api import (
|
||||
IPReputationViewSet,
|
||||
ReputationPolicyViewSet,
|
||||
UserReputationViewSet,
|
||||
)
|
||||
from authentik.policies.reputation.api import ReputationPolicyViewSet, ReputationViewSet
|
||||
from authentik.providers.ldap.api import LDAPOutpostConfigViewSet, LDAPProviderViewSet
|
||||
from authentik.providers.oauth2.api.provider import OAuth2ProviderViewSet
|
||||
from authentik.providers.oauth2.api.scope import ScopeMappingViewSet
|
||||
|
@ -151,8 +147,7 @@ router.register("policies/event_matcher", EventMatcherPolicyViewSet)
|
|||
router.register("policies/haveibeenpwned", HaveIBeenPwendPolicyViewSet)
|
||||
router.register("policies/password_expiry", PasswordExpiryPolicyViewSet)
|
||||
router.register("policies/password", PasswordPolicyViewSet)
|
||||
router.register("policies/reputation/users", UserReputationViewSet)
|
||||
router.register("policies/reputation/ips", IPReputationViewSet)
|
||||
router.register("policies/reputation/scores", ReputationViewSet)
|
||||
router.register("policies/reputation", ReputationPolicyViewSet)
|
||||
|
||||
router.register("providers/all", ProviderViewSet)
|
||||
|
|
|
@ -35,12 +35,11 @@ class GeoIPReader:
|
|||
|
||||
def __open(self):
|
||||
"""Get GeoIP Reader, if configured, otherwise none"""
|
||||
path = CONFIG.y("authentik.geoip")
|
||||
path = CONFIG.y("geoip")
|
||||
if path == "" or not path:
|
||||
return
|
||||
try:
|
||||
reader = Reader(path)
|
||||
self.__reader = reader
|
||||
self.__reader = Reader(path)
|
||||
self.__last_mtime = stat(path).st_mtime
|
||||
LOGGER.info("Loaded GeoIP database", last_write=self.__last_mtime)
|
||||
except OSError as exc:
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
"""Source API Views"""
|
||||
"""Reputation policy API Views"""
|
||||
from rest_framework import mixins
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.policies.api.policies import PolicySerializer
|
||||
from authentik.policies.reputation.models import IPReputation, ReputationPolicy, UserReputation
|
||||
from authentik.policies.reputation.models import Reputation, ReputationPolicy
|
||||
|
||||
|
||||
class ReputationPolicySerializer(PolicySerializer):
|
||||
|
@ -29,59 +29,32 @@ class ReputationPolicyViewSet(UsedByMixin, ModelViewSet):
|
|||
ordering = ["name"]
|
||||
|
||||
|
||||
class IPReputationSerializer(ModelSerializer):
|
||||
"""IPReputation Serializer"""
|
||||
class ReputationSerializer(ModelSerializer):
|
||||
"""Reputation Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = IPReputation
|
||||
model = Reputation
|
||||
fields = [
|
||||
"pk",
|
||||
"identifier",
|
||||
"ip",
|
||||
"ip_geo_data",
|
||||
"score",
|
||||
"updated",
|
||||
]
|
||||
|
||||
|
||||
class IPReputationViewSet(
|
||||
class ReputationViewSet(
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
UsedByMixin,
|
||||
mixins.ListModelMixin,
|
||||
GenericViewSet,
|
||||
):
|
||||
"""IPReputation Viewset"""
|
||||
"""Reputation Viewset"""
|
||||
|
||||
queryset = IPReputation.objects.all()
|
||||
serializer_class = IPReputationSerializer
|
||||
search_fields = ["ip", "score"]
|
||||
filterset_fields = ["ip", "score"]
|
||||
queryset = Reputation.objects.all()
|
||||
serializer_class = ReputationSerializer
|
||||
search_fields = ["identifier", "ip", "score"]
|
||||
filterset_fields = ["identifier", "ip", "score"]
|
||||
ordering = ["ip"]
|
||||
|
||||
|
||||
class UserReputationSerializer(ModelSerializer):
|
||||
"""UserReputation Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = UserReputation
|
||||
fields = [
|
||||
"pk",
|
||||
"username",
|
||||
"score",
|
||||
"updated",
|
||||
]
|
||||
|
||||
|
||||
class UserReputationViewSet(
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
UsedByMixin,
|
||||
mixins.ListModelMixin,
|
||||
GenericViewSet,
|
||||
):
|
||||
"""UserReputation Viewset"""
|
||||
|
||||
queryset = UserReputation.objects.all()
|
||||
serializer_class = UserReputationSerializer
|
||||
search_fields = ["username", "score"]
|
||||
filterset_fields = ["username", "score"]
|
||||
ordering = ["username"]
|
||||
|
|
|
@ -13,3 +13,4 @@ class AuthentikPolicyReputationConfig(AppConfig):
|
|||
|
||||
def ready(self):
|
||||
import_module("authentik.policies.reputation.signals")
|
||||
import_module("authentik.policies.reputation.tasks")
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Generated by Django 4.0.1 on 2022-01-05 18:56
|
||||
|
||||
import uuid
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_policies_reputation", "0002_auto_20210529_2046"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Reputation",
|
||||
fields=[
|
||||
(
|
||||
"reputation_uuid",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4, primary_key=True, serialize=False, unique=True
|
||||
),
|
||||
),
|
||||
("identifier", models.TextField()),
|
||||
("ip", models.GenericIPAddressField()),
|
||||
("ip_geo_data", models.JSONField(default=dict)),
|
||||
("score", models.BigIntegerField(default=0)),
|
||||
("updated", models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
"unique_together": {("identifier", "ip")},
|
||||
},
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name="IPReputation",
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name="UserReputation",
|
||||
),
|
||||
]
|
|
@ -1,17 +1,20 @@
|
|||
"""authentik reputation request policy"""
|
||||
from django.core.cache import cache
|
||||
from uuid import uuid4
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Sum
|
||||
from django.db.models.query_utils import Q
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.serializers import BaseSerializer
|
||||
from structlog import get_logger
|
||||
|
||||
from authentik.lib.models import SerializerModel
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.policies.models import Policy
|
||||
from authentik.policies.types import PolicyRequest, PolicyResult
|
||||
|
||||
LOGGER = get_logger()
|
||||
CACHE_KEY_IP_PREFIX = "authentik_reputation_ip_"
|
||||
CACHE_KEY_USER_PREFIX = "authentik_reputation_user_"
|
||||
CACHE_KEY_PREFIX = "goauthentik.io/policies/reputation/scores/"
|
||||
|
||||
|
||||
class ReputationPolicy(Policy):
|
||||
|
@ -34,19 +37,20 @@ class ReputationPolicy(Policy):
|
|||
def passes(self, request: PolicyRequest) -> PolicyResult:
|
||||
remote_ip = get_client_ip(request.http_request)
|
||||
passing = False
|
||||
query = Q()
|
||||
if self.check_ip:
|
||||
score = cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0)
|
||||
passing += passing or score <= self.threshold
|
||||
LOGGER.debug("Score for IP", ip=remote_ip, score=score, passing=passing)
|
||||
query |= Q(ip=remote_ip)
|
||||
if self.check_username:
|
||||
score = cache.get_or_set(CACHE_KEY_USER_PREFIX + request.user.username, 0)
|
||||
passing += passing or score <= self.threshold
|
||||
LOGGER.debug(
|
||||
"Score for Username",
|
||||
username=request.user.username,
|
||||
score=score,
|
||||
passing=passing,
|
||||
)
|
||||
query |= Q(identifier=request.user.username)
|
||||
score = Reputation.objects.filter(query).annotate(total_score=Sum("score")).total_score
|
||||
passing += passing or score <= self.threshold
|
||||
LOGGER.debug(
|
||||
"Score for user",
|
||||
username=request.user.username,
|
||||
remote_ip=remote_ip,
|
||||
score=score,
|
||||
passing=passing,
|
||||
)
|
||||
return PolicyResult(bool(passing))
|
||||
|
||||
class Meta:
|
||||
|
@ -55,23 +59,27 @@ class ReputationPolicy(Policy):
|
|||
verbose_name_plural = _("Reputation Policies")
|
||||
|
||||
|
||||
class IPReputation(models.Model):
|
||||
"""Store score coming from the same IP"""
|
||||
class Reputation(SerializerModel):
|
||||
"""Reputation for user and or IP."""
|
||||
|
||||
ip = models.GenericIPAddressField(unique=True)
|
||||
score = models.IntegerField(default=0)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
reputation_uuid = models.UUIDField(primary_key=True, unique=True, default=uuid4)
|
||||
|
||||
def __str__(self):
|
||||
return f"IPReputation for {self.ip} @ {self.score}"
|
||||
identifier = models.TextField()
|
||||
ip = models.GenericIPAddressField()
|
||||
ip_geo_data = models.JSONField(default=dict)
|
||||
score = models.BigIntegerField(default=0)
|
||||
|
||||
updated = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class UserReputation(models.Model):
|
||||
"""Store score attempting to log in as the same username"""
|
||||
@property
|
||||
def serializer(self) -> BaseSerializer:
|
||||
from authentik.policies.reputation.api import ReputationSerializer
|
||||
|
||||
username = models.TextField()
|
||||
score = models.IntegerField(default=0)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
return ReputationSerializer
|
||||
|
||||
def __str__(self):
|
||||
return f"UserReputation for {self.username} @ {self.score}"
|
||||
def __str__(self) -> str:
|
||||
return f"Reputation {self.identifier}/{self.ip} @ {self.score}"
|
||||
|
||||
class Meta:
|
||||
|
||||
unique_together = ("identifier", "ip")
|
||||
|
|
|
@ -2,13 +2,8 @@
|
|||
from celery.schedules import crontab
|
||||
|
||||
CELERY_BEAT_SCHEDULE = {
|
||||
"policies_reputation_ip_save": {
|
||||
"task": "authentik.policies.reputation.tasks.save_ip_reputation",
|
||||
"schedule": crontab(minute="*/5"),
|
||||
"options": {"queue": "authentik_scheduled"},
|
||||
},
|
||||
"policies_reputation_user_save": {
|
||||
"task": "authentik.policies.reputation.tasks.save_user_reputation",
|
||||
"policies_reputation_save": {
|
||||
"task": "authentik.policies.reputation.tasks.save_reputation",
|
||||
"schedule": crontab(minute="*/5"),
|
||||
"options": {"queue": "authentik_scheduled"},
|
||||
},
|
||||
|
|
|
@ -7,28 +7,30 @@ from structlog.stdlib import get_logger
|
|||
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.policies.reputation.models import CACHE_KEY_IP_PREFIX, CACHE_KEY_USER_PREFIX
|
||||
from authentik.policies.reputation.models import CACHE_KEY_PREFIX
|
||||
from authentik.stages.identification.signals import identification_failed
|
||||
|
||||
LOGGER = get_logger()
|
||||
CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_reputation"))
|
||||
|
||||
|
||||
def update_score(request: HttpRequest, username: str, amount: int):
|
||||
def update_score(request: HttpRequest, identifier: str, amount: int):
|
||||
"""Update score for IP and User"""
|
||||
remote_ip = get_client_ip(request)
|
||||
|
||||
try:
|
||||
# We only update the cache here, as its faster than writing to the DB
|
||||
cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0, CACHE_TIMEOUT)
|
||||
cache.incr(CACHE_KEY_IP_PREFIX + remote_ip, amount)
|
||||
|
||||
cache.get_or_set(CACHE_KEY_USER_PREFIX + username, 0, CACHE_TIMEOUT)
|
||||
cache.incr(CACHE_KEY_USER_PREFIX + username, amount)
|
||||
score = cache.get_or_set(
|
||||
CACHE_KEY_PREFIX + remote_ip + identifier,
|
||||
{"ip": remote_ip, "identifier": identifier, "score": 0},
|
||||
CACHE_TIMEOUT,
|
||||
)
|
||||
score["score"] += amount
|
||||
cache.set(CACHE_KEY_PREFIX + remote_ip + identifier, score)
|
||||
except ValueError as exc:
|
||||
LOGGER.warning("failed to set reputation", exc=exc)
|
||||
|
||||
LOGGER.debug("Updated score", amount=amount, for_user=username, for_ip=remote_ip)
|
||||
LOGGER.debug("Updated score", amount=amount, for_user=identifier, for_ip=remote_ip)
|
||||
|
||||
|
||||
@receiver(user_login_failed)
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
from django.core.cache import cache
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.geo import GEOIP_READER
|
||||
from authentik.events.monitored_tasks import (
|
||||
MonitoredTask,
|
||||
TaskResult,
|
||||
TaskResultStatus,
|
||||
prefill_task,
|
||||
)
|
||||
from authentik.policies.reputation.models import IPReputation, UserReputation
|
||||
from authentik.policies.reputation.signals import CACHE_KEY_IP_PREFIX, CACHE_KEY_USER_PREFIX
|
||||
from authentik.policies.reputation.models import Reputation
|
||||
from authentik.policies.reputation.signals import CACHE_KEY_PREFIX
|
||||
from authentik.root.celery import CELERY_APP
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
@ -17,29 +18,16 @@ LOGGER = get_logger()
|
|||
|
||||
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
||||
@prefill_task
|
||||
def save_ip_reputation(self: MonitoredTask):
|
||||
def save_reputation(self: MonitoredTask):
|
||||
"""Save currently cached reputation to database"""
|
||||
objects_to_update = []
|
||||
for key, score in cache.get_many(cache.keys(CACHE_KEY_IP_PREFIX + "*")).items():
|
||||
remote_ip = key.replace(CACHE_KEY_IP_PREFIX, "")
|
||||
rep, _ = IPReputation.objects.get_or_create(ip=remote_ip)
|
||||
rep.score = score
|
||||
for _, score in cache.get_many(cache.keys(CACHE_KEY_PREFIX + "*")).items():
|
||||
rep, _ = Reputation.objects.get_or_create(
|
||||
ip=score["ip"],
|
||||
identifier=score["identifier"],
|
||||
)
|
||||
rep.ip_geo_data = GEOIP_READER.city_dict(score["ip"]) or {}
|
||||
rep.score = score["score"]
|
||||
objects_to_update.append(rep)
|
||||
IPReputation.objects.bulk_update(objects_to_update, ["score"])
|
||||
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, ["Successfully updated IP Reputation"]))
|
||||
|
||||
|
||||
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
||||
@prefill_task
|
||||
def save_user_reputation(self: MonitoredTask):
|
||||
"""Save currently cached reputation to database"""
|
||||
objects_to_update = []
|
||||
for key, score in cache.get_many(cache.keys(CACHE_KEY_USER_PREFIX + "*")).items():
|
||||
username = key.replace(CACHE_KEY_USER_PREFIX, "")
|
||||
rep, _ = UserReputation.objects.get_or_create(username=username)
|
||||
rep.score = score
|
||||
objects_to_update.append(rep)
|
||||
UserReputation.objects.bulk_update(objects_to_update, ["score"])
|
||||
self.set_status(
|
||||
TaskResult(TaskResultStatus.SUCCESSFUL, ["Successfully updated User Reputation"])
|
||||
)
|
||||
Reputation.objects.bulk_update(objects_to_update, ["score", "ip_geo_data"])
|
||||
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, ["Successfully updated Reputation"]))
|
||||
|
|
|
@ -5,14 +5,8 @@ from django.test import RequestFactory, TestCase
|
|||
|
||||
from authentik.core.models import User
|
||||
from authentik.lib.utils.http import DEFAULT_IP
|
||||
from authentik.policies.reputation.models import (
|
||||
CACHE_KEY_IP_PREFIX,
|
||||
CACHE_KEY_USER_PREFIX,
|
||||
IPReputation,
|
||||
ReputationPolicy,
|
||||
UserReputation,
|
||||
)
|
||||
from authentik.policies.reputation.tasks import save_ip_reputation, save_user_reputation
|
||||
from authentik.policies.reputation.models import CACHE_KEY_PREFIX, Reputation, ReputationPolicy
|
||||
from authentik.policies.reputation.tasks import save_reputation
|
||||
from authentik.policies.types import PolicyRequest
|
||||
|
||||
|
||||
|
@ -24,9 +18,8 @@ class TestReputationPolicy(TestCase):
|
|||
self.request = self.request_factory.get("/")
|
||||
self.test_ip = "127.0.0.1"
|
||||
self.test_username = "test"
|
||||
cache.delete(CACHE_KEY_IP_PREFIX + self.test_ip)
|
||||
cache.delete(CACHE_KEY_IP_PREFIX + DEFAULT_IP)
|
||||
cache.delete(CACHE_KEY_USER_PREFIX + self.test_username)
|
||||
keys = cache.keys(CACHE_KEY_PREFIX + "*")
|
||||
cache.delete_many(keys)
|
||||
# We need a user for the one-to-one in userreputation
|
||||
self.user = User.objects.create(username=self.test_username)
|
||||
|
||||
|
@ -35,20 +28,26 @@ class TestReputationPolicy(TestCase):
|
|||
# Trigger negative reputation
|
||||
authenticate(self.request, username=self.test_username, password=self.test_username)
|
||||
# Test value in cache
|
||||
self.assertEqual(cache.get(CACHE_KEY_IP_PREFIX + self.test_ip), -1)
|
||||
self.assertEqual(
|
||||
cache.get(CACHE_KEY_PREFIX + self.test_ip + self.test_username),
|
||||
{"ip": "127.0.0.1", "identifier": "test", "score": -1},
|
||||
)
|
||||
# Save cache and check db values
|
||||
save_ip_reputation.delay().get()
|
||||
self.assertEqual(IPReputation.objects.get(ip=self.test_ip).score, -1)
|
||||
save_reputation.delay().get()
|
||||
self.assertEqual(Reputation.objects.get(ip=self.test_ip).score, -1)
|
||||
|
||||
def test_user_reputation(self):
|
||||
"""test User reputation"""
|
||||
# Trigger negative reputation
|
||||
authenticate(self.request, username=self.test_username, password=self.test_username)
|
||||
# Test value in cache
|
||||
self.assertEqual(cache.get(CACHE_KEY_USER_PREFIX + self.test_username), -1)
|
||||
self.assertEqual(
|
||||
cache.get(CACHE_KEY_PREFIX + self.test_ip + self.test_username),
|
||||
{"ip": "127.0.0.1", "identifier": "test", "score": -1},
|
||||
)
|
||||
# Save cache and check db values
|
||||
save_user_reputation.delay().get()
|
||||
self.assertEqual(UserReputation.objects.get(username=self.test_username).score, -1)
|
||||
save_reputation.delay().get()
|
||||
self.assertEqual(Reputation.objects.get(identifier=self.test_username).score, -1)
|
||||
|
||||
def test_policy(self):
|
||||
"""Test Policy"""
|
||||
|
|
|
@ -26,8 +26,8 @@ class PytestTestRunner: # pragma: no cover
|
|||
|
||||
settings.TEST = True
|
||||
settings.CELERY_TASK_ALWAYS_EAGER = True
|
||||
CONFIG.y_set("authentik.avatars", "none")
|
||||
CONFIG.y_set("authentik.geoip", "tests/GeoLite2-City-Test.mmdb")
|
||||
CONFIG.y_set("avatars", "none")
|
||||
CONFIG.y_set("geoip", "tests/GeoLite2-City-Test.mmdb")
|
||||
CONFIG.y_set(
|
||||
"outposts.container_image_base",
|
||||
f"ghcr.io/goauthentik/dev-%(type)s:{get_docker_tag()}",
|
||||
|
|
353
schema.yml
353
schema.yml
|
@ -9099,11 +9099,15 @@ paths:
|
|||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/policies/reputation/ips/:
|
||||
/policies/reputation/scores/:
|
||||
get:
|
||||
operationId: policies_reputation_ips_list
|
||||
description: IPReputation Viewset
|
||||
operationId: policies_reputation_scores_list
|
||||
description: Reputation Viewset
|
||||
parameters:
|
||||
- in: query
|
||||
name: identifier
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: ip
|
||||
schema:
|
||||
|
@ -9145,22 +9149,23 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PaginatedIPReputationList'
|
||||
$ref: '#/components/schemas/PaginatedReputationList'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/policies/reputation/ips/{id}/:
|
||||
/policies/reputation/scores/{reputation_uuid}/:
|
||||
get:
|
||||
operationId: policies_reputation_ips_retrieve
|
||||
description: IPReputation Viewset
|
||||
operationId: policies_reputation_scores_retrieve
|
||||
description: Reputation Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
name: reputation_uuid
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this ip reputation.
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this reputation.
|
||||
required: true
|
||||
tags:
|
||||
- policies
|
||||
|
@ -9171,21 +9176,22 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/IPReputation'
|
||||
$ref: '#/components/schemas/Reputation'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
delete:
|
||||
operationId: policies_reputation_ips_destroy
|
||||
description: IPReputation Viewset
|
||||
operationId: policies_reputation_scores_destroy
|
||||
description: Reputation Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
name: reputation_uuid
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this ip reputation.
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this reputation.
|
||||
required: true
|
||||
tags:
|
||||
- policies
|
||||
|
@ -9198,143 +9204,17 @@ paths:
|
|||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/policies/reputation/ips/{id}/used_by/:
|
||||
/policies/reputation/scores/{reputation_uuid}/used_by/:
|
||||
get:
|
||||
operationId: policies_reputation_ips_used_by_list
|
||||
operationId: policies_reputation_scores_used_by_list
|
||||
description: Get a list of all objects that use this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this ip reputation.
|
||||
required: true
|
||||
tags:
|
||||
- policies
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UsedBy'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/policies/reputation/users/:
|
||||
get:
|
||||
operationId: policies_reputation_users_list
|
||||
description: UserReputation Viewset
|
||||
parameters:
|
||||
- name: ordering
|
||||
required: false
|
||||
in: query
|
||||
description: Which field to use when ordering the results.
|
||||
name: reputation_uuid
|
||||
schema:
|
||||
type: string
|
||||
- name: page
|
||||
required: false
|
||||
in: query
|
||||
description: A page number within the paginated result set.
|
||||
schema:
|
||||
type: integer
|
||||
- name: page_size
|
||||
required: false
|
||||
in: query
|
||||
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:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PaginatedUserReputationList'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/policies/reputation/users/{id}/:
|
||||
get:
|
||||
operationId: policies_reputation_users_retrieve
|
||||
description: UserReputation Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this user reputation.
|
||||
required: true
|
||||
tags:
|
||||
- policies
|
||||
security:
|
||||
- authentik: []
|
||||
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
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this user reputation.
|
||||
required: true
|
||||
tags:
|
||||
- policies
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'204':
|
||||
description: No response body
|
||||
'400':
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'403':
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
/policies/reputation/users/{id}/used_by/:
|
||||
get:
|
||||
operationId: policies_reputation_users_used_by_list
|
||||
description: Get a list of all objects that use this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this user reputation.
|
||||
format: uuid
|
||||
description: A UUID string identifying this reputation.
|
||||
required: true
|
||||
tags:
|
||||
- policies
|
||||
|
@ -21938,28 +21818,6 @@ components:
|
|||
type: integer
|
||||
maximum: 2147483647
|
||||
minimum: -2147483648
|
||||
IPReputation:
|
||||
type: object
|
||||
description: IPReputation Serializer
|
||||
properties:
|
||||
pk:
|
||||
type: integer
|
||||
readOnly: true
|
||||
title: ID
|
||||
ip:
|
||||
type: string
|
||||
score:
|
||||
type: integer
|
||||
maximum: 2147483647
|
||||
minimum: -2147483648
|
||||
updated:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
required:
|
||||
- ip
|
||||
- pk
|
||||
- updated
|
||||
IdentificationChallenge:
|
||||
type: object
|
||||
description: Identification challenges with all UI elements
|
||||
|
@ -23433,7 +23291,6 @@ components:
|
|||
minLength: 1
|
||||
additional_scopes:
|
||||
type: string
|
||||
minLength: 1
|
||||
required:
|
||||
- consumer_key
|
||||
- consumer_secret
|
||||
|
@ -24497,41 +24354,6 @@ components:
|
|||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedIPReputationList:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
type: object
|
||||
properties:
|
||||
next:
|
||||
type: number
|
||||
previous:
|
||||
type: number
|
||||
count:
|
||||
type: number
|
||||
current:
|
||||
type: number
|
||||
total_pages:
|
||||
type: number
|
||||
start_index:
|
||||
type: number
|
||||
end_index:
|
||||
type: number
|
||||
required:
|
||||
- next
|
||||
- previous
|
||||
- count
|
||||
- current
|
||||
- total_pages
|
||||
- start_index
|
||||
- end_index
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/IPReputation'
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedIdentificationStageList:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -25547,6 +25369,41 @@ components:
|
|||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedReputationList:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
type: object
|
||||
properties:
|
||||
next:
|
||||
type: number
|
||||
previous:
|
||||
type: number
|
||||
count:
|
||||
type: number
|
||||
current:
|
||||
type: number
|
||||
total_pages:
|
||||
type: number
|
||||
start_index:
|
||||
type: number
|
||||
end_index:
|
||||
type: number
|
||||
required:
|
||||
- next
|
||||
- previous
|
||||
- count
|
||||
- current
|
||||
- total_pages
|
||||
- start_index
|
||||
- end_index
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Reputation'
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedReputationPolicyList:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -26212,41 +26069,6 @@ components:
|
|||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedUserReputationList:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
type: object
|
||||
properties:
|
||||
next:
|
||||
type: number
|
||||
previous:
|
||||
type: number
|
||||
count:
|
||||
type: number
|
||||
current:
|
||||
type: number
|
||||
total_pages:
|
||||
type: number
|
||||
start_index:
|
||||
type: number
|
||||
end_index:
|
||||
type: number
|
||||
required:
|
||||
- next
|
||||
- previous
|
||||
- count
|
||||
- current
|
||||
- total_pages
|
||||
- start_index
|
||||
- end_index
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UserReputation'
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedUserSourceConnectionList:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -27656,7 +27478,6 @@ components:
|
|||
minLength: 1
|
||||
additional_scopes:
|
||||
type: string
|
||||
minLength: 1
|
||||
PatchedOutpostRequest:
|
||||
type: object
|
||||
description: Outpost Serializer
|
||||
|
@ -29462,6 +29283,34 @@ components:
|
|||
- provider
|
||||
- scope
|
||||
- user
|
||||
Reputation:
|
||||
type: object
|
||||
description: Reputation Serializer
|
||||
properties:
|
||||
pk:
|
||||
type: string
|
||||
format: uuid
|
||||
title: Reputation uuid
|
||||
identifier:
|
||||
type: string
|
||||
ip:
|
||||
type: string
|
||||
ip_geo_data:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
score:
|
||||
type: integer
|
||||
maximum: 9223372036854775807
|
||||
minimum: -9223372036854775808
|
||||
format: int64
|
||||
updated:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
required:
|
||||
- identifier
|
||||
- ip
|
||||
- updated
|
||||
ReputationPolicy:
|
||||
type: object
|
||||
description: Reputation Policy Serializer
|
||||
|
@ -31139,28 +30988,6 @@ components:
|
|||
minLength: 1
|
||||
required:
|
||||
- password
|
||||
UserReputation:
|
||||
type: object
|
||||
description: UserReputation Serializer
|
||||
properties:
|
||||
pk:
|
||||
type: integer
|
||||
readOnly: true
|
||||
title: ID
|
||||
username:
|
||||
type: string
|
||||
score:
|
||||
type: integer
|
||||
maximum: 2147483647
|
||||
minimum: -2147483648
|
||||
updated:
|
||||
type: string
|
||||
format: date-time
|
||||
readOnly: true
|
||||
required:
|
||||
- pk
|
||||
- updated
|
||||
- username
|
||||
UserRequest:
|
||||
type: object
|
||||
description: User Serializer
|
||||
|
|
11
web/package-lock.json
generated
11
web/package-lock.json
generated
|
@ -45,6 +45,7 @@
|
|||
"chartjs-adapter-moment": "^1.0.0",
|
||||
"codemirror": "^5.65.0",
|
||||
"construct-style-sheets-polyfill": "^3.0.5",
|
||||
"country-flag-icons": "^1.4.19",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.4",
|
||||
|
@ -3869,6 +3870,11 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/country-flag-icons": {
|
||||
"version": "1.4.19",
|
||||
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.19.tgz",
|
||||
"integrity": "sha512-1hmXFJ4UURQt0Ex0990B7oOL4n9KLpT9NOSEmZoYh+/5DQ7/pikyqaptqCLUFFv/bYHyvYFeo0fqV82XxU6VOA=="
|
||||
},
|
||||
"node_modules/create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
|
@ -11581,6 +11587,11 @@
|
|||
"yaml": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"country-flag-icons": {
|
||||
"version": "1.4.19",
|
||||
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.19.tgz",
|
||||
"integrity": "sha512-1hmXFJ4UURQt0Ex0990B7oOL4n9KLpT9NOSEmZoYh+/5DQ7/pikyqaptqCLUFFv/bYHyvYFeo0fqV82XxU6VOA=="
|
||||
},
|
||||
"create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
"chartjs-adapter-moment": "^1.0.0",
|
||||
"codemirror": "^5.65.0",
|
||||
"construct-style-sheets-polyfill": "^3.0.5",
|
||||
"country-flag-icons": "^1.4.19",
|
||||
"eslint": "^8.6.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.4",
|
||||
|
|
|
@ -242,11 +242,8 @@ export class AdminInterface extends LitElement {
|
|||
<ak-sidebar-item path="/policy/policies">
|
||||
<span slot="label">${t`Policies`}</span>
|
||||
</ak-sidebar-item>
|
||||
<ak-sidebar-item path="/policy/reputation/ip">
|
||||
<span slot="label">${t`Reputation policy - IPs`}</span>
|
||||
</ak-sidebar-item>
|
||||
<ak-sidebar-item path="/policy/reputation/user">
|
||||
<span slot="label">${t`Reputation policy - Users`}</span>
|
||||
<ak-sidebar-item path="/policy/reputation">
|
||||
<span slot="label">${t`Reputation scores`}</span>
|
||||
</ak-sidebar-item>
|
||||
<ak-sidebar-item path="/core/property-mappings">
|
||||
<span slot="label">${t`Property Mappings`}</span>
|
||||
|
|
|
@ -1370,8 +1370,7 @@ msgstr "Define how notifications are sent to users, like Email or Webhook."
|
|||
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||
#: src/pages/policies/BoundPoliciesList.ts
|
||||
#: src/pages/policies/PolicyListPage.ts
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
||||
#: src/pages/providers/ProviderListPage.ts
|
||||
#: src/pages/sources/SourcesListPage.ts
|
||||
|
@ -2331,14 +2330,14 @@ msgstr "ID"
|
|||
msgid "ID Token"
|
||||
msgstr "ID Token"
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "IP"
|
||||
msgstr "IP"
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
msgid "IP Reputation"
|
||||
msgstr "IP Reputation"
|
||||
#~ msgid "IP Reputation"
|
||||
#~ msgstr "IP Reputation"
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts
|
||||
#: src/pages/applications/ApplicationForm.ts
|
||||
|
@ -2354,6 +2353,7 @@ msgid "Icon shown in the browser tab."
|
|||
msgstr "Icon shown in the browser tab."
|
||||
|
||||
#: src/pages/flows/FlowListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
#: src/pages/system-tasks/SystemTaskListPage.ts
|
||||
#: src/pages/tokens/TokenForm.ts
|
||||
#: src/pages/tokens/TokenListPage.ts
|
||||
|
@ -3869,21 +3869,34 @@ msgstr "Related objects"
|
|||
msgid "Remove the user from the current session."
|
||||
msgstr "Remove the user from the current session."
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation"
|
||||
msgstr "Reputation"
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr "Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login."
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgstr "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgstr "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "Reputation policy - IPs"
|
||||
msgstr "Reputation policy - IPs"
|
||||
#~ msgid "Reputation policy - IPs"
|
||||
#~ msgstr "Reputation policy - IPs"
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "Reputation policy - Users"
|
||||
msgstr "Reputation policy - Users"
|
||||
#~ msgid "Reputation policy - Users"
|
||||
#~ msgstr "Reputation policy - Users"
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation scores"
|
||||
msgstr "Reputation scores"
|
||||
|
||||
#: src/pages/events/EventInfo.ts
|
||||
#: src/pages/events/EventInfo.ts
|
||||
|
@ -4048,8 +4061,7 @@ msgstr "Scope which the client can specify to access these properties."
|
|||
msgid "Scopes"
|
||||
msgstr "Scopes"
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Score"
|
||||
msgstr "Score"
|
||||
|
||||
|
@ -5559,6 +5571,10 @@ msgstr "Update password"
|
|||
msgid "Update {0}"
|
||||
msgstr "Update {0}"
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Updated"
|
||||
msgstr "Updated"
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||
msgid "Upstream host that the requests are forwarded to."
|
||||
msgstr "Upstream host that the requests are forwarded to."
|
||||
|
@ -5640,8 +5656,8 @@ msgstr "User Property Mappings"
|
|||
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
msgid "User Reputation"
|
||||
msgstr "User Reputation"
|
||||
#~ msgid "User Reputation"
|
||||
#~ msgstr "User Reputation"
|
||||
|
||||
#:
|
||||
#:
|
||||
|
@ -5752,7 +5768,6 @@ msgid "Userinfo URL"
|
|||
msgstr "Userinfo URL"
|
||||
|
||||
#: src/flows/stages/identification/IdentificationStage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||
#: src/pages/users/ServiceAccountForm.ts
|
||||
#: src/pages/users/ServiceAccountForm.ts
|
||||
|
|
|
@ -1369,8 +1369,7 @@ msgstr "Définit les méthodes d'envoi des notifications aux utilisateurs, telle
|
|||
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||
#: src/pages/policies/BoundPoliciesList.ts
|
||||
#: src/pages/policies/PolicyListPage.ts
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
||||
#: src/pages/providers/ProviderListPage.ts
|
||||
#: src/pages/sources/SourcesListPage.ts
|
||||
|
@ -2315,14 +2314,14 @@ msgstr "ID"
|
|||
msgid "ID Token"
|
||||
msgstr "ID du jeton"
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "IP"
|
||||
msgstr "IP"
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
msgid "IP Reputation"
|
||||
msgstr "Réputation IP"
|
||||
#~ msgid "IP Reputation"
|
||||
#~ msgstr "Réputation IP"
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts
|
||||
#: src/pages/applications/ApplicationForm.ts
|
||||
|
@ -2338,6 +2337,7 @@ msgid "Icon shown in the browser tab."
|
|||
msgstr "Icône affichée dans l'onglet du navigateur."
|
||||
|
||||
#: src/pages/flows/FlowListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
#: src/pages/system-tasks/SystemTaskListPage.ts
|
||||
#: src/pages/tokens/TokenForm.ts
|
||||
#: src/pages/tokens/TokenListPage.ts
|
||||
|
@ -3841,21 +3841,34 @@ msgstr ""
|
|||
msgid "Remove the user from the current session."
|
||||
msgstr "Supprimer l'utilisateur de la session actuelle."
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr "Réputation pour les IPs. Les notes sont réduites à chaque échec de connexion, et augmentées à chaque connexion réussie."
|
||||
#~ msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgstr "Réputation pour les IPs. Les notes sont réduites à chaque échec de connexion, et augmentées à chaque connexion réussie."
|
||||
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr "Réputation pour les noms d'utilisateur. Les notes sont réduites à chaque échec de connexion, et augmentées à chaque connexion réussie."
|
||||
#~ msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgstr "Réputation pour les noms d'utilisateur. Les notes sont réduites à chaque échec de connexion, et augmentées à chaque connexion réussie."
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "Reputation policy - IPs"
|
||||
msgstr "Politique de réputation - IPs"
|
||||
#~ msgid "Reputation policy - IPs"
|
||||
#~ msgstr "Politique de réputation - IPs"
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "Reputation policy - Users"
|
||||
msgstr "Politique de réputation - Utilisateurs"
|
||||
#~ msgid "Reputation policy - Users"
|
||||
#~ msgstr "Politique de réputation - Utilisateurs"
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation scores"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/events/EventInfo.ts
|
||||
#: src/pages/events/EventInfo.ts
|
||||
|
@ -4019,8 +4032,7 @@ msgstr "Portée que le client peut spécifier pour accéder à ces propriétés.
|
|||
msgid "Scopes"
|
||||
msgstr "Portées"
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Score"
|
||||
msgstr "Note"
|
||||
|
||||
|
@ -5500,6 +5512,10 @@ msgstr ""
|
|||
msgid "Update {0}"
|
||||
msgstr "Mettre à jour {0}"
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Updated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||
msgid "Upstream host that the requests are forwarded to."
|
||||
msgstr "Hôte amont où transférer les requêtes."
|
||||
|
@ -5581,8 +5597,8 @@ msgstr "Mapping des propriétés d'utilisateur"
|
|||
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
msgid "User Reputation"
|
||||
msgstr "Réputation utilisateur"
|
||||
#~ msgid "User Reputation"
|
||||
#~ msgstr "Réputation utilisateur"
|
||||
|
||||
#~ msgid "User Settings"
|
||||
#~ msgstr "Paramètres utilisateur"
|
||||
|
@ -5691,7 +5707,6 @@ msgid "Userinfo URL"
|
|||
msgstr "URL Userinfo"
|
||||
|
||||
#: src/flows/stages/identification/IdentificationStage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||
#: src/pages/users/ServiceAccountForm.ts
|
||||
#: src/pages/users/ServiceAccountForm.ts
|
||||
|
|
|
@ -1364,8 +1364,7 @@ msgstr ""
|
|||
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||
#: src/pages/policies/BoundPoliciesList.ts
|
||||
#: src/pages/policies/PolicyListPage.ts
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
||||
#: src/pages/providers/ProviderListPage.ts
|
||||
#: src/pages/sources/SourcesListPage.ts
|
||||
|
@ -2323,14 +2322,14 @@ msgstr ""
|
|||
msgid "ID Token"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "IP"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
msgid "IP Reputation"
|
||||
msgstr ""
|
||||
#~ msgid "IP Reputation"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/pages/applications/ApplicationForm.ts
|
||||
#: src/pages/applications/ApplicationForm.ts
|
||||
|
@ -2346,6 +2345,7 @@ msgid "Icon shown in the browser tab."
|
|||
msgstr ""
|
||||
|
||||
#: src/pages/flows/FlowListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
#: src/pages/system-tasks/SystemTaskListPage.ts
|
||||
#: src/pages/tokens/TokenForm.ts
|
||||
#: src/pages/tokens/TokenListPage.ts
|
||||
|
@ -3859,20 +3859,33 @@ msgstr ""
|
|||
msgid "Remove the user from the current session."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#~ msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
msgstr ""
|
||||
#~ msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "Reputation policy - IPs"
|
||||
msgstr ""
|
||||
#~ msgid "Reputation policy - IPs"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
msgid "Reputation policy - Users"
|
||||
#~ msgid "Reputation policy - Users"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/interfaces/AdminInterface.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Reputation scores"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/events/EventInfo.ts
|
||||
|
@ -4038,8 +4051,7 @@ msgstr ""
|
|||
msgid "Scopes"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Score"
|
||||
msgstr ""
|
||||
|
||||
|
@ -5539,6 +5551,10 @@ msgstr ""
|
|||
msgid "Update {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||
msgid "Updated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||
msgid "Upstream host that the requests are forwarded to."
|
||||
msgstr ""
|
||||
|
@ -5620,8 +5636,8 @@ msgstr ""
|
|||
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
msgid "User Reputation"
|
||||
msgstr ""
|
||||
#~ msgid "User Reputation"
|
||||
#~ msgstr ""
|
||||
|
||||
#:
|
||||
#:
|
||||
|
@ -5732,7 +5748,6 @@ msgid "Userinfo URL"
|
|||
msgstr ""
|
||||
|
||||
#: src/flows/stages/identification/IdentificationStage.ts
|
||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||
#: src/pages/users/ServiceAccountForm.ts
|
||||
#: src/pages/users/ServiceAccountForm.ts
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,76 +0,0 @@
|
|||
import { t } from "@lingui/macro";
|
||||
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { IPReputation, PoliciesApi } from "@goauthentik/api";
|
||||
|
||||
import { AKResponse } from "../../../api/Client";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
import { uiConfig } from "../../../common/config";
|
||||
import "../../../elements/buttons/ModalButton";
|
||||
import "../../../elements/buttons/SpinnerButton";
|
||||
import "../../../elements/forms/DeleteBulkForm";
|
||||
import "../../../elements/forms/ModalForm";
|
||||
import { TableColumn } from "../../../elements/table/Table";
|
||||
import { TablePage } from "../../../elements/table/TablePage";
|
||||
|
||||
@customElement("ak-policy-reputation-ip-list")
|
||||
export class IPReputationListPage extends TablePage<IPReputation> {
|
||||
searchEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
pageTitle(): string {
|
||||
return t`IP Reputation`;
|
||||
}
|
||||
pageDescription(): string {
|
||||
return t`Reputation for IPs. Scores are decreased for each failed login and increased for each successful login.`;
|
||||
}
|
||||
pageIcon(): string {
|
||||
return "fa fa-ban";
|
||||
}
|
||||
|
||||
@property()
|
||||
order = "ip";
|
||||
|
||||
checkbox = true;
|
||||
|
||||
async apiEndpoint(page: number): Promise<AKResponse<IPReputation>> {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsList({
|
||||
ordering: this.order,
|
||||
page: page,
|
||||
pageSize: (await uiConfig()).pagination.perPage,
|
||||
search: this.search || "",
|
||||
});
|
||||
}
|
||||
|
||||
columns(): TableColumn[] {
|
||||
return [new TableColumn(t`IP`, "ip"), new TableColumn(t`Score`, "score")];
|
||||
}
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${t`IP Reputation`}
|
||||
.objects=${this.selectedElements}
|
||||
.usedBy=${(item: IPReputation) => {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsUsedByList({
|
||||
id: item.pk,
|
||||
});
|
||||
}}
|
||||
.delete=${(item: IPReputation) => {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationIpsDestroy({
|
||||
id: item.pk,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${t`Delete`}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
row(item: IPReputation): TemplateResult[] {
|
||||
return [html`${item.ip}`, html`${item.score}`];
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
import getUnicodeFlagIcon from "country-flag-icons/unicode/index.js";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { PoliciesApi, UserReputation } from "@goauthentik/api";
|
||||
import { PoliciesApi, Reputation } from "@goauthentik/api";
|
||||
|
||||
import { AKResponse } from "../../../api/Client";
|
||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||
|
@ -15,28 +17,28 @@ import "../../../elements/forms/ModalForm";
|
|||
import { TableColumn } from "../../../elements/table/Table";
|
||||
import { TablePage } from "../../../elements/table/TablePage";
|
||||
|
||||
@customElement("ak-policy-reputation-user-list")
|
||||
export class UserReputationListPage extends TablePage<UserReputation> {
|
||||
@customElement("ak-policy-reputation-list")
|
||||
export class ReputationListPage extends TablePage<Reputation> {
|
||||
searchEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
pageTitle(): string {
|
||||
return t`User Reputation`;
|
||||
return t`Reputation scores`;
|
||||
}
|
||||
pageDescription(): string {
|
||||
return t`Reputation for usernames. Scores are decreased for each failed login and increased for each successful login.`;
|
||||
return t`Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login.`;
|
||||
}
|
||||
pageIcon(): string {
|
||||
return "fa fa-ban";
|
||||
}
|
||||
|
||||
@property()
|
||||
order = "identifier";
|
||||
|
||||
checkbox = true;
|
||||
|
||||
@property()
|
||||
order = "username";
|
||||
|
||||
async apiEndpoint(page: number): Promise<AKResponse<UserReputation>> {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersList({
|
||||
async apiEndpoint(page: number): Promise<AKResponse<Reputation>> {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({
|
||||
ordering: this.order,
|
||||
page: page,
|
||||
pageSize: (await uiConfig()).pagination.perPage,
|
||||
|
@ -45,22 +47,27 @@ export class UserReputationListPage extends TablePage<UserReputation> {
|
|||
}
|
||||
|
||||
columns(): TableColumn[] {
|
||||
return [new TableColumn(t`Username`, "username"), new TableColumn(t`Score`, "score")];
|
||||
return [
|
||||
new TableColumn(t`Identifier`, "identifier"),
|
||||
new TableColumn(t`IP`, "ip"),
|
||||
new TableColumn(t`Score`, "score"),
|
||||
new TableColumn(t`Updated`, "updated"),
|
||||
];
|
||||
}
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${t`User Reputation`}
|
||||
objectLabel=${t`Reputation`}
|
||||
.objects=${this.selectedElements}
|
||||
.usedBy=${(item: UserReputation) => {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersUsedByList({
|
||||
id: item.pk,
|
||||
.usedBy=${(item: Reputation) => {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresUsedByList({
|
||||
reputationUuid: item.pk || "",
|
||||
});
|
||||
}}
|
||||
.delete=${(item: UserReputation) => {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersDestroy({
|
||||
id: item.pk,
|
||||
.delete=${(item: Reputation) => {
|
||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresDestroy({
|
||||
reputationUuid: item.pk || "",
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
@ -70,7 +77,15 @@ export class UserReputationListPage extends TablePage<UserReputation> {
|
|||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
row(item: UserReputation): TemplateResult[] {
|
||||
return [html`${item.username}`, html`${item.score}`];
|
||||
row(item: Reputation): TemplateResult[] {
|
||||
return [
|
||||
html`${item.identifier}`,
|
||||
html`${item.ipGeoData?.country
|
||||
? html` ${getUnicodeFlagIcon(item.ipGeoData.country)} `
|
||||
: html``}
|
||||
${item.ip}`,
|
||||
html`${item.score}`,
|
||||
html`${item.updated.toLocaleString()}`,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -16,8 +16,7 @@ import "./pages/groups/GroupListPage";
|
|||
import "./pages/outposts/OutpostListPage";
|
||||
import "./pages/outposts/ServiceConnectionListPage";
|
||||
import "./pages/policies/PolicyListPage";
|
||||
import "./pages/policies/reputation/IPReputationListPage";
|
||||
import "./pages/policies/reputation/UserReputationListPage";
|
||||
import "./pages/policies/reputation/ReputationListPage";
|
||||
import "./pages/property-mappings/PropertyMappingListPage";
|
||||
import "./pages/providers/ProviderListPage";
|
||||
import "./pages/providers/ProviderViewPage";
|
||||
|
@ -72,12 +71,8 @@ export const ROUTES: Route[] = [
|
|||
new Route(new RegExp("^/core/tenants$"), html`<ak-tenant-list></ak-tenant-list>`),
|
||||
new Route(new RegExp("^/policy/policies$"), html`<ak-policy-list></ak-policy-list>`),
|
||||
new Route(
|
||||
new RegExp("^/policy/reputation/ip$"),
|
||||
html`<ak-policy-reputation-ip-list></ak-policy-reputation-ip-list>`,
|
||||
),
|
||||
new Route(
|
||||
new RegExp("^/policy/reputation/user$"),
|
||||
html`<ak-policy-reputation-user-list></ak-policy-reputation-user-list>`,
|
||||
new RegExp("^/policy/reputation$"),
|
||||
html`<ak-policy-reputation-list></ak-policy-reputation-list>`,
|
||||
),
|
||||
new Route(new RegExp("^/identity/groups$"), html`<ak-group-list></ak-group-list>`),
|
||||
new Route(new RegExp("^/identity/users$"), html`<ak-user-list></ak-user-list>`),
|
||||
|
|
Reference in a new issue