jiveapps 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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