Add endpoint for getting upcoming event and adding swagger docs to all endpoints

This commit is contained in:
Patrick Müller 2025-04-18 15:05:32 +02:00
parent a38fb20e5a
commit 45dfc22c60
Signed by: Paddy
GPG Key ID: D10B5E2CFD8E7C6D
8 changed files with 1240 additions and 0 deletions

1
app.ts
View File

@ -67,6 +67,7 @@ const options = {
swaggerDefinition,
// Paths to files containing OpenAPI definitions
apis: [
'./src/models/**/*.interface.ts',
'./src/models/**/*.router.ts'
]
};

View File

@ -16,6 +16,39 @@ calendarRouter.use('/events', eventsRouter);
calendarRouter.use('/users', usersRouter);
/**
* @swagger
* /calendar:
* get:
* summary: Calendar API root endpoint
* description: Returns a welcome message for the Nachklang e.V. Calendar API.
* tags:
* - calendar
* responses:
* 200:
* description: Success
* content:
* text/plain:
* schema:
* type: string
* example: Nachklang e.V. Calendar API Endpoint
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
calendarRouter.get('/', async (req: Request, res: Response) => {
try {
res.status(200).send('Nachklang e.V. Calendar API Endpoint');

View File

@ -1,3 +1,84 @@
/**
* @swagger
* components:
* schemas:
* Event:
* type: object
* required:
* - eventId
* - calendarId
* - uuid
* - name
* - description
* - startDateTime
* - endDateTime
* - createdDate
* - location
* - createdById
* - url
* - wholeDay
* properties:
* eventId:
* type: integer
* description: The unique identifier for the event
* example: 123
* calendarId:
* type: integer
* description: The ID of the calendar this event belongs to
* example: 1
* uuid:
* type: string
* description: A unique UUID for the event
* example: "550e8400-e29b-41d4-a716-446655440000"
* name:
* type: string
* description: The name/title of the event
* example: "Concert at Musikhochschule"
* description:
* type: string
* description: A detailed description of the event
* example: "Annual concert at the Musikhochschule"
* startDateTime:
* type: string
* format: date-time
* description: The start date and time of the event
* example: "2023-06-15T19:00:00.000Z"
* endDateTime:
* type: string
* format: date-time
* description: The end date and time of the event
* example: "2023-06-15T21:00:00.000Z"
* createdDate:
* type: string
* format: date-time
* description: The date and time when the event was created
* example: "2023-05-01T10:00:00.000Z"
* location:
* type: string
* description: The location of the event
* example: "Musikhochschule, Karlsruhe"
* createdBy:
* type: string
* description: The name of the user who created the event
* example: "John Doe"
* createdById:
* type: integer
* description: The ID of the user who created the event
* example: 456
* url:
* type: string
* description: A URL with more information about the event
* example: "https://www.nachklang.art/events/concert"
* wholeDay:
* type: boolean
* description: Whether the event lasts the whole day
* example: false
* status:
* type: string
* description: The status of the event
* enum: [PUBLIC, PRIVATE, DRAFT, DELETED]
* example: "PUBLIC"
*/
export interface Event {
eventId: number;
calendarId: number;

View File

@ -33,6 +33,77 @@ export const calendarNames = new Map<string, any>([
* Controller Definitions
*/
/**
* @swagger
* /calendar/events/{calendar}/json:
* get:
* summary: Get all events from a specific calendar in JSON format
* description: Returns all events from the specified calendar in JSON format. Authentication required.
* tags:
* - calendar
* parameters:
* - in: path
* name: calendar
* required: true
* schema:
* type: string
* enum: [public, members, choir, management]
* description: The name of the calendar to get events from
* - in: query
* name: sessionId
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* schema:
* type: string
* description: Session key for authentication
* - in: query
* name: password
* schema:
* type: string
* description: Password for calendar access (if not using session authentication)
* responses:
* 200:
* description: Success
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/Event'
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Please state the name of the calendar you want events from.
* 403:
* description: Forbidden - no access to the calendar
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Internal Server Error. Try again later.
*/
eventsRouter.get('/:calendar/json', async (req: Request, res: Response) => {
try {
// Get request params
@ -80,6 +151,214 @@ eventsRouter.get('/:calendar/json', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/events/{calendar}/json/next:
* get:
* summary: Get the next upcoming event from a calendar
* description: Returns the next upcoming event from the specified calendar. Authentication required.
* tags:
* - calendar
* parameters:
* - in: path
* name: calendar
* required: true
* schema:
* type: string
* enum: [public, members, choir, management]
* description: The name of the calendar to get the next event from
* - in: query
* name: sessionId
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* schema:
* type: string
* description: Session key for authentication
* - in: query
* name: password
* schema:
* type: string
* description: Password for calendar access (if not using session authentication)
* responses:
* 200:
* description: Success
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Event'
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Please state the name of the calendar you want events from.
* 403:
* description: Forbidden - no access to the calendar
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 404:
* description: Not found - no upcoming events
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: No upcoming events found.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
eventsRouter.get('/:calendar/json/next', async (req: Request, res: Response) => {
try {
// Get request params
let calendarName: string = req.params.calendar as string ?? '';
let sessionId: string = req.query.sessionId as string ?? '';
let sessionKey: string = req.query.sessionKey as string ?? '';
let password: string = req.query.password as string ?? '';
let ip: string = req.socket.remoteAddress ?? '';
if (calendarName.length < 1) {
res.status(400).send({'message': 'Please state the name of the calendar you want events from.'});
return;
}
if (!Array.from(calendarNames.keys()).includes(calendarName)) {
res.status(400).send({'message': 'Unknown calendar.'});
return;
}
let calendarId: number = calendarNames.get(calendarName)!.id;
if (! await CredentialService.hasAccess(calendarName, sessionId, sessionKey, password, ip)) {
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
return;
}
// Get next upcoming event
let event = await EventService.getNextUpcomingEvent(calendarId);
if (event === null) {
res.status(404).send({'message': 'No upcoming events found.'});
return;
}
// Send the event back
res.status(200).send(event);
} catch (e: any) {
let errorGuid = Guid.create().toString();
logger.error('Error handling a request: ' + e.message, {reference: errorGuid});
res.status(500).send({
'status': 'PROCESSING_ERROR',
'message': 'Internal Server Error. Try again later.',
'reference': errorGuid
});
}
});
/**
* @swagger
* /calendar/events/{calendar}/ical:
* get:
* summary: Get all events from a specific calendar in iCal format
* description: Returns all events from the specified calendar in iCal format for calendar applications. Authentication required.
* tags:
* - calendar
* parameters:
* - in: path
* name: calendar
* required: true
* schema:
* type: string
* enum: [public, members, choir, management]
* description: The name of the calendar to get events from
* - in: query
* name: sessionId
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* schema:
* type: string
* description: Session key for authentication
* - in: query
* name: password
* schema:
* type: string
* description: Password for calendar access (if not using session authentication)
* responses:
* 200:
* description: Success - returns iCal file
* content:
* text/calendar:
* schema:
* type: string
* format: binary
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Please state the name of the calendar you want events from.
* 403:
* description: Forbidden - no access to the calendar
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
eventsRouter.get('/:calendar/ical', async (req: Request, res: Response) => {
try {
// Get request params
@ -127,6 +406,120 @@ eventsRouter.get('/:calendar/ical', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/events:
* post:
* summary: Create a new event
* description: Creates a new event in the specified calendar. Authentication required.
* tags:
* - calendar
* parameters:
* - in: query
* name: sessionId
* required: true
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* required: true
* schema:
* type: string
* description: Session key for authentication
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - calendarId
* - name
* - startDateTime
* - endDateTime
* properties:
* calendarId:
* type: integer
* example: 1
* name:
* type: string
* example: "Concert at Musikhochschule"
* description:
* type: string
* example: "Annual concert at the Musikhochschule"
* startDateTime:
* type: string
* format: date-time
* example: "2023-06-15T19:00:00.000Z"
* endDateTime:
* type: string
* format: date-time
* example: "2023-06-15T21:00:00.000Z"
* location:
* type: string
* example: "Musikhochschule, Karlsruhe"
* url:
* type: string
* example: "https://www.nachklang.art/events/concert"
* wholeDay:
* type: boolean
* example: false
* status:
* type: string
* enum: [PUBLIC, PRIVATE, DRAFT, DELETED]
* example: "PUBLIC"
* responses:
* 201:
* description: Event created successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Event with id 123 was created successfully.
* eventId:
* type: integer
* example: 123
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Required parameters missing
* 403:
* description: Forbidden - no access to create events
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
eventsRouter.post('/', async (req: Request, res: Response) => {
try {
// Get params
@ -184,6 +577,126 @@ eventsRouter.post('/', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/events/{eventId}:
* put:
* summary: Update an existing event
* description: Updates an existing event with the provided data. Authentication required.
* tags:
* - calendar
* parameters:
* - in: path
* name: eventId
* required: true
* schema:
* type: integer
* description: The ID of the event to update
* - in: query
* name: sessionId
* required: true
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* required: true
* schema:
* type: string
* description: Session key for authentication
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - calendarId
* - name
* - startDateTime
* - endDateTime
* properties:
* calendarId:
* type: integer
* example: 1
* name:
* type: string
* example: "Updated Concert at Musikhochschule"
* description:
* type: string
* example: "Updated annual concert at the Musikhochschule"
* startDateTime:
* type: string
* format: date-time
* example: "2023-06-15T19:00:00.000Z"
* endDateTime:
* type: string
* format: date-time
* example: "2023-06-15T21:00:00.000Z"
* location:
* type: string
* example: "Musikhochschule, Karlsruhe"
* createdBy:
* type: string
* example: "John Doe"
* url:
* type: string
* example: "https://www.nachklang.art/events/concert"
* wholeDay:
* type: boolean
* example: false
* status:
* type: string
* enum: [PUBLIC, PRIVATE, DRAFT, DELETED]
* example: "PUBLIC"
* responses:
* 200:
* description: Event updated successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Event was successfully updated
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Required parameters missing
* 403:
* description: Forbidden - no access to update events
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
try {
// Get params
@ -246,6 +759,124 @@ eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/events/move/{eventId}:
* put:
* summary: Move an event to a different calendar
* description: Moves an existing event to a different calendar. Authentication required.
* tags:
* - calendar
* parameters:
* - in: path
* name: eventId
* required: true
* schema:
* type: integer
* description: The ID of the event to move
* - in: query
* name: sessionId
* required: true
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* required: true
* schema:
* type: string
* description: Session key for authentication
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - calendarId
* properties:
* calendarId:
* type: integer
* example: 2
* description: The ID of the calendar to move the event to
* name:
* type: string
* example: "Concert at Musikhochschule"
* description:
* type: string
* example: "Annual concert at the Musikhochschule"
* startDateTime:
* type: string
* format: date-time
* example: "2023-06-15T19:00:00.000Z"
* endDateTime:
* type: string
* format: date-time
* example: "2023-06-15T21:00:00.000Z"
* location:
* type: string
* example: "Musikhochschule, Karlsruhe"
* createdBy:
* type: string
* example: "John Doe"
* url:
* type: string
* example: "https://www.nachklang.art/events/concert"
* wholeDay:
* type: boolean
* example: false
* status:
* type: string
* enum: [PUBLIC, PRIVATE, DRAFT, DELETED]
* example: "PUBLIC"
* responses:
* 200:
* description: Event moved successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Event was successfully moved
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Required parameters missing
* 403:
* description: Forbidden - no access to move events
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
eventsRouter.put('/move/:eventId', async (req: Request, res: Response) => {
try {
// Get params
@ -303,6 +934,81 @@ eventsRouter.put('/move/:eventId', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/events/{eventId}:
* delete:
* summary: Delete an event
* description: Deletes an existing event. Authentication required.
* tags:
* - calendar
* parameters:
* - in: path
* name: eventId
* required: true
* schema:
* type: integer
* description: The ID of the event to delete
* - in: query
* name: sessionId
* required: true
* schema:
* type: string
* description: Session ID for authentication
* - in: query
* name: sessionKey
* required: true
* schema:
* type: string
* description: Session key for authentication
* responses:
* 200:
* description: Event deleted successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Event was successfully deleted
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Required parameters missing
* 403:
* description: Forbidden - no access to delete events
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: You do not have access to the specified calendar.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
eventsRouter.delete('/:eventId', async (req: Request, res: Response) => {
try {
// Get params

View File

@ -211,3 +211,63 @@ export const moveEvent = async (event: Event): Promise<boolean> => {
await conn.end();
}
}
/**
* Returns the next upcoming event for the given calendar
* @param calendarId The calendar Id
*/
export const getNextUpcomingEvent = async (calendarId: number): Promise<Event | null> => {
let conn = await NachklangCalendarDB.getConnection();
try {
const calendarQuery = 'SELECT calendar_id, includes_calendars FROM calendars WHERE calendar_id = ?';
const calendarRes = await conn.query(calendarQuery, calendarId);
let calendarsToFetch: number[] = [calendarId];
for(let row of calendarRes) {
let includes: number[] = JSON.parse(row.includes_calendars);
calendarsToFetch = [...calendarsToFetch, ...includes];
}
const now = new Date();
const eventsQuery = `
SELECT e.calendar_id, e.uuid, e.created_date, e.created_by_id, u.full_name, v.* FROM events e
INNER JOIN (
SELECT event_id, MAX(event_version_id) AS latest_version
FROM event_versions
GROUP BY event_id
) latest_versions
ON e.event_id = latest_versions.event_id
INNER JOIN event_versions v
ON v.event_id = latest_versions.event_id AND v.event_version_id = latest_versions.latest_version
LEFT OUTER JOIN users u ON u.user_id = e.created_by_id
WHERE e.calendar_id IN (?) AND v.status = 'PUBLIC' AND v.start_datetime > ?
ORDER BY v.start_datetime ASC
LIMIT 1`;
const eventsRes = await conn.query(eventsQuery, [calendarsToFetch, now]);
if (eventsRes.length === 0) {
return null;
}
const row = eventsRes[0];
return {
eventId: row.event_id,
calendarId: row.calendar_id,
uuid: row.uuid,
name: row.name,
description: row.description,
startDateTime: row.start_datetime,
endDateTime: row.end_datetime,
createdDate: row.created_date,
location: row.location,
createdBy: row.full_name,
createdById: row.created_by_id,
url: row.url,
wholeDay: row.whole_day
} as Event;
} catch (err) {
throw err;
} finally {
// Return connection
await conn.end();
}
}

View File

@ -1,3 +1,47 @@
/**
* @swagger
* components:
* schemas:
* Session:
* type: object
* required:
* - sessionId
* - userId
* - sessionKey
* - sessionKeyHash
* - lastIP
* properties:
* sessionId:
* type: integer
* description: The unique identifier for the session
* example: 789
* userId:
* type: integer
* description: The ID of the user this session belongs to
* example: 456
* sessionKey:
* type: string
* description: The session key used for authentication
* example: "abc123def456"
* sessionKeyHash:
* type: string
* description: The hashed session key (not returned in API responses)
* example: "$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG"
* createdDate:
* type: string
* format: date-time
* description: The date and time when the session was created
* example: "2023-05-01T10:00:00.000Z"
* validUntil:
* type: string
* format: date-time
* description: The date and time until when the session is valid
* example: "2023-05-08T10:00:00.000Z"
* lastIP:
* type: string
* description: The last IP address used with this session
* example: "192.168.1.1"
*/
export interface Session {
sessionId: number;
userId: number;

View File

@ -1,3 +1,38 @@
/**
* @swagger
* components:
* schemas:
* User:
* type: object
* required:
* - userId
* - fullName
* - passwordHash
* - email
* - isActive
* properties:
* userId:
* type: integer
* description: The unique identifier for the user
* example: 456
* fullName:
* type: string
* description: The full name of the user
* example: "John Doe"
* passwordHash:
* type: string
* description: The hashed password of the user (not returned in API responses)
* example: "$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG"
* email:
* type: string
* format: email
* description: The email address of the user
* example: "john.doe@nachklang.art"
* isActive:
* type: boolean
* description: Whether the user account is active
* example: true
*/
export interface User {
userId: number;
fullName: string;

View File

@ -20,6 +20,78 @@ export const usersRouter = express.Router();
* Controller Definitions
*/
/**
* @swagger
* /calendar/users/register:
* post:
* summary: Register a new user
* description: Creates a new user account with the provided email, password, and full name. Only accepts official Nachklang email addresses.
* tags:
* - calendar
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* - password
* - fullName
* properties:
* email:
* type: string
* format: email
* example: john.doe@nachklang.art
* description: Must be an official Nachklang email address
* password:
* type: string
* format: password
* example: securePassword123
* fullName:
* type: string
* example: John Doe
* responses:
* 201:
* description: User registered successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* sessionId:
* type: integer
* example: 123
* sessionKey:
* type: string
* example: abc123def456
* 400:
* description: Bad request - missing or invalid parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Missing parameters
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
// POST users/register
usersRouter.post('/register', async (req: Request, res: Response) => {
try {
@ -60,6 +132,71 @@ usersRouter.post('/register', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/users/activate:
* get:
* summary: Activate a user account
* description: Activates a user account using the provided user ID and activation token.
* tags:
* - calendar
* parameters:
* - in: query
* name: id
* required: true
* schema:
* type: integer
* description: The ID of the user to activate
* - in: query
* name: token
* required: true
* schema:
* type: string
* description: The activation token sent to the user's email
* responses:
* 200:
* description: User activated successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: OK
* message:
* type: string
* example: User activated
* 400:
* description: Bad request - missing parameters or activation failed
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Error activating user. Please contact your administrator.
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
// GET /users/activate
usersRouter.get('/activate', async (req: Request, res: Response) => {
try {
@ -95,6 +232,89 @@ usersRouter.get('/activate', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/users/login:
* post:
* summary: Login a user
* description: Authenticates a user with the provided email and password and returns a session.
* tags:
* - calendar
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* - password
* properties:
* email:
* type: string
* format: email
* example: john.doe@nachklang.art
* password:
* type: string
* format: password
* example: securePassword123
* responses:
* 200:
* description: Login successful
* content:
* application/json:
* schema:
* type: object
* properties:
* sessionId:
* type: integer
* example: 123
* sessionKey:
* type: string
* example: abc123def456
* 400:
* description: Bad request - missing parameters
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Missing parameters
* 401:
* description: Unauthorized - invalid credentials
* content:
* application/json:
* schema:
* type: object
* properties:
* message:
* type: string
* example: Wrong username and / or password
* sessionId:
* type: integer
* example: -1
* sessionKey:
* type: string
* example: ""
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
// POST users/login
usersRouter.post('/login', async (req: Request, res: Response) => {
try {
@ -133,6 +353,66 @@ usersRouter.post('/login', async (req: Request, res: Response) => {
}
});
/**
* @swagger
* /calendar/users/checkSessionValid:
* post:
* summary: Check if a session is valid
* description: Checks if the provided session is valid and returns the user information if it is.
* tags:
* - calendar
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - sessionId
* - sessionKey
* properties:
* sessionId:
* type: integer
* example: 123
* sessionKey:
* type: string
* example: abc123def456
* responses:
* 200:
* description: Session is valid
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/User'
* 401:
* description: Unauthorized - invalid session
* content:
* application/json:
* schema:
* type: object
* properties:
* messages:
* type: array
* items:
* type: string
* example: ["Invalid session"]
* 500:
* description: Server error
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: PROCESSING_ERROR
* message:
* type: string
* example: Internal Server Error. Try again later.
* reference:
* type: string
* example: 6ec1361c-4175-4e81-b2ef-a0792a9a1dc3
*/
// POST users/checkSessionValid
usersRouter.post('/checkSessionValid', async (req: Request, res: Response) => {
try {