Initial commit
This commit is contained in:
54
src/Database.php
Normal file
54
src/Database.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\Phpvault;
|
||||
|
||||
use SQLite3;
|
||||
|
||||
class Database {
|
||||
private $db;
|
||||
|
||||
public function __construct() {
|
||||
$this->db = new SQLite3(__DIR__ . '/../database/db.sqlite');
|
||||
if (!$this->db) {
|
||||
echo 'Unable to connect to database';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
public function query($query) {
|
||||
return $this->db->query($query);
|
||||
}
|
||||
|
||||
public function createTables() {
|
||||
$queries = [
|
||||
'CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL
|
||||
)',
|
||||
'CREATE TABLE IF NOT EXISTS vault (
|
||||
id INTEGER PRIMARY KEY,
|
||||
username TEXT NOT NULL,
|
||||
vaultname TEXT NOT NULL,
|
||||
encrypted_data TEXT NOT NULL
|
||||
)',
|
||||
'CREATE INDEX IF NOT EXISTS username_idx ON users (username)',
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS vault_unique_idx ON vault (username, vaultname);',
|
||||
];
|
||||
|
||||
foreach ($queries as $query) {
|
||||
if (!$this->db->exec($query)) {
|
||||
echo 'Error creating tables: ' . $this->db->lastErrorMsg();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getDb() {
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
public function close() {
|
||||
$this->db->close();
|
||||
}
|
||||
}
|
||||
70
src/Handler/AuthHandler.php
Normal file
70
src/Handler/AuthHandler.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\Phpvault\Handler;
|
||||
|
||||
use Exception;
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use Hpz937\Phpvault\Database;
|
||||
use stdClass;
|
||||
|
||||
class AuthHandler
|
||||
{
|
||||
private $secretKey;
|
||||
private $database;
|
||||
|
||||
public function __construct($secretKey, Database $database)
|
||||
{
|
||||
$this->secretKey = $secretKey;
|
||||
$this->database = $database->getDb();
|
||||
}
|
||||
|
||||
public function generateToken($username, $password)
|
||||
{
|
||||
$query = "SELECT * FROM users WHERE username='$username'";
|
||||
$result = $this->database->query($query);
|
||||
if (!$result) {
|
||||
return null;
|
||||
}
|
||||
$user = $result->fetchArray();
|
||||
if (!$user) {
|
||||
return null;
|
||||
}
|
||||
if (password_verify($password, $user['password'])) {
|
||||
$payload = [
|
||||
'username' => $username,
|
||||
];
|
||||
|
||||
$issuedAt = time();
|
||||
$expirationTime = $issuedAt + 3600; // jwt valid for 1 hour
|
||||
$payload['iat'] = $issuedAt;
|
||||
$payload['exp'] = $expirationTime;
|
||||
|
||||
return JWT::encode($payload, $this->secretKey, 'HS256');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function addUser($username, $password)
|
||||
{
|
||||
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
|
||||
$username = $this->database->escapeString($username);
|
||||
$hashedPassword = $this->database->escapeString($hashedPassword);
|
||||
$query = "INSERT INTO users (username, password) VALUES ('$username', '$hashedPassword')";
|
||||
return $this->database->exec($query);
|
||||
}
|
||||
|
||||
public function verifyToken($token)
|
||||
{
|
||||
try {
|
||||
if (! preg_match('/Bearer\s(\S+)/', $token, $matches)) {
|
||||
throw new Exception('Invalid token');
|
||||
}
|
||||
$decoded = JWT::decode($matches[1], new Key($this->secretKey, 'HS256'));
|
||||
return $decoded->username;
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/Middleware/AuthMiddleware.php
Normal file
38
src/Middleware/AuthMiddleware.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\Phpvault\Middleware;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
|
||||
use Slim\Psr7\Response as SlimResponse;
|
||||
use Hpz937\Phpvault\Handler\AuthHandler;
|
||||
|
||||
class AuthMiddleware
|
||||
{
|
||||
private $authHandler;
|
||||
|
||||
public function __construct(AuthHandler $authHandler)
|
||||
{
|
||||
$this->authHandler = $authHandler;
|
||||
}
|
||||
|
||||
public function __invoke(Request $request, RequestHandler $handler): Response
|
||||
{
|
||||
$authHeader = $request->getHeaderLine('Authorization');
|
||||
|
||||
// Verify the token
|
||||
$username = $this->authHandler->verifyToken($authHeader);
|
||||
|
||||
if ($username === null) {
|
||||
// Token is invalid, return 401 Unauthorized
|
||||
$response = new SlimResponse();
|
||||
$response->getBody()->write(json_encode(['error' => 'Unauthorized']));
|
||||
return $response->withStatus(401)->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
$request = $request->withAttribute('username', $username);
|
||||
|
||||
// Token is valid, proceed to the next middleware/route
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
||||
95
src/Vault.php
Normal file
95
src/Vault.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Hpz937\Phpvault;
|
||||
|
||||
use Hpz937\Encryption\DataEncryptor;
|
||||
|
||||
class Vault
|
||||
{
|
||||
private $database;
|
||||
|
||||
public function __construct(Database $database)
|
||||
{
|
||||
$this->database = $database->getDb();
|
||||
}
|
||||
|
||||
public function storeSecret(string $userName, string $vaultName, string $key, string $secret)
|
||||
{
|
||||
$jsonSecret = json_decode($secret, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return false;
|
||||
}
|
||||
$key = $jsonSecret['key'];
|
||||
if (!$key) {
|
||||
return false;
|
||||
}
|
||||
unset($jsonSecret['key']);
|
||||
$dataEncryptor = new DataEncryptor($key);
|
||||
$encryptedSecret = $dataEncryptor->encrypt(json_encode($jsonSecret));
|
||||
// make sure vaultname does not exist first
|
||||
$query = "SELECT * FROM vault WHERE username = '$userName' AND vaultname = '$vaultName'";
|
||||
$result = $this->database->query($query);
|
||||
$row = $result->fetchArray();
|
||||
if ($row) {
|
||||
throw new \Exception('Vault already exists, try PUT to update');
|
||||
}
|
||||
$query = "INSERT INTO vault (username, vaultname, encrypted_data) VALUES ('$userName', '$vaultName', '$encryptedSecret')";
|
||||
if ($result = $this->database->exec($query)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function getSecret(string $userName, string $key, string $vaultName)
|
||||
{
|
||||
$query = "SELECT encrypted_data FROM vault WHERE username = '$userName' AND vaultname = '$vaultName'";
|
||||
$result = $this->database->query($query);
|
||||
$row = $result->fetchArray();
|
||||
if ($row) {
|
||||
$dataEncryptor = new DataEncryptor($key);
|
||||
return $dataEncryptor->decrypt($row['encrypted_data']);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function updateSecret(string $userName, string $vaultName, string $key, string $secret)
|
||||
{
|
||||
$jsonSecret = json_decode($secret, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return false;
|
||||
}
|
||||
$key = $jsonSecret['key'];
|
||||
if (!$key) {
|
||||
return false;
|
||||
}
|
||||
unset($jsonSecret['key']);
|
||||
$dataEncryptor = new DataEncryptor($key);
|
||||
$encryptedSecret = $dataEncryptor->encrypt(json_encode($jsonSecret));
|
||||
|
||||
$query = "SELECT * FROM vault WHERE username = '$userName' AND vaultname = '$vaultName'";
|
||||
$result = $this->database->query($query);
|
||||
$row = $result->fetchArray();
|
||||
if ($row) {
|
||||
$query = "UPDATE vault SET encrypted_data = '$encryptedSecret' WHERE username = '$userName' AND vaultname = '$vaultName'";
|
||||
if ($this->database->exec($query)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('Vault does not exist, try POST to create');
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteSecret(string $userName, string $vaultName)
|
||||
{
|
||||
$query = "SELECT * FROM vault WHERE username = '$userName' AND vaultname = '$vaultName'";
|
||||
$result = $this->database->query($query);
|
||||
$row = $result->fetchArray();
|
||||
if ($row) {
|
||||
$query = "DELETE FROM vault WHERE username = '$userName' AND vaultname = '$vaultName'";
|
||||
if ($this->database->exec($query)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('Vault does not exist');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user