packages/oae-jitsi/lib/rest.js
/*!
* Copyright 2016 Apereo Foundation (AF) Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import _ from 'underscore';
import { AuthzConstants } from 'oae-authz/lib/constants.js';
import * as OAE from 'oae-util/lib/oae.js';
import * as OaeUtil from 'oae-util/lib/util.js';
import * as MeetingsAPI from 'oae-jitsi';
/**
* @REST postMeetingCreate
*
* Create a new meeting
*
* @Server tenant
* @Method POST
* @Path /meeting/create
* @FormParam {string} description A longer description for the meeting
* @FormParam {string} displayName The display name of the meeting
* @FormParam {string} [chat] Flag declaring whether or not Jitsi chat should be enabled
* @FormParam {string} [contactList] Flag declaring whether or not Jitsi contact list should be enabled
* @FormParam {string[]} [managers] Unique identifier(s) for users and groups to add as managers of the meeting. The user creating the meeting will be added as a manager automatically
* @FormParam {string[]} [members] Unique identifier(s) for users and groups to add as members of the meeting
* @FormParam {string} [visibility] The visibility of the meeting. Defaults to the configured tenant default [loggedin,private,public]
* @Return {BasicMeeting} The created meeting
* @HttpResponse 200 Meeting created
* @HttpResponse 400 Must provide a display name for the meeting
* @HttpResponse 400 Must provide a description for the meeting
* @HttpResponse 400 A display name can be at most 1000 characters long
* @HttpResponse 400 A description can be at most 10000 characters long
* @HttpResponse 400 An invalid meeting visibility option has been provided
* @HttpResponse 400 One or more target members being granted access are not authorized to become members on this meeting
* @HttpResponse 400 One or more target members being granted access do not exist
* @HttpResponse 401 Anonymous users cannot create a meeting
*/
OAE.tenantRouter.on('post', '/api/meeting-jitsi/create', (request, response) => {
// Ensure proper arrays for the multi-value parameters
request.body.managers = OaeUtil.toArray(request.body.managers);
request.body.members = OaeUtil.toArray(request.body.members);
// Construct a hash for additional members that maps each user to their role
const additionalMembers = {};
_.each(request.body.managers, (userId) => {
additionalMembers[userId] = AuthzConstants.role.MANAGER;
});
_.each(request.body.members, (userId) => {
additionalMembers[userId] = AuthzConstants.role.MEMBER;
});
MeetingsAPI.Meetings.createMeeting(
request.ctx,
request.body.displayName,
request.body.description,
request.body.chat,
request.body.contactList,
request.body.visibility,
additionalMembers,
(error, meeting) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(201).send(meeting);
}
);
});
/**
* @REST getMeetingMeetingId
*
* Get a full meeting profile
*
* @Server tenant
* @Method GET
* @Path /meeting/{meetingId}
* @PathParam {string} meetingId The id of the meeting to get
* @Return {Meeting} Full meeting profile
* @HttpResponse 200 Meeting profile available
* @HttpResponse 400 meetingId must be a valid resource id
* @HttpResponse 401 You are not authorized to view this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('get', '/api/meeting-jitsi/:meetingId', (request, response) => {
MeetingsAPI.Meetings.getFullMeetingProfile(request.ctx, request.params.meetingId, (error, meeting) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).send(meeting);
});
});
/**
* @REST getMeetingMeetingIdInvitations
*
* Get all the invitations associated to a meeting
*
* @Server tenant
* @Method GET
* @Path /meeting/{meetingId}/invitations
* @PathParam {string} meetingId The id of the meeting for which to get invitations
* @Return {InvitationsResponse} The invitations associated to the meeting
* @HttpResponse 200 Invitations available
* @HttpResponse 400 A valid meeting id must be provided
* @HttpResponse 401 You are not allowed to get invitations for this meeting
* @HttpResponse 404 Meeting not available
*/
OAE.tenantRouter.on('get', '/api/meeting-jitsi/:meetingId/invitations', (request, response) => {
MeetingsAPI.Meetings.getMeetingInvitations(request.ctx, request.params.meetingId, (error, invitations) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).send({ results: invitations });
});
});
/**
* @REST getMeetingMeetingIdMembers
*
* Get the members of a meeting and their roles
*
* @Server tenant
* @Method GET
* @Path /meeting/{meetingId}/members
* @PathParam {string} meetingId The id of the meeting to get the members for
* @QueryParam {number} [limit] The maximum number of results to return. Default: 10
* @QueryParam {string} [start] The meeting paging token from which to start fetching meeting members
* @Return {MembersResponse} Members of the specified meeting
* @HttpResponse 200 Meeting members available
* @HttpResponse 400 A valid meeting id must be provided
* @HttpResponse 401 You are not authorized to view this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('get', '/api/meeting-jitsi/:meetingId/members', (request, response) => {
const limit = OaeUtil.getNumberParam(request.query.limit, 10, 1, 25);
MeetingsAPI.Meetings.getMeetingMembers(
request.ctx,
request.params.meetingId,
request.query.start,
limit,
(error, members, nextToken) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).send({ results: members, nextToken });
}
);
});
/**
* @REST postMeetingMeetingId
*
* Update a meeting's metadata.
*
* @Server tenant
* @Method PUT
* @Path /meeting/{meetingId}
* @PathParam {string} meetingId The id of the meeting to update
* @FormParam {string} description Updated description for the meeting
* @FormParam {string} displayName Updated display name for the meeting
* @FormParam {string} visibility Updated visibility for the meeting [loggedin,private,public]
* @Return {BasicMeeting} The updated meeting
* @HttpResponse 200 Meeting updated
* @HttpResponse 400 A valid meeting id must be provided
* @HttpResponse 400 A display name cannot be empty
* @HttpResponse 400 A description cannot be empty
* @HttpResponse 400 A display name can be at most 1000 characters long
* @HttpResponse 400 A description can only be 10000 characters long
* @HttpResponse 400 An invalid visibility was specified
* @HttpResponse 400 An invalid field was specified
* @HttpResponse 400 You should specify at least one profile field to update
* @HttpResponse 401 You are not authorized to update this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('put', '/api/meeting-jitsi/:meetingId', (request, response) => {
MeetingsAPI.Meetings.updateMeeting(request.ctx, request.params.meetingId, request.body, (error, meeting) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).send(meeting);
});
});
/**
* @REST deleteMeetingMeetingId
*
* Delete a meeting
*
* @Server tenant
* @Method DELETE
* @Path /meeting/{meetingId}
* @PathParam {string} meetingId The id of the meeting to delete
* @HttpResponse 200 Meeting deleted
* @HttpResponse 400 A valid meeting id must be provided
* @HttpResponse 401 You are not authorized to delete this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('delete', '/api/meeting-jitsi/:meetingId', (request, response) => {
MeetingsAPI.Meetings.deleteMeeting(request.ctx, request.params.meetingId, (error) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).end();
});
});
/**
* @REST postMeetingMeetingIdMembers
*
* Update the members of a meeting
*
* @Server tenant
* @Method PUT
* @Path /meeting/{meetingId}/members
* @PathParam {string} meetingId The id of the meeting to update the members for
* @BodyParam {MeetingMembersUpdate} body Object that describes the membership updates to apply to the meeting
* @Return {void}
* @HttpResponse 200 Meeting members updated
* @HttpResponse 400 A valid meeting id must be provided
* @HttpResponse 400 Invalid principal id specified
* @HttpResponse 400 Must specify at least one permission change to apply
* @HttpResponse 400 One or more target members being granted access are not authorized to become members on this meeting
* @HttpResponse 400 The requested change results in a meeting with no managers
* @HttpResponse 400 An invalid role value was specified. Must either be a string, or false
* @HttpResponse 400 You must specify at least one permission change
* @HttpResponse 401 You are not authorized to update the permissions of this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('put', '/api/meeting-jitsi/:meetingId/members', (request, response) => {
// Parse the incoming false values
const permissionUpdates = {};
_.each(request.body, (value, key) => {
permissionUpdates[key] = OaeUtil.castToBoolean(value);
});
MeetingsAPI.Meetings.setMeetingMembers(request.ctx, request.params.meetingId, permissionUpdates, (error) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).end();
});
});
/**
* @REST getMeetingMeetingIdMessages
*
* Get the messages in a meeting
*
* @Server tenant
* @Method GET
* @Path /meeting/{meetingId}/messages
* @PathParam {string} meetingId The id of the meeting for which to get the messages
* @QueryParam {number} [limit] The maximum number of results to return. Default: 10
* @QueryParam {string} [start] The messages paging token from which to start fetching messages
* @Return {MessagesResponse} The messages in the meeting
* @HttpResponse 200 Meeting messages available
* @HttpResponse 400 A messageBoxId must be specified
* @HttpResponse 400 A timestamp cannot be in the future.
* @HttpResponse 400 A timestamp cannot be null
* @HttpResponse 400 A timestamp should be an integer
* @HttpResponse 400 Must provide a valid meeting id
* @HttpResponse 401 You are not authorized to view this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('get', '/api/meeting-jitsi/:meetingId/messages', (request, response) => {
const limit = OaeUtil.getNumberParam(request.query.limit, 10, 1, 25);
MeetingsAPI.Meetings.getMessages(
request.ctx,
request.params.meetingId,
request.query.start,
limit,
(error, messages, nextToken) => {
if (error) {
return response.status(error.code).send(error.msg);
}
response.status(200).send({ results: messages, nextToken });
}
);
});
/**
* @REST postMeetingMeetingIdMessages
*
* Create a new message in a meeting
*
* @Server tenant
* @Method POST
* @Path /meeting/{meetingId}/messages
* @PathParam {string} meetingId The id of the meeting to which to post the message
* @FormParam {string} body The body of the message
* @FormParam {number} [replyTo] The timestamp of the message to which this message is a reply. Not specifying this will create a top level comment
* @Return {Message} The created message
* @HttpResponse 200 Meeting message created
* @HttpResponse 400 A meeting body can only be 100000 characters long
* @HttpResponse 400 A meeting body must be provided
* @HttpResponse 400 A messageBoxId must be specified
* @HttpResponse 400 If the replyToCreated optional parameter is specified, it should point to an existing reply
* @HttpResponse 400 Invalid meeting id provided
* @HttpResponse 400 The body of the message must be specified
* @HttpResponse 401 You are not authorized to post messages to this meeting
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('post', '/api/meeting-jitsi/:meetingId/messages', (request, response) => {
MeetingsAPI.Meetings.createMessage(
request.ctx,
request.params.meetingId,
request.body.body,
request.body.replyTo,
(error, message) => {
if (error) {
return response.status(error.code).send(error.msg);
}
response.status(200).send(message);
}
);
});
/**
* @REST deleteMeetingMeetingIdMessagesCreated
*
* Delete a message in a meeting
*
* @Server tenant
* @Method DELETE
* @Path /meeting/{meetingId}/messages/{created}
* @PathParam {string} meetingId The id of the meeting from which to delete the message
* @PathParam {number} created The timestamp of the message that should be deleted
* @Return {Message} When the message has been soft deleted (because it has replies), a stripped down message object representing the deleted message will be returned, with the `deleted` parameter set to `false`. If the message has been removed entirely, no message object will be returned
* @HttpResponse 200 Meeting message deleted
* @HttpResponse 400 A meeting id must be provided
* @HttpResponse 400 A messageBoxId must be specified
* @HttpResponse 400 A valid integer message created timestamp must be specified
* @HttpResponse 400 The createdTimestamp should point to an existing message
* @HttpResponse 401 You are not authorized to delete this message
* @HttpResponse 404 Could not find the specified meeting
* @HttpResponse 404 Could not find the specified message
*/
OAE.tenantRouter.on('delete', '/api/meeting-jitsi/:meetingId/messages/:created', (request, response) => {
MeetingsAPI.Meetings.deleteMessage(
request.ctx,
request.params.meetingId,
request.params.created,
(error, message) => {
if (error) {
return response.status(error.code).send(error.msg);
}
response.status(200).send(message);
}
);
});
/**
* @REST getMeetingLibraryPrincipalId
*
* Get the meetings library items for a user or group
*
* @Server tenant
* @Method GET
* @Path /meeting-jitsi/library/{principalId}
* @PathParam {string} principalId The id of the principal whose meeting library to fetch
* @QueryParam {number} [limit] The maximum number of results to return. Default: 10
* @QueryParam {string} [start] The meeting paging token from which to start fetching meetings
* @Return {MeetingsLibrary} The meetings library items for the specified user or group
* @HttpResponse 200 Meeting library available
* @HttpResponse 400 A user or group id must be provided
* @HttpResponse 401 You do not have have access to this library
*/
OAE.tenantRouter.on('get', '/api/meeting-jitsi/library/:principalId', (request, response) => {
const limit = OaeUtil.getNumberParam(request.query.limit, 12, 1, 25);
MeetingsAPI.Meetings.getMeetingsLibrary(
request.ctx,
request.params.principalId,
request.query.start,
limit,
(error, meetings, nextToken) => {
if (error) {
return response.status(error.code).send(error.msg);
}
response.status(200).send({ results: meetings, nextToken });
}
);
});
/**
* @REST deleteMeetingLibraryPrincipalIdMeetingId
*
* Remove a meeting from a meeting library
*
* @Server tenant
* @Method DELETE
* @Path /meeting/library/{principalId}/{meetingId}
* @PathParam {string} principalId The id of the principal from whose meeting library to remove the meeting
* @PathParam {string} meetingId The id of the meeting to remove from the library
* @HttpResponse 200 Meeting removed from library
* @HttpResponse 400 A user or group id must be provided
* @HttpResponse 400 An invalid meeting id was provided
* @HttpResponse 400 The requested change results in a meeting with no managers
* @HttpResponse 400 The specified meeting is not in this library
* @HttpResponse 401 You are not authorized to remove a meeting from this library
* @HttpResponse 404 Could not find the specified meeting
*/
OAE.tenantRouter.on('delete', '/api/meeting-jitsi/library/:principalId/:meetingId', (request, response) => {
MeetingsAPI.Meetings.removeMeetingFromLibrary(
request.ctx,
request.params.principalId,
request.params.meetingId,
(error) => {
if (error) {
return response.status(error.code).send(error.msg);
}
return response.status(200).end();
}
);
});