cortex-reaver 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +25 -0
- data/README +48 -0
- data/bin/console +11 -0
- data/bin/cortex_reaver +110 -0
- data/bin/import.rb +78 -0
- data/lib/cortex_reaver.rb +114 -0
- data/lib/cortex_reaver/config.rb +21 -0
- data/lib/cortex_reaver/controller/comment.rb +113 -0
- data/lib/cortex_reaver/controller/config.rb +14 -0
- data/lib/cortex_reaver/controller/journal.rb +40 -0
- data/lib/cortex_reaver/controller/main.rb +56 -0
- data/lib/cortex_reaver/controller/page.rb +34 -0
- data/lib/cortex_reaver/controller/photograph.rb +45 -0
- data/lib/cortex_reaver/controller/project.rb +40 -0
- data/lib/cortex_reaver/controller/tag.rb +67 -0
- data/lib/cortex_reaver/controller/user.rb +71 -0
- data/lib/cortex_reaver/helper/activity.rb +9 -0
- data/lib/cortex_reaver/helper/attachments.rb +139 -0
- data/lib/cortex_reaver/helper/auth.rb +45 -0
- data/lib/cortex_reaver/helper/canonical.rb +55 -0
- data/lib/cortex_reaver/helper/crud.rb +317 -0
- data/lib/cortex_reaver/helper/date.rb +29 -0
- data/lib/cortex_reaver/helper/error.rb +14 -0
- data/lib/cortex_reaver/helper/feeds.rb +88 -0
- data/lib/cortex_reaver/helper/form.rb +114 -0
- data/lib/cortex_reaver/helper/navigation.rb +142 -0
- data/lib/cortex_reaver/helper/photographs.rb +25 -0
- data/lib/cortex_reaver/helper/tags.rb +47 -0
- data/lib/cortex_reaver/helper/workflow.rb +27 -0
- data/lib/cortex_reaver/migrations/001_users.rb +24 -0
- data/lib/cortex_reaver/migrations/002_pages.rb +29 -0
- data/lib/cortex_reaver/migrations/003_journals.rb +26 -0
- data/lib/cortex_reaver/migrations/004_photographs.rb +24 -0
- data/lib/cortex_reaver/migrations/005_projects.rb +27 -0
- data/lib/cortex_reaver/migrations/006_tags.rb +64 -0
- data/lib/cortex_reaver/migrations/007_comments.rb +40 -0
- data/lib/cortex_reaver/migrations/008_config.rb +23 -0
- data/lib/cortex_reaver/model/comment.rb +109 -0
- data/lib/cortex_reaver/model/journal.rb +53 -0
- data/lib/cortex_reaver/model/page.rb +87 -0
- data/lib/cortex_reaver/model/photograph.rb +133 -0
- data/lib/cortex_reaver/model/project.rb +49 -0
- data/lib/cortex_reaver/model/tag.rb +72 -0
- data/lib/cortex_reaver/model/user.rb +147 -0
- data/lib/cortex_reaver/public/css/admin.css +45 -0
- data/lib/cortex_reaver/public/css/custom.css +0 -0
- data/lib/cortex_reaver/public/css/form.css +51 -0
- data/lib/cortex_reaver/public/css/main.css +325 -0
- data/lib/cortex_reaver/public/css/photo.css +113 -0
- data/lib/cortex_reaver/public/css/ramaze_error.css +90 -0
- data/lib/cortex_reaver/public/css/text.css +25 -0
- data/lib/cortex_reaver/public/dispatch.fcgi +11 -0
- data/lib/cortex_reaver/public/images/CortexReaver.gif +0 -0
- data/lib/cortex_reaver/public/images/atom-xml-icon.png +0 -0
- data/lib/cortex_reaver/public/images/body.png +0 -0
- data/lib/cortex_reaver/public/images/border_bottom.png +0 -0
- data/lib/cortex_reaver/public/images/border_bottom_left.png +0 -0
- data/lib/cortex_reaver/public/images/border_bottom_right.png +0 -0
- data/lib/cortex_reaver/public/images/border_left.png +0 -0
- data/lib/cortex_reaver/public/images/border_right.png +0 -0
- data/lib/cortex_reaver/public/images/border_top.png +0 -0
- data/lib/cortex_reaver/public/images/border_top_left.png +0 -0
- data/lib/cortex_reaver/public/images/border_top_right.png +0 -0
- data/lib/cortex_reaver/public/images/comment.gif +0 -0
- data/lib/cortex_reaver/public/images/dark_trans.png +0 -0
- data/lib/cortex_reaver/public/images/delete.gif +0 -0
- data/lib/cortex_reaver/public/images/edit.gif +0 -0
- data/lib/cortex_reaver/public/images/header.png +0 -0
- data/lib/cortex_reaver/public/images/header.xcf +0 -0
- data/lib/cortex_reaver/public/images/header_background.png +0 -0
- data/lib/cortex_reaver/public/images/parent.gif +0 -0
- data/lib/cortex_reaver/public/images/rss-xml-icon.png +0 -0
- data/lib/cortex_reaver/public/images/sections.png +0 -0
- data/lib/cortex_reaver/public/images/sections_highlight.png +0 -0
- data/lib/cortex_reaver/public/js/admin.js +36 -0
- data/lib/cortex_reaver/public/js/cookie.js +27 -0
- data/lib/cortex_reaver/public/js/jquery.js +32 -0
- data/lib/cortex_reaver/public/js/photo.js +33 -0
- data/lib/cortex_reaver/snippets/array.rb +7 -0
- data/lib/cortex_reaver/snippets/ramaze/dispatcher/file.rb +37 -0
- data/lib/cortex_reaver/support/attachments.rb +235 -0
- data/lib/cortex_reaver/support/cached_rendering.rb +79 -0
- data/lib/cortex_reaver/support/canonical.rb +107 -0
- data/lib/cortex_reaver/support/comments.rb +69 -0
- data/lib/cortex_reaver/support/pagination.rb +38 -0
- data/lib/cortex_reaver/support/renderer.rb +196 -0
- data/lib/cortex_reaver/support/sequenceable.rb +248 -0
- data/lib/cortex_reaver/support/tags.rb +108 -0
- data/lib/cortex_reaver/support/timestamps.rb +33 -0
- data/lib/cortex_reaver/version.rb +8 -0
- data/lib/cortex_reaver/view/adminbox.rhtml +56 -0
- data/lib/cortex_reaver/view/blank_layout.rhtml +46 -0
- data/lib/cortex_reaver/view/comments/comment.rhtml +34 -0
- data/lib/cortex_reaver/view/comments/form.rhtml +25 -0
- data/lib/cortex_reaver/view/comments/list.rhtml +5 -0
- data/lib/cortex_reaver/view/comments/post_form.rhtml +36 -0
- data/lib/cortex_reaver/view/config/form.rhtml +10 -0
- data/lib/cortex_reaver/view/error.rhtml +72 -0
- data/lib/cortex_reaver/view/journals/form.rhtml +12 -0
- data/lib/cortex_reaver/view/journals/journal.rhtml +39 -0
- data/lib/cortex_reaver/view/journals/list.rhtml +33 -0
- data/lib/cortex_reaver/view/journals/short.rhtml +3 -0
- data/lib/cortex_reaver/view/journals/show.rhtml +5 -0
- data/lib/cortex_reaver/view/pages/form.rhtml +12 -0
- data/lib/cortex_reaver/view/pages/list.rhtml +26 -0
- data/lib/cortex_reaver/view/pages/show.rhtml +12 -0
- data/lib/cortex_reaver/view/photographs/atom_fragment.rhtml +82 -0
- data/lib/cortex_reaver/view/photographs/form.rhtml +19 -0
- data/lib/cortex_reaver/view/photographs/grid.rhtml +36 -0
- data/lib/cortex_reaver/view/photographs/list.rhtml +9 -0
- data/lib/cortex_reaver/view/photographs/short.rhtml +3 -0
- data/lib/cortex_reaver/view/photographs/show.rhtml +114 -0
- data/lib/cortex_reaver/view/photographs/sidebar.rhtml +7 -0
- data/lib/cortex_reaver/view/projects/form.rhtml +13 -0
- data/lib/cortex_reaver/view/projects/list.rhtml +27 -0
- data/lib/cortex_reaver/view/projects/show.rhtml +38 -0
- data/lib/cortex_reaver/view/tags/form.rhtml +9 -0
- data/lib/cortex_reaver/view/tags/list.rhtml +28 -0
- data/lib/cortex_reaver/view/tags/show.rhtml +51 -0
- data/lib/cortex_reaver/view/text_layout.rhtml +78 -0
- data/lib/cortex_reaver/view/users/form.rhtml +16 -0
- data/lib/cortex_reaver/view/users/list.rhtml +38 -0
- data/lib/cortex_reaver/view/users/login.rhtml +13 -0
- data/lib/cortex_reaver/view/users/register.rhtml +13 -0
- data/lib/cortex_reaver/view/users/show.rhtml +37 -0
- data/lib/cortex_reaver/view/users/user.rhtml +35 -0
- data/lib/proto/cortex_reaver.yaml +28 -0
- metadata +285 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
module CortexReaver
|
2
|
+
class Photograph < Sequel::Model(:photographs)
|
3
|
+
def self.url
|
4
|
+
'/photographs'
|
5
|
+
end
|
6
|
+
|
7
|
+
include CortexReaver::Model::Timestamps
|
8
|
+
include CortexReaver::Model::Canonical
|
9
|
+
include CortexReaver::Model::Attachments
|
10
|
+
include CortexReaver::Model::Comments
|
11
|
+
include CortexReaver::Model::Tags
|
12
|
+
include CortexReaver::Model::Sequenceable
|
13
|
+
|
14
|
+
# Target image sizes
|
15
|
+
SIZES = {
|
16
|
+
:thumbnail => '150x',
|
17
|
+
:grid => '150x150',
|
18
|
+
:small => 'x512',
|
19
|
+
:medium => 'x768',
|
20
|
+
:large => 'x1024',
|
21
|
+
}
|
22
|
+
|
23
|
+
many_to_many :tags, :class => 'CortexReaver::Tag'
|
24
|
+
belongs_to :user, :class => 'CortexReaver::User'
|
25
|
+
has_many :comments, :class => 'CortexReaver::Comment'
|
26
|
+
|
27
|
+
validates do
|
28
|
+
uniqueness_of :name
|
29
|
+
presence_of :name
|
30
|
+
length_of :name, :maximum => 255
|
31
|
+
presence_of :title
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.get(id)
|
35
|
+
self[:name => id] || self[id]
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.recent
|
39
|
+
reverse_order(:created_on).limit(16)
|
40
|
+
end
|
41
|
+
|
42
|
+
def atom_url
|
43
|
+
'/photographs/atom/' + name
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the exif data for this photograph
|
47
|
+
def exif
|
48
|
+
EXIFR::JPEG.new(self.full_local_path).exif
|
49
|
+
end
|
50
|
+
|
51
|
+
# Gives the best guess for this photograph's date.
|
52
|
+
def date
|
53
|
+
if exif = self.exif
|
54
|
+
fields = [:date_time_original, :date_time_digitized, :date_time]
|
55
|
+
fields.each do |field|
|
56
|
+
begin
|
57
|
+
if date = exif.send(field)
|
58
|
+
return date
|
59
|
+
end
|
60
|
+
rescue
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Fall back on creation date
|
66
|
+
self.created_on
|
67
|
+
end
|
68
|
+
|
69
|
+
# Store an photograph on disk in the appropriate sizes.
|
70
|
+
def image=(file)
|
71
|
+
if file.blank? or file.size == 0
|
72
|
+
return nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Write file to disk
|
76
|
+
attachment = Attachment.new(self, 'original.jpg')
|
77
|
+
attachment.file = file
|
78
|
+
|
79
|
+
# Read image through ImageMagick
|
80
|
+
image = Magick::Image.read(attachment.local_path).first
|
81
|
+
|
82
|
+
# Write appropriate sizes to disk
|
83
|
+
SIZES.each do |size, geometry|
|
84
|
+
image.change_geometry(geometry) do |width, height|
|
85
|
+
attachment = Attachment.new(self, size.to_s + '.jpg')
|
86
|
+
image.scale(width, height).write(attachment.local_path)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sets the date from the EXIF date tag.
|
94
|
+
def infer_date_from_exif!
|
95
|
+
if exif = self.exif
|
96
|
+
self.created_on = self.date
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns the system path to the full photograph
|
101
|
+
def full_local_path
|
102
|
+
path :local, 'medium'
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns the path to the full photograph
|
106
|
+
def full_public_path
|
107
|
+
path :public, 'medium'
|
108
|
+
end
|
109
|
+
|
110
|
+
# The path to a photograph
|
111
|
+
def path(type = :local, size = :full)
|
112
|
+
attachment(size.to_s + '.jpg').path(type)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the system path to the thumbnail photograph
|
116
|
+
def thumbnail_local_path
|
117
|
+
path :local, 'thumbnail'
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns the path to the thumbnail photograph
|
121
|
+
def thumbnail_public_path
|
122
|
+
path :public, 'thumbnail'
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_s
|
126
|
+
title || name
|
127
|
+
end
|
128
|
+
|
129
|
+
def url
|
130
|
+
'/photographs/show/' + name
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module CortexReaver
|
2
|
+
class Project < Sequel::Model(:projects)
|
3
|
+
def self.url
|
4
|
+
'/projects'
|
5
|
+
end
|
6
|
+
|
7
|
+
include CortexReaver::Model::Timestamps
|
8
|
+
include CortexReaver::Model::CachedRendering
|
9
|
+
include CortexReaver::Model::Renderer
|
10
|
+
include CortexReaver::Model::Canonical
|
11
|
+
include CortexReaver::Model::Attachments
|
12
|
+
include CortexReaver::Model::Comments
|
13
|
+
include CortexReaver::Model::Tags
|
14
|
+
include CortexReaver::Model::Sequenceable
|
15
|
+
|
16
|
+
many_to_many :tags, :class => 'CortexReaver::Tag'
|
17
|
+
belongs_to :user, :class => 'CortexReaver::User'
|
18
|
+
has_many :comments, :class => 'CortexReaver::Comment'
|
19
|
+
|
20
|
+
validates do
|
21
|
+
uniqueness_of :name
|
22
|
+
presence_of :name
|
23
|
+
length_of :name, :maximum => 255
|
24
|
+
presence_of :title
|
25
|
+
end
|
26
|
+
|
27
|
+
render :body
|
28
|
+
|
29
|
+
def self.get(id)
|
30
|
+
self[:name => id] || self[id]
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.recent
|
34
|
+
reverse_order(:updated_on).limit(16)
|
35
|
+
end
|
36
|
+
|
37
|
+
def atom_url
|
38
|
+
'/projects/atom/' + name
|
39
|
+
end
|
40
|
+
|
41
|
+
def url
|
42
|
+
'/projects/show/' + name
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
title || name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module CortexReaver
|
2
|
+
class Tag < Sequel::Model(:tags)
|
3
|
+
include CortexReaver::Model::Canonical
|
4
|
+
|
5
|
+
many_to_many :photographs, :class => 'CortexReaver::Photograph'
|
6
|
+
many_to_many :journals, :class => 'CortexReaver::Journal'
|
7
|
+
many_to_many :projects, :class => 'CortexReaver::Project'
|
8
|
+
many_to_many :pages, :class => 'CortexReaver::Page'
|
9
|
+
|
10
|
+
validates do
|
11
|
+
uniqueness_of :name
|
12
|
+
presence_of :name
|
13
|
+
length_of :name, :maximum => 255
|
14
|
+
presence_of :title
|
15
|
+
length_of :title, :maximum => 255
|
16
|
+
end
|
17
|
+
|
18
|
+
# When we delete a tag, ensure nothing else is linked to it.
|
19
|
+
before_destroy(:drop_associations) do
|
20
|
+
remove_all_photographs
|
21
|
+
remove_all_journals
|
22
|
+
remove_all_projects
|
23
|
+
remove_all_pages
|
24
|
+
end
|
25
|
+
|
26
|
+
# Autocompletes a tag. Returns an array of matching candidates
|
27
|
+
def self.autocomplete(string)
|
28
|
+
filter(:title.like(/^#{string}/i)).limit(6).map(:title)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Recalculates the number of children on each tag, and saves the updated values.
|
32
|
+
def self.refresh_counts
|
33
|
+
all.each do |tag|
|
34
|
+
tag.refresh_count
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.get(id)
|
39
|
+
self[:name => id] || self[id]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.url
|
43
|
+
'/tags'
|
44
|
+
end
|
45
|
+
|
46
|
+
def atom_url
|
47
|
+
'/tags/atom/' + name
|
48
|
+
end
|
49
|
+
|
50
|
+
# Recalculates the number of children on this tag, and saves the update value.
|
51
|
+
def refresh_count
|
52
|
+
# Find counts
|
53
|
+
self[:count] = photographs_dataset.count +
|
54
|
+
journals_dataset.count +
|
55
|
+
pages_dataset.count +
|
56
|
+
projects_dataset.count
|
57
|
+
|
58
|
+
# Save and return
|
59
|
+
self.skip_timestamp_update = true
|
60
|
+
self.save
|
61
|
+
self[:count]
|
62
|
+
end
|
63
|
+
|
64
|
+
def url
|
65
|
+
'/tags/show/' + name
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
title || name
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'digest/sha2'
|
2
|
+
|
3
|
+
module CortexReaver
|
4
|
+
class User < Sequel::Model(:users)
|
5
|
+
include CortexReaver::Model::Timestamps
|
6
|
+
include CortexReaver::Model::Sequenceable
|
7
|
+
|
8
|
+
has_many :comments, :class => 'CortexReaver::Comment'
|
9
|
+
has_many :journals, :class => 'CortexReaver::Journal'
|
10
|
+
has_many :pages, :class => 'CortexReaver::Page'
|
11
|
+
has_many :photographs, :class => 'CortexReaver::Photograph'
|
12
|
+
has_many :projects, :class => 'CortexReaver::Project'
|
13
|
+
|
14
|
+
validates do
|
15
|
+
uniqueness_of :login
|
16
|
+
length_of :login, :with => 5..255, :allow_blank => true
|
17
|
+
format_of :login, :with => /^[A-Za-z0-9\-_]+$/
|
18
|
+
length_of :name, :maximum => 255
|
19
|
+
length_of :http, :allow_blank => true, :maximum => 255
|
20
|
+
uniqueness_of :email
|
21
|
+
length_of :email, :allow_blank => true, :maximum => 255
|
22
|
+
format_of :email,
|
23
|
+
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/, :allow_blank => true
|
24
|
+
confirmation_of :password, :allow_nil => true#, :allow_false => true
|
25
|
+
each(:password_length, :tag => :password_length) do |object, attribute, value|
|
26
|
+
unless value.nil? or (8..255) === value
|
27
|
+
object.errors['password'] << 'must be between 8 and 255 characters.'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Ensure an administrator is always available. TODO: This is probably
|
33
|
+
# subject to a race condition, especially between servers. Backup plan?
|
34
|
+
validates_each :admin do |object, attribute, value|
|
35
|
+
if User.filter(:admin => true).count == 1 and not value
|
36
|
+
object.errors[attribute] << "can't be unset; only one administrator left!"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
self.window_size = 64
|
41
|
+
|
42
|
+
# Returns an authenticated user by login and password, or nil.
|
43
|
+
def self.authenticate(login, password)
|
44
|
+
user = self[:login => login]
|
45
|
+
if user and user.authenticate(password)
|
46
|
+
user
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# CRUD uses this to construct URLs. Even though we don't need the full
|
53
|
+
# power of Canonical, CRUD is pretty useful. :)
|
54
|
+
def self.canonical_name_attr
|
55
|
+
:login
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get a user
|
59
|
+
def self.get(id)
|
60
|
+
self[:login => id] || self[id]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns true if the user is an administrator.
|
64
|
+
def admin?
|
65
|
+
self.admin
|
66
|
+
end
|
67
|
+
|
68
|
+
# Authenticate with password
|
69
|
+
def authenticate(test_password)
|
70
|
+
if self[:password] == self.class.crypt(test_password, self.salt)
|
71
|
+
true
|
72
|
+
else
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Set user password
|
78
|
+
def password=(password)
|
79
|
+
self.salt ||= self.class.new_salt
|
80
|
+
self[:password] = self.class.crypt(password, self.salt)
|
81
|
+
@password_length = password.length
|
82
|
+
end
|
83
|
+
|
84
|
+
# Password confirmation
|
85
|
+
def password_confirmation=(password)
|
86
|
+
self.salt ||= self.class.new_salt
|
87
|
+
@password_confirmation = self.class.crypt(password, self.salt)
|
88
|
+
end
|
89
|
+
|
90
|
+
def password_confirmation
|
91
|
+
# If password_confirmation was set, use that. Otherwise, fall back
|
92
|
+
# to the normal password, so we don't need set the confirmation every
|
93
|
+
# time the password is updated programmatically.
|
94
|
+
@password_confirmation || self.password
|
95
|
+
end
|
96
|
+
|
97
|
+
# A cache for password length, so we can validate without keeping the
|
98
|
+
# password as plaintext.
|
99
|
+
def password_length
|
100
|
+
@password_length
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_s
|
104
|
+
if name.blank?
|
105
|
+
login
|
106
|
+
else
|
107
|
+
name
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# A URL to view this user
|
112
|
+
def url
|
113
|
+
'/users/show/' + login
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
# Valid characters for salt
|
118
|
+
SALT_CHARS = ('0'..'9').to_a + ('a'..'z').to_a + ('A'..'Z').to_a
|
119
|
+
|
120
|
+
# Returns hash of password with salt.
|
121
|
+
def self.crypt(password, salt)
|
122
|
+
Digest::SHA512.hexdigest(password.to_s + salt.to_s)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns random salt
|
126
|
+
def self.new_salt
|
127
|
+
salt = ''
|
128
|
+
40.times do
|
129
|
+
salt << SALT_CHARS[rand(SALT_CHARS.size - 1).to_i]
|
130
|
+
end
|
131
|
+
salt
|
132
|
+
end
|
133
|
+
|
134
|
+
public
|
135
|
+
|
136
|
+
# Create default user if none exist
|
137
|
+
if table_exists? and count == 0
|
138
|
+
u = User.new(
|
139
|
+
:login => 'shodan',
|
140
|
+
:name => 'Shodan',
|
141
|
+
:admin => true
|
142
|
+
)
|
143
|
+
u.password = 'shodan'
|
144
|
+
u.save!
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#adminbox {
|
2
|
+
display: none;
|
3
|
+
padding: 0.5em;
|
4
|
+
margin: 0 0 1em 0;
|
5
|
+
background-color: #eaeaea;
|
6
|
+
border: 1px solid #aaa;
|
7
|
+
border-top: none;
|
8
|
+
font-size: 80%;
|
9
|
+
}
|
10
|
+
|
11
|
+
#main #adminbox {
|
12
|
+
margin: -0.8em 0em 1em 0em;
|
13
|
+
}
|
14
|
+
|
15
|
+
#adminbox .actions-table {
|
16
|
+
width: 100%;
|
17
|
+
}
|
18
|
+
|
19
|
+
#adminbox p {
|
20
|
+
margin: 0;
|
21
|
+
padding: 0;
|
22
|
+
}
|
23
|
+
|
24
|
+
#adminbox td.title {
|
25
|
+
font-weight: bold;
|
26
|
+
}
|
27
|
+
|
28
|
+
#adminbox input[type=text] {
|
29
|
+
width: 160px;
|
30
|
+
}
|
31
|
+
|
32
|
+
#admin_section_actions {
|
33
|
+
text-align: center;
|
34
|
+
}
|
35
|
+
|
36
|
+
#admin_page_actions {
|
37
|
+
}
|
38
|
+
|
39
|
+
#admin_new_actions {
|
40
|
+
float: left;
|
41
|
+
}
|
42
|
+
|
43
|
+
#admin_user_actions {
|
44
|
+
float: right;
|
45
|
+
}
|