Skip to content

Commit

Permalink
chore: finish mercure setup
Browse files Browse the repository at this point in the history
  • Loading branch information
jesusantguerrero committed Dec 22, 2023
1 parent e69f77a commit 616c689
Show file tree
Hide file tree
Showing 14 changed files with 188 additions and 58 deletions.
18 changes: 16 additions & 2 deletions Caddyfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
frankenphp
order mercure after encode
order php_server before file_server
{$GLOBAL_OPTIONS}
}

# The domain name of your server
Expand All @@ -12,9 +14,21 @@ dev-loger.neatlancer.com {
}

mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt://mercure.db}
# Publisher JWT key
publisher_jwt !ChangeThisMercureHubJWTSecretKey!
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt !ChangeThisMercureHubJWTSecretKey!
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
# Permissive configuration for the development environment
cors_origins *
publish_origins *
demo
anonymous
subscriptions
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}

{$CADDY_SERVER_EXTRA_DIRECTIVES}
}
21 changes: 21 additions & 0 deletions Caddyfile.dev
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
frankenphp
order mercure after encode
order php_server before file_server
{$GLOBAL_OPTIONS}
}

# The domain name of your server
Expand All @@ -14,4 +16,23 @@ localhost {
# Required for the public/storage/ dir
resolve_root_symlink
}

mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt://mercure.db}
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY}
# Permissive configuration for the development environment
cors_origins *
publish_origins *
demo
anonymous
subscriptions
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}

{$CADDY_SERVER_EXTRA_DIRECTIVES}
}
22 changes: 15 additions & 7 deletions app/Console/Commands/TestMessaging.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

namespace App\Console\Commands;

use Exception;
use App\Models\UserDevice;
use App\Services\MessagingService;
use Illuminate\Console\Command;
use App\Events\BudgetCalculated;
use App\Services\MessagingService;

class TestMessaging extends Command
{
Expand All @@ -27,11 +29,17 @@ class TestMessaging extends Command
*/
public function handle()
{
$service = new MessagingService();
$userDevice = UserDevice::find(3);
$service->occurrenceType([
'title' => 'test',
], $userDevice->device_id);
echo $userDevice->device_id;
// $service = new MessagingService();
// $userDevice = UserDevice::find(3);
// $service->occurrenceType([
// 'title' => 'test',
// ], $userDevice->device_id);
// echo $userDevice->device_id;
try {
broadcast( new BudgetCalculated());
} catch (Exception $e) {
dd($e);
}
echo "Done";
}
}
40 changes: 22 additions & 18 deletions app/Events/BudgetCalculated.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,39 @@

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use App\Models\User;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Duijker\LaravelMercureBroadcaster\Broadcasting\Channel;

class BudgetCalculated implements ShouldBroadcast
class BudgetCalculated implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
use SerializesModels;
public User $user;

/**
* Create a new event instance.
*/
public function __construct()
public function __construct(string $message = "Hello world")
{
//
$this->user= User::all()->first();
}

/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('http://example/budget-calculated'),
new Channel('https://example.com/main', false),
];
}

