Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
83 changes: 83 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: CI

on:
pull_request:
push:
branches: [ main, develop ]

jobs:
run:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php:
- '8.3'
- '8.4'
coverage: ['none']
doctrine-orm-versions:
- '^2.17'
- '^3.0'
symfony-versions:
- '6.4.*'
- '7.0.*'
include:
- description: 'Log Code Coverage'
php: '8.3'
symfony-versions: '^7.0'
doctrine-orm-versions: '^3.0'
coverage: xdebug

name: PHP ${{ matrix.php }} Symfony ${{ matrix.symfony-versions }} Doctrine ${{ matrix.doctrine-orm-versions }} ${{ matrix.description }}
steps:
- name: Checkout
uses: actions/checkout@v4

- uses: actions/cache@v4
with:
path: ~/.composer/cache/files
key: ${{ matrix.php }}-${{ matrix.symfony-versions }}

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: xdebug

- name: Add PHPUnit matcher
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

- name: Set composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache composer
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.symfony-versions }}-composer-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.symfony-versions }}-composer

- name: Update Symfony version
if: matrix.symfony-versions != ''
run: |
composer require symfony/framework-bundle:${{ matrix.symfony-versions }} --no-update --no-scripts
composer require doctrine/orm:${{ matrix.doctrine-orm-versions }} --no-update --no-scripts
composer require --dev symfony/yaml:${{ matrix.symfony-versions }} --no-update --no-scripts

- name: Install dependencies
run: composer install

- name: Run PHPUnit tests
run: vendor/bin/phpunit
if: matrix.coverage == 'none'

- name: PHPUnit tests and Log Code coverage
run: vendor/bin/phpunit --coverage-clover=coverage.xml
if: matrix.coverage == 'xdebug'

- name: Upload coverage reports to Codecov
if: matrix.coverage == 'xdebug'
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}
24 changes: 24 additions & 0 deletions .github/workflows/security.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
on:
pull_request:
push:
branches: [ main, develop ]

jobs:
security-checker:
name: Security checker
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2

- name: Install dependencies
run: composer install --no-progress --no-interaction --prefer-dist

- name: Download local-php-security-checker
run: curl -s -L -o local-php-security-checker https://github.com/fabpot/local-php-security-checker/releases/download/v1.0.0/local-php-security-checker_1.0.0_linux_amd64

- name: Run local-php-security-checker
run: chmod +x local-php-security-checker && ./local-php-security-checker
55 changes: 55 additions & 0 deletions .github/workflows/static-analysis.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Code style and static analysis

on:
pull_request:
push:
branches: [ main, develop ]

jobs:
php-cs-fixer:
name: PHP-CS-Fixer
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2

- name: Install dependencies
run: composer install --no-progress --no-interaction --prefer-dist

- name: Run script
run: vendor/bin/phpcs

phpstan:
name: PHPStan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2

- name: Install dependencies
run: composer install --no-progress --no-interaction --prefer-dist

- name: Run script
run: vendor/bin/phpstan analyse

composer-validate:
name: Composer validate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2

- name: Install dependencies
run: composer install --no-progress --no-interaction --prefer-dist

- name: Run script
run: composer composer-validate
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.idea
/vendor/
/composer.lock
/.phpcs-cache

###> phpunit/phpunit ###
/phpunit.xml
.phpunit.result.cache
###< phpunit/phpunit ###
73 changes: 71 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,71 @@
# postgres-schema-bundle
Postgres schema bundle
# Postgres Schema Bundle
The **Postgres Schema Bundle** provides seamless multi-tenant schema support for PostgreSQL within Symfony applications. It automatically switches PostgreSQL `search_path` based on the current request context and ensures proper schema resolution across Doctrine and Messenger.## Installation

## Features

