Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gustavocampana #8

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
44 changes: 44 additions & 0 deletions app/Console/Commands/NicArWhoisCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace App\Console\Commands;

use App\Service\RDPA\RDPAQuery;
use Illuminate\Console\Command;

class NicArWhoisCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'nick-ar:whois {domain}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Query nick.ar whois for expiration date';

/**
* Execute the console command.
*
* @return int
*/
public function handle(RDPAQuery $RDPAQuery)
{
try{
$domain = $this->argument('domain');
$expirationDate = $RDPAQuery->makeCall($domain);
$this->line($expirationDate);
return 0;
} catch(\InvalidArgumentException $e){
$this->line('Dominio inválido. Solo se permiten dominios .com.ar');
return -1;
} catch(\UnexpectedValueException $e){
$this->line('Dominio no encontrado');
return -1;
}
}
}
18 changes: 18 additions & 0 deletions app/Http/Controllers/Api/V1/ProductController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Repository\ProductRepository;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ProductController extends Controller
{
public function index(Request $request, ProductRepository $productRepository): JsonResponse
{
$categoryId = $request->get('idCategory');
$products = $productRepository->findProducts($categoryId);
return response()->json($products);
}
}
20 changes: 20 additions & 0 deletions app/Http/Controllers/Api/V1/WhoisQueryController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Service\Whois\WhoisService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;


class WhoisQueryController extends Controller
{
public function index(Request $request, WhoisService $whoisService): JsonResponse
{
$whoisServer = 'whois.donweb.com';
$domain = $request->get('domain');
$queryResult = $whoisService->makeQuery($whoisServer, $domain);
return response()->json($queryResult);
}
}
13 changes: 13 additions & 0 deletions app/Models/Product.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
public function category()
{
return $this->belongsToMany(Category::class);
}
}
19 changes: 19 additions & 0 deletions app/Repository/CategoryRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Repository;

use Illuminate\Support\Facades\DB;

class CategoryRepository
{
public function getCategoriesPath(): array
{
return DB::table('categories as c1')
->select(DB::raw("c1.nombre || COALESCE(' -> ' || c2.nombre, '') || COALESCE(' -> ' || c3.nombre, '') AS path"))
->join('categories as c2', 'c1.id', '=', 'c2.idcategoriapadre')
->leftJoin('categories as c3', 'c2.id', '=', 'c3.idcategoriapadre')
->whereNull('c1.idcategoriapadre')
->pluck('path')
->toArray();
}
}
20 changes: 20 additions & 0 deletions app/Repository/ProductRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Repository;

use Illuminate\Support\Facades\DB;

class ProductRepository
{
public function findProducts(?string $categoryId): array
{
$qb = DB::table('products')
->select('products.id', 'products.descripcion', 'products.precio', 'categories.nombre as categoria')
->join('categories','products.category_id', '=', 'categories.id');
if(!empty($categoryId)){
$qb->where('products.category_id', '=', $categoryId);
}
return $qb->get()->toArray();
}
}

45 changes: 45 additions & 0 deletions app/Service/RDPA/RDPAQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace App\Service\RDPA;

use Illuminate\Support\Facades\Http;

class RDPAQuery
{
/**
* @throws \InvalidArgumentException
* @throws \UnexpectedValueException
*/
public function makeCall(string $domain): string
{
if(!str_ends_with($domain, 'com.ar')){
throw new \InvalidArgumentException('Dominio inválido. Solo se permiten dominios .com.ar');
}
$domainEvents = $this->callRDPAForDomainEvents($domain);
return $this->getExpirationDate($domainEvents);
}

/**
* @throws \UnexpectedValueException
*/
public function callRDPAForDomainEvents(string $domain): array
{
$response = Http::get("https://rdap.nic.ar/domain/$domain");
$domainEvents = $response->json('events');
if(!is_array($domainEvents) || count($domainEvents) == 0){
throw new \UnexpectedValueException('Dominio no encontrado');
}
return $domainEvents;
}

private function getExpirationDate(array $domainEvents): string
{
$expirationDate = '';
foreach($domainEvents as $event){
if($event['eventAction'] == 'expiration'){
$expirationDate = (new \DateTime($event['eventDate']))->format('h:i:s d/M/Y');
}
}
return $expirationDate;
}
}
21 changes: 21 additions & 0 deletions app/Service/Whois/DonwebResponseParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Service\Whois;

