This commit is contained in:
2026-05-17 20:07:18 -05:00
parent 1025d48877
commit 24169162aa
5 changed files with 1821 additions and 42 deletions

View File

@@ -52,3 +52,8 @@ VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}" VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
JWT_ISSUER=
JWT_AUDIENCE=
JWT_PUBLIC_KEY_PEM=
JWT_TOKEN=

375
README.md
View File

@@ -1,49 +1,362 @@
# 🎮 Game Ranking API - Microserviço # 🎮 Microsserviço de Rankings de Jogos (Game Ranking API)
Este é um microserviço desenvolvido em **Laravel 11** para gerenciamento e exposição de rankings de jogos. A API fornece dados sobre os jogos mais jogados, rankings gerais por período e rankings específicos por plataforma. ![Laravel](https://img.shields.io/badge/Laravel-11-red)
![PHP](https://img.shields.io/badge/PHP-8.2-blue)
![SQLite](https://img.shields.io/badge/SQLite-Database-green)
## 🚀 Funcionalidades ---
- **Ranking Geral:** Consulta de top 10 (semanal, mensal e anual).
- **Mais Jogados:** Listagem baseada no volume de jogadores ativos.
- **Filtro por Plataforma:** Rankings específicos para Steam, PlayStation, Xbox e Nintendo.
- **Documentação Automática:** Interface interativa via Scribe.
## 🛠️ Pré-requisitos # 📌 Sobre o Projeto
- PHP >= 8.2
- Composer
- Extensão SQLite habilitada no PHP
## 📥 Instalação e Configuração Este microsserviço faz parte do ecossistema **GameVerse**.
Ele é responsável por processar, armazenar e disponibilizar estatísticas de engajamento, permitindo que a plataforma exiba rankings dinâmicos e tendências globais.
---
# 👥 Integrantes
* Kaiky Andrade de Oliveira
* Gabriel Henrique Lina Batista Pereira Nunes
---
# 📝 Descrição do Serviço
O serviço centraliza métricas de performance dos jogos, como:
* pontuação
* tempo de jogo
* quantidade de jogadores ativos
* evolução de desempenho
Ele resolve o problema de sobrecarga do sistema principal ao isolar o processamento de grandes volumes de dados estatísticos em um microsserviço dedicado, garantindo que as tabelas de classificação sejam atualizadas e entregues rapidamente aos usuários finais.
---
# 🎯 Responsabilidades do Microsserviço
O serviço possui as seguintes responsabilidades:
* Fornecer rankings de desempenho semanal, mensal e anual
* Listar os jogos mais populares
* Exibir histórico de evolução de pontuação
* Segmentar rankings por plataforma
* Disponibilizar dados estatísticos para outros microsserviços
---
# 🛠️ Tecnologias Utilizadas
* PHP 8.2
* Laravel 11
* SQLite
* Composer
* Laravel Scribe (Documentação OpenAPI)
---
# ✅ Requisitos Necessários
Antes de executar o projeto, é necessário possuir instalado:
* PHP >= 8.2
* Composer
* Git
* SQLite
---
# ⚙️ Variáveis de Ambiente
O projeto utiliza variáveis configuradas no arquivo `.env`.
Exemplo:
| Variável | Descrição |
| ------------- | ------------------------ |
| APP_NAME | Nome da aplicação |
| APP_ENV | Ambiente da aplicação |
| APP_KEY | Chave do Laravel |
| APP_DEBUG | Modo de depuração |
| DB_CONNECTION | Banco de dados utilizado |
---
# 📥 Instalação do Projeto
## 1. Clone o repositório
```bash
git clone https://github.com/gabriellina640/api-ranking-jogos.git
```
## 2. Acesse a pasta do projeto
```bash
cd api-ranking-jogos
```
## 3. Instale as dependências
1. **Instalar dependências:**
```bash ```bash
composer install composer install
Configurar Ambiente: ```
Certifique-se de que o arquivo .env existe e está configurado para SQLite:
Snippet de código ---
# ⚙️ Configuração do .env
Crie uma cópia do arquivo de ambiente:
```bash
cp .env.example .env
```
Configure o banco SQLite no arquivo `.env`:
```env
DB_CONNECTION=sqlite DB_CONNECTION=sqlite
Preparar o Banco de Dados: ```
Crie o arquivo do banco e popule com dados fictícios:
Bash ---
php artisan migrate --seed
Gerar a Documentação:
Bash # 🗄️ Preparação do Banco de Dados
Execute as migrations e seeders:
```bash
php artisan migrate:fresh --seed
```
---
# 📚 Gerar Documentação da API
Execute o comando:
```bash
php artisan scribe:generate php artisan scribe:generate
🖥️ Como Usar ```
Para subir o servidor local:
Bash ---
# 🚀 Executando o Projeto
Inicie o servidor Laravel:
```bash
php artisan serve php artisan serve
API: http://localhost:8000/api/v1/... ```
Documentação Interativa: http://localhost:8000/docs A aplicação ficará disponível em:
🛠️ Tecnologias ```bash
Framework: Laravel 11 http://localhost:8000
```
Banco de Dados: SQLite ---
Documentação: Scribe (OpenAPI/Swagger) # 📖 Documentação Interativa da API
Após iniciar o projeto, acesse:
```bash
http://localhost:8000/docs
```
A documentação gerada pelo Scribe permite:
* visualizar endpoints
* testar requisições
* consultar parâmetros
* visualizar respostas JSON
---
# 🧪 Como Testar o Projeto
Você pode testar a API utilizando:
* Scribe
* Postman
* Insomnia
* Thunder Client
Exemplo:
```http
GET http://localhost:8000/api/v1/rankings/weekly
```
---
# 📑 Rotas da API
| Método | Endpoint | Descrição |
| ------ | ------------------------------------- | ---------------------------------------- |
| GET | /api/v1/rankings/weekly | Lista o Top 10 jogos da última semana |
| GET | /api/v1/rankings/monthly | Lista o Top 10 jogos do último mês |
| GET | /api/v1/rankings/yearly | Lista o Top 10 jogos do último ano |
| GET | /api/v1/rankings/history/{id} | Busca a evolução de pontuação de um jogo |
| GET | /api/v1/games/most-played | Lista os jogos mais jogados |
| GET | /api/v1/rankings/platforms/{platform} | Lista rankings por plataforma |
---
# 📥 Exemplo de Requisição
## Buscar ranking semanal
```http
GET /api/v1/rankings/weekly HTTP/1.1
Host: localhost:8000
Accept: application/json
```
---
# 📤 Exemplo de Resposta JSON
```json
[
{
"id": 1,
"name": "Elden Ring",
"platform": "Steam",
"active_players": 1500000,
"weekly_points": 850,
"monthly_points": 7000,
"yearly_points": 85000,
"created_at": "2026-05-04T22:00:00.000000Z",
"updated_at": "2026-05-04T22:00:00.000000Z"
}
]
```
---
# 🔗 Integrações com Outros Microsserviços
## Quais dados recebe
O microsserviço recebe:
* IDs de jogos
* parâmetros de filtro
* plataformas
* períodos de ranking
---
## Quais dados retorna
O serviço retorna:
* rankings
* estatísticas
* histórico de pontuação
* quantidade de jogadores ativos
Todos os dados são retornados em formato JSON.
---
## Quais serviços consome
O microsserviço consome:
* Microsserviço de Telemetria
* Microsserviço de Catálogo de Jogos
---
## Quais serviços utilizam esta API
Os serviços que utilizam esta API são:
* Front-end GameVerse
* Microsserviço de Loja
* Sistema de Recomendações
---
# 🔄 Fluxo Principal do Serviço
1. O usuário acessa a plataforma GameVerse
2. O Front-end solicita os rankings
3. O microsserviço consulta o banco SQLite
4. Os dados são processados e ordenados
5. O JSON é retornado ao Front-end
6. Os rankings são exibidos ao usuário
---
# ⚠️ Possíveis Erros e Retornos Esperados
| Código | Erro | Descrição |
| ------ | ---------------------- | ------------------------- |
| 400 | Dados inválidos | Parâmetros incorretos |
| 404 | Jogo inexistente | Jogo não encontrado |
| 404 | Plataforma inexistente | Plataforma não encontrada |
| 500 | Erro interno | Falha no servidor |
| 503 | Serviço indisponível | Banco indisponível |
---
# 📤 Exemplo de Erro JSON
```json
{
"success": false,
"message": "Jogo não encontrado"
}
```
---
# 📁 Estrutura do Projeto
```bash
app/
bootstrap/
config/
database/
public/
resources/
routes/
storage/
tests/
```
---
# 📦 Arquivos Obrigatórios da Entrega
Este repositório contém:
* README.md
* .env.example
* Código-fonte completo
⚠️ A pasta `vendor/` não deve ser enviada para o GitHub.
---
# 📌 Participação no Ecossistema GameVerse
Este microsserviço é responsável por fornecer estatísticas e rankings em tempo real dentro do GameVerse.
Ele participa diretamente:
* das vitrines de jogos populares
* das recomendações de destaque
* dos rankings competitivos
* das estatísticas globais da plataforma
Seu objetivo é garantir alta performance na consulta de dados estatísticos.
---
# 📬 Contato
Projeto acadêmico desenvolvido para a disciplina de Microsserviços — GameVerse.

View File

@@ -4,8 +4,6 @@ namespace App\Http\Middleware;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class JwtAuthMiddleware class JwtAuthMiddleware
{ {
@@ -24,20 +22,24 @@ class JwtAuthMiddleware
$token = $matches[1]; $token = $matches[1];
$publicKey = str_replace('\\n', "\n", env('JWT_PUBLIC_KEY_PEM')); [$header, $payload, $signature] = $this->decodeToken($token);
$decoded = JWT::decode($token, new Key($publicKey, 'RS256')); if (($header['alg'] ?? null) !== 'RS256') {
return response()->json(['message' => 'Invalid token algorithm'], 401);
}
if ( if (
$decoded->iss !== env('JWT_ISSUER') || !$this->signatureIsValid($token, $signature) ||
$decoded->aud !== env('JWT_AUDIENCE') || ($payload['iss'] ?? null) !== config('jwt.issuer') ||
empty($decoded->sub) ($payload['aud'] ?? null) !== config('jwt.audience') ||
empty($payload['sub']) ||
$this->tokenIsExpired($payload)
) { ) {
return response()->json(['message' => 'Invalid token'], 401); return response()->json(['message' => 'Invalid token'], 401);
} }
$request->attributes->set('auth', [ $request->attributes->set('auth', [
'id' => $decoded->sub, 'id' => $payload['sub'],
'token' => $token 'token' => $token
]); ]);
@@ -47,4 +49,68 @@ class JwtAuthMiddleware
return response()->json(['message' => 'Invalid or expired token'], 401); return response()->json(['message' => 'Invalid or expired token'], 401);
} }
} }
private function decodeToken(string $token): array
{
$parts = explode('.', $token);
if (count($parts) !== 3) {
throw new \InvalidArgumentException('Invalid token structure');
}
return [
$this->base64UrlDecodeJson($parts[0]),
$this->base64UrlDecodeJson($parts[1]),
$this->base64UrlDecode($parts[2]),
];
}
private function base64UrlDecodeJson(string $value): array
{
$decoded = json_decode($this->base64UrlDecode($value), true);
if (!is_array($decoded)) {
throw new \InvalidArgumentException('Invalid token payload');
}
return $decoded;
}
private function base64UrlDecode(string $value): string
{
$value .= str_repeat('=', (4 - strlen($value) % 4) % 4);
$decoded = base64_decode(strtr($value, '-_', '+/'), true);
if ($decoded === false) {
throw new \InvalidArgumentException('Invalid base64url value');
}
return $decoded;
}
private function signatureIsValid(string $token, string $signature): bool
{
[$header, $payload] = explode('.', $token, 3);
$publicKey = str_replace('\\n', "\n", (string) config('jwt.public_key'));
if ($publicKey === '') {
return false;
}
return openssl_verify(
$header . '.' . $payload,
$signature,
$publicKey,
OPENSSL_ALGO_SHA256
) === 1;
}
private function tokenIsExpired(array $payload): bool
{
if (!isset($payload['exp']) || !is_numeric($payload['exp'])) {
return true;
}
return time() >= (int) $payload['exp'];
}
} }

7
config/jwt.php Normal file
View File

@@ -0,0 +1,7 @@
<?php
return [
'issuer' => env('JWT_ISSUER'),
'audience' => env('JWT_AUDIENCE'),
'public_key' => env('JWT_PUBLIC_KEY_PEM'),
];

1388
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff