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}),
|
_("Successfully re-scheduled Task %(name)s!" % {"name": task.task_name}),
|
||||||
)
|
)
|
||||||
return Response(status=204)
|
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
|
# if we get an import error, the module path has probably changed
|
||||||
task.delete()
|
task.delete()
|
||||||
return Response(status=500)
|
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.expression.api import ExpressionPolicyViewSet
|
||||||
from authentik.policies.hibp.api import HaveIBeenPwendPolicyViewSet
|
from authentik.policies.hibp.api import HaveIBeenPwendPolicyViewSet
|
||||||
from authentik.policies.password.api import PasswordPolicyViewSet
|
from authentik.policies.password.api import PasswordPolicyViewSet
|
||||||
from authentik.policies.reputation.api import (
|
from authentik.policies.reputation.api import ReputationPolicyViewSet, ReputationViewSet
|
||||||
IPReputationViewSet,
|
|
||||||
ReputationPolicyViewSet,
|
|
||||||
UserReputationViewSet,
|
|
||||||
)
|
|
||||||
from authentik.providers.ldap.api import LDAPOutpostConfigViewSet, LDAPProviderViewSet
|
from authentik.providers.ldap.api import LDAPOutpostConfigViewSet, LDAPProviderViewSet
|
||||||
from authentik.providers.oauth2.api.provider import OAuth2ProviderViewSet
|
from authentik.providers.oauth2.api.provider import OAuth2ProviderViewSet
|
||||||
from authentik.providers.oauth2.api.scope import ScopeMappingViewSet
|
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/haveibeenpwned", HaveIBeenPwendPolicyViewSet)
|
||||||
router.register("policies/password_expiry", PasswordExpiryPolicyViewSet)
|
router.register("policies/password_expiry", PasswordExpiryPolicyViewSet)
|
||||||
router.register("policies/password", PasswordPolicyViewSet)
|
router.register("policies/password", PasswordPolicyViewSet)
|
||||||
router.register("policies/reputation/users", UserReputationViewSet)
|
router.register("policies/reputation/scores", ReputationViewSet)
|
||||||
router.register("policies/reputation/ips", IPReputationViewSet)
|
|
||||||
router.register("policies/reputation", ReputationPolicyViewSet)
|
router.register("policies/reputation", ReputationPolicyViewSet)
|
||||||
|
|
||||||
router.register("providers/all", ProviderViewSet)
|
router.register("providers/all", ProviderViewSet)
|
||||||
|
|
|
@ -35,12 +35,11 @@ class GeoIPReader:
|
||||||
|
|
||||||
def __open(self):
|
def __open(self):
|
||||||
"""Get GeoIP Reader, if configured, otherwise none"""
|
"""Get GeoIP Reader, if configured, otherwise none"""
|
||||||
path = CONFIG.y("authentik.geoip")
|
path = CONFIG.y("geoip")
|
||||||
if path == "" or not path:
|
if path == "" or not path:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
reader = Reader(path)
|
self.__reader = Reader(path)
|
||||||
self.__reader = reader
|
|
||||||
self.__last_mtime = stat(path).st_mtime
|
self.__last_mtime = stat(path).st_mtime
|
||||||
LOGGER.info("Loaded GeoIP database", last_write=self.__last_mtime)
|
LOGGER.info("Loaded GeoIP database", last_write=self.__last_mtime)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
"""Source API Views"""
|
"""Reputation policy API Views"""
|
||||||
from rest_framework import mixins
|
from rest_framework import mixins
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
|
|
||||||
from authentik.core.api.used_by import UsedByMixin
|
from authentik.core.api.used_by import UsedByMixin
|
||||||
from authentik.policies.api.policies import PolicySerializer
|
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):
|
class ReputationPolicySerializer(PolicySerializer):
|
||||||
|
@ -29,59 +29,32 @@ class ReputationPolicyViewSet(UsedByMixin, ModelViewSet):
|
||||||
ordering = ["name"]
|
ordering = ["name"]
|
||||||
|
|
||||||
|
|
||||||
class IPReputationSerializer(ModelSerializer):
|
class ReputationSerializer(ModelSerializer):
|
||||||
"""IPReputation Serializer"""
|
"""Reputation Serializer"""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IPReputation
|
model = Reputation
|
||||||
fields = [
|
fields = [
|
||||||
"pk",
|
"pk",
|
||||||
|
"identifier",
|
||||||
"ip",
|
"ip",
|
||||||
|
"ip_geo_data",
|
||||||
"score",
|
"score",
|
||||||
"updated",
|
"updated",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class IPReputationViewSet(
|
class ReputationViewSet(
|
||||||
mixins.RetrieveModelMixin,
|
mixins.RetrieveModelMixin,
|
||||||
mixins.DestroyModelMixin,
|
mixins.DestroyModelMixin,
|
||||||
UsedByMixin,
|
UsedByMixin,
|
||||||
mixins.ListModelMixin,
|
mixins.ListModelMixin,
|
||||||
GenericViewSet,
|
GenericViewSet,
|
||||||
):
|
):
|
||||||
"""IPReputation Viewset"""
|
"""Reputation Viewset"""
|
||||||
|
|
||||||
queryset = IPReputation.objects.all()
|
queryset = Reputation.objects.all()
|
||||||
serializer_class = IPReputationSerializer
|
serializer_class = ReputationSerializer
|
||||||
search_fields = ["ip", "score"]
|
search_fields = ["identifier", "ip", "score"]
|
||||||
filterset_fields = ["ip", "score"]
|
filterset_fields = ["identifier", "ip", "score"]
|
||||||
ordering = ["ip"]
|
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):
|
def ready(self):
|
||||||
import_module("authentik.policies.reputation.signals")
|
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"""
|
"""authentik reputation request policy"""
|
||||||
from django.core.cache import cache
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.db import models
|
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 django.utils.translation import gettext as _
|
||||||
from rest_framework.serializers import BaseSerializer
|
from rest_framework.serializers import BaseSerializer
|
||||||
from structlog import get_logger
|
from structlog import get_logger
|
||||||
|
|
||||||
|
from authentik.lib.models import SerializerModel
|
||||||
from authentik.lib.utils.http import get_client_ip
|
from authentik.lib.utils.http import get_client_ip
|
||||||
from authentik.policies.models import Policy
|
from authentik.policies.models import Policy
|
||||||
from authentik.policies.types import PolicyRequest, PolicyResult
|
from authentik.policies.types import PolicyRequest, PolicyResult
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
CACHE_KEY_IP_PREFIX = "authentik_reputation_ip_"
|
CACHE_KEY_PREFIX = "goauthentik.io/policies/reputation/scores/"
|
||||||
CACHE_KEY_USER_PREFIX = "authentik_reputation_user_"
|
|
||||||
|
|
||||||
|
|
||||||
class ReputationPolicy(Policy):
|
class ReputationPolicy(Policy):
|
||||||
|
@ -34,16 +37,17 @@ class ReputationPolicy(Policy):
|
||||||
def passes(self, request: PolicyRequest) -> PolicyResult:
|
def passes(self, request: PolicyRequest) -> PolicyResult:
|
||||||
remote_ip = get_client_ip(request.http_request)
|
remote_ip = get_client_ip(request.http_request)
|
||||||
passing = False
|
passing = False
|
||||||
|
query = Q()
|
||||||
if self.check_ip:
|
if self.check_ip:
|
||||||
score = cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0)
|
query |= Q(ip=remote_ip)
|
||||||
passing += passing or score <= self.threshold
|
|
||||||
LOGGER.debug("Score for IP", ip=remote_ip, score=score, passing=passing)
|
|
||||||
if self.check_username:
|
if self.check_username:
|
||||||
score = cache.get_or_set(CACHE_KEY_USER_PREFIX + request.user.username, 0)
|
query |= Q(identifier=request.user.username)
|
||||||
|
score = Reputation.objects.filter(query).annotate(total_score=Sum("score")).total_score
|
||||||
passing += passing or score <= self.threshold
|
passing += passing or score <= self.threshold
|
||||||
LOGGER.debug(
|
LOGGER.debug(
|
||||||
"Score for Username",
|
"Score for user",
|
||||||
username=request.user.username,
|
username=request.user.username,
|
||||||
|
remote_ip=remote_ip,
|
||||||
score=score,
|
score=score,
|
||||||
passing=passing,
|
passing=passing,
|
||||||
)
|
)
|
||||||
|
@ -55,23 +59,27 @@ class ReputationPolicy(Policy):
|
||||||
verbose_name_plural = _("Reputation Policies")
|
verbose_name_plural = _("Reputation Policies")
|
||||||
|
|
||||||
|
|
||||||
class IPReputation(models.Model):
|
class Reputation(SerializerModel):
|
||||||
"""Store score coming from the same IP"""
|
"""Reputation for user and or IP."""
|
||||||
|
|
||||||
ip = models.GenericIPAddressField(unique=True)
|
reputation_uuid = models.UUIDField(primary_key=True, unique=True, default=uuid4)
|
||||||
score = models.IntegerField(default=0)
|
|
||||||
updated = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
identifier = models.TextField()
|
||||||
return f"IPReputation for {self.ip} @ {self.score}"
|
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):
|
@property
|
||||||
"""Store score attempting to log in as the same username"""
|
def serializer(self) -> BaseSerializer:
|
||||||
|
from authentik.policies.reputation.api import ReputationSerializer
|
||||||
|
|
||||||
username = models.TextField()
|
return ReputationSerializer
|
||||||
score = models.IntegerField(default=0)
|
|
||||||
updated = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"UserReputation for {self.username} @ {self.score}"
|
return f"Reputation {self.identifier}/{self.ip} @ {self.score}"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
unique_together = ("identifier", "ip")
|
||||||
|
|
|
@ -2,13 +2,8 @@
|
||||||
from celery.schedules import crontab
|
from celery.schedules import crontab
|
||||||
|
|
||||||
CELERY_BEAT_SCHEDULE = {
|
CELERY_BEAT_SCHEDULE = {
|
||||||
"policies_reputation_ip_save": {
|
"policies_reputation_save": {
|
||||||
"task": "authentik.policies.reputation.tasks.save_ip_reputation",
|
"task": "authentik.policies.reputation.tasks.save_reputation",
|
||||||
"schedule": crontab(minute="*/5"),
|
|
||||||
"options": {"queue": "authentik_scheduled"},
|
|
||||||
},
|
|
||||||
"policies_reputation_user_save": {
|
|
||||||
"task": "authentik.policies.reputation.tasks.save_user_reputation",
|
|
||||||
"schedule": crontab(minute="*/5"),
|
"schedule": crontab(minute="*/5"),
|
||||||
"options": {"queue": "authentik_scheduled"},
|
"options": {"queue": "authentik_scheduled"},
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,28 +7,30 @@ from structlog.stdlib import get_logger
|
||||||
|
|
||||||
from authentik.lib.config import CONFIG
|
from authentik.lib.config import CONFIG
|
||||||
from authentik.lib.utils.http import get_client_ip
|
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
|
from authentik.stages.identification.signals import identification_failed
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
CACHE_TIMEOUT = int(CONFIG.y("redis.cache_timeout_reputation"))
|
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"""
|
"""Update score for IP and User"""
|
||||||
remote_ip = get_client_ip(request)
|
remote_ip = get_client_ip(request)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# We only update the cache here, as its faster than writing to the DB
|
# 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)
|
score = cache.get_or_set(
|
||||||
cache.incr(CACHE_KEY_IP_PREFIX + remote_ip, amount)
|
CACHE_KEY_PREFIX + remote_ip + identifier,
|
||||||
|
{"ip": remote_ip, "identifier": identifier, "score": 0},
|
||||||
cache.get_or_set(CACHE_KEY_USER_PREFIX + username, 0, CACHE_TIMEOUT)
|
CACHE_TIMEOUT,
|
||||||
cache.incr(CACHE_KEY_USER_PREFIX + username, amount)
|
)
|
||||||
|
score["score"] += amount
|
||||||
|
cache.set(CACHE_KEY_PREFIX + remote_ip + identifier, score)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
LOGGER.warning("failed to set reputation", exc=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)
|
@receiver(user_login_failed)
|
||||||
|
|
|
@ -2,14 +2,15 @@
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
from authentik.events.geo import GEOIP_READER
|
||||||
from authentik.events.monitored_tasks import (
|
from authentik.events.monitored_tasks import (
|
||||||
MonitoredTask,
|
MonitoredTask,
|
||||||
TaskResult,
|
TaskResult,
|
||||||
TaskResultStatus,
|
TaskResultStatus,
|
||||||
prefill_task,
|
prefill_task,
|
||||||
)
|
)
|
||||||
from authentik.policies.reputation.models import IPReputation, UserReputation
|
from authentik.policies.reputation.models import Reputation
|
||||||
from authentik.policies.reputation.signals import CACHE_KEY_IP_PREFIX, CACHE_KEY_USER_PREFIX
|
from authentik.policies.reputation.signals import CACHE_KEY_PREFIX
|
||||||
from authentik.root.celery import CELERY_APP
|
from authentik.root.celery import CELERY_APP
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
|
@ -17,29 +18,16 @@ LOGGER = get_logger()
|
||||||
|
|
||||||
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
||||||
@prefill_task
|
@prefill_task
|
||||||
def save_ip_reputation(self: MonitoredTask):
|
def save_reputation(self: MonitoredTask):
|
||||||
"""Save currently cached reputation to database"""
|
"""Save currently cached reputation to database"""
|
||||||
objects_to_update = []
|
objects_to_update = []
|
||||||
for key, score in cache.get_many(cache.keys(CACHE_KEY_IP_PREFIX + "*")).items():
|
for _, score in cache.get_many(cache.keys(CACHE_KEY_PREFIX + "*")).items():
|
||||||
remote_ip = key.replace(CACHE_KEY_IP_PREFIX, "")
|
rep, _ = Reputation.objects.get_or_create(
|
||||||
rep, _ = IPReputation.objects.get_or_create(ip=remote_ip)
|
ip=score["ip"],
|
||||||
rep.score = score
|
identifier=score["identifier"],
|
||||||
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"])
|
|
||||||
)
|
)
|
||||||
|
rep.ip_geo_data = GEOIP_READER.city_dict(score["ip"]) or {}
|
||||||
|
rep.score = score["score"]
|
||||||
|
objects_to_update.append(rep)
|
||||||
|
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.core.models import User
|
||||||
from authentik.lib.utils.http import DEFAULT_IP
|
from authentik.lib.utils.http import DEFAULT_IP
|
||||||
from authentik.policies.reputation.models import (
|
from authentik.policies.reputation.models import CACHE_KEY_PREFIX, Reputation, ReputationPolicy
|
||||||
CACHE_KEY_IP_PREFIX,
|
from authentik.policies.reputation.tasks import save_reputation
|
||||||
CACHE_KEY_USER_PREFIX,
|
|
||||||
IPReputation,
|
|
||||||
ReputationPolicy,
|
|
||||||
UserReputation,
|
|
||||||
)
|
|
||||||
from authentik.policies.reputation.tasks import save_ip_reputation, save_user_reputation
|
|
||||||
from authentik.policies.types import PolicyRequest
|
from authentik.policies.types import PolicyRequest
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,9 +18,8 @@ class TestReputationPolicy(TestCase):
|
||||||
self.request = self.request_factory.get("/")
|
self.request = self.request_factory.get("/")
|
||||||
self.test_ip = "127.0.0.1"
|
self.test_ip = "127.0.0.1"
|
||||||
self.test_username = "test"
|
self.test_username = "test"
|
||||||
cache.delete(CACHE_KEY_IP_PREFIX + self.test_ip)
|
keys = cache.keys(CACHE_KEY_PREFIX + "*")
|
||||||
cache.delete(CACHE_KEY_IP_PREFIX + DEFAULT_IP)
|
cache.delete_many(keys)
|
||||||
cache.delete(CACHE_KEY_USER_PREFIX + self.test_username)
|
|
||||||
# We need a user for the one-to-one in userreputation
|
# We need a user for the one-to-one in userreputation
|
||||||
self.user = User.objects.create(username=self.test_username)
|
self.user = User.objects.create(username=self.test_username)
|
||||||
|
|
||||||
|
@ -35,20 +28,26 @@ class TestReputationPolicy(TestCase):
|
||||||
# Trigger negative reputation
|
# Trigger negative reputation
|
||||||
authenticate(self.request, username=self.test_username, password=self.test_username)
|
authenticate(self.request, username=self.test_username, password=self.test_username)
|
||||||
# Test value in cache
|
# 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 cache and check db values
|
||||||
save_ip_reputation.delay().get()
|
save_reputation.delay().get()
|
||||||
self.assertEqual(IPReputation.objects.get(ip=self.test_ip).score, -1)
|
self.assertEqual(Reputation.objects.get(ip=self.test_ip).score, -1)
|
||||||
|
|
||||||
def test_user_reputation(self):
|
def test_user_reputation(self):
|
||||||
"""test User reputation"""
|
"""test User reputation"""
|
||||||
# Trigger negative reputation
|
# Trigger negative reputation
|
||||||
authenticate(self.request, username=self.test_username, password=self.test_username)
|
authenticate(self.request, username=self.test_username, password=self.test_username)
|
||||||
# Test value in cache
|
# 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 cache and check db values
|
||||||
save_user_reputation.delay().get()
|
save_reputation.delay().get()
|
||||||
self.assertEqual(UserReputation.objects.get(username=self.test_username).score, -1)
|
self.assertEqual(Reputation.objects.get(identifier=self.test_username).score, -1)
|
||||||
|
|
||||||
def test_policy(self):
|
def test_policy(self):
|
||||||
"""Test Policy"""
|
"""Test Policy"""
|
||||||
|
|
|
@ -26,8 +26,8 @@ class PytestTestRunner: # pragma: no cover
|
||||||
|
|
||||||
settings.TEST = True
|
settings.TEST = True
|
||||||
settings.CELERY_TASK_ALWAYS_EAGER = True
|
settings.CELERY_TASK_ALWAYS_EAGER = True
|
||||||
CONFIG.y_set("authentik.avatars", "none")
|
CONFIG.y_set("avatars", "none")
|
||||||
CONFIG.y_set("authentik.geoip", "tests/GeoLite2-City-Test.mmdb")
|
CONFIG.y_set("geoip", "tests/GeoLite2-City-Test.mmdb")
|
||||||
CONFIG.y_set(
|
CONFIG.y_set(
|
||||||
"outposts.container_image_base",
|
"outposts.container_image_base",
|
||||||
f"ghcr.io/goauthentik/dev-%(type)s:{get_docker_tag()}",
|
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'
|
$ref: '#/components/schemas/ValidationError'
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
/policies/reputation/ips/:
|
/policies/reputation/scores/:
|
||||||
get:
|
get:
|
||||||
operationId: policies_reputation_ips_list
|
operationId: policies_reputation_scores_list
|
||||||
description: IPReputation Viewset
|
description: Reputation Viewset
|
||||||
parameters:
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: identifier
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
- in: query
|
- in: query
|
||||||
name: ip
|
name: ip
|
||||||
schema:
|
schema:
|
||||||
|
@ -9145,22 +9149,23 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/PaginatedIPReputationList'
|
$ref: '#/components/schemas/PaginatedReputationList'
|
||||||
description: ''
|
description: ''
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/schemas/ValidationError'
|
$ref: '#/components/schemas/ValidationError'
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
/policies/reputation/ips/{id}/:
|
/policies/reputation/scores/{reputation_uuid}/:
|
||||||
get:
|
get:
|
||||||
operationId: policies_reputation_ips_retrieve
|
operationId: policies_reputation_scores_retrieve
|
||||||
description: IPReputation Viewset
|
description: Reputation Viewset
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: id
|
name: reputation_uuid
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
description: A unique integer value identifying this ip reputation.
|
format: uuid
|
||||||
|
description: A UUID string identifying this reputation.
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- policies
|
- policies
|
||||||
|
@ -9171,21 +9176,22 @@ paths:
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/IPReputation'
|
$ref: '#/components/schemas/Reputation'
|
||||||
description: ''
|
description: ''
|
||||||
'400':
|
'400':
|
||||||
$ref: '#/components/schemas/ValidationError'
|
$ref: '#/components/schemas/ValidationError'
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
delete:
|
delete:
|
||||||
operationId: policies_reputation_ips_destroy
|
operationId: policies_reputation_scores_destroy
|
||||||
description: IPReputation Viewset
|
description: Reputation Viewset
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: id
|
name: reputation_uuid
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: string
|
||||||
description: A unique integer value identifying this ip reputation.
|
format: uuid
|
||||||
|
description: A UUID string identifying this reputation.
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- policies
|
- policies
|
||||||
|
@ -9198,143 +9204,17 @@ paths:
|
||||||
$ref: '#/components/schemas/ValidationError'
|
$ref: '#/components/schemas/ValidationError'
|
||||||
'403':
|
'403':
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
/policies/reputation/ips/{id}/used_by/:
|
/policies/reputation/scores/{reputation_uuid}/used_by/:
|
||||||
get:
|
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
|
description: Get a list of all objects that use this object
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: id
|
name: reputation_uuid
|
||||||
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.
|
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
- name: page
|
format: uuid
|
||||||
required: false
|
description: A UUID string identifying this reputation.
|
||||||
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.
|
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- policies
|
- policies
|
||||||
|
@ -21938,28 +21818,6 @@ components:
|
||||||
type: integer
|
type: integer
|
||||||
maximum: 2147483647
|
maximum: 2147483647
|
||||||
minimum: -2147483648
|
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:
|
IdentificationChallenge:
|
||||||
type: object
|
type: object
|
||||||
description: Identification challenges with all UI elements
|
description: Identification challenges with all UI elements
|
||||||
|
@ -23433,7 +23291,6 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
additional_scopes:
|
additional_scopes:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
|
||||||
required:
|
required:
|
||||||
- consumer_key
|
- consumer_key
|
||||||
- consumer_secret
|
- consumer_secret
|
||||||
|
@ -24497,41 +24354,6 @@ components:
|
||||||
required:
|
required:
|
||||||
- pagination
|
- pagination
|
||||||
- results
|
- 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:
|
PaginatedIdentificationStageList:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -25547,6 +25369,41 @@ components:
|
||||||
required:
|
required:
|
||||||
- pagination
|
- pagination
|
||||||
- results
|
- 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:
|
PaginatedReputationPolicyList:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -26212,41 +26069,6 @@ components:
|
||||||
required:
|
required:
|
||||||
- pagination
|
- pagination
|
||||||
- results
|
- 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:
|
PaginatedUserSourceConnectionList:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -27656,7 +27478,6 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
additional_scopes:
|
additional_scopes:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
|
||||||
PatchedOutpostRequest:
|
PatchedOutpostRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Outpost Serializer
|
description: Outpost Serializer
|
||||||
|
@ -29462,6 +29283,34 @@ components:
|
||||||
- provider
|
- provider
|
||||||
- scope
|
- scope
|
||||||
- user
|
- 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:
|
ReputationPolicy:
|
||||||
type: object
|
type: object
|
||||||
description: Reputation Policy Serializer
|
description: Reputation Policy Serializer
|
||||||
|
@ -31139,28 +30988,6 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
required:
|
required:
|
||||||
- password
|
- 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:
|
UserRequest:
|
||||||
type: object
|
type: object
|
||||||
description: User Serializer
|
description: User Serializer
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
"chartjs-adapter-moment": "^1.0.0",
|
"chartjs-adapter-moment": "^1.0.0",
|
||||||
"codemirror": "^5.65.0",
|
"codemirror": "^5.65.0",
|
||||||
"construct-style-sheets-polyfill": "^3.0.5",
|
"construct-style-sheets-polyfill": "^3.0.5",
|
||||||
|
"country-flag-icons": "^1.4.19",
|
||||||
"eslint": "^8.6.0",
|
"eslint": "^8.6.0",
|
||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-plugin-custom-elements": "0.0.4",
|
"eslint-plugin-custom-elements": "0.0.4",
|
||||||
|
@ -3869,6 +3870,11 @@
|
||||||
"node": ">=10"
|
"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": {
|
"node_modules/create-require": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||||
|
@ -11581,6 +11587,11 @@
|
||||||
"yaml": "^1.10.0"
|
"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": {
|
"create-require": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
"chartjs-adapter-moment": "^1.0.0",
|
"chartjs-adapter-moment": "^1.0.0",
|
||||||
"codemirror": "^5.65.0",
|
"codemirror": "^5.65.0",
|
||||||
"construct-style-sheets-polyfill": "^3.0.5",
|
"construct-style-sheets-polyfill": "^3.0.5",
|
||||||
|
"country-flag-icons": "^1.4.19",
|
||||||
"eslint": "^8.6.0",
|
"eslint": "^8.6.0",
|
||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-plugin-custom-elements": "0.0.4",
|
"eslint-plugin-custom-elements": "0.0.4",
|
||||||
|
|
|
@ -242,11 +242,8 @@ export class AdminInterface extends LitElement {
|
||||||
<ak-sidebar-item path="/policy/policies">
|
<ak-sidebar-item path="/policy/policies">
|
||||||
<span slot="label">${t`Policies`}</span>
|
<span slot="label">${t`Policies`}</span>
|
||||||
</ak-sidebar-item>
|
</ak-sidebar-item>
|
||||||
<ak-sidebar-item path="/policy/reputation/ip">
|
<ak-sidebar-item path="/policy/reputation">
|
||||||
<span slot="label">${t`Reputation policy - IPs`}</span>
|
<span slot="label">${t`Reputation scores`}</span>
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/policy/reputation/user">
|
|
||||||
<span slot="label">${t`Reputation policy - Users`}</span>
|
|
||||||
</ak-sidebar-item>
|
</ak-sidebar-item>
|
||||||
<ak-sidebar-item path="/core/property-mappings">
|
<ak-sidebar-item path="/core/property-mappings">
|
||||||
<span slot="label">${t`Property Mappings`}</span>
|
<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/outposts/ServiceConnectionListPage.ts
|
||||||
#: src/pages/policies/BoundPoliciesList.ts
|
#: src/pages/policies/BoundPoliciesList.ts
|
||||||
#: src/pages/policies/PolicyListPage.ts
|
#: src/pages/policies/PolicyListPage.ts
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
||||||
#: src/pages/providers/ProviderListPage.ts
|
#: src/pages/providers/ProviderListPage.ts
|
||||||
#: src/pages/sources/SourcesListPage.ts
|
#: src/pages/sources/SourcesListPage.ts
|
||||||
|
@ -2331,14 +2330,14 @@ msgstr "ID"
|
||||||
msgid "ID Token"
|
msgid "ID Token"
|
||||||
msgstr "ID Token"
|
msgstr "ID Token"
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
msgid "IP"
|
msgid "IP"
|
||||||
msgstr "IP"
|
msgstr "IP"
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
msgid "IP Reputation"
|
#~ msgid "IP Reputation"
|
||||||
msgstr "IP Reputation"
|
#~ msgstr "IP Reputation"
|
||||||
|
|
||||||
#: src/pages/applications/ApplicationForm.ts
|
#: src/pages/applications/ApplicationForm.ts
|
||||||
#: 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."
|
msgstr "Icon shown in the browser tab."
|
||||||
|
|
||||||
#: src/pages/flows/FlowListPage.ts
|
#: src/pages/flows/FlowListPage.ts
|
||||||
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/system-tasks/SystemTaskListPage.ts
|
#: src/pages/system-tasks/SystemTaskListPage.ts
|
||||||
#: src/pages/tokens/TokenForm.ts
|
#: src/pages/tokens/TokenForm.ts
|
||||||
#: src/pages/tokens/TokenListPage.ts
|
#: src/pages/tokens/TokenListPage.ts
|
||||||
|
@ -3869,21 +3869,34 @@ msgstr "Related objects"
|
||||||
msgid "Remove the user from the current session."
|
msgid "Remove the user from the current session."
|
||||||
msgstr "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
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
msgid "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."
|
#~ msgstr "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
||||||
|
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
msgid "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."
|
#~ msgstr "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
|
||||||
|
|
||||||
#: src/interfaces/AdminInterface.ts
|
#: src/interfaces/AdminInterface.ts
|
||||||
msgid "Reputation policy - IPs"
|
#~ msgid "Reputation policy - IPs"
|
||||||
msgstr "Reputation policy - IPs"
|
#~ msgstr "Reputation policy - IPs"
|
||||||
|
|
||||||
#: src/interfaces/AdminInterface.ts
|
#: src/interfaces/AdminInterface.ts
|
||||||
msgid "Reputation policy - Users"
|
#~ msgid "Reputation policy - Users"
|
||||||
msgstr "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
|
||||||
#: 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"
|
msgid "Scopes"
|
||||||
msgstr "Scopes"
|
msgstr "Scopes"
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
msgid "Score"
|
msgid "Score"
|
||||||
msgstr "Score"
|
msgstr "Score"
|
||||||
|
|
||||||
|
@ -5559,6 +5571,10 @@ msgstr "Update password"
|
||||||
msgid "Update {0}"
|
msgid "Update {0}"
|
||||||
msgstr "Update {0}"
|
msgstr "Update {0}"
|
||||||
|
|
||||||
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
|
msgid "Updated"
|
||||||
|
msgstr "Updated"
|
||||||
|
|
||||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||||
msgid "Upstream host that the requests are forwarded to."
|
msgid "Upstream host that the requests are forwarded to."
|
||||||
msgstr "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
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
msgid "User Reputation"
|
#~ msgid "User Reputation"
|
||||||
msgstr "User Reputation"
|
#~ msgstr "User Reputation"
|
||||||
|
|
||||||
#:
|
#:
|
||||||
#:
|
#:
|
||||||
|
@ -5752,7 +5768,6 @@ msgid "Userinfo URL"
|
||||||
msgstr "Userinfo URL"
|
msgstr "Userinfo URL"
|
||||||
|
|
||||||
#: src/flows/stages/identification/IdentificationStage.ts
|
#: src/flows/stages/identification/IdentificationStage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||||
#: src/pages/users/ServiceAccountForm.ts
|
#: src/pages/users/ServiceAccountForm.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/outposts/ServiceConnectionListPage.ts
|
||||||
#: src/pages/policies/BoundPoliciesList.ts
|
#: src/pages/policies/BoundPoliciesList.ts
|
||||||
#: src/pages/policies/PolicyListPage.ts
|
#: src/pages/policies/PolicyListPage.ts
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
||||||
#: src/pages/providers/ProviderListPage.ts
|
#: src/pages/providers/ProviderListPage.ts
|
||||||
#: src/pages/sources/SourcesListPage.ts
|
#: src/pages/sources/SourcesListPage.ts
|
||||||
|
@ -2315,14 +2314,14 @@ msgstr "ID"
|
||||||
msgid "ID Token"
|
msgid "ID Token"
|
||||||
msgstr "ID du jeton"
|
msgstr "ID du jeton"
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
msgid "IP"
|
msgid "IP"
|
||||||
msgstr "IP"
|
msgstr "IP"
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
msgid "IP Reputation"
|
#~ msgid "IP Reputation"
|
||||||
msgstr "Réputation IP"
|
#~ msgstr "Réputation IP"
|
||||||
|
|
||||||
#: src/pages/applications/ApplicationForm.ts
|
#: src/pages/applications/ApplicationForm.ts
|
||||||
#: 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."
|
msgstr "Icône affichée dans l'onglet du navigateur."
|
||||||
|
|
||||||
#: src/pages/flows/FlowListPage.ts
|
#: src/pages/flows/FlowListPage.ts
|
||||||
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/system-tasks/SystemTaskListPage.ts
|
#: src/pages/system-tasks/SystemTaskListPage.ts
|
||||||
#: src/pages/tokens/TokenForm.ts
|
#: src/pages/tokens/TokenForm.ts
|
||||||
#: src/pages/tokens/TokenListPage.ts
|
#: src/pages/tokens/TokenListPage.ts
|
||||||
|
@ -3841,21 +3841,34 @@ msgstr ""
|
||||||
msgid "Remove the user from the current session."
|
msgid "Remove the user from the current session."
|
||||||
msgstr "Supprimer l'utilisateur de la session actuelle."
|
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
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
msgid "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 "Réputation pour les IPs. Les notes sont réduites à chaque échec de connexion, et augmentées à chaque connexion réussie."
|
#~ 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
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
msgid "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 "Réputation pour les noms d'utilisateur. Les notes sont réduites à chaque échec de connexion, et augmentées à chaque connexion réussie."
|
#~ 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
|
#: src/interfaces/AdminInterface.ts
|
||||||
msgid "Reputation policy - IPs"
|
#~ msgid "Reputation policy - IPs"
|
||||||
msgstr "Politique de réputation - IPs"
|
#~ msgstr "Politique de réputation - IPs"
|
||||||
|
|
||||||
#: src/interfaces/AdminInterface.ts
|
#: src/interfaces/AdminInterface.ts
|
||||||
msgid "Reputation policy - Users"
|
#~ msgid "Reputation policy - Users"
|
||||||
msgstr "Politique de réputation - Utilisateurs"
|
#~ 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
|
||||||
#: 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"
|
msgid "Scopes"
|
||||||
msgstr "Portées"
|
msgstr "Portées"
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
msgid "Score"
|
msgid "Score"
|
||||||
msgstr "Note"
|
msgstr "Note"
|
||||||
|
|
||||||
|
@ -5500,6 +5512,10 @@ msgstr ""
|
||||||
msgid "Update {0}"
|
msgid "Update {0}"
|
||||||
msgstr "Mettre à jour {0}"
|
msgstr "Mettre à jour {0}"
|
||||||
|
|
||||||
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
|
msgid "Updated"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||||
msgid "Upstream host that the requests are forwarded to."
|
msgid "Upstream host that the requests are forwarded to."
|
||||||
msgstr "Hôte amont où transférer les requêtes."
|
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
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
msgid "User Reputation"
|
#~ msgid "User Reputation"
|
||||||
msgstr "Réputation utilisateur"
|
#~ msgstr "Réputation utilisateur"
|
||||||
|
|
||||||
#~ msgid "User Settings"
|
#~ msgid "User Settings"
|
||||||
#~ msgstr "Paramètres utilisateur"
|
#~ msgstr "Paramètres utilisateur"
|
||||||
|
@ -5691,7 +5707,6 @@ msgid "Userinfo URL"
|
||||||
msgstr "URL Userinfo"
|
msgstr "URL Userinfo"
|
||||||
|
|
||||||
#: src/flows/stages/identification/IdentificationStage.ts
|
#: src/flows/stages/identification/IdentificationStage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||||
#: src/pages/users/ServiceAccountForm.ts
|
#: src/pages/users/ServiceAccountForm.ts
|
||||||
#: src/pages/users/ServiceAccountForm.ts
|
#: src/pages/users/ServiceAccountForm.ts
|
||||||
|
|
|
@ -1364,8 +1364,7 @@ msgstr ""
|
||||||
#: src/pages/outposts/ServiceConnectionListPage.ts
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
#: src/pages/policies/BoundPoliciesList.ts
|
#: src/pages/policies/BoundPoliciesList.ts
|
||||||
#: src/pages/policies/PolicyListPage.ts
|
#: src/pages/policies/PolicyListPage.ts
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
#: src/pages/property-mappings/PropertyMappingListPage.ts
|
||||||
#: src/pages/providers/ProviderListPage.ts
|
#: src/pages/providers/ProviderListPage.ts
|
||||||
#: src/pages/sources/SourcesListPage.ts
|
#: src/pages/sources/SourcesListPage.ts
|
||||||
|
@ -2323,14 +2322,14 @@ msgstr ""
|
||||||
msgid "ID Token"
|
msgid "ID Token"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
msgid "IP"
|
msgid "IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/IPReputationListPage.ts
|
||||||
msgid "IP Reputation"
|
#~ msgid "IP Reputation"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/pages/applications/ApplicationForm.ts
|
#: src/pages/applications/ApplicationForm.ts
|
||||||
#: src/pages/applications/ApplicationForm.ts
|
#: src/pages/applications/ApplicationForm.ts
|
||||||
|
@ -2346,6 +2345,7 @@ msgid "Icon shown in the browser tab."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/flows/FlowListPage.ts
|
#: src/pages/flows/FlowListPage.ts
|
||||||
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/system-tasks/SystemTaskListPage.ts
|
#: src/pages/system-tasks/SystemTaskListPage.ts
|
||||||
#: src/pages/tokens/TokenForm.ts
|
#: src/pages/tokens/TokenForm.ts
|
||||||
#: src/pages/tokens/TokenListPage.ts
|
#: src/pages/tokens/TokenListPage.ts
|
||||||
|
@ -3859,20 +3859,33 @@ msgstr ""
|
||||||
msgid "Remove the user from the current session."
|
msgid "Remove the user from the current session."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
|
msgid "Reputation"
|
||||||
msgstr ""
|
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
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
msgid "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 ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/interfaces/AdminInterface.ts
|
#: src/interfaces/AdminInterface.ts
|
||||||
msgid "Reputation policy - IPs"
|
#~ msgid "Reputation policy - IPs"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/interfaces/AdminInterface.ts
|
#: 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 ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/events/EventInfo.ts
|
#: src/pages/events/EventInfo.ts
|
||||||
|
@ -4038,8 +4051,7 @@ msgstr ""
|
||||||
msgid "Scopes"
|
msgid "Scopes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/policies/reputation/IPReputationListPage.ts
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
msgid "Score"
|
msgid "Score"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -5539,6 +5551,10 @@ msgstr ""
|
||||||
msgid "Update {0}"
|
msgid "Update {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/policies/reputation/ReputationListPage.ts
|
||||||
|
msgid "Updated"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||||
msgid "Upstream host that the requests are forwarded to."
|
msgid "Upstream host that the requests are forwarded to."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -5620,8 +5636,8 @@ msgstr ""
|
||||||
|
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
#: src/pages/policies/reputation/UserReputationListPage.ts
|
||||||
msgid "User Reputation"
|
#~ msgid "User Reputation"
|
||||||
msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#:
|
#:
|
||||||
#:
|
#:
|
||||||
|
@ -5732,7 +5748,6 @@ msgid "Userinfo URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/flows/stages/identification/IdentificationStage.ts
|
#: src/flows/stages/identification/IdentificationStage.ts
|
||||||
#: src/pages/policies/reputation/UserReputationListPage.ts
|
|
||||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||||
#: src/pages/users/ServiceAccountForm.ts
|
#: src/pages/users/ServiceAccountForm.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 { t } from "@lingui/macro";
|
||||||
|
|
||||||
import { TemplateResult, html } from "lit";
|
import { TemplateResult, html } from "lit";
|
||||||
import { customElement, property } from "lit/decorators.js";
|
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 { AKResponse } from "../../../api/Client";
|
||||||
import { DEFAULT_CONFIG } from "../../../api/Config";
|
import { DEFAULT_CONFIG } from "../../../api/Config";
|
||||||
|
@ -15,28 +17,28 @@ import "../../../elements/forms/ModalForm";
|
||||||
import { TableColumn } from "../../../elements/table/Table";
|
import { TableColumn } from "../../../elements/table/Table";
|
||||||
import { TablePage } from "../../../elements/table/TablePage";
|
import { TablePage } from "../../../elements/table/TablePage";
|
||||||
|
|
||||||
@customElement("ak-policy-reputation-user-list")
|
@customElement("ak-policy-reputation-list")
|
||||||
export class UserReputationListPage extends TablePage<UserReputation> {
|
export class ReputationListPage extends TablePage<Reputation> {
|
||||||
searchEnabled(): boolean {
|
searchEnabled(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pageTitle(): string {
|
pageTitle(): string {
|
||||||
return t`User Reputation`;
|
return t`Reputation scores`;
|
||||||
}
|
}
|
||||||
pageDescription(): string {
|
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 {
|
pageIcon(): string {
|
||||||
return "fa fa-ban";
|
return "fa fa-ban";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property()
|
||||||
|
order = "identifier";
|
||||||
|
|
||||||
checkbox = true;
|
checkbox = true;
|
||||||
|
|
||||||
@property()
|
async apiEndpoint(page: number): Promise<AKResponse<Reputation>> {
|
||||||
order = "username";
|
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresList({
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<AKResponse<UserReputation>> {
|
|
||||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersList({
|
|
||||||
ordering: this.order,
|
ordering: this.order,
|
||||||
page: page,
|
page: page,
|
||||||
pageSize: (await uiConfig()).pagination.perPage,
|
pageSize: (await uiConfig()).pagination.perPage,
|
||||||
|
@ -45,22 +47,27 @@ export class UserReputationListPage extends TablePage<UserReputation> {
|
||||||
}
|
}
|
||||||
|
|
||||||
columns(): TableColumn[] {
|
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 {
|
renderToolbarSelected(): TemplateResult {
|
||||||
const disabled = this.selectedElements.length < 1;
|
const disabled = this.selectedElements.length < 1;
|
||||||
return html`<ak-forms-delete-bulk
|
return html`<ak-forms-delete-bulk
|
||||||
objectLabel=${t`User Reputation`}
|
objectLabel=${t`Reputation`}
|
||||||
.objects=${this.selectedElements}
|
.objects=${this.selectedElements}
|
||||||
.usedBy=${(item: UserReputation) => {
|
.usedBy=${(item: Reputation) => {
|
||||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersUsedByList({
|
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresUsedByList({
|
||||||
id: item.pk,
|
reputationUuid: item.pk || "",
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
.delete=${(item: UserReputation) => {
|
.delete=${(item: Reputation) => {
|
||||||
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUsersDestroy({
|
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationScoresDestroy({
|
||||||
id: item.pk,
|
reputationUuid: item.pk || "",
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -70,7 +77,15 @@ export class UserReputationListPage extends TablePage<UserReputation> {
|
||||||
</ak-forms-delete-bulk>`;
|
</ak-forms-delete-bulk>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
row(item: UserReputation): TemplateResult[] {
|
row(item: Reputation): TemplateResult[] {
|
||||||
return [html`${item.username}`, html`${item.score}`];
|
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/OutpostListPage";
|
||||||
import "./pages/outposts/ServiceConnectionListPage";
|
import "./pages/outposts/ServiceConnectionListPage";
|
||||||
import "./pages/policies/PolicyListPage";
|
import "./pages/policies/PolicyListPage";
|
||||||
import "./pages/policies/reputation/IPReputationListPage";
|
import "./pages/policies/reputation/ReputationListPage";
|
||||||
import "./pages/policies/reputation/UserReputationListPage";
|
|
||||||
import "./pages/property-mappings/PropertyMappingListPage";
|
import "./pages/property-mappings/PropertyMappingListPage";
|
||||||
import "./pages/providers/ProviderListPage";
|
import "./pages/providers/ProviderListPage";
|
||||||
import "./pages/providers/ProviderViewPage";
|
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("^/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/policies$"), html`<ak-policy-list></ak-policy-list>`),
|
||||||
new Route(
|
new Route(
|
||||||
new RegExp("^/policy/reputation/ip$"),
|
new RegExp("^/policy/reputation$"),
|
||||||
html`<ak-policy-reputation-ip-list></ak-policy-reputation-ip-list>`,
|
html`<ak-policy-reputation-list></ak-policy-reputation-list>`,
|
||||||
),
|
|
||||||
new Route(
|
|
||||||
new RegExp("^/policy/reputation/user$"),
|
|
||||||
html`<ak-policy-reputation-user-list></ak-policy-reputation-user-list>`,
|
|
||||||
),
|
),
|
||||||
new Route(new RegExp("^/identity/groups$"), html`<ak-group-list></ak-group-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>`),
|
new Route(new RegExp("^/identity/users$"), html`<ak-user-list></ak-user-list>`),
|
||||||
|
|
Reference in New Issue