carabiner 0.0.1 → 0.0.2.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzQ1NTdlZmFiNWU5ZDc2OWM2YWIwNzlhNjMwMGZiYzZiYjA2OGY4Ng==
5
+ data.tar.gz: !binary |-
6
+ NzBkZjEwNDJhNTEyYjM3OTUxOTc5MTcxYmZkMDg2NTE2MzM4MTRjNQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OTc0OGIwYmZiNjA3MzA2ZjRkZGQ4ZWJhMTkxMDRhMGE4NmYyMjU2ZGI0ODMz
10
+ MWQ1NGI5YWJlZDU2Nzc4NThkM2Y2NWEwMDg0ODMxYzM0N2FlZTQ3YzY2ZjM1
11
+ MjUyOWJmNmE1ZTliMWY0ZWJiNzJkMzVmY2JmYzYyMWEyYWNkOGU=
12
+ data.tar.gz: !binary |-
13
+ NGM4YTE2NzViMzVkNTQyZGFiYzFlNjMwYWRkYTI1YTg0MjA2NzRkYThlZGQ5
14
+ Yjc5Yzk1MjFhNGFkNmI1MjExMjhmMmYyNDMyOWIxZTA5ZGNjNWUzZGE3Njkz
15
+ YzY3YjI1OTA5ZTc4OTViMWZmNDMxYjJiYzcwOGQ4OTFmMjIwNTA=
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ .repl_history
3
+ build-*
4
+ build
5
+ xcuserdata
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: objective-c
2
+ install: bundle install
3
+ script: bundle exec rake spec
4
+ before_script:
5
+ - chmod 777 ./scripts/travis/add-key.sh
6
+ - ./scripts/travis/add-key.sh
7
+ after_script:
8
+ - chmod 777 ./scripts/travis/remove-key.sh
9
+ - ./scripts/travis/remove-key.sh
10
+ env:
11
+ global:
12
+ secure: Usy8ZlZSUKzHUEtxR6zcWhG7c7OnynTn85+L0jjgrMZYw1AOFOmSjttfvfci8/f312YpUXOayBOOtE3U6B0TSbSbs7IwPlf76ZW7ZYa7SyE+BAsdS1E97IwpVL7DhKs17ZZl+6Ln9IJpHuZGF5N4RG9ItPzCQs0IGhRSGE32iNk=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in guard-motion.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ carabiner (0.0.1)
5
+ bubble-wrap
6
+ motion-require (~> 0.0.3)
7
+ rake
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ bubble-wrap (1.3.0)
13
+ coderay (1.0.9)
14
+ ffi (1.9.0)
15
+ formatador (0.2.4)
16
+ guard (1.8.2)
17
+ formatador (>= 0.2.4)
18
+ listen (>= 1.0.0)
19
+ lumberjack (>= 1.0.2)
20
+ pry (>= 0.9.10)
21
+ thor (>= 0.14.6)
22
+ guard-motion (0.1.2)
23
+ guard (>= 1.1.0)
24
+ rake (>= 0.9)
25
+ listen (1.3.1)
26
+ rb-fsevent (>= 0.9.3)
27
+ rb-inotify (>= 0.9)
28
+ rb-kqueue (>= 0.2)
29
+ lumberjack (1.0.4)
30
+ method_source (0.8.2)
31
+ motion-require (0.0.7)
32
+ pry (0.9.12.2)
33
+ coderay (~> 1.0.5)
34
+ method_source (~> 0.8)
35
+ slop (~> 3.4)
36
+ rake (10.1.0)
37
+ rb-fsevent (0.9.3)
38
+ rb-inotify (0.9.1)
39
+ ffi (>= 0.5.0)
40
+ rb-kqueue (0.2.0)
41
+ ffi (>= 0.5.0)
42
+ slop (3.4.6)
43
+ thor (0.18.1)
44
+
45
+ PLATFORMS
46
+ ruby
47
+
48
+ DEPENDENCIES
49
+ bundler
50
+ carabiner!
51
+ guard-motion
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Fabio Kuhn
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # Carabiner [![Build Status](https://travis-ci.org/mordaroso/carabiner.png)](https://travis-ci.org/mordaroso/carabiner)
2
+
3
+ Rubymotion wrapper for the easy access to the keychain.
4
+
5
+ ![Carabiners](http://upload.wikimedia.org/wikipedia/commons/2/2e/Cheap_carabiners.JPG)
6
+
7
+ **This gem is still under heavy development and will be released soon. Please be paitent.**
8
+
9
+ ## TODOs
10
+
11
+ * Better error handling
12
+ * Code Documentation
13
+ * README
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ $:.unshift("/Library/RubyMotion/lib")
2
+ require 'motion/project/template/ios'
3
+
4
+ $:.unshift("./lib/")
5
+ require './lib/carabiner'
6
+
7
+ Motion::Project::App.setup do |app|
8
+ # Use `rake config' to see complete project settings.
9
+ app.name = 'KeychainExample'
10
+
11
+ app.frameworks += ['Security']
12
+
13
+ app.entitlements['keychain-access-groups'] = [
14
+ app.seed_id + '.' + app.identifier
15
+ ]
16
+ end
@@ -0,0 +1,13 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
4
+ @window.rootViewController = SettingsController.alloc.init
5
+ @window.rootViewController.wantsFullScreenLayout = true
6
+ @window.makeKeyAndVisible
7
+ return true
8
+ end
9
+
10
+ def user
11
+ @user ||= User.new
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ class SettingsController < UIViewController
2
+ def loadView
3
+ self.view = SettingsView.alloc.init
4
+ self.view.setNeedsDisplay
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ class User
2
+ attr_accessor :username, :password
3
+
4
+ def initialize
5
+ @keychain = Carabiner::PasswordKeychainItem.new 'ExampleAppLoginData'
6
+ load
7
+ end
8
+
9
+ def save
10
+ @keychain.account = username
11
+ @keychain.password = password
12
+ @keychain.save!
13
+ end
14
+
15
+ def load
16
+ self.username = @keychain.account
17
+ self.password = @keychain.password
18
+ end
19
+
20
+ def reset
21
+ self.username = ''
22
+ self.password = ''
23
+ @keychain.reset!
24
+ end
25
+ end
@@ -0,0 +1,61 @@
1
+ class SettingsView < UIView
2
+
3
+ def initWithFrame(rect)
4
+ if super
5
+ self.backgroundColor = UIColor.groupTableViewBackgroundColor
6
+ @user = UIApplication.sharedApplication.delegate.user
7
+ drawUsername
8
+ drawPassword
9
+ drawButton
10
+ end
11
+ self
12
+ end
13
+
14
+ def drawUsername
15
+ @username = UITextField.alloc.initWithFrame CGRectMake(40, 30, 240, 30)
16
+ @username.setBorderStyle UITextBorderStyleRoundedRect
17
+ @username.placeholder = 'Username'
18
+ @username.text = @user.username
19
+ @username.setReturnKeyType UIReturnKeyDone
20
+ @username.addTarget self, action: 'textFieldFinished', forControlEvents:UIControlEventEditingDidEndOnExit
21
+
22
+ addSubview @username
23
+ end
24
+
25
+ def drawPassword
26
+ @password = UITextField.alloc.initWithFrame CGRectMake(40, 75, 240, 30)
27
+ @password.setBorderStyle UITextBorderStyleRoundedRect
28
+ @password.placeholder = 'Password'
29
+ @password.text = @user.password
30
+ @password.setSecureTextEntry true
31
+ @password.setReturnKeyType UIReturnKeyDone
32
+ @password.addTarget self, action: 'textFieldFinished', forControlEvents:UIControlEventEditingDidEndOnExit
33
+
34
+ addSubview @password
35
+ end
36
+
37
+ def drawButton
38
+ @saveButton = UIButton.buttonWithType UIButtonTypeRoundedRect
39
+ @saveButton.setFrame CGRectMake(80, 130, 160, 40)
40
+ @saveButton.setTitle "Save", forState: UIControlStateNormal
41
+
42
+ pointer = Pointer.new(:object)
43
+
44
+ @saveButton.addTarget self, action:'saveSettings', forControlEvents: UIControlEventTouchUpInside
45
+
46
+ addSubview @saveButton
47
+ end
48
+
49
+ def textFieldFinished
50
+ self.endEditing true
51
+ end
52
+
53
+ def saveSettings
54
+ @user.username = @username.text
55
+ @user.password = @password.text
56
+ @user.save
57
+
58
+ @saveButton.setTitle "Saved", forState: UIControlStateNormal
59
+ self.endEditing true
60
+ end
61
+ end
data/carabiner.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/carabiner/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["mordaroso"]
6
+ gem.email = ["mordaroso@gmail.com"]
7
+ gem.homepage = 'http://rubygems.org/gems/carabiner'
8
+ gem.summary = 'Rubymotion wrapper for the keychain'
9
+ gem.description = 'Easy access to the ios keychain'
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "carabiner"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Carabiner::VERSION
17
+
18
+ gem.add_dependency 'rake'
19
+ gem.add_dependency 'bubble-wrap'
20
+ gem.add_dependency 'motion-require', '~> 0.0.3'
21
+
22
+ gem.add_development_dependency 'bundler'
23
+ gem.add_development_dependency 'guard-motion'
24
+ end
data/lib/carabiner.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'bubble-wrap/core'
2
+
3
+ require 'motion-require'
4
+
5
+ Motion::Require.all(Dir.glob(File.expand_path('../carabiner/**/*.rb', __FILE__)))
@@ -0,0 +1,48 @@
1
+ module Carabiner
2
+ class KeychainReturnCodeException < Exception
3
+
4
+ attr_accessor :return_code
5
+
6
+ RETURN_CODES = {
7
+ ErrSecSuccess => {:constant_name => 'ErrSecSuccess', :message => "No error."},
8
+ ErrSecUnimplemented => {:constant_name => 'ErrSecUnimplemented', :message => "Function or operation not implemented."},
9
+ ErrSecParam => {:constant_name => 'ErrSecParam', :message => "One or more parameters passed to the function were not valid."},
10
+ ErrSecAllocate => {:constant_name => 'ErrSecAllocate', :message => "Failed to allocate memory."},
11
+ ErrSecNotAvailable => {:constant_name => 'ErrSecNotAvailable', :message => "No trust results are available."},
12
+ ErrSecAuthFailed => {:constant_name => 'ErrSecAuthFailed', :message => "Authorization/Authentication failed."},
13
+ ErrSecDuplicateItem => {:constant_name => 'ErrSecDuplicateItem', :message => "The item already exists."},
14
+ ErrSecItemNotFound => {:constant_name => 'ErrSecItemNotFound', :message => "The item cannot be found."},
15
+ ErrSecInteractionNotAllowed => {:constant_name => 'ErrSecInteractionNotAllowed', :message => "Interaction with the Security Server is not allowed."},
16
+ ErrSecDecode => {:constant_name => 'ErrSecDecode', :message => "Unable to decode the provided data."}
17
+ }
18
+
19
+ def initialize message, return_code
20
+ @return_code = return_code
21
+ super message
22
+ end
23
+
24
+ def message
25
+ super + "\nReturn Code: #{constant_name} (#{return_message})"
26
+ end
27
+
28
+ def return_message
29
+ if return_code_item
30
+ return_code_item[:message]
31
+ else
32
+ "Keychain return code #{return_code} unknown."
33
+ end
34
+ end
35
+
36
+ def constant_name
37
+ if return_code_item
38
+ return_code_item[:constant_name]
39
+ else
40
+ return_code.to_s
41
+ end
42
+ end
43
+
44
+ def return_code_item
45
+ RETURN_CODES[return_code]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,160 @@
1
+ module Carabiner
2
+ class PasswordKeychainItem
3
+
4
+ attr_accessor :generic_password_query
5
+
6
+ # These are the default constants and their respective types,
7
+ # available for the kSecClassGenericPassword Keychain Item class:
8
+ #
9
+ # See the header file Security/SecItem.h for more details.
10
+ ATTRIBUTES = {
11
+ :access_group => KSecAttrAccessGroup,
12
+ :creation_time => KSecAttrCreationDate,
13
+ :modifaction_date => KSecAttrModificationDate,
14
+ :description => KSecAttrDescription,
15
+ :comment => KSecAttrComment,
16
+ :creator => KSecAttrCreator,
17
+ :type => KSecAttrType,
18
+ :label => KSecAttrLabel,
19
+ :is_invisible => KSecAttrIsInvisible,
20
+ :is_negative => KSecAttrIsNegative,
21
+ :account => KSecAttrAccount,
22
+ :service => KSecAttrService,
23
+ :generic => KSecAttrGeneric,
24
+ :password => KSecValueData
25
+ }
26
+
27
+ ATTRIBUTES.keys.each do |key|
28
+ attr_accessor key
29
+ end
30
+
31
+ NoErr = 0
32
+
33
+ def initialize identifier, accessGroup = nil
34
+ self.generic_password_query = {}
35
+ generic_password_query[KSecClass] = KSecClassGenericPassword
36
+ generic_password_query[KSecAttrGeneric] = identifier
37
+
38
+ if !accessGroup.nil? && !Device.simulator?
39
+ generic_password_query[KSecAttrAccessGroup] = accessGroup
40
+ end
41
+
42
+ generic_password_query[KSecMatchLimit] = KSecMatchLimitOne
43
+ generic_password_query[KSecReturnAttributes] = KCFBooleanTrue
44
+
45
+ tempQuery = NSDictionary.dictionaryWithDictionary generic_password_query
46
+ outDictionaryPtr = Pointer.new(:object)
47
+
48
+ if !(SecItemCopyMatching(tempQuery, outDictionaryPtr) == NoErr)
49
+ reset!
50
+ self.generic = identifier
51
+
52
+ if !accessGroup.nil? && !Device.simulator?
53
+ generic_password_query[KSecAttrAccessGroup] = accessGroup
54
+ end
55
+ else
56
+ self.keychain_item_data = secItemFormatToDictionary(outDictionaryPtr[0])
57
+ end
58
+ end
59
+
60
+ def reset!
61
+ delete! unless keychain_item_data.empty?
62
+ self.account = ''
63
+ self.label = ''
64
+ self.description = ''
65
+ self.password = ''
66
+ true
67
+ end
68
+
69
+ def save!
70
+ writeToKeychain
71
+ true
72
+ end
73
+
74
+ def delete!
75
+ tempDictionary = dictionaryToSecItemFormat(keychain_item_data)
76
+ result = SecItemDelete(tempDictionary)
77
+ if result != NoErr && result != ErrSecItemNotFound
78
+ raise KeychainReturnCodeException.new "Problem deleting current dictionary.", result
79
+ end
80
+ self.keychain_item_data = {}
81
+ true
82
+ end
83
+
84
+ def self.key_accepted? key
85
+ ATTRIBUTES.values.include? key
86
+ end
87
+
88
+ private
89
+
90
+ def keychain_item_data
91
+ ATTRIBUTES.keys.inject({}) do |memo, getter_name|
92
+ constant = ATTRIBUTES[getter_name]
93
+ value = send(getter_name)
94
+ memo[constant] = value if value
95
+ memo
96
+ end
97
+ end
98
+
99
+ def keychain_item_data=(hash)
100
+ ATTRIBUTES.each do |getter_name, constant|
101
+ send("#{getter_name}=", hash[constant])
102
+ end
103
+ end
104
+
105
+ def dictionaryToSecItemFormat dictionaryToConvert
106
+ returnDictionary = NSMutableDictionary.dictionaryWithDictionary dictionaryToConvert
107
+ returnDictionary[KSecClass] = KSecClassGenericPassword
108
+ passwordString = dictionaryToConvert[KSecValueData]
109
+
110
+ returnDictionary[KSecValueData] = passwordString.dataUsingEncoding(NSUTF8StringEncoding)
111
+ returnDictionary
112
+ end
113
+
114
+ def secItemFormatToDictionary dictionaryToConvert
115
+ returnDictionary = NSMutableDictionary.dictionaryWithDictionary dictionaryToConvert
116
+ returnDictionary[KSecReturnData] = KCFBooleanTrue
117
+ returnDictionary[KSecClass] = KSecClassGenericPassword
118
+
119
+ passwordDataPtr = Pointer.new(:object)
120
+
121
+ result = SecItemCopyMatching(returnDictionary, passwordDataPtr)
122
+ if result == NoErr
123
+ returnDictionary.delete KSecReturnData
124
+ passwordData = passwordDataPtr[0]
125
+ password = NSString.alloc.initWithBytes(passwordData.bytes, length: passwordData.length, encoding: NSUTF8StringEncoding)
126
+ returnDictionary[KSecValueData] = password
127
+ else
128
+ raise KeychainReturnCodeException.new "Serious error, no matching item found in the keychain.", result
129
+ end
130
+
131
+ returnDictionary
132
+ end
133
+
134
+ def writeToKeychain
135
+ attributesPtr = Pointer.new(:object)
136
+ if SecItemCopyMatching(generic_password_query, attributesPtr) == NoErr
137
+ query = NSMutableDictionary.dictionaryWithDictionary attributesPtr[0]
138
+
139
+ query[KSecClass] = generic_password_query[KSecClass]
140
+ attributes_to_update = dictionaryToSecItemFormat keychain_item_data
141
+ attributes_to_update.delete_if { |key, value| !self.class.key_accepted? key }
142
+
143
+ if Device.simulator?
144
+ attributes_to_update.delete KSecAttrAccessGroup
145
+ end
146
+
147
+ result = SecItemUpdate(query, attributes_to_update)
148
+ unless result == NoErr
149
+ raise KeychainReturnCodeException.new "Couldn't update the Keychain Item.", result
150
+ end
151
+ else
152
+ result = SecItemAdd(dictionaryToSecItemFormat(keychain_item_data), nil)
153
+ unless result == NoErr
154
+ raise KeychainReturnCodeException.new "Couldn't add the Keychain Item.", result
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,3 @@
1
+ module Carabiner
2
+ VERSION = "0.0.2-alpha1"
3
+ end
@@ -0,0 +1,2 @@
1
+ mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
2
+ cp ./scripts/travis/profile/* ~/Library/MobileDevice/Provisioning\ Profiles/
@@ -0,0 +1 @@
1
+ rm -f ~/Library/MobileDevice/Provisioning\ Profiles/*
data/spec/main_spec.rb ADDED
@@ -0,0 +1,9 @@
1
+ describe "Application 'keychain_example'" do
2
+ before do
3
+ @app = UIApplication.sharedApplication
4
+ end
5
+
6
+ it "has one window" do
7
+ @app.windows.size.should == 1
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ module Carabiner
2
+ describe KeychainReturnCodeException do
3
+ describe 'known return value' do
4
+ before do
5
+ @exception = KeychainReturnCodeException.new "custom message", ErrSecNotAvailable
6
+ end
7
+
8
+ it 'has return_message' do
9
+ @exception.return_message.should == 'No trust results are available.'
10
+ end
11
+
12
+ it 'has constant_name' do
13
+ @exception.constant_name.should == 'ErrSecNotAvailable'
14
+ end
15
+
16
+ it 'has descriptive error message' do
17
+ @exception.message.should == "custom message\nReturn Code: ErrSecNotAvailable (No trust results are available.)"
18
+ end
19
+ end
20
+
21
+ describe 'unknown return value' do
22
+ before do
23
+ @exception = KeychainReturnCodeException.new "custom message", 999
24
+ end
25
+
26
+ it 'has return_message' do
27
+ @exception.return_message.should == 'Keychain return code 999 unknown.'
28
+ end
29
+
30
+ it 'has constant_name' do
31
+ @exception.constant_name.should == '999'
32
+ end
33
+
34
+ it 'has descriptive error message' do
35
+ @exception.message.should == "custom message\nReturn Code: 999 (Keychain return code 999 unknown.)"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ module Carabiner
2
+ describe PasswordKeychainItem do
3
+ before do
4
+ @item = PasswordKeychainItem.new 'TestPasswordItem'
5
+ @item.password = 'secret'
6
+ @item.account = 'Test'
7
+ @item.save!
8
+ end
9
+
10
+ it 'initialize attributes' do
11
+ new_item = PasswordKeychainItem.new 'TestPasswordItem'
12
+ new_item.account.should == 'Test'
13
+ new_item.password.should == 'secret'
14
+ end
15
+
16
+ it 'reset!' do
17
+ @item.reset!
18
+ @item.account.should == ''
19
+ @item.password.should == ''
20
+ end
21
+
22
+ it 'delete!' do
23
+ @item.delete!
24
+ @item.account.should == nil
25
+ @item.password.should == nil
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ describe "User" do
2
+ before do
3
+ @user = User.new
4
+ @user.username = 'Username'
5
+ @user.password = 'Secret'
6
+ @user.save
7
+ end
8
+
9
+ it "should save username and password" do
10
+ @user.username = 'New Username'
11
+ @user.password = 'New Secret'
12
+ @user.save
13
+
14
+ @user.username.should == 'New Username'
15
+ @user.password.should == 'New Secret'
16
+ end
17
+
18
+ it "should load username and password" do
19
+ @second_user_object = User.new
20
+ @user.username.should == 'Username'
21
+ @user.password.should == 'Secret'
22
+ end
23
+
24
+ it "should reset information" do
25
+ @user.reset
26
+ @user.load
27
+ @user.username.should == ''
28
+ @user.username.should == ''
29
+ end
30
+ end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carabiner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 0.0.2.pre.alpha1
6
5
  platform: ruby
7
6
  authors:
8
7
  - mordaroso
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-09-09 00:00:00.000000000 Z
11
+ date: 2013-09-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
@@ -22,15 +20,41 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ! '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bubble-wrap
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: motion-require
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.0.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.0.3
30
55
  - !ruby/object:Gem::Dependency
31
56
  name: bundler
32
57
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
58
  requirements:
35
59
  - - ! '>='
36
60
  - !ruby/object:Gem::Version
@@ -38,7 +62,6 @@ dependencies:
38
62
  type: :development
39
63
  prerelease: false
40
64
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
65
  requirements:
43
66
  - - ! '>='
44
67
  - !ruby/object:Gem::Version
@@ -46,7 +69,6 @@ dependencies:
46
69
  - !ruby/object:Gem::Dependency
47
70
  name: guard-motion
48
71
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
72
  requirements:
51
73
  - - ! '>='
52
74
  - !ruby/object:Gem::Version
@@ -54,7 +76,6 @@ dependencies:
54
76
  type: :development
55
77
  prerelease: false
56
78
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
79
  requirements:
59
80
  - - ! '>='
60
81
  - !ruby/object:Gem::Version
@@ -65,30 +86,56 @@ email:
65
86
  executables: []
66
87
  extensions: []
67
88
  extra_rdoc_files: []
68
- files: []
89
+ files:
90
+ - .gitignore
91
+ - .travis.yml
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - app/app_delegate.rb
98
+ - app/controllers/settings_controller.rb
99
+ - app/models/user.rb
100
+ - app/views/settings_view.rb
101
+ - carabiner.gemspec
102
+ - lib/carabiner.rb
103
+ - lib/carabiner/keychain_return_code_exception.rb
104
+ - lib/carabiner/password_keychain_item.rb
105
+ - lib/carabiner/version.rb
106
+ - scripts/travis/add-key.sh
107
+ - scripts/travis/profile/4A8AC2EE-F24B-4F4E-A6F0-67F9BC46B924.mobileprovision
108
+ - scripts/travis/remove-key.sh
109
+ - spec/main_spec.rb
110
+ - spec/models/keychain_return_code_exception_spec.rb
111
+ - spec/models/password_keychain_item_spec.rb
112
+ - spec/models/user_spec.rb
69
113
  homepage: http://rubygems.org/gems/carabiner
70
114
  licenses: []
115
+ metadata: {}
71
116
  post_install_message:
72
117
  rdoc_options: []
73
118
  require_paths:
74
119
  - lib
75
120
  required_ruby_version: !ruby/object:Gem::Requirement
76
- none: false
77
121
  requirements:
78
122
  - - ! '>='
79
123
  - !ruby/object:Gem::Version
80
124
  version: '0'
81
125
  required_rubygems_version: !ruby/object:Gem::Requirement
82
- none: false
83
126
  requirements:
84
- - - ! '>='
127
+ - - ! '>'
85
128
  - !ruby/object:Gem::Version
86
- version: '0'
129
+ version: 1.3.1
87
130
  requirements: []
88
131
  rubyforge_project:
89
- rubygems_version: 1.8.23
132
+ rubygems_version: 2.1.3
90
133
  signing_key:
91
- specification_version: 3
134
+ specification_version: 4
92
135
  summary: Rubymotion wrapper for the keychain
93
- test_files: []
136
+ test_files:
137
+ - spec/main_spec.rb
138
+ - spec/models/keychain_return_code_exception_spec.rb
139
+ - spec/models/password_keychain_item_spec.rb
140
+ - spec/models/user_spec.rb
94
141
  has_rdoc: