1
0
mirror of https://framagit.org/tykayn/date-poll-api synced 2023-08-25 08:23:11 +02:00

save new stack and return updated poll

This commit is contained in:
Tykayn 2021-04-29 11:41:36 +02:00 committed by tykayn
parent a481a41a6c
commit 80abd003ae
7 changed files with 279 additions and 330 deletions

View File

@ -1,78 +1,81 @@
{ {
"type": "project", "type": "project",
"license": "proprietary", "license": "aGPLv3",
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true, "description": "Une API pour framadate funky",
"require": { "name": "datepollapi",
"php": ">=7.2.5", "prefer-stable": true,
"ext-ctype": "*", "require": {
"ext-iconv": "*", "php": ">=7.2.5",
"composer/package-versions-deprecated": "1.11.99.1", "ext-ctype": "*",
"doctrine/annotations": "^1.12", "ext-iconv": "*",
"doctrine/doctrine-bundle": "^2.3", "composer/package-versions-deprecated": "1.11.99.1",
"doctrine/doctrine-migrations-bundle": "^3.1", "doctrine/annotations": "^1.12",
"doctrine/orm": "^2.8", "doctrine/doctrine-bundle": "^2.3",
"friendsofsymfony/rest-bundle": "^3.0", "doctrine/doctrine-migrations-bundle": "^3.1",
"jms/serializer-bundle": "^3.9", "doctrine/orm": "^2.8",
"nelmio/cors-bundle": "^2.1", "friendsofsymfony/rest-bundle": "^3.0",
"sensio/framework-extra-bundle": "^6.1", "jms/serializer-bundle": "^3.9",
"symfony/asset": "5.2.*", "nelmio/cors-bundle": "^2.1",
"symfony/console": "5.2.*", "sensio/framework-extra-bundle": "^6.1",
"symfony/dotenv": "5.2.*", "symfony/asset": "5.2.*",
"symfony/flex": "^1.3.1", "symfony/console": "5.2.*",
"symfony/form": "5.2.*", "symfony/dotenv": "5.2.*",
"symfony/framework-bundle": "5.2.*", "symfony/flex": "^1.3.1",
"symfony/proxy-manager-bridge": "5.2.*", "symfony/form": "5.2.*",
"symfony/swiftmailer-bundle": "^3.5", "symfony/framework-bundle": "5.2.*",
"symfony/twig-bundle": "5.2.*", "symfony/proxy-manager-bridge": "5.2.*",
"symfony/yaml": "5.2.*" "symfony/swiftmailer-bundle": "^3.5",
"symfony/twig-bundle": "5.2.*",
"symfony/yaml": "5.2.*",
"ext-json": "*"
},
"config": {
"optimize-autoloader": true,
"preferred-install": {
"*": "dist"
}, },
"config": { "sort-packages": true
"optimize-autoloader": true, },
"preferred-install": { "autoload": {
"*": "dist" "psr-4": {
}, "App\\": "src/"
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "5.2.*"
}
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4",
"symfony/debug-bundle": "5.2.*",
"symfony/maker-bundle": "^1.30"
} }
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "5.2.*"
}
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4",
"symfony/debug-bundle": "5.2.*",
"symfony/maker-bundle": "^1.30"
}
} }

View File

@ -1,5 +1,6 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html # see https://symfony.com/doc/current/reference/configuration/framework.html
framework: framework:
trusted_hosts: ['localhost:4200', 'localhost']
secret: '%env(APP_SECRET)%' secret: '%env(APP_SECRET)%'
#csrf_protection: true #csrf_protection: true
#http_method_override: true #http_method_override: true

View File

@ -3,8 +3,9 @@ nelmio_cors:
origin_regex: true origin_regex: true
allow_origin: [ '*' ] allow_origin: [ '*' ]
allow_methods: [ 'GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ] allow_methods: [ 'GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ]
allow_headers: [ 'Accept','Authorization','Cache-Control','Content-Type','DNT','If-Modified-Since','Keep-Alive','Origin','User-Agent','X-Requested-With' ] allow_headers: [ '*' ]
expose_headers: [ 'Authorization' ] expose_headers: [ 'Authorization' ]
allow_credentials: true
max_age: 3600 max_age: 3600
paths: paths:
'^/': ~ '^/': ~

View File

@ -5,7 +5,7 @@
use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
header( 'Access-Control-Allow-Origin: *' ); // header( 'Access-Control-Allow-Origin: *' );
// header( "Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method" ); // header( "Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method" );
// header( "Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE" ); // header( "Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE" );
header( "Allow: GET, POST, OPTIONS, PUT, DELETE" ); header( "Allow: GET, POST, OPTIONS, PUT, DELETE" );

View File