/**
* Get the data to broadcast.
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return [
'message' => "{$this->user->name} Are you not entertained?"
];
}
}
3 changes: 3 additions & 0 deletions app/Http/Controllers/Finance/FinanceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Carbon\Carbon;
use App\Models\Setting;
use Illuminate\Http\Request;
use App\Events\BudgetCalculated;
use Laravel\Jetstream\Jetstream;
use Freesgen\Atmosphere\Http\Querify;
use App\Domains\Budget\Models\BudgetMonth;
Expand Down Expand Up @@ -51,6 +52,8 @@ public function index(Request $request)
$savings = BudgetMonthService::getSavingsBalance($teamId, $endDate);
$savingsInMonth = BudgetMonthService::getSavingsBalance($teamId, $endDate, $startDate);

BudgetCalculated::dispatch();

return Jetstream::inertia()->render($request, 'Finance/Index', [
'sectionTitle' => 'Finance',
'planned' => $this->plannedService->getPlanned($teamId),
Expand Down
2 changes: 2 additions & 0 deletions app/Http/Controllers/System/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers\System;

use Inertia\Inertia;
use App\Events\BudgetCalculated;
use App\Domains\Budget\Models\BudgetMonth;
use App\Domains\Housing\Models\Occurrence;
use App\Domains\Meal\Services\MealService;
Expand Down Expand Up @@ -33,6 +34,7 @@ public function __invoke()
$plannedMeals = $this->mealService->getMealSchedule($teamId);
$nextPayments = $this->budgetTargetService->getNextBudgetItems($teamId);


return inertia('Dashboard', [
'sectionTitle' => 'Dashboard',
'meals' => PlannedMealResource::collection($plannedMeals),
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Middleware/EncryptCookies.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ class EncryptCookies extends Middleware
* @var array
*/
protected $except = [
//
'mercureAuthorization'
];
}
55 changes: 55 additions & 0 deletions app/Http/Middleware/MercureBroarcasterAuthorizationCookie.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Illuminate\Support\Facades\Cookie;

class MercureBroadcasterAuthorizationCookie
{
public function handle(Request $request, Closure $next)
{
/** @var Response $response */
$response = $next($request);

if (!method_exists($response, 'withCookie')) {
return $response;
}

return $response->withCookie($this->createCookie($request->user(), $request->secure()));
}

private function createCookie($user, bool $secure)
{
// Add topic(s) this user has access to
// This can also be URI Templates (to match several topics), or * (to match all topics)
$subscriptions = [
"http://example/user/{$user->id}/direct-messages",
];

$jwtConfiguration = Configuration::forSymmetricSigner(
new Sha256(),
InMemory::plainText(config('broadcasting.connections.mercure.secret'))
);

$token = $jwtConfiguration->builder()
->withClaim('mercure', ['subscribe' => $subscriptions])
->getToken($jwtConfiguration->signer(), $jwtConfiguration->signingKey())
->toString();

return Cookie::make(
'mercureAuthorization',
$token,
15,
'/.well-known/mercure', // or which path you have mercure running
parse_url(config('app.url'), PHP_URL_HOST),
$secure,
true
);
}
}
7 changes: 7 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ export {}

