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 QCod\Gamify\Gamify;
use Spatie\Comments\Models\Concerns\InteractsWithComments; use Spatie\Comments\Models\Concerns\InteractsWithComments;
use Spatie\Comments\Models\Concerns\Interfaces\CanComment; use Spatie\Comments\Models\Concerns\Interfaces\CanComment;
use Spatie\LaravelCipherSweet\Concerns\UsesCipherSweet;
use Spatie\LaravelCipherSweet\Contracts\CipherSweetEncrypted;
use Spatie\Permission\Traits\HasRoles; 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 HasApiTokens;
use HasFactory; use HasFactory;
use HasProfilePhoto; use HasProfilePhoto;
@@ -56,6 +61,21 @@ class User extends Authenticatable implements MustVerifyEmail, CanComment
'profile_photo_url', '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() public function orangePills()
{ {
return $this->hasMany(OrangePill::class); return $this->hasMany(OrangePill::class);

View File

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

View File

@@ -9,14 +9,17 @@ use App\Actions\Jetstream\DeleteUser;
use App\Actions\Jetstream\InviteTeamMember; use App\Actions\Jetstream\InviteTeamMember;
use App\Actions\Jetstream\RemoveTeamMember; use App\Actions\Jetstream\RemoveTeamMember;
use App\Actions\Jetstream\UpdateTeamName; use App\Actions\Jetstream\UpdateTeamName;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;
use Laravel\Jetstream\Jetstream; use Laravel\Jetstream\Jetstream;
class JetstreamServiceProvider extends ServiceProvider class JetstreamServiceProvider extends ServiceProvider
{ {
/** /**
* Register any application services. * Register any application services.
*
* @return void * @return void
*/ */
public function register() public function register()
@@ -26,7 +29,6 @@ class JetstreamServiceProvider extends ServiceProvider
/** /**
* Bootstrap any application services. * Bootstrap any application services.
*
* @return void * @return void
*/ */
public function boot() public function boot()
@@ -40,11 +42,22 @@ class JetstreamServiceProvider extends ServiceProvider
Jetstream::removeTeamMembersUsing(RemoveTeamMember::class); Jetstream::removeTeamMembersUsing(RemoveTeamMember::class);
Jetstream::deleteTeamsUsing(DeleteTeam::class); Jetstream::deleteTeamsUsing(DeleteTeam::class);
Jetstream::deleteUsersUsing(DeleteUser::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. * Configure the roles and permissions that are available within the application.
*
* @return void * @return void
*/ */
protected function configurePermissions() protected function configurePermissions()
@@ -56,12 +69,14 @@ class JetstreamServiceProvider extends ServiceProvider
'read', 'read',
'update', 'update',
'delete', 'delete',
])->description('Administrator users can perform any action.'); ])
->description('Administrator users can perform any action.');
Jetstream::role('editor', 'Editor', [ Jetstream::role('editor', 'Editor', [
'read', 'read',
'create', 'create',
'update', '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", "simplito/elliptic-php": "^1.0",
"spatie/eloquent-sortable": "^4.0", "spatie/eloquent-sortable": "^4.0",
"spatie/icalendar-generator": "^2.5", "spatie/icalendar-generator": "^2.5",
"spatie/laravel-ciphersweet": "^1.0",
"spatie/laravel-comments": "^1.4", "spatie/laravel-comments": "^1.4",
"spatie/laravel-comments-livewire": "^1.2", "spatie/laravel-comments-livewire": "^1.2",
"spatie/laravel-google-fonts": "^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", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "de6fecaf71d0b9f0abef4ce825043f92", "content-hash": "1c4001e831e2129cc09124c228198ef2",
"packages": [ "packages": [
{ {
"name": "akuechler/laravel-geoly", "name": "akuechler/laravel-geoly",
@@ -5400,6 +5400,67 @@
], ],
"time": "2023-01-19T13:22:14+00:00" "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", "name": "paragonie/constant_time_encoding",
"version": "v2.6.3", "version": "v2.6.3",
@@ -8259,6 +8320,78 @@
}, },
"time": "2021-12-21T10:08:05+00:00" "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", "name": "spatie/laravel-comments",
"version": "1.4.3", "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 @endif
</div> </div>
</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"> <div x-show="show">
@if($pleb->lightning_address || $pleb->lnurl || $pleb->node_id) @if($address)
<div wire:ignore> <div wire:ignore>
<lightning-widget <lightning-widget
name="{{ $pleb->name }}" name="{{ $pleb->name }}"
accent="#f7931a" accent="#f7931a"
to="{{ $pleb->lightning_address ?? $pleb->lnurl ?? $pleb->node_id }}" to="{{ $address }}"
image="{{ $pleb->profile_photo_url }}" image="{{ $pleb->profile_photo_url }}"
amounts="21,210,2100,21000" amounts="21,210,2100,21000"
/> />

View File

@@ -34,7 +34,8 @@ Route::middleware([])
->group(function () { ->group(function () {
Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class); Route::resource('languages', \App\Http\Controllers\Api\LanguageController::class);
Route::get('meetups', function () { Route::get('meetups', function () {
return \App\Models\Meetup::with([ return \App\Models\Meetup::query()
->with([
'city', 'city',
]) ])
->get() ->get()
@@ -57,7 +58,7 @@ Route::middleware([])
Route::get('/lnurl-auth-callback', function (\Illuminate\Http\Request $request) { Route::get('/lnurl-auth-callback', function (\Illuminate\Http\Request $request) {
if (lnurl\auth($request->k1, $request->sig, $request->key)) { if (lnurl\auth($request->k1, $request->sig, $request->key)) {
// find User by $wallet_public_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(); ->first();
if (!$user) { if (!$user) {
// create User // create User