settings.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. get '/settings/?' do
  2. require_login
  3. @site = parent_site
  4. erb :'settings/account'
  5. end
  6. def require_ownership_for_settings
  7. @site = Site[username: params[:username]]
  8. not_found if @site.nil?
  9. unless @site.owned_by? parent_site
  10. flash[:error] = 'Cannot edit this site, you do not have permission.'
  11. redirect request.referrer
  12. end
  13. end
  14. get '/settings/invoices/?' do
  15. require_login
  16. @title = 'Invoices'
  17. @invoices = parent_site.stripe_customer_id ? Stripe::Invoice.list(customer: parent_site.stripe_customer_id) : []
  18. erb :'settings/invoices'
  19. end
  20. get '/settings/:username/?' do |username|
  21. # This is for the email_unsubscribe below
  22. pass if Site.select(:id).where(username: username).first.nil?
  23. require_login
  24. require_ownership_for_settings
  25. @bluesky_did = $redis_proxy.hget "dns-_atproto.#{@site.username}.neocities.org", 'TXT'
  26. @title = "Site settings for #{username}"
  27. erb :'settings/site'
  28. end
  29. post '/settings/:username/delete' do
  30. require_login
  31. require_ownership_for_settings
  32. if params[:confirm_username] != @site.username
  33. flash[:error] = 'Site user name and entered user name did not match.'
  34. redirect "/settings/#{@site.username}#delete"
  35. end
  36. @site.deleted_reason = params[:deleted_reason]
  37. @site.save validate: false
  38. @site.destroy
  39. flash[:success] = 'Site deleted.'
  40. if @site.username == current_site.username
  41. signout
  42. redirect '/'
  43. end
  44. redirect '/settings#sites'
  45. end
  46. post '/settings/:username/profile' do
  47. require_login
  48. require_ownership_for_settings
  49. @site.update(
  50. profile_comments_enabled: params[:site][:profile_comments_enabled],
  51. profile_enabled: params[:site][:profile_enabled]
  52. )
  53. flash[:success] = 'Profile settings changed.'
  54. redirect "/settings/#{@site.username}#profile"
  55. end
  56. post '/settings/:username/change_name' do
  57. require_login
  58. require_ownership_for_settings
  59. old_site = Site[username: @site.username]
  60. old_username = @site.username
  61. if params[:name] == nil || params[:name] == ''
  62. flash[:error] = 'Name cannot be blank.'
  63. redirect "/settings/#{@site.username}#username"
  64. end
  65. if old_username.downcase == params[:name].downcase
  66. flash[:error] = 'You already have this name.'
  67. redirect "/settings/#{@site.username}#username"
  68. end
  69. old_host = @site.host
  70. old_site_file_paths = @site.site_files.collect {|site_file| site_file.path}
  71. @site.username = params[:name]
  72. if @site.valid?
  73. DB.transaction {
  74. @site.save_changes
  75. @site.move_files_from old_username
  76. }
  77. old_site.delete_all_thumbnails_and_screenshots
  78. old_site.purge_all_cache
  79. @site.purge_all_cache
  80. @site.regenerate_thumbnails_and_screenshots
  81. flash[:success] = "Site/user name has been changed. You will need to use this name to login, <b>don't forget it!</b>"
  82. redirect "/settings/#{@site.username}#username"
  83. else
  84. flash[:error] = @site.errors.first.last.first
  85. redirect "/settings/#{old_username}#username"
  86. end
  87. end
  88. post '/settings/:username/tipping' do
  89. require_login
  90. require_ownership_for_settings
  91. current_site.tipping_enabled = params[:site][:tipping_enabled]
  92. current_site.tipping_paypal = params[:site][:tipping_paypal]
  93. current_site.tipping_bitcoin = params[:site][:tipping_bitcoin]
  94. if current_site.valid?
  95. current_site.save_changes
  96. flash[:success] = "Tip settings have been updated."
  97. else
  98. flash[:error] = current_site.errors.first.last.first
  99. end
  100. redirect "/settings/#{current_site.username}#tipping"
  101. end
  102. post '/settings/:username/change_nsfw' do
  103. require_login
  104. require_ownership_for_settings
  105. redirect "/settings/#{@site.username}" if @site.admin_nsfw == true
  106. @site.is_nsfw = params[:is_nsfw]
  107. @site.save_changes validate: false
  108. flash[:success] = @site.is_nsfw ? 'Marked 18+' : 'Unmarked 18+'
  109. redirect "/settings/#{@site.username}#nsfw"
  110. end
  111. post '/settings/:username/custom_domain' do
  112. require_login
  113. require_ownership_for_settings
  114. original_domain = @site.domain
  115. @site.domain = params[:domain]
  116. if params[:domain] =~ /^www\..+$/i
  117. flash[:error] = 'Cannot begin with www - please only enter the domain name.'
  118. redirect "/settings/#{@site.username}/#custom_domain"
  119. end
  120. begin
  121. Socket.gethostbyname @site.values[:domain]
  122. rescue SocketError, ResolutionError => e
  123. flash[:error] = "The domain isn't setup to use Neocities yet, cannot add. Please make the A and CNAME record changes where you registered your domain."
  124. redirect "/settings/#{@site.username}#custom_domain"
  125. end
  126. if @site.valid?
  127. @site.save_changes
  128. if @site.domain != original_domain
  129. LetsEncryptWorker.perform_async @site.id
  130. # Sometimes the www record isn't ready for some reason, so try a delay to fix that.
  131. LetsEncryptWorker.perform_in 40.minutes, @site.id
  132. end
  133. flash[:success] = 'The domain has been successfully updated! Make sure your configuration with the domain registrar is correct. It could take a while for the changes to take effect (15-40 minutes), please be patient.'
  134. redirect "/settings/#{@site.username}#custom_domain"
  135. else
  136. flash[:error] = @site.errors.first.last.first
  137. redirect "/settings/#{@site.username}#custom_domain"
  138. end
  139. end
  140. post '/settings/:username/bluesky_set_did' do
  141. require_login
  142. require_ownership_for_settings
  143. redirect '/settings' if !@site.domain.empty?
  144. # todo standards based validation
  145. if params[:did].length > 50
  146. flash[:error] = 'DID provided was too long'
  147. elsif !params[:did].match(/^did=did:plc:([a-z|0-9)]+)$/)
  148. flash[:error] = 'DID was invalid'
  149. else
  150. $redis_proxy.hset "dns-_atproto.#{@site.username}.neocities.org", 'TXT', params[:did]
  151. flash[:success] = 'DID set! You can now verify the domain on the Bluesky app.'
  152. end
  153. redirect "/settings/#{@site.username}#bluesky"
  154. end
  155. post '/settings/:username/generate_api_key' do
  156. require_login
  157. require_ownership_for_settings
  158. is_new = @site.api_key.nil?
  159. @site.generate_api_key!
  160. msg = is_new ? "New API key has been generated." : "API key has been regenerated."
  161. flash[:success] = msg
  162. redirect "/settings/#{@site.username}#api_key"
  163. end
  164. post '/settings/change_password' do
  165. require_login
  166. if !current_site.password_reset_confirmed && !Site.valid_login?(parent_site.username, params[:current_password])
  167. flash[:error] = 'Your provided password does not match the current one.'
  168. redirect "/settings#password"
  169. end
  170. parent_site.password = params[:new_password]
  171. parent_site.valid?
  172. if params[:new_password] != params[:new_password_confirm]
  173. parent_site.errors.add :password, 'New passwords do not match.'
  174. end
  175. parent_site.password_reset_token = nil
  176. parent_site.password_reset_confirmed = false
  177. if parent_site.errors.empty?
  178. parent_site.save_changes
  179. parent_site.send_email(
  180. subject: "[Neocities] Your password has been changed",
  181. body: Tilt.new('./views/templates/email/password_changed.erb', pretty: true).render(self)
  182. )
  183. flash[:success] = 'Successfully changed password.'
  184. redirect "/settings#password"
  185. else
  186. flash[:error] = current_site.errors.first.last.first
  187. redirect '/settings#password'
  188. end
  189. end
  190. post '/settings/change_email' do
  191. require_login
  192. if params[:from_confirm]
  193. redirect_url = "/site/#{parent_site.username}/confirm_email"
  194. else
  195. redirect_url = '/settings#email'
  196. end
  197. if params[:email] == parent_site.email
  198. flash[:error] = 'You are already using this email address for this account.'
  199. redirect redirect_url
  200. end
  201. previous_email = parent_site.email
  202. parent_site.email = params[:email]
  203. parent_site.email_confirmation_token = SecureRandom.hex 3
  204. parent_site.email_confirmed = false
  205. parent_site.password_reset_token = nil
  206. if parent_site.valid?
  207. parent_site.save_changes
  208. send_confirmation_email
  209. parent_site.send_email(
  210. subject: "[Neocities] Your email address has been changed",
  211. body: Tilt.new('./views/templates/email/email_changed.erb', pretty: true).render(self, site: parent_site, previous_email: previous_email)
  212. )
  213. if !parent_site.supporter?
  214. session[:fromsettings] = true
  215. redirect "/site/#{parent_site.email}/confirm_email"
  216. else
  217. flash[:success] = 'Email address changed.'
  218. redirect '/settings#email'
  219. end
  220. end
  221. flash[:error] = parent_site.errors.first.last.first
  222. redirect redirect_url
  223. end
  224. post '/settings/change_email_notification' do
  225. require_login
  226. owner = current_site.owner
  227. owner.send_emails = params[:send_emails]
  228. owner.send_comment_emails = params[:send_comment_emails]
  229. owner.send_follow_emails = params[:send_follow_emails]
  230. owner.email_invoice = params[:email_invoice]
  231. owner.save_changes validate: false
  232. flash[:success] = 'Email notification settings have been updated.'
  233. redirect '/settings#email'
  234. end
  235. post '/settings/create_child' do
  236. require_login
  237. if !current_site.plan_feature(:unlimited_site_creation)
  238. flash[:error] = 'Cannot create a new site with your current plan, please become a supporter.'
  239. redirect '/settings#sites'
  240. end
  241. site = Site.new
  242. site.parent_site_id = parent_site.id
  243. site.username = params[:username]
  244. if site.valid?
  245. site.save
  246. flash[:success] = 'Your new site has been created! To manage it, click your username in the top right and go to "Switch Site".'
  247. redirect '/settings#sites'
  248. else
  249. flash[:error] = site.errors.first.last.first
  250. redirect '/settings#sites'
  251. end
  252. end
  253. get '/settings/unsubscribe_email/?' do
  254. redirect "/settings/#email" if signed_in?
  255. if params[:email] && params[:token] && params[:email] != '' && Site.valid_email_unsubscribe_token?(params[:email], params[:token])
  256. Site.where(email: params[:email]).all.each do |site|
  257. site.send_emails = false
  258. site.save_changes validate: false
  259. end
  260. @message = "You have been successfully unsubscribed from future emails to #{params[:email]}. Our apologies for the inconvenience."
  261. else
  262. @message = 'There was an error unsubscribing your email address. Please contact support.'
  263. end
  264. erb :'settings/account/unsubscribe'
  265. end
  266. post '/settings/update_card' do
  267. require_login
  268. customer = Stripe::Customer.retrieve parent_site.stripe_customer_id
  269. old_card_ids = customer.sources.collect {|s| s.id}
  270. begin
  271. customer.sources.create source: params[:stripe_token]
  272. rescue Stripe::InvalidRequestError, Stripe::CardError => e
  273. if e.message.match /cannot use a.+token more than once/
  274. flash[:error] = 'Card is already being used.'
  275. redirect '/settings#billing'
  276. elsif e.message.match /Your card was declined/
  277. flash[:error] = 'The card was declined. Please contact your bank.'
  278. else
  279. raise e
  280. end
  281. end
  282. old_card_ids.each do |card_id|
  283. customer.sources.retrieve(card_id).delete
  284. end
  285. flash[:success] = 'Card information updated.'
  286. redirect '/settings#billing'
  287. end