/store-sentry

Manage access to in-app purchase content hosted in Cloudflare based on App Store Server Notifications

Primary LanguageJavaScriptMIT LicenseMIT

Absolutely, I can help with that. Here's a draft for the README file of your project.


Store-Sentry

Store-Sentry is a serverless application that allows developers to manage access to in-app purchase content hosted on Cloudflare, based on App Store Server Notifications. The application is structured into two main components: gatekeeper and listening-post.

Getting Started

Before setting up Store-Sentry, make sure you have Node.js and npm (Node Package Manager) installed on your machine.

Prerequisites

  • Node.js
  • npm (comes with Node.js)
  • A Cloudflare account
  • Access to the Apple App Store Server Notifications

Installation

  1. Clone the repository
git clone https://github.com/yourusername/store-sentry.git
  1. Change the directory
cd store-sentry
  1. Install the dependencies
npm install
  1. Fill out the necessary environment variables in the wrangler.toml files in both gatekeeper and listening-post directories.

Usage

Store-Sentry is divided into two components:

  1. gatekeeper: This component is responsible for managing access to in-app purchase content. It controls the access to both public and premium content based on the user status stored in a key-value pair storage.

  2. listening-post: This component listens for App Store Server Notifications and updates user access status in the key-value pair storage accordingly.

The two components are independent but work together to manage access to in-app purchase content.

Contributing

What this code does:

Gatekeeper

This code defines two functions, update and read, and exports an object with a fetch method.

The update function handles a PUT request. It takes in a request object and an env object as parameters. It first extracts the search parameters from the request URL and assigns them to searchParams. Then, it creates a new URL object from the request URL and assigns it to url. It slices the pathname from the URL and assigns it to fullpath. It retrieves the value of the "key" parameter from searchParams and assigns it to key.

If the key is equal to the ADMIN_KEY stored in the env object, it uses the put method of APP_CONTENT (presumably a storage API) to update the content at the specified fullpath with the request body. It returns a response with the message "Updated {fullpath} successfully!".

If the key does not match the ADMIN_KEY, it returns a response with the message "Forbidden" and a status code of 403.

The read function handles a GET request. It takes in a request object and an env object as parameters. It creates a new URL object from the request URL and assigns it to url. It slices the pathname from the URL and assigns it to fullpath. It splits the pathname into an array of subpaths using the "/" delimiter and assigns it to subpaths.

If the first element of subpaths is "public", it uses the get method of APP_CONTENT to retrieve the content at the specified fullpath and assigns it to plan.

If the first element of subpaths is "premium", it retrieves the "uuid" parameter from the URL search parameters and assigns it to uuid. It uses the get method of APP_USERS to retrieve the status associated with uuid and assigns it to status. If status is "ALLOW", it uses the get method of APP_CONTENT to retrieve the content at the specified fullpath and assigns it to plan. If status is "DENY", it returns a response with the message "Forbidden" and a status code of 403.

If the first element of subpaths is neither "public" nor "premium", it uses the get method of APP_CONTENT to retrieve the content at the path "inventory.json" and assigns it to plan.

Next, the function creates a new Headers object and calls the writeHttpMetadata method on plan (assuming it's an object with that method) to write the HTTP metadata to the headers. It sets the "etag" header to the HTTP etag of plan. Finally, it returns a response with the body of plan and the headers.

The exported object has a fetch method that takes in a request, env, and ctx as parameters. It uses a switch statement to determine the method of the request. If the method is "PUT", it calls the update function with the request and env parameters. If the method is "GET", it calls the read function with the request and env parameters. Otherwise, it returns a response with the message "Method Not Allowed" and a status code of 405.

Listening Post

This code defines several functions that handle an incoming request and perform various operations based on the request's payload. Here's a breakdown of each function and its purpose:

  1. read: This function reads the incoming request body and returns a parsed JSON object if the content-type of the request is "application/json". Otherwise, it returns null.

  2. decode: This function takes a signed payload (assumed to be a JSON web token) and decodes it. It splits the payload by periods, extracts the encoded payload (the second part), and uses the atob function to decode the base64-encoded payload. It then parses the decoded payload and returns it as a JSON object.

  3. storeToken: This function accepts a unique user ID (uuid), a notification type, and a subtype. Based on the notification type and subtype, it assigns a verdict ("ALLOW" or "DENY"). The function stores the uuid and the verdict in a KV (Key-Value) database.

  4. handle: This function is the main request handler. It takes an incoming request as a parameter. If the request method is "POST", it reads the request body using the read function. If the body contains a "signedPayload" property, it decodes the signed payload using the decode function and extracts the notification type, subtype, and data from the payload. If the data includes a "signedTransactionInfo" property, it decodes it and retrieves the appAccountToken. The storeToken function is then called with the appAccountToken, notification type, and subtype to store the token in the KV database. Finally, it returns a new Response with a status of 202 (Accepted).

  5. addEventListener: This code registers an event listener for the "fetch" event. When a fetch event occurs, it calls the handle function with the request and responds with the returned response.

Decodes your JWTs.

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

License

This project is licensed under the MIT License