better file create

This commit is contained in:
Kyle Drake 2015-05-07 14:32:52 -07:00
parent 85fc6d6e39
commit 93b5b94f14
6 changed files with 97 additions and 22 deletions

View file

@ -9,32 +9,67 @@ get '/site_files/new' do
redirect '/site_files/new_page' redirect '/site_files/new_page'
end end
post '/site_files/create_page' do post '/site_files/create' do
require_login require_login
@errors = [] @errors = []
params[:pagefilename].gsub!(/[^a-zA-Z0-9_\-.]/, '') filename = params[:pagefilename] || params[:filename]
params[:pagefilename].gsub!(/\.html$/i, '')
if params[:pagefilename].nil? || params[:pagefilename].strip.empty? filename.gsub!(/[^a-zA-Z0-9_\-.]/, '')
@errors << 'You must provide a file name.'
halt erb(:'site_files/new_page') redirect_uri = '/dashboard'
redirect_uri += "?dir=#{Rack::Utils.escape params[:dir]}" if params[:dir]
if filename.nil? || filename.strip.empty?
flash[:error] = 'You must provide a file name.'
redirect redirect_uri
end end
name = "#{params[:pagefilename]}.html" name = "#{filename}"
name = "#{params[:dir]}/#{name}" if params[:dir] name = "#{params[:dir]}/#{name}" if params[:dir]
name = current_site.scrubbed_path name
if current_site.file_exists?(name) if current_site.file_exists?(name)
@errors << %{Web page "#{name}" already exists! Choose another name.} flash[:error] = %{Web page "#{name}" already exists! Choose another name.}
halt erb(:'site_files/new_page') redirect redirect_uri
end end
current_site.install_new_html_file name extname = File.extname name
unless extname.match /^\.#{Site::EDITABLE_FILE_EXT}/i
flash[:error] = "Must be an text editable file type (#{Site::VALID_EDITABLE_EXTENSIONS.join(', ')})."
redirect redirect_uri
end
site_file = current_site.site_files_dataset.where(path: name).first
if site_file
flash[:error] = 'File already exists, cannot create.'
redirect redirect_uri
end
if extname.match(/^\.html|^\.htm/i)
current_site.install_new_html_file name
else
file_path = current_site.files_path(name)
FileUtils.touch file_path
File.chmod 0640, file_path
site_file ||= SiteFile.new site_id: current_site.id, path: name
site_file.set_all(
size: 0,
sha1_hash: Digest::SHA1.hexdigest(''),
updated_at: Time.now
)
site_file.save
end
flash[:success] = %{#{name} was created! <a style="color: #FFFFFF; text-decoration: underline" href="/site_files/text_editor/#{name}">Click here to edit it</a>.} flash[:success] = %{#{name} was created! <a style="color: #FFFFFF; text-decoration: underline" href="/site_files/text_editor/#{name}">Click here to edit it</a>.}
redirect params[:dir] ? "/dashboard?dir=#{Rack::Utils.escape params[:dir]}" : '/dashboard' redirect redirect_uri
end end
def file_upload_response(error=nil) def file_upload_response(error=nil)

View file

@ -36,6 +36,10 @@ class Site < Sequel::Model
html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff woff2 json geojson csv tsv mf ico pdf asc key pgp xml mid midi manifest otf webapp html htm txt text css js jpg jpeg png gif svg md markdown eot ttf woff woff2 json geojson csv tsv mf ico pdf asc key pgp xml mid midi manifest otf webapp
} }
VALID_EDITABLE_EXTENSIONS = %w{
html htm txt js css md manifest
}
MINIMUM_PASSWORD_LENGTH = 5 MINIMUM_PASSWORD_LENGTH = 5
BAD_USERNAME_REGEX = /[^\w-]/i BAD_USERNAME_REGEX = /[^\w-]/i
VALID_HOSTNAME = /^[a-z0-9][a-z0-9-]+?[a-z0-9]$/i # http://tools.ietf.org/html/rfc1123 VALID_HOSTNAME = /^[a-z0-9][a-z0-9-]+?[a-z0-9]$/i # http://tools.ietf.org/html/rfc1123
@ -73,7 +77,7 @@ class Site < Sequel::Model
PHISHING_FORM_REGEX = /www.formbuddy.com\/cgi-bin\/form.pl/i PHISHING_FORM_REGEX = /www.formbuddy.com\/cgi-bin\/form.pl/i
SPAM_MATCH_REGEX = ENV['RACK_ENV'] == 'test' ? /pillz/ : /#{$config['spam_smart_filter'].join('|')}/i SPAM_MATCH_REGEX = ENV['RACK_ENV'] == 'test' ? /pillz/ : /#{$config['spam_smart_filter'].join('|')}/i
EMAIL_SANITY_REGEX = /.+@.+\..+/i EMAIL_SANITY_REGEX = /.+@.+\..+/i
EDITABLE_FILE_EXT = /html|htm|txt|js|css|md|manifest/i EDITABLE_FILE_EXT = /#{VALID_EDITABLE_EXTENSIONS.join('|')}/i
BANNED_TIME = 2592000 # 30 days in seconds BANNED_TIME = 2592000 # 30 days in seconds
TITLE_MAX = 100 TITLE_MAX = 100
@ -692,8 +696,12 @@ class Site < Sequel::Model
end end
def install_new_html_file(path) def install_new_html_file(path)
File.write files_path(path), render_template('index.erb') tmpfile = Tempfile.new 'neocities_html_template'
tmpfile.write render_template('index.erb')
tmpfile.close
store_file path, tmpfile
purge_cache path purge_cache path
tmpfile.unlink
end end
def file_exists?(path) def file_exists?(path)

