yodel_production_environment 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +1 -0
  4. data/lib/layouts/common.html +23 -0
  5. data/lib/layouts/common/site.html +79 -0
  6. data/lib/layouts/common/sites.html +13 -0
  7. data/lib/layouts/common/user.html +10 -0
  8. data/lib/layouts/common/users.html +30 -0
  9. data/lib/layouts/home.html +49 -0
  10. data/lib/layouts/production_login_page.html +131 -0
  11. data/lib/migrations/site/01_users_model.rb +23 -0
  12. data/lib/migrations/site/02_page_structure.rb +58 -0
  13. data/lib/migrations/site/03_security_and_home_page.rb +103 -0
  14. data/lib/migrations/yodel/01_record_model.rb +29 -0
  15. data/lib/migrations/yodel/02_page_model.rb +45 -0
  16. data/lib/migrations/yodel/03_layout_model.rb +38 -0
  17. data/lib/migrations/yodel/04_group_model.rb +61 -0
  18. data/lib/migrations/yodel/05_user_model.rb +23 -0
  19. data/lib/migrations/yodel/06_snippet_model.rb +13 -0
  20. data/lib/migrations/yodel/07_search_page_model.rb +32 -0
  21. data/lib/migrations/yodel/08_default_site_options.rb +21 -0
  22. data/lib/migrations/yodel/09_security_page_models.rb +36 -0
  23. data/lib/migrations/yodel/10_record_proxy_page_model.rb +17 -0
  24. data/lib/migrations/yodel/11_email_model.rb +28 -0
  25. data/lib/migrations/yodel/12_api_call_model.rb +23 -0
  26. data/lib/migrations/yodel/13_redirect_page_model.rb +13 -0
  27. data/lib/migrations/yodel/14_menu_model.rb +20 -0
  28. data/lib/models/git_http.rb +326 -0
  29. data/lib/models/git_page.rb +38 -0
  30. data/lib/models/production_login_page.rb +13 -0
  31. data/lib/models/production_sites_page.rb +127 -0
  32. data/lib/models/production_user.rb +17 -0
  33. data/lib/public/css/screen.css +64 -0
  34. data/lib/yodel_production_environment.rb +3 -0
  35. data/yodel_production_environment.gemspec +22 -0
  36. metadata +80 -0
