mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig-portal.git
synced 2025-12-11 06:46:47 +00:00
encrypt user data
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
135
composer.lock
generated
@@ -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
36
config/ciphersweet.php
Normal 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'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -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']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
18
resources/views/errors/503.blade.php
Normal file
18
resources/views/errors/503.blade.php
Normal 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’ll be back soon!</h1>
|
||||||
|
<div>
|
||||||
|
<p>Sorry for the inconvenience but we’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’ll be back online shortly!</p>
|
||||||
|
<p>— Einundzwanzig Team</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
@@ -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"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user