Add new "choir" calendar and add cascading functionality for calendars
All checks were successful
Jenkins Production Deployment
All checks were successful
Jenkins Production Deployment
This commit is contained in:
parent
59fee19a76
commit
cb85e81d67
|
@ -29,6 +29,19 @@ export const checkMemberPrivileges = async (sessionId: string, sessionKey: strin
|
||||||
return password == process.env.MEMBER_CREDENTIAL;
|
return password == process.env.MEMBER_CREDENTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the password gives choir view privileges
|
||||||
|
* @param password
|
||||||
|
*/
|
||||||
|
export const checkChoirPrivileges = async (sessionId: string, sessionKey: string, password: string, ip: string) => {
|
||||||
|
if(sessionId) {
|
||||||
|
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
||||||
|
return user.isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
return password == process.env.CHOIR_CREDENTIAL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the password gives management view privileges
|
* Checks if the password gives management view privileges
|
||||||
* @param password
|
* @param password
|
||||||
|
@ -48,6 +61,8 @@ export const hasAccess = async (calendarName: string, sessionId: string, session
|
||||||
return true;
|
return true;
|
||||||
case 'members':
|
case 'members':
|
||||||
return await checkMemberPrivileges(sessionId, sessionKey, password, ip);
|
return await checkMemberPrivileges(sessionId, sessionKey, password, ip);
|
||||||
|
case 'choir':
|
||||||
|
return await checkChoirPrivileges(sessionId, sessionKey, password, ip);
|
||||||
case 'management':
|
case 'management':
|
||||||
return await checkManagementPrivileges(sessionId, sessionKey, password, ip);
|
return await checkManagementPrivileges(sessionId, sessionKey, password, ip);
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -24,6 +24,7 @@ export const eventsRouter = express.Router();
|
||||||
export const calendarNames = new Map<string, any>([
|
export const calendarNames = new Map<string, any>([
|
||||||
['public', {id: 1, name: 'Nachklang_calendar'}],
|
['public', {id: 1, name: 'Nachklang_calendar'}],
|
||||||
['members', {id: 2, name: 'Nachklang_internal_calendar'}],
|
['members', {id: 2, name: 'Nachklang_internal_calendar'}],
|
||||||
|
['choir', {id: 4, name: 'Nachklang_choir_calendar'}],
|
||||||
['management', {id: 3, name: 'Nachklang_management_calendar'}]
|
['management', {id: 3, name: 'Nachklang_management_calendar'}]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ eventsRouter.get('/:calendar/json', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
||||||
|
|
||||||
|
// If no user was found, check if the password gives access to the calendar
|
||||||
if(user === null || !user.isActive) {
|
if(user === null || !user.isActive) {
|
||||||
if (! await CredentialService.hasAccess(calendarName, sessionId, sessionKey, password, ip)) {
|
if (! await CredentialService.hasAccess(calendarName, sessionId, sessionKey, password, ip)) {
|
||||||
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
||||||
|
|
|
@ -14,6 +14,14 @@ export const getAllEvents = async (calendarId: number): Promise<Event[]> => {
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
let conn = await NachklangCalendarDB.getConnection();
|
||||||
let eventRows: Event[] = [];
|
let eventRows: Event[] = [];
|
||||||
try {
|
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 eventsQuery = `
|
const eventsQuery = `
|
||||||
SELECT e.calendar_id, e.uuid, e.created_date, e.created_by_id, u.full_name, v.* FROM events e
|
SELECT e.calendar_id, e.uuid, e.created_date, e.created_by_id, u.full_name, v.* FROM events e
|
||||||
INNER JOIN (
|
INNER JOIN (
|
||||||
|
@ -25,9 +33,9 @@ export const getAllEvents = async (calendarId: number): Promise<Event[]> => {
|
||||||
INNER JOIN event_versions v
|
INNER JOIN event_versions v
|
||||||
ON v.event_id = latest_versions.event_id AND v.event_version_id = latest_versions.latest_version
|
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
|
LEFT OUTER JOIN users u ON u.user_id = e.created_by_id
|
||||||
WHERE e.calendar_id = ? AND v.status = 'PUBLIC'
|
WHERE e.calendar_id IN (?) AND v.status = 'PUBLIC'
|
||||||
ORDER BY e.event_id`;
|
ORDER BY e.event_id`;
|
||||||
const eventsRes = await conn.query(eventsQuery, calendarId);
|
const eventsRes = await conn.query(eventsQuery, [calendarsToFetch]);
|
||||||
|
|
||||||
for (let row of eventsRes) {
|
for (let row of eventsRes) {
|
||||||
eventRows.push({
|
eventRows.push({
|
||||||
|
@ -56,6 +64,11 @@ export const getAllEvents = async (calendarId: number): Promise<Event[]> => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all events for the given calendar for the admin UI (therefore includes admin relevant information and
|
||||||
|
* ignores the calendar includes
|
||||||
|
* @param calendarId
|
||||||
|
*/
|
||||||
export const getAllEventsAdmin = async (calendarId: number): Promise<Event[]> => {
|
export const getAllEventsAdmin = async (calendarId: number): Promise<Event[]> => {
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
let conn = await NachklangCalendarDB.getConnection();
|
||||||
let eventRows: Event[] = [];
|
let eventRows: Event[] = [];
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import {Event} from './event.interface';
|
import {Event} from './event.interface';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to external classes - Turns the given events into an ical string
|
||||||
|
* @param events
|
||||||
|
*/
|
||||||
export const convertToIcal = async (events: Event[]): Promise<string> => {
|
export const convertToIcal = async (events: Event[]): Promise<string> => {
|
||||||
try {
|
try {
|
||||||
let ical: iCalFile = {body: []};
|
let ical: iCalFile = {body: []};
|
||||||
|
@ -15,6 +19,10 @@ export const convertToIcal = async (events: Event[]): Promise<string> => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to serialize an iCalFile object into an ical string
|
||||||
|
* @param ical
|
||||||
|
*/
|
||||||
const serializeIcalFile = (ical: iCalFile): string => {
|
const serializeIcalFile = (ical: iCalFile): string => {
|
||||||
let returnString = '';
|
let returnString = '';
|
||||||
|
|
||||||
|
@ -27,6 +35,10 @@ const serializeIcalFile = (ical: iCalFile): string => {
|
||||||
return returnString;
|
return returnString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to serialize a single ical event into an ical event string
|
||||||
|
* @param icalevent
|
||||||
|
*/
|
||||||
const serializeIcalEvent = (icalevent: iCalEvent): string => {
|
const serializeIcalEvent = (icalevent: iCalEvent): string => {
|
||||||
let returnString = '';
|
let returnString = '';
|
||||||
|
|
||||||
|
@ -50,7 +62,10 @@ const serializeIcalEvent = (icalevent: iCalEvent): string => {
|
||||||
return returnString;
|
return returnString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to generate the ical header string
|
||||||
|
* @param ical
|
||||||
|
*/
|
||||||
const generateHeaderInfo = (ical: iCalFile) => {
|
const generateHeaderInfo = (ical: iCalFile) => {
|
||||||
ical.header = 'BEGIN:VCALENDAR\n' +
|
ical.header = 'BEGIN:VCALENDAR\n' +
|
||||||
'VERSION:2.0\n' +
|
'VERSION:2.0\n' +
|
||||||
|
@ -78,14 +93,27 @@ const generateHeaderInfo = (ical: iCalFile) => {
|
||||||
'END:VTIMEZONE\n';
|
'END:VTIMEZONE\n';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to generate the ical footer info
|
||||||
|
* @param ical
|
||||||
|
*/
|
||||||
const generateFooterInfo = (ical: iCalFile) => {
|
const generateFooterInfo = (ical: iCalFile) => {
|
||||||
ical.footer = 'END:VCALENDAR';
|
ical.footer = 'END:VCALENDAR';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to add events to the iCalFile object
|
||||||
|
* @param ical
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
const addEventToFile = (ical: iCalFile, event: Event) => {
|
const addEventToFile = (ical: iCalFile, event: Event) => {
|
||||||
ical.body.push(createIcalEvent(event));
|
ical.body.push(createIcalEvent(event));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to turn an event object into an iCalEvent object
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
const createIcalEvent = (event: Event): iCalEvent => {
|
const createIcalEvent = (event: Event): iCalEvent => {
|
||||||
let description = event.description ? event.description + '\n' : '';
|
let description = event.description ? event.description + '\n' : '';
|
||||||
let location = event.location ? event.location + '\n' : '';
|
let location = event.location ? event.location + '\n' : '';
|
||||||
|
@ -107,6 +135,12 @@ const createIcalEvent = (event: Event): iCalEvent => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to format dates in a valid iCal format
|
||||||
|
* @param date
|
||||||
|
* @param wholeDayFormat
|
||||||
|
* @param isEndDate
|
||||||
|
*/
|
||||||
const formatDate = (date: Date, wholeDayFormat: boolean = false, isEndDate: boolean = false): string => {
|
const formatDate = (date: Date, wholeDayFormat: boolean = false, isEndDate: boolean = false): string => {
|
||||||
let returnString = '';
|
let returnString = '';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user