Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2f9f529
Reconfigured Request as an abstract factory class. Updated construct…
Feb 10, 2017
73587b2
Update package name and Readme
Feb 10, 2017
cd897a2
Add tag .1.7
Feb 10, 2017
62c0c80
Add CustomSkillRequestType abstract
Feb 11, 2017
b9d868b
Refactor factory method into a separate class as non-static to improv…
Mar 8, 2017
be5ca44
Add getters to Request classes to improve Open/Closed and testability
Mar 8, 2017
8daa8a0
Adds setters and a bunch of PSR
Mar 8, 2017
ae16211
Breaking change - Move to symfony validation and more PSR and cleanup
Mar 10, 2017
ecbff89
Adds HtmlPurifier for xss cleaning
Mar 10, 2017
d9fd83a
Access token key is not provided in un-linked services
Mar 11, 2017
870cdc4
Add purifier destroyer to make the object easier to log
Mar 11, 2017
21a8ceb
Wrong access on method
Mar 11, 2017
d95207e
Adds support for the Standard card type and cleans up the rendering i…
Mar 11, 2017
3d55558
All setters null check before casting to string
Mar 11, 2017
c68a01a
Fix card type
Mar 11, 2017
1eae822
Breaking change - Object calisthenics - Made all objects stateless. …
Mar 11, 2017
be03b01
Add enumerations for valid card types and outputspeech types
Mar 11, 2017
8efe8c7
Update README.md
Mar 11, 2017
ab116f2
Fix broken child class constructors. Go back to public destroyPurifi…
Mar 11, 2017
44dc407
Fix broken reference
Mar 11, 2017
875f6ed
Fix missing return
Mar 11, 2017
4334c22
Fix missing calls to ->render()
Mar 11, 2017
45722ec
Fix defaulting for purifier
Mar 11, 2017
61e5e2e
Update README.md
Mar 11, 2017
2359de4
Add all getters from BaseRequest to the interface, should have done t…
Mar 13, 2017
d8dd333
Add all getters from BaseRequest to the interface, should have done t…
Mar 13, 2017
2f35228
Purifier instantiated in the wrong order
Mar 13, 2017
b2ed7b6
Fix typo in error string
Mar 22, 2017
da4dd1d
Fix typo in error string
Mar 22, 2017
4861a28
At least on the test portal, the empty slots member is not being crea…
Apr 9, 2017
e8e0b7c
Add tags
Oct 18, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
# Amazon Alexa PHP Library

This library provides provides a convient interface for developing Amazon Alexa Skills for your PHP app.
This library provides provides a convenient interface for developing Amazon Alexa Skills for your PHP app.

It represents a breaking change (and is forked) from jakobsuchy/amazon-alexa-php
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reword this statement


The most important changes are the addition of XSS purification and some basic Doctrine validation, and making
everything stateless, SRP and more testable

## Usage

Install via composer: `composer require minicodemonkey/amazon-alexa-php`.
Install via composer: `composer require froodley/amazon-alexa-php`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the correct repo name here


### Requests
When Amazon Alexa triggers your skill, a HTTP request will be sent to the URL you specified for your app.

You can get the `JSON` body of the request like so:
```php
$applicationId = "your-application-id-from-alexa"; // See developer.amazon.com and your Application. Will start with "amzn1.echo-sdk-ams.app."
$rawRequest = $request->getContent; // This is how you would retrieve this with Laravel or Symfony 2.
$alexa = new \Alexa\Request\Request($rawRequest, $applicationId);
$alexaRequest = $alexa->fromData();
$rawRequest = $request->getContent(); // This is how you would retrieve this with Laravel or Symfony 2.
$alexaRequestFactory = new \Alexa\Request\RequestFactory();
$alexaRequest = $alexaRequestFactory->fromRawData($rawRequest, [$applicationId]);
```

