Bladeren bron

Initiate the Release Radar

Bubka 2 jaren geleden
bovenliggende
commit
062d809a28

+ 28 - 0
app/Events/ReleaseRadarActivated.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Events;
+
+use Illuminate\Broadcasting\InteractsWithSockets;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+
+class ReleaseRadarActivated
+{
+    use Dispatchable, InteractsWithSockets, SerializesModels;
+
+    /**
+     * @var \App\Models\Group
+     */
+    // public $group;
+
+    /**
+     * Create a new event instance.
+     *
+     * @param  \App\Models\Group  $group
+     * @return void
+     */
+    public function __construct()
+    {
+        // $this->group = $group;
+    }
+}

+ 17 - 0
app/Http/Controllers/SystemController.php

@@ -2,6 +2,9 @@
 
 namespace App\Http\Controllers;
 
+use App\Events\ReleaseRadarActivated;
+use App\Services\ReleaseRadarService;
+use Illuminate\Support\Facades\App;
 use App\Http\Controllers\Controller;
 use App\Facades\Settings;
 use Illuminate\Http\Request;
@@ -48,4 +51,18 @@ class SystemController extends Controller
 
         return response()->json($infos);
     }
+
+
+    /**
+     * Get latest release
+     * 
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function latestRelease(Request $request)
+    {
+        $releaseRadarService = App::make(ReleaseRadarService::class);
+        $release = $releaseRadarService->scanForRelease();
+
+        return response()->json($release);
+    }
 }

+ 35 - 0
app/Listeners/ReleaseRadar.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Listeners;
+
+use App\Events\ReleaseRadarActivated;
+use App\Services\ReleaseRadarService;
+use Illuminate\Support\Facades\App;
+use Illuminate\Support\Facades\Log;
+
+class ReleaseRadar
+{
+    /**
+     * Create the event listener.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * Handle the event.
+     *
+     * @param  \App\Events\ReleaseRadarActivated  $event
+     * @return void
+     */
+    public function handle(ReleaseRadarActivated $event)
+    {
+        Log::info('Release radar activated');
+
+        $releaseRadarService = App::make(ReleaseRadarService::class);
+        $releaseRadarService->scanForNewRelease();
+    }
+}

+ 13 - 4
app/Providers/EventServiceProvider.php

@@ -2,6 +2,12 @@
 
 namespace App\Providers;
 
+use App\Events\GroupDeleting;
+use App\Events\TwoFAccountDeleted;
+use App\Events\ReleaseRadarActivated;
+use App\Listeners\ReleaseRadar;
+use App\Listeners\CleanIconStorage;
+use App\Listeners\DissociateTwofaccountFromGroup;
 use Illuminate\Auth\Events\Registered;
 use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
 use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -17,11 +23,14 @@ class EventServiceProvider extends ServiceProvider
         Registered::class => [
             SendEmailVerificationNotification::class,
         ],
-        'App\Events\TwoFAccountDeleted' => [
-            'App\Listeners\CleanIconStorage',
+        TwoFAccountDeleted::class => [
+            CleanIconStorage::class,
         ],
-        'App\Events\GroupDeleting' => [
-            'App\Listeners\DissociateTwofaccountFromGroup',
+        GroupDeleting::class => [
+            DissociateTwofaccountFromGroup::class,
+        ],
+        ReleaseRadarActivated::class => [
+            ReleaseRadar::class,
         ],
     ];
 

+ 6 - 0
app/Providers/TwoFAuthServiceProvider.php

@@ -4,6 +4,7 @@ namespace App\Providers;
 
 use App\Services\LogoService;
 use App\Services\SettingService;
+use App\Services\ReleaseRadarService;
 use Illuminate\Support\ServiceProvider;
 use Illuminate\Contracts\Support\DeferrableProvider;
 
@@ -23,6 +24,10 @@ class TwoFAuthServiceProvider extends ServiceProvider implements DeferrableProvi
         $this->app->singleton(LogoService::class, function () {
             return new LogoService();
         });
+
+        $this->app->singleton(ReleaseRadarService::class, function () {
+            return new ReleaseRadarService();
+        });
     }
 
     /**
@@ -45,6 +50,7 @@ class TwoFAuthServiceProvider extends ServiceProvider implements DeferrableProvi
     {
         return [
             LogoService::class,
+            LogoSeReleaseRadarServicervice::class,
         ];
     }
 }

+ 58 - 0
app/Services/ReleaseRadarService.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace App\Services;
+
+use App\Facades\Settings;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
+
+class ReleaseRadarService
+{
+    /**
+     * 
+     */
+    public function scanForNewRelease() : void
+    {
+        // Only if the last check is old enough
+        // if ((Settings::get('lastRadarScan') + 604800) < time()) {
+            if ($latestReleaseData = json_decode($this->GetLatestReleaseData()))
+            {
+                if ($latestReleaseData->prerelease == false && $latestReleaseData->draft == false) {
+
+                    Settings::set('lastRadarScan', time());
+                    Settings::set('lastRadarScan', time());
+                }
+            }
+
+            return $latestReleaseData;
+        // }
+
+        // tag_name
+        // prerelease
+        // draft
+    }
+
+
+    /**
+     * Fetch releases on Github
+     * 
+     * @return string|null
+     */
+    protected function GetLatestReleaseData() : string|null
+    {
+        return null;
+        try {
+            $response = Http::retry(3, 100)
+                ->get(config('2fauth.latestReleaseUrl'));
+            
+            if ($response->successful()) {
+                return $response->body();
+            }
+        }
+        catch (\Exception $exception) {
+            Log::error('cannot reach latestReleaseUrl endpoint');
+        }
+
+        return null;
+    }
+}

