** This project is no longer being maintained, please use at your own discretion! **
Reactive application that listens on Google calendars within a G Suite with the ability to process business logic
π¨ This project is no longer being actively maintained, and remains as provided as good will for public consumption. Please use at your own discretion.
stenella
is an unofficial, server-to-server, Node.js application that listens to Google calendars events that are created, deleted, or updated. With each event, developers can define and execute their own business logic in regards to contextual cues found within a calenader event payload (date, subject, summary, attendees, location, status, etc.). These are known as "observers" (calendar event handlers), which are flexible, open-ended, and simple to write.
π
The demo above displays the application receiving a calendar event being created, which is logged to the console in real-time
- Features
- Requirements
- Installation
- Deployment
- Configuration
- Google API Usage
- Observers
- Restricting Users
- Authors
- Contributing
- License
Along with listening to a Google calendar, stenella
provides the following features and performs additional heavy work:
- Ability to manually set users to listen
- Automatically renew listening channels with Google
- An easy to use, and straightforward way to implement observers
- Handles the complexities of processing events to
observers
:- Events created, deleted, or updated within a short period of time will cause the application to only process the most recent change
- The application will prevent any duplicated events being processed twice within a cached time
- An event with "Guests Can Modify" will only process the most recent event received, and will only process new changes
- Events with multiple guests will only be regarded as one unique event for
observers
- Includes a
Dockerfile
, along withdocker-compose
files for easier deployment examples - Automatically listens to newly created users within a organization
- A means to verify domains with Google and to remain verified throughout the life of the application
- G Suite (Previously known as Google Apps for Work)
- Admin privileges within a G Suite
- MongoDB
- A publicly available server with a domain
-
Verify your application's domain name ownership
Verification of the application domain name with Google proves that you own/trust it. This enables the application to handle Google calendar notifications.
stenella
provides a/verify
directory where you can simply drop yourverification.html
files into it and it will be publicly available to Google verfication servers. -
Create a Google App
- Go to the Google API Console
- From the project drop-down, select Create a New Project
- Select Dashboard Menu and click Enable API
- Select the Google Calendar API under Google Apps API. This enables the application to use the Google Calendar API.
- Go to the IAM & Admin view (click on left hamburger icon)
- Select Service Account > CREATE SERVICE ACCOUNT
- Enter a service account name, leave the role blank, and check Enable G Suite Domain-wide Delegation
- Check Furnish a new private key: Key Type: JSON > Create
This will automatically download a private key to your computer. This is the only copy of the key, so store it in a secure manner and ensure that it is accessible to the application.
- Go to the API Manager view, select the Credentials menu
- Select the Domain Verification tab, click Add Domain and add your domain that was verified in Step 1
β οΈ Please complete the appropriate Google permissions and steps before moving on with Stenella
- Download repository and install dependencies
$ git clone https://github.com/cisco-ie/stenella.git && cd stenella $ npm install
- Configure environment variables, refer to configuration for more details
$ cp example.env .env
- Setup the MongoDB database
- Initiate Mongodb,
mongod
- Start up application,
$ npm start
- Go to
https://<YOUR_DOMAIN>:<?PORT>
(localhost if you have not pointed the domain) and you should see aCalendar Listener Works!
Before running docker-compose, ensure an .env
file is properly populated with correct configurations. The /containers
directory contain different deployment examples:
- /containers/ - A base deployment which includes mongodb, stenella
- /containers/nginx - An advance deployment which includes a mongodb, stenella, and nginx
DB_URL
should be set tomongodb://database/<databaseName>
- Within the compose file,
volumes
should mount the location of your service token. e.g.volumes: - ../path/to/token:/app/secret
To bring up docker containers:
$ cd [containers or containers/nginx]
$ docker-compose up
Validate that the application is exposed and running by checking the localhost, it should respond with Google Listener Works!
- Base depoyment: https://localhost:5000
- With Nginx https://localhost:5001
Stenella includes various configurations that are managed within the .env
file of the application or environment variables set within shell of the application instance. Please refer to the table below, or the example.env
file.
ENV Variable | Required | Description |
---|---|---|
ADMIN | β | A G Suite admin for the application to act as proxy for |
DOMAIN | β | The domain associated with the Google organization |
CUSTOMER | β | A customerId for organizations with multiple domains, the application will only run across that customerId |
RECEIVING_URL | β | The public server url for Google to send notifications, and authorize API calls from |
DB_URL | β | The primary mongodb location of where stenella will store information regarding calendar subscriptions |
DB_URL_TEST | π« | This is an mongodb location where the test suite would run it's associated file. It should be different from DB_URL |
GOOGLE_APPLICATION_CREDENTIALS | β | The path containing the Google service JSON web token, this should also be granted delegated permissions |
PRIVATE_KEY_PATH | π« | If you want to run SSL on the application server, this path should point to the private key (.pem). |
FULL_CHAIN_CERT_PATH | π« | To run SSL on the application server, this path should point to the full chain certificate (.pem). |
CERT_PASSPHRASE | π« | Required if the cert was generated using a passphrase, insert the passphrase here. |
USER_WHITELIST_PATH | π« | A JavaScript file containing an array of emails for the application to listen on |
TTL | π« | A "time-to-live" in ms for user subscriptions -- how long to keep the subscription open with google before renewing. Default: 1500 ms (25 mins) |
While stenella
is using several Google APIs, it heavily relies on Google Calendar API. In most scenarios, we don't believe this will exceed the 1,000,000 / day quota, but large organizations (> 10,000) with significant amount of users should account for additional cost associated with API usage.
Action | # of API Request |
---|---|
Start Up | 1 / User |
Updated, Cancelled, Created Event | 1 / Attendee & Creator |
Renewing Calendar Subscription | 1 / User |
If you are not familar with
observers
, please check out the rx.js documentation onobservers
Observers
give you the flexibility to create your own set of business logic in respose to events. Within stenella
, observers
are simply functions that receieve the event payload.
-
Create a new file within the
/observers
directoryπ‘ All observers are loaded from the
/observers
directory, no configuration needed. -
Within your file, import the observable object from the event controller to allow the observer to subscribe to new calendar events.
const calendarEvents = require('../controllers/event-controller').observable;
-
Now subscribe to events, and write your own handler to perform any logic
calendarEvents.subscribe((event) => { // Do work based on particular conditions });
-
Start the listener and your
Observer
will now be invoked upon calendar event notifications
Refer to the example observer within the /observers
directory for coding reference.
- Avoid multiple observers processing for the same condition
- Include a means to indicate a change was caused by your observer as
stenella
is unaware of any events created, deleted, or updated by observers - For every update done on an event, this will count as 1 API call and + (1 *
X
# Attendees) since this will count as a theoretical new event
Restrict the calendar to only listen on a subset of users by exporting a JavaScript array of emails to only listen to and set the USER_WHITELIST_PATH
to the path of the JavaScript file.
Example: exampleList.js
module.exports = [
"testuser1@gmail.com",
"testuser2@gmail.com"
];
Setting the environment variable:
USER_WHITELIST_PATH=./exampleList.js
We know Stenella
is far from perfect, so we are excited to build upon our existing work with other community members. With that said, please submit an issue prior to getting started to avoid duplicated effort.
For additional developer docs, refer to the Wiki's Development Docs.
Feel free to submit a issue for any questions in regards to bugs, deployment, details, etc.
Apache License 2.0 Β© Innovation Edge @ Cisco