mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Merge pull request #3732 from modoboa/fix/better_frontend_auth
Faster frontend authentication.
This commit is contained in:
@@ -490,9 +490,6 @@ router.beforeEach(async (to, from, next) => {
|
||||
const previousPage = window.location.href
|
||||
sessionStorage.setItem('previousPage', previousPage)
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.authUser) {
|
||||
await authStore.initialize()
|
||||
}
|
||||
const isAuth = await authStore.validateAccess()
|
||||
if (isAuth) {
|
||||
if (to.meta.allowedRoles !== undefined) {
|
||||
|
||||
@@ -106,17 +106,6 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
})
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
if (isAuthenticated.value) {
|
||||
return null
|
||||
}
|
||||
const user = await manager.getUser()
|
||||
if (!user) {
|
||||
return null
|
||||
}
|
||||
return fetchUser()
|
||||
}
|
||||
|
||||
async function validateAccess() {
|
||||
const user = await manager.getUser()
|
||||
if (!user || user.expired) {
|
||||
@@ -124,6 +113,9 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
}
|
||||
repository.defaults.headers.common.Authorization = `Bearer ${user.access_token}`
|
||||
repository.defaults.headers.post['Content-Type'] = 'application/json'
|
||||
if (!isAuthenticated.value) {
|
||||
await fetchUser()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -137,7 +129,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
|
||||
async function completeLogin(redirectUrl) {
|
||||
try {
|
||||
const user = await manager.signinRedirectCallback()
|
||||
const user = await manager.signinCallback()
|
||||
isAuthenticated.value = true
|
||||
const previousPage = sessionStorage.getItem('previousPage')
|
||||
// Redirect the user to the previous page if available
|
||||
@@ -204,7 +196,6 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
addFidoCred,
|
||||
deleteFidoCreds,
|
||||
editFidoCred,
|
||||
initialize,
|
||||
login,
|
||||
$reset,
|
||||
updateAccount,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { useAuthStore } from '@/stores'
|
||||
import { useModoboaTheme } from '@/composables/theme'
|
||||
|
||||
@@ -10,10 +9,7 @@ const props = defineProps({
|
||||
const authStore = useAuthStore()
|
||||
const { enableTheme } = useModoboaTheme()
|
||||
|
||||
onMounted(() => {
|
||||
authStore.completeLogin(props.redirectUrl)
|
||||
})
|
||||
|
||||
await authStore.completeLogin(props.redirectUrl)
|
||||
await enableTheme()
|
||||
</script>
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
return self.dnsrecord_set.filter(type="autodiscover").first()
|
||||
|
||||
@cached_property
|
||||
def allocated_quota(self):
|
||||
def allocated_quota(self) -> int:
|
||||
"""Return current quota allocation."""
|
||||
if not self.quota:
|
||||
return 0
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Admin model mixins."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from modoboa.policyd.utils import get_message_counter
|
||||
|
||||
|
||||
@@ -18,7 +20,7 @@ class MessageLimitMixin:
|
||||
return self.message_limit - get_message_counter(self.message_counter_key)
|
||||
|
||||
@property
|
||||
def sent_messages_in_percent(self):
|
||||
def sent_messages_in_percent(self) -> Optional[int]: # noqa
|
||||
"""Return number of sent messages as a percentage."""
|
||||
if not self.message_limit:
|
||||
return None
|
||||
|
||||
@@ -62,7 +62,7 @@ class ARMessageViewSetTestCase(PatcherMixin, ModoAPITestCase):
|
||||
def test_retrieve_armessage_domadmin(self):
|
||||
admin = User.objects.get(username="admin@test.com")
|
||||
self.client.logout()
|
||||
self.client.force_login(admin)
|
||||
self.client.force_authenticate(admin)
|
||||
url = reverse("api:armessage-list")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -74,7 +74,7 @@ class ARMessageViewSetTestCase(PatcherMixin, ModoAPITestCase):
|
||||
|
||||
def test_retrieve_armessage_simpleuser(self):
|
||||
self.client.logout()
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
url = reverse("api:armessage-list")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -156,7 +156,7 @@ class AccountARMessageViewSetTestCase(PatcherMixin, ModoAPITestCase):
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.client.logout()
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
self.assertFalse(
|
||||
models.ARmessage.objects.filter(mbox=self.account.mailbox).exists()
|
||||
)
|
||||
@@ -168,7 +168,7 @@ class AccountARMessageViewSetTestCase(PatcherMixin, ModoAPITestCase):
|
||||
|
||||
def test_set_armessage(self):
|
||||
self.client.logout()
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
url = reverse("api:account_armessage-armessage")
|
||||
fromdate = timezone.now()
|
||||
todate = fromdate + relativedelta(days=4)
|
||||
|
||||
@@ -13,7 +13,7 @@ from modoboa.admin import factories as admin_factories
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.core import factories as core_factories
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib.tests import ModoTestCase, ModoAPITestCase
|
||||
from modoboa.lib.tests import ModoAPITestCase
|
||||
|
||||
from modoboa.admin.factories import populate_database
|
||||
|
||||
@@ -53,7 +53,7 @@ class TestDataMixin:
|
||||
cls.scalendar2 = factories.SharedCalendarFactory(domain=cls.domain2)
|
||||
|
||||
|
||||
class AccessRuleTestCase(ModoTestCase):
|
||||
class AccessRuleTestCase(ModoAPITestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@@ -139,7 +139,7 @@ class UserCalendarViewSetTestCase(TestDataMixin, ModoAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
self.set_global_parameter("server_location", "http://localhost:5232")
|
||||
|
||||
def test_get_calendars(self):
|
||||
@@ -214,7 +214,7 @@ class SharedCalendarViewSetTestCase(TestDataMixin, ModoAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
self.client.force_login(self.admin_account)
|
||||
self.client.force_authenticate(self.admin_account)
|
||||
self.set_global_parameter("server_location", "http://localhost:5232")
|
||||
|
||||
def test_get_calendars(self):
|
||||
@@ -304,7 +304,7 @@ class AccessRuleViewSetTestCase(TestDataMixin, ModoAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
|
||||
def test_get_accessrules(self):
|
||||
"""Test access rule retrieval."""
|
||||
@@ -383,7 +383,7 @@ class EventViewSetTestCase(TestDataMixin, ModoAPITestCase):
|
||||
self.cal_mock.return_value = mocks.Calendar(client=self.client_mock)
|
||||
self.addCleanup(patcher2.stop)
|
||||
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
self.set_global_parameter("server_location", "http://localhost")
|
||||
|
||||
def test_get_user_events(self):
|
||||
@@ -550,7 +550,7 @@ class AttendeeViewSetTestCase(ModoAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
|
||||
def test_get_attendees(self):
|
||||
"""Test attendees retrieval."""
|
||||
@@ -571,7 +571,7 @@ class MailboxViewSetTestCase(ModoAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
self.client.force_login(self.account)
|
||||
self.client.force_authenticate(self.account)
|
||||
|
||||
def test_get_mailboxes(self):
|
||||
"""Test mailbox retrieval."""
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.utils import timezone
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib.tests import ModoAPITestCase, ModoTestCase
|
||||
from modoboa.lib.tests import ModoAPITestCase
|
||||
|
||||
from . import factories
|
||||
from . import mocks
|
||||
@@ -46,7 +46,7 @@ class TestDataMixin:
|
||||
|
||||
def setUp(self, *args, **kwargs):
|
||||
"""Initiate test context."""
|
||||
self.client.force_login(self.user)
|
||||
self.client.force_authenticate(self.user)
|
||||
self.set_global_parameter(
|
||||
"server_location", "http://example.test/radicale/", app="calendars"
|
||||
)
|
||||
@@ -72,8 +72,7 @@ class ViewsTestCase(TestDataMixin, ModoAPITestCase):
|
||||
def test_user_settings(self):
|
||||
"""Check that remote collection creation request is sent."""
|
||||
# 1. Addressbook with contacts must be synced manually
|
||||
data = {"username": self.user.username, "password": "toto"}
|
||||
self.client.post(reverse("core:login"), data)
|
||||
self.client.force_authenticate(self.user)
|
||||
self.enable_cdav_sync()
|
||||
self.addressbook.refresh_from_db()
|
||||
self.assertIs(self.addressbook.last_sync, None)
|
||||
@@ -81,8 +80,7 @@ class ViewsTestCase(TestDataMixin, ModoAPITestCase):
|
||||
# 2. Addressbook with no contacts can be considered synced
|
||||
user = core_models.User.objects.get(username="user@test2.com")
|
||||
abook = user.addressbook_set.first()
|
||||
data = {"username": user.username, "password": "toto"}
|
||||
self.client.post(reverse("core:login"), data)
|
||||
self.client.force_authenticate(user)
|
||||
abook.refresh_from_db()
|
||||
self.assertIs(abook.last_sync, None)
|
||||
# Now enable sync.
|
||||
@@ -312,7 +310,7 @@ class EmailAddressViewSetTestCase(TestDataMixin, ModoAPITestCase):
|
||||
self.assertEqual(len(response.data), 3)
|
||||
|
||||
|
||||
class ImportTestCase(TestDataMixin, ModoTestCase):
|
||||
class ImportTestCase(TestDataMixin, ModoAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
from modoboa.lib.tests import ModoAPITestCase
|
||||
|
||||
|
||||
class OpenAPITestCase(ModoTestCase):
|
||||
class OpenAPITestCase(ModoAPITestCase):
|
||||
openapi_schema_url = reverse_lazy("schema-v1-legacy")
|
||||
|
||||
def test_unauthorized(self):
|
||||
|
||||
@@ -235,7 +235,6 @@ REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
),
|
||||
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
|
||||
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning',
|
||||
|
||||
@@ -220,7 +220,7 @@ class User(AbstractUser):
|
||||
return self.email
|
||||
|
||||
@property
|
||||
def tfa_enabled(self):
|
||||
def tfa_enabled(self) -> bool:
|
||||
return self.totp_enabled or self.webauthn_enabled
|
||||
|
||||
def is_owner(self, obj):
|
||||
|
||||
@@ -158,6 +158,8 @@ class ProfileTestCase(LDAPTestCaseMixin, ModoAPITestCase):
|
||||
|
||||
username = "testuser@example.com"
|
||||
self.authenticate(username, "test")
|
||||
user = models.User.objects.get(username=username)
|
||||
self.client.force_authenticate(user)
|
||||
response = self.client.post(
|
||||
reverse("v2:account-set-me-password"),
|
||||
{"password": "test", "new_password": "Toto1234"},
|
||||
|
||||
@@ -252,7 +252,6 @@ REST_FRAMEWORK = {
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
|
||||
"rest_framework.authentication.TokenAuthentication",
|
||||
"rest_framework.authentication.SessionAuthentication",
|
||||
),
|
||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning",
|
||||
|
||||
Reference in New Issue
Block a user