Skip to content

Commit

Permalink
chore: Bumped
Browse files Browse the repository at this point in the history
  • Loading branch information
roadiz-ci committed Jun 21, 2024
1 parent 5eb9968 commit 006143a
Show file tree
Hide file tree
Showing 41 changed files with 990 additions and 760 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 19,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: ['8.1', '8.2', '8.3']
php-version: ['8.0', '8.1']
steps:
- uses: shivammathur/setup-php@v2
with:
Expand Down
14 changes: 14 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 1,14 @@
language: php
php:
- '8.0'
- '8.1'
- 'nightly'
jobs:
allow_failures:
- php: 'nightly'
install:
- composer install --dev --no-scripts --no-suggest

script:
- vendor/bin/phpcs -p ./src
- vendor/bin/phpstan analyse -c phpstan.neon
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
The MIT License (MIT)

Copyright © 2024 Ambroise Maupate
Copyright © 2023 Ambroise Maupate

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 82,9 @@ framework:
security:
access_control:
# Append user routes configuration
- { path: "^/api/users/signup", methods: [ POST ], roles: PUBLIC_ACCESS }
- { path: "^/api/users/password_request", methods: [ POST ], roles: PUBLIC_ACCESS }
- { path: "^/api/users/password_reset", methods: [ PUT ], roles: PUBLIC_ACCESS }
- { path: "^/api/users/signup", methods: [ POST ], roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: "^/api/users/password_request", methods: [ POST ], roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: "^/api/users/password_reset", methods: [ PUT ], roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: "^/api/users", methods: [ GET, PUT, PATCH, POST ], roles: ROLE_USER }
```
- Edit your `./.env` file with:
Expand Down
26 changes: 9 additions & 17 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,11 1,9 @@
{
"name": "roadiz/user-bundle",
"description": "Public user management bundle for Roadiz CMS",
"license": "MIT",
"keywords": [
"cms",
"backoffice",
"roadiz",
"rezo zero"
],
"authors": [
Expand All @@ -18,25 16,19 @@
],
"type": "symfony-bundle",
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=8.1",
"api-platform/core": "~3.2.14",
"roadiz/core-bundle": "2.3.*",
"symfony/framework-bundle": "6.4.*",
"symfony/rate-limiter": "6.4.*",
"symfony/lock": "6.4.*",
"doctrine/orm": "~2.19.0"
"php": ">=8.0",
"api-platform/core": "~2.7.0",
"symfony/framework-bundle": "5.4.*",
"symfony/rate-limiter": "5.4.*",
"doctrine/orm": "<2.17"
},
"require-dev": {
"roadiz/core-bundle": "2.1.*",
"php-coveralls/php-coveralls": "^2.4",
"phpstan/phpstan": "^1.5.3",
"squizlabs/php_codesniffer": "^3.5",
"phpstan/phpstan-doctrine": "^1.3",
"roadiz/entity-generator": "2.3.*",
"roadiz/doc-generator": "2.3.*",
"roadiz/random": "2.3.*",
"roadiz/jwt": "2.3.*"
"phpstan/phpstan-doctrine": "^1.3"
},
"config": {
"optimize-autoloader": true,
Expand All @@ -58,8 50,8 @@
},
"extra": {
"branch-alias": {
"dev-main": "2.3.x-dev",
"dev-develop": "2.4.x-dev"
"dev-main": "2.1.x-dev",
"dev-develop": "2.2.x-dev"
}
}
}
124 changes: 56 additions & 68 deletions config/api_resources/user.yaml
Original file line number Diff line number Diff line change
@@ -1,117 1,105 @@
---
RZ\Roadiz\CoreBundle\Entity\User:
operations:
api_user_signup:
class: ApiPlatform\Metadata\Post
iri: User
shortName: User
attributes:
cache_headers:
public: false
max_age: 0
collectionOperations:
signup:
method: 'POST'
uriTemplate: '/users/signup'
processor: RZ\Roadiz\UserBundle\State\UserSignupProcessor
path: '/users/signup'
controller: RZ\Roadiz\UserBundle\Controller\SignupController
input: RZ\Roadiz\UserBundle\Api\Dto\UserInput
output: RZ\Roadiz\UserBundle\Api\Dto\VoidOutput
validation_groups:
- no_empty_password
openapiContext:
openapi_context:
summary: Create a new public user
parameters:
- in: header
name: x-g-recaptcha-response
schema:
type: string
required: true
- in: header
name: x-g-recaptcha-response
schema:
type: string
required: true
description: |
Create a new public user. User won't be validated and will not be granted with any role.
This operation may require a *Google Recaptcha* response to protect against flooding.
api_user_password_request:
class: ApiPlatform\Metadata\Post
password_request:
method: 'POST'
uriTemplate: '/users/password_request'
processor: RZ\Roadiz\UserBundle\State\UserPasswordRequestProcessor
path: '/users/password_request'
controller: RZ\Roadiz\UserBundle\Controller\PasswordRequestController
input: RZ\Roadiz\UserBundle\Api\Dto\UserPasswordRequestInput
output: RZ\Roadiz\UserBundle\Api\Dto\VoidOutput
openapiContext:
# Password request must not call WriteListener to let PasswordRequestController persist changes.
write: false
validate: false
openapi_context:
summary: Request a public user new password
parameters:
- in: header
name: x-g-recaptcha-response
schema:
type: string
required: true
- in: header
name: x-g-recaptcha-response
schema:
type: string
required: true
description: |
Initiate a public user new password request (forgot my password). This operation may
require a *Google Recaptcha* response to protect against flooding.
api_user_validation_request:
class: ApiPlatform\Metadata\Post
validation_request:
method: 'POST'
uriTemplate: '/users/validation_request'
processor: RZ\Roadiz\UserBundle\State\UserValidationRequestProcessor
path: '/users/validation_request'
controller: RZ\Roadiz\UserBundle\Controller\ValidationRequestController
input: RZ\Roadiz\UserBundle\Api\Dto\UserValidationRequestInput
output: RZ\Roadiz\UserBundle\Api\Dto\VoidOutput
openapiContext:
# Validation request must not call WriteListener to let ValidationRequestController persist changes.
write: false
validate: false
openapi_context:
summary: Request a public user email validation token
description: |
Initiate a public user validation request (to verify user email address)
api_user_password_reset:
itemOperations:
information:
method: 'GET'
read: false
path: '/users/me'
controller: RZ\Roadiz\UserBundle\Controller\InformationController
output: RZ\Roadiz\UserBundle\Api\Dto\UserOutput
openapi_context:
summary: Get current user (JWT) information
description: |
Get current user (JWT) information
password_reset:
method: 'PUT'
class: ApiPlatform\Metadata\Put
uriTemplate: '/users/password_reset'
processor: RZ\Roadiz\UserBundle\State\UserPasswordResetProcessor
path: '/users/password_reset'
controller: RZ\Roadiz\UserBundle\Controller\PasswordResetController
input: RZ\Roadiz\UserBundle\Api\Dto\UserPasswordTokenInput
output: RZ\Roadiz\UserBundle\Api\Dto\VoidOutput
# Password reset must not call ReadListener to let DataTransformer provide User.
read: false
validate: false
validation_groups:
- no_empty_password
openapiContext:
openapi_context:
summary: Reset a public user password
parameters: ~
description: |
Change a public user password against a unique temporary token (forgot my password)
api_user_validate:
class: ApiPlatform\Metadata\Put
validate:
method: 'PUT'
uriTemplate: '/users/validate'
processor: RZ\Roadiz\UserBundle\State\UserValidationTokenProcessor
input: RZ\Roadiz\UserBundle\Api\Dto\UserValidationTokenInput
path: '/users/validate'
controller: RZ\Roadiz\UserBundle\Controller\ValidateController
input: RZ\Roadiz\UserBundle\Api\Dto\UserTokenInput
output: RZ\Roadiz\UserBundle\Api\Dto\VoidOutput
read: false
validate: false
openapiContext:
openapi_context:
summary: Validate a public user email
description: |
Validate a public user email with a unique and temporary token
ApiPlatform\Metadata\Get:
method: 'GET'
security: "is_granted('ROLE_ACCESS_USERS') or object == user"
normalizationContext:
groups: ['user', 'user_personal', 'user_security']
enable_max_depth: true

ApiPlatform\Metadata\GetCollection:
method: 'GET'
security: "is_granted('ROLE_ACCESS_USERS')"
normalizationContext:
groups: [ 'user', 'user_personal' ]
enable_max_depth: true

# Current user information operation MUST be declared AFTER ApiPlatform\Metadata\Get
# to avoid conflict with IRI generation.
api_user_information:
method: 'GET'
class: ApiPlatform\Metadata\Get
# Path must be different from item operation to avoid conflict
uriTemplate: '/me'
provider: RZ\Roadiz\UserBundle\State\UserTokenProvider
output: RZ\Roadiz\UserBundle\Api\Dto\UserOutput
normalizationContext:
groups: ['user', 'user_personal', 'user_security']
enable_max_depth: true
openapiContext:
summary: Get current user (JWT) information
description: |
Get current user (JWT) information
8 changes: 4 additions & 4 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 2,7 @@
parameters:
env(USER_PASSWORD_RESET_URL): 'loginResetPage'
env(USER_VALIDATION_URL): 'http://example.test/my-account/validate'
env(USER_PASSWORD_RESET_EXPIRES_IN): '900'
env(USER_PASSWORD_RESET_EXPIRES_IN): '600'
env(USER_VALIDATION_EXPIRES_IN): '3600'

services:
Expand All @@ -17,7 17,6 @@ services:
$userValidationExpiresIn: '%roadiz_user.user_validation_expires_in%'
$publicUserRoleName: '%roadiz_user.public_user_role_name%'
$emailValidatedRoleName: '%roadiz_user.email_validated_role_name%'
$persistProcessor: '@api_platform.doctrine.orm.state.persist_processor'

RZ\Roadiz\UserBundle\:
resource: '../src/'
Expand All @@ -27,5 26,6 @@ services:
- '../src/Tests/'
- '../src/Event/'

RZ\Roadiz\UserBundle\State\UserSignupProcessor:
tags: [ 'api_platform.state_processor' ]
RZ\Roadiz\UserBundle\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
8 changes: 3 additions & 5 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,14 1,12 @@
parameters:
level: 7
level: 5
paths:
- src
excludePaths:
- */node_modules/*
- */bower_components/*
- */static/*
ignoreErrors:
- identifier: missingType.iterableValue
- identifier: missingType.generics
- '#Call to an undefined method RZ\\Roadiz\\CoreBundle\\Repository#'
- '#Call to an undefined method RZ\\Roadiz\\UserBundle\\Repository#'
- '#Call to an undefined method Doctrine\\Persistence\\ObjectRepository#'
Expand All @@ -28,10 26,10 @@ parameters:
- '#Doctrine\\ORM\\Mapping\\GeneratedValue constructor expects#'
- '#type mapping mismatch: property can contain Doctrine\\Common\\Collections\\Collection<int, [^\>] > but database expects Doctrine\\Common\\Collections\\Collection&iterable<[^\>] >#'
- '#should return Doctrine\\Common\\Collections\\Collection<int, [^\>] Interface> but returns Doctrine\\Common\\Collections\\Collection<int, [^\>] >#'
- '#but returns Doctrine\\Common\\Collections\\ReadableCollection<int, [^\>] >#'
- '#does not accept Doctrine\\Common\\Collections\\ReadableCollection<int, [^\>] >#'

reportUnmatchedIgnoredErrors: false
checkGenericClassInNonGenericObjectType: false
checkMissingIterableValueType: false
doctrine:
repositoryClass: RZ\Roadiz\CoreBundle\Repository\EntityRepository
includes:
Expand Down
63 changes: 63 additions & 0 deletions src/Api/DataTransformer/UserInputDataTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 1,63 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\UserBundle\Api\DataTransformer;

use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
use RZ\Roadiz\CoreBundle\Bag\Roles;
use RZ\Roadiz\CoreBundle\Entity\User;
use RZ\Roadiz\UserBundle\Api\Dto\UserInput;
use RZ\Roadiz\UserBundle\Manager\UserMetadataManagerInterface;
use Symfony\Component\Security\Core\User\UserInterface;

final class UserInputDataTransformer implements DataTransformerInterface
{
private UserMetadataManagerInterface $userMetadataManager;
private Roles $rolesBag;
private string $publicUserRoleName;

public function __construct(UserMetadataManagerInterface $userMetadataManager, Roles $rolesBag, string $publicUserRoleName)
{
$this->rolesBag = $rolesBag;
$this->publicUserRoleName = $publicUserRoleName;
$this->userMetadataManager = $userMetadataManager;
}

public function transform($object, string $to, array $context = []): User
{
if (!$object instanceof UserInput) {
throw new \RuntimeException(sprintf('Cannot transform %s to %s', get_class($object), $to));
}

$user = new User();
$user->setEmail($object->email);
$user->setUsername($object->email);
$user->setFirstName($object->firstName);
$user->setPublicName($object->publicName);
$user->setLastName($object->lastName);
$user->setPhone($object->phone);
$user->setCompany($object->company);
$user->setJob($object->job);
$user->setBirthday($object->birthday);
$user->setPlainPassword($object->plainPassword);
$user->addRoleEntity($this->rolesBag->get($this->publicUserRoleName));
$user->sendCreationConfirmationEmail(true);

if (null !== $object->metadata) {
$userMetadata = $this->userMetadataManager->createMetadataForUser($user);
$userMetadata->setMetadata($object->metadata);
}

return $user;
}

public function supportsTransformation($data, string $to, array $context = []): bool
{
if ($data instanceof UserInterface) {
return false;
}

return User::class === $to && UserInput::class === ($context['input']['class'] ?? null);
}
}
Loading

0 comments on commit 006143a

Please sign in to comment.