This commit is contained in:
parent
a38fb20e5a
commit
45dfc22c60
1
app.ts
1
app.ts
|
@ -67,6 +67,7 @@ const options = {
|
||||||
swaggerDefinition,
|
swaggerDefinition,
|
||||||
// Paths to files containing OpenAPI definitions
|
// Paths to files containing OpenAPI definitions
|
||||||
apis: [
|
apis: [
|
||||||
|
'./src/models/**/*.interface.ts',
|
||||||
'./src/models/**/*.router.ts'
|
'./src/models/**/*.router.ts'
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,39 @@ calendarRouter.use('/events', eventsRouter);
|
||||||
calendarRouter.use('/users', usersRouter);
|
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) => {
|
calendarRouter.get('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
res.status(200).send('Nachklang e.V. Calendar API Endpoint');
|
res.status(200).send('Nachklang e.V. Calendar API Endpoint');
|
||||||
|
|
|
@ -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 {
|
export interface Event {
|
||||||
eventId: number;
|
eventId: number;
|
||||||
calendarId: number;
|
calendarId: number;
|
||||||
|
|
|
@ -33,6 +33,77 @@ export const calendarNames = new Map<string, any>([
|
||||||
* Controller Definitions
|
* 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) => {
|
eventsRouter.get('/:calendar/json', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get request params
|
// 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) => {
|
eventsRouter.get('/:calendar/ical', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get request params
|
// 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) => {
|
eventsRouter.post('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// 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) => {
|
eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// 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) => {
|
eventsRouter.put('/move/:eventId', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// 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) => {
|
eventsRouter.delete('/:eventId', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// Get params
|
||||||
|
|
|
@ -211,3 +211,63 @@ export const moveEvent = async (event: Event): Promise<boolean> => {
|
||||||
await conn.end();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
export interface Session {
|
||||||
sessionId: number;
|
sessionId: number;
|
||||||
userId: number;
|
userId: number;
|
||||||
|
|
|
@ -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 {
|
export interface User {
|
||||||
userId: number;
|
userId: number;
|
||||||
fullName: string;
|
fullName: string;
|
||||||
|
|
|
@ -20,6 +20,78 @@ export const usersRouter = express.Router();
|
||||||
* Controller Definitions
|
* 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
|
// POST users/register
|
||||||
usersRouter.post('/register', async (req: Request, res: Response) => {
|
usersRouter.post('/register', async (req: Request, res: Response) => {
|
||||||
try {
|
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
|
// GET /users/activate
|
||||||
usersRouter.get('/activate', async (req: Request, res: Response) => {
|
usersRouter.get('/activate', async (req: Request, res: Response) => {
|
||||||
try {
|
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
|
// POST users/login
|
||||||
usersRouter.post('/login', async (req: Request, res: Response) => {
|
usersRouter.post('/login', async (req: Request, res: Response) => {
|
||||||
try {
|
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
|
// POST users/checkSessionValid
|
||||||
usersRouter.post('/checkSessionValid', async (req: Request, res: Response) => {
|
usersRouter.post('/checkSessionValid', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user