Class: Saro::Dat::Dat

Inherits:
Object
  • Object
show all
Defined in:
lib/saro/dat/dat.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dat_str) ⇒ Dat

Returns a new instance of Dat.



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
# File 'lib/saro/dat/dat.rb', line 18

def initialize(dat_str)
  @dat = dat_str || ''
  @format = false
  @expire = 0
  @cid = 0
  @plain = "".b
  @secure = "".b
  @signature = "".b
  @error = nil

  if @dat.empty?
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::TOKEN_MALFORMED, "token is empty")
    return
  end

  # 1) 먼저 구조를 확정한다. 파트가 5개가 아니면 그건 만료된 토큰이 아니라
  #    애초에 토큰이 아니다.
  #    split 의 limit 을 -1 로 준다: 기본값은 뒤쪽 빈 필드를 버려서
  #    "a.b.c.d.e." (6필드) 가 5파트로 보였고, 빈 서명("a.b.c.d.")은
  #    4파트로 보여 서명 오류를 구조 오류로 오인하게 만들었다.
  parts = @dat.split('.', -1)
  if parts.length != 5
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::TOKEN_MALFORMED, "expected exactly 5 dot-separated fields")
    return
  end

  # 2) 구조가 맞은 뒤에야 값을 본다. 필드마다 어디서 틀렸는지 코드를 붙인다.
  begin
    @expire = Saro::Dat::Util.parse_u64(parts[0])
  rescue Saro::Dat::Error => e
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::TOKEN_MALFORMED, "expire field is not a plain decimal u64", cause: e)
    return
  end

  begin
    @cid = Saro::Dat::Util.parse_u64_hex(parts[1])
  rescue Saro::Dat::Error => e
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::TOKEN_MALFORMED, "cid field is not a plain hex u64", cause: e)
    return
  end

  begin
    @plain = Saro::Dat::Util.decode_base64_url(parts[2])
  rescue Saro::Dat::Error => e
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::TOKEN_MALFORMED, "plain field is not base64url", cause: e)
    return
  end

  begin
    @secure = Saro::Dat::Util.decode_base64_url(parts[3])
  rescue Saro::Dat::Error => e
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::TOKEN_MALFORMED, "secure field is not base64url", cause: e)
    return
  end

  # 빈 서명은 구조 오류가 아니라 서명 오류다 (error.pre2.md: DAT_SIG_MALFORMED
  # 가 "빈 서명"을 포함한다). 위조(SIG_MISMATCH)와도 구분된다.
  if parts[4].empty?
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::SIG_MALFORMED, "signature field is empty")
    return
  end

  begin
    @signature = Saro::Dat::Util.decode_base64_url(parts[4])
  rescue Saro::Dat::Error => e
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::SIG_MALFORMED, "signature field is not base64url", cause: e)
    return
  end

  if @signature.empty?
    @error = Saro::Dat::Error.new(Saro::Dat::ErrorCode::SIG_MALFORMED, "signature field is empty")
    return
  end

  @format = true
end

Instance Attribute Details

#cidObject (readonly)

Returns the value of attribute cid.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def cid
  @cid
end

#datObject (readonly)

Returns the value of attribute dat.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def dat
  @dat
end

#errorObject (readonly)

파싱이 실패한 이유. 성공이면 nil 이다.

예전에는 빈 rescue StandardError 가 모든 실패를 삼키고 @format=false 하나만 남겼다. 어느 필드가 왜 틀렸는지가 전부 사라져 호출부는 "Invalid DAT: Format" 밖에 볼 수 없었다.



16
17
18
# File 'lib/saro/dat/dat.rb', line 16

def error
  @error
end

#expireObject (readonly)

Returns the value of attribute expire.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def expire
  @expire
end

#formatObject (readonly)

Returns the value of attribute format.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def format
  @format
end

#plainObject (readonly)

Returns the value of attribute plain.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def plain
  @plain
end

#secureObject (readonly)

Returns the value of attribute secure.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def secure
  @secure
end

#signatureObject (readonly)

Returns the value of attribute signature.



9
10
11
# File 'lib/saro/dat/dat.rb', line 9

def signature
  @signature
end

Class Method Details

.from_value(value) ⇒ Object



101
102
103
104
# File 'lib/saro/dat/dat.rb', line 101

def self.from_value(value)
  return value if value.is_a?(Dat)
  new(value)
end

Instance Method Details

#body_stringObject



113
114
115
116
117
# File 'lib/saro/dat/dat.rb', line 113

def body_string
  idx = @dat.rindex('.')
  return "" unless idx
  @dat[0, idx]
end

#expiredObject Also known as: expired?



106
107
108
109
# File 'lib/saro/dat/dat.rb', line 106

def expired
  return true unless @format
  Time.now.to_i >= @expire
end

#raise_if_invalid!Object

파싱에 실패했으면 그 코드로 던진다.

Raises:



96
97
98
99
# File 'lib/saro/dat/dat.rb', line 96

def raise_if_invalid!
  raise @error if @error
  nil
end