@@ -6,6 +6,7 @@ |
||
6 | 6 |
#= require jquery.json-editor |
7 | 7 |
#= require latlon_and_geo |
8 | 8 |
#= require ./worker-checker |
9 |
+#= require ./users |
|
9 | 10 |
#= require_self |
10 | 11 |
|
11 | 12 |
window.setupJsonEditor = ($editor = $(".live-json-editor")) -> |
@@ -0,0 +1,13 @@ |
||
1 |
+//alert("i get included"); |
|
2 |
+function remove_fields(link){ |
|
3 |
+ $(link).prev().val("1"); |
|
4 |
+ $(link).parent(".fields").hide(); |
|
5 |
+} |
|
6 |
+ |
|
7 |
+function add_fields(link, association, content) { |
|
8 |
+ var new_id = new Date().getTime(); |
|
9 |
+ var regexp = new RegExp("new_" + association, "g") |
|
10 |
+ $(link).parent().before(content.replace(regexp, new_id)); |
|
11 |
+} |
|
12 |
+ |
|
13 |
+ |
@@ -14,4 +14,18 @@ module ApplicationHelper |
||
14 | 14 |
link_to '<span class="label label-warning">No</span>'.html_safe, agent_path(agent, :tab => (agent.recent_error_logs? ? 'logs' : 'details')) |
15 | 15 |
end |
16 | 16 |
end |
17 |
+ |
|
18 |
+ def link_to_remove_fields(name, f, options = {}) |
|
19 |
+ f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)", options) |
|
20 |
+ end |
|
21 |
+ |
|
22 |
+ def link_to_add_fields(name, f, options = {}) |
|
23 |
+ association = options[:association] |
|
24 |
+ new_object = f.object.class.reflect_on_association(association).klass.new |
|
25 |
+ fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| |
|
26 |
+ render(association.to_s.singularize + "_fields", :f => builder) |
|
27 |
+ end |
|
28 |
+ link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")") |
|
29 |
+ end |
|
30 |
+ |
|
17 | 31 |
end |
@@ -59,6 +59,10 @@ class Agent < ActiveRecord::Base |
||
59 | 59 |
where(:type => type) |
60 | 60 |
} |
61 | 61 |
|
62 |
+ def credential(name) |
|
63 |
+ user.user_credentials.where(:credential_name => name).first.try(:credential_value) || nil |
|
64 |
+ end |
|
65 |
+ |
|
62 | 66 |
def check |
63 | 67 |
# Implement me in your subclass of Agent. |
64 | 68 |
end |
@@ -22,6 +22,10 @@ class User < ActiveRecord::Base |
||
22 | 22 |
validates_format_of :username, :with => /\A[a-zA-Z0-9_-]{3,15}\Z/, :message => "can only contain letters, numbers, underscores, and dashes, and must be between 3 and 15 characters in length." |
23 | 23 |
validates_inclusion_of :invitation_code, :on => :create, :in => INVITATION_CODES, :message => "is not valid" |
24 | 24 |
|
25 |
+ has_many :user_credentials, :dependent => :destroy |
|
26 |
+ accepts_nested_attributes_for :user_credentials, |
|
27 |
+ :allow_destroy => true |
|
28 |
+ attr_accessible :user_credentials_attributes |
|
25 | 29 |
has_many :events, :order => "events.created_at desc", :dependent => :delete_all, :inverse_of => :user |
26 | 30 |
has_many :agents, :order => "agents.created_at desc", :dependent => :destroy, :inverse_of => :user |
27 | 31 |
has_many :logs, :through => :agents, :class_name => "AgentLog" |
@@ -0,0 +1,6 @@ |
||
1 |
+class UserCredential < ActiveRecord::Base |
|
2 |
+ attr_accessible :credential_name, :credential_value, :user_id |
|
3 |
+ belongs_to :user |
|
4 |
+ validates_presence_of :credential_name |
|
5 |
+ validates_uniqueness_of :credential_name, :scope => :user_id |
|
6 |
+end |
@@ -0,0 +1,9 @@ |
||
1 |
+<p class="fields"> |
|
2 |
+ <%= f.label :credential_name, "Name" %> |
|
3 |
+ <%= f.text_field :credential_name %> |
|
4 |
+ <%= f.label :credential_value, "Value" %> |
|
5 |
+ <%= f.text_field :credential_value %> |
|
6 |
+ <%= f.hidden_field :_destroy %> |
|
7 |
+ <%= link_to_remove_fields("remove", f) %> |
|
8 |
+</p> |
|
9 |
+ |
@@ -48,6 +48,12 @@ |
||
48 | 48 |
<div class='form-actions'> |
49 | 49 |
<%= f.submit "Update", :class => "btn btn-primary" %> |
50 | 50 |
</div> |
51 |
+ <div class="control-group"> |
|
52 |
+ <%= f.fields_for(:user_credentials) do |uc| %> |
|
53 |
+ <%= render 'user_credential_fields', :f => uc %> |
|
54 |
+ <% end %> |
|
55 |
+ </div> |
|
56 |
+ <p><%= link_to_add_fields "Add A Credential", f, :association => :user_credentials %></p> |
|
51 | 57 |
<% end %> |
52 | 58 |
|
53 | 59 |
<h3>Cancel my account</h3> |
@@ -58,4 +64,4 @@ |
||
58 | 64 |
</div> |
59 | 65 |
</div> |
60 | 66 |
</div> |
61 |
-</div> |
|
67 |
+</div> |
@@ -0,0 +1,12 @@ |
||
1 |
+class CreateUserCredentials < ActiveRecord::Migration |
|
2 |
+ def change |
|
3 |
+ create_table :user_credentials do |t| |
|
4 |
+ t.integer :user_id |
|
5 |
+ t.string :credential_name |
|
6 |
+ t.string :credential_value |
|
7 |
+ |
|
8 |
+ t.timestamps |
|
9 |
+ end |
|
10 |
+ add_index :user_credentials, [:user_id, :credential_name], :unique => true |
|
11 |
+ end |
|
12 |
+end |
@@ -11,7 +11,7 @@ |
||
11 | 11 |
# |
12 | 12 |
# It's strongly recommended to check this file into your version control system. |
13 | 13 |
|
14 |
-ActiveRecord::Schema.define(:version => 20131227000021) do |
|
14 |
+ActiveRecord::Schema.define(:version => 20140121075418) do |
|
15 | 15 |
|
16 | 16 |
create_table "agent_logs", :force => true do |t| |
17 | 17 |
t.integer "agent_id", :null => false |
@@ -87,6 +87,16 @@ ActiveRecord::Schema.define(:version => 20131227000021) do |
||
87 | 87 |
add_index "links", ["receiver_id", "source_id"], :name => "index_links_on_receiver_id_and_source_id" |
88 | 88 |
add_index "links", ["source_id", "receiver_id"], :name => "index_links_on_source_id_and_receiver_id" |
89 | 89 |
|
90 |
+ create_table "user_credentials", :force => true do |t| |
|
91 |
+ t.integer "user_id" |
|
92 |
+ t.string "credential_name" |
|
93 |
+ t.string "credential_value" |
|
94 |
+ t.datetime "created_at", :null => false |
|
95 |
+ t.datetime "updated_at", :null => false |
|
96 |
+ end |
|
97 |
+ |
|
98 |
+ add_index "user_credentials", ["user_id", "credential_name"], :name => "index_user_credentials_on_user_id_and_credential_name", :unique => true |
|
99 |
+ |
|
90 | 100 |
create_table "users", :force => true do |t| |
91 | 101 |
t.string "email", :default => "", :null => false |
92 | 102 |
t.string "encrypted_password", :default => "", :null => false |
@@ -0,0 +1,8 @@ |
||
1 |
+bob_aws_key: |
|
2 |
+ user: bob |
|
3 |
+ credential_name: aws_key |
|
4 |
+ credential_value: 2222222222 |
|
5 |
+bob_aws_secret: |
|
6 |
+ user: bob |
|
7 |
+ credential_name: aws_secret |
|
8 |
+ credential_value: 1111111111 |
@@ -27,6 +27,16 @@ describe Agent do |
||
27 | 27 |
end |
28 | 28 |
end |
29 | 29 |
|
30 |
+ describe "credential" do |
|
31 |
+ it "should return the value of the credential when credential is present" do |
|
32 |
+ agents(:bob_weather_agent).credential("aws_secret").should == user_credentials(:bob_aws_secret).credential_value |
|
33 |
+ end |
|
34 |
+ |
|
35 |
+ it "should return nil when credential is not present" do |
|
36 |
+ agents(:bob_weather_agent).credential("non_existing_credential").should == nil |
|
37 |
+ end |
|
38 |
+ end |
|
39 |
+ |
|
30 | 40 |
describe "changes to type" do |
31 | 41 |
it "validates types" do |
32 | 42 |
source = Agent.new |
@@ -473,4 +483,4 @@ describe Agent do |
||
473 | 483 |
end |
474 | 484 |
end |
475 | 485 |
end |
476 |
-end |
|
486 |
+end |
@@ -0,0 +1,14 @@ |
||
1 |
+require 'spec_helper' |
|
2 |
+ |
|
3 |
+describe UserCredential do |
|
4 |
+ describe "validation" do |
|
5 |
+ it {should validate_uniqueness_of(:credential_name).scoped_to(:user_id)} |
|
6 |
+ end |
|
7 |
+ describe "mass assignment" do |
|
8 |
+ it {should allow_mass_assignment_of :credential_name} |
|
9 |
+ |
|
10 |
+ it {should allow_mass_assignment_of :credential_value} |
|
11 |
+ |
|
12 |
+ it {should allow_mass_assignment_of :user_id} |
|
13 |
+ end |
|
14 |
+end |
@@ -16,4 +16,12 @@ describe User do |
||
16 | 16 |
end |
17 | 17 |
end |
18 | 18 |
end |
19 |
-end |
|
19 |
+ |
|
20 |
+ describe "nested attributes" do |
|
21 |
+ it { should accept_nested_attributes_for(:user_credentials).allow_destroy(true) } |
|
22 |
+ end |
|
23 |
+ |
|
24 |
+ describe "mass assignment" do |
|
25 |
+ it {should allow_mass_assignment_of :user_credentials_attributes} |
|
26 |
+ end |
|
27 |
+end |