mongo_fe 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.
Files changed (71) hide show
  1. data/.DS_Store +0 -0
  2. data/.gitignore +34 -0
  3. data/.rspec +2 -0
  4. data/CHANGES.md +3 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +138 -0
  7. data/LICENSE +22 -0
  8. data/Procfile +2 -0
  9. data/README.md +72 -0
  10. data/Rakefile +14 -0
  11. data/TODO.tasks +9 -0
  12. data/bin/config.ru +28 -0
  13. data/bin/mongofe +54 -0
  14. data/lib/mongo_fe/application_controller.rb +91 -0
  15. data/lib/mongo_fe/controllers/collections_controller.rb +278 -0
  16. data/lib/mongo_fe/controllers/databases_controller.rb +94 -0
  17. data/lib/mongo_fe/helpers/helpers.rb +128 -0
  18. data/lib/mongo_fe/public/app/application.js +3 -0
  19. data/lib/mongo_fe/public/bootstrap/css/bootstrap-responsive.css +567 -0
  20. data/lib/mongo_fe/public/bootstrap/css/bootstrap.css +3380 -0
  21. data/lib/mongo_fe/public/bootstrap/img/glyphicons-halflings-white.png +0 -0
  22. data/lib/mongo_fe/public/bootstrap/img/glyphicons-halflings.png +0 -0
  23. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-alert.js +91 -0
  24. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-button.js +98 -0
  25. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-carousel.js +154 -0
  26. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-collapse.js +136 -0
  27. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-dropdown.js +92 -0
  28. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-modal.js +209 -0
  29. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-popover.js +95 -0
  30. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-scrollspy.js +125 -0
  31. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-tab.js +130 -0
  32. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-tooltip.js +270 -0
  33. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-transition.js +51 -0
  34. data/lib/mongo_fe/public/bootstrap/js/basic/bootstrap-typeahead.js +271 -0
  35. data/lib/mongo_fe/public/bootstrap/js/bootstrap.js +1722 -0
  36. data/lib/mongo_fe/public/bootstrap/js/bootstrap.min.js +1 -0
  37. data/lib/mongo_fe/public/bootstrap/js/jquery.js +9252 -0
  38. data/lib/mongo_fe/public/bootstrap/js/underscore-min.js +32 -0
  39. data/lib/mongo_fe/public/bootstrap/js/underscore.js +1059 -0
  40. data/lib/mongo_fe/public/css/digg_pagination.css +28 -0
  41. data/lib/mongo_fe/public/css/jsoneditor.css +70 -0
  42. data/lib/mongo_fe/public/css/styles.css +11 -0
  43. data/lib/mongo_fe/public/images/missing_avatar_small.png +0 -0
  44. data/lib/mongo_fe/public/js/collection-tools.js +63 -0
  45. data/lib/mongo_fe/public/js/db-tools.js +45 -0
  46. data/lib/mongo_fe/public/js/jsoneditor/jquery.jsoneditor.min.LICENSE +20 -0
  47. data/lib/mongo_fe/public/js/jsoneditor/jquery.jsoneditor.min.js +6 -0
  48. data/lib/mongo_fe/public/js/jsoneditor/json2.js +482 -0
  49. data/lib/mongo_fe/version.rb +6 -0
  50. data/lib/mongo_fe/views/collections/_document_attributes.haml +6 -0
  51. data/lib/mongo_fe/views/collections/_documents.haml +35 -0
  52. data/lib/mongo_fe/views/collections/_documents_page.haml +82 -0
  53. data/lib/mongo_fe/views/collections/_indexes.haml +76 -0
  54. data/lib/mongo_fe/views/collections/index.haml +80 -0
  55. data/lib/mongo_fe/views/databases/_list_users.haml +27 -0
  56. data/lib/mongo_fe/views/databases/info.haml +80 -0
  57. data/lib/mongo_fe/views/footer.haml +4 -0
  58. data/lib/mongo_fe/views/index.haml +7 -0
  59. data/lib/mongo_fe/views/layout.haml +148 -0
  60. data/lib/mongo_fe/views/navbar.haml +17 -0
  61. data/lib/mongo_fe.rb +170 -0
  62. data/mongo_fe.gemspec +50 -0
  63. data/screens/example_db_view.png +0 -0
  64. data/screens/example_doc_view.png +0 -0
  65. data/screens/example_indexes.png +0 -0
  66. data/spec/config_spec.rb +17 -0
  67. data/spec/controllers/collections_controller_spec.rb +151 -0
  68. data/spec/controllers/db_controller_spec.rb +69 -0
  69. data/spec/factories/factories.rb +19 -0
  70. data/spec/spec_helper.rb +88 -0
  71. metadata +559 -0
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe "MongoFe" do
4
+ describe "the gem configuration" do
5
+ it "is versioned" do
6
+ MongoFe::VERSION.should =~ /\d+\.\d+\.\d+/
7
+ end
8
+
9
+ it "has access to a local database" do
10
+ MongoFe::MongoDB.connection.should_not be_nil
11
+ end
12
+
13
+ it "can access some data" do
14
+ MongoFe::MongoDB.available_databases.count.should >= 0
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,151 @@
1
+ require "spec_helper"
2
+ require "ostruct"
3
+ require "json"
4
+
5
+ describe "Collections Controller" do
6
+ class Index
7
+ attr_accessor :name
8
+ attr_reader :fields
9
+
10
+ def initialize(fields="", unique=true, sparse=false)
11
+ @fields=fields
12
+ @unique=unique
13
+ @sparse=sparse
14
+ end
15
+
16
+ def unique?
17
+ @unique
18
+ end
19
+
20
+ def sparse?
21
+ @sparse
22
+ end
23
+ end
24
+
25
+ let(:db_name) { "mongo_fe_test_db_collections_29837419283741928374192834719283" }
26
+ let(:collection_name) { "my_mongo_fe_collection" }
27
+ let(:collection_new_name) { "my_new_mongo_fe_collection" }
28
+
29
+ # use Time.new.strftime("%d-%m-%Y")? meh
30
+ let(:test_doc) { {:lng => "gr", :description => "Hopa!", :created_at => Time.now.to_i} }
31
+ let(:test_doc_json) { test_doc.to_json }
32
+
33
+ let(:index) { Index.new("lng:asc, created_at:desc") }
34
+
35
+ # select/create a test database
36
+ before(:all) do
37
+ get "/databases/#{db_name}"
38
+ end
39
+
40
+ # clean the test database.
41
+ after(:all) do
42
+ delete "/databases/#{db_name}"
43
+ end
44
+
45
+ # Adding a new collection to a test database
46
+ describe "POST /databases/:db_name/collections/" do
47
+ it "should create a new collection" do
48
+ post "/databases/#{db_name}/collections", {:collection_name => collection_name}
49
+ follow_redirect!
50
+ last_response.body.should contain("#{collection_name}, successfully created!")
51
+ end
52
+ end
53
+
54
+ # return success if a database is selected and we want to display the available
55
+ # collections
56
+ describe "GET /databases/:db_name/collections" do
57
+ #,{}, "rack.session" => {:session => {:db => "test"} } .... meh
58
+ it "should list all the collections available" do
59
+ get "/databases/#{db_name}/collections"
60
+ last_response.status.should eq(200)
61
+ last_response.body.should contain("#{collection_name}")
62
+ end
63
+ end
64
+
65
+ describe "GET /databases/:db_name/collections/:collection_name" do
66
+ it "should display the stats for the given collection" do
67
+ get "/databases/#{db_name}/collections/#{collection_name}"
68
+ last_response.body.should contain("\"ns\": \"#{db_name}.#{collection_name}\"")
69
+ end
70
+ end
71
+
72
+ describe "PUT /databases/:db_name/collections/:collection_name" do
73
+ it "should rename a collection" do
74
+ put "/databases/#{db_name}/collections/#{collection_name}", {:collection_new_name => collection_new_name}
75
+ follow_redirect!
76
+ last_response.body.should_not contain("\"ns\": \"#{db_name}.#{collection_name}\"")
77
+ last_response.body.should contain("\"ns\": \"#{db_name}.#{collection_new_name}\"")
78
+ end
79
+ end
80
+
81
+ describe "POST /databases/:db_name/collections/:collection_name/documents" do
82
+ it "should insert a new document" do
83
+ post "/databases/#{db_name}/collections/#{collection_name}/documents", {:json_doc_attributes => test_doc_json}
84
+ last_response.body.should contain("added to: #{db_name}.#{collection_name}")
85
+ # todo verify the Document insertion
86
+ end
87
+ end
88
+
89
+ describe "DELETE /databases/:db_name/collections/:collection_name/documents" do
90
+ it "should delete an existing document" do
91
+
92
+ db = MongoFe::MongoDB.use db_name
93
+ db.should_not be_nil
94
+
95
+ c = db.collection(collection_name)
96
+ c.should_not be_nil
97
+
98
+ doc = c.find_one test_doc
99
+ doc.should_not be_nil
100
+
101
+ doc_id=doc['_id'].to_s
102
+ delete "/databases/#{db_name}/collections/#{collection_name}/documents", {:doc_id => doc_id}
103
+ follow_redirect!
104
+ last_response.body.should contain("deleted from: #{db_name}.#{collection_name}")
105
+ end
106
+ end
107
+
108
+ describe "POST /databases/:db_name/collections/:collection_name/indexes" do
109
+ it "should create a new index" do
110
+ post "/databases/#{db_name}/collections/#{collection_name}/indexes",
111
+ {:index_fields => index.fields, :index_unique => index.unique?, :sparse => index.sparse?}
112
+
113
+ follow_redirect!
114
+ # "The index: '#{index_name}' was successfully created"
115
+ index.name = last_response.body[/index: '([^']+)/,1]
116
+ last_response.body.should contain("was successfully created")
117
+ end
118
+ end
119
+
120
+ # Drop a collection index
121
+ describe "DELETE /databases/:db_name/collections/:collection_name/indexes" do
122
+ it "should delete an existing index" do
123
+ db = MongoFe::MongoDB.use db_name
124
+ db.should_not be_nil
125
+
126
+ collection = db.collection(collection_name)
127
+ collection.name.should_not be_nil
128
+
129
+ indexes = collection.index_information
130
+ indexes.should contain(index.name)
131
+
132
+ delete "/databases/#{db_name}/collections/#{collection_name}/indexes", {:index_name => index.name}
133
+ follow_redirect!
134
+ last_response.body.should contain("The index: '#{index.name}', was deleted successfully.")
135
+
136
+ indexes = collection.index_information
137
+ indexes.should_not contain(index.name)
138
+ end
139
+ end
140
+
141
+ # Delete a collection from a test database
142
+ describe "DELETE /databases/:db_name/collections/:collection_name" do
143
+ it "should delete a collection" do
144
+ delete "/databases/#{db_name}/collections/#{collection_name}"
145
+ # , {:collection_name => collection_name}
146
+ follow_redirect!
147
+ last_response.body.should contain("#{collection_name}, deleted.")
148
+ end
149
+ end
150
+
151
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Databases Controller" do
4
+ # careful not to overwrite any existing db; todo: improve the naming solution
5
+ let(:db_name) { "mongo_fe_test_db_01293801983479827349832987234987234987" }
6
+ let(:new_db_name) { "mongo_fe_test_db_012938019747473873563872ABHEYYO827PI12" }
7
+
8
+ describe "GET /databases" do
9
+ it "should return success" do
10
+ get '/databases'
11
+ last_response.body.should contain("Move along, nothing to see here!")
12
+ end
13
+ end
14
+
15
+ describe "POST /databases" do
16
+ context "when a new database is successfully created" do
17
+ before(:all) do
18
+ post '/databases', {:name => db_name}
19
+ end
20
+
21
+ it "returns a 302 response code" do
22
+ last_response.status.should eq(302)
23
+ end
24
+
25
+ it "should create a new database" do
26
+ get "/databases/#{db_name}"
27
+ last_response.body.should contain("#{db_name}")
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ describe "GET /databases/:name" do
34
+ it "should return info about the newly created database" do
35
+ get "/databases/#{db_name}"
36
+ last_response.body.should contain("\"db\": \"#{db_name}\",")
37
+ end
38
+ end
39
+
40
+ # test the user creation
41
+ describe "POST /databases/:name/users" do
42
+ let(:test_user) { FactoryGirl.build(:user) }
43
+ it "should create a new user" do
44
+ post "/databases/#{db_name}/users", {:username => test_user.username,
45
+ :password => test_user.password, :readonly => test_user.readonly}
46
+ follow_redirect!
47
+ last_response.body.should contain("User: '#{test_user.username}', was added successfully.")
48
+ # or better:
49
+ # flash[:notice].should =~ /User: '#{test_user.username}', was added successfully./
50
+ end
51
+ end
52
+
53
+ # test the user deletion
54
+ describe "DELETE /databases/:name/users" do
55
+ let(:test_user) { FactoryGirl.build(:user) }
56
+ it "should delete a user" do
57
+ delete "/databases/#{db_name}/users", {:username => test_user.username}
58
+ follow_redirect!
59
+ last_response.body.should contain("User deleted: '#{test_user.username}'")
60
+ end
61
+ end
62
+
63
+ describe "DELETE /databases/:name" do
64
+ it "should delete a database" do
65
+ delete "/databases/#{db_name}"
66
+ last_response.body.should contain("Database: #{db_name} was deleted.")
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,19 @@
1
+ FactoryGirl.define do
2
+ # user.rb
3
+ class User
4
+ attr_accessor :username, :email, :password, :readonly, :created_at
5
+ end
6
+
7
+ sequence :email do |n|
8
+ "user#{n}@example.com"
9
+ end
10
+
11
+ factory :user do
12
+ username "alphaville"
13
+ email
14
+ password "password"
15
+ readonly true
16
+ # created_at { rand(10).days.ago }
17
+ end
18
+
19
+ end
@@ -0,0 +1,88 @@
1
+ ENV["RACK_ENV"] ||= "test"
2
+
3
+ require 'rack/test'
4
+ require "hashie/mash"
5
+ require 'yajl'
6
+ require 'cgi'
7
+ require "yaml"
8
+ require "mongo"
9
+ require "rspec"
10
+ require "SimpleCov"
11
+ require 'factory_girl'
12
+ require "webrat"
13
+ require 'shoulda-matchers'
14
+ require "sinatra/base"
15
+ require "sinatra/contrib"
16
+ require 'will_paginate'
17
+ require 'will_paginate/array'
18
+ require 'will_paginate/view_helpers/sinatra'
19
+ require 'will_paginate/view_helpers/link_renderer'
20
+
21
+ SimpleCov.start
22
+
23
+ Dir["./lib/**/*.rb"].each { |f| require f}
24
+
25
+ #load factories
26
+ Dir[File.dirname(__FILE__)+"/factories/*.rb"].each { |file| require file}
27
+
28
+ Webrat.configure do |conf|
29
+ conf.mode = :rack
30
+ end
31
+
32
+
33
+ # see: http://bit.ly/KureJx, for a similar discussion
34
+ # and this is my solution:
35
+ module RSpecMixin
36
+ include Rack::Test::Methods
37
+ include Webrat::Methods
38
+ include Webrat::Matchers
39
+ include FactoryGirl::Syntax::Methods
40
+
41
+ begin
42
+ require "./lib/mongo_fe"
43
+
44
+ config = Hashie::Mash.new (YAML.load(File.new(File.expand_path('~/.mongo_fe'))))
45
+ MongoFe::MongoDB.uri = config.uri
46
+ rescue
47
+ puts "You must create a file in your home directory called .mongo_fe; error: #{$!.message}"
48
+ exit 1
49
+ end
50
+
51
+ def self.app=(application)
52
+ @app = application
53
+ end
54
+
55
+ def self.app
56
+ @app
57
+ end
58
+
59
+ def app
60
+ RSpecMixin.app ||=
61
+ Rack::Builder.new do
62
+ Dir.glob('../lib/{mongo_fe,mongo_fe/helpers,mongo_fe/controllers}/*.rb').each { |file| require file }
63
+ use MongoFe::ApplicationController
64
+ use MongoFe::DatabasesController
65
+ use MongoFe::CollectionsController
66
+
67
+ run Sinatra::Base
68
+ end
69
+ end
70
+
71
+ def request
72
+ last_request
73
+ end
74
+
75
+ def session
76
+ last_request.env['rack.session']
77
+ end
78
+
79
+ end
80
+
81
+ RSpec.configure { |c| c.include RSpecMixin }
82
+
83
+ RSpec.configure do |c|
84
+ c.include Rack::Test::Methods
85
+ c.include Webrat::Methods
86
+ c.include Webrat::Matchers
87
+ c.include FactoryGirl::Syntax::Methods
88
+ end