summaryrefslogtreecommitdiff
path: root/vendor/gems/couchrest_session_store/lib/couchrest/session/store.rb
blob: 516d5dd5a7bfe763f90c5243dab01fd479041fcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
class CouchRest::Session::Store < ActionDispatch::Session::AbstractStore

  # delegate configure to document
  def self.configure(*args, &block)
    CouchRest::Session::Document.configure *args, &block
  end

  def self.set_options(options)
    @options = options
    if @options[:database]
      CouchRest::Session::Document.use_database @options[:database]
    end
  end

  def initialize(app, options = {})
    super
    self.class.set_options(options)
  end

  def cleanup(rows)
    rows.each do |row|
      doc = CouchRest::Session::Document.fetch(row['id'])
      doc.delete
    end
  end

  def expired
    CouchRest::Session::Document.find_by_expires startkey: 1,
      endkey: Time.now.utc.iso8601
  end

  def never_expiring
    CouchRest::Session::Document.find_by_expires endkey: 1
  end

  private

  def get_session(env, sid)
    if session = fetch_session(sid)
      [sid, session]
    else
      [generate_sid, {}]
    end
  rescue CouchRest::NotFound
    # session data does not exist anymore
    return [sid, {}]
  rescue CouchRest::Unauthorized,
    Errno::EHOSTUNREACH,
    Errno::ECONNREFUSED => e
    # can't connect to couch. We add some status to the session
    # so the app can react. (Display error for example)
    return [sid, {"_status" => {"couch" => "unreachable"}}]
  end

  def set_session(env, sid, session, options)
    raise CouchRest::NotFound if /^_design\/(.*)/ =~ sid
    couchrest_session = build_or_update_doc(sid, session, options)
    couchrest_session.save
    return sid
  # if we can't store the session we just return false.
  rescue CouchRest::Unauthorized,
    Errno::EHOSTUNREACH,
    Errno::ECONNREFUSED => e
    return false
  end

  def destroy_session(env, sid, options)
    doc = secure_get(sid)
    doc.delete
    generate_sid unless options[:drop]
  rescue CouchRest::NotFound
    # already destroyed - we're done.
    generate_sid unless options[:drop]
  end

  def fetch_session(sid)
    return nil unless sid
    couchrest_session = secure_get(sid)
    couchrest_session.to_session unless couchrest_session.expired?
  end

  def build_or_update_doc(sid, session, options)
    CouchRest::Session.build_or_update(sid, session, options)
  end

  # prevent access to design docs
  # this should be prevented on a couch permission level as well.
  # but better be save than sorry.
  def secure_get(sid)
    raise CouchRest::NotFound if /^_design\/(.*)/ =~ sid
    CouchRest::Session.fetch(sid)
  end

end