encrypt user data

This commit is contained in:
HolgerHatGarKeineNode
2023-02-03 17:11:23 +01:00
parent fa474cd159
commit 0276247de3
11 changed files with 302 additions and 16 deletions

View File

@@ -13,10 +13,15 @@ use Laravel\Sanctum\HasApiTokens;
use QCod\Gamify\Gamify;
use Spatie\Comments\Models\Concerns\InteractsWithComments;
use Spatie\Comments\Models\Concerns\Interfaces\CanComment;
use Spatie\LaravelCipherSweet\Concerns\UsesCipherSweet;
use Spatie\LaravelCipherSweet\Contracts\CipherSweetEncrypted;
use Spatie\Permission\Traits\HasRoles;
use ParagonIE\CipherSweet\EncryptedRow;
use ParagonIE\CipherSweet\BlindIndex;
class User extends Authenticatable implements MustVerifyEmail, CanComment
class User extends Authenticatable implements MustVerifyEmail, CanComment, CipherSweetEncrypted
{
use UsesCipherSweet;
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
@@ -56,6 +61,21 @@ class User extends Authenticatable implements MustVerifyEmail, CanComment
'profile_photo_url',
];
public static function configureCipherSweet(EncryptedRow $encryptedRow): void
{
$encryptedRow
->addField('public_key')
->addField('lightning_address')
->addField('lnurl')
->addField('node_id')
->addField('email')
->addBlindIndex('public_key', new BlindIndex('public_key_index'))
->addBlindIndex('lightning_address', new BlindIndex('lightning_address_index'))
->addBlindIndex('lnurl', new BlindIndex('lnurl_index'))
->addBlindIndex('node_id', new BlindIndex('node_id_index'))
->addBlindIndex('email', new BlindIndex('email_index'));
}
public function orangePills()
{
return $this->hasMany(OrangePill::class);

View File

@@ -30,7 +30,7 @@ class User extends Resource
* @var array
*/
public static $search = [
'id', 'name', 'email',
'id', 'name',
];
public static function label()

View File

@@ -9,14 +9,17 @@ use App\Actions\Jetstream\DeleteUser;
use App\Actions\Jetstream\InviteTeamMember;
use App\Actions\Jetstream\RemoveTeamMember;
use App\Actions\Jetstream\UpdateTeamName;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;
use Laravel\Jetstream\Jetstream;
class JetstreamServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
@@ -26,7 +29,6 @@ class JetstreamServiceProvider extends ServiceProvider
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
@@ -40,11 +42,22 @@ class JetstreamServiceProvider extends ServiceProvider
Jetstream::removeTeamMembersUsing(RemoveTeamMember::class);
Jetstream::deleteTeamsUsing(DeleteTeam::class);
Jetstream::deleteUsersUsing(DeleteUser::class);
Fortify::authenticateUsing(function (Request $request) {
$user = User::query()
->whereBlind('email', 'email_index', $request->email)
->first();
if ($user &&
Hash::check($request->password, $user->password)) {
return $user;
}
});
}
/**
* Configure the roles and permissions that are available within the application.
*
* @return void
*/
protected function configurePermissions()
@@ -56,12 +69,14 @@ class JetstreamServiceProvider extends ServiceProvider
'read',
'update',
'delete',
])->description('Administrator users can perform any action.');
])
->description('Administrator users can perform any action.');
Jetstream::role('editor', 'Editor', [
'read',
'create',
'update',
])->description('Editor users have the ability to read, create, and update.');
])
->description('Editor users have the ability to read, create, and update.');
}
}

View File

@@ -40,6 +40,7 @@
"simplito/elliptic-php": "^1.0",
"spatie/eloquent-sortable": "^4.0",
"spatie/icalendar-generator": "^2.5",
"spatie/laravel-ciphersweet": "^1.0",
"spatie/laravel-comments": "^1.4",
"spatie/laravel-comments-livewire": "^1.2",
"spatie/laravel-google-fonts": "^1.2",

135
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "de6fecaf71d0b9f0abef4ce825043f92",
"content-hash": "1c4001e831e2129cc09124c228198ef2",
"packages": [
{
"name": "akuechler/laravel-geoly",
@@ -5400,6 +5400,67 @@
],
"time": "2023-01-19T13:22:14+00:00"
},
{
"name": "paragonie/ciphersweet",
"version": "v4.2.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/ciphersweet.git",
"reference": "7459af64c412453ffa8813518c44292a9742c326"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/ciphersweet/zipball/7459af64c412453ffa8813518c44292a9742c326",
"reference": "7459af64c412453ffa8813518c44292a9742c326",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-openssl": "*",
"paragonie/constant_time_encoding": "^2",
"paragonie/sodium_compat": ">= 1.17 <2",
"php": "^8.1"
},
"require-dev": {
"phpunit/phpunit": "^9",
"vimeo/psalm": "^4"
},
"type": "library",
"autoload": {
"psr-4": {
"ParagonIE\\CipherSweet\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com"
}
],
"description": "Searchable field-level encryption library for relational databases",
"keywords": [
"FIPS 140-2",
"SQL encryption",
"crm",
"cryptography",
"database encryption",
"encrypt",
"encryption",
"field-level encryption",
"libsodium",
"queryable encryption",
"searchable encryption"
],
"support": {
"issues": "https://github.com/paragonie/ciphersweet/issues",
"source": "https://github.com/paragonie/ciphersweet/tree/v4.2.0"
},
"time": "2023-01-15T19:02:28+00:00"
},
{
"name": "paragonie/constant_time_encoding",
"version": "v2.6.3",
@@ -8259,6 +8320,78 @@
},
"time": "2021-12-21T10:08:05+00:00"
},
{
"name": "spatie/laravel-ciphersweet",
"version": "1.0.4",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-ciphersweet.git",
"reference": "cc336648b94f88e9d0fd4be11c14e61e2f5882e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-ciphersweet/zipball/cc336648b94f88e9d0fd4be11c14e61e2f5882e0",
"reference": "cc336648b94f88e9d0fd4be11c14e61e2f5882e0",
"shasum": ""
},
"require": {
"illuminate/contracts": "^9.19|^10.0",
"paragonie/ciphersweet": "^4.0.1",
"php": "^8.1",
"spatie/laravel-package-tools": "^1.12.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.8",
"nunomaduro/collision": "^6.0",
"nunomaduro/larastan": "^2.0.1",
"orchestra/testbench": "^7.0|^8.0",
"pestphp/pest": "^1.21",
"pestphp/pest-plugin-laravel": "^1.1",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5",
"spatie/laravel-ray": "^1.26"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Spatie\\LaravelCipherSweet\\LaravelCipherSweetServiceProvider"
],
"aliases": {
"LaravelCipherSweet": "Spatie\\LaravelCipherSweet\\Facades\\LaravelCipherSweet"
}
}
},
"autoload": {
"psr-4": {
"Spatie\\LaravelCipherSweet\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rias Van der Veken",
"email": "rias@spatie.be",
"role": "Developer"
}
],
"description": "Use ciphersweet in your Laravel project",
"homepage": "https://github.com/spatie/laravel-ciphersweet",
"keywords": [
"laravel",
"laravel-ciphersweet",
"spatie"
],
"support": {
"source": "https://github.com/spatie/laravel-ciphersweet/tree/1.0.4"
},
"time": "2023-01-26T12:33:48+00:00"
},
{
"name": "spatie/laravel-comments",
"version": "1.4.3",

36
config/ciphersweet.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
return [
/**
* This controls which cryptographic backend will be used by CipherSweet.
* Unless you have specific compliance requirements, you should choose
* "nacl".
*
* Supported: "boring", "fips", "nacl"
*/
'backend' => env('CIPHERSWEET_BACKEND', 'nacl'),
/**
* Select which key provider your application will use. The default option
* is to read a string literal out of .env, but it's also possible to
* provide the key in a file or use random keys for testing.
*
* Supported: "file", "random", "string"
*/
'provider' => env('CIPHERSWEET_PROVIDER', 'string'),
/**
* Set provider-specific options here. "string" will read the key directly
* from your .env file. "file" will read the contents of the specified file
* to use as your key. "custom" points to a factory class that returns a
* provider from its `__invoke` method. Please see the docs for more details.
*/
'providers' => [
'file' => [
'path' => env('CIPHERSWEET_FILE_PATH'),
],
'string' => [
'key' => env('CIPHERSWEET_KEY'),
],
],
];

View File

@@ -0,0 +1,20 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('blind_indexes', function (Blueprint $table) {
$table->morphs('indexable');
$table->string('name');
$table->string('value');
$table->index(['name', 'value']);
$table->unique(['indexable_type', 'indexable_id', 'name']);
});
}
};

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->text('public_key')->nullable()->change();
$table->text('email')->nullable()->change();
$table->text('node_id')->nullable()->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
//
});
}
};

View File

@@ -0,0 +1,18 @@
<!doctype html>
<title>Site Maintenance</title>
<style>
body { text-align: center; padding: 150px; }
h1 { font-size: 50px; }
body { font: 20px Helvetica, sans-serif; color: #333; }
article { display: block; text-align: left; width: 650px; margin: 0 auto; }
a { color: #dc8100; text-decoration: none; }
a:hover { color: #333; text-decoration: none; }
</style>
<article>
<h1>We&rsquo;ll be back soon!</h1>
<div>
<p>Sorry for the inconvenience but we&rsquo;re performing some maintenance at the moment. If you need to you can always <a href="https://t.me/HolgerHatGarKeineNode">contact us</a>, otherwise we&rsquo;ll be back online shortly!</p>
<p>&mdash; Einundzwanzig Team</p>
</div>
</article>

View File

@@ -57,13 +57,21 @@
@endif
</div>
</div>
@php
$address = match(true) {
$pleb->lightning_address !== '' => $pleb->lightning_address,
$pleb->lnurl !== '' => $pleb->lnurl,
$pleb->node_id !== '' => $pleb->node_id,
default => null,
};
@endphp
<div x-show="show">
@if($pleb->lightning_address || $pleb->lnurl || $pleb->node_id)
@if($address)
<div wire:ignore>
<lightning-widget
name="{{ $pleb->name }}"
accent="#f7931a"
to="{{ $pleb->lightning_address ?? $pleb->lnurl ?? $pleb->node_id }}"
to="{{ $address }}"
image="{{ $pleb->profile_photo_url }}"
amounts="21,210,2100,21000"
/>

View File

@@ -34,7 +34,8 @@ Route::middleware([])
->group(function () {
Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class);
Route::get('meetups', function () {
return \App\Models\Meetup::with([
return \App\Models\Meetup::query()
->with([
'city',
])
->get()
@@ -46,8 +47,8 @@ Route::middleware([])
'country' => str($meetup->city->country->code)->upper(),
'state' => $meetup->github_data['state'] ?? null,
'city' => $meetup->city->name,
'longitude' => (float)$meetup->city->longitude,
'latitude' => (float)$meetup->city->latitude,
'longitude' => (float) $meetup->city->longitude,
'latitude' => (float) $meetup->city->latitude,
'twitter_username' => $meetup->twitter_username,
'website' => $meetup->webpage,
]);
@@ -57,7 +58,7 @@ Route::middleware([])
Route::get('/lnurl-auth-callback', function (\Illuminate\Http\Request $request) {
if (lnurl\auth($request->k1, $request->sig, $request->key)) {
// find User by $wallet_public_key
$user = User::where('public_key', $request->key)
$user = User::query()->whereBlind('public_key', 'public_key_index', $request->key)
->first();
if (!$user) {
// create User