class DonwebResponseParser implements WhoisResponseParser
{
public function parseResponse(string $responseContent): array
{
$responseLines = array_map('trim', preg_split('/\n|\r\n?/', $responseContent));
return $this->getNameServers($responseLines);
}

public function getNameServers(array $textLines): array
{
$nameServers = array_filter($textLines, function($el){
return str_contains(strtolower($el), 'name server');
});
$nameServers = str_replace('Name Server: ', '', $nameServers);
return [ 'Name Servers' => array_values($nameServers) ];
}
}
15 changes: 15 additions & 0 deletions app/Service/Whois/ResponseParserFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace App\Service\Whois;
use Ramsey\Collection\Exception\UnsupportedOperationException;

class ResponseParserFactory
{
public static function getResponseParser($whoisServer): WhoisResponseParser
{
if($whoisServer == 'whois.donweb.com'){
return new DonwebResponseParser;
}
throw new UnsupportedOperationException('Parser no encontrado');
}
}
58 changes: 58 additions & 0 deletions app/Service/Whois/WhoisQuerier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace App\Service\Whois;

class WhoisQuerier
{
private string $port = '43';

private string $timeOut = '30';

private $socket;

/**
* Make a query to the Whois server
*
* @param string $whoisServer
* @param string $domainToQuery
* @return string
* @throws \ErrorException
*/
public function queryServer(string $whoisServer, string $domainToQuery): string
{
$this->connectToServer($whoisServer);
$this->writeDomain($domainToQuery);
$response = $this->readResponse();
$this->closeConnection();
return $response;
}

/**
* @param string $whoisServer
* @return void
* @throws \ErrorException
*/
private function connectToServer(string $whoisServer): void
{
$this->socket = fsockopen("tcp://$whoisServer", $this->port, $errno, $errstr, $this->timeOut);
}

private function writeDomain(string $domainToQuery): void
{
fwrite($this->socket, $domainToQuery."\r\n");
}

private function readResponse(): string
{
$response = '';
while(!feof($this->socket)) {
$response .= fgets($this->socket, 1024);
}
return $response;
}

private function closeConnection(): void
{
fclose($this->socket);
}
}
8 changes: 8 additions & 0 deletions app/Service/Whois/WhoisResponseParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace App\Service\Whois;

interface WhoisResponseParser
{
public function parseResponse(string $content): array;
}
19 changes: 19 additions & 0 deletions app/Service/Whois/WhoisService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Service\Whois;

class WhoisService
{
private WhoisQuerier $whoisQuerier;

public function __construct(WhoisQuerier $whoisQuerier)
{
$this->whoisQuerier = $whoisQuerier;
}
public function makeQuery(string $whoisServer, string $domainToQuery): array
{
$response = $this->whoisQuerier->queryServer($whoisServer, $domainToQuery);
$parser = ResponseParserFactory::getResponseParser($whoisServer);
return $parser->parseResponse($response);
}
}
8 changes: 6 additions & 2 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::apiResource('v1/categories', App\Http\Controllers\Api\V1\CategoryController::class)->only('index');
Route::apiResource('v1/categories', App\Http\Controllers\Api\V1\CategoryController::class)->only('index');

Route::apiResource('v1/products', App\Http\Controllers\Api\V1\ProductController::class)
->only('index');

Route::get('v1/whois', 'App\Http\Controllers\Api\V1\WhoisQueryController@index');
5 changes: 5 additions & 0 deletions scripts/create-cron-entry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

SCRIPT_BACKUP="$PWD/make-db-backup.sh"

(crontab -l; echo "0 0 * * * $SCRIPT_BACKUP") | sort -u | crontab -u $USER -
7 changes: 7 additions & 0 deletions scripts/make-db-backup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

source ../.env
DATE=$(date +%F)
FILE="backup_$DATE.sql"

mysqldump -u $DB_USERNAME -h localhost -P $DB_PORT -p$DB_PASSWORD $DB_DATABASE > $FILE
27 changes: 27 additions & 0 deletions tests/Feature/CategoryRepositoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Tests\Feature;

use App\Repository\CategoryRepository;
use Tests\TestCase;

class CategoryRepositoryTest extends TestCase
{

public function testGetCategoriesPath()
{
$expected = [
'Indumentaria -> Adidas',
'Indumentaria -> Nike',
'Calzado -> Calzado Dita',
'Calzado -> Calzado Nike',
'Calzado -> Calzado Adidas',
'Calzado -> Running -> Adidas',
'Calzado -> Running -> Puma',
'Calzado -> Crocs'
];
$categoryRepository = new CategoryRepository();
$result = $categoryRepository->getCategoriesPath();
$this->assertEquals($expected, $result);
}
}
Loading