Merge branch 'main' into feature/privacy-require-user
This commit is contained in:
commit
3cefc829f8
|
@ -0,0 +1,35 @@
|
|||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/docker-existing-docker-compose
|
||||
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
|
||||
{
|
||||
"name": "Retrospring",
|
||||
|
||||
// Update the 'dockerComposeFile' list if you have more compose files or use different names.
|
||||
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
|
||||
"dockerComposeFile": [
|
||||
"../docker-compose.yml"
|
||||
],
|
||||
|
||||
// The 'service' property is the name of the service for the container that VS Code should
|
||||
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
|
||||
"service": "web",
|
||||
|
||||
// The optional 'workspaceFolder' property is the path VS Code should open by default when
|
||||
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
|
||||
"workspaceFolder": "/app",
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Uncomment the next line if you want start specific services in your Docker Compose config.
|
||||
// "runServices": [],
|
||||
|
||||
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
|
||||
// "shutdownAction": "none",
|
||||
|
||||
// Uncomment the next line to run commands after the container is created - for example installing curl.
|
||||
// "postCreateCommand": "apt-get update && apt-get install -y curl",
|
||||
|
||||
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "app"
|
||||
}
|
|
@ -8,7 +8,7 @@ ARG GID=1000
|
|||
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||
|
||||
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
|
||||
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
|
||||
|
||||
RUN apt-get update -qq \
|
||||
&& apt-get install -y --no-install-recommends build-essential \
|
||||
|
@ -47,4 +47,4 @@ COPY . /app
|
|||
ENTRYPOINT ["entrypoint.sh"]
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["rails", "server", "-b", "0.0.0.0"]
|
||||
CMD ["rails", "server", "-b", "0.0.0.0"]
|
||||
|
|
|
@ -48,10 +48,10 @@ jobs:
|
|||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
bundler-cache: true
|
||||
- name: Set up Node 12
|
||||
- name: Set up Node 14
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '12'
|
||||
node-version: '14'
|
||||
- name: Copy default configuration
|
||||
run: |
|
||||
cp config/database.yml.postgres config/database.yml
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -80,13 +80,11 @@ gem "puma"
|
|||
group :development, :test do
|
||||
gem "better_errors"
|
||||
gem "bullet"
|
||||
gem "capybara"
|
||||
gem "database_cleaner"
|
||||
gem "factory_bot_rails", require: false
|
||||
gem "faker"
|
||||
gem "haml_lint", require: false
|
||||
gem "letter_opener" # Use this just in local test environments
|
||||
gem "poltergeist"
|
||||
gem "rails-controller-testing"
|
||||
gem "rake"
|
||||
gem "rspec-its", "~> 1.3"
|
||||
|
|
19
Gemfile.lock
19
Gemfile.lock
|
@ -95,15 +95,6 @@ GEM
|
|||
bullet (7.0.3)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
capybara (3.37.1)
|
||||
addressable
|
||||
matrix
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (~> 1.8)
|
||||
rack (>= 1.6.0)
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
carrierwave (2.1.0)
|
||||
activemodel (>= 5.0.0)
|
||||
activesupport (>= 5.0.0)
|
||||
|
@ -112,7 +103,6 @@ GEM
|
|||
mimemagic (>= 0.3.0)
|
||||
mini_mime (>= 0.1.3)
|
||||
chunky_png (1.4.0)
|
||||
cliver (0.3.2)
|
||||
coderay (1.1.3)
|
||||
colorize (0.8.1)
|
||||
concurrent-ruby (1.1.10)
|
||||
|
@ -261,7 +251,6 @@ GEM
|
|||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
marcel (1.0.2)
|
||||
matrix (0.4.2)
|
||||
memoizable (0.4.2)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
method_source (1.0.0)
|
||||
|
@ -315,10 +304,6 @@ GEM
|
|||
pg (1.4.4)
|
||||
pghero (3.0.1)
|
||||
activerecord (>= 6)
|
||||
poltergeist (1.18.1)
|
||||
capybara (>= 2.1, < 4)
|
||||
cliver (~> 0.3.1)
|
||||
websocket-driver (>= 0.2.0)
|
||||
public_suffix (4.0.7)
|
||||
puma (6.0.0)
|
||||
nio4r (~> 2.0)
|
||||
|
@ -521,8 +506,6 @@ GEM
|
|||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.5)
|
||||
|
||||
PLATFORMS
|
||||
|
@ -536,7 +519,6 @@ DEPENDENCIES
|
|||
bootsnap
|
||||
bootstrap_form (~> 4.5)
|
||||
bullet
|
||||
capybara
|
||||
carrierwave (~> 2.0)
|
||||
carrierwave_backgrounder!
|
||||
colorize
|
||||
|
@ -571,7 +553,6 @@ DEPENDENCIES
|
|||
omniauth-twitter
|
||||
pg
|
||||
pghero
|
||||
poltergeist
|
||||
puma
|
||||
questiongenerator (~> 1.0)
|
||||
rails (~> 6.1)
|
||||
|
|
|
@ -6,7 +6,8 @@ class Settings::PrivacyController < ApplicationController
|
|||
def edit; end
|
||||
|
||||
def update
|
||||
user_attributes = params.require(:user).permit(:privacy_allow_anonymous_questions,
|
||||
user_attributes = params.require(:user).permit(:privacy_lock_inbox,
|
||||
:privacy_allow_anonymous_questions,
|
||||
:privacy_allow_public_timeline,
|
||||
:privacy_allow_stranger_answers,
|
||||
:privacy_show_in_search,
|
||||
|
|
|
@ -169,6 +169,10 @@ class User < ApplicationRecord
|
|||
!self.export_processing
|
||||
end
|
||||
|
||||
def inbox_locked?
|
||||
privacy_lock_inbox
|
||||
end
|
||||
|
||||
# %w[admin moderator].each do |m|
|
||||
# define_method(m) { raise "not allowed: #{m}" }
|
||||
# define_method(m+??) { raise "not allowed: #{m}?"}
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
- elsif user_signed_in? && user.blocking?(current_user)
|
||||
.text-center
|
||||
%strong= t(".status.blocked")
|
||||
- elsif user.inbox_locked?
|
||||
.text-center
|
||||
%strong= t(".status.locked")
|
||||
- elsif !user_signed_in? && user.privacy_require_user?
|
||||
.text-center
|
||||
%strong= t(".status.require_user_html", sign_in: link_to(t("voc.login"), new_user_session_path), sign_up: link_to(t("voc.register"), new_user_registration_path))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.card
|
||||
.card-body
|
||||
= bootstrap_form_for(current_user, url: settings_privacy_path, method: :patch, data: { turbo: false }) do |f|
|
||||
= f.check_box :privacy_lock_inbox
|
||||
= f.check_box :privacy_allow_anonymous_questions
|
||||
= f.check_box :privacy_require_user
|
||||
= f.check_box :privacy_allow_public_timeline
|
||||
|
|
|
@ -12,6 +12,7 @@ class QuestionWorker
|
|||
question = Question.find(question_id)
|
||||
|
||||
user.followers.each do |f|
|
||||
next if f.inbox_locked?
|
||||
next if f.banned?
|
||||
next if MuteRule.where(user: f).any? { |rule| rule.applies_to? question }
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ en:
|
|||
remember_created_at: "Remember me set at"
|
||||
password: "Password"
|
||||
password_confirmation: "Confirm your password"
|
||||
privacy_lock_inbox: "Lock inbox and don't allow new questions"
|
||||
privacy_allow_anonymous_questions: "Allow anonymous questions"
|
||||
privacy_require_user: "Require users to be logged in to ask you questions"
|
||||
privacy_allow_public_timeline: "Show your answers in the public timeline"
|
||||
|
|
|
@ -6,6 +6,7 @@ en:
|
|||
param_is_missing: "param is missing"
|
||||
|
||||
forbidden: "This is illegal, you know"
|
||||
inbox_locked: "This user currently does not accept questions"
|
||||
blocked: "You have been blocked from performing this request"
|
||||
other_blocked_self: "You have been blocked by this user"
|
||||
asking_other_blocked_self: "You have been blocked from asking this user questions"
|
||||
|
|
|
@ -122,6 +122,7 @@ en:
|
|||
banned: "This user got hit with ye olde banhammer."
|
||||
blocking: "You are blocking this user."
|
||||
blocked: "This user has blocked you."
|
||||
locked: "This user currently does not accept questions."
|
||||
require_user_html: |
|
||||
This user requires others to be logged in to ask questions. <br/>
|
||||
(%{sign_in} or %{sign_up})
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddInboxLockedToUsers < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
add_column :users, :privacy_lock_inbox, :boolean, default: false
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :users, :privacy_lock_inbox
|
||||
end
|
||||
end
|
16
db/schema.rb
16
db/schema.rb
|
@ -31,8 +31,8 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.string "identifier"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.bigint "question_id"
|
||||
t.bigint "user_id"
|
||||
t.bigint "question_id"
|
||||
t.index ["identifier"], name: "index_anonymous_blocks_on_identifier"
|
||||
t.index ["question_id"], name: "index_anonymous_blocks_on_question_id"
|
||||
t.index ["user_id"], name: "index_anonymous_blocks_on_user_id"
|
||||
|
@ -46,8 +46,6 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "smile_count", default: 0, null: false
|
||||
t.datetime "deleted_at"
|
||||
t.index ["deleted_at"], name: "index_answers_on_deleted_at"
|
||||
t.index ["question_id"], name: "index_answers_on_question_id"
|
||||
t.index ["user_id", "created_at"], name: "index_answers_on_user_id_and_created_at"
|
||||
end
|
||||
|
@ -60,8 +58,6 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.text "content"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "deleted_at"
|
||||
t.index ["deleted_at"], name: "index_appendables_on_deleted_at"
|
||||
t.index ["parent_id", "parent_type"], name: "index_appendables_on_parent_id_and_parent_type"
|
||||
t.index ["user_id", "created_at"], name: "index_appendables_on_user_id_and_created_at"
|
||||
end
|
||||
|
@ -73,9 +69,7 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "smile_count", default: 0, null: false
|
||||
t.datetime "deleted_at"
|
||||
t.index ["answer_id"], name: "index_comments_on_answer_id"
|
||||
t.index ["deleted_at"], name: "index_comments_on_deleted_at"
|
||||
t.index ["user_id", "created_at"], name: "index_comments_on_user_id_and_created_at"
|
||||
end
|
||||
|
||||
|
@ -108,10 +102,10 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
end
|
||||
|
||||
create_table "mute_rules", id: :bigint, default: -> { "gen_timestamp_id('mute_rules'::text)" }, force: :cascade do |t|
|
||||
t.bigint "user_id"
|
||||
t.string "muted_phrase"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.bigint "user_id"
|
||||
t.index ["user_id"], name: "index_mute_rules_on_user_id"
|
||||
end
|
||||
|
||||
|
@ -150,8 +144,6 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.datetime "updated_at"
|
||||
t.integer "answer_count", default: 0, null: false
|
||||
t.boolean "direct", default: false, null: false
|
||||
t.datetime "deleted_at"
|
||||
t.index ["deleted_at"], name: "index_questions_on_deleted_at"
|
||||
t.index ["user_id", "created_at"], name: "index_questions_on_user_id_and_created_at"
|
||||
end
|
||||
|
||||
|
@ -302,8 +294,8 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.integer "otp_module", default: 0, null: false
|
||||
t.datetime "deleted_at"
|
||||
t.boolean "privacy_require_user", default: false
|
||||
t.boolean "privacy_lock_inbox", default: false
|
||||
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
||||
t.index ["deleted_at"], name: "index_users_on_deleted_at"
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||
t.index ["screen_name"], name: "index_users_on_screen_name", unique: true
|
||||
|
@ -317,5 +309,7 @@ ActiveRecord::Schema.define(version: 2022_11_13_110942) do
|
|||
t.index ["user_id"], name: "index_users_roles_on_user_id"
|
||||
end
|
||||
|
||||
add_foreign_key "anonymous_blocks", "questions"
|
||||
add_foreign_key "anonymous_blocks", "users"
|
||||
add_foreign_key "profiles", "users"
|
||||
end
|
||||
|
|
|
@ -35,6 +35,9 @@ module Errors
|
|||
class SelfAction < Forbidden
|
||||
end
|
||||
|
||||
class InboxLocked < Forbidden
|
||||
end
|
||||
|
||||
class FollowingSelf < SelfAction
|
||||
end
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ module UseCase
|
|||
|
||||
def call
|
||||
check_user
|
||||
check_lock
|
||||
check_anonymous_rules
|
||||
check_blocks
|
||||
|
||||
|
@ -43,6 +44,10 @@ module UseCase
|
|||
|
||||
private
|
||||
|
||||
def check_lock
|
||||
raise Errors::InboxLocked if target_user.inbox_locked?
|
||||
end
|
||||
|
||||
def check_anonymous_rules
|
||||
if !source_user_id && !anonymous
|
||||
# We can not create a non-anonymous question without a source user
|
||||
|
|
|
@ -328,6 +328,23 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do
|
|||
include_examples "does not create the question"
|
||||
end
|
||||
end
|
||||
|
||||
context "when users inbox is locked" do
|
||||
let(:user_allows_anonymous_questions) { true }
|
||||
let(:expected_response) do
|
||||
{
|
||||
"success" => false,
|
||||
"status" => "inbox_locked",
|
||||
"message" => anything
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
target_user.update(privacy_lock_inbox: true)
|
||||
end
|
||||
|
||||
include_examples "does not create the question"
|
||||
end
|
||||
end
|
||||
|
||||
context "when rcpt is followers" do
|
||||
|
|
|
@ -10,8 +10,6 @@ require "rspec/rails"
|
|||
# Add additional requires below this line. Rails is not loaded until this point!
|
||||
require "rspec/its"
|
||||
require "devise"
|
||||
require "capybara/rails"
|
||||
require "capybara/rspec"
|
||||
require "rspec-sidekiq"
|
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc, in
|
||||
|
|
|
@ -6,7 +6,7 @@ describe QuestionWorker do
|
|||
describe "#perform" do
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
let(:user_id) { user.id }
|
||||
let(:question) { FactoryBot.create(:question, user: user) }
|
||||
let(:question) { FactoryBot.create(:question, user:) }
|
||||
let(:question_id) { question.id }
|
||||
|
||||
before do
|
||||
|
@ -41,6 +41,18 @@ describe QuestionWorker do
|
|||
)
|
||||
end
|
||||
|
||||
it "respects inbox locks" do
|
||||
user.followers.first.update(privacy_lock_inbox: true)
|
||||
|
||||
|
||||
expect { subject }
|
||||
.to(
|
||||
change { Inbox.where(user_id: user.followers.ids, question_id:, new: true).count }
|
||||
.from(0)
|
||||
.to(4)
|
||||
)
|
||||
end
|
||||
|
||||
it "does not send questions to banned users" do
|
||||
user.followers.first.ban
|
||||
|
||||
|
|
Loading…
Reference in New Issue