+ 7 - 1
config/2fauth.php

@@ -4,12 +4,15 @@ return [
 
     /*
     |--------------------------------------------------------------------------
-    | Application Version
+    | Application infos
     |--------------------------------------------------------------------------
     |
     */
 
     'version' => '3.3.3',
+    'repository' => 'https://github.com/Bubka/2FAuth',
+    'latestReleaseUrl' => 'https://api.github.com/repos/Bubka/2FAuth/releases/latest',
+
 
     /*
     |--------------------------------------------------------------------------
@@ -62,6 +65,9 @@ return [
         'useWebauthnAsDefault' => false,
         'useWebauthnOnly' => false,
         'getOfficialIcons' => true,
+        'checkForUpdate' => true,
+        'lastRadarScan' => 0,
+        'latestRelease' => '',
     ],
 
 ];

+ 5 - 0
resources/js/components/FormCheckbox.vue

@@ -23,6 +23,11 @@
                 default: ''
             },
 
+            labelClass: {
+                type: String,
+                default: ''
+            },
+
             fieldName: {
                 type: String,
                 default: '',

+ 46 - 2
resources/js/views/About.vue

@@ -7,9 +7,25 @@
                 {{ $t('commons.2fauth_teaser')}}
             </p>
             <img src="logo.svg" style="height: 32px" alt="2FAuth logo" />
-            <p class="block">
+            <p class="block mb-6">
                 ©Bubka <a class="is-size-7" href="https://github.com/Bubka/2FAuth/blob/master/LICENSE">AGPL-3.0 license</a>
             </p>
+            <div v-if="showUserOptions" class="block">
+                <form>
+                    <form-checkbox 
+                        v-on:checkForUpdate="saveSetting('checkForUpdate', $event)" 
+                        :form="form" 
+                        fieldName="checkForUpdate" 
+                        :label="$t('commons.check_for_update')" 
+                        :help="$t('commons.check_for_update_help')"
+                        labelClass="has-text-weight-normal"
+                    />
+                </form>
+                <button type="button" class="button is-link" @click="getLatestRelease">{{ $t('commons.cancel') }}</button>
+            </div>
+            <h2 class="title is-5 has-text-grey-light">
+                {{ $t('commons.resources') }}
+            </h2>
             <div class="buttons">
                 <a class="button is-dark" href="https://github.com/Bubka/2FAuth">
                     <span class="icon is-small">
@@ -82,12 +98,17 @@
 </template>
 
 <script>
+    import Form from './../components/Form'
+
     export default {
         data() {
             return {
                 infos : null,
                 options : null,
                 showUserOptions: false,
+                form: new Form({
+                    checkForUpdate: null,
+                }),
             }
         },
 
@@ -101,12 +122,35 @@
                     this.showUserOptions = true
                 }
             })
+
+            await this.form.get('/api/v1/settings/checkForUpdate', {returnError: true}).then(response => {
+                if (response.status === 200) {
+                    this.form.fillWithKeyValueObject(response.data)
+                }
+            })
+            .catch(error => {
+                // do nothing
+            })
         },
 
         methods: {
 
-            clipboardSuccessHandler ({ value, event }) {
+            saveSetting(settingName, event) {
+
+                this.axios.put('/api/v1/settings/' + settingName, { value: event }).then(response => {
+                    this.$notify({ type: 'is-success', text: this.$t('settings.forms.setting_saved') })
+                    this.$root.appSettings[response.data.key] = response.data.value
+                })
+            },
 
+            async getLatestRelease() {
+
+                await this.axios.get('latestRelease').then(response => {
+                    console.log(response.data)
+                })
+            },
+
+            clipboardSuccessHandler ({ value, event }) {
                 this.$notify({ type: 'is-success', text: this.$t('commons.copied_to_clipboard') })
             },
 

+ 11 - 0
resources/js/views/Accounts.vue

@@ -431,6 +431,17 @@
                 }
             },
 
+
+            /**
+             * Get a fresh OTP for the provided account
+             */
+            getOTP(accountId) {
+                this.axios.get('api/v1/twofaccounts/' + accountId + '/otp').then(response => {
+                    this.$notify({ type: 'is-success', text: this.$t('commons.copied_to_clipboard')+ ' '+response.data })
+                })
+            },
+
+
             /**
              * Save the account order in db
              */

+ 3 - 0
resources/lang/en/commons.php

@@ -58,6 +58,9 @@ return [
     'ui_icons_by' => 'UI Icons by',
     'logos_by' => 'Logos by',
     'search' => 'Search',
+    'resources' => 'Resources',
+    'check_for_update' => 'Check regularly for new version',
+    'check_for_update_help' => 'Automatically check (once a week) and warn when a new release of 2FAuth is published on Github',
     '2fauth_description' => 'A web app to manage your Two-Factor Authentication (2FA) accounts and generate their security codes',
     'image_of_qrcode_to_scan' => 'Image of a QR code to scan',
 ];

+ 1 - 0
routes/web.php

@@ -59,6 +59,7 @@ Route::get('refresh-csrf', function(){
     return csrf_token();
 });
 Route::get('infos', 'SystemController@infos')->name('system.infos');
+Route::get('latestRelease', 'SystemController@latestRelease')->name('system.latestRelease');
 
 /**
  * Route for the main landing view