jiveapps 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jiveapps (0.0.8.alpha)
4
+ jiveapps (0.1.0.alpha)
5
5
  activesupport (= 2.3.5)
6
6
  rest-client (= 1.6.1)
7
7
  rubigen (= 1.5.5)
@@ -34,9 +34,6 @@ PLATFORMS
34
34
  ruby
35
35
 
36
36
  DEPENDENCIES
37
- activesupport (= 2.3.5)
38
37
  jiveapps!
39
- rest-client (= 1.6.1)
40
38
  rspec (>= 2.2.0)
41
- rubigen (= 1.5.5)
42
39
  webmock (>= 1.6.1)
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 0.1.0 2011-02-16
2
+ * Major enhancements
3
+ * Multi Developer Collaboration features. Added jiveapps sharing:list, sharing:add, and sharing:remove commands.
4
+ * Updated app templates to include more examples of commonly used Jive App features.
5
+
6
+ === 0.0.9 2011-01-28
7
+ * Minor enhancement
8
+ * Updated app code generator to require feature "jive-core-v2" instead of "jive-core-5.0.0"
9
+
1
10
  === 0.0.8 2011-01-28
2
11
  * Major Enhancements
3
12
  * OAuth Services management for 3rd party services. Added jiveapps oauth:list, oauth:add, and oauth:remove commands.
@@ -28,7 +28,9 @@ class CreateGenerator < RubiGen::Base
28
28
  m.template "hello.html", "hello.html"
29
29
  m.template "stylesheets/main.css", "stylesheets/main.css"
30
30
  m.template "javascripts/main.js", "javascripts/main.js"
31
- m.file "images/j-icon-jaf-48.png", "images/j-icon-jaf-48.png"
31
+ m.file "images/icon16.png", "images/icon16.png"
32
+ m.file "images/icon48.png", "images/icon48.png"
33
+ m.file "images/icon128.png", "images/icon128.png"
32
34
 
33
35
  # Samples
34
36
  # m.template_copy_each ["template.rb", "template2.rb"]
@@ -1,16 +1,62 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <Module>
2
+ <Module specificationVersion="1">
3
3
  <ModulePrefs title="<%= name %>"
4
+ description="TODO: Replace with real description of <%= name %> inside app.xml: Module/ModulePrefs/description"
4
5
  author="<%= author_name = `git config --global user.name`.to_s.strip; author_name.length > 0 ? author_name : 'TODO: Author Name' %>"
6
+ author_affiliation="Company Name"
7
+ author_email="<%= author_email = `git config --global user.email`.to_s.strip; author_email.length > 0 ? author_email : 'TODO: Author Email' %>"
5
8
  height="300"
6
- description="TODO: Replace with real description of <%= name %> inside app.xml: Module/ModulePrefs/description"
7
- thumbnail="<%= Jiveapps::WEBHOST %>/apps/<%= name %>/images/j-icon-jaf-48.png">
9
+ thumbnail="<%= Jiveapps::WEBHOST %>/apps/<%= name %>/images/thumbnail.png"
10
+ screenshot="<%= Jiveapps::WEBHOST %>/apps/<%= name %>/images/screenshot.png">
11
+
12
+ <!-- Commonly used features -->
8
13
  <Require feature="dynamic-height" />
9
14
  <Require feature="jive-core-v2" />
10
- <Require feature="opensocial-1.0"/>
11
15
  <Require feature="osapi"/>
12
16
  <Require feature="settitle"/>
13
17
  <Require feature="views" />