View file

@ -17,10 +17,22 @@ describe 'dashboard' do
visit '/dashboard' visit '/dashboard'
click_link 'New Folder' click_link 'New Folder'
fill_in 'name', with: 'testimages' fill_in 'name', with: 'testimages'
click_button 'Create' #click_button 'Create'
all('#createDir button[type=submit]').first.click
page.must_have_content /testimages/ page.must_have_content /testimages/
File.directory?(@site.files_path('testimages')).must_equal true File.directory?(@site.files_path('testimages')).must_equal true
end end
it 'creates a new file' do
random = SecureRandom.uuid.gsub('-', '')
visit '/dashboard'
click_link 'New Page / File'
fill_in 'filename', with: "#{random}.html"
#click_button 'Create'
all('#createFile button[type=submit]').first.click
page.must_have_content /#{random}\.html/
File.exist?(@site.files_path("#{random}.html")).must_equal true
end
end end
end end
end end

View file

@ -18,7 +18,6 @@
<div class="header-Outro with-site-image dashboard"> <div class="header-Outro with-site-image dashboard">
<div class="row content wide"> <div class="row content wide">
<div class="col col-50 signup-Area"> <div class="col col-50 signup-Area">
<div class="signup-Form"> <div class="signup-Form">
<fieldset class="content"> <fieldset class="content">
@ -102,7 +101,7 @@
<% end %> <% end %>
</div> </div>
<div class="actions"> <div class="actions">
<a href="/site_files/new_page?dir=<%= Rack::Utils.escape @dir %>" class="btn-Action"><i class="fa fa-file"></i> New Page</a> <a href="#createFile" class="btn-Action" data-toggle="modal"><i class="fa fa-file"></i> New Page / File</a>
<a href="#createDir" class="btn-Action" data-toggle="modal"><i class="fa fa-folder"></i> New Folder</a> <a href="#createDir" class="btn-Action" data-toggle="modal"><i class="fa fa-folder"></i> New Folder</a>
<a href="#" class="btn-Action" onclick="clickUploadFiles(); return false"><i class="fa fa-arrow-circle-up"></i> Upload</a> <a href="#" class="btn-Action" onclick="clickUploadFiles(); return false"><i class="fa fa-arrow-circle-up"></i> Upload</a>
</div> </div>
@ -222,6 +221,24 @@
</form> </form>
</div> </div>
<div class="modal hide fade" id="createFile" tabindex="-1" role="dialog" aria-labelledby="createFileLabel" aria-hidden="true">
<form method="post" action="/site_files/create">
<input type="hidden" value="<%= csrf_token %>" name="csrf_token">
<input type="hidden" value="<%= @dir %>" name="dir">
<div class="modal-header">
<button class="close" type="button" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times"></i></button>
<h3 id="createFileLabel">Create New File</h3>
</div>
<div class="modal-body">
<input id="newFileInput" name="filename" type="text" placeholder="newfile.html">
<p>Note: We will automatically scrub any characters not matching: a-z A-Z 0-9 _ - .</p>
</div>
<div class="modal-footer">
<button type="button" class="btn cancel" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button type="submit" class="btn-Action">Create</button>
</div>
</form>
</div>
<script src="/js/dropzone.min.js"></script> <script src="/js/dropzone.min.js"></script>
<script> <script>
@ -292,4 +309,8 @@
$('#createDir').on('shown', function () { $('#createDir').on('shown', function () {
$('#newDirInput').focus(); $('#newDirInput').focus();
}) })
$('#createFile').on('shown', function () {
$('#newFileInput').focus();
})
</script> </script>

View file

@ -17,11 +17,11 @@
<% end %> <% end %>
</section> </section>
<section> <section>
<form method="POST" action="/site_files/create_page" enctype="multipart/form-data"> <form method="POST" action="/site_files/create" enctype="multipart/form-data">
<%== csrf_token_input_html %> <%== csrf_token_input_html %>
<input name="dir" type="hidden" value="<%= params[:dir] %>"> <input name="dir" type="hidden" value="<%= params[:dir] %>">
<h2>What's the name of your page?</h2> <h2>What's the name of your page?</h2>
<p><input type="text" name="pagefilename" autocapitalize="off" autocorrect="off">.html</p> <p><input type="text" name="filename" autocapitalize="off" autocorrect="off">.html</p>
<p><input class="btn-Action" type="submit" value="Create Page"></p> <p><input class="btn-Action" type="submit" value="Create Page"></p>
<p>Note: We will automatically scrub any characters not matching: a-z A-Z 0-9 _ - .</p> <p>Note: We will automatically scrub any characters not matching: a-z A-Z 0-9 _ - .</p>
@ -29,4 +29,4 @@
<p>If you want to make this the index page (and an index page doesn't exist), name it <strong>index.html</strong>.</p> <p>If you want to make this the index page (and an index page doesn't exist), name it <strong>index.html</strong>.</p>
</section> </section>
</article> </article>
</div> </div>

View file

@ -90,8 +90,7 @@
<div class="row editor"> <div class="row editor">
<div class="col col-100"> <div class="col col-100">
<div id="editor"><%==encoding_fix(@file_data) %> <div id="editor"><%==encoding_fix(@file_data) %></div>
</div>
</div> </div>
</div> </div>