fails when user exists
This commit is contained in:
parent
23bdcc7957
commit
bbf81e143e
8 changed files with 39 additions and 27 deletions
|
@ -5,7 +5,7 @@ from requests import Request
|
||||||
import structlog
|
import structlog
|
||||||
|
|
||||||
from app.authentik.settings import AuthentikSettings
|
from app.authentik.settings import AuthentikSettings
|
||||||
from .models import User
|
from .models import AuthentikUser
|
||||||
|
|
||||||
logging = structlog.get_logger()
|
logging = structlog.get_logger()
|
||||||
|
|
||||||
|
@ -147,13 +147,13 @@ class Authentik:
|
||||||
return r.json()
|
return r.json()
|
||||||
raise Exception(r.status_code, r.url, r.text)
|
raise Exception(r.status_code, r.url, r.text)
|
||||||
|
|
||||||
def get_user_by_pk(self, pk: str) -> Optional[User]:
|
def get_user_by_pk(self, pk: str) -> Optional[AuthentikUser]:
|
||||||
r = self.get(f"core/users/{pk}").json()
|
r = self.get(f"core/users/{pk}").json()
|
||||||
if "pk" in r:
|
if "pk" in r:
|
||||||
return User(**r)
|
return AuthentikUser(**r)
|
||||||
raise Exception(r)
|
raise Exception(r)
|
||||||
|
|
||||||
def get_user(self, user: User) -> Optional[User]:
|
def get_user(self, user: AuthentikUser) -> Optional[AuthentikUser]:
|
||||||
if user.pk:
|
if user.pk:
|
||||||
r = self.get(f"core/users/{user.pk}").json()
|
r = self.get(f"core/users/{user.pk}").json()
|
||||||
else:
|
else:
|
||||||
|
@ -165,16 +165,16 @@ class Authentik:
|
||||||
r = r["results"][0]
|
r = r["results"][0]
|
||||||
|
|
||||||
if "pk" in r:
|
if "pk" in r:
|
||||||
return User(**r)
|
return AuthentikUser(**r)
|
||||||
raise Exception(r)
|
raise Exception(r)
|
||||||
|
|
||||||
def create_user(self, user: User) -> User:
|
def create_user(self, user: AuthentikUser) -> AuthentikUser:
|
||||||
r = self.post("core/users/", user.dict()).json()
|
r = self.post("core/users/", user.dict()).json()
|
||||||
if "pk" in r:
|
if "pk" in r:
|
||||||
return User(**r)
|
return AuthentikUser(**r)
|
||||||
raise Exception(r)
|
raise Exception(r)
|
||||||
|
|
||||||
def delete_user(self, user: User) -> bool:
|
def delete_user(self, user: AuthentikUser) -> bool:
|
||||||
if user == None or user.pk == None:
|
if user == None or user.pk == None:
|
||||||
raise Exception("Not a valid user")
|
raise Exception("Not a valid user")
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class GroupsObjItem(BaseModel):
|
||||||
attributes: Dict[str, Any]
|
attributes: Dict[str, Any]
|
||||||
users_obj: List[UsersObjItem]
|
users_obj: List[UsersObjItem]
|
||||||
|
|
||||||
class User(BaseUser):
|
class AuthentikUser(BaseUser):
|
||||||
pk: Optional[str]
|
pk: Optional[str]
|
||||||
username: str
|
username: str
|
||||||
name: str
|
name: str
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
|
|
||||||
from app.authentik.settings import AuthentikSettings
|
from app.authentik.settings import AuthentikSettings
|
||||||
from .api import Authentik
|
from .api import Authentik
|
||||||
from .models import User
|
from .models import AuthentikUser
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
|
@ -34,7 +34,7 @@ def test_create_event_rule_already_exists(api: Authentik):
|
||||||
assert not exception == None # TODO create exception types
|
assert not exception == None # TODO create exception types
|
||||||
|
|
||||||
def test_get_user_by_username(api: Authentik):
|
def test_get_user_by_username(api: Authentik):
|
||||||
u = User(username="akadmin",
|
u = AuthentikUser(username="akadmin",
|
||||||
name="",
|
name="",
|
||||||
groups=[],
|
groups=[],
|
||||||
email="",
|
email="",
|
||||||
|
@ -47,7 +47,7 @@ def test_get_user_by_username(api: Authentik):
|
||||||
|
|
||||||
|
|
||||||
def test_create_user(api: Authentik):
|
def test_create_user(api: Authentik):
|
||||||
u = User(username="banane",
|
u = AuthentikUser(username="banane",
|
||||||
name="banane",
|
name="banane",
|
||||||
groups=[],
|
groups=[],
|
||||||
email="foo@example.org",
|
email="foo@example.org",
|
||||||
|
|
|
@ -3,7 +3,7 @@ from typing import List
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from fastapi import FastAPI, Depends
|
from fastapi import FastAPI, Depends
|
||||||
from app.authentik.api import Authentik
|
from app.authentik.api import Authentik
|
||||||
from app.authentik.models import User
|
from app.authentik.models import AuthentikUser
|
||||||
from app.consumer.baseConsumer import Consumer
|
from app.consumer.baseConsumer import Consumer
|
||||||
from app.consumer.wekan.api import WekanApi
|
from app.consumer.wekan.api import WekanApi
|
||||||
from app.consumer.wekan.main import WekanConsumer
|
from app.consumer.wekan.main import WekanConsumer
|
||||||
|
@ -32,6 +32,7 @@ class EventController:
|
||||||
# try:
|
# try:
|
||||||
self._authentik = authentik_api
|
self._authentik = authentik_api
|
||||||
self._sinks = []
|
self._sinks = []
|
||||||
|
self._exceptions = []
|
||||||
for sc in Consumer.__subclasses__():
|
for sc in Consumer.__subclasses__():
|
||||||
obj = sc()
|
obj = sc()
|
||||||
self._sinks.append(obj)
|
self._sinks.append(obj)
|
||||||
|
@ -47,11 +48,12 @@ class EventController:
|
||||||
self._sinks = sinks
|
self._sinks = sinks
|
||||||
|
|
||||||
def handle_model_created_event(self, model: Authentik_Hook_Model):
|
def handle_model_created_event(self, model: Authentik_Hook_Model):
|
||||||
user: User = self._authentik.get_user_by_pk(model.pk)
|
user: AuthentikUser = self._authentik.get_user_by_pk(model.pk)
|
||||||
for sink in self._sinks: # TODO this could run async
|
for sink in self._sinks: # TODO this could run async
|
||||||
logging.info(f"Creating User {user.username} in {sink.__class__}")
|
logging.info(f"Creating User {user.username} in {sink.__class__}")
|
||||||
try:
|
try:
|
||||||
sink.create_user(user)
|
sink.create_user(user)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("create user", exception=str(e), sink=sink, user=user)
|
logging.error("create user", exception=str(e), sink=sink, user=user)
|
||||||
|
self._exceptions.append(str(e))
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -5,7 +5,7 @@ from fastapi import Depends, FastAPI, Request, BackgroundTasks
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from app.consumer.baseConsumer import BaseUser, Consumer
|
from app.consumer.baseConsumer import BaseUser, Consumer
|
||||||
from app.authentik.api import Authentik
|
from app.authentik.api import Authentik
|
||||||
from app.authentik.models import User
|
from app.authentik.models import AuthentikUser
|
||||||
from app.event_controller import Authentik_Hook_Model, EventController, Http_request
|
from app.event_controller import Authentik_Hook_Model, EventController, Http_request
|
||||||
from app.authentik.settings import AuthentikSettings
|
from app.authentik.settings import AuthentikSettings
|
||||||
from .consumer.wekan.api import WekanApi
|
from .consumer.wekan.api import WekanApi
|
||||||
|
@ -42,7 +42,7 @@ async def create_demo_user(request: Request):
|
||||||
a = Authentik(base="http://localhost:9000/", token="foobar123")
|
a = Authentik(base="http://localhost:9000/", token="foobar123")
|
||||||
try:
|
try:
|
||||||
user = a.create_user(
|
user = a.create_user(
|
||||||
User(username="demo", name="dmeo", email="foo@example.org"))
|
AuthentikUser(username="demo", name="dmeo", email="foo@example.org"))
|
||||||
except Exception as e: # TODO
|
except Exception as e: # TODO
|
||||||
return e
|
return e
|
||||||
logging.info(user)
|
logging.info(user)
|
||||||
|
|
|
@ -7,6 +7,7 @@ from app.authentik.settings import AuthentikSettings
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
ec = EventController(Authentik(AuthentikSettings()))
|
||||||
|
|
||||||
@router.post("/authentik/hook/")
|
@router.post("/authentik/hook/")
|
||||||
async def hook(model: Authentik_Hook_Model,
|
async def hook(model: Authentik_Hook_Model,
|
||||||
|
@ -15,7 +16,10 @@ async def hook(model: Authentik_Hook_Model,
|
||||||
):
|
):
|
||||||
logging.info(model)
|
logging.info(model)
|
||||||
logging.info(http_request)
|
logging.info(http_request)
|
||||||
ec = EventController(Authentik(AuthentikSettings()))
|
|
||||||
if http_request.path == "/api/v3/core/users/":
|
if http_request.path == "/api/v3/core/users/":
|
||||||
background_tasks.add_task(ec.handle_model_created_event, model)
|
background_tasks.add_task(ec.handle_model_created_event, model)
|
||||||
return 200
|
return 200
|
||||||
|
|
||||||
|
@router.get("/authentik/errors/")
|
||||||
|
async def errors():
|
||||||
|
return ec._exceptions
|
|
@ -1,14 +1,14 @@
|
||||||
from app.authentik.models import User
|
from app.authentik.models import AuthentikUser
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from .event_controller import Authentik_Hook_Model, EventController
|
from .event_controller import Authentik_Hook_Model, EventController
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mock_user():
|
def mock_user():
|
||||||
return User(pk="5", username="asd", name="asd", email="asd@example.org")
|
return AuthentikUser(pk="5", username="asd", name="asd", email="asd@example.org")
|
||||||
|
|
||||||
|
|
||||||
def test_handle_model_created_event(mocker: MockerFixture, mock_user: User):
|
def test_handle_model_created_event(mocker: MockerFixture, mock_user: AuthentikUser):
|
||||||
wekan_mock = mocker.MagicMock()
|
wekan_mock = mocker.MagicMock()
|
||||||
wekan_mock.get_user.return_value = None
|
wekan_mock.get_user.return_value = None
|
||||||
nextcloud_mock = mocker.MagicMock()
|
nextcloud_mock = mocker.MagicMock()
|
||||||
|
|
|
@ -7,7 +7,7 @@ from fastapi.testclient import TestClient
|
||||||
|
|
||||||
from .main import app
|
from .main import app
|
||||||
from app.authentik.api import Authentik
|
from app.authentik.api import Authentik
|
||||||
from app.authentik.models import User
|
from app.authentik.models import AuthentikUser
|
||||||
from app.authentik.settings import AuthentikSettings
|
from app.authentik.settings import AuthentikSettings
|
||||||
from app.consumer.wekan.models import User as WekanUser
|
from app.consumer.wekan.models import User as WekanUser
|
||||||
from app.consumer.wekan.api import WekanApi
|
from app.consumer.wekan.api import WekanApi
|
||||||
|
@ -42,13 +42,13 @@ def authentik(settings: AuthentikSettings):
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def authentik_user(authentik):
|
def authentik_user(authentik):
|
||||||
user = authentik.create_user(User(username="foobar", name="Foo Bar", email="foo@bar.com"))
|
user = authentik.create_user(AuthentikUser(username="foobar", name="Foo Bar", email="foo@bar.com"))
|
||||||
yield user
|
yield user
|
||||||
authentik.delete_user(user)
|
authentik.delete_user(user)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_create_user(mocker, authentik_user: WekanUser, wekan: WekanApi):
|
def test_create_user(mocker, authentik_user: AuthentikUser, wekan: WekanApi):
|
||||||
# Actually authentik user creation should already trigger the hook, but in authentik it doesn't trigger when come from api
|
# Actually authentik user creation should already trigger the hook, but in authentik it doesn't trigger when come from api
|
||||||
# mock = mocker.patch("app.event_controller.EventController.handle_model_created_event")
|
# mock = mocker.patch("app.event_controller.EventController.handle_model_created_event")
|
||||||
authentik_message = {"model": {"pk": authentik_user.pk, "app": "authentik_core", "name": authentik_user.name,
|
authentik_message = {"model": {"pk": authentik_user.pk, "app": "authentik_core", "name": authentik_user.name,
|
||||||
|
@ -68,7 +68,13 @@ def test_create_user_with_same_email(wekan_api, authentik_api):
|
||||||
"authentik notifcation rule doesn't work with api?? , create two user with identical email in authentik")
|
"authentik notifcation rule doesn't work with api?? , create two user with identical email in authentik")
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
def test_user_already_exists_excepts(authentik_user: AuthentikUser, wekan: WekanApi):
|
||||||
@pytest.mark.skip()
|
authentik_message = {"model": {"pk": authentik_user.pk, "app": "authentik_core", "name": authentik_user.name,
|
||||||
def test_user_already_exists_excepts():
|
"model_name": "user"}, "http_request": {"args": {}, "path": "/api/v3/core/users/", "method": "POST"}}
|
||||||
assert False
|
response = client.post("/authentik/hook/", json=authentik_message)
|
||||||
|
response = client.post("/authentik/hook/", json=authentik_message)
|
||||||
|
assert response.status_code == 200
|
||||||
|
errors = client.get("/authentik/errors/")
|
||||||
|
assert errors.status_code == 200
|
||||||
|
assert errors.json() == ["[Wekan] User already exists"] # TODO introduce error models
|
||||||
|
wekan.delete_user(wekan.get_user(authentik_user.username).id)
|
||||||
|
|
Loading…
Reference in a new issue