An unofficial, mostly Bitwarden-compatible API server written in Ruby (Sinatra and ActiveRecord)
at master 226 lines 8.0 kB view raw
1require_relative "spec_helper.rb" 2 3@access_token = nil 4 5describe "cipher module" do 6 before do 7 User.all.delete_all 8 9 Rubywarden::Test::Factory.create_user 10 @access_token = Rubywarden::Test::Factory.login_user 11 end 12 13 it "should not allow access with bogus bearer token" do 14 post_json "/api/ciphers", { 15 :type => 1, 16 :folderId => nil, 17 :organizationId => nil, 18 :name => "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=", 19 :notes => nil, 20 :favorite => false, 21 :login => { 22 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 23 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 24 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 25 :totp => nil 26 } 27 }, { 28 "HTTP_AUTHORIZATION" => "Bearer #{@access_token.upcase}", 29 } 30 31 last_response.status.wont_equal 200 32 end 33 34 it "should allow creating, updating, and deleting ciphers" do 35 post_json "/api/ciphers", { 36 :type => 1, 37 :folderId => nil, 38 :organizationId => nil, 39 :name => "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=", 40 :notes => nil, 41 :favorite => false, 42 :login => { 43 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 44 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 45 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 46 :totp => nil 47 } 48 }, { 49 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 50 } 51 52 last_response.status.must_equal 200 53 uuid = last_json_response["Id"] 54 uuid.to_s.wont_equal "" 55 56 c = Cipher.find_by_uuid(uuid) 57 c.wont_be_nil 58 c.uuid.must_equal uuid 59 c.name.must_equal "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=" 60 61 # update 62 63 ik = Bitwarden.makeKey("asdf", "api@example.com", 64 User::DEFAULT_KDF_TYPE, 65 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE]) 66 ek = Bitwarden.makeEncKey(ik) 67 k = Bitwarden.decrypt(ek, ik) 68 new_name = Bitwarden.encrypt("some new name", k).to_s 69 70 put_json "/api/ciphers/#{uuid}", { 71 :type => 1, 72 :folderId => nil, 73 :organizationId => nil, 74 :name => new_name, 75 :notes => nil, 76 :favorite => false, 77 :login => { 78 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 79 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 80 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 81 :totp => nil 82 } 83 }, { 84 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 85 } 86 87 last_response.status.must_equal 200 88 last_json_response["Id"].to_s.wont_equal "" 89 90 c = Cipher.find_by_uuid(last_json_response["Id"]) 91 c.name.must_equal new_name 92 93 uuid = c.uuid 94 95 # delete 96 97 delete_json "/api/ciphers/#{uuid}", {}, { 98 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 99 } 100 last_response.status.must_equal 200 101 102 Cipher.find_by_uuid(uuid).must_be_nil 103 end 104 105 it "should not allow creating, updating, or deleting bogus ciphers" do 106 post_json "/api/ciphers", { 107 :type => -5, 108 }, { 109 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 110 } 111 112 last_response.status.wont_equal 200 113 114 # create, then bogus update 115 116 post_json "/api/ciphers", { 117 :type => 1, 118 :folderId => nil, 119 :organizationId => nil, 120 :name => "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=", 121 :notes => nil, 122 :favorite => false, 123 :login => { 124 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 125 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 126 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 127 :totp => nil 128 } 129 }, { 130 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 131 } 132 133 last_response.status.must_equal 200 134 uuid = last_json_response["Id"] 135 136 put_json "/api/ciphers/#{uuid}", { 137 :type => -5, 138 }, { 139 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 140 } 141 142 last_response.status.wont_equal 200 143 144 # bogus delete 145 146 delete_json "/api/ciphers/something-bogus", {}, { 147 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 148 } 149 last_response.status.wont_equal 200 150 end 151 152 it "should allow assigning ciphers to valid folders" do 153 post_json "/api/ciphers", { 154 :type => 1, 155 :folderId => nil, 156 :organizationId => nil, 157 :name => "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=", 158 :notes => nil, 159 :favorite => false, 160 :login => { 161 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 162 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 163 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 164 :totp => nil 165 } 166 }, { 167 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 168 } 169 170 last_response.status.must_equal 200 171 uuid = last_json_response["Id"] 172 173 # create folder 174 175 post_json "/api/folders", { 176 :name => "2.tqb+y2z4ChCYHj4romVwGQ==|E8+D7aR5CNnd+jF7fdb9ow==|wELCxyy341G2F+w8bTb87PAUi6sdXeIFTFb4N8tk3E0=", 177 }, { 178 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 179 } 180 181 last_response.status.must_equal 200 182 folder_uuid = last_json_response["Id"] 183 184 # update to put in valid folder 185 186 put_json "/api/ciphers/#{uuid}", { 187 :type => 1, 188 :folderId => folder_uuid, 189 :organizationId => nil, 190 :name => "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=", 191 :notes => nil, 192 :favorite => false, 193 :login => { 194 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 195 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 196 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 197 :totp => nil 198 } 199 }, { 200 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 201 } 202 203 last_response.status.must_equal 200 204 205 # now assign to bogus folder 206 207 put_json "/api/ciphers/#{uuid}", { 208 :type => 1, 209 :folderId => folder_uuid.reverse, 210 :organizationId => nil, 211 :name => "2.d7MttWzJTSSKx1qXjHUxlQ==|01Ath5UqFZHk7csk5DVtkQ==|EMLoLREgCUP5Cu4HqIhcLqhiZHn+NsUDp8dAg1Xu0Io=", 212 :notes => nil, 213 :favorite => false, 214 :login => { 215 :uri => "2.T57BwAuV8ubIn/sZPbQC+A==|EhUSSpJWSzSYOdJ/AQzfXuUXxwzcs/6C4tOXqhWAqcM=|OWV2VIqLfoWPs9DiouXGUOtTEkVeklbtJQHkQFIXkC8=", 216 :username => "2.JbFkAEZPnuMm70cdP44wtA==|fsN6nbT+udGmOWv8K4otgw==|JbtwmNQa7/48KszT2hAdxpmJ6DRPZst0EDEZx5GzesI=", 217 :password => "2.e83hIsk6IRevSr/H1lvZhg==|48KNkSCoTacopXRmIZsbWg==|CIcWgNbaIN2ix2Fx1Gar6rWQeVeboehp4bioAwngr0o=", 218 :totp => nil 219 } 220 }, { 221 "HTTP_AUTHORIZATION" => "Bearer #{@access_token}", 222 } 223 224 last_response.status.wont_equal 200 225 end 226end