Skip to content

Commit

Permalink
Merge pull request #34 from GoteoFoundation/feat/user_info_endpoint
Browse files Browse the repository at this point in the history
FEAT: Update /userInfo endpoint
  • Loading branch information
davidbeig authored May 17, 2024
2 parents 87eadac + 378d46a commit 42e9303
Show file tree
Hide file tree
Showing 21 changed files with 1,596 additions and 1,327 deletions.
7 changes: 7 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
###< doctrine/doctrine-bundle ###

#BASE_AVATAR_URL=https://ca.goteo.org/img/100x100c/

###> league/oauth2-server-bundle ###
OAUTH_PRIVATE_KEY=%kernel.project_dir%/config/jwt/private.pem
OAUTH_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
OAUTH_PASSPHRASE=5350dadf2987e9830cb8cf24114577fe
OAUTH_ENCRYPTION_KEY=80c1a79c6c22c87711fde0b515de0c06
###< league/oauth2-server-bundle ###
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ public.key
.phpunit.result.cache
/phpunit.xml
###< symfony/phpunit-bridge ###

###> league/oauth2-server-bundle ###
/config/jwt/*.pem
###< league/oauth2-server-bundle ###
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Run all these commands under the Docker service. E.g.: `docker exec goteo-oauth_
- Type: OAuth 2.0
- Token name: Any name
- Grant type: Use "Client Credentials"
- Access Token URL: "http://127.0.0.1:52000/token"
- Access Token URL: "http://127.0.0.1:52000/{locale}/token" (Replace `{locale}` with an actual locale string).
- Client ID: The one you've just obtained in step 1
- Client secret: The one you've just obtained in step 1
- Scope: Use "TEST", or any that's in `config/packages/league_oauth2_server.yaml` at the `league_oauth2_server.scopes.available` entry
Expand All @@ -81,7 +81,7 @@ Create a new OAuth2 client:

At step 2, do the following:
- Grant type: "Password Credentials"
- Username: the user's email
- Username: the user's username (id) or email
- Password : Type the user's password

## Test OAuth2 "authorization_code" grant (Postman):
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"doctrine/doctrine-bundle": "^2.5",
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.11",
"league/oauth2-server-bundle": "^0.3.0",
"league/oauth2-server-bundle": "^0.5.0",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.2",
"rych/phpass": "3.0.*@beta",
Expand Down
2,353 changes: 1,167 additions & 1,186 deletions composer.lock

Large diffs are not rendered by default.

91 changes: 16 additions & 75 deletions config/packages/league_oauth2_server.yaml
Original file line number Diff line number Diff line change
@@ -1,76 +1,17 @@
league_oauth2_server:
authorization_server: # Required

# Full path to the private key file.
# How to generate a private key: https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys
private_key: '%env(OAUTH2_PRIVATE_KEY_PATH)%' # Required, Example: /var/oauth/private.key

# Passphrase of the private key, if any
private_key_passphrase: null

# The plain string or the ascii safe string used to create a Defuse\Crypto\Key to be used as an encryption key.
# How to generate an encryption key: https://oauth2.thephpleague.com/installation/#string-password
encryption_key: '%env(OAUTH2_ENCRYPTION_KEY)%' # Required

# The type of value of 'encryption_key'
encryption_key_type: plain # One of "plain"; "defuse"

# How long the issued access token should be valid for.
# The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters
access_token_ttl: PT1H

# How long the issued refresh token should be valid for.
# The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters
refresh_token_ttl: P1M

# How long the issued auth code should be valid for.
# The value should be a valid interval: http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters
auth_code_ttl: PT10M

# Whether to enable the client credentials grant
enable_client_credentials_grant: true

# Whether to enable the password grant
enable_password_grant: true

# Whether to enable the refresh token grant
enable_refresh_token_grant: true

# Whether to enable the authorization code grant
enable_auth_code_grant: true

# Whether to require code challenge for public clients for the auth code grant
require_code_challenge_for_public_clients: true

# Whether to enable access token saving to persistence layer (default to true)
persist_access_token: true

resource_server: # Required

# Full path to the public key file
# How to generate a public key: https://oauth2.thephpleague.com/installation/#generating-public-and-private-keys
public_key: '%env(OAUTH2_PUBLIC_KEY_PATH)%' # Required, Example: /var/oauth/public.key

scopes:
# Scopes that you wish to utilize in your application.
# This should be a simple array of strings.
available: [TEST]

# Scopes that will be assigned when no scope given.
# This should be a simple array of strings.
default: [TEST]

# Configures different persistence methods that can be used by the bundle for saving client and token data.
# Only one persistence method can be configured at a time.
persistence: # Required
doctrine:
# Name of the entity manager that you wish to use for managing clients and tokens.
entity_manager: default
# in_memory: ~

# Set a custom prefix that replaces the default 'ROLE_OAUTH2_' role prefix
role_prefix: ROLE_OAUTH2_

client:
# Set a custom client class. Must be a League\Bundle\OAuth2ServerBundle\Model\Client
classname: League\Bundle\OAuth2ServerBundle\Model\Client
authorization_server:
private_key: '%env(resolve:OAUTH_PRIVATE_KEY)%'
private_key_passphrase: '%env(resolve:OAUTH_PASSPHRASE)%'
encryption_key: '%env(resolve:OAUTH_ENCRYPTION_KEY)%'
resource_server:
public_key: '%env(resolve:OAUTH_PUBLIC_KEY)%'
scopes:
available: ['email']
default: ['email']
persistence:
doctrine: null

when@test:
league_oauth2_server:
persistence:
in_memory: null
10 changes: 0 additions & 10 deletions config/packages/nyholm_psr7.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,5 @@ services:
Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory'
Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory'

# Register nyholm/psr7 services for autowiring with HTTPlug factories
Http\Message\MessageFactory: '@nyholm.psr7.httplug_factory'
Http\Message\RequestFactory: '@nyholm.psr7.httplug_factory'
Http\Message\ResponseFactory: '@nyholm.psr7.httplug_factory'
Http\Message\StreamFactory: '@nyholm.psr7.httplug_factory'
Http\Message\UriFactory: '@nyholm.psr7.httplug_factory'

nyholm.psr7.psr17_factory:
class: Nyholm\Psr7\Factory\Psr17Factory

nyholm.psr7.httplug_factory:
class: Nyholm\Psr7\Factory\HttplugFactory
2 changes: 1 addition & 1 deletion config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ security:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/(userInfo|userApiToken)
pattern: ^/(userInfo|userApiToken|userInvests|userInvestedToReward|userActiveInvestedToReward)
security: true
stateless: true
oauth2: true
Expand Down
3 changes: 3 additions & 0 deletions config/routes/league_oauth2_server.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
oauth2_server:
resource: '@LeagueOAuth2ServerBundle/Resources/config/routes.php'
type: php
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 35 additions & 9 deletions src/Controller/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,24 @@

namespace App\Controller;

use App\UseCase\GetUserActiveInvestedRewardUseCase;
use App\UseCase\GetUserApiTokenUseCase;
use App\UseCase\GetUserInfoUseCase;
use App\UseCase\GetUserInvestsUseCase;
use App\UseCase\GetUserInvestedToRewardUseCase;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class HomeController extends AbstractController
{

#[Route('/')]
public function indexNoLocale(Request $request): Response
{
return $this->redirectToRoute('home', ['_locale' => $request->getLocale()]);
}

#[Route('/{_locale}', name: 'home')]
public function index(): Response
{
return $this->render('home/index.html.twig', [
'controller_name' => 'HomeController',
]);
}

#[Route('/userInfo', name: 'userInfo')]
public function userInfo(GetUserInfoUseCase $useCase): Response
{
Expand All @@ -52,4 +46,36 @@ public function userApiToken(GetUserApiTokenUseCase $useCase): Response

return $this->json($response);
}

#[Route('/userInvests', name: 'userInvests')]
public function userInvests(GetUserInvestsUseCase $useCase): Response
{
$response = $useCase->execute($this->getUser()->getUserIdentifier());

return $this->json($response);
}

#[Route('/userInvestedToReward/{reward_id}', name: 'userInvestedToReward')]
public function userInvestedToReward(Request $request, int $reward_id, GetUserInvestedToRewardUseCase $useCase): Response
{
$response = $useCase->execute($reward_id, $this->getUser()->getUserIdentifier());

return $this->json($response);
}

#[Route('/userActiveInvestedToReward/{reward_id}', name: 'userInvestedToReward')]
public function userActiveInvestInReward(int $reward_id, GetUserActiveInvestedRewardUseCase $useCase): Response
{
$response = $useCase->execute($reward_id, $this->getUser()->getUserIdentifier());

return $this->json($response);
}

#[Route('/{_locale}', name: 'home')]
public function index(): Response
{
return $this->render('home/index.html.twig', [
'controller_name' => 'HomeController',
]);
}
}
81 changes: 81 additions & 0 deletions src/Entity/Invest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

namespace App\Entity;

use App\Repository\InvestRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: InvestRepository::class)]
class Invest
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;

#[ORM\Column(name: 'user', type: 'string', length: 50)]
private ?string $userId = null;

#[ORM\Column]
private ?int $amount = null;

#[ORM\Column]
private ?int $status = null;

#[ORM\Column(type: Types::DATE_MUTABLE)]
private ?\DateTimeInterface $invested = null;

public function getId(): ?int
{
return $this->id;
}

public function getUserId(): ?string
{
return $this->userId;
}

public function setUserId(?string $userId): static
{
$this->userId = $userId;

return $this;
}

public function getAmount(): ?int
{
return $this->amount;
}

public function setAmount(int $amount): static
{
$this->amount = $amount;

return $this;
}

public function getStatus(): ?int
{
return $this->status;
}

public function setStatus(int $status): static
{
$this->status = $status;

return $this;
}

public function getInvested(): ?\DateTimeInterface
{
return $this->invested;
}

public function setInvested(\DateTimeInterface $invested): static
{
$this->invested = $invested;

return $this;
}
}
50 changes: 50 additions & 0 deletions src/Entity/InvestReward.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Entity;

use App\Repository\InvestRewardRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: InvestRewardRepository::class)]
class InvestReward
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;

#[ORM\Column()]
private ?int $invest = null;

#[ORM\Column()]
private ?int $reward = null;

public function getId(): ?int
{
return $this->id;
}

public function getInvest(): ?int
{
return $this->invest;
}

public function setInvest(int $invest): static
{
$this->invest = $invest;

return $this;
}

public function getReward(): ?int
{
return $this->reward;
}

public function setReward(int $reward): static
{
$this->reward = $reward;

return $this;
}
}
4 changes: 2 additions & 2 deletions src/EventListener/UserResolveListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public function __construct(UserRepository $userRepository, PasswordValidatorSer

public function onUserResolve(UserResolveEvent $event): void
{
$user = $this->userRepository->findOneBy(['email' => $event->getUsername()]);
$user = $this->userRepository->findOneByIdentifier($event->getUsername());

if ($user && $this->passwordValidator->isPasswordValid($user->getPassword(), $event->getPassword())) {
$event->setUser($user);
}
}
}
}
Loading

0 comments on commit 42e9303

Please sign in to comment.