Compare commits
10 Commits
fcfc8ad1e0
...
5e32c6b431
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e32c6b431 | ||
|
|
7ed986d122 | ||
|
|
58daf7bf30 | ||
|
|
d3365ae065 | ||
|
|
8b3e8a0579 | ||
|
|
ab8d143aeb | ||
|
|
47e4e8ce55 | ||
|
|
20012b729e | ||
|
|
975e3121a5 | ||
|
|
56a28bbff7 |
@@ -1,4 +1,5 @@
|
|||||||
import { BASE_API_URI } from "$lib/utils/constants.js";
|
import { BASE_API_URI } from "$lib/utils/constants.js";
|
||||||
|
import { refreshCookie, userDatesFromRFC3339 } from "$lib/utils/helpers";
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Handle} */
|
/** @type {import('@sveltejs/kit').Handle} */
|
||||||
export async function handle({ event, resolve }) {
|
export async function handle({ event, resolve }) {
|
||||||
@@ -30,52 +31,29 @@ export async function handle({ event, resolve }) {
|
|||||||
|
|
||||||
// Check if the server sent a new token
|
// Check if the server sent a new token
|
||||||
const newToken = response.headers.get("Set-Cookie");
|
const newToken = response.headers.get("Set-Cookie");
|
||||||
if (newToken) {
|
refreshCookie(newToken, event);
|
||||||
const match = newToken.match(/jwt=([^;]+)/);
|
|
||||||
if (match) {
|
|
||||||
event.cookies.set("jwt", match[1], {
|
|
||||||
path: "/",
|
|
||||||
httpOnly: true,
|
|
||||||
secure: process.env.NODE_ENV === "production", // Secure in production
|
|
||||||
sameSite: "lax",
|
|
||||||
maxAge: 5 * 24 * 60 * 60, // 5 days in seconds
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event.locals.subscriptions = data.subscriptions;
|
userDatesFromRFC3339(data.user);
|
||||||
|
|
||||||
|
const [subscriptionsResponse, licenceCategoriesResponse] = await Promise.all([
|
||||||
|
fetch(`${BASE_API_URI}/backend/membership/subscriptions`, {
|
||||||
|
credentials: "include",
|
||||||
|
headers: { Cookie: `jwt=${jwt}` },
|
||||||
|
}),
|
||||||
|
fetch(`${BASE_API_URI}/backend/licence/categories`, {
|
||||||
|
credentials: "include",
|
||||||
|
headers: { Cookie: `jwt=${jwt}` },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
const [subscriptionsData, licence_categoriesData] = await Promise.all([
|
||||||
|
subscriptionsResponse.json(),
|
||||||
|
licenceCategoriesResponse.json(),
|
||||||
|
]);
|
||||||
event.locals.user = data.user;
|
event.locals.user = data.user;
|
||||||
event.locals.licence_categories = data.licence_categories;
|
event.locals.subscriptions = subscriptionsData.subscriptions;
|
||||||
console.dir(event.locals.user);
|
event.locals.licence_categories = licence_categoriesData.licence_categories;
|
||||||
if (event.locals.user.date_of_birth) {
|
// console.log("hooks.server: Printing locals:");
|
||||||
event.locals.user.date_of_birth =
|
// console.dir(event.locals);
|
||||||
event.locals.user.date_of_birth.split("T")[0];
|
|
||||||
}
|
|
||||||
if (event.locals.user.membership) {
|
|
||||||
if (event.locals.user.membership.start_date) {
|
|
||||||
event.locals.user.membership.start_date =
|
|
||||||
event.locals.user.membership.start_date.split("T")[0];
|
|
||||||
}
|
|
||||||
if (event.locals.user.membership.end_date) {
|
|
||||||
event.locals.user.membership.end_date =
|
|
||||||
event.locals.user.membership.end_date.split("T")[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event.locals.user.licence?.issued_date) {
|
|
||||||
event.locals.user.licence.issued_date =
|
|
||||||
event.locals.user.licence.issued_date.split("T")[0];
|
|
||||||
}
|
|
||||||
if (event.locals.user.licence?.expiration_date) {
|
|
||||||
event.locals.user.licence.expiration_date =
|
|
||||||
event.locals.user.licence.expiration_date.split("T")[0];
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
event.locals.user.bank_account &&
|
|
||||||
event.locals.user.bank_account.mandate_date_signed
|
|
||||||
) {
|
|
||||||
event.locals.user.bank_account.mandate_date_signed =
|
|
||||||
event.locals.user.bank_account.mandate_date_signed.split("T")[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// load page as normal
|
// load page as normal
|
||||||
return await resolve(event);
|
return await resolve(event);
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
import { applyAction, enhance } from "$app/forms";
|
import { applyAction, enhance } from "$app/forms";
|
||||||
import { page } from "$app/stores";
|
import { page } from "$app/stores";
|
||||||
// import Developer from "$lib/img/hero-image.png";
|
// import Developer from "$lib/img/hero-image.png";
|
||||||
import Avatar from "$lib/img/TeamAvatar.jpeg";
|
// import Avatar from "$lib/img/TeamAvatar.jpeg";
|
||||||
|
import { t } from "svelte-i18n";
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
console.log("Page data in Header:", $page);
|
console.log("Page data in Header:", $page);
|
||||||
});
|
});
|
||||||
@@ -45,14 +46,22 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="header-nav-item">
|
<div class="header-nav-item">
|
||||||
<a href="/auth/about/{$page.data.user.id}">
|
<a href="/auth/about/{$page.data.user.id}">
|
||||||
<img
|
<!-- <img
|
||||||
src={$page.data.user.profile_picture
|
src={$page.data.user.profile_picture ? $page.data.user.profile_picture : Avatar}
|
||||||
? $page.data.user.profile_picture
|
|
||||||
: Avatar}
|
|
||||||
alt={`${$page.data.user.first_name} ${$page.data.user.last_name}`}
|
alt={`${$page.data.user.first_name} ${$page.data.user.last_name}`}
|
||||||
/>
|
/> -->
|
||||||
|
{$page.data.user.first_name}
|
||||||
|
{$page.data.user.last_name}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
{#if $page.data.user.role_id > 0}
|
||||||
|
<div
|
||||||
|
class="header-nav-item"
|
||||||
|
class:active={$page.url.pathname.startsWith("/auth/admin/users")}
|
||||||
|
>
|
||||||
|
<a href="/auth/admin/users">{$t("user.management")}</a>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<!-- {#if $page.data.user.is_superuser}
|
<!-- {#if $page.data.user.is_superuser}
|
||||||
<div
|
<div
|
||||||
class="header-nav-item"
|
class="header-nav-item"
|
||||||
|
|||||||
@@ -11,8 +11,56 @@
|
|||||||
/** @type {App.Locals['subscriptions']}*/
|
/** @type {App.Locals['subscriptions']}*/
|
||||||
export let subscriptions;
|
export let subscriptions;
|
||||||
|
|
||||||
/** @type {App.Locals['user']}*/
|
/** @type {App.Locals['user'] | null} */
|
||||||
export let user;
|
export let user;
|
||||||
|
if (user == null) {
|
||||||
|
user = {
|
||||||
|
id: 0,
|
||||||
|
email: "",
|
||||||
|
first_name: "",
|
||||||
|
last_name: "",
|
||||||
|
phone: "",
|
||||||
|
address: "",
|
||||||
|
zip_code: "",
|
||||||
|
city: "",
|
||||||
|
company: "",
|
||||||
|
date_of_birth: "",
|
||||||
|
notes: "",
|
||||||
|
profile_picture: "",
|
||||||
|
payment_status: 0,
|
||||||
|
status: 1,
|
||||||
|
role_id: 0,
|
||||||
|
membership: {
|
||||||
|
id: 0,
|
||||||
|
start_date: "",
|
||||||
|
end_date: "",
|
||||||
|
status: 3,
|
||||||
|
parent_member_id: 0,
|
||||||
|
subscription_model: {
|
||||||
|
id: 0,
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
licence: {
|
||||||
|
id: 0,
|
||||||
|
status: 1,
|
||||||
|
licence_number: "",
|
||||||
|
issued_date: "",
|
||||||
|
expiration_date: "",
|
||||||
|
country: "",
|
||||||
|
licence_categories: [],
|
||||||
|
},
|
||||||
|
bank_account: {
|
||||||
|
id: 0,
|
||||||
|
mandate_date_signed: "",
|
||||||
|
bank: "",
|
||||||
|
account_holder_name: "",
|
||||||
|
iban: "",
|
||||||
|
bic: "",
|
||||||
|
mandate_reference: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {App.Locals['licence_categories']} */
|
/** @type {App.Locals['licence_categories']} */
|
||||||
export let licence_categories;
|
export let licence_categories;
|
||||||
@@ -113,7 +161,7 @@
|
|||||||
use:enhance={handleUpdate}
|
use:enhance={handleUpdate}
|
||||||
>
|
>
|
||||||
<input name="id" type="number" hidden bind:value={user.id} />
|
<input name="id" type="number" hidden bind:value={user.id} />
|
||||||
<h1 class="step-title" style="text-align: center;">{$t("user_edit")}</h1>
|
<h1 class="step-title" style="text-align: center;">{$t("user.edit")}</h1>
|
||||||
{#if form?.success}
|
{#if form?.success}
|
||||||
<h4
|
<h4
|
||||||
class="step-subtitle warning"
|
class="step-subtitle warning"
|
||||||
@@ -170,7 +218,7 @@
|
|||||||
<InputField
|
<InputField
|
||||||
name="role_id"
|
name="role_id"
|
||||||
type="select"
|
type="select"
|
||||||
label={$t("user_role")}
|
label={$t("user.role")}
|
||||||
bind:value={user.role_id}
|
bind:value={user.role_id}
|
||||||
options={userRoleOptions}
|
options={userRoleOptions}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -98,8 +98,22 @@ export default {
|
|||||||
L: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 40km/h",
|
L: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 40km/h",
|
||||||
T: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 60km/h",
|
T: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 60km/h",
|
||||||
},
|
},
|
||||||
|
user: {
|
||||||
|
login: "Nutzer Anmeldung",
|
||||||
|
edit: "Nutzer bearbeiten",
|
||||||
|
user: "Nutzer",
|
||||||
|
management: "Mitgliederverwaltung",
|
||||||
|
id: "Mitgliedsnr",
|
||||||
|
name: "Name",
|
||||||
|
email: "Email",
|
||||||
|
status: "Status",
|
||||||
|
role: "Nutzerrolle",
|
||||||
|
},
|
||||||
cancel: "Abbrechen",
|
cancel: "Abbrechen",
|
||||||
confirm: "Bestätigen",
|
confirm: "Bestätigen",
|
||||||
|
actions: "Aktionen",
|
||||||
|
edit: "Bearbeiten",
|
||||||
|
delete: "Löschen",
|
||||||
mandate_date_signed: "Mandatserteilungsdatum",
|
mandate_date_signed: "Mandatserteilungsdatum",
|
||||||
licence_categories: "Führerscheinklassen",
|
licence_categories: "Führerscheinklassen",
|
||||||
subscription_model: "Mitgliedschatfsmodell",
|
subscription_model: "Mitgliedschatfsmodell",
|
||||||
@@ -112,7 +126,6 @@ export default {
|
|||||||
hourly_rate: "Stundensatz",
|
hourly_rate: "Stundensatz",
|
||||||
details: "Details",
|
details: "Details",
|
||||||
conditions: "Bedingungen",
|
conditions: "Bedingungen",
|
||||||
user_role: "Nutzerrolle",
|
|
||||||
unknown: "Unbekannt",
|
unknown: "Unbekannt",
|
||||||
notes: "Notizen",
|
notes: "Notizen",
|
||||||
address: "Straße & Hausnummer",
|
address: "Straße & Hausnummer",
|
||||||
@@ -124,14 +137,12 @@ export default {
|
|||||||
email: "Email",
|
email: "Email",
|
||||||
company: "Firma",
|
company: "Firma",
|
||||||
login: "Anmeldung",
|
login: "Anmeldung",
|
||||||
user: "Nutzer",
|
|
||||||
user_login: "Nutzer Anmeldung",
|
|
||||||
user_edit: "Nutzer bearbeiten",
|
|
||||||
profile: "Profil",
|
profile: "Profil",
|
||||||
membership: "Mitgliedschaft",
|
membership: "Mitgliedschaft",
|
||||||
bankaccount: "Kontodaten",
|
bankaccount: "Kontodaten",
|
||||||
first_name: "Vorname",
|
first_name: "Vorname",
|
||||||
last_name: "Nachname",
|
last_name: "Nachname",
|
||||||
|
name: "Name",
|
||||||
phone: "Telefonnummer",
|
phone: "Telefonnummer",
|
||||||
birth_date: "Geburtstag",
|
birth_date: "Geburtstag",
|
||||||
status: "Status",
|
status: "Status",
|
||||||
|
|||||||
@@ -69,6 +69,81 @@ export function isEmpty(obj) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toRFC3339(dateString) {
|
||||||
|
if (!dateString) dateString = "0001-01-01T00:00:00.000Z";
|
||||||
|
const date = new Date(dateString);
|
||||||
|
return date.toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fromRFC3339(dateString) {
|
||||||
|
if (!dateString) dateString = "0001-01-01T00:00:00.000Z";
|
||||||
|
const date = new Date(dateString);
|
||||||
|
return date.toISOString().split("T")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {App.Locals.User} user - The user object to format
|
||||||
|
*/
|
||||||
|
export function userDatesFromRFC3339(user) {
|
||||||
|
if (user.date_of_birth) {
|
||||||
|
user.date_of_birth = fromRFC3339(user.date_of_birth);
|
||||||
|
}
|
||||||
|
if (user.membership) {
|
||||||
|
if (user.membership.start_date) {
|
||||||
|
user.membership.start_date = fromRFC3339(user.membership.start_date);
|
||||||
|
}
|
||||||
|
if (user.membership.end_date) {
|
||||||
|
user.membership.end_date = fromRFC3339(user.membership.end_date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (user.licence?.issued_date) {
|
||||||
|
user.licence.issued_date = fromRFC3339(user.licence.issued_date);
|
||||||
|
}
|
||||||
|
if (user.licence?.expiration_date) {
|
||||||
|
user.licence.expiration_date = fromRFC3339(user.licence.expiration_date);
|
||||||
|
}
|
||||||
|
if (user.bank_account && user.bank_account.mandate_date_signed) {
|
||||||
|
user.bank_account.mandate_date_signed = fromRFC3339(
|
||||||
|
user.bank_account.mandate_date_signed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats dates in the user object to RFC3339 format
|
||||||
|
* @param {App.Locals.User} user - The user object to format
|
||||||
|
*/
|
||||||
|
export function userDatesToRFC3339(user) {
|
||||||
|
if (user.date_of_birth) {
|
||||||
|
user.date_of_birth = toRFC3339(user.date_of_birth);
|
||||||
|
}
|
||||||
|
if (user.membership) {
|
||||||
|
if (user.membership.start_date) {
|
||||||
|
user.membership.start_date = toRFC3339(user.membership.start_date);
|
||||||
|
}
|
||||||
|
if (user.membership.end_date) {
|
||||||
|
user.membership.end_date = toRFC3339(user.membership.end_date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (user.licence?.issued_date) {
|
||||||
|
user.licence.issued_date = toRFC3339(user.licence.issued_date);
|
||||||
|
}
|
||||||
|
if (user.licence?.expiration_date) {
|
||||||
|
user.licence.expiration_date = toRFC3339(user.licence.expiration_date);
|
||||||
|
}
|
||||||
|
if (user.bank_account && user.bank_account.mandate_date_signed) {
|
||||||
|
user.bank_account.mandate_date_signed = toRFC3339(
|
||||||
|
user.bank_account.mandate_date_signed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} obj - The error object to format
|
||||||
|
* @returns {array} The formatted error object
|
||||||
|
*/
|
||||||
export function formatError(obj) {
|
export function formatError(obj) {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
if (typeof obj === "object" && obj !== null) {
|
if (typeof obj === "object" && obj !== null) {
|
||||||
@@ -98,3 +173,33 @@ export function formatError(obj) {
|
|||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string | null} newToken - The new token for the cookie to set
|
||||||
|
* @param {import('RequestEvent<Partial<Record<string, string>>, string | null>')} event - The event object
|
||||||
|
*/
|
||||||
|
export function refreshCookie(newToken, event) {
|
||||||
|
if (newToken) {
|
||||||
|
const match = newToken.match(/jwt=([^;]+)/);
|
||||||
|
if (match) {
|
||||||
|
if (event) {
|
||||||
|
event.cookies.set("jwt", match[1], {
|
||||||
|
path: "/",
|
||||||
|
httpOnly: true,
|
||||||
|
secure: process.env.NODE_ENV === "production", // Secure in production
|
||||||
|
sameSite: "lax",
|
||||||
|
maxAge: 5 * 24 * 60 * 60, // 5 days in seconds
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cookies.set("jwt", match[1], {
|
||||||
|
path: "/",
|
||||||
|
httpOnly: true,
|
||||||
|
secure: process.env.NODE_ENV === "production", // Secure in production
|
||||||
|
sameSite: "lax",
|
||||||
|
maxAge: 5 * 24 * 60 * 60, // 5 days in seconds
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import { quintOut } from "svelte/easing";
|
|
||||||
import { crossfade } from "svelte/transition";
|
|
||||||
|
|
||||||
export const [send, receive] = crossfade({
|
|
||||||
duration: (d) => Math.sqrt(d * 200),
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
fallback(node, params) {
|
|
||||||
const style = getComputedStyle(node);
|
|
||||||
const transform = style.transform === "none" ? "" : style.transform;
|
|
||||||
|
|
||||||
return {
|
|
||||||
duration: 600,
|
|
||||||
easing: quintOut,
|
|
||||||
css: (t) => `
|
|
||||||
transform: ${transform} scale(${t});
|
|
||||||
opacity: ${t}
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates an email field
|
|
||||||
* @file lib/utils/helpers/input.validation.ts
|
|
||||||
* @param {string} email - The email to validate
|
|
||||||
*/
|
|
||||||
export const isValidEmail = (email) => {
|
|
||||||
const EMAIL_REGEX =
|
|
||||||
/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
|
|
||||||
return EMAIL_REGEX.test(email.trim());
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Validates a strong password field
|
|
||||||
* @file lib/utils/helpers/input.validation.ts
|
|
||||||
* @param {string} password - The password to validate
|
|
||||||
*/
|
|
||||||
export const isValidPasswordStrong = (password) => {
|
|
||||||
const strongRegex = new RegExp(
|
|
||||||
"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})"
|
|
||||||
);
|
|
||||||
|
|
||||||
return strongRegex.test(password.trim());
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Validates a medium password field
|
|
||||||
* @file lib/utils/helpers/input.validation.ts
|
|
||||||
* @param {string} password - The password to validate
|
|
||||||
*/
|
|
||||||
export const isValidPasswordMedium = (password) => {
|
|
||||||
const mediumRegex = new RegExp(
|
|
||||||
"^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})"
|
|
||||||
);
|
|
||||||
|
|
||||||
return mediumRegex.test(password.trim());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether or not an object is empty.
|
|
||||||
* @param {Record<string, string>} obj - The object to test
|
|
||||||
* @returns `true` or `false`
|
|
||||||
*/
|
|
||||||
|
|
||||||
export function isEmpty(obj) {
|
|
||||||
for (const _i in obj) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} FormattedError
|
|
||||||
* @property {string} error - The error message
|
|
||||||
* @property {number} id - A unique identifier for the error
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Format Error object(s)
|
|
||||||
* @param {any} obj - The object to test
|
|
||||||
* @returns @type {FormattedError[]}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export function formatError(obj) {
|
|
||||||
/** @type {FormattedError[]} */
|
|
||||||
const errors = [];
|
|
||||||
if (typeof obj === "object" && obj !== null) {
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
obj.forEach((/** @type {Object} */ error) => {
|
|
||||||
Object.keys(error).map((k) => {
|
|
||||||
errors.push({
|
|
||||||
error: error[k],
|
|
||||||
id: Math.random() * 1000,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Object.keys(obj).map((k) => {
|
|
||||||
errors.push({
|
|
||||||
error: obj[k],
|
|
||||||
id: Math.random() * 1000,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errors.push({
|
|
||||||
error: obj.charAt(0).toUpperCase() + obj.slice(1),
|
|
||||||
id: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toRFC3339(dateString) {
|
|
||||||
if (!dateString) dateString = "0001-01-01T00:00:00.000Z";
|
|
||||||
const date = new Date(dateString);
|
|
||||||
return date.toISOString();
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
/** @type {import('./$types').LayoutLoad} */
|
/** @type {import('./$types').LayoutLoad} */
|
||||||
export async function load({ fetch, url, data }) {
|
export async function load({ fetch, url, data }) {
|
||||||
const { user } = data;
|
const user = data.user;
|
||||||
return { fetch, url: url.pathname, user };
|
const subscriptions = data.subscriptions;
|
||||||
|
const licence_categories = data.licence_categories;
|
||||||
|
return { fetch, url: url.pathname, user, subscriptions, licence_categories };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import { BASE_API_URI } from "$lib/utils/constants";
|
||||||
|
import { refreshCookie } from "$lib/utils/helpers";
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
/** @type {import('./$types').LayoutServerLoad} */
|
/** @type {import('./$types').LayoutServerLoad} */
|
||||||
export async function load({ locals }) {
|
export async function load({ locals, cookies }) {
|
||||||
return {
|
return {
|
||||||
user: locals.user,
|
user: locals.user,
|
||||||
|
licence_categories: locals.licence_categories,
|
||||||
|
subscriptions: locals.subscriptions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
/** @type {import('./$types').LayoutLoad} */
|
|
||||||
export async function load({ fetch, url, data }) {
|
|
||||||
const { user, subscriptions, licence_categories } = data;
|
|
||||||
return { fetch, url: url.pathname, user, subscriptions, licence_categories };
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import { BASE_API_URI } from "$lib/utils/constants";
|
|
||||||
|
|
||||||
/** @type {import('./$types').LayoutServerLoad} */
|
|
||||||
export async function load({ cookies, fetch, locals }) {
|
|
||||||
const jwt = cookies.get("jwt");
|
|
||||||
try {
|
|
||||||
// Fetch user data, subscriptions, and licence categories in parallel
|
|
||||||
const [subscriptionsResponse, licenceCategoriesResponse] =
|
|
||||||
await Promise.all([
|
|
||||||
fetch(`${BASE_API_URI}/backend/membership/subscriptions`, {
|
|
||||||
credentials: "include",
|
|
||||||
headers: { Cookie: `jwt=${jwt}` },
|
|
||||||
}),
|
|
||||||
fetch(`${BASE_API_URI}/backend/licence/categories`, {
|
|
||||||
credentials: "include",
|
|
||||||
headers: { Cookie: `jwt=${jwt}` },
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Check if any of the responses are not ok
|
|
||||||
if (!subscriptionsResponse.ok || !licenceCategoriesResponse.ok) {
|
|
||||||
cookies.delete("jwt", { path: "/" });
|
|
||||||
throw new Error("One or more API requests failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the JSON responses
|
|
||||||
const [subscriptionsData, licence_categoriesData] = await Promise.all([
|
|
||||||
subscriptionsResponse.json(),
|
|
||||||
licenceCategoriesResponse.json(),
|
|
||||||
]);
|
|
||||||
// Check if the server sent a new token
|
|
||||||
const newToken =
|
|
||||||
subscriptionsResponse.headers.get("Set-Cookie") == null
|
|
||||||
? licenceCategoriesResponse.headers.get("Set-Cookie")
|
|
||||||
: subscriptionsResponse.headers.get("Set-Cookie");
|
|
||||||
|
|
||||||
if (newToken) {
|
|
||||||
const match = newToken.match(/jwt=([^;]+)/);
|
|
||||||
if (match) {
|
|
||||||
cookies.set("jwt", match[1], {
|
|
||||||
path: "/",
|
|
||||||
httpOnly: true,
|
|
||||||
secure: process.env.NODE_ENV === "production", // Secure in production
|
|
||||||
sameSite: "lax",
|
|
||||||
maxAge: 5 * 24 * 60 * 60, // 5 days in seconds
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.dir(subscriptionsData);
|
|
||||||
console.dir(licence_categoriesData);
|
|
||||||
return {
|
|
||||||
user: locals.user,
|
|
||||||
subscriptions: subscriptionsData.subscriptions,
|
|
||||||
licence_categories: licence_categoriesData.licence_categories,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching data:", error);
|
|
||||||
// In case of any error, clear the JWT cookie
|
|
||||||
cookies.delete("jwt", { path: "/" });
|
|
||||||
return {
|
|
||||||
user: locals.user,
|
|
||||||
subscriptions: null,
|
|
||||||
licence_categories: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { BASE_API_URI } from "$lib/utils/constants";
|
import { BASE_API_URI } from "$lib/utils/constants";
|
||||||
import { formatError } from "$lib/utils/helpers";
|
import { formatError, userDatesFromRFC3339 } from "$lib/utils/helpers";
|
||||||
import { fail, redirect } from "@sveltejs/kit";
|
import { fail, redirect } from "@sveltejs/kit";
|
||||||
import { toRFC3339 } from "$lib/utils/utils";
|
import { toRFC3339 } from "$lib/utils/helpers";
|
||||||
|
|
||||||
/** @type {import('./$types').PageServerLoad} */
|
/** @type {import('./$types').PageServerLoad} */
|
||||||
export async function load({ locals, params }) {
|
export async function load({ locals, params }) {
|
||||||
@@ -36,6 +36,7 @@ export const actions = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
/** @type {Partial<App.Locals['user']>} */
|
/** @type {Partial<App.Locals['user']>} */
|
||||||
const updateData = {
|
const updateData = {
|
||||||
id: Number(formData.get("id")),
|
id: Number(formData.get("id")),
|
||||||
@@ -111,31 +112,7 @@ export const actions = {
|
|||||||
|
|
||||||
const response = await res.json();
|
const response = await res.json();
|
||||||
locals.user = response;
|
locals.user = response;
|
||||||
|
userDatesFromRFC3339(locals.user);
|
||||||
// Format dates
|
|
||||||
if (locals.user.date_of_birth) {
|
|
||||||
locals.user.date_of_birth = response.date_of_birth.split("T")[0];
|
|
||||||
}
|
|
||||||
if (locals.user.membership?.start_date) {
|
|
||||||
locals.user.membership.start_date =
|
|
||||||
locals.user.membership.start_date.split("T")[0];
|
|
||||||
}
|
|
||||||
if (locals.user.membership?.end_date) {
|
|
||||||
locals.user.membership.end_date =
|
|
||||||
locals.user.membership.end_date.split("T")[0];
|
|
||||||
}
|
|
||||||
if (locals.user.bank_account?.mandate_date_signed) {
|
|
||||||
locals.user.bank_account.mandate_date_signed =
|
|
||||||
locals.user.bank_account.mandate_date_signed.split("T")[0];
|
|
||||||
}
|
|
||||||
if (locals.user.licence?.issued_date) {
|
|
||||||
locals.user.licence.issued_date =
|
|
||||||
locals.user.licence.issued_date.split("T")[0];
|
|
||||||
}
|
|
||||||
if (locals.user.licence?.expiration_date) {
|
|
||||||
locals.user.licence.expiration_date =
|
|
||||||
locals.user.licence.expiration_date.split("T")[0];
|
|
||||||
}
|
|
||||||
throw redirect(303, `/auth/about/${response.id}`);
|
throw redirect(303, `/auth/about/${response.id}`);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import SmallLoader from "$lib/components/SmallLoader.svelte";
|
|
||||||
import Modal from "$lib/components/Modal.svelte";
|
import Modal from "$lib/components/Modal.svelte";
|
||||||
import { onMount } from "svelte";
|
|
||||||
import { applyAction, enhance } from "$app/forms";
|
|
||||||
import { page } from "$app/stores";
|
|
||||||
import { receive, send } from "$lib/utils/helpers";
|
|
||||||
import { t } from "svelte-i18n";
|
|
||||||
import { fly } from "svelte/transition";
|
|
||||||
import UserEditForm from "$lib/components/UserEditForm.svelte";
|
import UserEditForm from "$lib/components/UserEditForm.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { t } from "svelte-i18n";
|
||||||
|
|
||||||
/** @type {import('./$types').ActionData} */
|
/** @type {import('./$types').ActionData} */
|
||||||
export let form;
|
export let form;
|
||||||
|
|
||||||
$: ({ user, subscriptions, licence_categories } = $page.data);
|
$: ({ user, licence_categories, subscriptions } = $page.data);
|
||||||
|
|
||||||
let showModal = false;
|
let showModal = false;
|
||||||
|
|
||||||
|
|||||||
8
frontend/src/routes/auth/admin/users/+layout.js
Normal file
8
frontend/src/routes/auth/admin/users/+layout.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('./$types').LayoutLoad} */
|
||||||
|
export async function load({ fetch, url, data }) {
|
||||||
|
const { users } = data;
|
||||||
|
return {
|
||||||
|
users: data.users,
|
||||||
|
user: data.user,
|
||||||
|
};
|
||||||
|
}
|
||||||
56
frontend/src/routes/auth/admin/users/+layout.server.js
Normal file
56
frontend/src/routes/auth/admin/users/+layout.server.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { BASE_API_URI } from "$lib/utils/constants";
|
||||||
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
import { userDatesFromRFC3339, refreshCookie } from "$lib/utils/helpers";
|
||||||
|
|
||||||
|
/** @type {import('./$types').LayoutServerLoad} */
|
||||||
|
export async function load({ cookies, fetch, locals }) {
|
||||||
|
// if (locals.users) {
|
||||||
|
// return {
|
||||||
|
// users: locals.users,
|
||||||
|
// user: locals.user,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
const jwt = cookies.get("jwt");
|
||||||
|
try {
|
||||||
|
// Fetch user data, subscriptions, and licence categories in parallel
|
||||||
|
const response = await fetch(`${BASE_API_URI}/backend/users/all`, {
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
Cookie: `jwt=${jwt}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
// Clear the invalid JWT cookie
|
||||||
|
cookies.delete("jwt", { path: "/" });
|
||||||
|
throw redirect(302, "/auth/login?next=/");
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// Check if the server sent a new token
|
||||||
|
const newToken = response.headers.get("Set-Cookie");
|
||||||
|
refreshCookie(newToken, null);
|
||||||
|
|
||||||
|
/** @type {App.Locals['users']}*/
|
||||||
|
const users = data.users;
|
||||||
|
|
||||||
|
users.forEach((user) => {
|
||||||
|
userDatesFromRFC3339(user);
|
||||||
|
});
|
||||||
|
|
||||||
|
locals.users = users;
|
||||||
|
return {
|
||||||
|
subscriptions: locals.subscriptions,
|
||||||
|
licence_categories: locals.licence_categories,
|
||||||
|
users: locals.users,
|
||||||
|
user: locals.user,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
// In case of any error, clear the JWT cookie
|
||||||
|
cookies.delete("jwt", { path: "/" });
|
||||||
|
|
||||||
|
throw redirect(302, "/auth/login?next=/");
|
||||||
|
}
|
||||||
|
}
|
||||||
122
frontend/src/routes/auth/admin/users/+page.server.js
Normal file
122
frontend/src/routes/auth/admin/users/+page.server.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
// - Add authentication check to ensure only admins can access this route.
|
||||||
|
// - Implement a load function to fetch a list of all users.
|
||||||
|
// - Create actions for updating user information (similar to the about/[id] route).
|
||||||
|
|
||||||
|
import { BASE_API_URI } from "$lib/utils/constants";
|
||||||
|
import { formatError, userDatesFromRFC3339 } from "$lib/utils/helpers";
|
||||||
|
import { fail, redirect } from "@sveltejs/kit";
|
||||||
|
import { toRFC3339 } from "$lib/utils/helpers";
|
||||||
|
|
||||||
|
/** @type {import('./$types').PageServerLoad} */
|
||||||
|
export async function load({ locals, params }) {
|
||||||
|
// redirect user if not logged in
|
||||||
|
if (!locals.user) {
|
||||||
|
throw redirect(302, `/auth/login?next=/auth/users`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import('./$types').Actions} */
|
||||||
|
export const actions = {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param request - The request object
|
||||||
|
* @param fetch - Fetch object from sveltekit
|
||||||
|
* @param cookies - SvelteKit's cookie object
|
||||||
|
* @param locals - The local object, housing current user
|
||||||
|
* @returns Error data or redirects user to the home page or the previous page
|
||||||
|
*/
|
||||||
|
updateUser: async ({ request, fetch, cookies, locals }) => {
|
||||||
|
let formData = await request.formData();
|
||||||
|
|
||||||
|
const licenceCategories = formData
|
||||||
|
.getAll("licence_categories[]")
|
||||||
|
.filter((value) => typeof value === "string")
|
||||||
|
.map((value) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(value);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse licence category:", value);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
/** @type {Partial<App.Locals['user']>} */
|
||||||
|
const updateData = {
|
||||||
|
id: Number(formData.get("id")),
|
||||||
|
first_name: String(formData.get("first_name")),
|
||||||
|
last_name: String(formData.get("last_name")),
|
||||||
|
email: String(formData.get("email")),
|
||||||
|
phone: String(formData.get("phone")),
|
||||||
|
notes: String(formData.get("notes")),
|
||||||
|
address: String(formData.get("address")),
|
||||||
|
zip_code: String(formData.get("zip_code")),
|
||||||
|
city: String(formData.get("city")),
|
||||||
|
date_of_birth: toRFC3339(formData.get("birth_date")),
|
||||||
|
company: String(formData.get("company")),
|
||||||
|
profile_picture: String(formData.get("profile_picture")),
|
||||||
|
membership: {
|
||||||
|
id: Number(formData.get("membership_id")),
|
||||||
|
start_date: toRFC3339(formData.get("membership_start_date")),
|
||||||
|
end_date: toRFC3339(formData.get("membership_end_date")),
|
||||||
|
status: Number(formData.get("membership_status")),
|
||||||
|
parent_member_id: Number(formData.get("parent_member_id")),
|
||||||
|
subscription_model: {
|
||||||
|
id: Number(formData.get("subscription_model_id")),
|
||||||
|
name: String(formData.get("subscription_model_name")),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bank_account: {
|
||||||
|
id: Number(formData.get("bank_account_id")),
|
||||||
|
mandate_date_signed: toRFC3339(
|
||||||
|
String(formData.get("mandate_date_signed"))
|
||||||
|
),
|
||||||
|
bank: String(formData.get("bank")),
|
||||||
|
account_holder_name: String(formData.get("account_holder_name")),
|
||||||
|
iban: String(formData.get("iban")),
|
||||||
|
bic: String(formData.get("bic")),
|
||||||
|
mandate_reference: String(formData.get("mandate_reference")),
|
||||||
|
},
|
||||||
|
licence: {
|
||||||
|
id: Number(formData.get("drivers_licence_id")),
|
||||||
|
status: Number(formData.get("licence_status")),
|
||||||
|
licence_number: String(formData.get("licence_number")),
|
||||||
|
issued_date: toRFC3339(formData.get("issued_date")),
|
||||||
|
expiration_date: toRFC3339(formData.get("expiration_date")),
|
||||||
|
country: String(formData.get("country")),
|
||||||
|
licence_categories: licenceCategories,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Remove undefined or null properties
|
||||||
|
const cleanUpdateData = JSON.parse(
|
||||||
|
JSON.stringify(updateData),
|
||||||
|
(key, value) => (value !== null && value !== "" ? value : undefined)
|
||||||
|
);
|
||||||
|
console.dir(formData);
|
||||||
|
console.dir(cleanUpdateData);
|
||||||
|
const apiURL = `${BASE_API_URI}/backend/users/update/`;
|
||||||
|
|
||||||
|
/** @type {RequestInit} */
|
||||||
|
const requestUpdateOptions = {
|
||||||
|
method: "PATCH",
|
||||||
|
credentials: "include",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Cookie: `jwt=${cookies.get("jwt")}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cleanUpdateData),
|
||||||
|
};
|
||||||
|
const res = await fetch(apiURL, requestUpdateOptions);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
const response = await res.json();
|
||||||
|
const errors = formatError(response.errors);
|
||||||
|
return fail(400, { errors: errors });
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await res.json();
|
||||||
|
locals.user = response;
|
||||||
|
userDatesFromRFC3339(locals.user);
|
||||||
|
throw redirect(303, `/auth/about/${response.id}`);
|
||||||
|
},
|
||||||
|
};
|
||||||
92
frontend/src/routes/auth/admin/users/+page.svelte
Normal file
92
frontend/src/routes/auth/admin/users/+page.svelte
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<!-- - Create a table or list view of all users.
|
||||||
|
- Implement a search or filter functionality.
|
||||||
|
- Add a modal component for editing user details (reuse the modal from about/[id]). -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import Modal from "$lib/components/Modal.svelte";
|
||||||
|
import UserEditForm from "$lib/components/UserEditForm.svelte";
|
||||||
|
import { t } from "svelte-i18n";
|
||||||
|
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
|
||||||
|
/** @type {import('./$types').ActionData} */
|
||||||
|
export let form;
|
||||||
|
|
||||||
|
$: ({ user, users, licence_categories, subscriptions } = $page.data);
|
||||||
|
|
||||||
|
/** @type(App.Locals['user'] | null) */
|
||||||
|
let selectedUser = null;
|
||||||
|
let showModal = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the edit modal for the selected user.
|
||||||
|
* @param {App.Locals['user']} user The user to edit.
|
||||||
|
*/
|
||||||
|
const openEditModal = (user) => {
|
||||||
|
selectedUser = user;
|
||||||
|
showModal = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the delete modal for the selected user.
|
||||||
|
* @param {App.Locals['user']} user The user to edit.
|
||||||
|
*/
|
||||||
|
const openDelete = (user) => {};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
showModal = false;
|
||||||
|
selectedUser = null;
|
||||||
|
if (form) {
|
||||||
|
form.errors = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="admin-users-page">
|
||||||
|
<h1>{$t("user.management")}</h1>
|
||||||
|
|
||||||
|
<div class="search-filter" />
|
||||||
|
|
||||||
|
<table class="user-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{$t("user.id")}</th>
|
||||||
|
<th>{$t("name")}</th>
|
||||||
|
<th>{$t("email")}</th>
|
||||||
|
<th>{$t("status")}</th>
|
||||||
|
<th>{$t("actions")}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each users as user}
|
||||||
|
<tr>
|
||||||
|
<td>{user.id}</td>
|
||||||
|
<td>{user.first_name} {user.last_name}</td>
|
||||||
|
<td>{user.email}</td>
|
||||||
|
<td>{$t("userStatus." + user.status)}</td>
|
||||||
|
<td>
|
||||||
|
<button on:click={() => openEditModal(user)}>{$t("edit")}</button>
|
||||||
|
<button on:click={() => openDelete(user)}>{$t("delete")}</button>
|
||||||
|
</td>
|
||||||
|
</tr>{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="pagination" />
|
||||||
|
|
||||||
|
{#if showModal}
|
||||||
|
<Modal on:close={close}>
|
||||||
|
<UserEditForm
|
||||||
|
{form}
|
||||||
|
user={selectedUser}
|
||||||
|
{subscriptions}
|
||||||
|
{licence_categories}
|
||||||
|
on:cancel={close}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
action="?/login"
|
action="?/login"
|
||||||
use:enhance={handleLogin}
|
use:enhance={handleLogin}
|
||||||
>
|
>
|
||||||
<h1 class="step-title">{$t("user_login")}</h1>
|
<h1 class="step-title">{$t("user.login")}</h1>
|
||||||
{#if form?.errors}
|
{#if form?.errors}
|
||||||
{#each form?.errors as error (error.id)}
|
{#each form?.errors as error (error.id)}
|
||||||
<h4
|
<h4
|
||||||
|
|||||||
@@ -31,6 +31,58 @@ type RegistrationData struct {
|
|||||||
User models.User `json:"user"`
|
User models.User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (uc *UserController) CurrentUserHandler(c *gin.Context) {
|
||||||
|
userIDInterface, ok := c.Get("user_id")
|
||||||
|
if !ok || userIDInterface == nil {
|
||||||
|
logger.Error.Printf("Error getting user_id from header")
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
||||||
|
"field": "general",
|
||||||
|
"key": "server.validation.no_user_id_provided",
|
||||||
|
}}})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userID, ok := userIDInterface.(uint)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
logger.Error.Printf("Error: user_id is not of type uint")
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
||||||
|
"field": "user",
|
||||||
|
"key": "server.error.internal_server_error",
|
||||||
|
}}})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := uc.Service.GetUserByID(uint(userID))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error.Printf("Error retrieving valid user: %v", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
||||||
|
"field": "general",
|
||||||
|
"key": "server.error.internal_server_error",
|
||||||
|
}}})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"user": user.Safe(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uc *UserController) GetAllUsers(c *gin.Context) {
|
||||||
|
users, err := uc.Service.GetUsers(nil)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error.Printf("Error retrieving users: %v", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
||||||
|
"field": "general",
|
||||||
|
"key": "server.error.internal_server_error",
|
||||||
|
}}})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"users": users,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (uc *UserController) UpdateHandler(c *gin.Context) {
|
func (uc *UserController) UpdateHandler(c *gin.Context) {
|
||||||
var user models.User
|
var user models.User
|
||||||
if err := c.ShouldBindJSON(&user); err != nil {
|
if err := c.ShouldBindJSON(&user); err != nil {
|
||||||
@@ -141,42 +193,6 @@ func (uc *UserController) UpdateHandler(c *gin.Context) {
|
|||||||
c.JSON(http.StatusAccepted, gin.H{"message": "User updated successfully", "user": updatedUser})
|
c.JSON(http.StatusAccepted, gin.H{"message": "User updated successfully", "user": updatedUser})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uc *UserController) CurrentUserHandler(c *gin.Context) {
|
|
||||||
userIDInterface, ok := c.Get("user_id")
|
|
||||||
if !ok || userIDInterface == nil {
|
|
||||||
logger.Error.Printf("Error getting user_id from header")
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
|
||||||
"field": "general",
|
|
||||||
"key": "server.validation.no_user_id_provided",
|
|
||||||
}}})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userID, ok := userIDInterface.(uint)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
logger.Error.Printf("Error: user_id is not of type uint")
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
|
||||||
"field": "user",
|
|
||||||
"key": "server.error.internal_server_error",
|
|
||||||
}}})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := uc.Service.GetUserByID(uint(userID))
|
|
||||||
if err != nil {
|
|
||||||
logger.Error.Printf("Error retrieving valid user: %v", err)
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"errors": []gin.H{{
|
|
||||||
"field": "general",
|
|
||||||
"key": "server.error.internal_server_error",
|
|
||||||
}}})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"user": user.Safe(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (uc *UserController) LogoutHandler(c *gin.Context) {
|
func (uc *UserController) LogoutHandler(c *gin.Context) {
|
||||||
tokenString, err := c.Cookie("jwt")
|
tokenString, err := c.Cookie("jwt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -37,21 +37,9 @@ func Open(dbPath string, adminMail string) error {
|
|||||||
|
|
||||||
logger.Info.Print("Opened DB")
|
logger.Info.Print("Opened DB")
|
||||||
|
|
||||||
var count int64
|
var categoriesCount int64
|
||||||
db.Model(&models.User{}).Count(&count)
|
db.Model(&models.Category{}).Count(&categoriesCount)
|
||||||
if count == 0 {
|
if categoriesCount == 0 {
|
||||||
subscriptionModels := createSubscriptionModels()
|
|
||||||
for _, model := range subscriptionModels {
|
|
||||||
result := db.Create(&model)
|
|
||||||
if result.Error != nil {
|
|
||||||
return result.Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var createdModel models.SubscriptionModel
|
|
||||||
if err := db.First(&createdModel).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
categories := createLicenceCategories()
|
categories := createLicenceCategories()
|
||||||
for _, model := range categories {
|
for _, model := range categories {
|
||||||
result := db.Create(&model)
|
result := db.Create(&model)
|
||||||
@@ -59,6 +47,28 @@ func Open(dbPath string, adminMail string) error {
|
|||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var subscriptionsCount int64
|
||||||
|
db.Model(&models.SubscriptionModel{}).Count(&subscriptionsCount)
|
||||||
|
if subscriptionsCount == 0 {
|
||||||
|
subscriptionModels := createSubscriptionModels()
|
||||||
|
for _, model := range subscriptionModels {
|
||||||
|
result := db.Create(&model)
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var userCount int64
|
||||||
|
db.Model(&models.User{}).Count(&userCount)
|
||||||
|
if userCount == 0 {
|
||||||
|
var createdModel models.SubscriptionModel
|
||||||
|
if err := db.First(&createdModel).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
admin, err := createAdmin(adminMail, createdModel.ID)
|
admin, err := createAdmin(adminMail, createdModel.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -68,6 +78,7 @@ func Open(dbPath string, adminMail string) error {
|
|||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ func RegisterRoutes(router *gin.Engine, userController *controllers.UserControll
|
|||||||
userRouter.GET("/current", userController.CurrentUserHandler)
|
userRouter.GET("/current", userController.CurrentUserHandler)
|
||||||
userRouter.POST("/logout", userController.LogoutHandler)
|
userRouter.POST("/logout", userController.LogoutHandler)
|
||||||
userRouter.PATCH("/update", userController.UpdateHandler)
|
userRouter.PATCH("/update", userController.UpdateHandler)
|
||||||
|
userRouter.GET("/all", userController.GetAllUsers)
|
||||||
}
|
}
|
||||||
|
|
||||||
membershipRouter := router.Group("/backend/membership")
|
membershipRouter := router.Group("/backend/membership")
|
||||||
|
|||||||
@@ -115,6 +115,9 @@ func (service *UserService) GetUserByEmail(email string) (*models.User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (service *UserService) GetUsers(where map[string]interface{}) (*[]models.User, error) {
|
func (service *UserService) GetUsers(where map[string]interface{}) (*[]models.User, error) {
|
||||||
|
if where == nil {
|
||||||
|
where = map[string]interface{}{}
|
||||||
|
}
|
||||||
return service.Repo.GetUsers(where)
|
return service.Repo.GetUsers(where)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user