diff --git a/.github/workflows/lint-and-analyse-php.yml b/.github/workflows/lint-and-analyse-php.yml index c0dae652e..267d07e4c 100644 --- a/.github/workflows/lint-and-analyse-php.yml +++ b/.github/workflows/lint-and-analyse-php.yml @@ -39,10 +39,9 @@ jobs: - name: markdownlint-cli2-action uses: DavidAnson/markdownlint-cli2-action@v20 with: - config: 'doc/.markdownlint.yml' + config: 'docs/.markdownlint.yml' globs: | *.md - doc/*.md phpunit: runs-on: ubuntu-latest diff --git a/doc/API.md b/doc/API.md deleted file mode 100644 index 66c64b055..000000000 --- a/doc/API.md +++ /dev/null @@ -1,2430 +0,0 @@ -# LibreBooking API Documentation - -A dynamically generated API documentation Page can be found by opening `/Web/Services/index.php` (API has to be enabled in config) - -- [Getting Started With The API](#getting-started-with-the-api) -- [Accessories](#accessories) -- [Accounts](#accounts) -- [Attributes](#attributes) -- [Authentication](#authentication) -- [Groups](#groups) -- [Reservations](#reservations) -- [Resources](#resources) -- [Schedules](#schedules) -- [Users](#users) - -## Getting Started With the API - -### Authenticating to LibreBooking - -For all of the secure service calls it is required to be -[Authenticated](#authenticate). The basic steps are: - -1. Make a request to the [Authenticate](#authenticate) POST API endpoint. The - POST data must be sent as JSON -1. The result from the [Authenticate](#authenticate) POST API call, if - successful, will contain the two values: `sessionToken` and `userId` -1. When making secure service calls the following headers must be set: - 1. `X-Booked-SessionToken` set to the value of `sessionToken` - returned by the [Authenticate](#authenticate) API call. - 1. `X-Booked-UserId` set to the value of `userId` returned by the - [Authenticate](#authenticate) API call. - -### POST Requests - -When making POST API requests it is required to send the POST data as JSON - -## Accessories - -### POST Services - -na. - -### GET Services - -#### GetAllAccessories - -__Description:__ -Loads all accessories. -CreditApplicability of 1 is per slot, 2 is per reservation - -__Route:__ `/Web/Services/index.php/Accessories/` -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "accessories": [ - { - "id": 1, - "name": "accessoryName", - "quantityAvailable": 3, - "associatedResourceCount": 10, - "creditCount": 1, - "peakCreditCount": 2, - "creditApplicability": 1, - "creditsChargedAllSlots": null, - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetAccessory - -__Description:__ -Loads a specific accessory by id. CreditApplicability of 1 is per slot, 2 is per reservation - -__Route:__ `/Web/Services/index.php/Accessories/:accessoryId` -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "id": 1, - "name": "accessoryName", - "quantityAvailable": 10, - "associatedResources": [ - { - "resourceId": 1, - "minQuantity": 4, - "maxQuantity": 10, - "links": [], - "message": null - } - ], - "creditCount": 1, - "peakCreditCount": 2, - "creditApplicability": 1, - "links": [], - "message": null -} -``` - -## Accounts - -### POST Services - -#### CreateAccount - -__Description:__ -Creates a user account. This does not authenticate - -__Route:__ `/Web/Services/index.php/Accounts/` - -__Response:__ - -Unstructured response of type _AccountCreatedResponse_ - -__Request:__ - -```json -{ - "password": "plaintextpassword", - "acceptTermsOfService": true, - "firstName": "FirstName", - "lastName": "LastName", - "emailAddress": "email@address.com", - "userName": "username", - "language": "en_us", - "timezone": "America/Chicago", - "phone": "phone", - "organization": "organization", - "position": "position", - "customAttributes": [ - { - "attributeId": 1, - "attributeValue": "attribute value" - } - ] -} -``` - -#### UpdateAccount - -__Description:__ -Updates an existing user account - -__Route:__ `/Web/Services/index.php/Accounts/:userId` - -_This service is secure and requires authentication_ - -__Response:__ -Unstructured response of type _AccountUpdatedResponse_ - -__Request:__ - -```json -{ - "firstName": "FirstName", - "lastName": "LastName", - "emailAddress": "email@address.com", - "userName": "username", - "language": "en_us", - "timezone": "America/Chicago", - "phone": "phone", - "organization": "organization", - "position": "position", - "customAttributes": [ - { - "attributeId": 1, - "attributeValue": "attribute value" - } - ] -} -``` - -#### UpdatePassword - -__Description:__ - -Updates the password for an existing user - -__Route:__ `/Web/Services/index.php/Accounts/:userId/Password` - -_This service is secure and requires authentication_ - -__Response:__ - -Unstructured response of type _AccountUpdatedResponse_ - -__Request:__ - -```json -{ - "currentPassword": "plain.text.current.password", - "newPassword": "plain.text.new.password" -} -``` - -### GET Services - -#### GetAccount - -__Description:__ - -Gets the currently authenticated users's account information - -__Route:__ `/Web/Services/index.php/Accounts/:userId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "userId": 1, - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "userName": "username", - "language": "en_us", - "timezone": "America/Chicago", - "phone": "phone", - "organization": "organization", - "position": "position", - "customAttributes": [ - { - "id": 123, - "label": "label", - "value": "value", - "links": [], - "message": null - } - ], - "icsUrl": "webcal://path-to-calendar", - "links": [], - "message": null -} -``` - -## Attributes - -### POST Services - -#### CreateCustomAttribute - -__Description:__ - -Creates a new custom attribute. -Allowed values for type: 1 (single line), 2 (multi line), 3 (select list), 4 (checkbox), 5 (datetime) -Allowed values for categoryId: 1 (reservation), 2 (user), 4 (resource), 5 (resource type) -appliesToIds only allowed for category 2, 4, 5 and must match the id of corresponding entities -secondaryCategoryId and secondaryEntityIds only applies to category 1 and must match the id of the corresponding entities - -__Route:__ `/Web/Services/index.php/Attributes/` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "attributeId": 1, - "links": [ - { - "href": "http://url/to/attribute", - "title": "get_custom_attribute" - }, - { - "href": "http://url/to/update/attribute", - "title": "update_custom_attribute" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "label": "attribute name", - "type": 1, - "categoryId": 1, - "regex": "validation regex", - "required": true, - "possibleValues": [ - "possible", - "values", - "only valid for select list" - ], - "sortOrder": 100, - "appliesToIds": [ - 10 - ], - "adminOnly": true, - "isPrivate": true, - "secondaryCategoryId": 1, - "secondaryEntityIds": [ - 1, - 2 - ] -} -``` - -#### UpdateCustomAttribute - -__Description:__ - -Updates and existing custom attribute -Allowed values for type: 1 (single line), 2 (multi line), 3 (select list), 4 (checkbox), 5 (datetime) -Allowed values for categoryId: 1 (reservation), 2 (user), 4 (resource), 5 (resource type) -appliesToIds only allowed for category 2, 4, 5 and must match the id of corresponding entities -secondaryCategoryId and secondaryEntityIds only applies to category 1 and must match the id of the corresponding entities - -__Route:__ `/Web/Services/index.php/Attributes/:attributeId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "attributeId": 1, - "links": [ - { - "href": "http://url/to/attribute", - "title": "get_custom_attribute" - }, - { - "href": "http://url/to/update/attribute", - "title": "update_custom_attribute" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "label": "attribute name", - "type": 1, - "categoryId": 1, - "regex": "validation regex", - "required": true, - "possibleValues": [ - "possible", - "values", - "only valid for select list" - ], - "sortOrder": 100, - "appliesToIds": [ - 10 - ], - "adminOnly": true, - "isPrivate": true, - "secondaryCategoryId": 1, - "secondaryEntityIds": [ - 1, - 2 - ] -} -``` - -### GET Services - -#### GetCategoryAttributes - -__Description:__ - -Gets all custom attribute definitions for the requested category -Categories are RESERVATION = 1, USER = 2, RESOURCE = 4 - -__Route:__ `/Web/Services/index.php/Attributes/Category/:categoryId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "attributes": [ - { - "id": 1, - "label": "display label", - "type": "Allowed values for type: 4 (checkbox), 2 (multi line), 3 (select list), 1 (single line)", - "categoryId": "Allowed values for category: 1 (reservation), 4 (resource), 5 (resource type), 2 (user)", - "regex": "validation regex", - "required": true, - "possibleValues": [ - "possible", - "values" - ], - "sortOrder": 100, - "appliesToIds": [ - 10 - ], - "adminOnly": true, - "isPrivate": true, - "secondaryCategoryId": 1, - "secondaryEntityIds": [ - 1, - 2 - ], - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetAttribute - -__Description:__ - -Gets all custom attribute definitions for the requested attribute - -__Route:__ `/Web/Services/index.php/Attributes/:attributeId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "id": 1, - "label": "display label", - "type": "Allowed values for type: 4 (checkbox), 2 (multi line), 3 (select list), 1 (single line)", - "categoryId": "Allowed values for category: 1 (reservation), 4 (resource), 5 (resource type), 2 (user)", - "regex": "validation regex", - "required": true, - "possibleValues": [ - "possible", - "values" - ], - "sortOrder": 100, - "appliesToIds": [ - 10 - ], - "adminOnly": true, - "isPrivate": true, - "secondaryCategoryId": 1, - "secondaryEntityIds": [ - 1, - 2 - ], - "links": [], - "message": null -} -``` - -#### DeleteCustomAttribute - -__Description:__ - -Deletes an existing custom attribute - -__Route:__ `/Web/Services/index.php/Attributes/:attributeId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "links": [], - "message": "The item was deleted" -} -``` - -## Authentication - -### POST Services - -#### SignOut - -__Description:__ - -invalidate Authenication Token - -__Route:__ `/Web/Services/index.php/Authentication/SignOut` - -__Response:__ - -No response - -__Request:__ - -```json -{ - "userId": null, - "sessionToken": null -} -``` - -#### Authenticate - -__Description:__ - -Authenticates an existing LibreBooking user - -__Route:__ `/Web/Services/index.php/Authentication/Authenticate` - -__Response:__ - -```json -{ - "sessionToken": "sessiontoken", - "sessionExpires": "2021-03-08T09:56:04+0000", - "userId": 123, - "isAuthenticated": true, - "version": "1.0", - "links": [], - "message": null -} -``` - -__Request:__ - -```json -{ - "username":null, - "password":null -} -``` - -### GET Services - -na. - -## Groups - -### POST Services - -#### CreateGroup - -__Description:__ - -Creates a new group - -__Route:__ `/Web/Services/index.php/Groups/` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "attributeId": 1, - "links": [ - { - "href": "http://url/to/attribute", - "title": "get_custom_attribute" - }, - { - "href": "http://url/to/update/attribute", - "title": "update_custom_attribute" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{"name":"group name","isDefault":true} -``` - -#### UpdateGroup - -__Description:__ - -Updates and existing group - -__Route:__ `/Web/Services/index.php/Groups/:groupId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "groupId": 1, - "links": [ - { - "href": "http://url/to/group", - "title": "get_group" - }, - { - "href": "http://url/to/update/group", - "title": "update_group" - }, - { - "href": "http://url/to/delete/group", - "title": "delete_group" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "name": "group name", - "isDefault": true -} -``` - -### ChangeGroupRoles - -__Description:__ - -Updates the roles for an existing group -roleIds : 1 (Group Administrator), 2 (Application Administrator), 3 (Resource Administrator), 4 (Schedule Administrator) - -__Route:__ `/Web/Services/index.php/Groups/:groupId/Roles` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "groupId": 1, - "links": [ - { - "href": "http://url/to/group", - "title": "get_group" - }, - { - "href": "http://url/to/update/group", - "title": "update_group" - }, - { - "href": "http://url/to/delete/group", - "title": "delete_group" - } - ], - "message": null -} -``` - -__Request:__ - -No request - -### ChangeGroupPermissions - -__Description:__ - -Updates the permissions for an existing group - -__Route:__ `/Web/Services/index.php/Groups/:groupId/Permissions` -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "groupId": 1, - "links": [ - { - "href": "http://url/to/group", - "title": "get_group" - }, - { - "href": "http://url/to/update/group", - "title": "update_group" - }, - { - "href": "http://url/to/delete/group", - "title": "delete_group" - } - ], - "message": null -} -``` - -__Request:__ - -No request - -### ChangeGroupUsers - -__Description:__ - -Updates the permissions for an existing group - -__Route:__ `/Web/Services/index.php/Groups/:groupId/Users` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "groupId": 1, - "links": [ - { - "href": "http://url/to/group", - "title": "get_group" - }, - { - "href": "http://url/to/update/group", - "title": "update_group" - }, - { - "href": "http://url/to/delete/group", - "title": "delete_group" - } - ], - "message": null -} -``` - -__Request:__ - -No request - -### GET Services - -#### GetAllGroups - -__Description:__ - -Loads all groups - -__Route:__ `/Web/Services/index.php/Groups/` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "groups": [ - { - "id": 1, - "name": "group name", - "isDefault": true, - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetGroup - -__Description:__ - -Loads a specific group by id - -__Route:__ `/Web/Services/index.php/Groups/:groupId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "id": 123, - "name": "group name", - "adminGroup": "http://url/to/group", - "permissions": [ - "http://url/to/resource" - ], - "viewPermissions": [ - "http://url/to/resource" - ], - "users": [ - "http://url/to/user" - ], - "roles": [ - 1, - 2 - ], - "isDefault": true, - "links": [], - "message": null -} -``` - -#### DeleteGroup - -__Description:__ - -Deletes an existing group - -__Route:__ `/Web/Services/index.php/Groups/:groupId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "links": [], - "message": "The item was deleted" -} -``` - -## Reservations - -### POST Services - -#### CreateReservation - -__Description:__ - -Creates a new reservation - -__Route:__ `/Web/Services/index.php/Reservations/` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "referenceNumber": "referenceNumber", - "isPendingApproval": true, - "links": [ - { - "href": "http://url/to/reservation", - "title": "get_reservation" - }, - { - "href": "http://url/to/update/reservation", - "title": "update_reservation" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "accessories": [ - { - "accessoryId": 1, - "quantityRequested": 2 - } - ], - "customAttributes": [ - { - "attributeId": 2, - "attributeValue": "some value" - } - ], - "description": "reservation description", - "endDateTime": "2021-03-08T09:56:04+0000", - "invitees": [ - 1, - 2, - 3 - ], - "participants": [ - 1, - 2 - ], - "participatingGuests": [ - "participating.guest@email.com" - ], - "invitedGuests": [ - "invited.guest@email.com" - ], - "recurrenceRule": { - "type": "daily|monthly|none|weekly|yearly", - "interval": 3, - "monthlyType": "dayOfMonth|dayOfWeek|null", - "weekdays": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "repeatTerminationDate": "2021-03-08T09:56:04+0000" - }, - "resourceId": 1, - "resources": [ - 2, - 3 - ], - "startDateTime": "2021-03-08T09:56:04+0000", - "title": "reservation title", - "userId": 1, - "startReminder": { - "value": 15, - "interval": "hours or minutes or days" - }, - "endReminder": null, - "allowParticipation": true, - "retryParameters": [ - { - "name": "name", - "value": "value" - } - ], - "termsAccepted": true -} -``` - -#### UpdateReservation - -__Description:__ - -Updates an existing reservation. -Pass an optional updateScope query string parameter to restrict changes. Possible values for updateScope are this|full|future - -__Route:__ `/Web/Services/index.php/Reservations/:referenceNumber` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "referenceNumber": "referenceNumber", - "isPendingApproval": true, - "links": [ - { - "href": "http://url/to/reservation", - "title": "get_reservation" - }, - { - "href": "http://url/to/update/reservation", - "title": "update_reservation" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "accessories": [ - { - "accessoryId": 1, - "quantityRequested": 2 - } - ], - "customAttributes": [ - { - "attributeId": 2, - "attributeValue": "some value" - } - ], - "description": "reservation description", - "endDateTime": "2021-03-08T09:56:04+0000", - "invitees": [ - 1, - 2, - 3 - ], - "participants": [ - 1, - 2 - ], - "participatingGuests": [ - "participating.guest@email.com" - ], - "invitedGuests": [ - "invited.guest@email.com" - ], - "recurrenceRule": { - "type": "daily|monthly|none|weekly|yearly", - "interval": 3, - "monthlyType": "dayOfMonth|dayOfWeek|null", - "weekdays": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "repeatTerminationDate": "2021-03-08T09:56:04+0000" - }, - "resourceId": 1, - "resources": [ - 2, - 3 - ], - "startDateTime": "2021-03-08T09:56:04+0000", - "title": "reservation title", - "userId": 1, - "startReminder": { - "value": 15, - "interval": "hours or minutes or days" - }, - "endReminder": null, - "allowParticipation": true, - "retryParameters": [ - { - "name": "name", - "value": "value" - } - ], - "termsAccepted": true -} -``` - -#### ApproveReservation - -__Description:__ - -Approves a pending reservation. - -__Route:__ `/Web/Services/index.php/Reservations/:referenceNumber/Approval` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "referenceNumber": "referenceNumber", - "isPendingApproval": true, - "links": [ - { - "href": "http://url/to/reservation", - "title": "get_reservation" - }, - { - "href": "http://url/to/update/reservation", - "title": "update_reservation" - } - ], - "message": null -} -``` - -__Request:__ - -No request - -#### CheckinReservation - -__Description:__ - -Checks in to a reservation. - -__Route:__ `/Web/Services/index.php/Reservations/:referenceNumber/CheckIn` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "referenceNumber": "referenceNumber", - "isPendingApproval": true, - "links": [ - { - "href": "http://url/to/reservation", - "title": "get_reservation" - }, - { - "href": "http://url/to/update/reservation", - "title": "update_reservation" - } - ], - "message": null -} -``` - -__Request:__ - -No request - -#### CheckoutReservation - -__Description:__ - -Checks out of a reservation. - -__Route:__ `/Web/Services/index.php/Reservations/:referenceNumber/CheckOut` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "referenceNumber": "referenceNumber", - "isPendingApproval": true, - "links": [ - { - "href": "http://url/to/reservation", - "title": "get_reservation" - }, - { - "href": "http://url/to/update/reservation", - "title": "update_reservation" - } - ], - "message": null -} -``` - -__Request:__ - -No request - -### GET Services - -#### GetReservations - -__Description:__ - -Gets a list of reservations for the specified parameters. -Optional query string parameters: userId, resourceId, scheduleId, startDateTime, endDateTime. -If no dates are provided, reservations for the next two weeks will be returned. -If dates do not include the timezone offset, the timezone of the authenticated user will be assumed. - -__Route:__ `/Web/Services/index.php/Reservations/` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "reservations": [ - { - "referenceNumber": "refnum", - "startDate": "2021-03-08T09:56:04+0000", - "endDate": "2021-03-08T09:56:04+0000", - "firstName": "first", - "lastName": "last", - "resourceName": "resourcename", - "title": "reservation title", - "description": "reservation description", - "requiresApproval": true, - "isRecurring": true, - "scheduleId": 22, - "userId": 11, - "resourceId": 123, - "duration": "1 hours 45 minutes", - "bufferTime": "1 minutes", - "bufferedStartDate": "2021-03-08T09:56:04+0000", - "bufferedEndDate": "2021-03-08T09:56:04+0000", - "participants": [ - "participant name" - ], - "invitees": [ - "invitee name" - ], - "participatingGuests": [], - "invitedGuests": [], - "startReminder": 10, - "endReminder": 10, - "color": "#FFFFFF", - "textColor": "#000000", - "checkInDate": "2021-03-08T09:56:04+0000", - "checkOutDate": "2021-03-08T09:56:04+0000", - "originalEndDate": "2021-03-08T09:56:04+0000", - "isCheckInEnabled": true, - "autoReleaseMinutes": 1, - "resourceStatusId": null, - "creditsConsumed": 15, - "links": [], - "message": null - } - ], - "startDateTime": null, - "endDateTime": null, - "links": [], - "message": null -} -``` - -#### GetReservation - -__Description:__ - -Loads a specific reservation by reference number - -__Route:__ `/Web/Services/index.php/Reservations/:referenceNumber` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "referenceNumber": "refnum", - "startDate": "2021-03-08T09:56:04+0000", - "endDate": "2021-03-08T09:56:04+0000", - "title": "reservation title", - "description": "reservation description", - "requiresApproval": true, - "isRecurring": true, - "scheduleId": 123, - "resourceId": 123, - "owner": { - "userId": 123, - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "links": [], - "message": null - }, - "participants": [ - { - "userId": 123, - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "links": [], - "message": null - } - ], - "invitees": [ - { - "userId": 123, - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "links": [], - "message": null - } - ], - "customAttributes": [ - { - "id": 123, - "label": "label", - "value": "value", - "links": [], - "message": null - } - ], - "recurrenceRule": { - "type": "daily|monthly|none|weekly|yearly", - "interval": 3, - "monthlyType": "dayOfMonth|dayOfWeek|null", - "weekdays": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "repeatTerminationDate": "2021-03-08T09:56:04+0000" - }, - "attachments": [ - { - "url": "http://example/attachments/url" - } - ], - "resources": [ - { - "id": 123, - "name": "resource name", - "type": null, - "groups": null, - "links": [], - "message": null - } - ], - "accessories": [ - { - "id": 1, - "name": "Example", - "quantityAvailable": 12, - "quantityReserved": 3, - "links": [], - "message": null - } - ], - "startReminder": { - "value": 15, - "interval": "hours or minutes or days" - }, - "endReminder": { - "value": 15, - "interval": "hours or minutes or days" - }, - "allowParticipation": null, - "checkInDate": null, - "checkOutDate": null, - "originalEndDate": null, - "isCheckInAvailable": null, - "isCheckoutAvailable": null, - "autoReleaseMinutes": null, - "links": [], - "message": null -} -``` - -#### DeleteReservation - -__Description:__ - -Deletes an existing reservation. -Pass an optional updateScope query string parameter to restrict changes. Possible values for updateScope are this|full|future - -__Route:__ `/Web/Services/index.php/Reservations/:referenceNumber` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "links": [], - "message": "The item was deleted" -} -``` - -## Resources - -### POST Services - -#### CreateResource - -__Description:__ - -Creates a new resource - -__Route:__ `/Web/Services/index.php/Resources/` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "resourceId": 1, - "links": [ - { - "href": "http://url/to/resource", - "title": "get_resource" - }, - { - "href": "http://url/to/update/resource", - "title": "update_resource" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "name": "resource name", - "location": "location", - "contact": "contact information", - "notes": "notes", - "minLength": "1d0h0m", - "maxLength": "3600", - "requiresApproval": true, - "allowMultiday": true, - "maxParticipants": 100, - "minNotice": "86400", - "maxNotice": "0d12h30m", - "description": "description", - "scheduleId": 10, - "autoAssignPermissions": true, - "customAttributes": [ - { - "attributeId": 1, - "attributeValue": "attribute value" - } - ], - "sortOrder": 1, - "statusId": 1, - "statusReasonId": 2, - "autoReleaseMinutes": 15, - "requiresCheckIn": true, - "color": "#ffffff", - "credits": 3, - "peakCredits": 6, - "creditApplicability": 1, - "creditsChargedAllSlots": 1, - "maxConcurrentReservations": 1 -} -``` - -#### UpdateResource - -__Description:__ - -Updates an existing resource - -__Route:__ `/Web/Services/index.php/Resources/:resourceId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "resourceId": 1, - "links": [ - { - "href": "http://url/to/resource", - "title": "get_resource" - }, - { - "href": "http://url/to/update/resource", - "title": "update_resource" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "name": "resource name", - "location": "location", - "contact": "contact information", - "notes": "notes", - "minLength": "1d0h0m", - "maxLength": "3600", - "requiresApproval": true, - "allowMultiday": true, - "maxParticipants": 100, - "minNotice": "86400", - "maxNotice": "0d12h30m", - "description": "description", - "scheduleId": 10, - "autoAssignPermissions": true, - "customAttributes": [ - { - "attributeId": 1, - "attributeValue": "attribute value" - } - ], - "sortOrder": 1, - "statusId": 1, - "statusReasonId": 2, - "autoReleaseMinutes": 15, - "requiresCheckIn": true, - "color": "#ffffff", - "credits": 3, - "peakCredits": 6, - "creditApplicability": 1, - "creditsChargedAllSlots": 1, - "maxConcurrentReservations": 1 -} -``` - -### GET Services - -#### GetStatuses - -__Description:__ - -Returns all available resource statuses - -__Route:__ `/Web/Services/index.php/Resources/Status` - -__Response:__ - -```json -{ - "statuses": [ - { - "id": 0, - "name": "Hidden" - }, - { - "id": 1, - "name": "Available" - }, - { - "id": 2, - "name": "Unavailable" - } - ], - "links": [], - "message": null -} -``` - -#### GetAllResources - -__Description:__ - -Loads all resources - -__Route:__ `/Web/Services/index.php/Resources/` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "resources": [ - { - "resourceId": 123, - "name": "resource name", - "location": "location", - "contact": "contact", - "notes": "notes", - "minLength": "2 minutes", - "maxLength": "2 minutes", - "requiresApproval": true, - "allowMultiday": true, - "maxParticipants": 10, - "minNoticeAdd": "2 minutes", - "minNoticeUpdate": "2 minutes", - "minNoticeDelete": "2 minutes", - "maxNotice": "2 minutes", - "description": "resource description", - "scheduleId": 123, - "icsUrl": null, - "statusId": 1, - "statusReasonId": 3, - "customAttributes": [ - { - "id": 123, - "label": "label", - "value": "value", - "links": [], - "message": null - } - ], - "typeId": 2, - "groupIds": null, - "bufferTime": "1 hours 30 minutes", - "autoReleaseMinutes": 15, - "requiresCheckIn": true, - "color": "#ffffff", - "credits": 3, - "peakCredits": 6, - "creditApplicability": 1, - "creditsChargedAllSlots": true, - "maxConcurrentReservations": 1, - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetStatusReasons - -__Description:__ - -Returns all available resource status reasons - -__Route:__ `/Web/Services/index.php/Resources/Status/Reasons` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "reasons": [ - { - "id": 1, - "description": "reason description", - "statusId": 2 - } - ], - "links": [], - "message": null -} -``` - -#### GetAvailability - -__Description:__ - -Returns resource availability for the requested resource (optional). "availableAt" and "availableUntil" will include availability through the next 7 days -Optional query string parameter: dateTime. If no dateTime is requested the current datetime will be used. - -__Route:__ `/Web/Services/index.php/Resources/Availability` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "resources": [ - { - "available": true, - "resource": { - "resourceId": 1, - "name": "resource name", - "scheduleId": 2, - "statusId": 1, - "statusReasonId": 123, - "links": [ - { - "href": "http://get-resource-url", - "title": "get_resource" - }, - { - "href": "http://get-schedule-url", - "title": "get_schedule" - } - ], - "message": null - }, - "availableAt": "2021-03-08T09:56:04+0000", - "availableUntil": "2021-03-08T09:56:04+0000", - "links": [ - { - "href": "http://get-user-url", - "title": "get_user" - }, - { - "href": "http://get-reservation-url", - "title": "get_reservation" - } - ], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetGroups - -__Description:__ - -Returns the full resource group tree - -__Route:__ `/Web/Services/index.php/Resources/Groups` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "groups": [ - { - "id": 0, - "name": "Resource Group 1", - "label": "Resource Group 1", - "parent": null, - "parent_id": null, - "children": [ - { - "type": "resource", - "group_id": 0, - "resource_name": "Resource 1", - "id": "resource-0-1", - "label": "Resource 1", - "resource_id": 1, - "resourceAdminGroupId": null, - "scheduleId": 2, - "statusId": 1, - "scheduleAdminGroupId": null, - "requiresApproval": false, - "isCheckInEnabled": true, - "isAutoReleased": true, - "autoReleaseMinutes": 30, - "minLength": 10, - "resourceTypeId": 1, - "color": "#ffffff", - "textColor": "#000000", - "maxConcurrentReservations": 2, - "requiredResourceIds": [ - 2 - ] - }, - { - "id": 1, - "name": "Resource Group 2", - "label": "Resource Group 2", - "parent": null, - "parent_id": 0, - "children": [ - { - "type": "resource", - "group_id": 1, - "resource_name": "Resource 2", - "id": "resource-1-1", - "label": "Resource 2", - "resource_id": 1, - "resourceAdminGroupId": null, - "scheduleId": 2, - "statusId": 1, - "scheduleAdminGroupId": null, - "requiresApproval": true, - "isCheckInEnabled": false, - "isAutoReleased": false, - "autoReleaseMinutes": null, - "minLength": null, - "resourceTypeId": 2, - "color": "#000000", - "textColor": "#FFFFFF", - "maxConcurrentReservations": 1, - "requiredResourceIds": [ - 1 - ] - } - ], - "type": "group" - } - ], - "type": "group" - } - ], - "links": [], - "message": null -} -``` - -#### GetResource - -__Description:__ - -Loads a specific resource by id - -__Route:__ `/Web/Services/index.php/Resources/:resourceId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "resourceId": 123, - "name": "resource name", - "location": "location", - "contact": "contact", - "notes": "notes", - "minLength": "2 minutes", - "maxLength": "2 minutes", - "requiresApproval": true, - "allowMultiday": true, - "maxParticipants": 10, - "minNoticeAdd": "2 minutes", - "minNoticeUpdate": "2 minutes", - "minNoticeDelete": "2 minutes", - "maxNotice": "2 minutes", - "description": "resource description", - "scheduleId": 123, - "icsUrl": null, - "statusId": 1, - "statusReasonId": 3, - "customAttributes": [ - { - "id": 123, - "label": "label", - "value": "value", - "links": [], - "message": null - } - ], - "typeId": 2, - "groupIds": null, - "bufferTime": "1 hours 30 minutes", - "autoReleaseMinutes": 15, - "requiresCheckIn": true, - "color": "#ffffff", - "credits": 3, - "peakCredits": 6, - "creditApplicability": 1, - "creditsChargedAllSlots": true, - "maxConcurrentReservations": 1, - "links": [], - "message": null -} -``` - -GetAvailability - -__Description:__ - -Returns resource availability for the requested resource (optional). "availableAt" and "availableUntil" will include availability through the next 7 days -Optional query string parameter: dateTime. If no dateTime is requested the current datetime will be used. - -__Route:__ `/Web/Services/index.php/Resources/:resourceId/Availability` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "resources": [ - { - "available": true, - "resource": { - "resourceId": 1, - "name": "resource name", - "scheduleId": 2, - "statusId": 1, - "statusReasonId": 123, - "links": [ - { - "href": "http://get-resource-url", - "title": "get_resource" - }, - { - "href": "http://get-schedule-url", - "title": "get_schedule" - } - ], - "message": null - }, - "availableAt": "2021-03-08T09:56:04+0000", - "availableUntil": "2021-03-08T09:56:04+0000", - "links": [ - { - "href": "http://get-user-url", - "title": "get_user" - }, - { - "href": "http://get-reservation-url", - "title": "get_reservation" - } - ], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### DeleteResource - -__Description:__ - -Deletes an existing resource - -__Route:__ `/Web/Services/index.php/Resources/:resourceId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "links": [], - "message": "The item was deleted" -} -``` - -## Schedules - -### POST Services - -na. - -### GET Services - -#### GetAllSchedules - -__Description:__ - -Loads all schedules - -__Route:__ `/Web/Services/index.php/Schedules/` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "schedules": [ - { - "daysVisible": 5, - "id": 123, - "isDefault": true, - "name": "schedule name", - "timezone": "timezone_name", - "weekdayStart": 0, - "availabilityBegin": "2021-03-08T09:56:04+0000", - "availabilityEnd": "2021-03-28T09:56:04+0000", - "maxResourcesPerReservation": 10, - "totalConcurrentReservationsAllowed": 0, - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetSchedule - -__Description:__ - -Loads a specific schedule by id - -__Route:__ `/Web/Services/index.php/Schedules/:scheduleId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "daysVisible": 5, - "id": 123, - "isDefault": true, - "name": "schedule name", - "timezone": "timezone_name", - "weekdayStart": 0, - "icsUrl": "webcal://url/to/calendar", - "availabilityStart": "2021-03-08T09:56:04+0000", - "availabilityEnd": "2021-03-08T09:56:04+0000", - "maxResourcesPerReservation": 10, - "totalConcurrentReservationsAllowed": 0, - "periods": [ - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ], - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ], - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ], - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ], - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ], - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ], - [ - { - "start": "2021-03-08T09:56:04+0000", - "end": "2021-03-08T09:56:04+0000", - "label": "label", - "startTime": "09:56:04", - "endTime": "09:56:04", - "isReservable": true - } - ] - ], - "links": [], - "message": null -} -``` - -#### GetSlots - -__Description:__ - -Loads slots for a specific schedule -Optional query string parameters: resourceId, startDateTime, endDateTime. -If no dates are provided the default schedule dates will be returned. -If dates do not include the timezone offset, the timezone of the authenticated user will be assumed. - -__Route:__ `/Web/Services/index.php/Schedules/:scheduleId/Slots` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "dates": [ - { - "date": "2021-03-08T09:56:04+0000", - "resources": [ - { - "slots": [ - { - "slotSpan": 4, - "isReserved": true, - "label": "username", - "isReservable": false, - "color": "#ffffff", - "startDateTime": "2021-03-08T09:56:04+0000", - "endDateTime": "2021-03-08T09:56:04+0000", - "reservation": { - "referenceNumber": "refnum", - "startDate": "2021-03-08T09:56:04+0000", - "endDate": "2021-03-08T09:56:04+0000", - "firstName": "first", - "lastName": "last", - "resourceName": "resourcename", - "title": "reservation title", - "description": "reservation description", - "requiresApproval": true, - "isRecurring": true, - "scheduleId": 22, - "userId": 11, - "resourceId": 123, - "duration": "1 hours 45 minutes", - "bufferTime": "1 minutes", - "bufferedStartDate": "2021-03-08T09:56:04+0000", - "bufferedEndDate": "2021-03-08T09:56:04+0000", - "participants": [ - "participant name" - ], - "invitees": [ - "invitee name" - ], - "participatingGuests": [], - "invitedGuests": [], - "startReminder": 10, - "endReminder": 10, - "color": "#FFFFFF", - "textColor": "#000000", - "checkInDate": "2021-03-08T09:56:04+0000", - "checkOutDate": "2021-03-08T09:56:04+0000", - "originalEndDate": "2021-03-08T09:56:04+0000", - "isCheckInEnabled": true, - "autoReleaseMinutes": 1, - "resourceStatusId": null, - "creditsConsumed": 15, - "links": [], - "message": null - }, - "links": [], - "message": null - } - ], - "resourceId": 1, - "resourceName": "resourcename", - "links": [], - "message": null - } - ], - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -## Users - -### POST Services - -#### CreateUser - -__Description:__ - -Creates a new user - -__Route:__ `/Web/Services/index.php/Users/` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "userId": null, - "links": [ - { - "href": "http://url/to/user", - "title": "get_user" - }, - { - "href": "http://url/to/update/user", - "title": "update_user" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "password": "unencrypted password", - "language": "en_us", - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "userName": "username", - "timezone": "America/Chicago", - "phone": "123-456-7989", - "organization": "organization", - "position": "position", - "customAttributes": [ - { - "attributeId": 99, - "attributeValue": "attribute value" - } - ], - "groups": [ - 1, - 2, - 4 - ] -} -``` - -#### UpdateUser - -__Description:__ - -Updates an existing user - -__Route:__ `/Web/Services/index.php/Users/:userId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "userId": null, - "links": [ - { - "href": "http://url/to/user", - "title": "get_user" - }, - { - "href": "http://url/to/update/user", - "title": "update_user" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "userName": "username", - "timezone": "America/Chicago", - "phone": "123-456-7989", - "organization": "organization", - "position": "position", - "customAttributes": [ - { - "attributeId": 99, - "attributeValue": "attribute value" - } - ], - "groups": [ - 1, - 2, - 4 - ] -} -``` - -#### UpdatePassword - -__Description:__ - -Updates the password for an existing user - -__Route:__ `/Web/Services/index.php/Users/:userId/Password` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "userId": null, - "links": [ - { - "href": "http://url/to/user", - "title": "get_user" - }, - { - "href": "http://url/to/update/user", - "title": "update_user" - } - ], - "message": null -} -``` - -__Request:__ - -```json -{ - "password":"plaintext password" -} -``` - -### GET Services - -#### GetAllUsers - -__Description:__ - -Loads all users that the current user can see. -Optional query string parameters: username, email, firstName, lastName, phone, organization, position and any custom attributes. -If searching on custom attributes, the query string parameter has to be in the format att#=value. -For example, Users/?att1=ExpectedAttribute1Value - -__Route:__ `/Web/Services/index.php/Users/` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "users": [ - { - "id": 1, - "userName": "username", - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "phoneNumber": "phone", - "dateCreated": "2021-03-08T09:56:04+0000", - "lastLogin": "2021-03-08T09:56:04+0000", - "statusId": "statusId", - "timezone": "timezone", - "organization": "organization", - "position": "position", - "language": "language_code", - "customAttributes": [ - { - "id": 123, - "label": "label", - "value": "value", - "links": [], - "message": null - } - ], - "currentCredits": "2.50", - "reservationColor": "#000000", - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### GetUser - -__Description:__ - -Loads the requested user by Id - -__Route:__ `/Web/Services/index.php/Users/:userId` - -_This service is secure and requires authentication_ - -__Response:__ - -```json -{ - "id": 1, - "userName": "username", - "firstName": "first", - "lastName": "last", - "emailAddress": "email@address.com", - "phoneNumber": "phone", - "lastLogin": "2021-03-08T09:56:04+0000", - "statusId": "statusId", - "timezone": "timezone", - "organization": "organization", - "position": "position", - "language": "language_code", - "icsUrl": "webcal://url/to/calendar", - "defaultScheduleId": 1, - "currentCredits": "2.50", - "reservationColor": "#000000", - "customAttributes": [ - { - "id": 123, - "label": "label", - "value": "value", - "links": [], - "message": null - } - ], - "permissions": [ - { - "id": 123, - "name": "resource name", - "type": null, - "groups": null, - "links": [], - "message": null - } - ], - "groups": [ - { - "id": 1, - "name": "group name", - "isDefault": null, - "roleIds": null, - "links": [], - "message": null - } - ], - "links": [], - "message": null -} -``` - -#### DeleteUser - -__Description:__ - -Deletes an existing user - -__Route:__ `/Web/Services/index.php/Users/:userId` - -_This service is secure and requires authentication_ - -_This service is only available to application administrators_ - -__Response:__ - -```json -{ - "links": [], - "message": "The item was deleted" -} -``` diff --git a/doc/ERD.svg b/doc/ERD.svg deleted file mode 100644 index 5cbd4390d..000000000 --- a/doc/ERD.svg +++ /dev/null @@ -1,11480 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/HISTORY.md b/doc/HISTORY.md deleted file mode 100644 index 4e9a47252..000000000 --- a/doc/HISTORY.md +++ /dev/null @@ -1,9 +0,0 @@ -# History - -Unfortunately the source code for Booked Scheduler is no longer being distributed and version 2.8.5 seems to have been the last open source release, see and "Booked Scheduler will become a full SaaS offering on November 1, 2020. This open source project will be discontinued. " - -This repo is a copy of the git repo, it also contains several branches where I'm hoping to fix bugs, add features, etc. - -Sadly I don't have the time to dedicate myself to this project, but I'm hoping to at least fix whatever bug may appear, with the limited understanding of the source code that I have. If you can help, or better yet, do you want go on with this project please fork it and keep developing it. Forks, help, bug reports are all welcome. - -UPDATE: The worst-case scenario seems to have occurred, the original repo is gone and all the releases are also gone. As such I've added the few releases that I had downloaded but as I didn’t know exactly to what commit/tag they were connect, the releases and the commits do not correspond. diff --git a/doc/INSTALLATION.md b/doc/INSTALLATION.md deleted file mode 100644 index f83c2531d..000000000 --- a/doc/INSTALLATION.md +++ /dev/null @@ -1,215 +0,0 @@ -# LibreBooking Installation - -Note: for users without web hosting service or existing environment, packages like [XAMMP](http://www.apachefriends.org/en/index.html) or [WampServer](http://www.wampserver.com/en/) can help you get set up quickly. - -## Fresh Installation - -### Server Configuration - -In an **Apache** or similar server environment, some required modules for LibreBooking may not be enabled by default. The following modules (or their equivalents) are often not enabled as part of a standard installation but should be enabled for the proper operation of the LibreBooking application: - -* headers -* rewrite - -The enabled modules in an **Apache2** environment can be verified as follows: - -```bash -apachectl -M -``` - -If required modules are not present in the enabled list, modules can be enabled in an **Apache2** environment as follows: - -```bash -sudo a2enmod headers -sudo a2enmod rewrite -sudo service apache2 restart -``` - -### Application Deployment to Server - -Move the contents of the directory to your webserver's document root (or subsite). -If you don't have direct access to your document root or use a hosting service, then transfer the directory to your web server's document root using FTP or [WinSCP](https://winscp.net/). - -Copy `/config/config.dist.php` to `/config/config.php` and adjust the settings for your environment. - -Important! The web server must have write access (0755) to `/librebooking/tpl_c` and `/librebooking/tpl` [want to know why?](http://www.smarty.net/docs/en/variable.compile.dir.tpl) - -If using an (S)FTP client, check read/write/execute for Owner and Group on `/tpl`, `/tpl_c`, and `/uploads` - -LibreBooking will not work if PHP [session.autostart](http://www.php.net/manual/en/session.configuration.php#ini.session.auto-start) is enabled. -Ensure this setting is disabled. - -### Application Configuration - -You can configure LibreBooking to fit your environments and needs or use the minimal default settings which should be enough for the application to work. -We recommend you to change according to your specifics. Additional information on all configuration settings can be found in the application help page. -To configure the application, you can open `/config/config.php` and alter any settings accordingly. -The admin email address can be set in the `librebooking/config/config.php` file of `$conf['settings']['admin.email']` -When later register an account with admin email address the user will be given admin privilege. - -In addition, to allow resource image uploads, the web server must also have read/write access to your configurable uploads directory of `$conf['settings']['image.upload.directory']` in the `config.php`. -By default, LibreBooking uses standard username/password for user authentication. -Alternatively, you can use LDAP authentication. -See the plugins section of the application help page for more details. -Note: If you try to load the application at this time (eg. ), you will probably get a white page. - -This is because there is no backend database configured yet. -So continue on ... - -### Database Setup - -You have 2 ways to set up your database for the application to work. - -#### Automatic Database Setup - -You must have the application configured correctly before running the automated install. - -The automated database setup only supports MySQL at this time. -To run the automated database setup, navigate to the `/Web/install` directory in a web browser and follow the on-screen instructions. -Note: Some may see directory permission issues displayed on the page. -The web server must have write access to `/librebooking/tpl_c` and `/librebooking/tpl`. -If you cannot provide the required permission. Contact your web server administrator or hosting service to resolve or run the manual install - -#### Manual Database Setup - -The packaged database scripts make assumptions about your desired database configuration and set default values. -Please edit them to suit your environment before running. The files are located in `librebooking/database_schema/` -Import the following sql files in the listed order (we recommend [phpMyAdmin](https://www.phpmyadmin.net/): - -On a remote host with no database creation privileges -If you are installing LibreBooking on a remote host, please follow these steps. -These steps assume you are using cPanel and have the ability to create databases via the cPanel tool and phpMyAdmin. - -Adding the database and user - -Select the MySQL Databases tool - -Add a new user with username and password of your choice. -This will be the database user and database password set in your LibreBooking config file. - -**Please be aware that some hosts will prefix your database user name.** - -Create a new database with whatever name you choose. -This will be the name of the database in your LibreBooking config file. 'librebooking' is the recommended database name. - -**Please be aware that some hosts will prefix your database name.** - -Associate the new user with the new database, giving the user permission to SELECT, CREATE, UPDATE, INSERT and DELETE. -Click the 'Add User to Db' button. 'Creating tables' -Open phpMyAdmin. -Click on the database name that you just created in the left panel. -Click the SQL tab at the top of the page. -Import `/database_schema/create-schema.sql` to librebooking (or whatever database name was used in the creation process) -Import `/database_schema/create-data.sql` to librebooking (or whatever database name was used in the creation process) - -If you have database creation privileges in MySQL -Open `/database_schema/full-install.sql` and edit the database name and username/password to match your `config.php` database values -Run or import `/database_schema/full-install.sql` Optionally - run/import `/database_schema/testdata-utf8.sql` to librebooking (sample application data will be created with 2 users: admin/password and user/password). -These users are available for testing your installation. - -You are done. Try to load the application at (eg. [http://yourhostname/librebooking/Web/](http://yourhostname/librebooking/Web/)). - -### Registering the Administrator Account - -After the database has been set up you will need to register the account for your application administrator. Navigate to register.php register an account with email address set in `$conf['settings']['admin.email']`. - -## Upgrading - -### Upgrading from a previous version of LibreBooking (or Booked 2.x and phpScheduleIt 2.x) - -The steps for upgrading from a previous version of LibreBooking are very similar to the steps described above in Application Deployment to Server. - -#### Recommended - -The recommended approach is to backup your current LibreBooking files, then upload the new files to the that same location. -This prevents any old files from interfering with new ones. -After the new files are uploaded, copy your old `config/config.php` file to the config directory in the new version. -Then run `/Web/install/configure.php` to bring your config file up to date. -If you have any uploaded resource images you will need to copy them from their old location to the new one. - -#### Alternative - -An alternative upgrade approach is to overwrite the current LibreBooking files with the new ones. -If doing this, you must delete the contents of `/tpl_c`. -This approach will not allow you to roll back and will not clear out any obsolete files. - -#### Database - -After the application files have been upgraded you will need to upgrade the database. - -##### Automatical Database Upgrade - -The automatic database upgrade is exactly the same as the automatic database install. -Please follow the instructions in the Automatic Database Setup section above. - -##### Manual Database Upgrade - -The packaged database scripts make assumptions about your desired database configuration and set default values. -Please edit them to suit your environment before running. -The files are located in `librebooking/database_schema/upgrades.` -Depending on your current version, import the `upgrade.sql` file within each subdirectory to get to the current version (we recommend [adminer](https://www.adminer.org/) for this) -For example, if you are running version 2.0 and the current version is 2.2 then you should run `librebooking/database_schema/upgrade/2.1/upgrade.sql` then `librebooking/database_schema/upgrade/2.2/upgrade.sql` - -### Migrating from version 1.2 - -A migration from 1.2 to 2.0 is supported for MySQL only. -This can be run after the 2.0 installation. -To run the migration open `/Web/install/migrate.php` directory in a web browser and follow the on-screen instructions. - -## Getting Started - -### The First Login - -There are 2 main types of accounts, they are admin and user account. - -* If you imported a sample application data, you now can use admin/password and user/password to login and make changes or addition via the application. -* If not, **you will need to register an account with your configured admin email address**. The admin email address can be set in the `librebooking/config/config.php` file of setting `$conf['settings']['admin.email']` - -Other self registration accounts are defaulted to normal users. - -After registration you will be logged in automatically. - -At this time, it is recommended to change your password. - -* For LDAP authentication please login with your LDAP username/password. - -#### Log Files - -LibreBooking logs multiple levels of information categorized into either application or database logs. To do this: - -* To allow application logging, the PHP account requires write access (0755) to your configured log directory. -* Logging is configured in /config/config.php -* Levels used by LibreBooking are OFF, DEBUG, ERROR. For normal operation, ERROR is appropriate. If trace logs are needed, DEBUG is appropriate. -* To turn on application logging, change the `$conf['settings']['logging']['level'] =` to an appropriate level for either the default or sql loggers. For example, `$conf['settings']['logging']['level'] = 'debug';` - -### Enabling LibreBooking API - -LibreBooking has the option to expose a RESTful JSON API. This API can be leveraged for third party integration, automation or to develop client applications. - -#### Prerequisites - -* PHP 7.0 or greater -* To use 'friendly' URLs, mod_rewrite or URL rewriting must be enabled -* Your web server must accept all verbs: GET, POST, PUT, DELETE - -#### Configuration - -* Set `$conf['settings']['api']['enabled'] = 'true'`; in your config file. -* If you want friendly URL paths, mod_rewrite or URL rewriting must be enabled. Note, this is not required in order to use the API. -* If using mod_rewrite and an Apache alias, ensure RewriteBase in /Web/Services/.htaccess is set to that alias root. - -#### API Documentation - -Auto-generated documentation for API usage can be found by browsing http://your_librebooking_url/Web/Services. -This documentation describes each available service, indicates whether or not the service is available to unauthenticated users/administrators, and provides example requests/responses. - -#### Consuming the API - -If URL rewriting is being used, all services will be available from http://your_librebooking_url/Web/Services -If not using URL rewriting, all services will be available from http://your_librebooking_url/Web/Services/index.php - -Certain services are only available to authenticated users or administrators. Secure services will require a session token and userid, which can be obtained from the Authentication service. - -## Support - -Please post any questions or issues to the github repo or the gitter chat room. diff --git a/doc/Oauth2-Configuration.md b/doc/Oauth2-Configuration.md deleted file mode 100644 index 00266bb5d..000000000 --- a/doc/Oauth2-Configuration.md +++ /dev/null @@ -1,42 +0,0 @@ -# Oauth2 Configuration - -You can use any IdP (Identity Provider) which supports Oauth2 like -[authentik](https://goauthentik.io) or [Keycloak](https://www.keycloak.org/) -for authentication with LibreBooking - -## IdP Configuration - -First you need to create a Client in your IdP in Confidential mode (Client ID -and Client Secret). The Client need to allow redirects to `/Web/oauth2-auth.php` ex. `https://librebooking.com/Web/oauth2-auth.php` -and needs the scopes `openid`, `email` and `profile`. - -The mapping of Oauth2 attributes to LibreBooking attributes is: - -- `email` -> `email` -- `given_name` -> `firstName` -- `family_name` -> `lastName` -- `preferred_username` -> `username` -- `phone` -> `phone_number` -- `organization` -> `organization` -- `title` -> `title` - -## LibreBooking Config - -To connect LibreBooking with your Oauth2 IdP you need to add the following vars to your `config.php`, in this example with authentik as IdP with the url `authentik.io`. - -```php -$conf['settings']['authentication']['allow.oauth2.login'] = 'true'; // Enable Oauth2 -$conf['settings']['authentication']['oauth2.name'] = 'authentik'; // Display name of Oauth2 IdP -$conf['settings']['authentication']['oauth2.url.authorize'] = 'https://authentik.io/application/o/authorize/'; // Oauth2 Authorization Endpoint -$conf['settings']['authentication']['oauth2.url.token'] = 'https://authentik.io/application/o/token/'; // Oauth2 Token Endpoint -$conf['settings']['authentication']['oauth2.url.userinfo'] = 'https://authentik.io/application/o/userinfo/'; // Oauth2 Userinfo Endpoint -$conf['settings']['authentication']['oauth2.client.id'] = 'c3zzBXq9Qw3K9KErd9ta6tQgvVhr6wT3rkQaInz8'; -$conf['settings']['authentication']['oauth2.client.secret'] = '13246zgtfd4t456zhg8rdgf98g789df7gFG56z5zhb'; -``` - -To hide the internal LibreBooking Login you can additional add the following variable. - -```php -$conf['settings']['authentication']['hide.booked.login.prompt'] = 'true'; -``` diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index c874fd6ce..000000000 --- a/doc/README.md +++ /dev/null @@ -1,124 +0,0 @@ -# Developer Documentation - -## Working on the project - -The `develop` branch contains the most current working code of the Project and should be considered beta. -The `master` branch is the most current stable release of LibreBooking. -You can automatically keep your fork up to date with the [pull GitHub App](https://github.com/apps/pull). which will sync the `master` (hardreset) and `develop` (rebase) branches for you. -Please commit bugfixes / features to a new branch prefixed `bugfix-`, `feature-` so they can be looked over, and pull requested to the `develop` branch and will eventually end up in a release on `master`. - -## Design philosophy - -The Model-View-Presenter (MVP) pattern is used to keep a clear separation between application logic and presentation logic. -Page objects act as thin abstraction to the template engine and typically have no other logic. -Presenter objects orchestrate interactions between underlying application logic objects and the page. -This typically includes fetching and transforming data and minimal application logic. - -```text - [page].php should - - define ROOT_DIR - - include /Pages/[page]Page.php - - construct [page]Page and call PageLoad() -``` - -- Each page should have at least one corresponding template in `/tpl` -- Each page should have a corresponding class in `/Pages` -- Each Page class should have a corresponding presenter class in `/Presenters` - -Logically related code should be grouped in a directory with a "namespace.php" file, which requires all files in that directory. -This simply makes it easier to include necessary file dependencies. - -## API - -LibreBooking has a REST-API -[API-Documentation](./API.md) - -## User interface - -[Smarty template engine](https://www.smarty.net/docsv2/en/language.basic.syntax.tpl) is used for all UI presentation. -Page templates are located in `/tpl` and, by default, are cached to `/tpl_c` -[Fugue Icons](https://p.yusukekamiyamane.com/) are used as the default iconset and when needed saved to `/Web/img/.png` - -## Tools - -you can easily install these useful php tools needed for development with [phive](https://github.com/phar-io/phive#getting-phive) and [composer](https://getcomposer.org/download/) -For phive to work properly you also need to install [gnupgp](https://www.gnupg.org/download/index.html#binary) - -Simply run `composer install-tools` in the root of the project and all tools will be available inside the `/tools` directory. - -### [Phing](https://www.phing.info/#docs) - -`composer build` Builds / Packages a distributable relase inside `/build` configured via `/build.xml`. - -### [PHPUnit](https://phpunit.readthedocs.io/en/latest/writing-tests-for-phpunit.html) - -All classes should have good unit test coverage. The level of coverage is up to the developer and should be done when the code is sufficiently complex. -Tests must all succeed for a final release. - -### [PHPDocumentor](https://docs.phpdoc.org/latest/guide/guides/running-phpdocumentor.html) - -Generates automatic documentation based on code comments. -You can customize the output by copying `/phpdoc.dist.xml` to `/phpdoc.xml` which now takes precedence and isn't tracked with git. -The documentation will be generated in `/.phpdoc/build`. - -### [PHP-CS-Fixer](https://github.com/FriendsOfPhp/PHP-CS-Fixer#usage) - -`composer lint` and `composer fix` -lints (just warnings) and fixes (changes files) code formating to [PSR-12] - -## Application Structure - -```text - /config Application configuration - /Controls All reusable page control objects - /database_schema Base and upgrade sql scripts - - /Domain Domain specific entities, repositories, services, etc - /Access Domain repository objects (db abstraction layer) - /Events Domain events - /Values Value objects - - /Jobs All tasks that run on a schedule (cron tasks, for example) - /lang Translations - /lib All application supporting objects - - /Application Most of the subdirectories are self-explanatory - /Admin Application administration logic - /Attributes Custom attributes - /Authentication Authentication (login) - /Authorization Authorization (access) - /Reporting Logic for generating and running reports - /Reservation - /Notification Post-reservation logic - /Persistence Creating, updating, deleting reservation information - /Validation Pre-reservation logic - /Schedule Schedule population - /User - - /Common Non-specific shared objects (localization, dates, smarty, etc) - /Config Configuration read/write - /Database Database access and abstractions - /Email Email abstractions and services - /external Third party libraries - /FileSystem Filesystem, I/O object - /Graphics Creating and manipulating images - /Server Web server abstractions (sessions, cookies, etc) - /WebService Objects for creating and invoking web services (the API) - - /Pages Page binding and work flow logic - /phing-tasks Custom build tasks that hook into phing - /plugins Contains subdirectories for each type of plugin - /Presenters Application logic, page population - /tests All unit tests - /tpl All Smarty page and control templates - /tpl_c Default Smarty template cache directory - /uploads Default file upload directory - /Web All user facing pages - /scripts All application related javascript files - /WebServices The LibreBooking API -``` - -## Database - -![Entity Relationship Diagram](./ERD.svg) -you can open `/doc/LibreBooking.mbw` with [MySQL Workbench](https://www.mysql.com/products/workbench/) to edit/update this ERD diff --git a/doc/SAML-Configuration.md b/doc/SAML-Configuration.md deleted file mode 100644 index 4d7d0d1f3..000000000 --- a/doc/SAML-Configuration.md +++ /dev/null @@ -1,159 +0,0 @@ -# SAML (Security Assertion Markup Language) Configuration - -**It is important to make sure registration.require.email.activation is set to false in Application Configuration. If -email activation is enabled users will never be able to log in.** - -## LibreBooking SAML Introduction - -LibreBooking comes with multiple Single Sign On -plugins out of the box. There are many benefits to SSO over standard authentication. For administrators, having a single -point of account credential and access administration is very valuable. If someone leaves the organization they don’t -have to deactivate accounts in multiple systems. For your normal user, the benefit is not having to register and -remember yet another set of application credentials. - -In this post we’ll cover how to set up SSO with SAML. Most SSO -configurations for LibreBooking are pretty straightforward – you just update the configuration options for the plugin. -But SAML is different. SAML requires a 3rd party application -called [SimpleSAMLphp](http://web.archive.org/web/20210303172340/https://simplesamlphp.org/) to be running on the same -server as LibreBooking. - -## Install SimpleSAMLphp - -Our first step is to download the latest version -of [SimpleSAMLphp](http://web.archive.org/web/20210303172340/https://simplesamlphp.org/) and install it on your web -server. I recommend installing it outside your publicly visible directories and set up a subdomain pointing to the -www directory. For example, if you install it to `/home/username/simplesamlphp` and you have LibreBooking running out of -`/home/username/public\_html/librebooking`, then you’d create a subdomain such as `saml.librebooking.xpto` pointing to -`/home/username/simplesamlphp/www`. The reason we do this is because the only files which need to be publicly visible in -SimpleSAMLphp are located in the www directory. Exposing more than that opens unnecessary security holes. - -## Configure SimpleSAMLphp - -SimpleSAMLphp has a lot of configuration options. If you’re like me and far from an expert in SAML, it’s overwhelming. -Luckily, since LibreBooking is a Service Provider it doesn’t need anything special. I’ll go through each of the settings -that need to be updated individually. Please note that at the time of writing this post, the latest version of -SimpleSAMLphp was 1.18.5. It’s possible that the names of the options will change in future versions. - -Copy `/home/username/simplesamlphp/config/config.php.dist` to `/home/username/simplesamlphp/config/config.php` - -Open up `/home/username/simplesamlphp/config/config.php` with a text editor. - -`baseurlpath` - Set this to the full path of the SimpleSAMLphp WWW directory. If you followed the above advice and -created a -subdomain, this should be something like `https://saml.yourdomain.com` - -`technicalcontact_email` - Your email address (or anyone responsible for managing SSO integrations) - -`secretsalt` - Set this to any secure, random value. - -`auth.adminpassword` - Set this to any secure, random value, you will use this to access the admin page of the web UI -for SimpleSAML. - -`trusted.url.domains` - This should be set to an array of domains that will participate in the SSO -handshake. I use `array('saml.librebooking.com', 'librebooking.com')` - -`session.cookie.domain` - This should be set to the wildcard subdomain of your primary domain. For example, I -use `.librebooking.com` - -`session.cookie.secure` - This should be set to true, assuming all traffic is sent over https. - -`store.type` - Set this to `sql`. This ensures that PHP sessions -from LibreBooking and sessions from SimpleSAMLphp do not conflict. - -`store.sql.dsn` - This should be set to a writable location for the sqlite database. You **must** have SQLite support in -PHP enabled for this -to work. Alternatively, you can set up -any PDO supported database to store session data. Since I use SQLite, I have this set to something -like `sqlite:/home/username/tmp/sqlitedatabase.sq3` - -## Exchange Metadata - -Now that we have the configuration set, we’ll need to exchange metadata. - -The first thing to do is get the metadata XML -from the Identity Provider that you’re integrating with. For example in Azure apps you can find this under Manage -> -Single sign-on -> SAML Certificates -> Federation Metadata XML - -SimpleSAMLphp has a handy metadata XML conversion tool, which -we’ll use to finish up our configuration. - -* Open the admin page from the subdomain for SimpleSAMLphp in a - browser ( was what I used). -* You’ll be prompted to enter the _auth.adminpassword_ that you set in your config.php -* Click on the _Federation_ tab -* then the _XML to SimpleSAMLphp metadata converter_ link. -* Paste in the XML or, if you have it saved to a file, upload it. -* SimpleSAMLphp will output at least one PHP version of that - metadata. -* For each one of those, create a file with that name plus `.php` in the folder `/home/username/simplesamlphp/metadata`. - The file should contain ` -* Open up `/simplesamlphp/config/authsources.php` -* Find the `idp` setting, and paste the value of the remote `entityid` into the `idp` field. -* Then set the local `entityid` field to a value of your choice. Usually the URL of the website you are creating SSO for. Remember this value as you will need this value in a later step when you configure the remote single sign on provider. - -## Update SAML Configuration in LibreBooking - -Whew, almost done! The last few settings are in LibreBooking. - -First, open up -`/your-librebooking-directory/config/config.php` and set the authentication: - -`$conf['settings']['plugins']['Authentication'] = 'Saml';` - -Then go to the folder -`/your-librebooking-directory/plugins/Authentication/Saml` - -Then copy `Saml.config.dist.php` to `Saml.config.php`. - -Open `Saml.config.php` in an editor: - -`simplesamlphp.lib` - set this to the root filesystem directory of SimpleSAMLphp. If you’re using the settings I -described here, this would be `/home/username/simplesamlphp`. - -`simplesamlphp.config` - Set this to the config filesystem directory for SimpleSAMLphp. In this case -`/home/username/simplesamlphp/config` - -Most of the remaining settings are attribute maps. SAML will send over user -attributes, but often with obscure names. LibreBooking needs to know which attribute maps to the proper user field in -LibreBooking. - -There are only 2 absolutely required fields to map – username/userid and email. For example, if the -username is being sent across in the SAML payload as `urn:oid:0.1.2.3` you’d set `simplesamlphp.username` to this value -like `$conf['settings']['simplesamlphp.username'] = 'urn:oid:0.1.2.3';` - -This is the same for all the other -attributes. If you don’t know the attributes coming across then you can add the following line to -plugins/Authentication/Saml/SamlUser.php as the first line in the -constructor: `Log::Debug('Saml attributes are: %s', var_export($saml_attributes, true));` Enable Logging in LibreBooking -and try to log in. We’ll write out the attributes to the log file and you can copy the names into the LibreBooking SAML -configuration file. - -## Configuring the other end - -You will need to configure the other end. For example the Azure Application Saml SSO settings. - -First of all, you need to set the identifier ID, which is the value you used for your local entityId at the end of the section titled "Exchange Metadata". - -Then you need to tell it the URL to send data back to. This is called the ACS or Assertion Consumer Service URL or Reply URL. Set it to - -You probably also want to set a logout URL which should be: - -## Some Restrictions - -A couple important notes with SAML enabled: - -The first is that you will no longer be able to log into LibreBooking with -any other credentials. There is no “back door” – so every authentication request will be routed through SAML. - -The other restriction is that you will not be able to use any authenticated method from the API. SAML performs a series -of browser -redirects in order to complete the authentication process. When using the API you are not within the context of a -browser, so authentication will fail. - -## Logging In - -Once all the mapping is complete, you should be able to log into LibreBooking via your organization’s federated log in -page. Your users will no longer have to remember another set of credentials and your account management just got one -step easier! diff --git a/doc/.markdownlint.yml b/docs/.markdownlint.yml similarity index 100% rename from doc/.markdownlint.yml rename to docs/.markdownlint.yml diff --git a/doc/LibreBooking.mwb b/docs/entity-relationship-diagram/LibreBooking.mwb similarity index 100% rename from doc/LibreBooking.mwb rename to docs/entity-relationship-diagram/LibreBooking.mwb