- Automatically sets PostgreSQL `search_path` from request headers.
- Validates that the schema exists in the database.
- Works only if the configured database driver is PostgreSQL.
- Integrates with [Schema Context Bundle](https://github.com/macpaw/schema-context-bundle).
- Compatible with Symfony Messenger and Doctrine ORM.

## Installation
Use Composer to install the bundle:
```
composer require macpaw/postgres-schema-bundle
```

### Applications that don't use Symfony Flex
Enable the bundle by adding it to the list of registered bundles in ```config/bundles.php```

```
// config/bundles.php
<?php

return [
Macpaw\SchemaContextBundle\SchemaContextBundle::class => ['all' => true],
Macpaw\SchemaContextBundle\PostgresSchemaBundle::class => ['all' => true],
// ...
];
```

## Configuration

You must tell Doctrine to use the SchemaConnection class as its DBAL connection class:

```yaml
# config/packages/doctrine.yaml
doctrine:
dbal:
connections:
default:
wrapper_class: Macpaw\PostgresSchemaBundle\Doctrine\SchemaConnection
```
Make sure you configure the context bundle properly:

See https://github.com/MacPaw/schema-context-bundle/blob/develop/README.md

```yaml
schema_context:
app_name: '%env(APP_NAME)%' # Application name
header_name: 'X-Tenant' # Request header to extract schema name
default_schema: 'public' # Default schema to fallback to
allowed_app_names: ['develop', 'staging', 'test'] # App names where schema context is allowed to change
```

## How it Works
* A request comes in with a header like X-Tenant-Id: tenant123.
* The SchemaRequestListener sets this schema in the context.
* When Doctrine connects to PostgreSQL, it sets the search_path to the specified schema.
* If the schema does not exist or DB is not PostgreSQL, an exception is thrown.

## Testing
To run tests:
```bash
vendor/bin/phpunit
```
## Contributing
Feel free to open issues and submit pull requests.

## License
This bundle is released under the MIT license.
23 changes: 23 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Security Policy

## Reporting Security Issues
If you believe you have found a security vulnerability in any MacPaw-owned repository, please report it to us through coordinated disclosure.

Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.

Instead, please send an email to security[@]macpaw.com.

Please include as much of the information listed below as you can to help us better understand and resolve the issue:

- The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue

This information will help us triage your report more quickly.

## Policy
See MacPaw's [Vulnerability Disclosure Policy](https://macpaw.com/vulnerability-disclosure-policy)
50 changes: 50 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "macpaw/postgres-schema-bundle",
"description": "A Symfony bundle to add schema wrapper for postgres",
"type": "symfony-bundle",
"license": "MIT",
"autoload": {
"psr-4": {
"Macpaw\\PostgresSchemaBundle\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Macpaw\\PostgresSchemaBundle\\Tests\\": "tests/"
}
},
"require": {
"php": ">=8.3",
"doctrine/orm": "^2.17 || ^3.0",
"symfony/doctrine-bridge": "^6.4 || ^7.0",
"doctrine/dbal": "^3.4",
"macpaw/schema-context-bundle": "^1.0"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.0",
"squizlabs/php_codesniffer": "3.7.*"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"scripts": {
"composer-validate": [
"composer validate"
],
"cs": [
"vendor/bin/phpcs"
],
"cs-fix": [
"vendor/bin/phpcbf"
],
"phpstan": [
"vendor/bin/phpstan analyse"
],
"phpunit": [
"vendor/bin/phpunit"
]
}
}
41 changes: 41 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">

<arg name="basepath" value="."/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<arg value="p"/>
<arg name="extensions" value="php"/>
<arg name="tab-width" value="4"/>
<arg name="report-width" value="120"/>

<rule ref="PSR12" />

<file>src/</file>
<file>tests/</file>

<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
<rule ref="Generic.PHP.RequireStrictTypes"/>
<rule ref="Squiz.Arrays.ArrayBracketSpacing"/>
<rule ref="Generic.Arrays.DisallowLongArraySyntax.Found"></rule>
<rule ref="Squiz.Commenting.FunctionComment.SpacingAfterParamType"></rule>

<rule ref="Generic.PHP.ForbiddenFunctions">
<properties>
<property name="forbiddenFunctions" type="array" value="eval=>NULL,dd=>NULL,die=>NULL,var_dump=>NULL,dump=>NULL,sizeof=>count,delete=>unset,print=>echo,echo=>NULL,print_r=>NULL,create_function=>NULL"/>
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.FunctionSpacing">
<properties>
<property name="spacing" value="1" />
<property name="spacingBeforeFirst" value="0" />
<property name="spacingAfterLast" value="0" />
</properties>
</rule>
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
<properties>
<property name="ignoreBlankLines" value="false" />
</properties>
</rule>
</ruleset>
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
level: max
paths:
- src
23 changes: 23 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
colors="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
>
<testsuites>
<testsuite name="Symfony Messenger Bundle Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<coverage>
<report>
<clover outputFile="clover.xml"/>
</report>
</coverage>
<source>
<include>
<directory>./src</directory>
</include>
</source>
</phpunit>
Loading
Loading