fixed Patch installation (bnc#579034), fixed possible race condition
[opensuse:yast-rest-service.git] / plugins / software / app / controllers / patches_controller.rb
1 require 'singleton'
2
3 class PatchesController < ApplicationController
4
5    before_filter :login_required
6
7    # always check permissions and cache expiration
8    # even if the result is already created and cached
9    before_filter :check_read_permissions, :only => [:index, :show]
10    before_filter :check_cache_status, :only => :index
11
12    # cache 'index' method result
13    caches_action :index
14
15   private
16
17   def check_read_permissions
18     permission_check "org.opensuse.yast.system.patches.read"
19   end
20
21   # check whether the cached result is still valid
22   def check_cache_status
23     cache_timestamp = Rails.cache.read('patches:timestamp')
24
25     if cache_timestamp.nil?
26         # this is the first run, the cache is not initialized yet, just return
27         Rails.cache.write('patches:timestamp', Time.now)
28         return
29     # the cache expires after 5 minutes, repository metadata
30     # or RPM database update invalidates the cache immediately
31     # (new patches might be applicable)
32     elsif cache_timestamp < 15.minutes.ago || cache_timestamp < Patch.mtime
33         logger.debug "#### Patch cache expired"
34         expire_action :action => :index, :format => params["format"]
35         Rails.cache.write('patches:timestamp', Time.now)
36     end
37   end
38
39   public
40
41   # GET /patch_updates
42   # GET /patch_updates.xml
43   def index
44     # note: permission check was performed in :before_filter
45     bgr = params['background']
46     Rails.logger.info "Reading patches in background" if bgr
47
48     @patches = Patch.find(:available, {:background => bgr})
49
50     respond_to do |format|
51       format.xml { render  :xml => @patches.to_xml( :root => "patches", :dasherize => false ) }
52       format.json { render :json => @patches.to_json( :root => "patches", :dasherize => false ) }
53     end
54
55     # do not cache the background progress status
56     # (expire the cache in the next request)
57     if bgr && @patches.first.class == BackgroundStatus
58       Rails.cache.write('patches:timestamp', Time.at(0))
59     end
60   end
61
62   # GET /patch_updates/1
63   # GET /patch_updates/1.xml
64   def show
65     @patch_update = Patch.find(params[:id])
66     if @patch_update.nil?
67       logger.error "Patch: #{params[:id]} not found."
68       render ErrorResult.error(404, 1, "Patch: #{params[:id]} not found.") and return
69     end
70   end
71
72   # PUT /patch_updates/1
73   # PUT /patch_updates/1.xml
74   def update
75     permission_check "org.opensuse.yast.system.patches.install"
76     @patch_update = Patch.find(params[:id])
77     if @patch_update.nil?
78       logger.error "Patch: #{params[:id]} not found."
79       render ErrorResult.error(404, 1, "Patch: #{params[:id]} not found.") and return
80     end
81     unless @patch_update.install
82       render ErrorResult.error(404, 2, "packagekit error") and return
83     end
84     render :show
85   end
86
87   # POST /patch_updates/
88   def create
89     permission_check "org.opensuse.yast.system.patches.install"
90     @patch_update = Patch.find(params[:patches][:resolvable_id].to_s)
91     if @patch_update.nil?
92       logger.error "Patch: #{params[:patches][:resolvable_id]} not found."
93       render ErrorResult.error(404, 1, "Patch: #{params[:patches][:resolvable_id]} not found.") and return
94     end
95     unless Patch.install @patch_update
96       render ErrorResult.error(404, 2, "packagekit error") and return
97     end
98     render :show
99   end
100
101
102 end