diff options
79 files changed, 991 insertions, 197 deletions
@@ -15,6 +15,8 @@ gem 'activerecord-session_store' gem 'highlight_js-rails', github: 'RedstonerServer/highlight_js-rails' gem 'kaminari', github: 'jomo/kaminari', branch: 'patch-2' # pagination gem 'jquery-textcomplete-rails', github: 'RedstonerServer/jquery-textcomplete-rails' # @mentions +gem 'actionpack-action_caching', github: 'antulik/actionpack-action_caching', ref: '8c6e52c69315d67437f480da5dce4b7c8737fb32' +gem 'mail-gpg', github: 'jomo/mail-gpg', ref: 'a666b48ee866dfa3eaa700f9c5edf4d195d0f8c9' # Gems used only for assets and not required # in production environments by default. @@ -43,4 +45,4 @@ end group :production do # Use unicorn as the app server gem 'unicorn' -end
\ No newline at end of file +end diff --git a/Gemfile.lock b/Gemfile.lock index 1e638b9..f88e22b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -15,6 +15,14 @@ GIT sass-rails (>= 3.2.0) GIT + remote: git://github.com/antulik/actionpack-action_caching.git + revision: 8c6e52c69315d67437f480da5dce4b7c8737fb32 + ref: 8c6e52c69315d67437f480da5dce4b7c8737fb32 + specs: + actionpack-action_caching (1.2.0) + actionpack (>= 4.0.0, < 6) + +GIT remote: git://github.com/jomo/kaminari.git revision: e49066e94d77a6abb03a0819f3c4b0cc6923cb70 branch: patch-2 @@ -24,6 +32,15 @@ GIT activesupport (>= 3.0.0) GIT + remote: git://github.com/jomo/mail-gpg.git + revision: a666b48ee866dfa3eaa700f9c5edf4d195d0f8c9 + ref: a666b48ee866dfa3eaa700f9c5edf4d195d0f8c9 + specs: + mail-gpg (0.3.1) + gpgme (~> 2.0, >= 2.0.2) + mail (~> 2.5, >= 2.5.3) + +GIT remote: git://github.com/rails/rails.git revision: 2c8f567e53580872d8c6dfe61201e58793ca131e branch: 4-2-stable @@ -127,6 +144,8 @@ GEM execjs (2.6.0) globalid (0.3.6) activesupport (>= 4.1.0) + gpgme (2.0.11) + mini_portile (>= 0.5.0) hirb (0.7.3) http-cookie (1.0.2) domain_name (~> 0.5) @@ -142,6 +161,7 @@ GEM mail (2.6.3) mime-types (>= 1.16, < 3) mime-types (2.99) + mini_portile (0.6.2) mini_portile2 (2.0.0) minitest (5.8.4) mysql2 (0.4.2) @@ -223,6 +243,7 @@ PLATFORMS ruby DEPENDENCIES + actionpack-action_caching! activerecord-session_store bcrypt better_errors @@ -235,6 +256,7 @@ DEPENDENCIES jquery-rails jquery-textcomplete-rails! kaminari! + mail-gpg! mysql2 rails! rails-erd diff --git a/app/assets/images/mastodon.png b/app/assets/images/mastodon.png Binary files differnew file mode 100644 index 0000000..a4305d9 --- /dev/null +++ b/app/assets/images/mastodon.png diff --git a/app/assets/images/tor.png b/app/assets/images/tor.png Binary files differnew file mode 100644 index 0000000..47a4a16 --- /dev/null +++ b/app/assets/images/tor.png diff --git a/app/assets/javascripts/editor.js b/app/assets/javascripts/editor.js index 4b35aea..4f4de5d 100644 --- a/app/assets/javascripts/editor.js +++ b/app/assets/javascripts/editor.js @@ -88,5 +88,45 @@ $(function() { }], { debounce: 300 }); + $('.md_editor .field_container_user .editor_field').textcomplete([{ + // match up to 2 words (everything except some special characters) + // each word can have up to 16 characters (up to 32 total) + // words must be separated by a single space + match: /(^|\s)([^!"§$%&\/()=?.,;+*@\s]{1,16})$/, + search: function (text, callback, match) { + console.log("Searching " + text); + text = text.toLowerCase(); + $.ajax("/users/suggestions", { + type: "post", + data: {name: text}, + dataType: "json", + headers: { + "X-CSRF-Token": $('meta[name="csrf-token"]').attr("content") + }, + success: function(data) { + callback(data); + }, + error: function(xhr, status, err) { + console.error(err); + callback([]); + } + }); + }, + template: function(user) { + var name = user[0]; + var ign = user[1]; + if (name != ign) { + return name + " <small>(" + ign + ")</small>"; + } else { + return ign; + } + }, + cache: true, + replace: function (word) { + return "$1" + word[1] + " "; + } + }], { + debounce: 300 + }); -});
\ No newline at end of file +}); diff --git a/app/assets/stylesheets/dark.css.scss b/app/assets/stylesheets/dark.css.scss new file mode 100644 index 0000000..90c7fc0 --- /dev/null +++ b/app/assets/stylesheets/dark.css.scss @@ -0,0 +1,105 @@ +body { + background-color:rgb(50, 50, 50); + text-shadow:none !important; + color:rgb(190, 190, 190) !important; +} +::selection { + background-color:rgb(100, 150, 255); +} +a { + color:rgb(203, 75, 22); + border-color:black !important; +} +a:hover { + color:rgb(215, 100, 40); +} +#main-content { + border-color:black !important; + padding:30px 100px; + box-shadow:none; +} +#main-content-scroll { + padding: 131px 100px; + border: 1px solid #000; + box-shadow: 0 0 5px #000; +} +hr { + background-color:black !important; + border-color:black !important; +} +code { + background-color:rgb(30, 30, 30) !important; + border-color:black !important; + color:white !important; +} +#head_top { + width:100%; + z-index:100; +} +#head_scroll { + @extend #head_top; + position: fixed; + width: 100%; + z-index: 1; +} +div#userbar { + background-color:rgb(90, 90, 90) !important; + border-color:black !important; + color:white !important; + text-shadow:none !important; +} +#head a { + text-shadow:none !important; + color:white !important; +} +#head a:hover { + color:rgb(190, 190, 190) !important; +} +.header { + background-color:rgb(0, 0, 0); + border:none !important; +} +input[type="email"], input[type="text"], input[type="password"] { + background-color:rgb(110, 110, 110) !important; + color:white !important; +} +::placeholder { + color:lightgray; +} +.item { + background-color:rgb(40, 40, 40) !important; + border-color:black !important; +} +.item-group { + border-color:black !important; +} +div.header { + background-color:rgb(20, 20, 20) !important; +} +.avatar { + border-color:black !important; +} +.items { + border-color:black !important; +} +.markdown-help { + background-color:rgb(90, 90, 90); + color:white; + border-color:black; +} +textarea { + background-color:rgb(100, 100, 100); + color:white; +} +.headline { + border-color:black !important; +} +.role { + opacity:0.7 !important; +} +.label { + opacity:0.7 !important; +} +.notice { + color:white; +} diff --git a/app/assets/stylesheets/mobi.css.scss b/app/assets/stylesheets/mobi.css.scss index cc437cb..c1b44fd 100644 --- a/app/assets/stylesheets/mobi.css.scss +++ b/app/assets/stylesheets/mobi.css.scss @@ -4,12 +4,12 @@ th, td { // force tables into line-mode - // it's a bit ugly, but probably the best + // it''s a bit ugly, but probably the best // solution for small screens display: block; } - #head { + #head_top { #menu { #logo { display: none; @@ -17,10 +17,19 @@ } } + #head_scroll { + @extend #head_top; + position: fixed; +} + #main-content { padding: 30px 5px; } + #main-content-scroll { + padding: 181px 5px; + } + .front-page { h1 { font-size: 2em !important; @@ -66,4 +75,4 @@ margin: 50px 20px 0; } -}
\ No newline at end of file +} diff --git a/app/assets/stylesheets/style.css.scss b/app/assets/stylesheets/style.css.scss index 6de5aa2..f8d1d8e 100644 --- a/app/assets/stylesheets/style.css.scss +++ b/app/assets/stylesheets/style.css.scss @@ -80,7 +80,7 @@ a { } } -#head { +#head_top { background: #3f3f3f; #menu { @@ -181,6 +181,13 @@ a { } } +#head_scroll { + @extend #head_top; + position: fixed; + width: 100%; + z-index: 1; +} + .front-page { margin: auto; text-align: center; @@ -260,6 +267,11 @@ span.no-about { } } +#main-content-scroll { + @extend #main-content; + padding: 131px 100px; +} + #user-info { .user-avatar { margin-bottom: 30px; @@ -437,18 +449,14 @@ blockquote p { color: #ddd !important; } } - - .donor { - color: #fff; - background: #f60 !important; - margin-left: 2px !important; - } - .ign { display: block; color: #000; font-style: italic; } + .badge { + margin-left: 2px !important; + } } #online-users { @@ -458,6 +466,7 @@ blockquote p { } .md_editor { + .field_container { position: relative; @@ -465,7 +474,7 @@ blockquote p { position: absolute; top: 1em; left: 1em; - z-index: 10; + z-index: 0; } .editor_field { @@ -480,6 +489,10 @@ blockquote p { padding: 4em 1em 1em; } } + .field_container_user { + .editor_field { + } + } } ul.dropdown-menu { @@ -675,6 +688,13 @@ tr.spacer { color: #ddd; } + &.variable-size { + background: #4096ee; + @media only screen and (max-width: 500px) { + font-size: 9px; + } + } + &.blue { background: #4096ee; @@ -1026,4 +1046,20 @@ nav.pagination { padding: 0.1em 0.2em; border-radius: 0.2em; text-shadow: none; -}
\ No newline at end of file +} + +.searchfield { + height:40px; + display: inline-block; + &.field { + width: 300px; + } + &.btn { + margin: 4px 1px 0 0; + cursor: default; + color: #fff; + font-size: 12px; + background: #4096ee; + width: 40px; + } +} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a0e166e..d489611 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -75,4 +75,4 @@ class ApplicationController < ActionController::Base !!(current_user && current_user.confirmed?) end -end
\ No newline at end of file +end diff --git a/app/controllers/blogposts_controller.rb b/app/controllers/blogposts_controller.rb index 79c9e5d..1ff310d 100644 --- a/app/controllers/blogposts_controller.rb +++ b/app/controllers/blogposts_controller.rb @@ -4,7 +4,7 @@ class BlogpostsController < ApplicationController before_filter :auth, except: [:index, :show] def index - @posts = Blogpost.order("created_at desc").page(params[:page]).per(10) + @posts = Blogpost.order(id: :desc).page(params[:page]).per(10) end def show @@ -75,4 +75,4 @@ class BlogpostsController < ApplicationController end end -end
\ No newline at end of file +end diff --git a/app/controllers/forumgroups_controller.rb b/app/controllers/forumgroups_controller.rb index a7b31ab..fe359af 100644 --- a/app/controllers/forumgroups_controller.rb +++ b/app/controllers/forumgroups_controller.rb @@ -77,4 +77,4 @@ class ForumgroupsController < ApplicationController params.require(:forumgroup).permit(a) end -end
\ No newline at end of file +end diff --git a/app/controllers/forums_controller.rb b/app/controllers/forums_controller.rb index ecf570e..206f01f 100644 --- a/app/controllers/forums_controller.rb +++ b/app/controllers/forums_controller.rb @@ -1,4 +1,5 @@ class ForumsController < ApplicationController + before_filter :check_permission, only: [:show, :edit, :update, :destroy] def index @@ -10,7 +11,7 @@ class ForumsController < ApplicationController @threads = @forum.forumthreads.select {|f| f.can_read?(current_user) }.to_a @threads.sort_by! do |t| # sticky goes first, then sort by last activity (new replies) - [t.sticky ? 0 : 1, -(t.replies.last.try(:created_at) || t.created_at).to_i] + [t.sticky ? 0 : 1, -(t.replies.order(:id).last.try(:created_at) || t.created_at).to_i] end @threads = Kaminari.paginate_array(@threads).page(params[:page]) end @@ -77,7 +78,6 @@ class ForumsController < ApplicationController redirect_to forums_path end - private def check_permission @@ -89,7 +89,7 @@ class ForumsController < ApplicationController end def forum_params(add = []) - a = [:name, :position, :role_read_id, :role_write_id] + add + a = [:name, :position, :role_read_id, :role_write_id, :necro_length] + add params.require(:forum).permit(a) end -end
\ No newline at end of file +end diff --git a/app/controllers/forumthreads_controller.rb b/app/controllers/forumthreads_controller.rb index b9b5714..d40ce58 100644 --- a/app/controllers/forumthreads_controller.rb +++ b/app/controllers/forumthreads_controller.rb @@ -3,11 +3,19 @@ class ForumthreadsController < ApplicationController before_filter :check_permission, only: [:show, :edit, :update, :destroy] def index - redirect_to forum_path(@thread.forum.forumgroup, f) - end + params[:forum] = nil if params[:forum] && !Forum.find_by(id: params[:forum]) + + params.delete_if{|k,v| v.blank?} + @threads = Forumthread.filter(current_user, params[:title].try(:slice, 0..255), params[:content].try(:slice, 0..255), params[:reply].try(:slice, 0..255), params[:label], User.find_by(ign: params[:author].to_s.strip) || params[:author], params[:query].try(:slice, 0..255), Forum.find_by(id: params[:forum])) + .page(params[:page]).per(30) + end def show - @replies = @thread.replies.page(params[:page]) + if params[:reverse] == "true" + @replies = @thread.replies.order(id: :desc).page(params[:page]) + else + @replies = @thread.replies.order(:id).page(params[:page]) + end end def edit @@ -76,6 +84,9 @@ class ForumthreadsController < ApplicationController redirect_to @thread.forum end + def search + end + private def check_permission @@ -92,4 +103,4 @@ class ForumthreadsController < ApplicationController a += add params.require(:forumthread).permit(a) end -end
\ No newline at end of file +end diff --git a/app/controllers/statics_controller.rb b/app/controllers/statics_controller.rb index f2891f3..0d42fa9 100644 --- a/app/controllers/statics_controller.rb +++ b/app/controllers/statics_controller.rb @@ -1,5 +1,7 @@ class StaticsController < ApplicationController + caches_action :online, expires_in: 10.seconds, layout: false + def index if current_user redirect_to blogposts_path @@ -14,4 +16,30 @@ class StaticsController < ApplicationController def donate end + def online + @players = [] + @count = 0 + begin + json = JSON.parse(File.read("/etc/minecraft/redstoner/plugins/ModuleLoader/players.json")) + rescue + flash.now[:alert] = "The server is currently offline." + else + case json["dataFormat"] + when "v1" + @players = json["players"].collect!{ |p| User.find_by(uuid: p["UUID"].tr("-", "")) or User.new(name: p["name"], ign: p["name"], uuid: p["UUID"].tr("-", ""), role: Role.get("normal"), badge: Badge.get("none"), confirmed: true) } + @count = json["amount"] + when "v2" + json["players"].reject{|p| !mod? && p["vanished"] == "true"}.each do |p| + @players.push(User.find_by(uuid: p["UUID"].tr("-", "")) || User.new(name: p["name"], ign: p["name"], uuid: p["UUID"].tr("-", ""), role: Role.get("normal"), badge: Badge.get("none"), confirmed: true)) + end + @count = @players.count + else + flash.now[:alert] = "The server is using an incompatible data format. We are aware of this issue and are most likely already working on it." + end + @players.sort_by!(&:role).reverse! + end + end + + def privacy + end end diff --git a/app/controllers/threadreplies_controller.rb b/app/controllers/threadreplies_controller.rb index 946155d..a801fbc 100644 --- a/app/controllers/threadreplies_controller.rb +++ b/app/controllers/threadreplies_controller.rb @@ -37,7 +37,7 @@ class ThreadrepliesController < ApplicationController if @reply.update_attributes(reply_params) @reply.send_new_reply_mail(old_content) flash[:notice] = "Reply updated!" - position = @reply.thread.replies.index(@reply) + position = @reply.thread.replies.order(:id).index(@reply) page = position / Kaminari.config.default_per_page + 1 redirect_to forumthread_path(@reply.thread, page: page) + "#reply-#{@reply.id}" else diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e7a13d6..f6d9a71 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -9,24 +9,10 @@ class UsersController < ApplicationController caches_action :show, expires_in: 10.seconds, layout: false def index - if params[:role] - if params[:role].downcase == "staff" - @users = User.joins(:role).where("roles.value >= ?", Role.get(:mod).to_i) - elsif params[:role].downcase == "donor" - @users = User.joins(:role).where(donor: true) - else - if role = Role.get(params[:role]) - @users = User.joins(:role).where(role: role) - else - flash[:alert] = "role '#{params[:role]}' does not exist!" - redirect_to users_path - return - end - end - else - @users = User.joins(:role).where.not(id: User.first.id) #Remove first user - end - @users = @users.order("roles.value desc", "confirmed desc", :name) + role = Role.find_by(name: params[:role]) + badge = Badge.find_by(name: params[:badge]) + + @users = User.search(params[:search], role, badge, params.include?(:staff), params.include?(:donor)) @count = @users.size @users = @users.page(params[:page]).per(100) end @@ -159,9 +145,14 @@ class UsersController < ApplicationController def update if (mod? && current_user.role >= @user.role ) || (@user.is?(current_user) && confirmed?) if mod? - userdata = user_params([:name, :skype, :skype_public, :youtube, :twitter, :about, :role, :confirmed, :donor]) + userdata = user_params([:name, :skype, :youtube, :twitter, :about, :role, :badge, :confirmed, :header_scroll, :utc_time, :dark]) else - userdata = user_params([:name, :skype, :skype_public, :youtube, :twitter, :about]) + userdata = user_params([:name, :skype, :youtube, :twitter, :about, :header_scroll, :utc_time, :dark]) + end + if User.find_by(name: userdata[:name]) && User.find_by(name: userdata[:name]) != @user + flash[:alert] = "You have entered a name that belongs to someone else. Please try another." + redirect_to edit_user_path(@user) + return end if userdata[:role] role = Role.get(userdata[:role]) @@ -172,6 +163,9 @@ class UsersController < ApplicationController userdata.delete(:role) end end + if userdata[:badge] + userdata[:badge] = Badge.get(userdata[:badge]) + end if @user.youtube != userdata[:youtube] youtube = get_youtube(userdata[:youtube]) userdata[:youtube] = youtube[:channel] @@ -240,6 +234,13 @@ class UsersController < ApplicationController end end + def edit_website_settings + unless @user.is?(current_user) || admin? && current_user.role > @user.role || superadmin? + flash[:alert] = "You are not allowed to edit this user's website settings!" + redirect_to @user + end + end + def update_login if @user.is?(current_user) || admin? && current_user.role > @user.role || superadmin? authenticated = !@user.is?(current_user) || @user.authenticate(params[:current_password]) @@ -359,7 +360,7 @@ class UsersController < ApplicationController end def user_params(add = []) - a = [:ign, :email, :password, :password_confirmation, :mail_own_thread_reply, :mail_other_thread_reply, :mail_own_blogpost_comment, :mail_other_blogpost_comment, :mail_mention] + add + a = [:ign, :email, :password, :password_confirmation, :mail_own_thread_reply, :mail_other_thread_reply, :mail_own_blogpost_comment, :mail_other_blogpost_comment, :mail_mention, :public_key] + add params.require(:user).permit(a) end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1419391..a1bf22c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -11,10 +11,12 @@ module ApplicationHelper end def ago(tm) - if tm + if tm && current_user.try(:utc_time) != true content_tag :time, title: tm.strftime("%e %b %Y, %H:%M %Z"), datetime: tm.to_datetime.rfc3339 do tm.strftime("%e %b %Y, %H:%M") end + else + tm end end @@ -90,4 +92,4 @@ module ApplicationHelper https://www.youtube-nocookie.com/embed/\\1?theme=light&vq=hd720&hd=1&iv_load_policy=3&showinfo=1&showsearch=0&rel=0&modestbranding&hd=1&autohide=1&html5=1&start=\\3'> </iframe>") end -end
\ No newline at end of file +end diff --git a/app/helpers/mailer_helper.rb b/app/helpers/mailer_helper.rb index dbacf81..5e5649c 100644 --- a/app/helpers/mailer_helper.rb +++ b/app/helpers/mailer_helper.rb @@ -24,4 +24,4 @@ module MailerHelper end end end -end
\ No newline at end of file +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 2ce1765..7ad99d8 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -52,4 +52,4 @@ module UsersHelper end end -end
\ No newline at end of file +end diff --git a/app/mailers/redstoner_mailer.rb b/app/mailers/redstoner_mailer.rb index 1b387f8..e1e22b2 100644 --- a/app/mailers/redstoner_mailer.rb +++ b/app/mailers/redstoner_mailer.rb @@ -19,29 +19,49 @@ class RedstonerMailer < ActionMailer::Base def new_thread_mention_mail(user, thread) @user = user @thread = thread - mail(to: @user.email, subject: "#{thread.author.name} mentioned you in '#{thread.title}' on Redstoner") + if @user.public_key? + mail(to: @user.email, subject: "Encrypted Notification from Redstoner", gpg: {encrypt: true, keys: {@user.email => @user.public_key}}) + else + mail(to: @user.email, subject: "#{thread.author.name} mentioned you in '#{thread.title}' on Redstoner") + end end def new_thread_reply_mail(user, reply) @user = user @reply = reply - mail(to: @user.email, subject: "#{reply.author.name} replied to '#{reply.thread.title}' on Redstoner") + if @user.public_key? + mail(to: @user.email, subject: "Encrypted Notification from Redstoner", gpg: {encrypt: true, keys: {@user.email => @user.public_key}}) + else + mail(to: @user.email, subject: "#{reply.author.name} replied to '#{reply.thread.title}' on Redstoner") + end end def new_post_mention_mail(user, post) @user = user @post = post - mail(to: @user.email, subject: "#{post.author.name} mentioned you in '#{post.title}' on Redstoner") + if @user.public_key? + mail(to: @user.email, subject: "Encrypted Notification from Redstoner", gpg: {encrypt: true, keys: {@user.email => @user.public_key}}) + else + mail(to: @user.email, subject: "#{post.author.name} mentioned you in '#{post.title}' on Redstoner") + end end def new_post_comment_mail(user, comment) @user = user @comment = comment - mail(to: @user.email, subject: "#{comment.author.name} replied to '#{comment.blogpost.title}' on Redstoner") + if @user.public_key? + mail(to: @user.email, subject: "Encrypted Notification from Redstoner", gpg: {encrypt: true, keys: {@user.email => @user.public_key}}) + else + mail(to: @user.email, subject: "#{comment.author.name} replied to '#{comment.blogpost.title}' on Redstoner") + end end def email_change_confirm_mail(user) @user = user - mail(to: @user.email, subject: "Email change on Redstoner.com") + if @user.public_key? + mail(to: @user.email, subject: "Encrypted Notification from Redstoner", gpg: {encrypt: true, keys: {@user.email => @user.public_key}}) + else + mail(to: @user.email, subject: "Email change on Redstoner.com") + end end end diff --git a/app/models/badge.rb b/app/models/badge.rb new file mode 100644 index 0000000..ee3de34 --- /dev/null +++ b/app/models/badge.rb @@ -0,0 +1,18 @@ +class Badge < ActiveRecord::Base + include Comparable + has_many :users + + def self.get (input) + if input.is_a?(String) || input.is_a?(Symbol) + Badge.find_by(name: input) + elsif input.is_a?(Fixnum) + Badge.find_by(id: input) + elsif input.is_a?(Badge) + return input + end + end + + def to_s + self.name + end +end diff --git a/app/models/blogpost.rb b/app/models/blogpost.rb index 9ff64fe..7275273 100644 --- a/app/models/blogpost.rb +++ b/app/models/blogpost.rb @@ -8,6 +8,8 @@ class Blogpost < ActiveRecord::Base belongs_to :user_editor, class_name: "User", foreign_key: "user_editor_id" has_many :comments, :dependent => :destroy accepts_nested_attributes_for :comments + validates_length_of :title, in: 5..255 + validates_length_of :content, in: 5..20000 def author @author ||= if self.user_author.present? diff --git a/app/models/comment.rb b/app/models/comment.rb index 35a9a60..951d684 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -61,4 +61,4 @@ class Comment < ActiveRecord::Base background_mailer(mails) end -end
\ No newline at end of file +end diff --git a/app/models/forum.rb b/app/models/forum.rb index 39e8f2a..e892462 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -4,6 +4,7 @@ class Forum < ActiveRecord::Base belongs_to :role_read, class_name: "Role", foreign_key: "role_read_id" belongs_to :role_write, class_name: "Role", foreign_key: "role_write_id" has_and_belongs_to_many :labels + validates_length_of :name, in: 4..30 def to_s name @@ -32,4 +33,4 @@ class Forum < ActiveRecord::Base def to_param [id, to_s.parameterize].join("-") end -end
\ No newline at end of file +end diff --git a/app/models/forumgroup.rb b/app/models/forumgroup.rb index f9d156c..0d5c1f8 100644 --- a/app/models/forumgroup.rb +++ b/app/models/forumgroup.rb @@ -7,7 +7,7 @@ class Forumgroup < ActiveRecord::Base validates_presence_of :name, :position - validates_length_of :name, in: 2..20 + validates_length_of :name, in: 4..20 def to_s name diff --git a/app/models/forumthread.rb b/app/models/forumthread.rb index 905e4d3..fe551c3 100644 --- a/app/models/forumthread.rb +++ b/app/models/forumthread.rb @@ -11,6 +11,7 @@ class Forumthread < ActiveRecord::Base validates_presence_of :title, :author, :forum validates_presence_of :content + validates_length_of :title, in: 5..255 validates_length_of :content, in: 5..20000 accepts_nested_attributes_for :threadreplies @@ -65,4 +66,49 @@ class Forumthread < ActiveRecord::Base def to_param [id, to_s.parameterize].join("-") end + + def self.filter (user, title, content, reply, label, author, query, forum) + order_phrase = query || [title, content, reply].select(&:present?).join(" ") + user_id = user.try(:id).to_i + role_value = user.try(:role).to_i + can_read = "COALESCE(forum_role_read.value, 0) <= ? AND COALESCE(forumgroup_role_read.value, 0) <= ?" + # A user can view sticky threads in write-only forums without read permissions. + sticky_can_write = "sticky = true AND (COALESCE(forum_role_write.value, 0) <= ? AND COALESCE(forumgroup_role_write.value, 0) <= ?)" + match = ["MATCH (title, forumthreads.content) AGAINST (#{Forumthread.sanitize(order_phrase)})", "MATCH (threadreplies.content) AGAINST (#{Forumthread.sanitize(order_phrase)})", "MATCH (title, forumthreads.content) AGAINST (?) OR MATCH (threadreplies.content) AGAINST (?)", "MATCH (title) AGAINST (?)", "MATCH (forumthreads.content) AGAINST (?)", "MATCH (threadreplies.content) AGAINST (?)"] + + threads = forum.try(:forumthreads) || Forumthread + + threads = threads.select("forumthreads.*", "#{match[0]} AS relevance", "#{match[1]} AS reply_rel") + + threads = threads.joins(forum: :forumgroup) + .joins("LEFT JOIN threadreplies ON forumthreads.id = threadreplies.forumthread_id") + .joins("LEFT JOIN roles as forum_role_read ON forums.role_read_id = forum_role_read.id") + .joins("LEFT JOIN roles as forum_role_write ON forums.role_write_id = forum_role_write.id") + .joins("LEFT JOIN roles as forumgroup_role_read ON forumgroups.role_read_id = forumgroup_role_read.id") + .joins("LEFT JOIN roles as forumgroup_role_write ON forumgroups.role_write_id = forumgroup_role_write.id") + + threads = threads.where("forumthreads.user_author_id = ? OR (#{can_read}) OR (#{sticky_can_write})", user_id, role_value, role_value, role_value, role_value) + if query + threads = threads.where("#{match[2]}", query[0..99], query[0..99]) + elsif [title, content, reply].any? + threads = threads.where("#{match[3]}", title[0..99]) if title + threads = threads.where("#{match[4]}", content[0..99]) if content + threads = threads.where("#{match[5]}", reply[0..99]) if reply + end + if label.try(:downcase) == "no label" + threads = threads.where(label: nil) + elsif label && l = Label.find_by(name: label) + threads = threads.where(label: l) + end + threads = threads.where(user_author: author) if author + + threads = threads.group("forumthreads.id") + + if order_phrase.present? + threads = threads.order("GREATEST(relevance, reply_rel) DESC") + else + threads = threads.order("sticky DESC", "threadreplies.id DESC", "forumthreads.id DESC") + end + threads + end end diff --git a/app/models/info.rb b/app/models/info.rb index b900ad0..cbfa1d3 100644 --- a/app/models/info.rb +++ b/app/models/info.rb @@ -11,4 +11,4 @@ class Info < ActiveRecord::Base [id, to_s.parameterize].join("-") end -end
\ No newline at end of file +end diff --git a/app/models/label.rb b/app/models/label.rb index ee2fb56..d7cdc30 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -23,4 +23,4 @@ class Label < ActiveRecord::Base end end end -end
\ No newline at end of file +end diff --git a/app/models/register_token.rb b/app/models/register_token.rb index 36c0cd1..5b956ff 100644 --- a/app/models/register_token.rb +++ b/app/models/register_token.rb @@ -1,2 +1,2 @@ class RegisterToken < ActiveRecord::Base -end
\ No newline at end of file +end diff --git a/app/models/role.rb b/app/models/role.rb index 708fb40..5e5efa5 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -14,14 +14,14 @@ class Role < ActiveRecord::Base end def is? (name) - !!(Role.find_by_name(name) == self) + !!(Role.find_by(name: name) == self) end def self.get (input) if input.is_a?(String) || input.is_a?(Symbol) - Role.find_by_name(input) + Role.find_by(name: input) elsif input.is_a?(Fixnum) - Role.find_by_id(input) + Role.find_by(id: input) elsif input.is_a?(Role) return input end @@ -31,7 +31,7 @@ class Role < ActiveRecord::Base if role.is_a?(Role) self.value - role.value elsif role.is_a?(Symbol) - self <=> Role.find_by_name(role) + self <=> Role.find_by(name: role) else self.to_i <=> role end @@ -53,4 +53,4 @@ class Role < ActiveRecord::Base Role.order(:value).select {|r| r >= from}.select {|r| r <= to} end -end
\ No newline at end of file +end diff --git a/app/models/threadreply.rb b/app/models/threadreply.rb index 47b0d97..aca7770 100644 --- a/app/models/threadreply.rb +++ b/app/models/threadreply.rb @@ -43,7 +43,7 @@ class Threadreply < ActiveRecord::Base unless old_content.present? posts.each do |post| # don't send mail to the author of this reply, don't send to banned/disabled users - if post.author != author && post.author.normal? && post.author.confirmed? # && + if post.author != author && post.author.normal? && post.author.confirmed? && thread.can_read?(post.author) users << post.author if post.author.mail_other_thread_reply? end end @@ -64,4 +64,4 @@ class Threadreply < ActiveRecord::Base end background_mailer(mails) end -end
\ No newline at end of file +end diff --git a/app/models/user.rb b/app/models/user.rb index c422e28..4f682c6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,10 +5,11 @@ class User < ActiveRecord::Base strip_attributes belongs_to :role + belongs_to :badge has_secure_password - before_validation :strip_whitespaces, :set_uuid, :set_name, :set_email_token, :set_role + before_validation :strip_whitespaces, :set_uuid, :set_name, :set_email_token, :set_role, :set_badge validates_presence_of :password, :password_confirmation, :email_token, on: :create validates_presence_of :name, :email, :ign @@ -21,6 +22,8 @@ class User < ActiveRecord::Base validates :email, uniqueness: {case_sensitive: false}, format: {with: /\A.+@(.+\..{2,}|\[(IPv6)?[0-9a-f:.]+\])\z/i, message: "That doesn't look like an email address."} validates :ign, uniqueness: {case_sensitive: false}, format: {with: /\A[a-z\d_]+\z/i, message: "Username is invalid (a-z, 0-9, _)."} + validates :public_key, format: {with: /\A(-----BEGIN PGP PUBLIC KEY BLOCK-----((.|\n)*?)-----END PGP PUBLIC KEY BLOCK-----)?\z/i, message: "That doesn't look like a PGP formatted public key."} + has_many :blogposts has_many :comments @@ -29,10 +32,6 @@ class User < ActiveRecord::Base self == user end - def donor? - !!self.donor - end - def confirmed? !!self.confirmed end @@ -150,6 +149,10 @@ class User < ActiveRecord::Base self.role ||= Role.get(:normal) end + def set_badge + self.badge ||= Badge.get(:none) + end + def set_uuid if !self.uuid.present? # idk @@ -173,4 +176,23 @@ class User < ActiveRecord::Base def set_email_token self.email_token ||= SecureRandom.hex(16) end -end
\ No newline at end of file + + def self.search (search, role, badge, staff, donor) + users = User.joins(:role) + if role + users = users.where(role: role) + elsif staff + users = users.where("roles.value >= ?", Role.get(:mod).to_i) + elsif donor + users = users.where("badge_id = ? OR badge_id = ?", Badge.get(:donor), Badge.get(:donorplus)) + end + users = users.where(badge: badge) if badge + if search + search_san = User.send(:sanitize_sql_like, search.to_s) + users = users.where("users.name like ? OR ign like ?", "%#{search_san}%", "%#{search_san}%") + end + users = users.where.not(id: User.first.id) unless [search, role, badge].any? + users = users.order("roles.value desc", "confirmed desc", :name) + users + end +end diff --git a/app/views/application/_md_editor_user.html.erb b/app/views/application/_md_editor_user.html.erb new file mode 100644 index 0000000..d799fce --- /dev/null +++ b/app/views/application/_md_editor_user.html.erb @@ -0,0 +1,8 @@ +<div class="md_editor"> + <div class="field_container_user"> + <% options = (defined?(options) && options || {}) %> + <% options[:class] = "#{options[:class]} editor_field" %> + <% options[:placeholder] ||= "Enter user's name." %> + <%= text_field_tag name, content, options %> + </div> +</div> diff --git a/app/views/forums/edit.html.erb b/app/views/forums/edit.html.erb index 60b3fb1..571b3b7 100644 --- a/app/views/forums/edit.html.erb +++ b/app/views/forums/edit.html.erb @@ -21,8 +21,12 @@ <td><%= f.label :role_write_id, "Min. write role" %></td> <td><%= f.select :role_write_id, role_selection, include_blank: false %></td> </tr> + <tr> + <td><%= f.label :necro_length, "Necropost warning delay (in days)" %></td> + <td><%= f.number_field :necro_length, placeholder: "Warning Delay (leave blank for no warning)" %></td> + </tr> </table> <p><%= f.submit "Update forum", class: "btn blue left" %></p> <% end %> <p><%= button_to "Delete forum", @forum, method: "delete", data: {confirm: "Delete forum forever?\nThreads won't be accessible!"}, class: "btn red right" %></p> -<div class="clear"></div>
\ No newline at end of file +<div class="clear"></div> diff --git a/app/views/forums/index.html.erb b/app/views/forums/index.html.erb index f09ea20..a30730a 100644 --- a/app/views/forums/index.html.erb +++ b/app/views/forums/index.html.erb @@ -1,5 +1,7 @@ <% title "Forums" %> +<%= link_to "All threads", forumthreads_path, class: "btn blue right" %> +<br> <div id="forum_groups"> <% @groups.each do |group| %> <div class="item-group" id="group-<%= group.id %>"> @@ -16,7 +18,7 @@ <%= link_to f.name, f, id: "forum-#{f.id}"%> <div class="item-info"> <% if last_thread = f.threads.last %> - <% last_reply = Threadreply.where(forumthread: f.threads).order(:created_at).last %> + <% last_reply = Threadreply.where(forumthread: f.threads).order(:id).last %> <% if last_reply && last_reply.created_at > last_thread.created_at %> <% if last_reply.thread.can_read?(current_user) %> <%= last_reply.author.name %> @@ -56,4 +58,4 @@ <%= link_to "New group", new_forumgroup_path, class: "btn blue" %> <% elsif mod? %> <%= link_to "New group", "#", class: "btn blue", disabled: true %> -<% end %>
\ No newline at end of file +<% end %> diff --git a/app/views/forums/new.html.erb b/app/views/forums/new.html.erb index f60e2b3..836a9b2 100644 --- a/app/views/forums/new.html.erb +++ b/app/views/forums/new.html.erb @@ -21,8 +21,12 @@ <td><%= f.label :role_write_id, "Min. write role" %></td> <td><%= f.select :role_write_id, role_selection, include_blank: false %></td> </tr> + <tr> + <td><%= f.label :necro_length, "Necropost warning delay (in days)" %></td> + <td><%= f.number_field :necro_length, placeholder: "Warning Delay (leave blank for no warning)" %></td> + </tr> </table> <%= f.hidden_field :forumgroup_id %> <p><%= f.submit "Create forum", class: "btn blue left" %></p> <div class="clear"></div> -<% end %>
\ No newline at end of file +<% end %> diff --git a/app/views/forums/show.html.erb b/app/views/forums/show.html.erb index 60f3185..cfe3918 100644 --- a/app/views/forums/show.html.erb +++ b/app/views/forums/show.html.erb @@ -1,8 +1,13 @@ <%= link_to @forum.group, forumgroup_path(@forum.group) %> → <%= @forum %> -<h1><%= title @forum %></h1> +<h1> + <%= title @forum %> + <%= link_to "Search Threads", forumthreads_path(forum: @forum.id), class: "btn blue right" %> +</h1> <% if @forum.can_write?(current_user) %> - <p><%= link_to "New thread", new_forumthread_path(forum: @forum), class: "btn blue" %></p> + <p> + <%= link_to "New thread", new_forumthread_path(forum: @forum), class: "btn blue" %> + </p> <% end %> <% if @forum.role_read && @forum.role_write && @forum.role_write < @forum.role_read %> @@ -33,7 +38,7 @@ <div class="item <%= "#{"locked" if thread.locked}#{"sticky" if thread.sticky}" %>"> <%= render partial: "labels/label", locals: {label: thread.label} %><%= link_to truncate(thread.title, length: 60, omission: " …"), forumthread_path(thread), title: thread.title %> <div class="item-info"> - <% if rpl = thread.replies.last %> + <% if rpl = thread.replies.order(:id).last %> <%= rpl.author.name %> <% position = thread.replies.count - 1 @@ -51,4 +56,4 @@ </div> <% end %> <%= paginate @threads %> -</div>
\ No newline at end of file +</div> diff --git a/app/views/forumthreads/index.html.erb b/app/views/forumthreads/index.html.erb new file mode 100644 index 0000000..5c3f97d --- /dev/null +++ b/app/views/forumthreads/index.html.erb @@ -0,0 +1,85 @@ +<%= link_to "Forums", forums_path %> → +<% params_list = params.slice(:query, :title, :content, :author, :label, :reply) %> +<% if params_list.any? %> + <%= link_to "All Threads", forumthreads_path %> → Search Results +<% else %> + <%= "All Threads" %> +<% end %> +<h1> + <% + if params[:forum] + text = "forum '#{Forum.find(params[:forum]).name}'" + if params_list.except(:forum).any? + text = "Search results in #{text} (#{@threads.total_count})" + else + text = text.capitalize + end + elsif params_list.any? + text = "Search results (#{@threads.total_count})" + else + text = "All threads" + end + %> + <%= title text %> +</h1> +<br> +<%= form_tag(forumthreads_path, method: :get) do %> + <%= text_field_tag "query", params[:query], placeholder: "Search...", class: "searchfield field" %> + <%= submit_tag "Go", class: "searchfield btn" %> + <%= link_to "Advanced Search", search_forumthreads_path(params_list), class: "btn right blue" %> + <% if params_list.any? %> + <% if params[:forum] %> + <%= link_to "Show All Threads", forumthreads_path(params_list.except("forum")), class: "btn right blue" %> + <% elsif params_list.except(:controller, :action).any? %> + <%= link_to "Show All Threads", forumthreads_path, class: "btn right blue" %> + <% end %> + <% end %> + <% if params[:forum] %> + <%= link_to "Go to Forum", forum_path(params[:forum]), class: "btn right blue" %> + <% end %> + <% params.slice(:forum, :title, :content, :reply, :label, :author).each do |key, value| %> + <%= hidden_field_tag key, params[key] %> + <% end %> +<% end %> + +<div id="forum_groups"> + <% @threads.each do |thread| %> + <div class="item-group with-avatar" id="thread-<%= thread.id %>"> + <div class="header"> + <%= link_to(thread.author.avatar(64), thread.author, title: thread.author.ign) %> + <%= render partial: "users/username", locals: { user: thread.author } %> + <%= link_to thread do %> + <%= ago thread.created_at %> + <% end %> + <span class="comment-counter"> + <%= link_to pluralize(thread.replies.count, "Reply"), thread %> + </span> + <div class="clear-right"></div> + </div> + <div class="items bold"> + <div class="item <%= "#{"locked" if thread.locked}#{"sticky" if thread.sticky}" %>"> + <%= render partial: "labels/label", locals: {label: thread.label} %><%= link_to truncate(thread.title, length: 60, omission: " …"), forumthread_path(thread), title: thread.title %> + <div class="item-info"> + <% if rpl = thread.replies.order(:id).last %> + <%= rpl.author.name %> + <% + position = thread.replies.count - 1 + page = position / Kaminari.config.default_per_page + 1 + %> + <%= link_to "replied", forumthread_path(thread, page: page) + "#reply-#{rpl.id}" %> + <%= ago rpl.created_at %>. + <% else %> + No replies yet. + <% end %> + </div> + <div class="clear"></div> + </div> + </div> + </div> + <% end %> + <% if @threads.empty? %> + <br> + <h3>No results found</h3> + <% end %> + <%= paginate @threads %> +</div> diff --git a/app/views/forumthreads/search.html.erb b/app/views/forumthreads/search.html.erb new file mode 100644 index 0000000..125868a --- /dev/null +++ b/app/views/forumthreads/search.html.erb @@ -0,0 +1,54 @@ +<% title "Thread Search" %> +<h1>Thread Search</h1> +<h3>Leave a field blank to ignore that search aspect.</h3> +<% label = Label.where(name: params[:label]).first %> +<table> + <tbody> +<%= form_tag(forumthreads_path, method: :get) do %> + <% + forums = [] + Forum.select{|f| f.can_read?(current_user)}.sort_by{ |f| f.forumgroup && f.forumgroup.position || 0 }.each do |f| + forums << ["#{f.forumgroup.name} → #{f.name}", f.id] if f.forumgroup + end + %> + <% label_list = Label.pluck(:name).prepend("No Label") %> + <tr> + <td>Forum</td> + <td><%= select_tag "forum", options_for_select(forums, params[:forum]), include_blank: "Search All Threads" %></td> + </tr> + <tr> + <td>Label</td> + <td> + <%= select_tag "label", options_for_select(label_list, params[:label]), include_blank: "Label" %> + </td> + </tr> + <tr> + <td>Title</td> + <td> + <%= text_field_tag "title", params[:title], placeholder: "Search Titles" %> + </td> + </tr> + <tr> + <td>Content</td> + <td> + <%= text_field_tag "content", params[:content], placeholder: "Search Contents" %> + </td> + <tr> + <td>Author</td> + <td> + <%= render partial: "md_editor_user", locals: {name: "author", content: params[:author]} %> + </td> + </tr> + <td>Replies</td> + <td> + <%= text_field_tag "reply", params[:reply], placeholder: "Search Replies" %> + </td> + </tr> + <tr> + <td> + <%= submit_tag "Go", class: "btn blue", style: "width:50px", name: nil %> + </td> + </tr> +<% end %> + </tbody> +</table> diff --git a/app/views/forumthreads/show.html.erb b/app/views/forumthreads/show.html.erb index 876d55d..b29d29e 100644 --- a/app/views/forumthreads/show.html.erb +++ b/app/views/forumthreads/show.html.erb @@ -1,6 +1,8 @@ <%= link_to @thread.forum.group, forumgroup_path(@thread.forum.group) %> → <%= link_to @thread.forum, @thread.forum %> → <%=truncate(@thread.title, length: 60, omission: " …") %> -<h1><%= render partial: "labels/label", locals: {label: @thread.label} %><%= title @thread.title %></h1> - +<h1> + <%= render partial: "labels/label", locals: {label: @thread.label} %><%= title @thread.title %> + <%= link_to "Reverse Replies", forumthread_path(@thread, reverse: params[:reverse] != "true"), class: "btn right blue" %> +</h1> <div class="item-group thread with-avatar" id="thread-<%= @thread.id %>"> <div class="header"> <%= link_to(@thread.author.avatar(64), @thread.author, title: @thread.author.ign) %> @@ -44,4 +46,4 @@ <% else %> <p>Please <%= link_to "Log in", login_path(return_path: request.env['PATH_INFO']), action: "new" %> to post a reply.</p> <% end %> -</div>
\ No newline at end of file +</div> diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb index 930eb26..cc2b2fd 100644 --- a/app/views/layouts/_footer.html.erb +++ b/app/views/layouts/_footer.html.erb @@ -13,6 +13,12 @@ <% end %> | <%= link_to "https://twitter.com/RedstonerServer", title: "Redstoner on Twitter" do %> Twitter <%= image_tag("twitter.png") %> + <% end %> | + <%= link_to "https://mstdn.io/@RedstonerServer", title: "Redstoner on Mastodon" do %> + Mastodon <%= image_tag("mastodon.png") %> + <% end %> | + <%= link_to "http://rdstnr4biap5nao2.onion", title: "Redstoner over Tor" do %> + Onion Service <%= image_tag("tor.png") %> <% end %> <% if current_user %> | <%= link_to "/slack/?" + {mail: current_user.try(:email)}.to_param do %> @@ -20,4 +26,4 @@ <% end %> <% end %> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/layouts/_head.html.erb b/app/views/layouts/_head.html.erb index 183a615..c64fe30 100644 --- a/app/views/layouts/_head.html.erb +++ b/app/views/layouts/_head.html.erb @@ -1,4 +1,9 @@ -<div id="head"> +<% head = "head_top" %> +<% if current_user != nil && current_user.header_scroll == true %> + <% head = "head_scroll" %> +<% end %> + +<div id="<%= head %>"> <div id="menu"> <%= link_to "", root_path, id: "logo" %> <ul> @@ -26,6 +31,9 @@ <li> <%= link_to "Donate", donate_statics_path, class: ("active" if con == "statics" && params[:action] == "donate") %> </li> + <li> + <%= link_to "Who's Playing?", online_statics_path, class: ("active" if con == "statics" && params[:action] == "online") %> + </li> </ul> </div> <div id="userbar"> @@ -41,4 +49,4 @@ <% end %> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a0a5f83..e85d417 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,6 +5,9 @@ <meta name="viewport" content="initial-scale=1,maximum-scale=1"> <meta name="description" content="Redstoner is a creative minecraft server made for redstoners"> <%= stylesheet_link_tag "application", :media => "all" %> + <% if current_user.try(:dark) == true %> + <%= stylesheet_link_tag "dark", :media => "all" %> + <% end %> <%= csrf_meta_tags %> <%= favicon_link_tag "favicon.ico" %> <%= javascript_include_tag "https://cdn.rawgit.com/jomo/ago.js/v0.0.1/ago.min.js", crossorigin: :anonymous, integrity: "sha256-xw0JUUdbuZQCVO+QScoxrlEsD4nZGCjMRh9PP8GLhcY=" %> @@ -14,7 +17,11 @@ </head> <body> <%= render partial: "/layouts/head" %> - <div id="main-content" class="<%= yield(:main_class) %>"> + <% content = "main-content" %> + <% if current_user.try(:header_scroll) == true %> + <% content = "main-content-scroll" %> + <% end %> + <div id="<%=content%>" class="<%=yield(:main_class) %>"> <% if alert %> <div class='flash alert'><%= alert %></div> <% end %> @@ -25,4 +32,4 @@ </div> <%= render partial: "/layouts/footer" %> </body> -</html>
\ No newline at end of file +</html> diff --git a/app/views/redstoner_mailer/email_change_confirm_mail.html.erb b/app/views/redstoner_mailer/email_change_confirm_mail.html.erb index 33e853a..8d108c9 100644 --- a/app/views/redstoner_mailer/email_change_confirm_mail.html.erb +++ b/app/views/redstoner_mailer/email_change_confirm_mail.html.erb @@ -13,7 +13,7 @@ </div> <p></p> - <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(role: "staff"), style: "text-decoration: none; color: #4096EE;" %> in-game.</p> + <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(staff: ""), style: "text-decoration: none; color: #4096EE;" %> in-game.</p> <p>Your Redstoner team</p> </div> @@ -25,9 +25,9 @@ <p>You can contact us via: <%= link_to "Website", root_url, style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Twitter", "https://twitter.com/RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | - <%= link_to "Google+", "https://google.com/+Redstoner", style: "text-decoration: none; color: #4096EE;" %> | + <%= link_to "Mastodon", "https://mstdn.io/@RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Email", "mailto:redstonerserver+website@gmail.com", style: "text-decoration: none; color: #4096EE;" %> </p> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/redstoner_mailer/new_post_comment_mail.html.erb b/app/views/redstoner_mailer/new_post_comment_mail.html.erb index 8936087..08e1813 100644 --- a/app/views/redstoner_mailer/new_post_comment_mail.html.erb +++ b/app/views/redstoner_mailer/new_post_comment_mail.html.erb @@ -14,7 +14,7 @@ %> <p><%= link_to "Click here", blogpost_url(@comment.blogpost, page: page) + "#comment-#{@comment.id}", style: "text-decoration: none; color: #4096EE;" %> to view the blog post.</p> - <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(role: "staff"), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> + <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(staff: ""), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> <p>Your Redstoner team</p> </div> @@ -24,9 +24,9 @@ <p>You can contact us via: <%= link_to "Website", root_url, style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Twitter", "https://twitter.com/RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | - <%= link_to "Google+", "https://google.com/+Redstoner", style: "text-decoration: none; color: #4096EE;" %> | + <%= link_to "Mastodon", "https://mstdn.io/@RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Email", "mailto:redstonerserver+website@gmail.com", style: "text-decoration: none; color: #4096EE;" %> </p> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/redstoner_mailer/new_post_mention_mail.html.erb b/app/views/redstoner_mailer/new_post_mention_mail.html.erb index 5119e7c..08c8097 100644 --- a/app/views/redstoner_mailer/new_post_mention_mail.html.erb +++ b/app/views/redstoner_mailer/new_post_mention_mail.html.erb @@ -10,7 +10,7 @@ <p><%= link_to "Click here", blogpost_url(@post), style: "text-decoration: none; color: #4096EE;" %> to view the blog post.</p> - <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(role: "staff"), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> + <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(staff: ""), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> <p>Your Redstoner team</p> </div> @@ -21,9 +21,9 @@ <p>You can contact us via: <%= link_to "Website", root_url, style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Twitter", "https://twitter.com/RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | - <%= link_to "Google+", "https://google.com/+Redstoner", style: "text-decoration: none; color: #4096EE;" %> | + <%= link_to "Mastodon", "https://mstdn.io/@RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Email", "mailto:redstonerserver+website@gmail.com", style: "text-decoration: none; color: #4096EE;" %> </p> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/redstoner_mailer/new_thread_mention_mail.html.erb b/app/views/redstoner_mailer/new_thread_mention_mail.html.erb index 701901e..35904d0 100644 --- a/app/views/redstoner_mailer/new_thread_mention_mail.html.erb +++ b/app/views/redstoner_mailer/new_thread_mention_mail.html.erb @@ -11,7 +11,7 @@ <p><%= link_to "Click here", forumthread_url(@thread), style: "text-decoration: none; color: #4096EE;" %> to view the thread.</p> - <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(role: "staff"), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> + <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(staff: ""), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> <p>Your Redstoner team</p> </div> @@ -23,9 +23,9 @@ <p>You can contact us via: <%= link_to "Website", root_url, style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Twitter", "https://twitter.com/RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | - <%= link_to "Google+", "https://google.com/+Redstoner", style: "text-decoration: none; color: #4096EE;" %> | + <%= link_to "Mastodon", "https://mstdn.io/@RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Email", "mailto:redstonerserver+website@gmail.com", style: "text-decoration: none; color: #4096EE;" %> </p> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/redstoner_mailer/new_thread_reply_mail.html.erb b/app/views/redstoner_mailer/new_thread_reply_mail.html.erb index eadd4f9..d71b136 100644 --- a/app/views/redstoner_mailer/new_thread_reply_mail.html.erb +++ b/app/views/redstoner_mailer/new_thread_reply_mail.html.erb @@ -15,7 +15,7 @@ %> <p><%= link_to "Click here", forumthread_url(@reply.thread, page: page) + "#reply-#{@reply.id}", style: "text-decoration: none; color: #4096EE;" %> to view the thread.</p> - <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(role: "staff"), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> + <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(staff: ""), style: "text-decoration: none; color: #4096EE;" %> in-game or on the forums!</p> <p>Your Redstoner team</p> </div> @@ -26,8 +26,8 @@ <p>You can contact us via: <%= link_to "Website", root_url, style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Twitter", "https://twitter.com/RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | - <%= link_to "Google+", "https://google.com/+Redstoner", style: "text-decoration: none; color: #4096EE;" %> | + <%= link_to "Mastodon", "https://mstdn.io/@RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Email", "mailto:redstonerserver+website@gmail.com", style: "text-decoration: none; color: #4096EE;" %> </p> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/redstoner_mailer/register_mail.html.erb b/app/views/redstoner_mailer/register_mail.html.erb index 3e09a1e..f0af4a4 100644 --- a/app/views/redstoner_mailer/register_mail.html.erb +++ b/app/views/redstoner_mailer/register_mail.html.erb @@ -25,7 +25,7 @@ </div> <p></p> - <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(role: "staff"), style: "text-decoration: none; color: #4096EE;" %> in-game.</p> + <p>If you have any questions or problems, just ask one of our <%= link_to "Staff", users_url(staff: ""), style: "text-decoration: none; color: #4096EE;" %> in-game.</p> <p>Your Redstoner team</p> </div> @@ -37,9 +37,9 @@ <p>You can contact us via: <%= link_to "Website", root_url, style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Twitter", "https://twitter.com/RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | - <%= link_to "Google+", "https://google.com/+Redstoner", style: "text-decoration: none; color: #4096EE;" %> | + <%= link_to "Mastodon", "https://mstdn.io/@RedstonerServer", style: "text-decoration: none; color: #4096EE;" %> | <%= link_to "Email", "mailto:redstonerserver+website@gmail.com", style: "text-decoration: none; color: #4096EE;" %> </p> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/app/views/statics/donate.html.erb b/app/views/statics/donate.html.erb index 2831807..c304917 100644 --- a/app/views/statics/donate.html.erb +++ b/app/views/statics/donate.html.erb @@ -1,3 +1,4 @@ +<% title "Donate" %> <h1>Donate</h1> <p>Running a server is really stressful and requires a lot of work.<br> @@ -11,7 +12,7 @@ <li>Donator+ ($20 or more) </ul> -<p>We also have <%= link_to "list of users who donated", users_path(role: "donor") %> already!</p> +<p>We also have a <%= link_to "list of users who donated", users_path(donor: "") %> already!</p> <h3>Perks for you</h3> <p>For <i>Donator</i> and <i>Donator+</i></p> @@ -19,16 +20,17 @@ <li>The warm feeling of donating for a good thing, plus a huge "<b>thank you</b>"! <li>You can have a nickname. See <%= link_to "our nickname guidelines", info_path("12-nickname-guidelines") %> <li>A "$" next to your name <i>(Including website)</i> + <li><i>Donator+</i> has access to the in-game command <code>/lol id</code></li> </ul> <hr> <div class="donations"> <div class="donation"> <div class="left"> - <img src="<%= image_url("anonymous_skin.png") %>" alt="sponsor's skin" class="body"> + <img src="https://crafatar.com/renders/body/97a4928198f045998e0e7a97eabae6ae?overlay=true&scale=3" alt="sponsor's skin" class="body"> </div> <div> <h1>Donate to our server sponsor</h1> - <h4>They pay for our server, but prefer to stay anonymous</h4> + <h4>PotatoKek pays for the server hardware. You can help him by donating here.</h4> <form target="_blank" method="post" action="https://www.paypal.com/cgi-bin/webscr"> <% if current_user %> <input name="custom" type="hidden" placeholder="Your Minecraft name" value="<%= current_user.ign %>"> @@ -45,4 +47,4 @@ </div> <hr> -<p class="small">Please note that you are not buying anything. We do not guarantee for these perks, however, we will try hard to make sure you'll get them! Donations are processed manually, it can take a few hours.</p>
\ No newline at end of file +<p class="small">Please note that you are not buying anything. We do not guarantee for these perks, however, we will try hard to make sure you'll get them! Donations are processed manually, it can take a few hours.</p> diff --git a/app/views/statics/online.html.erb b/app/views/statics/online.html.erb new file mode 100644 index 0000000..8bacf6f --- /dev/null +++ b/app/views/statics/online.html.erb @@ -0,0 +1,18 @@ +<% title "Who's Playing?" %> +<h1>These players are currently playing on Redstoner (<%= @count %>):</h1> +<div id="userlist"> + <% @players.each do |u| %> + <div class="list-user"> + <%= link_to(u.avatar(64), u) %> + <div class="detail"> + <%= render partial: "users/username", locals: { user: u } %><br> + <% if u.id %> + <i><%= u.ign %></i> + <% else %> + <i>(Not signed up)</i> + <% end %> + </div> + </div> + <% end %> +</div> + diff --git a/app/views/statics/privacy.html.erb b/app/views/statics/privacy.html.erb new file mode 100644 index 0000000..4f44697 --- /dev/null +++ b/app/views/statics/privacy.html.erb @@ -0,0 +1,41 @@ +<% title "Privacy Policy" %> +<h1>Privacy Policy</h1> +<p>Please note that this privacy policy is not legally binding. It is simply a reference intended to inform you about what is done with your information. Also, this privacy policy only applies to the Redstoner website and forums. The Minecraft server will have its own privacy policy at some point.</p> +<h2>How your information is stored and protected</h2> +<p>Everything on the website is stored in a database, to which access is strictly limited. Only users of the administrator rank or former administrators who are well known and are trusted by the rest of the current administrators may access the database. Offsite backups of this data are made daily only to the network and servers of at least one current administrator via an encrypted SSH connection.</p> +<p>Passwords are stored using the bcrypt algorithm. Plaintext passwords are never logged or stored anywhere.</p> +<p>The website code is <%= link_to "open source", "https://github.com/RedstonerServer/redstoner.com" %> and undergoes heavy testing and review before it is deployed to ensure no exploitable bugs or backdoors make it onto the production server.</p> +<p>All connections to our website are automatically forced to be made over HTTPS to ensure your data is protected while in transit. We maintain <%= link_to "good TLS paramters", "https://www.ssllabs.com/ssltest/analyze.html?d=redstoner.com" %> and also employ other techniques to ensure secure connections such as <%= link_to "being on the HSTS preload list", "https://hstspreload.org/?domain=redstoner.com" %> and OCSP stapling.</p> +<h2>Information we collect</h2> +<p>This information is needed in order for your account to be created:</p> +<ul> + <li>Your Minecraft account's IGN and UUID.</li> + <li>Your email address.</li> + <li>A unique password.</li> +</ul> +<p>This information is optional and is obtained only if you provide it:</p> +<ul> + <li>Your Skype username.</li> + <li>Your YouTube channel ID.</li> + <li>Your Twitter username.</li> +</ul> +<p>This information is also collected, however does not affect your Redstoner account directly:</p> +<ul> + <li>Your IP address.</li> +</ul> +<h2>How your information is used and who it is visible to</h2> +<ul> + <li><b>Minecraft account IGN and UUID</b> - This is used to link your Minecraft account with your Redstoner account. Anyone can see these.</li> + <li><b>Your email address</b> - This is used to send you email notifications about forums activity that you are involved in. These notifications can be disabled in your account settings. This is also used to perform a password reuse check, which is explained in more detail below. Only users of the moderator rank or higher can see your email address.</li> + <li><b>Your password</b> - This is used to authenticate you. This too is used to perform a password reuse check. The plaintext version is visible to no one, but the hashed version is visible only to users of the administrator rank or higher.</li> + <li><b>Your Skype username</b> - This is used to add a link to your profile that allows others to easily contact you over Skype. Anyone can see this.</li> + <li><b>Your YouTube channel</b> - This is used to add a link to your profile that allows others to easily find your YouTube channel. Anyone can see this.</li> + <li><b>Your Twitter username</b> - This is used to add a link to your profile that allows others to easily contact you over Twitter. Anyone can see this.</li> + <li><b>Your IP address</b> - This is used to help us identify and ban troublemakers from our forums. Only users of the moderator rank and above can see this.</li> +</ul> +<h2>Password reuse check</h2> +<p>When you first sign up on our website, we use your email address and password to check if you are reusing your password with your Mojang account. This is done by attempting to log into Mojang's server using this information. If it succeeds, then your confirmation email will contain a note warning you not to reuse your password. <b>The information used to perform this check is never used to actually take over your Minecraft account. In fact, we can't because your password is hashed after the check and is totally unusable to us. If you get this warning not to reuse your password, it is still highly recommended that you change your password for your Mojang account and also use a password manager.</b></p> +<h2>Who your information is shared with</h2> +<p>We do not share your information with any third parties. The only time we will release information is if we are legally required to.</p> +<hr> +<p><sup>This privacy policy was last revised October 31, 2017.</sup></p> diff --git a/app/views/threadreplies/_new.html.erb b/app/views/threadreplies/_new.html.erb index b0c4b5e..c22463d 100644 --- a/app/views/threadreplies/_new.html.erb +++ b/app/views/threadreplies/_new.html.erb @@ -1,4 +1,19 @@ <%= form_for [reply.thread, reply] do |f| %> <%= render partial: "md_editor", locals: {name: "threadreply[content]", content: reply.content} %> - <p><%= f.submit "Reply#{ ' (Locked)' if reply.thread.locked? }", class: "btn blue" %></p> -<% end %>
\ No newline at end of file + <% nec_msg = "" %> + <% forum = Forum.find(reply.thread.forum_id) %> + <% if forum.necro_length %> + <% if reply.thread.label.try(:name).try(:downcase) == "closed" %> + <% nec_msg = "This thread is closed. Are you sure you want to make this reply? If so, press 'Ok'" %> + <% elsif Threadreply.where(forumthread: reply.thread).any? %> + <% prevAgo = Threadreply.where(forumthread: reply.thread).order(:id).last.created_at %> + <% if prevAgo <= forum.necro_length.days.ago.utc %> + <% nec_msg = "You may be necroposting, as the last reply was made at least #{forum.necro_length} days ago. If you still wish to make this reply, press 'Ok'." %> + <% end %> + <% elsif reply.thread.created_at <= forum.necro_length.days.ago.utc %> + <% nec_msg = "You may be necroposting, as this thread was posted at least #{forum.necro_length} days ago. If you still wish to make this reply, press 'Ok'." %> + <% end %> + <% end %> + <p><%= f.submit "Reply#{ ' (Locked)' if reply.thread.locked? }", class: "btn blue", data: { confirm: nec_msg } %></p> + <% nec_msg = "" %> +<% end %> diff --git a/app/views/threadreplies/edit.html.erb b/app/views/threadreplies/edit.html.erb index c009cb0..8296d9c 100644 --- a/app/views/threadreplies/edit.html.erb +++ b/app/views/threadreplies/edit.html.erb @@ -1,7 +1,7 @@ <% title "Edit Thread Reply: #{@reply.thread.title}" %> <% - position = @reply.thread.replies.index(@reply) + position = @reply.thread.replies.order(:id).index(@reply) page = position / Kaminari.config.default_per_page + 1 %> diff --git a/app/views/users/_username.html.erb b/app/views/users/_username.html.erb index 10adb36..1220995 100644 --- a/app/views/users/_username.html.erb +++ b/app/views/users/_username.html.erb @@ -1,4 +1,6 @@ <div class="user"> <%= link_to user.name, user, class: "role #{user.role.name} #{"banned" if user.banned?} #{"disabled" if user.disabled?} #{"unconfirmed" unless user.confirmed?}", title: "#{user.ign} – #{user.role}", style: "color: #{fcolor(user.role.color)}; background-color: #{user.role.color}" %> - <%= link_to "$", donate_statics_path, class: "role donor", title: "Donator" if user.donor? %> -</div>
\ No newline at end of file + <% if user.badge %> + <%= link_to user.badge.symbol, users_path(badge: user.badge.name), class: "role badge", title: user.badge.name, style: "color: #{fcolor(user.badge.color)}; background-color: #{user.badge.color}" unless user.badge.symbol.blank? %> + <% end %> +</div> diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 6a6fe4d..abd1fa4 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -28,15 +28,17 @@ </td> </tr> <tr> - <td>Confirmed email address</td> + <td>Badge</td> <td> - <%= f.select :confirmed, [["No", false], ["Yes", true]], {}, { disabled: !can_edit? } %> + <% if current_user.role >= Role.get(:mod) %> + <%= f.select :badge, Badge.all %> + <% end %> </td> </tr> <tr> - <td>Donator</td> + <td>Confirmed email address</td> <td> - <%= f.select :donor, [["No", false], ["Yes", true]], {}, { disabled: !can_edit? } %> + <%= f.select :confirmed, [["No", false], ["Yes", true]], {}, { disabled: !can_edit? } %> </td> </tr> <% end %> @@ -47,12 +49,6 @@ </td> </tr> <tr> - <td>Show Skype to</td> - <td> - <%= f.select :skype_public, [["Staff only", false], ["All users", true]], {}, { disabled: !can_edit? } %> - </td> - </tr> - <tr> <td>YouTube Channel ID</td> <td> <%= f.text_field :youtube, placeholder: "YouTube Channel ID", disabled: !can_edit? %> @@ -73,10 +69,11 @@ </tbody> </table> -<p><%= f.submit "Save profile", class: "btn blue left", disabled: (!@user.confirmed? && @user.is?(current_user)) %></p> +<p><%= f.submit "Save profile", class: "btn variable-size left", disabled: (!@user.confirmed? && @user.is?(current_user)) %></p> <p> - <%= link_to "Edit login details", edit_login_user_path(@user), class: "btn blue right" %> - <%= link_to "Notification settings", edit_notifications_user_path(@user), class: "btn blue right" %> + <%= link_to "Edit login details", edit_login_user_path(@user), class: "btn variable-size right" %> + <%= link_to "Notification settings", edit_notifications_user_path(@user), class: "btn variable-size right" %> + <%= link_to "Website settings", edit_website_settings_user_path(@user), class: "btn variable-size right" %> </p> <div class="clear"></div> @@ -87,4 +84,4 @@ <span class='red-alert'>This user has not confirmed his email!</span> <% end %> <% end %> -<% end %>
\ No newline at end of file +<% end %> diff --git a/app/views/users/edit_notifications.html.erb b/app/views/users/edit_notifications.html.erb index 4e6de12..9c45445 100644 --- a/app/views/users/edit_notifications.html.erb +++ b/app/views/users/edit_notifications.html.erb @@ -45,6 +45,9 @@ </tr> </tbody> </table> + <h3>Public Key</h1> + <p>All notification emails will be encrypted with this key if you supply it.</p> + <%= f.text_area :public_key, placeholder: "-----BEGIN PGP PUBLIC KEY BLOCK-----" %> <p><%= f.submit "Save changes", class: "btn blue left" %></p> <div class="clear"></div> -<% end %>
\ No newline at end of file +<% end %> diff --git a/app/views/users/edit_website_settings.html.erb b/app/views/users/edit_website_settings.html.erb new file mode 100644 index 0000000..2fdeffb --- /dev/null +++ b/app/views/users/edit_website_settings.html.erb @@ -0,0 +1,34 @@ +<% title "Edit Website Settings: #{@user.name}" %> + +<%= link_to @user.name, @user %> → Edit Website Settings +<h1>Edit Website Settings</h1> + + +<%= form_for @user do |f| %> + <table> + <tbody> + <tr> + <td>Header moves with scrolling (Experimental - do not report bugs)</td> + <td> + <%= f.check_box :header_scroll %> + </td> + </tr> + <tr> + <td>Show exact UTC times</td> + <td> + <%= f.check_box :utc_time %> + </td> + </tr> + <tr> + <td>Dark theme*</td> + <td> + <%= f.check_box :dark %> + </td> + </tr> + </tbody> + </table> + <p><%= f.submit "Save changes", class: "btn blue left" %></p> + <div class="clear"></div> +<% end %> +<br><br><br> +*Warning: If as a result to enabling this style your eyes get infected with a severe case of eye cancer, we are not reliable for any damage. Please contact your doctor in advance to ensure that in case of infection you will be treated accordingly. Quality theme brought to you by Redempt™. diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 883ffb0..a8888db 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,12 +1,34 @@ +<%= form_tag(users_path, method: :get) do %> + <%= text_field_tag "search", params[:search], placeholder: "Search for a user", class: "searchfield field" %> + <%= submit_tag "Go", class: "searchfield btn", name: nil %> + <%= hidden_field_tag "role", params[:role] if params[:role] %> + <%= hidden_field_tag "badge", params[:badge] if params[:badge]%> +<% end %> <h1> - <% if params[:role] %> - <%= title "All '#{params[:role]}' users" %> + <% + if params[:role] && !params[:badge] + text = "All '#{params[:role]}' users" + elsif params[:badge] && !params[:role] + text = "All '#{params[:badge]}' users" + elsif params[:role] && params[:badge] + text = "All '#{params[:role]}' and '#{params[:badge]}' users" + elsif params.include?(:staff) + text = "All staff" + elsif params.include?(:donor) + text = "All donors" + else + text = "All users" + end + text += " that contain '#{params[:search]}'" if params[:search] + %> + <%= title text %> + <% if params[:search] %> + (<%= @users.total_count %>) <% else %> - <%= title "All Users" %> + (<%= @count %>) <% end %> - (<%= @count %>) </h1> -<%= link_to "show all", users_path if params[:role] %> +<%= link_to "show all", users_path if params[:role] || params[:badge] %> <div id="userlist"> <% @users.each do |u| %> @@ -19,4 +41,4 @@ </div> <% end %> <%= paginate @users %> -</div>
\ No newline at end of file +</div> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index c482df9..1d8a8c6 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -40,5 +40,5 @@ <%= f.submit "Sign up", class: "btn blue" %> - <p>Contact us ingame if you have problems singing up!</p> -<% end %>
\ No newline at end of file + <p>Contact us ingame if you have problems signing up!</p> +<% end %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index de784a2..a982928 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -54,7 +54,7 @@ <td><b>Role</b></td> <td><%= link_to @user.role, users_path(:role => @user.role.name) %></td> </tr> - <% if current_user && !@user.skype.blank? && (@user.skype_public || current_user == @user || mod?) %> + <% if current_user && !@user.skype.blank? %> <tr> <td><b>Skype</b></td> <td><%= link_to @user.skype, "skype:#{@user.skype}?chat", target: "_blank" %></a></td> diff --git a/config/database.yml b/config/database.yml index f421bef..db672c6 100644 --- a/config/database.yml +++ b/config/database.yml @@ -24,4 +24,4 @@ test: adapter: sqlite3 database: db/test.sqlite3 pool: 5 - timeout: 5000
\ No newline at end of file + timeout: 5000 diff --git a/config/environments/development.rb b/config/environments/development.rb index 06819fd..bfa0c96 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -6,6 +6,8 @@ Redstoner::Application.configure do # since you don't have to restart the web server when you make code changes. config.cache_classes = false + config.action_controller.perform_caching = true + # Log error messages when you accidentally call methods on nil. config.whiny_nils = true @@ -43,4 +45,4 @@ Redstoner::Application.configure do password: ENV["GMAIL_PASSWORD"], } -end
\ No newline at end of file +end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000..ea74dfd --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1 @@ +Rails.application.config.assets.precompile += %w( dark.css ) diff --git a/config/routes.rb b/config/routes.rb index 584c94f..6ad277b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,10 +4,12 @@ Redstoner::Application.routes.draw do resources :comments end - resources :statics, only: [:home, :donate], path: '/' do + resources :statics, only: [:home, :donate, :online], path: '/' do collection do get 'donate' get 'home' + get 'online' + get 'privacy' get 'index' end end @@ -21,6 +23,7 @@ Redstoner::Application.routes.draw do post 'resend_mail' get 'edit_notifications' put 'update_login' + get 'edit_website_settings' end collection do get 'lost_password' @@ -30,10 +33,13 @@ Redstoner::Application.routes.draw do end resources :forumgroups, path: '/forums/groups' - resources :forums, path: '/forums' resources :forumthreads, path: '/forums/threads' do resources :threadreplies, path: 'replies' + collection do + get 'search' + end end + resources :forums, path: '/forums' resources :tools do collection do diff --git a/db/migrate/20140617183701_create_roles.rb b/db/migrate/20140617183701_create_roles.rb index 3a25ea7..ad89207 100644 --- a/db/migrate/20140617183701_create_roles.rb +++ b/db/migrate/20140617183701_create_roles.rb @@ -5,4 +5,4 @@ class CreateRoles < ActiveRecord::Migration t.integer :value end end -end
\ No newline at end of file +end diff --git a/db/migrate/20140617183702_create_users.rb b/db/migrate/20140617183702_create_users.rb index 1fefaf9..20e8a20 100644 --- a/db/migrate/20140617183702_create_users.rb +++ b/db/migrate/20140617183702_create_users.rb @@ -23,4 +23,4 @@ class CreateUsers < ActiveRecord::Migration t.timestamps null: true end end -end
\ No newline at end of file +end diff --git a/db/migrate/20170319193517_add_badge_id_to_users.rb b/db/migrate/20170319193517_add_badge_id_to_users.rb new file mode 100644 index 0000000..4738e11 --- /dev/null +++ b/db/migrate/20170319193517_add_badge_id_to_users.rb @@ -0,0 +1,17 @@ +class AddBadgeIdToUsers < ActiveRecord::Migration + def change + + create_table "badges", force: :cascade do |t| + t.string "name" + t.string "symbol" + t.string "color" + end + + Badge.create!({name: "none", symbol: "", color: "#000"}) + dbadge = Badge.create!({name: "donor", symbol: "$", color: "#f60"}) + + add_column :users, :badge_id, :integer, default: 1 + User.where(donor: true).update_all(badge_id: dbadge.id) + remove_column :users, :donor + end +end diff --git a/db/migrate/20170320195301_add_utc_time_to_users.rb b/db/migrate/20170320195301_add_utc_time_to_users.rb new file mode 100644 index 0000000..538357c --- /dev/null +++ b/db/migrate/20170320195301_add_utc_time_to_users.rb @@ -0,0 +1,5 @@ +class AddUtcTimeToUsers < ActiveRecord::Migration + def change + add_column :users, :utc_time, :boolean, default: false + end +end diff --git a/db/migrate/20170328100851_add_header_scroll_to_users.rb b/db/migrate/20170328100851_add_header_scroll_to_users.rb new file mode 100644 index 0000000..0db36b1 --- /dev/null +++ b/db/migrate/20170328100851_add_header_scroll_to_users.rb @@ -0,0 +1,5 @@ +class AddHeaderScrollToUsers < ActiveRecord::Migration + def change + add_column :users, :header_scroll, :boolean, default: false + end +end diff --git a/db/migrate/20170409135858_add_necro_length_to_forums.rb b/db/migrate/20170409135858_add_necro_length_to_forums.rb new file mode 100644 index 0000000..53199e4 --- /dev/null +++ b/db/migrate/20170409135858_add_necro_length_to_forums.rb @@ -0,0 +1,5 @@ +class AddNecroLengthToForums < ActiveRecord::Migration + def change + add_column :forums, :necro_length, :integer + end +end diff --git a/db/migrate/20170515200733_add_dark_to_users.rb b/db/migrate/20170515200733_add_dark_to_users.rb new file mode 100644 index 0000000..c4bf3cc --- /dev/null +++ b/db/migrate/20170515200733_add_dark_to_users.rb @@ -0,0 +1,5 @@ +class AddDarkToUsers < ActiveRecord::Migration + def change + add_column :users, :dark, :boolean, default: false + end +end diff --git a/db/migrate/20170522210610_add_search_indexes.rb b/db/migrate/20170522210610_add_search_indexes.rb new file mode 100644 index 0000000..2225d7b --- /dev/null +++ b/db/migrate/20170522210610_add_search_indexes.rb @@ -0,0 +1,8 @@ +class AddSearchIndexes < ActiveRecord::Migration + def change + add_index :forumthreads, [:title, :content], type: :fulltext + add_index :forumthreads, :title, type: :fulltext + add_index :forumthreads, :content, type: :fulltext + add_index :threadreplies, :content, type: :fulltext + end +end diff --git a/db/migrate/20170703003647_add_index_forumthread_id_on_threadreplies.rb b/db/migrate/20170703003647_add_index_forumthread_id_on_threadreplies.rb new file mode 100644 index 0000000..ca08f5c --- /dev/null +++ b/db/migrate/20170703003647_add_index_forumthread_id_on_threadreplies.rb @@ -0,0 +1,5 @@ +class AddIndexForumthreadIdOnThreadreplies < ActiveRecord::Migration + def change + add_index :threadreplies, :forumthread_id + end +end diff --git a/db/migrate/20170708011014_remove_skype_visibility_from_users.rb b/db/migrate/20170708011014_remove_skype_visibility_from_users.rb new file mode 100644 index 0000000..92a9482 --- /dev/null +++ b/db/migrate/20170708011014_remove_skype_visibility_from_users.rb @@ -0,0 +1,6 @@ +class RemoveSkypeVisibilityFromUsers < ActiveRecord::Migration + def change + remove_column :users, :skype_public + User.update_all skype: nil + end +end diff --git a/db/migrate/20171013001146_add_public_key_to_users.rb b/db/migrate/20171013001146_add_public_key_to_users.rb new file mode 100644 index 0000000..a03743c --- /dev/null +++ b/db/migrate/20171013001146_add_public_key_to_users.rb @@ -0,0 +1,5 @@ +class AddPublicKeyToUsers < ActiveRecord::Migration + def change + add_column :users, :public_key, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index 2c68029..183a432 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,11 +11,18 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160926220738) do +ActiveRecord::Schema.define(version: 20171013001146) do + + create_table "badges", force: :cascade do |t| + t.string "name", limit: 191 + t.string "symbol", limit: 191 + t.string "color", limit: 191 + t.integer "value", limit: 4 + end create_table "blogposts", force: :cascade do |t| - t.string "title" - t.text "content", limit: 65535 + t.string "title", limit: 255 + t.text "content", limit: 16777215 t.integer "user_author_id", limit: 4 t.integer "user_editor_id", limit: 4 t.datetime "created_at" @@ -23,7 +30,7 @@ ActiveRecord::Schema.define(version: 20160926220738) do end create_table "comments", force: :cascade do |t| - t.text "content", limit: 65535 + t.text "content", limit: 16777215 t.integer "user_author_id", limit: 4 t.integer "user_editor_id", limit: 4 t.integer "blogpost_id", limit: 4 @@ -32,18 +39,19 @@ ActiveRecord::Schema.define(version: 20160926220738) do end create_table "forumgroups", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "position", limit: 4 t.integer "role_read_id", limit: 4 t.integer "role_write_id", limit: 4 end create_table "forums", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "position", limit: 4 t.integer "role_read_id", limit: 4 t.integer "role_write_id", limit: 4 t.integer "forumgroup_id", limit: 4 + t.integer "necro_length", limit: 4 end create_table "forums_labels", id: false, force: :cascade do |t| @@ -52,10 +60,10 @@ ActiveRecord::Schema.define(version: 20160926220738) do end create_table "forumthreads", force: :cascade do |t| - t.string "title" - t.text "content", limit: 65535 - t.boolean "sticky", default: false - t.boolean "locked", default: false + t.string "title", limit: 255 + t.text "content", limit: 16777215 + t.boolean "sticky", default: false + t.boolean "locked", default: false t.integer "user_author_id", limit: 4 t.integer "user_editor_id", limit: 4 t.integer "forum_id", limit: 4 @@ -64,44 +72,50 @@ ActiveRecord::Schema.define(version: 20160926220738) do t.integer "label_id", limit: 4 end + add_index "forumthreads", ["content"], name: "index_forumthreads_on_content", type: :fulltext + add_index "forumthreads", ["title", "content"], name: "forumthreads_title_content", type: :fulltext + add_index "forumthreads", ["title", "content"], name: "index_forumthreads_on_title_and_content", type: :fulltext + add_index "forumthreads", ["title"], name: "index_forumthreads_on_title", type: :fulltext + create_table "info", force: :cascade do |t| - t.string "title" - t.text "content", limit: 65535 + t.string "title", limit: 255 + t.text "content", limit: 16777215 t.datetime "created_at" t.datetime "updated_at" end create_table "labels", force: :cascade do |t| - t.string "name" - t.string "color" + t.string "name", limit: 255 + t.string "color", limit: 255 end create_table "register_tokens", force: :cascade do |t| - t.string "uuid", null: false - t.string "token", null: false - t.string "email", null: false + t.string "uuid", limit: 32, null: false + t.string "token", limit: 6, null: false + t.string "email", limit: 191 end + add_index "register_tokens", ["email"], name: "index_register_tokens_on_email", unique: true, using: :btree add_index "register_tokens", ["uuid"], name: "index_register_tokens_on_uuid", unique: true, using: :btree create_table "roles", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "value", limit: 4 - t.string "color" + t.string "color", limit: 255 end create_table "sessions", force: :cascade do |t| - t.string "session_id", null: false - t.text "data", limit: 65535 + t.string "session_id", limit: 255, null: false + t.text "data", limit: 16777215 t.datetime "created_at" t.datetime "updated_at" end - add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree + add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", length: {"session_id"=>191}, using: :btree add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree create_table "threadreplies", force: :cascade do |t| - t.text "content", limit: 65535 + t.text "content", limit: 16777215 t.integer "user_author_id", limit: 4 t.integer "user_editor_id", limit: 4 t.integer "forumthread_id", limit: 4 @@ -109,21 +123,22 @@ ActiveRecord::Schema.define(version: 20160926220738) do t.datetime "updated_at" end + add_index "threadreplies", ["content"], name: "index_threadreplies_on_content", type: :fulltext + add_index "threadreplies", ["forumthread_id"], name: "index_threadreplies_on_forumthread_id", using: :btree + create_table "users", force: :cascade do |t| - t.string "uuid", null: false - t.string "name", null: false - t.string "password_digest", null: false - t.string "ign", null: false - t.string "email", null: false + t.string "uuid", limit: 255, null: false + t.string "name", limit: 191 + t.string "password_digest", limit: 255, null: false + t.string "ign", limit: 255, null: false + t.string "email", limit: 191 t.text "about", limit: 65535 - t.string "last_ip" - t.string "skype" - t.boolean "skype_public", default: false - t.string "youtube" - t.string "youtube_channelname" - t.string "twitter" - t.boolean "donor", default: false - t.string "email_token" + t.string "last_ip", limit: 255 + t.string "skype", limit: 255 + t.string "youtube", limit: 255 + t.string "youtube_channelname", limit: 255 + t.string "twitter", limit: 255 + t.string "email_token", limit: 255 t.boolean "confirmed", default: false t.datetime "last_seen" t.integer "role_id", limit: 4, null: false @@ -134,6 +149,11 @@ ActiveRecord::Schema.define(version: 20160926220738) do t.boolean "mail_own_blogpost_comment", default: true t.boolean "mail_other_blogpost_comment", default: true t.boolean "mail_mention", default: true + t.integer "badge_id", limit: 4, default: 0 + t.boolean "utc_time", default: false + t.boolean "header_scroll", default: false + t.boolean "dark", default: false + t.text "public_key", limit: 65535 end add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree diff --git a/db/seeds.rb b/db/seeds.rb index 780ddb5..f6b731f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,6 +10,14 @@ Role.create!([ {name: "superadmin", value: 500, color: "#d22"} ]) +Badge.create!([ + {name: "none", symbol: "", color: "#000"}, + {name: "donor", symbol: "$", color: "#f60"}, + {name: "developer", symbol: "D", color: "#a0a"}, + {name: "retired", symbol: "R", color: "#0aa"}, + {name: "lead", symbol: "L", color: "#a00"} +]) + userpw = SecureRandom.hex(36) @@ -23,19 +31,13 @@ deleted_user = User.create!( password: userpw, password_confirmation: userpw, role: Role.get(:disabled), + badge: Badge.get(:none), skype: "echo123", - skype_public: true, last_ip: "0.0.0.0", confirmed: true, - last_seen: Time.utc(0).to_datetime + last_seen: Time.utc(0).to_datetime, + header_scroll: false, + utc_time: false, + dark: false ) deleted_user.update_attribute(:ign, "Steve") - -User.create!( - uuid: "ae795aa86327408e92ab25c8a59f3ba1", - ign: "jomo", - email: "jomo@example.com", - password: "123456789", # high seructity! - password_confirmation: "123456789", - role: Role.get(:superadmin) -)
\ No newline at end of file diff --git a/lib/tasks/create_admin_user.rake b/lib/tasks/create_admin_user.rake new file mode 100644 index 0000000..22dceb3 --- /dev/null +++ b/lib/tasks/create_admin_user.rake @@ -0,0 +1,18 @@ +desc "Creates a superadmin user. Usage: rake create:create_admin_user[uuid, ign, email, pass]" +namespace :create do + task :create_admin_user, [:uuid, :ign, :email, :pass] => :environment do |task, args| + User.create!( + uuid: args.uuid, + ign: args.ign, + email: args.email, + password: args.pass, + password_confirmation: args.pass, + role: Role.get(:superadmin), + header_scroll: false, + utc_time: false, + dark: false, + badge: Badge.get(:none), + confirmed: true + ) + end +end |