0

I am trying to generate a URL which can restrict the number of downloads to a certain number as entered in the input count_url as well as the link/URL should expire after certain time (maybe 1 or 2 mins)

For the temporary URL when I used (temporarySignedRoute) it works fine. To control the number of clicks on the link, I have written some code (basically a collection from different places as I am very new to Laravel and programming) which surprisingly works if the devtools are open and update the database on each click. Soon you hit the max number it says you have exceeded the limit! Good.

But very annoyingly, when you close the devtools it doesn’t work, only updates the database for the first time after that it let the file download but doesn’t update the database hence doesn’t put the brakes on and one can download unlimited. The logic is very simple and just of few lines if someone can help me out of it, I shall be very grateful!

I want this to work with/without devtools opened.

On refresh/back button, it shouldn’t update the (temporarySignedRoute), rather the link/url should stay there same forever or until someone close the page.

---- index.blade.php ----

<a href="{{ route('models.create') }}" class="btn btn-primary">Add new Models ss</a>
<br />
<table style="width:100%">                
    <tr>
        <th scope="col">Title</th>
        <th scope="col">Image</th>
        <th scope="col">No. of minutes</th>
        <th scope="col">Download file</th>
    </tr>
    @forelse($canaanmodels as $canaanmodel)
    <tr>
        <td >{{ $canaanmodel->title }}</td>
        <td > <img src= "canaanmodels/{{ $canaanmodel->img_name }}" class="img" height="80" width="100"> </td>
        <!-- <td> {{ $canaanmodel->photo ? $canaanmodel->photo->file : "image not found" }} </td> -->
        <td halign="bottom">
            <?php
            $user = Auth::user();
            $path_email = route('models.download', $canaanmodel->uuid);                                          
            ?>
            <form action='/display_links' method=post >
                @csrf

                <input name=uuid type=hidden value="{{$canaanmodel->uuid}}">
                <input name="link_to_email" value="{{$path_email}}" type="hidden">
                <input class="num_input" type=number name=count_url min=1 max=5 required>
                <input class="sub_input" type=submit value = "Download Link" class="btn btn-primary" style="float: right">
            </form>   
            <form action='/payment' method=post>
                @csrf

                <input name=uuid type=hidden value="{{$canaanmodel->uuid}}">
                <input name="link_to_email" value="{{$path_email}}" type="hidden">
                <input type=submit value = " BUY ME" class="btn btn-primary" style="float: right;">
            </form>
            <form action='/home' method=get>
                @csrf        
                <input type=submit value = " BUY ME" class="btn btn-primary" style="float: right;">
            </form>
        </td>   
    </tr>
    @empty
    <tr>
        <td colspan="2">No Models found.</td>
    </tr>
@endforelse
</table> 

----shop.blade.php----

<body>
    <button id="{{ $temp_url }}" name= "{{ $count }}" onclick="refresh_page(this.id, this.name)" target="_blank">
      Download
    </button>
     <script>
      function refresh_page(val,nam) {
          if (document.getElementById(val).style.color != "red")
            {
              location.href=(val);
              document.getElementById(val).style.color = "red";
            } else if (document.getElementById(val).style.color == "red"){
              location.href=(val);
              document.getElementById(val).style.color = "green";
      } 
    </script>

---- Routes ----

Route::resource('/models', 'CanaanController');
Auth::routes();
Route::get('/models/{uuid}/download', 'CanaanController@download')->name('models.download')->middleware('signed');
Route::post('display_links', 'CanaanController@display_link');

---- CanaanController ----

public function index() {
        $canaanmodels = Canaanmodel::all();
        return view('canaanmodels.index', compact('canaanmodels'));
    } 
    public function create() {
        return view('canaanmodels.create');
    }
    public function store(Request $request) {
        $canaanmodel = $request->all();
        $canaanmodel['uuid'] = (string)Uuid::generate();
        if ($request->hasFile('cover')) {
            $canaanmodel['cover'] = $request->cover->getClientOriginalName();
            $request->cover->storeAs('canaanmodels', $canaanmodel['cover']);
        }
        Canaanmodel::create($canaanmodel);
        return redirect()->route('models.index');
    }
    public function download($uuid, Request $request) {
            if (! $request->hasValidSignature()) {
                echo "URL expired";
         }
        else {
            $canaanmodel = Canaanmodel::where('uuid', $uuid)->firstOrFail();
            $user = Auth::user();
            $count = $user->download_count;
            $pathToFile = storage_path('app/canaanmodels/' .$canaanmodel->cover);
            if($count != 0) {
                $count = $count - 1;
                \DB::table('users')->where('email', $user->email)->update(['download_count'=>$count]);
                return response()->download($pathToFile); 
            }
            else{
                 echo "You exceeded your limit";
            }
        }   
    }

    public function display_link(Request $request) {
        $count = Input::get('count_url');
        $user = Auth::user();
        $myFlag = $user->flag;
        \DB::table('users')->where('email', $user->email)->update(['download_count'=>$count, 'flag'=> $count]);
        $tempUrl= URL::temporarySignedRoute('models.download',now()->addMinutes(1), ['uuid' => $request->uuid]); 
        return view('shop',['temp_url' => $tempUrl, 'requesty' => $request, 'count' => $count]);
    }

What I am trying to achieve is to restrict the number of downloads to a certain number as entered in the count_url input. Once it’s done then I shall try to get it done with admin/user point of view, where a user/customer can buy files and the admin can allow the customer/user to download that file for a certain period of time as well as certain number of downloads.

I am using mysql (using xampp) and have stored files into the storage/app/canaanmodels folders and have used webpatser/laravel-uuid package to generate uuid to hide the actual ID. And the rest is very simple coding, I am sharing router/controller/views code and happy to share more!

Many thanks in advance!

zaffar
  • 679
  • 6
  • 13
  • ` location.href=(val);` when clicked from the page may be causing your browser to reload a cached version of the page. https://stackoverflow.com/questions/14197276/how-can-i-force-window-location-to-make-an-http-request-instead-of-using-the-cac https://stackoverflow.com/questions/40629171/window-location-href-works-only-after-clearing-browser-cache-on-ie – jnadon Oct 11 '19 at 16:50
  • 1
    Yes your browser is caching, dev tools disables the cache – squareborg Oct 11 '19 at 16:52
  • This is not the answer to my question. ` location.href=(val) + (new Date()).getTime();` invalids the link, as I am using a temporarySignedUrl as well. Any other suggestion solutions please! Stuck here for a week or so .... – zaffar Oct 14 '19 at 12:20

1 Answers1

0

1) I just needed to tell my download function in the controller do not cache it by setting the headers, used the following code for this:

$headers =[
            'Content-Type' => 'application/text',
            'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
            'Cache-Control' => 'post-check=0, pre-check=0, false',
             'Pragma' => 'no-cache',                               ];
return response()->file($pathToFile, $headers);

2) To sort out the issue regeneration of temp url on refresh/reload, I stored that link first into the database (mysql) and then served it from there. Thanks to everyone who did or tried to help me.

The very same solutions goes for the PhP as well.

Cheers.

zaffar
  • 679
  • 6
  • 13