Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 5893bb3

Browse files
Fix support for spaces in parameters (#49)
* Add failing test get_user_rooms where id contains spaces * Fix escaping of parameters containing spaces * Add pending changes to CHANGELOG * Release 1.9.1
1 parent 7611440 commit 5893bb3

5 files changed

Lines changed: 64 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased](https://github.com/pusher/chatkit-server-ruby/compare/1.7.1...HEAD)]
88

9+
## [1.9.1](https://github.com/pusher/chatkit-server-ruby/compare/1.9.0...1.9.1)
10+
11+
### Fixes
12+
13+
- Fix support for parameters which allow spaces.
14+
Methods whose parameters contain spaces and were interpolated into URI path
15+
segments were incorrectly encoded. For example, user ids containing spaces
16+
when passed to get_user_rooms had spaces encoded as '+' (suitable for
17+
query strings) not '%20'.
18+
919
## [1.9.0](https://github.com/pusher/chatkit-server-ruby/compare/1.7.1...1.8.0)
1020

1121
### Additions

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
pusher-chatkit-server (1.9.0)
4+
pusher-chatkit-server (1.9.1)
55
pusher-platform (~> 0.11.2)
66

77
GEM

chatkit.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Gem::Specification.new do |s|
22
s.name = 'pusher-chatkit-server'
3-
s.version = '1.9.0'
3+
s.version = '1.9.1'
44
s.licenses = ['MIT']
55
s.summary = 'Pusher Chatkit Ruby SDK'
66
s.authors = ['Pusher']

lib/chatkit/client.rb

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ def generate_su_token(options = {})
8888
generate_access_token({ su: true }.merge(options))
8989
end
9090

91+
# This helper should be used to encode parameters that appear in path segments.
92+
# CGI::escape should NOT be used as it treats the string as if it appears in a query string.
93+
# E.G. We want "user name" to be encoded as "user%20name" rather than "user+name"
94+
def url_encode_path_segment(s)
95+
ERB::Util.url_encode(s)
96+
end
97+
9198
# User API
9299

93100
def create_user(options)
@@ -145,7 +152,7 @@ def update_user(options)
145152

146153
api_request({
147154
method: "PUT",
148-
path: "/users/#{CGI::escape options[:id]}",
155+
path: "/users/#{url_encode_path_segment options[:id]}",
149156
body: payload,
150157
jwt: generate_su_token({ user_id: options[:id] })[:token]
151158
})
@@ -158,7 +165,7 @@ def async_delete_user(options)
158165

159166
scheduler_request({
160167
method: "PUT",
161-
path: "/users/#{CGI::escape options[:id]}",
168+
path: "/users/#{url_encode_path_segment options[:id]}",
162169
jwt: generate_su_token[:token]
163170
})
164171
end
@@ -170,7 +177,7 @@ def get_delete_status(options)
170177

171178
scheduler_request({
172179
method: "GET",
173-
path: "/status/#{CGI::escape options[:id]}",
180+
path: "/status/#{url_encode_path_segment options[:id]}",
174181
jwt: generate_su_token[:token]
175182
})
176183
end
@@ -182,7 +189,7 @@ def get_user(options)
182189

183190
api_request({
184191
method: "GET",
185-
path: "/users/#{CGI::escape options[:id]}",
192+
path: "/users/#{url_encode_path_segment options[:id]}",
186193
jwt: generate_su_token[:token]
187194
})
188195
end
@@ -267,7 +274,7 @@ def update_room(options)
267274

268275
api_request({
269276
method: "PUT",
270-
path: "/rooms/#{CGI::escape options[:id]}",
277+
path: "/rooms/#{url_encode_path_segment options[:id]}",
271278
body: payload,
272279
jwt: generate_su_token[:token]
273280
})
@@ -280,7 +287,7 @@ def async_delete_room(options)
280287

281288
scheduler_request({
282289
method: "PUT",
283-
path: "/rooms/#{CGI::escape options[:id]}",
290+
path: "/rooms/#{url_encode_path_segment options[:id]}",
284291
jwt: generate_su_token[:token]
285292
})
286293
end
@@ -292,7 +299,7 @@ def get_room(options)
292299

293300
api_request({
294301
method: "GET",
295-
path: "/rooms/#{CGI::escape options[:id]}",
302+
path: "/rooms/#{url_encode_path_segment options[:id]}",
296303
jwt: generate_su_token[:token]
297304
})
298305
end
@@ -337,7 +344,7 @@ def add_users_to_room(options)
337344

338345
api_request({
339346
method: "PUT",
340-
path: "/rooms/#{CGI::escape options[:room_id]}/users/add",
347+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/users/add",
341348
body: { user_ids: options[:user_ids] },
342349
jwt: generate_su_token[:token]
343350
})
@@ -354,7 +361,7 @@ def remove_users_from_room(options)
354361

355362
api_request({
356363
method: "PUT",
357-
path: "/rooms/#{CGI::escape options[:room_id]}/users/remove",
364+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/users/remove",
358365
body: { user_ids: options[:user_ids] },
359366
jwt: generate_su_token[:token]
360367
})
@@ -370,7 +377,7 @@ def fetch_multipart_message(options)
370377

371378
api_request({
372379
method: "GET",
373-
path: "/rooms/#{CGI::escape options[:room_id]}/messages/#{options[:message_id]}",
380+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/messages/#{options[:message_id]}",
374381
jwt: generate_su_token[:token]
375382
})
376383
end
@@ -392,7 +399,7 @@ def fetch_multipart_messages(options)
392399

393400
api_request({
394401
method: "GET",
395-
path: "/rooms/#{CGI::escape options[:room_id]}/messages",
402+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/messages",
396403
query: query_params,
397404
jwt: generate_su_token[:token]
398405
})
@@ -410,7 +417,7 @@ def get_room_messages(options)
410417

411418
api_v2_request({
412419
method: "GET",
413-
path: "/rooms/#{CGI::escape options[:room_id]}/messages",
420+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/messages",
414421
query: query_params,
415422
jwt: generate_su_token[:token]
416423
})
@@ -467,7 +474,7 @@ def send_multipart_message(options)
467474

468475
api_request({
469476
method: "POST",
470-
path: "/rooms/#{CGI::escape options[:room_id]}/messages",
477+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/messages",
471478
body: {parts: request_parts},
472479
jwt: token
473480
})
@@ -509,7 +516,7 @@ def send_message(options)
509516

510517
api_v2_request({
511518
method: "POST",
512-
path: "/rooms/#{CGI::escape options[:room_id]}/messages",
519+
path: "/rooms/#{url_encode_path_segment options[:room_id]}/messages",
513520
body: payload,
514521
jwt: generate_su_token({ user_id: options[:sender_id] })[:token]
515522
})
@@ -591,7 +598,7 @@ def edit_multipart_message(room_id, message_id, options)
591598

592599
api_request({
593600
method: "PUT",
594-
path: "/rooms/#{CGI::escape room_id}/messages/#{message_id}",
601+
path: "/rooms/#{url_encode_path_segment room_id}/messages/#{message_id}",
595602
body: {parts: request_parts},
596603
jwt: token
597604
})
@@ -645,7 +652,7 @@ def edit_message(room_id, message_id, options)
645652

646653
api_v2_request({
647654
method: "PUT",
648-
path: "/rooms/#{CGI::escape room_id}/messages/#{message_id}",
655+
path: "/rooms/#{url_encode_path_segment room_id}/messages/#{message_id}",
649656
body: payload,
650657
jwt: generate_su_token({ user_id: options[:sender_id] })[:token]
651658
})
@@ -700,7 +707,7 @@ def get_user_roles(options)
700707

701708
authorizer_request({
702709
method: "GET",
703-
path: "/users/#{CGI::escape options[:user_id]}/roles",
710+
path: "/users/#{url_encode_path_segment options[:user_id]}/roles",
704711
jwt: generate_su_token[:token]
705712
})
706713
end
@@ -750,7 +757,7 @@ def get_read_cursor(options)
750757

751758
cursors_request({
752759
method: "GET",
753-
path: "/cursors/0/rooms/#{CGI::escape options[:room_id]}/users/#{CGI::escape options[:user_id]}",
760+
path: "/cursors/0/rooms/#{url_encode_path_segment options[:room_id]}/users/#{url_encode_path_segment options[:user_id]}",
754761
jwt: generate_su_token[:token]
755762
})
756763
end
@@ -770,7 +777,7 @@ def set_read_cursor(options)
770777

771778
cursors_request({
772779
method: "PUT",
773-
path: "/cursors/0/rooms/#{CGI::escape options[:room_id]}/users/#{CGI::escape options[:user_id]}",
780+
path: "/cursors/0/rooms/#{url_encode_path_segment options[:room_id]}/users/#{url_encode_path_segment options[:user_id]}",
774781
body: { position: options[:position] },
775782
jwt: generate_su_token[:token]
776783
})
@@ -783,7 +790,7 @@ def get_user_read_cursors(options)
783790

784791
cursors_request({
785792
method: "GET",
786-
path: "/cursors/0/users/#{CGI::escape options[:user_id]}",
793+
path: "/cursors/0/users/#{url_encode_path_segment options[:user_id]}",
787794
jwt: generate_su_token[:token]
788795
})
789796
end
@@ -795,7 +802,7 @@ def get_room_read_cursors(options)
795802

796803
cursors_request({
797804
method: "GET",
798-
path: "/cursors/0/rooms/#{CGI::escape options[:room_id]}",
805+
path: "/cursors/0/rooms/#{url_encode_path_segment options[:room_id]}",
799806
jwt: generate_su_token[:token]
800807
})
801808
end
@@ -852,7 +859,7 @@ def get_rooms_for_user(options)
852859

853860
request_options = {
854861
method: "GET",
855-
path: "/users/#{CGI::escape options[:id]}/rooms",
862+
path: "/users/#{url_encode_path_segment options[:id]}/rooms",
856863
jwt: generate_su_token[:token]
857864
}
858865

@@ -891,7 +898,7 @@ def delete_role(options)
891898

892899
authorizer_request({
893900
method: "DELETE",
894-
path: "/roles/#{CGI::escape options[:name]}/scope/#{options[:scope]}",
901+
path: "/roles/#{url_encode_path_segment options[:name]}/scope/#{options[:scope]}",
895902
jwt: generate_su_token[:token]
896903
})
897904
end
@@ -913,7 +920,7 @@ def assign_role_to_user(options)
913920

914921
authorizer_request({
915922
method: "PUT",
916-
path: "/users/#{CGI::escape options[:user_id]}/roles",
923+
path: "/users/#{url_encode_path_segment options[:user_id]}/roles",
917924
body: body,
918925
jwt: generate_su_token[:token]
919926
})
@@ -926,7 +933,7 @@ def remove_role_for_user(options)
926933

927934
request_options = {
928935
method: "DELETE",
929-
path: "/users/#{CGI::escape options[:user_id]}/roles",
936+
path: "/users/#{url_encode_path_segment options[:user_id]}/roles",
930937
jwt: generate_su_token[:token]
931938
}
932939

@@ -944,7 +951,7 @@ def get_permissions_for_role(options)
944951

945952
authorizer_request({
946953
method: "GET",
947-
path: "/roles/#{CGI::escape options[:name]}/scope/#{options[:scope]}/permissions",
954+
path: "/roles/#{url_encode_path_segment options[:name]}/scope/#{options[:scope]}/permissions",
948955
jwt: generate_su_token[:token]
949956
})
950957
end
@@ -967,7 +974,7 @@ def update_permissions_for_role(options)
967974

968975
authorizer_request({
969976
method: "PUT",
970-
path: "/roles/#{CGI::escape options[:name]}/scope/#{options[:scope]}/permissions",
977+
path: "/roles/#{url_encode_path_segment options[:name]}/scope/#{options[:scope]}/permissions",
971978
body: body,
972979
jwt: generate_su_token[:token]
973980
})
@@ -992,7 +999,7 @@ def upload_attachment(token, room_id, part)
992999

9931000
attachment_response = api_request({
9941001
method: "POST",
995-
path: "/rooms/#{CGI::escape room_id}/attachments",
1002+
path: "/rooms/#{url_encode_path_segment room_id}/attachments",
9961003
body: attachment_req,
9971004
jwt: token
9981005
})

spec/client_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,23 @@
701701
expect(get_user_rooms_res[:body][0][:member_user_ids]).to eq [user_id]
702702
end
703703

704+
it "an id is provided which contains spaces" do
705+
user_id = SecureRandom.uuid + " with spaces"
706+
create_res = @chatkit.create_user({ id: user_id, name: 'Ham' })
707+
expect(create_res[:status]).to eq 201
708+
709+
room_res = @chatkit.create_room({ creator_id: user_id, name: 'my room' })
710+
expect(room_res[:status]).to eq 201
711+
712+
get_user_rooms_res = @chatkit.get_user_rooms({ id: user_id })
713+
expect(get_user_rooms_res[:status]).to eq 200
714+
expect(get_user_rooms_res[:body].count).to eq 1
715+
expect(get_user_rooms_res[:body][0][:id]).to eq room_res[:body][:id]
716+
expect(get_user_rooms_res[:body][0][:name]).to eq 'my room'
717+
expect(get_user_rooms_res[:body][0][:private]).to be false
718+
expect(get_user_rooms_res[:body][0][:member_user_ids]).to eq [user_id]
719+
end
720+
704721
it "an id is provided and only return the correct rooms" do
705722
user_id = SecureRandom.uuid
706723
user_id2 = SecureRandom.uuid

0 commit comments

Comments
 (0)