18
+
19
+ <!-- Icons - 3 sizes, 16x16, 48x48, 128x128 -->
20
+ <Link rel="Icon" href="<%= Jiveapps::WEBHOST %>/apps/<%= name %>/images/icon16.png" />
21
+ <Link rel="MediumIcon" href="<%= Jiveapps::WEBHOST %>/apps/<%= name %>/images/icon48.png" />
22
+ <Link rel="LargeIcon" href="<%= Jiveapps::WEBHOST %>/apps/<%= name %>/images/icon128.png" />
23
+
24
+ <!-- OAuth Services: https://developers.jivesoftware.com/community/docs/DOC-1161 -->
25
+ <!--
26
+ <OAuth>
27
+ <Service name="example">
28
+ <Access url="http://api.example.com/oauth/access_token" method="POST" />
29
+ <Request url="http://api.example.com/oauth/request_token" method="POST" />
30
+ <Authorization url="http://api.example.com/oauth/authorize" />
31
+ </Service>
32
+ </OAuth>
33
+ -->
34
+
35
+ <!-- Lifecycle Events: https://developers.jivesoftware.com/community/docs/DOC-1119 -->
36
+ <!--
37
+ <link rel="event.addapp" href="http://www.example.com/add" />
38
+ <link rel="event.removeapp" href="http://www.example.com/remove" />
39
+ -->
40
+
41
+ <!-- User Preferences: http://code.google.com/apis/gadgets/docs/reference.html#Userprefs_Ref -->
42
+ <!--
43
+ <UserPref name="where_i_live" display_name="Where I Live" datatype="string" default_value="" required="false" />
44
+ <UserPref name="where_i_work" display_name="Where I Work" datatype="bool" default_value="" required="false" />
45
+ <UserPref name="difficulty"
46
+ display_name="Difficulty"
47
+ datatype="enum"
48
+ default_value="2">
49
+ <EnumValue value="1" display_value="Easy"/>
50
+ <EnumValue value="2" display_value="Medium"/>
51
+ <EnumValue value="3" display_value="Hard"/>
52
+ </UserPref>
53
+ -->
54
+
55
+ <!-- Preloaded Content: http://wiki.opensocial.org/index.php?title=Remote_Data_Requests_%28v0.9%29#Preloading_data -->
56
+ <!--
57
+ <Preload href="http://www.example.com" />
58
+ -->
59
+
14
60
  </ModulePrefs>
15
61
 
16
62
  <!-- To begin development, remove the hello view and uncomment the home and canvas views below -->
@@ -48,7 +48,7 @@ class Jiveapps::Client
48
48
  rescue => e
