Error handling on signup, login and home view
This commit is contained in:
@@ -7,7 +7,7 @@ public class MaxLengthRule : AbstractRule
|
|||||||
{
|
{
|
||||||
private readonly string _stringValue;
|
private readonly string _stringValue;
|
||||||
private readonly int _maximumLentgh;
|
private readonly int _maximumLentgh;
|
||||||
protected override string ErrorCode => "minimum_length";
|
protected override string ErrorCode => "maximum_length";
|
||||||
protected override string ErrorMessage
|
protected override string ErrorMessage
|
||||||
=> $"Length of '{ValueObjectName}' must be at most {_maximumLentgh} characters";
|
=> $"Length of '{ValueObjectName}' must be at most {_maximumLentgh} characters";
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ namespace AipsCore.Infrastructure.Authentication.AuthService;
|
|||||||
|
|
||||||
public class EfAuthService : IAuthService
|
public class EfAuthService : IAuthService
|
||||||
{
|
{
|
||||||
private readonly AipsDbContext _dbContext;
|
|
||||||
private readonly UserManager<Persistence.User.User> _userManager;
|
private readonly UserManager<Persistence.User.User> _userManager;
|
||||||
|
|
||||||
public EfAuthService(AipsDbContext dbContext, UserManager<Persistence.User.User> userManager)
|
public EfAuthService(UserManager<Persistence.User.User> userManager)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,8 +25,8 @@ public class EfAuthService : IAuthService
|
|||||||
|
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
var errors = string.Join(", ", result.Errors.Select(e => e.Description));
|
var validationErrors = result.Errors.Select(e => new ValidationError(e.Code, e.Description)).ToList();
|
||||||
throw new Exception($"User registration failed: {errors}");
|
throw new ValidationException(validationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userManager.AddToRoleAsync(entity, UserRole.User.Name);
|
await _userManager.AddToRoleAsync(entity, UserRole.User.Name);
|
||||||
|
|||||||
@@ -72,7 +72,14 @@ async function request<T = any>(method: string, url: string, body?: any, attempt
|
|||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const errorBody = await parseJsonOrThrow(res)
|
const errorBody = await parseJsonOrThrow(res)
|
||||||
throw Object.assign(new Error(res.statusText || 'Request failed'), { status: res.status, body: errorBody })
|
|
||||||
|
if (errorBody?.errors) {
|
||||||
|
const messages = errorBody.errors.map((e: any) => e.message ?? e)
|
||||||
|
|
||||||
|
const err = new Error(messages[0]) as any
|
||||||
|
err.messages = messages
|
||||||
|
throw err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await parseJsonOrThrow(res)
|
return await parseJsonOrThrow(res)
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ const selectedJoinPolicy = ref(WhiteboardJoinPolicy.FreeToJoin)
|
|||||||
const maxParticipants = ref(10)
|
const maxParticipants = ref(10)
|
||||||
const showCreateModal = ref(false)
|
const showCreateModal = ref(false)
|
||||||
|
|
||||||
|
const newWhiteboardError = ref<string[]>([])
|
||||||
|
const joinWithCodeError = ref<string[]>([])
|
||||||
|
|
||||||
async function handleCreateNewWhiteboard() {
|
async function handleCreateNewWhiteboard() {
|
||||||
|
newWhiteboardError.value = []
|
||||||
|
|
||||||
if (!whiteboardTitle.value.trim()) {
|
if (!whiteboardTitle.value.trim()) {
|
||||||
alert('Please enter a title for the whiteboard.')
|
alert('Please enter a title for the whiteboard.')
|
||||||
return
|
return
|
||||||
@@ -37,12 +42,16 @@ async function handleCreateNewWhiteboard() {
|
|||||||
maxParticipants.value = 10
|
maxParticipants.value = 10
|
||||||
|
|
||||||
await router.push({ name: 'whiteboard', params: { id: newWhiteboardId } })
|
await router.push({ name: 'whiteboard', params: { id: newWhiteboardId } })
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
console.error('Failed to create new whiteboard', e)
|
newWhiteboardError.value = e.messages || ['Failed to create whiteboard']
|
||||||
|
} finally {
|
||||||
|
whiteboards.isLoading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function joinWithCode() {
|
async function joinWithCode() {
|
||||||
|
joinWithCodeError.value = []
|
||||||
|
|
||||||
if (joinCode.value.length !== 8) {
|
if (joinCode.value.length !== 8) {
|
||||||
alert('Please enter a valid 8-digit code.')
|
alert('Please enter a valid 8-digit code.')
|
||||||
return
|
return
|
||||||
@@ -59,7 +68,7 @@ async function joinWithCode() {
|
|||||||
|
|
||||||
await router.push({ name: 'whiteboard', params: { id: joinResult.whiteboardId } })
|
await router.push({ name: 'whiteboard', params: { id: joinResult.whiteboardId } })
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error(err)
|
joinWithCodeError.value = err.messages || ['Failed to join whiteboard with code']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +108,13 @@ async function joinWithCode() {
|
|||||||
style="min-height: calc(100vh - 56px);"
|
style="min-height: calc(100vh - 56px);"
|
||||||
>
|
>
|
||||||
<div style="width: 320px;">
|
<div style="width: 320px;">
|
||||||
|
|
||||||
|
<div v-if="joinWithCodeError.length" class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
<li v-for="errorMessage in joinWithCodeError" :key="errorMessage">{{ errorMessage }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
v-model="joinCode"
|
v-model="joinCode"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -126,6 +142,13 @@ async function joinWithCode() {
|
|||||||
<button type="button" class="btn-close btn-close-white" @click="showCreateModal = false"></button>
|
<button type="button" class="btn-close btn-close-white" @click="showCreateModal = false"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<div v-if="newWhiteboardError.length" class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
<li v-for="errorMessage in newWhiteboardError" :key="errorMessage">{{ errorMessage }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
v-model="whiteboardTitle"
|
v-model="whiteboardTitle"
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
@@ -8,17 +8,17 @@ const auth = useAuthStore()
|
|||||||
|
|
||||||
const email = ref('')
|
const email = ref('')
|
||||||
const password = ref('')
|
const password = ref('')
|
||||||
const error = ref('')
|
const error = ref<string[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
error.value = ''
|
error.value = []
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
await auth.login({ email: email.value, password: password.value })
|
await auth.login({ email: email.value, password: password.value })
|
||||||
router.push('/')
|
router.push('/')
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error.value = e.message || 'Login failed'
|
error.value = e.messages || ['Login failed']
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,11 @@ async function onSubmit() {
|
|||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<h2 class="card-title text-center mb-4">Log In</h2>
|
<h2 class="card-title text-center mb-4">Log In</h2>
|
||||||
|
|
||||||
<div v-if="error" class="alert alert-danger">{{ error }}</div>
|
<div v-if="error.length" class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
<li v-for="m in error" :key="m">{{ m }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form @submit.prevent="onSubmit">
|
<form @submit.prevent="onSubmit">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
@@ -9,17 +9,17 @@ const auth = useAuthStore()
|
|||||||
const username = ref('')
|
const username = ref('')
|
||||||
const email = ref('')
|
const email = ref('')
|
||||||
const password = ref('')
|
const password = ref('')
|
||||||
const error = ref('')
|
const error = ref<string[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
error.value = ''
|
error.value = []
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
await auth.signup({ username: username.value, email: email.value, password: password.value })
|
await auth.signup({ username: username.value, email: email.value, password: password.value })
|
||||||
router.push('/')
|
router.push('/')
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error.value = e.message || 'Signup failed'
|
error.value = e.messages || ['Signup failed']
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,11 @@ async function onSubmit() {
|
|||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<h2 class="card-title text-center mb-4">Sign Up</h2>
|
<h2 class="card-title text-center mb-4">Sign Up</h2>
|
||||||
|
|
||||||
<div v-if="error" class="alert alert-danger">{{ error }}</div>
|
<div v-if="error.length" class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
<li v-for="m in error" :key="m">{{ m }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form @submit.prevent="onSubmit">
|
<form @submit.prevent="onSubmit">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
Reference in New Issue
Block a user