@ -1,269 +1,208 @@
<?php <?php
namespace App\Controller\api; namespace App\Controller\api;
use App\Controller\EmailsController; use App\Controller\EmailsController;
use App\Entity\Choice; use App\Entity\Owner;
use App\Entity\Owner; use App\Entity\Poll;
use App\Entity\Poll; use App\Entity\StackOfVotes;
use App\Entity\StackOfVotes; use App\Entity\Vote;
use App\Entity\Vote; use App\Repository\ChoiceRepository;
use App\Repository\ChoiceRepository; use FOS\RestBundle\Controller\Annotations\Delete;
use FOS\RestBundle\Controller\Annotations\Delete; use FOS\RestBundle\Controller\Annotations\Patch;
use FOS\RestBundle\Controller\Annotations\Patch; use FOS\RestBundle\Controller\Annotations\Route;
use FOS\RestBundle\Controller\Annotations\Post; use JMS\Serializer\SerializerInterface;
use FOS\RestBundle\Controller\Annotations\Route; use Symfony\Component\HttpFoundation\JsonResponse;
use JMS\Serializer\SerializerInterface; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /**
* Class DefaultController
* @package App\Controller
* @Route("/api/v1",name="api_")
*/
class VoteController extends EmailsController {
/** /**
* Class DefaultController * add a vote stack on a poll
* @package App\Controller * @Route(
* @Route("/api/v1",name="api_") * path = "/poll/{custom_url}/answer",
* name = "new_vote_stack",
* methods={"POST","OPTIONS"}
* )
*
* @param SerializerInterface $serializer
* @param string $custom_url
* @param Request $request
*
* @return JsonResponse|Response
*/ */
class VoteController extends EmailsController { public function newVoteStackAction(
SerializerInterface $serializer,
/** string $custom_url,
* add a vote stack on a poll Request $request,
* @Post( ChoiceRepository $choice_repository
* path = "/poll/{custom_url}/answer",
* name = "new_vote_stack",
* )
*
* @param SerializerInterface $serializer
* @param string $custom_url
* @param Request $request
*
* @return JsonResponse|Response
*/
public function newVoteStackAction(
SerializerInterface $serializer,
string $custom_url,
Request $request,
ChoiceRepository $choice_repository,
) { ) {
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
$emPol = $em->getRepository( Poll::class ); $emPol = $em->getRepository( Poll::class );
$poll = $emPol->findOneByCustomUrl( $custom_url ); $poll = $emPol->findOneByCustomUrl( $custom_url );
if ( ! $poll ) { if ( ! $poll ) {
return $this->json( [ 'message' => 'poll "' . $custom_url . '" not found' ], 404 ); return $this->json( [ 'message' => 'poll "' . $custom_url . '" not found' ], 404 );
}
$data = $request->getContent();
$data = json_decode( $data, true );
// var_dump($data);
// die();
$owner = new Owner();
$owner
->addPoll( $poll )
;
$newStack = new StackOfVotes();
$newStack
->setPoll($poll)
->setIp( $_SERVER[ 'REMOTE_ADDR' ] )
->setPseudo( $data[ "pseudo" ] )
->setOwner( $owner );
$owner
->setPseudo($data['owner'][ "pseudo" ])
->setPseudo($data['owner'][ "email" ])
->addStackOfVote($newStack);
// TODO manage new comment
$emChoice = $choice_repository;
foreach ( $data[ 'votes' ] as $vote ) {
if(!$vote[ 'value' ]){
continue;
}
$newVote = new Vote();
$newVote->setPoll( $poll );
$newStack->addVote( $newVote );
$choiceFound = $emChoice->find( $vote[ 'choice_id' ] );
if ( $choiceFound ) {
$choiceFound->addVote( $newVote );
$newVote->setStacksOfVotes( $newStack )
->setChoice( $choiceFound )
->setValue( $vote[ 'value' ] );
$em->persist( $choiceFound );
} else {
throw new NotFoundHttpException( 'no choice of id' . $vote[ 'choice_id' ] );
} }
$data = $request->getContent(); $poll->addVote( $newVote );
$data = json_decode( $data, true ); $em->persist( $newVote );
// $data = $data['data']; }
$newStack
->setPoll( $poll );
$em->persist( $newStack );
$em->persist( $poll );
$em->flush();
$owner = new Owner(); if ( $poll->getMailOnVote() ) {
$owner->addPoll($poll); $this->sendVoteNotificationAction( $newStack->getOwner(), $newStack );
$newStack = new StackOfVotes(); }
$newStack
->setPseudo( $data[ 'pseudo' ] )
->setOwner($owner );
// TODO manage new comment return $this->json( [
$emChoice = $choice_repository; 'poll' => $poll->display(),
] );
foreach ( $data[ 'votes' ] as $vote ) {
$newVote = new Vote();
$newVote->setPoll($poll);
$newStack->addVote( $newVote ); }
$choiceFound = $emChoice->find( $vote[ 'choice_id' ] );
if ( $choiceFound ) {
$choiceFound->addVote( $newVote ); /**
$newVote->setStacksOfVotes( $newStack ) * update vote stack
->setChoice( $choiceFound ) * @Patch(
->setValue( $vote[ 'value' ] ); * path = "/vote-stack/{id}/token/{modifierToken}",
$em->persist( $choiceFound ); * name = "update_vote_stack",
} else { * requirements = { "id"="\d+"}
throw new NotFoundHttpException( 'no choice of id' . $vote[ 'choice_id' ] ); * )
} *
* @param SerializerInterface $serializer
* @param StackOfVotes $id
* @param $modifierToken
* @param Request $request
*
* @return JsonResponse|Response
*/
public
function updateVoteStackAction(
SerializerInterface $serializer,
StackOfVotes $id,
$modifierToken,
Request $request
) {
$voteStack = $id;
if ( ! $voteStack ) {
return $this->json( [ 'message' => 'vote stack not found' ], 404 );
}
$poll = $voteStack->getPoll();
$poll->addVote($newVote); // if only self users are allowed to modify a vote, check it
$em->persist( $newVote ); if ( ! $modifierToken || $voteStack->getOwner()->getModifierToken() !== $modifierToken ) {
} return $this->json( [ 'message' => 'your token does not allow you to modify this vote ' ],
$newStack 403 );
->setPoll( $poll ); }
$em->persist( $newStack ); // everything is ok, we can update all the votes of the vote stack
$em->persist( $poll ); //TODO
// match votes and choices
// update answers
// save evrything
$jsonResponse = $serializer->serialize( [
'message' => 'ok',
'modifier_token' => $voteStack->getOwner()->getModifierToken(),
'vote_stack' => $voteStack,
],
'json' );
$response = new Response( $jsonResponse );
$response->headers->set( 'Content-Type', 'application/json' );
$response->setStatusCode( 200 );
return $response;
}
/**
* @Delete(
* path = "/poll/{id}/votes/{accessToken}",
* name = "poll_votes_delete",
* requirements = {"accessToken"="\w+", "poll_id"="\d+"}
* )
* @return JsonResponse
*/
public
function deletePollVotesAction(
Poll $poll,
$accessToken
) {
if ( $accessToken == $poll->getAdminKey() ) {
$em = $this->getDoctrine()->getManager();
$length = count( $poll->getVotes() );
$em->remove( $poll->getVotes() );
$em->flush(); $em->flush();
return $this->json( [ return $this->json( [
'data' => $data, 'message' => 'boom! les ' . $length . ' votes du sondage ont été supprimés',
] );
// $emOwner = $em->getRepository( Owner::class );
// $emChoice = $em->getRepository( Choice::class );
// $existingOwner = false;
// $foundOwner = $emOwner->findOneByEmail( trim( $data[ 'email' ] ) );
// manage existing or new Owner
// if ( ! $foundOwner ) {
// $foundOwner = new Owner();
// $foundOwner
// ->setEmail( $data[ 'email' ] )
// ->setPseudo( $data[ 'pseudo' ] );
// } else {
// $existingOwner = true;
// }
// TODO anti flood
// $foundOwner
// ->setModifierToken( $poll->generateRandomKey() );
// $stack = new StackOfVotes();
// $stack
// ->setOwner( $foundOwner )
// ->setIp( $_SERVER[ 'REMOTE_ADDR' ] )
// ->setPseudo( $data[ 'pseudo' ] )
// ->setPoll( $custom_url );
// foreach ( $data[ 'votes' ] as $voteInfo ) {
//
// if ( ! isset( $voteInfo[ 'value' ] ) ) {
// continue;
// }
// $allowedValuesToAnswer = [ 'yes', 'maybe', 'no' ];
//
// if ( ! in_array( $voteInfo[ 'value' ], $allowedValuesToAnswer ) ) {
// return $this->json( [
// 'message' => 'answer ' . $voteInfo[ 'value' ] . ' is not allowed. should be yes, maybe, or no.',
// 'vote_stack' => $stack,
// ],
// 404 );
// }
// $vote = new Vote();
// $foundChoice = $emChoice->find( $voteInfo[ 'choice_id' ] );
// if ( ! $foundChoice ) {
// return $this->json( [
// 'message' => 'choice ' . $voteInfo[ 'choice_id' ] . ' was not found',
// 'vote_stack' => $stack,
// ],
// 404 );
// }
// $vote->setPoll( $poll )
// ->setChoice( $foundChoice )
// ->setValue( $voteInfo[ 'value' ] );
// $vote->setPoll( $poll );
// $stack->addVote( $vote );
// $poll->addVote( $vote );
// $em->persist( $vote );
// $em->persist( $foundChoice );
// }
//
// // find poll from choices
// $poll->addStackOfVote( $stack );
// $em->persist( $stack );
// $em->persist( $poll );
// $em->flush();
// $precision = '';
// if ( $existingOwner ) {
// $precision = ' from an existing owner : ' . $foundOwner->getEmail();
// }
//
// if ( $poll->getMailOnVote() ) {
// $this->sendVoteNotificationAction( $stack->getOwner(), $stack );
// }
//
// $returnedVoteStack = $stack;
//
// $jsonResponse = $serializer->serialize( $returnedVoteStack, 'json' );
//
// $response = new Response( $jsonResponse );
// $response->headers->set( 'Content-Type', 'application/json' );
// $response->setStatusCode( 200 );
//
// return $response;
}
/**
* update vote stack
* @Patch(
* path = "/vote-stack/{id}/token/{modifierToken}",
* name = "update_vote_stack",
* requirements = { "id"="\d+"}
* )
*
* @param SerializerInterface $serializer
* @param StackOfVotes $id
* @param $modifierToken
* @param Request $request
*
* @return JsonResponse|Response
*/
public
function updateVoteStackAction(
SerializerInterface $serializer,
StackOfVotes $id,
$modifierToken,
Request $request
) {
$voteStack = $id;
if ( ! $voteStack ) {
return $this->json( [ 'message' => 'vote stack not found' ], 404 );
}
$poll = $voteStack->getPoll();
// if only self users are allowed to modify a vote, check it
if ( ! $modifierToken || $voteStack->getOwner()->getModifierToken() !== $modifierToken ) {
return $this->json( [ 'message' => 'your token does not allow you to modify this vote ' ],
403 );
}
// everything is ok, we can update all the votes of the vote stack
//TODO
// match votes and choices
// update answers
// save evrything
$jsonResponse = $serializer->serialize( [
'message' => 'ok',
'modifier_token' => $voteStack->getOwner()->getModifierToken(),
'vote_stack' => $voteStack,
], ],
'json' ); 200 );
} else {
$response = new Response( $jsonResponse ); return $this->json( [
$response->headers->set( 'Content-Type', 'application/json' ); 'message' => 'le token d\'autorisation est invalide, vous ne pouvez pas modifier ce sondage',
$response->setStatusCode( 200 ); ],
403 );
return $response;
}
/**
* @Delete(
* path = "/poll/{id}/votes/{accessToken}",
* name = "poll_votes_delete",
* requirements = {"accessToken"="\w+", "poll_id"="\d+"}
* )
* @return JsonResponse
*/
public
function deletePollVotesAction(
Poll $poll,
$accessToken
) {
if ( $accessToken == $poll->getAdminKey() ) {
$em = $this->getDoctrine()->getManager();
$length = count( $poll->getVotes() );
$em->remove( $poll->getVotes() );
$em->flush();
return $this->json( [
'message' => 'boom! les ' . $length . ' votes du sondage ont été supprimés',
],
200 );
} else {
return $this->json( [
'message' => 'le token d\'autorisation est invalide, vous ne pouvez pas modifier ce sondage',
],
403 );
}
} }
} }
}

View File

@ -316,6 +316,19 @@
'id' => $choice_id, 'id' => $choice_id,
'url' => $choice_url, 'url' => $choice_url,
'name' => $vote->getChoice()->getName(), 'name' => $vote->getChoice()->getName(),
'score' => 0,
'yes' => [
'count' => 0,
'people' => [],
],
'maybe' => [
'count' => 0,
'people' => [],
],
'no' => [
'count' => 0,
'people' => [],
],
]; ];
} }

View File

@ -67,15 +67,7 @@ class StackOfVotes {
'created_at' => $this->getCreatedAtAsString(), 'created_at' => $this->getCreatedAtAsString(),
'votes' => [], 'votes' => [],
]; ];
// prefill votes with all choices ids foreach ( $this->getVotes() as $vote ) {
// foreach ( $this->getPoll()->getChoices() as $choice ) {
// $tab[ 'votes' ][ $choice->getId() ] = [
// 'choice_id' => $choice->getId(),
// 'value' => null,
// ];
// }
foreach ( $votes as $vote ) {
$tab[ 'votes' ][ $vote->getChoice()->getId() ] = $vote->display(); $tab[ 'votes' ][ $vote->getChoice()->getId() ] = $vote->display();
} }