declare module 'vue' {
export interface GlobalComponents {
IFluentFoodApple20Filled: typeof import('~icons/fluent/food-apple20-filled')['default']
IMaterialSymbolsBrightnessAlertOutlineRounded: typeof import('~icons/material-symbols/brightness-alert-outline-rounded')['default']
IMdiBankTransfer: typeof import('~icons/mdi/bank-transfer')['default']
IMdiBankTransferIn: typeof import('~icons/mdi/bank-transfer-in')['default']
IMdiBankTransferOut: typeof import('~icons/mdi/bank-transfer-out')['default']
IMdiCallSplit: typeof import('~icons/mdi/call-split')['default']
IMdiEdit: typeof import('~icons/mdi/edit')['default']
IMdiEllipsisVertical: typeof import('~icons/mdi/ellipsis-vertical')['default']
IMdiFile: typeof import('~icons/mdi/file')['default']
IMdiLink: typeof import('~icons/mdi/link')['default']
IMdiLock: typeof import('~icons/mdi/lock')['default']
IMdiMinus: typeof import('~icons/mdi/minus')['default']
IMdiPlus: typeof import('~icons/mdi/plus')['default']
IMdiStar: typeof import('~icons/mdi/star')['default']
IMdiStarOutline: typeof import('~icons/mdi/star-outline')['default']
IMdiSync: typeof import('~icons/mdi/sync')['default']
Expand Down
2 changes: 1 addition & 1 deletion config/broadcasting.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
*/

'connections' => [

'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
Expand Down Expand Up @@ -63,6 +62,7 @@
'driver' => 'mercure',
'url' => env('MERCURE_URL', 'http://localhost:3000/.well-known/mercure'),
'secret' => env('MERCURE_SECRET', 'aVerySecretKey'),
'publisher_key' => env('MERCURE_PUBLISHER_JWT_KEY')
],
],

Expand Down
10 changes: 10 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ services:
- ./Caddyfile.dev:/etc/caddy/Caddyfile
- ./docker-compose/web/timezone:/etc/timezone
- loger_db:/var/lib/mysql
environment:
DEBUG: "debug"
# Change the following value if you know how it works.
# MERCURE_TRANSPORT_URL: "bolt://mercure.db"
MERCURE_PUBLISHER_JWT_KEY: "${MERCURE_PUBLISHER_JWT_KEY}"
MERCURE_SUBSCRIBER_JWT_KEY: "${MERCURE_SUBSCRIBER_JWT_KEY}"
# In the cors_origin, add your domain(s). Or just use *
MERCURE_EXTRA_DIRECTIVES: |-
cors_origins "*"
anonymous
networks:
- loger
depends_on:
Expand Down
Binary file added mercure.db
Binary file not shown.
60 changes: 32 additions & 28 deletions resources/js/Components/templates/AppGlobals.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,4 @@
<template>
<TransactionModal
v-model:show="isOpen"
v-bind="transactionModalState"
:max-width="modalMaxWidth"
:full-height="context.isMobile"
@saved="onTransactionSaved"
@close="onTransactionSaved"
/>

<MoreOptionsModal
v-model:show="context.isMoreOptionsModalOpen"
:max-width="modalMaxWidth"
v-if="context.isMobile"
/>

<ImportResourceModal v-model:show="isImportModalOpen" />
</template>

<script setup>
<script setup lang="ts">
import TransactionModal from "@/domains/transactions/components/TransactionModal.vue";
import { useTransactionModal, transactionModalState } from "@/domains/transactions";
import { useImportModal } from "@/domains/transactions/useImportModal";
Expand All @@ -26,12 +7,13 @@ import { useAppContextStore } from "@/store";
import { computed } from "vue";
import { router } from "@inertiajs/vue3";
import MoreOptionsModal from "../MoreOptionsModal.vue";
import { config } from "@/config/index";
const { isOpen, closeTransactionModal } = useTransactionModal();
const onTransactionSaved = () => {
debugger
router.reload();
closeTransactionModal();
debugger;
router.reload();
closeTransactionModal();
};
const context = useAppContextStore();
const modalMaxWidth = computed(() => {
Expand All @@ -40,9 +22,31 @@ const modalMaxWidth = computed(() => {
const { isOpen: isImportModalOpen } = useImportModal();
var es = new EventSource('http://localhost:3000/.well-known/mercure?topic=' + encodeURIComponent('http://example/budget-calculated'));
es.addEventListener('message', (messageEvent) => {
var eventData = JSON.parse(messageEvent.data);
console.log(eventData);
});
const url = new URL(config.MERCURE_URL);
url.searchParams.append("topic", "https://example.com/main");
url.searchParams.append("topic", "https://example.com/users/jesus");
var es = new EventSource(url);
es.onmessage = (messageEvent) => {
var eventData = JSON.parse(messageEvent.data);
console.log(eventData);
};
</script>

<template>
<TransactionModal
v-model:show="isOpen"
v-bind="transactionModalState"
:max-width="modalMaxWidth"
:full-height="context.isMobile"
@saved="onTransactionSaved"
@close="onTransactionSaved"
/>

<MoreOptionsModal
v-model:show="context.isMoreOptionsModalOpen"
:max-width="modalMaxWidth"
v-if="context.isMobile"
/>

<ImportResourceModal v-model:show="isImportModalOpen" />
</template>
Loading

0 comments on commit 616c689

Please sign in to comment.