@@ -0,0 +1,103 @@
1
+ class SecurityAndHomePageMigration < Migration
2
+ def self.up(site)
3
+ # existing pages
4
+ home = site.pages.where(path: '/').first
5
+ sites_page = site.pages.where(path: '/sites').first
6
+
7
+ # change home page to a normal page until editable production sites are ready
8
+ home.model = site.pages
9
+ home.page_layout = 'home'
10
+ home.save
11
+
12
+ # login page
13
+ site.login_pages.create_model :production_login_page do |production_login_pages|
14
+ production_login_pages.record_class_name = 'ProductionLoginPage'
15
+ end
16
+
17
+ login_page = site.production_login_pages.new
18
+ login_page.title = 'Login'
19
+ login_page.redirect_to = sites_page
20
+ login_page.parent = home
21
+ login_page.save
22
+
23
+ # remove login from the nav menu
24
+ nav = site.menus.first(name: 'nav')
25
+ login_ex = nav.exceptions.new
26
+ login_ex.page = login_page
27
+ login_ex.show = false
28
+ login_ex.save
29
+ nav.save
30
+
31
+ # logout page
32
+ logout_page = site.logout_pages.new
33
+ logout_page.title = 'Logout'
34
+ logout_page.redirect_to = home
35
+ logout_page.parent = home
36
+ logout_page.save
37
+
38
+ # prevent guest html requests; the sites and git pages implement their
39
+ # own auth for json requests
40
+ site.sites_pages.modify do |sites_pages|
41
+ sites_pages.view_group = site.groups['Administrators']
42
+ sites_pages.create_group = site.groups['Administrators']
43
+ sites_pages.update_group = site.groups['Administrators']
44
+ sites_pages.delete_group = site.groups['No One']
45
+ end
46
+
47
+ site.users.modify do |users|
48
+ users.view_group = site.groups['Administrators']
49
+ users.create_group = site.groups['Administrators']
50
+ users.update_group = site.groups['Administrators']
51
+ users.delete_group = site.groups['Administrators']
52
+ end
53
+
54
+ users_page = site.pages.where(path: '/users').first
55
+ users_page.model.modify do |users_page|
56
+ users_page.view_group = site.groups['Administrators']
57
+ users_page.create_group = site.groups['Administrators']
58
+ users_page.update_group = site.groups['Administrators']
59
+ users_page.delete_group = site.groups['No One']
60
+ end
61
+ end
62
+
63
+ def self.down(site)
64
+ # remove the login nav menu exception
65
+ nav = site.menus.first(name: 'nav')
66
+ login_ex = nav.exceptions.select {|ex| ex.page.path == '/login'}
67
+ login_ex.destroy
68
+ nav.save
69
+
70
+ # login/logout pages
71
+ site.pages.where(path: '/login').destroy
72
+ site.pages.where(path: '/logout').destroy
73
+
74
+ # reset homepage to a redirect page
75
+ home = site.pages.where(path: '/').first
76
+ home.model = site.redirect_pages
77
+ home.url = '/users'
78
+ home.save
79
+
80
+ # remove auth
81
+ site.sites_pages.modify do |sites_pages|
82
+ sites_pages.view_group = site.groups['Guests']
83
+ sites_pages.create_group = site.groups['Guests']
84
+ sites_pages.update_group = site.groups['Guests']
85
+ sites_pages.delete_group = site.groups['Guests']
86
+ end
87
+
88
+ site.users.modify do |users|
89
+ sites_pages.view_group = site.groups['Guests']
90
+ sites_pages.create_group = site.groups['Guests']
91
+ sites_pages.update_group = site.groups['Guests']
92
+ sites_pages.delete_group = site.groups['Guests']
93
+ end
94
+
95
+ users_page = site.pages.where(path: '/users').first
96
+ users_page.model.modify do |users_page|
97
+ sites_pages.view_group = site.groups['Guests']
98
+ sites_pages.create_group = site.groups['Guests']
99
+ sites_pages.update_group = site.groups['Guests']
100
+ sites_pages.delete_group = site.groups['Guests']
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,29 @@
1
+ class RecordModelMigration < Migration
2
+ def self.up(site)
3
+ records = Model.new(site, name: 'Record')
4
+ records.modify do |records|
5
+ # identity, hierarchy and search
6
+ add_many :children, model: :record, foreign_key: 'parent', order: 'index asc', display: false
7
+ add_field :index, :integer, validations: {required: {}}, display: false
8
+ add_one :owner, model: :user, display: false
9
+ add_field :name, :string
10
+ add_field :show_in_search, :boolean, default: true, section: 'Options'
11
+ add_field :search_keywords, :array, of: :string, display: false
12
+ add_field :search_title, :string, display: false
13
+
14
+ # modelling
15
+ add_one :eigenmodel, model: :model, destroy: true, display: false
16
+ add_one :parent, model: :record, index: true, display: false
17
+ add_one :model, index: true, display: false
18
+ records.descendants = [records]
19
+ end
20
+
21
+ site.model_types['records'] = records.id
22
+ site.model_plural_names['Record'] = 'records'
23
+ site.save
24
+ end
25
+
26
+ def self.down(site)
27
+ site.records.destroy
28
+ end
29
+ end
@@ -0,0 +1,45 @@
1
+ class PageModelMigration < Migration
2
+ def self.up(site)
3
+ site.records.create_model :pages do |pages|
4
+ # core page attributes
5
+ add_field :permalink, :string, validations: {required: {}}, index: true, searchable: false, display: false
6
+ add_field :path, :string, validations: {required: {}}, index: true, searchable: false, display: false
7
+ add_field :created_at, :time, display: false
8
+ add_field :title, :string, validations: {required: {}}
9
+ add_field :content, :html
10
+
11
+ # options section
12
+ add_field :show_in_menus, :boolean, default: true, section: 'Options'
13
+ add_field :description, :text, section: 'Options', searchable: false
14
+ add_field :keywords, :text, section: 'Options', searchable: false
15
+ add_field :custom_meta_tags, :text, section: 'Options', searchable: false
16
+ add_one :new_child_page, model: :page, section: 'Options', show_blank: true, blank_text: 'None'
17
+
18
+ # layout
19
+ add_field :page_layout, :string, section: 'Options', default: nil, searchable: false
20
+ add_one :page_layout_record, model: :layout, display: false
21
+ add_field :edit_layout, :string, searchable: false, section: 'Options'
22
+ add_one :edit_layout_record, model: :layout, display: false
23
+
24
+ add_field :name, :alias, of: :title
25
+ pages.default_child_model = pages.id
26
+ pages.allowed_children = [pages]
27
+ pages.allowed_parents = [pages]
28
+ pages.record_class_name = 'Page'
29
+ end
30
+
31
+ # glob pages are normal pages, but match paths with components at the end
32
+ # of the page's path, e.g /git/HEAD would match the glob page /git
33
+ site.pages.create_model :glob_pages do |glob_pages|
34
+ end
35
+
36
+ # default root page
37
+ page = site.pages.new
38
+ page.title = "Home"
39
+ page.save
40
+ end
41
+
42
+ def self.down(site)
43
+ site.pages.destroy
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ class LayoutModelMigration < Migration
2
+ def self.up(site)
3
+ site.records.create_model :layouts do |layouts|
4
+ add_field :name, :string, validations: {required: {}}, index: true
5
+ add_field :mime_type, :string, validations: {required: {}}, index: true
6
+
7
+ layouts.allowed_children = []
8
+ layouts.allowed_parents = []
9
+ layouts.searchable = false
10
+ layouts.record_class_name = 'Layout'
11
+ end
12
+
13
+ site.layouts.create_model :persistent_layouts do |persistent_layouts|
14
+ add_field :markup, :html, validations: {required: {}}
15
+ add_many :pages, foreign_key: 'page_layout_record'
16
+
17
+ persistent_layouts.allowed_children = [persistent_layouts]
18
+ persistent_layouts.allowed_parents = [persistent_layouts]
19
+ persistent_layouts.searchable = false
20
+ persistent_layouts.record_class_name = 'PersistentLayout'
21
+ end
22
+
23
+ site.layouts.create_model :file_layouts do |file_layouts|
24
+ add_field :path, :string, validations: {required: {}}
25
+
26
+ file_layouts.allowed_children = [file_layouts]
27
+ file_layouts.allowed_parents = [file_layouts]
28
+ file_layouts.searchable = false
29
+ file_layouts.record_class_name = 'FileLayout'
30
+ end
31
+ end
32
+
33
+ def self.down(site)
34
+ site.layouts.destroy
35
+ site.persistent_layouts.destroy
36
+ site.file_layouts.destroy
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ class GroupModelMigration < Migration
2
+ def self.up(site)
3
+ site.records.create_model :groups do |groups|
4
+ add_field :name, :string, validations: {required: {}}
5
+ add_many :users, store: false
6
+ groups.icon = '/admin/images/group_icon.png'
7
+ groups.record_class_name = 'Group'
8
+ end
9
+ site.reload
10
+
11
+ # a special singleton group representing an 'owner' of a record
12
+ site.groups.create_model :owner_groups do |group|
13
+ group.record_class_name = 'OwnerGroup'
14
+ end
15
+ site.reload
16
+
17
+ # a special singleton group representing no one
18
+ site.groups.create_model :noone_groups do |group|
19
+ group.record_class_name = 'NooneGroup'
20
+ end
21
+ site.reload
22
+
23
+ # a special singleton group representing 'everyone'
24
+ site.groups.create_model :guest_groups do |group|
25
+ group.record_class_name = 'GuestsGroup'
26
+ end
27
+ site.reload
28
+
29
+
30
+ # permissions are based on a hierarchy of groups. branches are permitted.
31
+ noone = site.noone_groups.new(name: 'No One')
32
+ noone.save
33
+
34
+ devs = site.groups.new(name: 'Developers')
35
+ devs.parent = noone
36
+ devs.save
37
+
38
+ admins = site.groups.new(name: 'Administrators')
39
+ admins.parent = devs
40
+ admins.save
41
+
42
+ owner = site.owner_groups.new(name: 'Owner')
43
+ owner.parent = admins
44
+ owner.save
45
+
46
+ users = site.groups.new(name: 'Users')
47
+ users.parent = owner
48
+ users.save
49
+
50
+ guests = site.guest_groups.new(name: 'Guests')
51
+ guests.parent = users
52
+ guests.save
53
+ end
54
+
55
+ def self.down(site)
56
+ site.groups.destroy
57
+ site.owner_groups.destroy
58
+ site.noone_groups.destroy
59
+ site.guest_groups.destroy
60
+ end
61
+ end
@@ -0,0 +1,23 @@
1
+ class UserModelMigration < Migration
2
+ def self.up(site)
3
+ site.records.create_model :users do |users|
4
+ add_field :first_name, :string
5
+ add_field :last_name, :string
6
+ add_field :email, :email, validations: {required: {}, unique: {}}, searchable: false
7
+ add_field :oauth_id, :string, index: true, searchable: false
8
+ add_field :username, :string, index: true, validations: {required: {}, unique: {}}, searchable: false
9
+ add_field :password, :password, validations: {required: {}}, searchable: false
10
+ add_field :password_salt, :string, display: false, searchable: false
11
+ add_many :groups, default: [site.groups['Users'].id]
12
+ add_field :owner, :self
13
+
14
+ add_field :name, :function, fn: 'format("{{first_name}} {{last_name}}").strip()'
15
+ users.icon = '/admin/images/user_icon.png'
16
+ users.record_class_name = 'User'
17
+ end
18
+ end
19
+
20
+ def self.down(site)
21
+ site.users.destroy
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ class SnippetModelMigration < Migration
2
+ def self.up(site)
3
+ site.records.create_model :snippets do |snippets|
4
+ add_field :name, :string, validations: {required: {}}, index: true
5
+ add_field :content, :text
6
+ snippets.searchable = false
7
+ end
8
+ end
9
+
10
+ def self.down(site)
11
+ site.snippets.destroy
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ class SearchPageModelMigration < Migration
2
+ def self.up(site)
3
+ operators = [ 'Equals', 'Not Equal', 'Greater Than',
4
+ 'Less Than', 'Greater Than or Equal To',
5
+ 'Less Than or Equal To', 'In']
6
+
7
+ site.pages.create_model :search_pages do |search_pages|
8
+ add_field :sort, :string, searchable: false
9
+ add_field :limit, :integer
10
+ add_field :skip, :integer
11
+ add_one :type, model: :model
12
+
13
+ add_embed_many :conditions do
14
+ add_field :name, :string
15
+ add_field :value, :string
16
+ add_field :operator, :enum, options: operators
17
+ end
18
+
19
+ add_embed_many :user_conditions, default: [{name: 'search_keywords', as: 'query', operator: 'In'}] do
20
+ add_field :name, :string
21
+ add_field :as, :string
22
+ add_field :operator, :enum, options: operators
23
+ end
24
+
25
+ search_pages.record_class_name = 'SearchPage'
26
+ end
27
+ end
28
+
29
+ def self.down(site)
30
+ site.search_pages.destroy
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ class DefaultSiteOptionsMigration < Migration
2
+ def self.up(site)
3
+ site.options = {
4
+ pages: {
5
+ permalink_character: {
6
+ description: 'When Yodel creates a URL for a page by using the title of the page, there are sometimes characters (such as spaces) that need to be replaced. This character will be used in their place. e.g "About Us" would become "about-us".',
7
+ type: 'String',
8
+ default: '-',
9
+ value: '-'
10
+ }
11
+ },
12
+ icon: nil
13
+ }
14
+ site.save
15
+ end
16
+
17
+ def self.down(site)
18
+ site.options = {}
19
+ site.save
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ class SecurityPageModelsMigration < Migration
2
+ def self.up(site)
3
+ site.pages.create_model :login_pages do |login_pages|
4
+ add_field :username_field, :string, validations: {required: {}}, default: 'username'
5
+ add_field :password_field, :string, validations: {required: {}}, default: 'password'
6
+ add_one :redirect_to, model: :page
7
+ login_pages.record_class_name = 'LoginPage'
8
+ end
9
+
10
+ site.pages.create_model :logout_pages do |logout_pages|
11
+ add_one :redirect_to, model: :page
12
+ logout_pages.record_class_name = 'LogoutPage'
13
+ end
14
+
15
+ site.pages.create_model :password_reset_pages do |password_reset_pages|
16
+ add_field :success, :html, default: 'Thank you, your password has been emailed to your email address.'
17
+ add_field :email_field, :string, validations: {required: {}}, default: 'email'
18
+ password_reset_pages.record_class_name = 'PasswordResetPage'
19
+ end
20
+
21
+ site.pages.create_model :facebook_login_pages do |facebook_login_pages|
22
+ add_field :callback_uri, :string
23
+ add_field :app_id, :string
24
+ add_field :app_secret, :string
25
+ add_one :join_page, model: :page
26
+ add_one :after_login_page, model: :page
27
+ facebook_login_pages.record_class_name = 'FacebookLoginPage'
28
+ end
29
+ end
30
+
31
+ def self.down(site)
32
+ site.login_pages.destroy
33
+ site.logout_pages.destroy
34
+ site.password_reset_pages.destroy
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ class RecordProxyPageModelMigration < Migration
2
+ def self.up(site)
3
+ site.pages.create_model :record_proxy_pages do |record_proxy_pages|
4
+ add_one :record_model, model: :model
5
+ add_one :after_create_page, model: :page
6
+ add_one :after_delete_page, model: :page
7
+ add_one :after_update_page, model: :page
8
+ add_field :show_record_layout, :string
9
+ add_one :show_record_layout_record, model: :layout, display: false
10
+ record_proxy_pages.record_class_name = 'RecordProxyPage'
11
+ end
12
+ end
13
+
14
+ def self.down(site)
15
+ site.record_proxy_pages.destroy
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ class EmailModelMigration < Migration
2
+ def self.up(site)
3
+ site.records.create_model :emails do |emails|
4
+ add_field :name, :string
5
+ add_field :from, :string
6
+ add_field :to, :string
7
+ add_field :cc, :string
8
+ add_field :bcc, :string
9
+ add_field :subject, :string
10
+ add_field :text_body, :text
11
+ add_field :html_body, :html
12
+ add_field :html_layout, :string
13
+ emails.record_class_name = 'Email'
14
+ end
15
+
16
+ # template password reset email
17
+ password_reset_email = site.emails.new
18
+ password_reset_email.name = 'password_reset'
19
+ password_reset_email.from = 'admin@site.com'
20
+ password_reset_email.subject = 'Password Reset'
21
+ password_reset_email.text_body = 'Hi <%= options["first_name"] %>, your password has been reset and is now: <%= options["new_password"] %>.'
22
+ password_reset_email.save
23
+ end
24
+
25
+ def self.down(site)
26
+ site.emails.destroy
27
+ end
28
+ end