Page MenuHomePhorge

D3029.1775317895.diff
No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None

D3029.1775317895.diff

diff --git a/src/app/Http/Controllers/API/V4/CompanionAppsController.php b/src/app/Http/Controllers/API/V4/CompanionAppsController.php
--- a/src/app/Http/Controllers/API/V4/CompanionAppsController.php
+++ b/src/app/Http/Controllers/API/V4/CompanionAppsController.php
@@ -3,8 +3,11 @@
namespace App\Http\Controllers\API\V4;
use App\Http\Controllers\Controller;
+use App\Utils;
+use App\Tenant;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
+use BaconQrCode;
class CompanionAppsController extends Controller
{
@@ -55,4 +58,47 @@
return response()->json(['status' => 'success']);
}
+
+
+ /**
+ * Generate a QR-code image for a contact
+ *
+ * @param array $contact Contact record
+ *
+ * @return string|null Image content, Null on error or missing PHP extensions
+ */
+ public static function generateQRCode($data)
+ {
+ $renderer_style = new BaconQrCode\Renderer\RendererStyle\RendererStyle(300, 1);
+ $renderer_image = new BaconQrCode\Renderer\Image\SvgImageBackEnd();
+ $renderer = new BaconQrCode\Renderer\ImageRenderer($renderer_style, $renderer_image);
+ $writer = new BaconQrCode\Writer($renderer);
+
+ return 'data:image/svg+xml;base64,' . base64_encode($writer->writeString($data));
+ }
+
+ /**
+ * Get the information about the specified companion app.
+ *
+ * @param int $id The Companion App identifier
+ *
+ * @return \Illuminate\Http\JsonResponse|void
+ */
+ public function show($id)
+ {
+ $user = $this->guard()->user();
+
+ $response['qrcode'] = self::generateQRCode(
+ json_encode([
+ "apiEndpoint" => Utils::serviceUrl('', $user->tenant_id),
+ "authorizationEndpoint" => Utils::serviceUrl('/oauth/authorize', $user->tenant_id),
+ "tokenEndpoint" => Utils::serviceUrl('/oauth/token', $user->tenant_id),
+ "clientIdentifier" => \App\Tenant::getConfig($user->tenant_id, 'app.companion_app_identifier'),
+ "clientSecret" => \App\Tenant::getConfig($user->tenant_id, 'app.companion_app_secret'),
+ "username" => $user->email
+ ])
+ );
+
+ return response()->json($response);
+ }
}
diff --git a/src/app/Http/Controllers/API/V4/UsersController.php b/src/app/Http/Controllers/API/V4/UsersController.php
--- a/src/app/Http/Controllers/API/V4/UsersController.php
+++ b/src/app/Http/Controllers/API/V4/UsersController.php
@@ -326,6 +326,7 @@
'enableDistlists' => $isController && $hasCustomDomain && in_array('distlist', $skus),
'enableUsers' => $isController,
'enableWallets' => $isController,
+ 'enableCompanionapps' => $isController,
'process' => $process,
'processState' => $state,
'isReady' => $all === $checked,
diff --git a/src/composer.json b/src/composer.json
--- a/src/composer.json
+++ b/src/composer.json
@@ -15,6 +15,7 @@
],
"require": {
"php": "^7.3",
+ "bacon/bacon-qr-code": "^2.0",
"barryvdh/laravel-dompdf": "^0.8.6",
"doctrine/dbal": "^2.13",
"dyrynda/laravel-nullable-fields": "*",
diff --git a/src/resources/js/user/routes.js b/src/resources/js/user/routes.js
--- a/src/resources/js/user/routes.js
+++ b/src/resources/js/user/routes.js
@@ -3,6 +3,7 @@
import DistlistListComponent from '../../vue/Distlist/List'
import DomainInfoComponent from '../../vue/Domain/Info'
import DomainListComponent from '../../vue/Domain/List'
+import CompanionAppComponent from '../../vue/CompanionApp'
import LoginComponent from '../../vue/Login'
import LogoutComponent from '../../vue/Logout'
import MeetComponent from '../../vue/Rooms'
@@ -39,6 +40,12 @@
component: DistlistListComponent,
meta: { requiresAuth: true, perm: 'distlists' }
},
+ {
+ path: '/companion',
+ name: 'companion',
+ component: CompanionAppComponent,
+ meta: { requiresAuth: true, perm: 'companionapps' }
+ },
{
path: '/domain/:domain',
name: 'domain',
diff --git a/src/resources/vue/CompanionApp.vue b/src/resources/vue/CompanionApp.vue
new file mode 100644
--- /dev/null
+++ b/src/resources/vue/CompanionApp.vue
@@ -0,0 +1,46 @@
+<template>
+ <div class="container" dusk="companionapp-component">
+ <div class="card">
+ <div class="card-body">
+ <div class="card-title">Companion App</div>
+ <div class="card-text">
+ <div class="alert">
+ Connect the companion app for 2fa.
+ </div>
+ <p>
+ <img :src="qrcode" />
+ </p>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+ import { Modal } from 'bootstrap'
+
+ export default {
+ components: {
+ },
+ data() {
+ return {
+ companion: {},
+ qrcode: ""
+ }
+ },
+ mounted() {
+ this.$root.startLoading()
+
+ axios.get('/api/v4/companion/1')
+ .then(response => {
+ this.$root.stopLoading()
+
+ this.companion = response.data
+ this.qrcode = response.data.qrcode
+ })
+ .catch(this.$root.errorHandler)
+ },
+ methods: {
+ },
+ }
+</script>
diff --git a/src/resources/vue/Dashboard.vue b/src/resources/vue/Dashboard.vue
--- a/src/resources/vue/Dashboard.vue
+++ b/src/resources/vue/Dashboard.vue
@@ -26,6 +26,9 @@
<a v-if="webmailURL" class="card link-webmail" :href="webmailURL">
<svg-icon icon="envelope"></svg-icon><span class="name">{{ $t('dashboard.webmail') }}</span>
</a>
+ <router-link v-if="status.enableCompanionapps" class="card link-companionapp" :to="{ name: 'companionapp' }">
+ <svg-icon icon="users"></svg-icon><span class="name">{{ $t('dashboard.companionapp') }}</span>
+ </router-link>
</div>
</div>
</template>
diff --git a/src/routes/api.php b/src/routes/api.php
--- a/src/routes/api.php
+++ b/src/routes/api.php
@@ -103,6 +103,8 @@
Route::get('payments/methods', 'API\V4\PaymentsController@paymentMethods');
Route::get('payments/pending', 'API\V4\PaymentsController@payments');
Route::get('payments/has-pending', 'API\V4\PaymentsController@hasPayments');
+
+ Route::apiResource('companion', API\V4\CompanionAppsController::class);
}
);

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 3:51 PM (2 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18830249
Default Alt Text
D3029.1775317895.diff (6 KB)

Event Timeline