49
49
  if e.response.body =~ /^\{/ # assume this is JSON if it starts with "{"
50
50
  errors = ActiveSupport::JSON.decode(e.response.body)
51
- return {"errors" => errors}
51
+ return errors
52
52
  else
53
53
  nil
54
54
  end
@@ -117,6 +117,29 @@ class Jiveapps::Client
117
117
  delete("/apps/#{app_name}/oauth_services/#{name}")
118
118
  end
119
119
 
120
+ ### Collaborators
121
+
122
+ # Get a list of collaborators on the app, returns an array of hashes each with :email
123
+ def list_collaborators(app_name)
124
+ collaborators = get("/apps/#{app_name}/collaborators")
125
+
126
+ if collaborators.class == Array
127
+ collaborators.map { |item| {:username => item['collaborator']['user']['username']} }
128
+ else
129
+ return []
130
+ end
131
+ end
132
+
133
+ # Invite a person by username to collaborate on the app.
134
+ def add_collaborator(app_name, username)
135
+ post("/apps/#{app_name}/collaborators", {:collaborator => {:username => username}})
136
+ end
137
+
138
+ # Remove a collaborator.
139
+ def remove_collaborator(app_name, username)
140
+ delete("/apps/#{app_name}/collaborators/#{escape(username)}").to_s
141
+ end
142
+
120
143
  ### General
121
144
 
122
145
  def version
@@ -70,21 +70,22 @@ module Jiveapps
70
70
  end
71
71
 
72
72
  def extract_error(body)
73
- msg = parse_error_xml(body) || parse_error_json(body) || 'Internal server error'
73
+ msg = parse_error_json(body) || 'Internal server error'
74
74
  msg.split("\n").map { |line| ' ! ' + line }.join("\n")
75
75
  end
76
76
 
77
- def parse_error_xml(body)
78
- xml_errors = REXML::Document.new(body).elements.to_a("//errors/error")
79
- msg = xml_errors.map { |a| a.text }.join(" / ")
80
- return msg unless msg.empty?
81
- rescue Exception
82
- end
83
-
84
77
  def parse_error_json(body)
85
- json = JSON.parse(body.to_s)
86
- json['error']
87
- rescue JSON::ParserError
78
+ json = ActiveSupport::JSON.decode(body.to_s)
79
+ error_hash = json['errors']
80
+ return if error_hash.nil?
81
+ results = ["Errors:"]
82
+ error_hash.each do |key, errors|
83
+ errors.each do |error|
84
+ results << "- #{key} #{error}"
85
+ end
86
+ end
87
+ results.join("\n")
88
+ rescue StandardError
88
89
  end
89
90
 
90
91
  end
@@ -48,8 +48,9 @@ module Jiveapps::Command
48
48
  end
49
49
 
50
50
  def install
51
- display "Installing \"#{app_name}\" on the Jive App Sandbox: ", false
52
- app = jiveapps.install(app_name)
51
+ name = (args.first && !args.first =~ /^\-\-/) ? args.first : extract_app
52
+ display "Installing \"#{name}\" on the Jive App Sandbox: ", false
53
+ app = jiveapps.install(name)
53
54
  handle_response_errors
54
55
  if app == nil
55
56
  display "App not found."
@@ -86,4 +86,14 @@ module Jiveapps::Command
86
86
  end
87
87
 
88
88
  end
89
+
90
+ class BaseWithApp < Base
91
+ attr_accessor :app
92
+
93
+ def initialize(args, jiveapps=nil)
94
+ super(args, jiveapps)
95
+ @app ||= extract_app
96
+ end
97
+ end
98
+
89
99
  end
@@ -24,6 +24,10 @@ oauth # show the oauth services for this ap
24
24
  oauth:add <service_name> <key> <secret> # add an oauth service for this app
25
25
  oauth:remove <service_name> # remove an oauth service for this app
26
26
 
27
+ sharing # list collaborators
28
+ sharing:add <username> # add a collaborator
29
+ sharing:remove <username> # remove a collaborator
30
+
27
31
  === Simple Workflow Example:
28
32
 
29
33
  $ jiveapps create myapp # create a new app named "myapp"
@@ -0,0 +1,34 @@
1
+ module Jiveapps::Command
2
+ class Sharing < BaseWithApp
3
+ def list
4
+ display_collaborators
5
+ end
6
+ alias :index :list
7
+
8
+ def add
9
+ username = args.shift.downcase rescue ''
10
+ raise(CommandFailed, "Specify a username to give commit access to.") if username == ''
11
+ display "=== Adding commit access to #{app} for \"#{username}\""
12
+ jiveapps.add_collaborator(app, username)
13
+ display_collaborators
14
+ end
15
+
16
+ def remove
17
+ username = args.shift.downcase rescue ''
18
+ raise(CommandFailed, "Specify a username to remove commit access from.") if username == ''
19
+ if confirm("Are you sure you wish to remove commit access to #{app} for \"#{username}\"? (y/n)?")
20
+ display "=== Removing commit access to #{app} for \"#{username}\""
21
+ jiveapps.remove_collaborator(app, username)
22
+ display_collaborators
23
+ end
24
+ end
25
+
26
+ def display_collaborators
27
+ collaborators = jiveapps.list_collaborators(app)
28
+ display "=== #{collaborators.length} #{collaborators.length == 1 ? 'user has' : 'users have'} commit access to #{app}"
29
+ collaborators.each_with_index do |collaborator, index|
30
+ display "#{index+1}. #{collaborator[:username]}"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -58,6 +58,7 @@ module Jiveapps
58
58
  end
59
59
  end
60
60
 
61
+ # Ask user for input, trim the response
61
62
  def ask
62
63
  gets.strip
63
64
  end
@@ -1,3 +1,3 @@
1
1
  module Jiveapps
2
- VERSION = '0.0.9'
2
+ VERSION = '0.1.0'
3
3
  end
data/spec/client_spec.rb CHANGED
@@ -6,72 +6,74 @@ describe Jiveapps::Client do
6
6
  @client = Jiveapps::Client.new(nil, nil)
7
7
  end
8
8
 
9
- it "list -> get a list of this user's apps" do
10
- stub_api_request(:get, "/apps").to_return(:body => <<-EOXML)
11
- [
12
- {
13
- "app": {
14
- "name" : "foo",
15
- "created_at" : "2010-10-15T23:59:10Z",
16
- "updated_at" : "2010-10-15T23:59:10Z",
17
- "id" : 1
9
+ describe "apps" do
10
+ it "list -> get a list of this user's apps" do
11
+ stub_api_request(:get, "/apps").to_return(:body => <<-EOJSON)
12
+ [
13
+ {
14
+ "app": {
15
+ "name" : "foo",
16
+ "created_at" : "2010-10-15T23:59:10Z",
17
+ "updated_at" : "2010-10-15T23:59:10Z",
18
+ "id" : 1
19
+ }
20
+ },
21
+ {
22
+ "app": {
23
+ "name" : "bar",
24
+ "created_at" : "2010-10-16T01:12:16Z",
25
+ "updated_at" : "2010-10-16T01:12:16Z",
26
+ "id" : 2
27
+ }
18
28
  }
29
+ ]
30
+ EOJSON
31
+ @client.list.should == [
32
+ {
33
+ "name" => "foo",
34
+ "created_at" => "2010-10-15T23:59:10Z",
35
+ "updated_at" => "2010-10-15T23:59:10Z",
36
+ "id" => 1
19
37
  },
20
38
  {
21
- "app": {
22
- "name" : "bar",
23
- "created_at" : "2010-10-16T01:12:16Z",
24
- "updated_at" : "2010-10-16T01:12:16Z",
25
- "id" : 2
26
- }
39
+ "name" => "bar",
40
+ "created_at" => "2010-10-16T01:12:16Z",
41
+ "updated_at" => "2010-10-16T01:12:16Z",
42
+ "id" => 2
27
43
  }
28
44
  ]
29
- EOXML
30
- @client.list.should == [
31
- {
32
- "name" => "foo",
45
+ end
46
+
47
+ it "info -> get app attributes" do
48
+ stub_api_request(:get, "/apps/myapp?extended=true").to_return(:body => <<-EOJSON)
49
+ {"app":{"name":"myapp","created_at":"2010-10-15T23:59:10Z","updated_at":"2010-10-15T23:59:10Z","id":1}}
50
+ EOJSON
51
+
52
+ @client.info('myapp').should == {
53
+ "name" => "myapp",
33
54
  "created_at" => "2010-10-15T23:59:10Z",
34
55
  "updated_at" => "2010-10-15T23:59:10Z",
35
56
  "id" => 1
36
- },
37
- {
38
- "name" => "bar",
39
- "created_at" => "2010-10-16T01:12:16Z",
40
- "updated_at" => "2010-10-16T01:12:16Z",
41
- "id" => 2
42
57
  }
43
- ]
44
- end
45
-
46
- it "info -> get app attributes" do
47
- stub_api_request(:get, "/apps/myapp?extended=true").to_return(:body => <<-EOXML)
48
- {"app":{"name":"myapp","created_at":"2010-10-15T23:59:10Z","updated_at":"2010-10-15T23:59:10Z","id":1}}
49
- EOXML
50
-
51
- @client.info('myapp').should == {
52
- "name" => "myapp",
53
- "created_at" => "2010-10-15T23:59:10Z",
54
- "updated_at" => "2010-10-15T23:59:10Z",
55
- "id" => 1
56
- }
57
- end
58
+ end
58
59
 
59
- it "create -> should create a new app and return it's attributes" do
60
- stub_api_request(:post, "/apps").to_return(:body => <<-EOXML)
61
- {"app":{"name":"myapp","created_at":"2010-10-15T23:59:10Z","updated_at":"2010-10-15T23:59:10Z","id":1}}
62
- EOXML
60
+ it "create -> should create a new app and return it's attributes" do
61
+ stub_api_request(:post, "/apps").to_return(:body => <<-EOJSON)
62
+ {"app":{"name":"myapp","created_at":"2010-10-15T23:59:10Z","updated_at":"2010-10-15T23:59:10Z","id":1}}
63
+ EOJSON
63
64
 
64
- @client.create('myapp').should == {
65
- "name" => "myapp",
66
- "created_at" => "2010-10-15T23:59:10Z",
67
- "updated_at" => "2010-10-15T23:59:10Z",
68
- "id" => 1
69
- }
65
+ @client.create('myapp').should == {
66
+ "name" => "myapp",
67
+ "created_at" => "2010-10-15T23:59:10Z",
68
+ "updated_at" => "2010-10-15T23:59:10Z",
69
+ "id" => 1
70
+ }
71
+ end
70
72
  end
71
73
 
72
74
  describe "ssh keys" do
73
75
  it "fetches a list of the user's current keys" do
74
- stub_api_request(:get, "/ssh_keys").to_return(:body => <<-EOXML)
76
+ stub_api_request(:get, "/ssh_keys").to_return(:body => <<-EOJSON)
75
77
  [
76
78
  {
77
79
  "ssh_key": {
@@ -84,7 +86,7 @@ describe Jiveapps::Client do
84
86
  }
85
87
  }
86
88
  ]
87
- EOXML
89
+ EOJSON
88
90
  @client.keys.should == [
89
91
  {
90
92
  "name" => "foobar",
@@ -98,9 +100,9 @@ describe Jiveapps::Client do
98
100
  end
99
101
 
100
102
  it "add_key(key) -> add an ssh key (e.g., the contents of id_rsa.pub) to the user" do
101
- stub_api_request(:post, "/ssh_keys").to_return(:body => <<-EOXML)
103
+ stub_api_request(:post, "/ssh_keys").with(:body => "{\"ssh_key\":{\"key\":\"a key\"}}").to_return(:body => <<-EOJSON)
102
104
  {"ssh_key":{"key":"a key"}}
103
- EOXML
105
+ EOJSON
104
106
  @client.add_key('a key')
105
107
  end
106
108
 
@@ -117,5 +119,58 @@ describe Jiveapps::Client do
117
119
  # end
118
120
  end
119
121
 
122
+ describe "collaborators" do
123
+ it "list(app_name) -> list app collaborators" do
124
+ stub_api_request(:get, "/apps/myapp/collaborators").to_return(:body => <<-EOJSON)
125
+ [
126
+ {
127
+ "collaborator": {
128
+ "created_at": "2011-02-04T11:16:55-08:00",
129
+ "updated_at": "2011-02-04T11:16:55-08:00",
130
+ "app_id": 135,
131
+ "id": 637,
132
+ "user_id": 120,
133
+ "user": {
134
+ "created_at": "2011-02-04T11:16:51-08:00",
135
+ "updated_at": "2011-02-04T11:16:51-08:00",
136
+ "username": "scott.becker",
137
+ "id": 120
138
+ }
139
+ }
140
+ },
141
+ {
142
+ "collaborator": {
143
+ "created_at": "2011-02-07T17:45:26-08:00",
144
+ "updated_at": "2011-02-07T17:45:26-08:00",
145
+ "app_id": 135,
146
+ "id": 657,
147
+ "user_id": 70,
148
+ "user": {
149
+ "created_at": "2011-02-04T11:16:51-08:00",
150
+ "updated_at": "2011-02-04T11:16:51-08:00",
151
+ "username": "aron.racho",
152
+ "id": 70
153
+ }
154
+ }
155
+ }
156
+ ]
157
+ EOJSON
158
+ @client.list_collaborators('myapp').should == [
159
+ { :username => 'scott.becker' },
160
+ { :username => 'aron.racho' }
161
+ ]
162
+ end
163
+
164
+ it "add_collaborator(app_name, username) -> adds collaborator to app" do
165
+ stub_api_request(:post, "/apps/myapp/collaborators").with(:body => "{\"collaborator\":{\"username\":\"joe@example.com\"}}")
166
+ @client.add_collaborator('myapp', 'joe@example.com')
167
+ end
168
+
169
+ it "remove_collaborator(app_name, username) -> removes collaborator from app" do
170
+ stub_api_request(:delete, "/apps/myapp/collaborators/joe%40example%2Ecom")
171
+ stub_api_request(:delete, "/apps/myapp/collaborators/joe%2540example%252Ecom") # Stub double encoded version too
172
+ @client.remove_collaborator('myapp', 'joe@example.com')
173
+ end
174
+ end
120
175
 
121
176
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ module Jiveapps::Command
4
+ describe Sharing do
5
+ before do
6
+ @cli = prepare_command(Sharing)
7
+ end
8
+
9
+ it "lists collaborators" do
10
+ @cli.jiveapps.should_receive(:list_collaborators).and_return([])
11
+ @cli.list
12
+ end
13
+
14
+ it "adds collaborators with default access to view only" do
15
+ @cli.stub!(:args).and_return(['joe_coworker'])
16
+ @cli.jiveapps.should_receive(:add_collaborator).with('myapp', 'joe_coworker')
17
+ @cli.add
18
+ end
19
+
20
+ it "removes collaborators" do
21
+ @cli.stub!(:args).and_return(['joe_coworker'])
22
+ @cli.jiveapps.should_receive(:remove_collaborator).with('myapp', 'joe_coworker')
23
+ @cli.remove
24
+ end
25
+
26
+ # it "transfers ownership" do
27
+ # @cli.stub!(:args).and_return(['joe_coworker'])
28
+ # @cli.jiveapps.should_receive(:update).with('myapp', :transfer_owner => 'joe_coworker')
29
+ # @cli.transfer
30
+ # end
31
+ end
32
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jiveapps
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 9
10
- version: 0.0.9
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Scott Becker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-28 00:00:00 -08:00
18
+ date: 2011-02-16 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -137,7 +137,9 @@ files:
137
137
  - app_generators/create/templates/canvas.html
138
138
  - app_generators/create/templates/hello.html
139
139
  - app_generators/create/templates/home.html
140
- - app_generators/create/templates/images/j-icon-jaf-48.png
140
+ - app_generators/create/templates/images/icon128.png
141
+ - app_generators/create/templates/images/icon16.png
142
+ - app_generators/create/templates/images/icon48.png
141
143
  - app_generators/create/templates/javascripts/main.js
142
144
  - app_generators/create/templates/stylesheets/main.css
143
145
  - autotest/discover.rb
@@ -152,12 +154,14 @@ files:
152
154
  - lib/jiveapps/commands/help.rb
153
155
  - lib/jiveapps/commands/keys.rb
154
156
  - lib/jiveapps/commands/oauth.rb
157
+ - lib/jiveapps/commands/sharing.rb
155
158
  - lib/jiveapps/helpers.rb
156
159
  - lib/jiveapps/version.rb
157
160
  - spec/client_spec.rb
158
161
  - spec/commands/app_spec.rb
159
162
  - spec/commands/base_spec.rb
160
163
  - spec/commands/keys_spec.rb
164
+ - spec/commands/sharing_spec.rb
161
165
  - spec/spec_helper.rb
162
166
  has_rdoc: true
163
167
  homepage: https://github.com/jivesoftware/jiveapps-gem
@@ -189,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
193
  requirements: []
190
194
 
191
195
  rubyforge_project:
192
- rubygems_version: 1.4.2
196
+ rubygems_version: 1.5.0
193
197
  signing_key:
194
198
  specification_version: 3
195
199
  summary: The "jiveapps" gem is a set of command line tools for building and hosting Jive App front-ends.
@@ -198,4 +202,5 @@ test_files:
198
202
  - spec/commands/app_spec.rb
199
203
  - spec/commands/base_spec.rb
200
204
  - spec/commands/keys_spec.rb
205
+ - spec/commands/sharing_spec.rb
201
206
  - spec/spec_helper.rb