Fix scouthub-home-be

This commit is contained in:
Lorenzo Sanesi
2026-07-25 12:09:12 +02:00
parent ac92ca43ce
commit 5b7c82d359
39 changed files with 2116 additions and 81 deletions
@@ -1,5 +1,5 @@
import { Request, Response, NextFunction } from 'express';
import { createGruppo } from '../services/gruppi.service';
import { createGruppo, listGruppi, listGruppiPubblico } from '../services/gruppi.service';
import { HttpError } from '../errors';
interface PostGruppoBody {
@@ -40,3 +40,21 @@ export async function postGruppo(req: Request, res: Response, next: NextFunction
next(err);
}
}
export async function getGruppi(_req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const gruppi = await listGruppi();
res.status(200).json(gruppi);
} catch (err) {
next(err);
}
}
export async function getGruppiElencoPubblico(_req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const gruppi = await listGruppiPubblico();
res.status(200).json(gruppi);
} catch (err) {
next(err);
}
}
@@ -20,12 +20,6 @@ function parseCreaInvitoBody(body: PostInvitoBody): { email: string; ruolo: stri
export async function postInvito(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { orgId } = req.params;
// Un capo gruppo può invitare solo all'interno della propria organization.
if (req.auth?.organizationId !== orgId) {
throw new HttpError(403, "Non puoi invitare persone in un'organizzazione diversa dalla tua");
}
const { email, ruolo } = parseCreaInvitoBody(req.body ?? {});
const result = await creaInvito({ orgId, email, ruolo });
@@ -0,0 +1,42 @@
import { Request, Response, NextFunction } from 'express';
import { creaOTrovaLinkIngresso, getLinkIngressoPubblico, richiediIngresso } from '../services/linkIngresso.service';
import { HttpError } from '../errors';
export async function postLinkIngresso(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { orgId } = req.params;
const { giaEsistente, ...result } = await creaOTrovaLinkIngresso(orgId, req.auth!.userId);
res.status(giaEsistente ? 200 : 201).json(result);
} catch (err) {
next(err);
}
}
export async function getLinkIngresso(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { token } = req.params;
const link = await getLinkIngressoPubblico(token);
if (!link) {
throw new HttpError(404, 'Link di ingresso non trovato');
}
res.json(link);
} catch (err) {
next(err);
}
}
export async function postRichiediIngresso(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { token } = req.params;
const result = await richiediIngresso(token, {
userId: req.auth!.userId,
email: req.auth!.email,
});
res.status(201).json(result);
} catch (err) {
next(err);
}
}
@@ -1,18 +1,36 @@
import { Request, Response, NextFunction } from 'express';
import { listaMembri, cambiaRuoloMembro, rimuoviMembro } from '../services/membri.service';
import { listaMembri, cambiaRuoloMembro, rimuoviMembro, aggiungiMembro } from '../services/membri.service';
import { HttpError } from '../errors';
function checkOrgAccess(req: Request): string {
const { orgId } = req.params;
if (req.auth?.organizationId !== orgId) {
throw new HttpError(403, "Non puoi gestire membri di un'organizzazione diversa dalla tua");
interface PostMembroBody {
email?: unknown;
ruolo?: unknown;
}
function parseAggiungiMembroBody(body: PostMembroBody): { email: string; ruolo: string } {
if (typeof body.email !== 'string' || body.email.trim().length === 0) {
throw new HttpError(400, "Il campo 'email' è obbligatorio ed è una stringa non vuota");
}
if (typeof body.ruolo !== 'string' || body.ruolo.trim().length === 0) {
throw new HttpError(400, "Il campo 'ruolo' è obbligatorio ed è una stringa non vuota");
}
return { email: body.email, ruolo: body.ruolo };
}
export async function postMembro(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { orgId } = req.params;
const { email, ruolo } = parseAggiungiMembroBody(req.body ?? {});
const result = await aggiungiMembro({ orgId, email, ruolo });
res.status(201).json(result);
} catch (err) {
next(err);
}
return orgId;
}
export async function getMembri(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const orgId = checkOrgAccess(req);
const { orgId } = req.params;
const membri = await listaMembri(orgId);
res.json(membri);
} catch (err) {
@@ -22,8 +40,7 @@ export async function getMembri(req: Request, res: Response, next: NextFunction)
export async function putRuoloMembro(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const orgId = checkOrgAccess(req);
const { userId } = req.params;
const { orgId, userId } = req.params;
const { ruolo } = req.body ?? {};
if (typeof ruolo !== 'string' || ruolo.trim().length === 0) {
@@ -39,8 +56,7 @@ export async function putRuoloMembro(req: Request, res: Response, next: NextFunc
export async function deleteMembro(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const orgId = checkOrgAccess(req);
const { userId } = req.params;
const { orgId, userId } = req.params;
await rimuoviMembro(orgId, userId);
res.status(204).send();
@@ -0,0 +1,74 @@
import { Request, Response, NextFunction } from 'express';
import {
creaRichiestaCreazioneGruppo,
listaRichiestePending,
approvaRichiesta,
rifiutaRichiesta,
} from '../services/richiesteCreazioneGruppo.service';
import { HttpError } from '../errors';
interface PostRichiestaBody {
nomeProposto?: unknown;
regione?: unknown;
}
function parsePostBody(body: PostRichiestaBody): { nomeProposto: string; regione?: string } {
if (typeof body.nomeProposto !== 'string' || body.nomeProposto.trim().length === 0) {
throw new HttpError(400, "Il campo 'nomeProposto' è obbligatorio ed è una stringa non vuota");
}
if (body.regione !== undefined && typeof body.regione !== 'string') {
throw new HttpError(400, "Il campo 'regione', se presente, deve essere una stringa");
}
return { nomeProposto: body.nomeProposto, regione: body.regione as string | undefined };
}
export async function postRichiestaCreazioneGruppo(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { nomeProposto, regione } = parsePostBody(req.body ?? {});
const result = await creaRichiestaCreazioneGruppo({
userId: req.auth!.userId,
email: req.auth!.email,
nomeProposto,
regione,
});
res.status(201).json(result);
} catch (err) {
next(err);
}
}
export async function getRichiesteCreazioneGruppo(_req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const richieste = await listaRichiestePending();
res.json(richieste);
} catch (err) {
next(err);
}
}
interface PutRichiestaBody {
esito?: unknown;
}
function parsePutBody(body: PutRichiestaBody): 'approvata' | 'rifiutata' {
if (body.esito !== 'approvata' && body.esito !== 'rifiutata') {
throw new HttpError(400, "Il campo 'esito' deve essere 'approvata' o 'rifiutata'");
}
return body.esito;
}
export async function putRichiestaCreazioneGruppo(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { id } = req.params;
const esito = parsePutBody(req.body ?? {});
const result = esito === 'approvata' ? await approvaRichiesta(id) : await rifiutaRichiesta(id);
res.status(200).json(result);
} catch (err) {
next(err);
}
}
@@ -0,0 +1,67 @@
import { Request, Response, NextFunction } from 'express';
import {
creaRichiestaIngresso,
listaRichiestePending,
approvaRichiesta,
rifiutaRichiesta,
ORIGINE_RICHIESTA,
} from '../services/richiesteIngresso.service';
import { HttpError } from '../errors';
export async function postRichiestaIngresso(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { orgId } = req.params;
const result = await creaRichiestaIngresso(
orgId,
{ userId: req.auth!.userId, email: req.auth!.email },
ORIGINE_RICHIESTA.PROFILO,
);
res.status(201).json(result);
} catch (err) {
next(err);
}
}
export async function getRichiesteIngresso(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { orgId } = req.params;
const richieste = await listaRichiestePending(orgId);
res.json(richieste);
} catch (err) {
next(err);
}
}
interface PutRichiestaBody {
esito?: unknown;
ruolo?: unknown;
}
function parsePutBody(body: PutRichiestaBody): { esito: 'approvata' | 'rifiutata'; ruolo?: string } {
if (body.esito !== 'approvata' && body.esito !== 'rifiutata') {
throw new HttpError(400, "Il campo 'esito' deve essere 'approvata' o 'rifiutata'");
}
if (body.esito === 'approvata') {
if (typeof body.ruolo !== 'string' || body.ruolo.trim().length === 0) {
throw new HttpError(400, "Il campo 'ruolo' è obbligatorio quando esito è 'approvata'");
}
return { esito: body.esito, ruolo: body.ruolo };
}
return { esito: body.esito };
}
export async function putRichiestaIngresso(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { orgId, id } = req.params;
const { esito, ruolo } = parsePutBody(req.body ?? {});
const result =
esito === 'approvata' ? await approvaRichiesta(orgId, id, ruolo!) : await rifiutaRichiesta(orgId, id);
res.status(200).json(result);
} catch (err) {
next(err);
}
}