The library expect raw request data, not parsed JSON as it needs to validate the request signature.
Expand Down
22 changes: 18 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
{
"name": "jakubsuchy/amazon-alexa-php",
"description": "Amazon Alexa interface for PHP",
"name": "froodley/amazon-alexa-php",
"description": "Amazon Alexa interface for PHP - XSS Filtering, Improved Testability",
"license": "MIT",
"type": "library",
"keywords": [
"Amazon Echo",
"Amazon Alexa",
"Alexa",
"Echo"
],
"authors": [
{
"name": "Mathias Hansen",
Expand All @@ -15,13 +21,21 @@
{
"name": "Jakub Suchy",
"email": "[email protected]"
},
{
"name": "froodley",
"email": "[email protected]"
}
],
"require": {
"php": ">=5.3.0"
"php": ">=5.5.9",
"ext-curl": "*",
"doctrine/orm": "^2.5.6",
"symfony/validator": "^3.2.6",
"ezyang/htmlpurifier": "^4.7"
},
"require-dev": {
"phpunit/phpunit": "~4.6"
"phpunit/phpunit": "^5.7.15"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will conflict with Drupal's current dependency on ">=4.8.35 <5". Perhaps use "~4.8" here, instead?

},
"autoload": {
"psr-4": {
Expand Down
119 changes: 89 additions & 30 deletions src/Request/Application.php
Original file line number Diff line number Diff line change
@@ -1,40 +1,99 @@
<?php
/**
* @file Application.php
*
* The application abstraction layer to provide Application ID validation to
* Alexa requests. Any implementations might provide their own implementations
* via the $request->setApplicationAbstraction() function but must provide the
* validateApplicationId() function.
*/

namespace Alexa\Request;
use InvalidArgumentException;

class Application {
public $applicationId;
public $requestApplicationId;
use Symfony\Component\Validator\Constraints as Assert;

public function __construct($applicationId) {
$this->applicationId = preg_split('/,/', $applicationId);
}

public function setRequestApplicationId($applicationId) {
$this->requestApplicationId = $applicationId;
}
use Alexa\Utility\Purifier\HasPurifier;

/**
* Validate that the request Application ID matches our Application. This is required as per Amazon requirements.
* Class Application
*
* Represents an Alexa application
*
* @param $requestApplicationId
Application ID from the Request (typically found in $data['session']['application']
* @package Alexa\Request
*/
public function validateApplicationId($requestApplicationId = "") {
if (empty($requestApplicationId)) {
$requestApplicationId = $this->requestApplicationId;
}
if (!in_array($requestApplicationId, $this->applicationId)) {
throw new InvalidArgumentException('Application Id not matched');
}
}
class Application
{
// Constants

const ERROR_APPLICATION_ID_NOT_STRING = 'The provided value for the Alexa application ID was not a string';
const ERROR_APPLICATION_ID_NOT_MATCHED = 'The application ID \'%s\' found in the request does not match ' .
'any of the expected application IDs.';

// Traits

use HasPurifier;

// Fields

/**
* @var string
*
* @Assert\Type("string")
* @Assert\NotBlank
*/
private $applicationId;


// Hooks

/**
* Application constructor.
*
* @param string $applicationId
* @param \HTMLPurifier $purifier
*/
public function __construct($applicationId, \HTMLPurifier $purifier)
{
// Set purifier
$this->setPurifier($purifier);

// Set application IDs
$this->setApplicationId($applicationId);
}

// Public Methods

/**
* validateApplicationId()
*
* Confirms the application ID from the request is one in the list provided as valid
*
* @param array[string] $validApplicationIds
*
* @throws \InvalidArgumentException
*/
public function validateApplicationId(array $validApplicationIds)
{
if (!in_array($this->getApplicationId(), $validApplicationIds)) {
throw new \InvalidArgumentException(
sprintf(self::ERROR_APPLICATION_ID_NOT_MATCHED, $this->getApplicationId())
);
}
}

// Accessors

/**
* @return string
*/
public function getApplicationId()
{
return $this->applicationId;
}

// Mutators

/**
* @param string $applicationId
*/
protected function setApplicationId($applicationId)
{
if (!is_string($applicationId)) {
throw new \InvalidArgumentException(self::ERROR_APPLICATION_ID_NOT_STRING);
}

$this->applicationId = $applicationId;
}
}
Loading