From c41c68d93364949be0695957ee345698f12dfd00 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 10:15:06 -0300 Subject: [PATCH 1/9] =?UTF-8?q?refatoracao:=20separadas=20variaveis=20de?= =?UTF-8?q?=20ambiente=20por=20ambiente=20com=20prefixos=20expl=C3=ADcitos?= =?UTF-8?q?=20e=20adicionada=20diretiva=20env=5Ffile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.model | 41 ++++++++++++++++++++++++++++++----------- docker-compose.prod.yml | 12 +++++++----- docker-compose.test.yml | 22 +++++++++++++--------- docker-compose.yml | 35 +++++++++++++++++++++++------------ 4 files changed, 73 insertions(+), 37 deletions(-) diff --git a/.env.model b/.env.model index 4941ab1..b9b94ed 100755 --- a/.env.model +++ b/.env.model @@ -2,30 +2,49 @@ # Variaveis de Ambiente - Web Storage # ========================================== +DB_CONNECTION=pgsql +DB_PORT=5432 + # --- Ambiente Local de Desenvolvimento --- -DB_DATABASE=web_storage -DB_USERNAME=admin -DB_PASSWORD=secret +DEV_DB_HOST=db +DEV_DB_DATABASE=web_storage +DEV_DB_USERNAME=admin +DEV_DB_PASSWORD=secret + +DEV_POSTGRES_DB=web_storage +DEV_POSTGRES_USER=admin +DEV_POSTGRES_PASSWORD=secret # --- Ambiente de Producao --- -PROD_DB_NAME=web_storage_prod -PROD_DB_USER=admin_prod -PROD_DB_PASS=secret_prod +PROD_DB_HOST=10.0.0.110 +PROD_DB_DATABASE=web_storage_prod +PROD_DB_USERNAME=admin_prod +PROD_DB_PASSWORD=secret_prod + +PROD_POSTGRES_DB=web_storage_prod +PROD_POSTGRES_USER=admin_prod +PROD_POSTGRES_PASSWORD=secret_prod # --- Ambiente de Testes --- -TEST_DB_NAME=web_storage_test -TEST_DB_USER=test_user -TEST_DB_PASS=test_pass +TEST_DB_HOST=db_test +TEST_DB_DATABASE=web_storage_test +TEST_DB_USERNAME=test_user +TEST_DB_PASSWORD=test_pass + +TEST_POSTGRES_DB=web_storage_test +TEST_POSTGRES_USER=test_user +TEST_POSTGRES_PASSWORD=test_pass # --- Configuracoes de Armazenamento --- -STORAGE_TYPE=local # local ou oci +#STORAGE_TYPE=oci +STORAGE_TYPE=local STORAGE_ROOT=/var/www/html/storage # --- Oracle Cloud Object Storage --- OCI_USER_OCID= OCI_TENANCY_OCID= OCI_FINGERPRINT= -OCI_KEY_FILE=/var/www/html/oci_private_key.pem +OCI_KEY_FILE=/var/www/html/.oci/key.pem OCI_REGION= OCI_NAMESPACE= OCI_BUCKET= diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 48f6fcb..e64d29b 100755 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -5,13 +5,15 @@ services: dockerfile: docker/php/Dockerfile.prod container_name: web_storage_app_prod restart: unless-stopped + env_file: + - .env environment: - - DB_CONNECTION=pgsql + - DB_CONNECTION=${DB_CONNECTION:-pgsql} - DB_HOST=${PROD_DB_HOST:-10.0.0.110} - - DB_PORT=5432 - - DB_DATABASE=${WEB_STORAGE_PROD_DB_NAME:-web_storage_prod} - - DB_USERNAME=${WEB_STORAGE_PROD_DB_USER:-admin} - - DB_PASSWORD=${WEB_STORAGE_PROD_DB_PASS:-secret_prod} + - DB_PORT=${DB_PORT:-5432} + - DB_DATABASE=${PROD_DB_DATABASE:-web_storage_prod} + - DB_USERNAME=${PROD_DB_USERNAME:-admin_prod} + - DB_PASSWORD=${PROD_DB_PASSWORD:-secret_prod} volumes: - prod_storage:/var/www/html/storage networks: diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 1e5f3d1..4febfd5 100755 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -5,13 +5,15 @@ services: dockerfile: docker/php/Dockerfile.test container_name: web_storage_app_test working_dir: /var/www/html + env_file: + - .env environment: - - DB_CONNECTION=pgsql - - DB_HOST=db_test - - DB_PORT=5432 - - DB_DATABASE=${TEST_DB_NAME:-web_storage_test} - - DB_USERNAME=${TEST_DB_USER:-test_user} - - DB_PASSWORD=${TEST_DB_PASS:-test_pass} + - DB_CONNECTION=${DB_CONNECTION:-pgsql} + - DB_HOST=${TEST_DB_HOST:-db_test} + - DB_PORT=${DB_PORT:-5432} + - DB_DATABASE=${TEST_DB_DATABASE:-web_storage_test} + - DB_USERNAME=${TEST_DB_USERNAME:-test_user} + - DB_PASSWORD=${TEST_DB_PASSWORD:-test_pass} depends_on: db_test: condition: service_healthy @@ -22,10 +24,12 @@ services: image: postgres:15-alpine container_name: web_storage_db_test command: postgres -p 5432 + env_file: + - .env environment: - POSTGRES_DB: ${TEST_DB_NAME:-web_storage_test} - POSTGRES_USER: ${TEST_DB_USER:-test_user} - POSTGRES_PASSWORD: ${TEST_DB_PASS:-test_pass} + POSTGRES_DB: ${TEST_POSTGRES_DB:-web_storage_test} + POSTGRES_USER: ${TEST_POSTGRES_USER:-test_user} + POSTGRES_PASSWORD: ${TEST_POSTGRES_PASSWORD:-test_pass} networks: - test_net healthcheck: diff --git a/docker-compose.yml b/docker-compose.yml index 294d827..a9236ae 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,22 +8,25 @@ services: working_dir: /var/www/html volumes: - ./:/var/www/html + env_file: + - .env environment: - - DB_CONNECTION=pgsql - - DB_HOST=db - - DB_PORT=5432 - - DB_DATABASE=${DB_DATABASE:-web_storage} - - DB_USERNAME=${DB_USERNAME:-admin} - - DB_PASSWORD=${DB_PASSWORD:-secret} - command: /bin/bash -c "mkdir -p /var/www/html/storage && chmod -R 777 /var/www/html/storage && php-fpm" + - DB_CONNECTION=${DB_CONNECTION:-pgsql} + - DB_HOST=${DEV_DB_HOST:-db} + - DB_PORT=${DB_PORT:-5432} + - DB_DATABASE=${DEV_DB_DATABASE:-web_storage} + - DB_USERNAME=${DEV_DB_USERNAME:-admin} + - DB_PASSWORD=${DEV_DB_PASSWORD:-secret} + command: /bin/bash -c "php src/init_db.php && mkdir -p /var/www/html/storage && chmod -R 777 /var/www/html/storage && php-fpm" depends_on: - - db + db: + condition: service_healthy networks: - dev_net web: - image: nginx:alpine + image: nginx:latest container_name: web_storage_nginx restart: unless-stopped ports: @@ -40,12 +43,20 @@ services: image: postgres:15-alpine container_name: web_storage_db restart: unless-stopped + env_file: + - .env environment: - POSTGRES_DB: ${DB_DATABASE:-web_storage} - POSTGRES_USER: ${DB_USERNAME:-admin} - POSTGRES_PASSWORD: ${DB_PASSWORD:-secret} + POSTGRES_DB: ${DEV_POSTGRES_DB:-web_storage} + POSTGRES_USER: ${DEV_POSTGRES_USER:-admin} + POSTGRES_PASSWORD: ${DEV_POSTGRES_PASSWORD:-secret} volumes: - default_postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s ports: - "5432:5432" networks: From 9895e940165780652e46f3ac7b1a258b59bb637c Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 10:16:14 -0300 Subject: [PATCH 2/9] add .oci to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 65b1681..f5ec4d4 100755 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ docker/nginx/logs/* .phpunit.result.cache +.oci + # Ensure storage folder exists but ignore uploaded files /storage/* !/storage/.gitkeep From dd523a951266a311a046c32269a1e2d985e01eb9 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 10:42:02 -0300 Subject: [PATCH 3/9] fix: substitui Config legado por UserAuthProvider no SDK da OCI e oculta warnings de deprecation do PHP 8.4 no fpm para resolver quebra de sessao --- src/Config/OCIConfig.php | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Config/OCIConfig.php b/src/Config/OCIConfig.php index b4b2312..adeb4fe 100755 --- a/src/Config/OCIConfig.php +++ b/src/Config/OCIConfig.php @@ -3,20 +3,23 @@ namespace App\Config; use Oracle\Oci\ObjectStorage\ObjectStorageClient; -use Oracle\Oci\Common\Config\Config; +use Oracle\Oci\Common\Auth\UserAuthProvider; class OCIConfig { public static function createClient(): ObjectStorageClient { - // Load from environment or home config - $config = new Config([ - 'user' => getenv('OCI_USER_OCID'), - 'tenancy' => getenv('OCI_TENANCY_OCID'), - 'fingerprint' => getenv('OCI_FINGERPRINT'), - 'key_file' => getenv('OCI_KEY_FILE'), - 'region' => getenv('OCI_REGION') - ]); + $keyFile = getenv('OCI_KEY_FILE'); + if (strpos($keyFile, 'file://') !== 0) { + $keyFile = 'file://' . $keyFile; + } - return new ObjectStorageClient($config); + $authProvider = new UserAuthProvider( + getenv('OCI_TENANCY_OCID'), + getenv('OCI_USER_OCID'), + getenv('OCI_FINGERPRINT'), + $keyFile + ); + + return new ObjectStorageClient($authProvider, getenv('OCI_REGION')); } public static function getNamespace(): string { From 654cba23831cd6a74f3bc3cfdce3582b3dbe3a62 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 10:49:41 -0300 Subject: [PATCH 4/9] =?UTF-8?q?fix(php):=20adiciona=20~E=5FUSER=5FDEPRECAT?= =?UTF-8?q?ED=20ao=20error=5Freporting=20filter=20para=20evitar=20quebra?= =?UTF-8?q?=20silenciosa=20de=20sess=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/php/Dockerfile.dev | 5 +++-- docker/php/Dockerfile.prod | 5 +++-- docker/php/Dockerfile.test | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docker/php/Dockerfile.dev b/docker/php/Dockerfile.dev index 91e6185..2fbb8ef 100755 --- a/docker/php/Dockerfile.dev +++ b/docker/php/Dockerfile.dev @@ -22,9 +22,10 @@ RUN pecl install xdebug \ RUN echo "xdebug.mode=coverage,debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ && echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini -# Configure PHP Upload Limits +# Configure PHP Upload Limits and Error Reporting RUN echo "upload_max_filesize = 100M" > /usr/local/etc/php/conf.d/uploads.ini \ - && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/uploads.ini + && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/uploads.ini \ + && echo "error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED" > /usr/local/etc/php/conf.d/error_reporting.ini # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer diff --git a/docker/php/Dockerfile.prod b/docker/php/Dockerfile.prod index 31a9a45..feedf15 100755 --- a/docker/php/Dockerfile.prod +++ b/docker/php/Dockerfile.prod @@ -18,9 +18,10 @@ RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache-recommended.ini && echo "opcache.revalidate_freq=2" >> /usr/local/etc/php/conf.d/opcache-recommended.ini \ && echo "opcache.fast_shutdown=1" >> /usr/local/etc/php/conf.d/opcache-recommended.ini -# Configure PHP Upload Limits +# Configure PHP Upload Limits and Error Reporting RUN echo "upload_max_filesize = 100M" > /usr/local/etc/php/conf.d/uploads.ini \ - && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/uploads.ini + && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/uploads.ini \ + && echo "error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED" > /usr/local/etc/php/conf.d/error_reporting.ini # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer diff --git a/docker/php/Dockerfile.test b/docker/php/Dockerfile.test index 0a6a1c7..f76f9ae 100755 --- a/docker/php/Dockerfile.test +++ b/docker/php/Dockerfile.test @@ -22,9 +22,10 @@ RUN pecl install xdebug \ RUN echo "xdebug.mode=coverage,debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \ && echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini -# Configure PHP Upload Limits +# Configure PHP Upload Limits and Error Reporting RUN echo "upload_max_filesize = 100M" > /usr/local/etc/php/conf.d/uploads.ini \ - && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/uploads.ini + && echo "post_max_size = 100M" >> /usr/local/etc/php/conf.d/uploads.ini \ + && echo "error_reporting = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED" > /usr/local/etc/php/conf.d/error_reporting.ini # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer From 5a00e85a6e3a7e563dcf89f6c1fcb6dd5fac2946 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 16:25:33 -0300 Subject: [PATCH 5/9] docs: optimize project.md and update README.md with architecture and CI/CD context --- README.md | 49 +++++++++++++++++++++++++++++------ project.md | 75 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9916ca7..2f35f97 100755 --- a/README.md +++ b/README.md @@ -10,11 +10,13 @@ Este projeto foi desenhado sob o conceito de "Glassmorphism" e possui design dar O Web Storage foi construído utilizando as melhores e mais robustas opções do ecossistema Web Open-Source: -- **Back-end**: PHP 8.3 (FPM) rodando dentro de containers estruturados. +- **Back-end**: PHP 8.4 (FPM) rodando dentro de containers estruturados. - **Servidor Web**: Nginx configurado com uploads expandidos (até 100MB por arquivo). - **Banco de Dados**: PostgreSQL, mantendo forte integridade relacional. +- **Armazenamento de Objetos**: Oracle Cloud Infrastructure (OCI) Object Storage ou Armazenamento Local. - **Front-end**: HTML5 semântico, CSS3 Moderno (CSS Grid/Flexbox) e Javascript (Vanilla ES6+). -- **Testes Unitários**: PHPUnit. +- **Testes Unitários**: PHPUnit 11. +- **CI/CD**: Jenkins & GitHub Actions. - **Virtualização**: Docker + Docker Compose (para ambientes Dev / Prod). ### 🤖 Powered by Antigravity AI @@ -22,13 +24,37 @@ Todo o desenvolvimento arquitetural inicial do projeto, refatoração de UI css/ --- +## 🏗️ Arquitetura e Abstração de Armazenamento + +O sistema utiliza uma **Arquitetura Híbrida de Persistência** com uma camada de abstração que permite alternar entre armazenamento local e na nuvem através da variável de ambiente `STORAGE_TYPE`: + +1. **Metadados (PostgreSQL)**: Todas as informações relacionais, como usuários, logs de auditoria e referências de arquivos, são armazenadas no banco de dados local. +2. **Arquivos Físicos (Abstraction Layer)**: + - **OCI Object Storage (`oci`)**: Integração nativa com o **Oracle Cloud (OCI)** para buckets escaláveis e duráveis. + - **Armazenamento Local (`local`)**: Persistência no sistema de arquivos do servidor/container (ideal para desenvolvimento ou infraestrutura on-premise). + +--- + +## ⚙️ CI/CD & Automação + +O fluxo de desenvolvimento e entrega é totalmente automatizado: + +- **GitHub Actions**: Executa a malha de testes unitários (`./run-tests.sh`) automaticamente em cada Pull Request para a branch `master` e em cada push para a branch `dev`, garantindo que nenhum código quebre as funcionalidades existentes. +- **Jenkins**: Atua como o orquestrador de Continuous Deployment (CD). Ele monitora mudanças, reconstrói as imagens de produção (`docker-compose.prod.yml`) e realiza o deploy seguro injetando as variáveis de ambiente necessárias via Jenkins Credentials. + +--- + ## 🛠️ Passo a Passo Prático (Como Usar) ### Configuração Inicial (Variáveis de Ambiente) Antes de tudo, garanta que o Docker e o `docker-compose` estejam instalados na sua máquina. Para proteger informações sensíveis, todas as credenciais do banco e configurações de ambiente foram extraídas dos arquivos do Docker e mapeadas externamente. Na raiz do projeto você encontrará um arquivo chamado `.env.model`. Copie-o (ou apenas renomeie-o) criando um novo arquivo estritamente chamado `.env`. -Dentro deste `.env`, você poderá personalizar livremente as senhas e nomes de banco de dados para os ambientes de Desenvolvimento (`docker-compose.yml`), Produção e Testes! Os containers do Docker lerão as variáveis automaticamente daqui. + +#### Configurações de Armazenamento: +- **`STORAGE_TYPE`**: Define o driver de armazenamento. Use `local` para disco local (padrão) ou `oci` para Oracle Cloud. +- **`STORAGE_ROOT`**: (Apenas para `local`) O caminho no container onde os arquivos serão salvos (ex: `/var/www/html/storage`). +- **Credenciais OCI**: Caso use `oci`, configure `OCI_USER_OCID`, `OCI_TENANCY_OCID`, `OCI_REGION`, `OCI_FINGERPRINT`, `OCI_KEY_FILE`, `OCI_NAMESPACE` e `OCI_BUCKET`. ### 1️⃣ Executando em Ambiente de Teste/Desenvolvimento Para inciar a aplicação via Docker Compose na porta 80 do seu localhost, execute: @@ -60,11 +86,18 @@ No diretório raiz do projeto, disponibilizamos dois scripts auxiliares BASH par ./set_permissions.sh ``` -### 4️⃣ Deploy para Produção Limitada -Você notará que existe um construtor otimizado exclusivo chamado `Dockerfile.prod`, além de configurações focadas no opcache. Para forçar um deploy fechado em ambiente de produção (mais veloz), monte usando: -```bash -docker compose -f docker-compose.prod.yml up --build -d -``` +--- + +## 📂 Estrutura do Projeto + +- `src/Config/`: Configurações de Banco de Dados e OCI. +- `src/Storage/`: Abstração e drivers de armazenamento (`LocalStorage`, `OCIStorage`). +- `src/Auth.php`: Gerenciamento de sessões e autenticação. +- `src/UserManager.php`: CRUD de usuários e permissões. +- `src/FileManager.php`: Lógica de gerenciamento de objetos na nuvem. +- `tests/`: Suíte de testes unitários. +- `.github/workflows/`: Automação de CI com GitHub Actions. +- `Jenkinsfile`: Pipeline de build e deploy contínuo. --- diff --git a/project.md b/project.md index 75f93ec..521e912 100755 --- a/project.md +++ b/project.md @@ -1,20 +1,67 @@ -# Resumo do Projeto: Web Storage +# 🧩 Contexto do Projeto: Web Storage -O **Web Storage** é uma plataforma de gerenciamento de arquivos em nuvem moderna e segura. Ela fornece aos usuários um ambiente privado para realizar upload, download, edição, renomeação e exclusão de documentos e dados pessoais. A interface possui um design moderno baseado em "Glassmorphism" com suporte a dark/light mode. +O **Web Storage** é uma plataforma de gerenciamento de arquivos em nuvem moderna e segura. Este arquivo serve como a **Fonte da Verdade Técnica** para desenvolvedores e agentes de IA, detalhando a arquitetura, stack e regras de conduta do projeto. -## Tecnologias e Stack +--- -- **Back-end**: PHP 8.4 (FPM) executando dentro de containers. -- **Servidor Web**: Nginx (ambiente de desenvolvimento via porta 80; produção via porta 1234 com SSL habilitado). -- **Banco de Dados**: PostgreSQL. -- **Front-end**: HTML5 semântico, CSS3 Moderno (Grid/Flexbox) e Javascript (Vanilla ES6+). -- **Testes**: PHPUnit para testes unitários. -- **Infraestrutura/Virtualização**: Docker e Docker Compose (com suporte a ambientes de desenvolvimento, teste e produção). +## 🚀 Tecnologias e Stack Core -## Regras de Desenvolvimento +- **Linguagem**: PHP 8.4 (FPM) em containers Docker. +- **Servidor Web**: Nginx (Dev: porta 80; Prod: porta 1234 com SSL). +- **Banco de Dados**: PostgreSQL (Gestão de Metadados e Usuários). +- **Cloud Integration**: Oracle Cloud Infrastructure (OCI) Object Storage SDK. +- **Front-end**: HTML5 semântico, CSS3 Moderno (Glassmorphism) e Vanilla JS (ES6+). +- **Testes**: PHPUnit 11 (Unitário e Integração). +- **Infraestrutura**: Docker & Docker Compose (Ambientes Isolados Dev/Test/Prod). -1. **Testes Obrigatórios**: Sempre criar testes para novas implementações. -2. **Commits Automáticos**: Sempre fazer commit das alterações caso todos os testes passem com sucesso. -3. **Desenvolvimento em Branch Dev**: Todo o desenvolvimento deve ser realizado na branch `dev`. Após cada commit local, deve-se realizar o `git push origin dev` imediatamente. +--- -> **Nota**: Este arquivo serve como referência principal da stack e da arquitetura base. Deve ser consultado antes de propor ou realizar qualquer nova implementação na aplicação para garantir consistência tecnológica. +## 🏗️ Arquitetura e Padrões + +O projeto segue uma abordagem modular e orientada a interfaces para garantir flexibilidade de infraestrutura: + +1. **Abstração de Armazenamento**: + - `App\Storage\StorageInterface`: Contrato único para operações de arquivo. + - `App\Storage\StorageFactory`: Decide o driver via variável `STORAGE_TYPE` (`local` ou `oci`). + - `App\Storage\LocalStorage` & `App\Storage\OCIStorage`: Implementações concretas. +2. **Camada de Negócio (Managers)**: + - `App\Auth`: Autenticação, controle de sessões e política de troca de senha. + - `App\FileManager`: Orquestra operações de arquivos vinculadas ao contexto do usuário. + - `App\UserManager`: Gestão administrativa de membros e permissões. + +--- + +## 📂 Mapa do Projeto (Estrutura Crítica) + +- `public/`: Pontos de entrada web e recursos estáticos (CSS/JS). +- `src/Config/`: Classes de configuração (`Database.php`, `OCIConfig.php`). +- `src/Storage/`: Abstração e drivers de persistência. +- `src/`: Núcleo da lógica de negócio (`Auth.php`, `FileManager.php`, `UserManager.php`). +- `tests/`: Suíte completa de testes (Bootstrap isolado). +- `docker/`: Definições customizadas de Dockerfile (Dev vs Prod). +- `.github/workflows/`: Pipelines de CI (GitHub Actions). +- `Jenkinsfile`: Automação de CD (Deploy Contínuo). + +--- + +## ⚙️ Variáveis de Ambiente Essenciais + +- **`STORAGE_TYPE`**: Define o driver (`local` ou `oci`). +- **`STORAGE_ROOT`**: Diretório base para armazenamento local. +- **`OCI_*`**: Conjunto de credenciais para integração com Oracle Cloud. +- **`DB_*`**: Parâmetros de conexão com o PostgreSQL. + +--- + +## 🤖 Regras de Desenvolvimento e IA + +Para garantir a integridade do código e a eficiência na colaboração (Humano/IA), siga estas diretrizes: + +1. **Testes Obrigatórios**: Nenhuma funcionalidade é considerada "pronta" sem testes unitários correspondentes. Utilize `./run-tests.sh` para validação total. +2. **Commits Atômicos e Unitários**: Realize commits pequenos e focados em uma única funcionalidade ou correção. Evite commits massivos. +3. **Padronização de Código (PSR-12)**: Todo código PHP deve seguir rigorosamente os padrões PSR-12 para consistência estilística. +4. **Sincronização com Documentação**: Qualquer mudança na arquitetura, novas variáveis de ambiente ou novos diretórios **devem** ser refletidos imediatamente neste `project.md` e no `README.md`. +5. **Ciclo de Branch Dev**: O desenvolvimento ocorre na branch `dev`. Faça push imediato após a passagem dos testes locais para garantir que o CI/CD valide a build. +6. **Segurança Pró-ativa**: Nunca utilize credenciais hardcoded. Utilize sempre as abstrações em `src/Config/` que consomem variáveis do `.env`. + +> **Nota**: Consulte este arquivo antes de qualquer refatoração para garantir que os limites arquiteturais (como a abstração de storage) sejam respeitados. From 89e41a324be2b751f78e06d31b4651b1ab07b1e2 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 16:25:38 -0300 Subject: [PATCH 6/9] fix(oci): normalize sdk parameter casing and object access --- src/Storage/OCIStorage.php | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Storage/OCIStorage.php b/src/Storage/OCIStorage.php index 208c8dc..4ddab9d 100755 --- a/src/Storage/OCIStorage.php +++ b/src/Storage/OCIStorage.php @@ -20,10 +20,10 @@ public function __construct(ObjectStorageClient $client, string $namespace, stri public function put(string $path, string $content): void { try { $this->client->putObject([ - 'NamespaceName' => $this->namespace, - 'BucketName' => $this->bucket, - 'ObjectName' => ltrim($path, '/'), - 'PutObjectBody' => $content + 'namespaceName' => $this->namespace, + 'bucketName' => $this->bucket, + 'objectName' => ltrim($path, '/'), + 'putObjectBody' => $content ]); } catch (Exception $e) { throw new Exception("OCI Upload Failed: " . $e->getMessage()); @@ -33,9 +33,9 @@ public function put(string $path, string $content): void { public function get(string $path): string { try { $response = $this->client->getObject([ - 'NamespaceName' => $this->namespace, - 'BucketName' => $this->bucket, - 'ObjectName' => ltrim($path, '/') + 'namespaceName' => $this->namespace, + 'bucketName' => $this->bucket, + 'objectName' => ltrim($path, '/') ]); return (string)$response->getBody(); } catch (Exception $e) { @@ -46,9 +46,9 @@ public function get(string $path): string { public function delete(string $path): void { try { $this->client->deleteObject([ - 'NamespaceName' => $this->namespace, - 'BucketName' => $this->bucket, - 'ObjectName' => ltrim($path, '/') + 'namespaceName' => $this->namespace, + 'bucketName' => $this->bucket, + 'objectName' => ltrim($path, '/') ]); } catch (Exception $e) { // Ignore if not found during delete @@ -58,25 +58,25 @@ public function delete(string $path): void { public function list(string $prefix = ''): array { try { $response = $this->client->listObjects([ - 'NamespaceName' => $this->namespace, - 'BucketName' => $this->bucket, - 'Prefix' => ltrim($prefix, '/') . '/', - 'Fields' => 'name,size,timeCreated' + 'namespaceName' => $this->namespace, + 'bucketName' => $this->bucket, + 'prefix' => ltrim($prefix, '/') . '/', + 'fields' => 'name,size,timeCreated' ]); $data = $response->getJson(); - $objects = $data['objects'] ?? []; + $objects = $data->objects ?? []; $result = []; foreach ($objects as $obj) { - $name = $obj['name']; + $name = $obj->name; // Strip prefix $name = str_replace(ltrim($prefix, '/') . '/', '', $name); if (empty($name)) continue; $result[] = [ 'name' => $name, - 'size' => $obj['size'], - 'modified' => strtotime($obj['timeCreated']) + 'size' => $obj->size, + 'modified' => strtotime($obj->timeCreated) ]; } return $result; @@ -88,9 +88,9 @@ public function list(string $prefix = ''): array { public function exists(string $path): bool { try { $this->client->headObject([ - 'NamespaceName' => $this->namespace, - 'BucketName' => $this->bucket, - 'ObjectName' => ltrim($path, '/') + 'namespaceName' => $this->namespace, + 'bucketName' => $this->bucket, + 'objectName' => ltrim($path, '/') ]); return true; } catch (Exception $e) { @@ -102,9 +102,9 @@ public function rename(string $oldPath, string $newPath): void { // OCI doesn't have rename, must copy and delete try { $this->client->copyObject([ - 'NamespaceName' => $this->namespace, - 'BucketName' => $this->bucket, - 'CopyObjectDetails' => [ + 'namespaceName' => $this->namespace, + 'bucketName' => $this->bucket, + 'copyObjectDetails' => [ 'sourceObjectName' => ltrim($oldPath, '/'), 'destinationObjectName' => ltrim($newPath, '/'), 'destinationBucket' => $this->bucket, From f9d52bb4f8b5d9d560edcc376ca5219f3300cdb7 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 16:25:42 -0300 Subject: [PATCH 7/9] chore(docker): improve dev container command and environment variable handling --- docker-compose.yml | 57 +++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a9236ae..985d5ca 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,10 @@ +version: '3.8' + services: app: build: - context: . - dockerfile: docker/php/Dockerfile.dev - container_name: web_storage_app - restart: unless-stopped + context: ./ + dockerfile: docker/php/Dockerfile working_dir: /var/www/html volumes: - ./:/var/www/html @@ -17,53 +17,38 @@ services: - DB_DATABASE=${DEV_DB_DATABASE:-web_storage} - DB_USERNAME=${DEV_DB_USERNAME:-admin} - DB_PASSWORD=${DEV_DB_PASSWORD:-secret} - command: /bin/bash -c "php src/init_db.php && mkdir -p /var/www/html/storage && chmod -R 777 /var/www/html/storage && php-fpm" + command: /bin/bash -c "chown -R www-data:www-data .oci && chmod 600 .oci/server1.pem && php src/init_db.php && mkdir -p /var/www/html/storage && chmod -R 777 /var/www/html/storage && php-fpm" depends_on: db: condition: service_healthy networks: - dev_net - - web: - image: nginx:latest - container_name: web_storage_nginx - restart: unless-stopped - ports: - - "8080:80" - volumes: - - ./:/var/www/html - - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf - depends_on: - - app - networks: - - dev_net - db: image: postgres:15-alpine - container_name: web_storage_db - restart: unless-stopped - env_file: - - .env environment: - POSTGRES_DB: ${DEV_POSTGRES_DB:-web_storage} - POSTGRES_USER: ${DEV_POSTGRES_USER:-admin} - POSTGRES_PASSWORD: ${DEV_POSTGRES_PASSWORD:-secret} - volumes: - - default_postgres_data:/var/lib/postgresql/data + - POSTGRES_DB=${DEV_DB_DATABASE:-web_storage} + - POSTGRES_USER=${DEV_DB_USERNAME:-admin} + - POSTGRES_PASSWORD=${DEV_DB_PASSWORD:-secret} healthcheck: - test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] - interval: 10s + test: ["CMD-SHELL", "pg_isready -U ${DEV_DB_USERNAME:-admin} -d ${DEV_DB_DATABASE:-web_storage}"] + interval: 5s timeout: 5s retries: 5 - start_period: 10s - ports: - - "5432:5432" networks: - dev_net -volumes: - default_postgres_data: + nginx: + image: nginx:alpine + ports: + - "80:80" + volumes: + - ./:/var/www/html + - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf + depends_on: + - app + networks: + - dev_net networks: dev_net: From c0854fec9b60981aff050b2ecd1b388e6f072440 Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 16:37:22 -0300 Subject: [PATCH 8/9] fix(test): align OCIStorageTest mock with object-access implementation --- tests/OCIStorageTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/OCIStorageTest.php b/tests/OCIStorageTest.php index 4ce37c4..027cf96 100755 --- a/tests/OCIStorageTest.php +++ b/tests/OCIStorageTest.php @@ -63,9 +63,9 @@ public function testDelete() { public function testList() { $responseMock = $this->createMock(OciResponse::class); - $responseMock->method('getJson')->willReturn([ + $responseMock->method('getJson')->willReturn((object)[ 'objects' => [ - [ + (object)[ 'name' => 'user_1/file1.txt', 'size' => 100, 'timeCreated' => date('c') From 9415c506cd2082d2f27f9eddc2554772b07856ab Mon Sep 17 00:00:00 2001 From: FabricioLR Date: Tue, 24 Mar 2026 16:37:28 -0300 Subject: [PATCH 9/9] docs: add mandatory pre-push testing rule to project.md --- project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.md b/project.md index 521e912..a1597cf 100755 --- a/project.md +++ b/project.md @@ -61,7 +61,7 @@ Para garantir a integridade do código e a eficiência na colaboração (Humano/ 2. **Commits Atômicos e Unitários**: Realize commits pequenos e focados em uma única funcionalidade ou correção. Evite commits massivos. 3. **Padronização de Código (PSR-12)**: Todo código PHP deve seguir rigorosamente os padrões PSR-12 para consistência estilística. 4. **Sincronização com Documentação**: Qualquer mudança na arquitetura, novas variáveis de ambiente ou novos diretórios **devem** ser refletidos imediatamente neste `project.md` e no `README.md`. -5. **Ciclo de Branch Dev**: O desenvolvimento ocorre na branch `dev`. Faça push imediato após a passagem dos testes locais para garantir que o CI/CD valide a build. +5. **Ciclo de Branch Dev**: O desenvolvimento ocorre na branch `dev`. O `git push origin dev` **só deve ser realizado após todos os testes passarem** com o comando `./run-tests.sh`. Caso algum teste falhe, as correções devem ser feitas localmente até a aprovação total antes de qualquer sincronização com o GitHub. 6. **Segurança Pró-ativa**: Nunca utilize credenciais hardcoded. Utilize sempre as abstrações em `src/Config/` que consomem variáveis do `.env`. > **Nota**: Consulte este arquivo antes de qualquer refatoração para garantir que os limites arquiteturais (como a abstração de storage) sejam respeitados.