FEATURE: initial implemenation of anonymous posting mode
This commit is contained in:
parent
cd5af46fb7
commit
f5d89169e2
|
@ -1,10 +1,24 @@
|
||||||
export default Ember.ArrayController.extend({
|
export default Ember.ArrayController.extend({
|
||||||
showAdminLinks: Em.computed.alias("currentUser.staff"),
|
showAdminLinks: Em.computed.alias("currentUser.staff"),
|
||||||
|
|
||||||
|
allowAnon: function(){
|
||||||
|
return Discourse.SiteSettings.allow_anonymous_posting &&
|
||||||
|
Discourse.User.currentProp("trust_level") >= Discourse.SiteSettings.anonymous_posting_min_trust_level;
|
||||||
|
}.property(),
|
||||||
|
|
||||||
|
isAnon: function(){
|
||||||
|
return Discourse.User.currentProp("is_anonymous");
|
||||||
|
}.property(),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
logout() {
|
logout() {
|
||||||
Discourse.logout();
|
Discourse.logout();
|
||||||
return false;
|
return false;
|
||||||
|
},
|
||||||
|
toggleAnon() {
|
||||||
|
Discourse.ajax("/users/toggle-anon", {method: 'POST'}).then(function(){
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
</li>
|
</li>
|
||||||
<li>{{#link-to 'userActivity.bookmarks' currentUser}}{{i18n 'user.bookmarks'}}{{/link-to}}</li>
|
<li>{{#link-to 'userActivity.bookmarks' currentUser}}{{i18n 'user.bookmarks'}}{{/link-to}}</li>
|
||||||
<li>{{#link-to 'preferences' currentUser}}{{i18n 'user.preferences'}}{{/link-to}}</li>
|
<li>{{#link-to 'preferences' currentUser}}{{i18n 'user.preferences'}}{{/link-to}}</li>
|
||||||
|
{{#if allowAnon}}
|
||||||
|
<li><a href {{action toggleAnon}}>{{#if isAnon}}{{i18n 'switch_from_anon'}}{{else}}{{i18n 'switch_to_anon'}}{{/if}}</a></li>
|
||||||
|
{{/if}}
|
||||||
<li>{{d-button action="logout" class="btn-danger right logout" icon="sign-out" label="user.log_out"}}</li>
|
<li>{{d-button action="logout" class="btn-danger right logout" icon="sign-out" label="user.log_out"}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -6,7 +6,7 @@ require_dependency 'rate_limiter'
|
||||||
class UsersController < ApplicationController
|
class UsersController < ApplicationController
|
||||||
|
|
||||||
skip_before_filter :authorize_mini_profiler, only: [:avatar]
|
skip_before_filter :authorize_mini_profiler, only: [:avatar]
|
||||||
skip_before_filter :check_xhr, only: [:show, :password_reset, :update, :account_created, :activate_account, :perform_account_activation, :authorize_email, :user_preferences_redirect, :avatar, :my_redirect]
|
skip_before_filter :check_xhr, only: [:show, :password_reset, :update, :account_created, :activate_account, :perform_account_activation, :authorize_email, :user_preferences_redirect, :avatar, :my_redirect, :toggle_anon]
|
||||||
|
|
||||||
before_filter :ensure_logged_in, only: [:username, :update, :change_email, :user_preferences_redirect, :upload_user_image, :pick_avatar, :destroy_user_image, :destroy, :check_emails]
|
before_filter :ensure_logged_in, only: [:username, :update, :change_email, :user_preferences_redirect, :upload_user_image, :pick_avatar, :destroy_user_image, :destroy, :check_emails]
|
||||||
before_filter :respond_to_suspicious_request, only: [:create]
|
before_filter :respond_to_suspicious_request, only: [:create]
|
||||||
|
@ -343,6 +343,18 @@ class UsersController < ApplicationController
|
||||||
@success = I18n.t(message)
|
@success = I18n.t(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def toggle_anon
|
||||||
|
user = AnonymousShadowCreator.get_master(current_user) ||
|
||||||
|
AnonymousShadowCreator.get(current_user)
|
||||||
|
|
||||||
|
if user
|
||||||
|
log_on_user(user)
|
||||||
|
render json: success_json
|
||||||
|
else
|
||||||
|
render json: failed_json, status: 403
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def change_email
|
def change_email
|
||||||
params.require(:email)
|
params.require(:email)
|
||||||
user = fetch_user_from_params
|
user = fetch_user_from_params
|
||||||
|
|
|
@ -25,7 +25,8 @@ class CurrentUserSerializer < BasicUserSerializer
|
||||||
:disable_jump_reply,
|
:disable_jump_reply,
|
||||||
:custom_fields,
|
:custom_fields,
|
||||||
:muted_category_ids,
|
:muted_category_ids,
|
||||||
:dismissed_banner_key
|
:dismissed_banner_key,
|
||||||
|
:is_anonymous
|
||||||
|
|
||||||
def include_site_flagged_posts_count?
|
def include_site_flagged_posts_count?
|
||||||
object.staff?
|
object.staff?
|
||||||
|
@ -102,4 +103,10 @@ class CurrentUserSerializer < BasicUserSerializer
|
||||||
object.user_profile.dismissed_banner_key
|
object.user_profile.dismissed_banner_key
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_anonymous
|
||||||
|
SiteSetting.allow_anonymous_posting &&
|
||||||
|
object.trust_level >= 1 &&
|
||||||
|
object.custom_fields["master_id"].to_i > 0
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
class AnonymousShadowCreator
|
||||||
|
|
||||||
|
def self.get_master(user)
|
||||||
|
return unless user
|
||||||
|
return if !SiteSetting.allow_anonymous_posting
|
||||||
|
|
||||||
|
if (master_id = user.custom_fields["master_id"].to_i) > 0
|
||||||
|
User.find_by(id: master_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get(user)
|
||||||
|
return unless user
|
||||||
|
return if !SiteSetting.allow_anonymous_posting ||
|
||||||
|
user.trust_level < SiteSetting.anonymous_posting_min_trust_level
|
||||||
|
|
||||||
|
if (shadow_id = user.custom_fields["shadow_id"].to_i) > 0
|
||||||
|
User.find_by(id: shadow_id) || create_shadow(user)
|
||||||
|
else
|
||||||
|
create_shadow(user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_shadow(user)
|
||||||
|
User.transaction do
|
||||||
|
shadow = User.create!(
|
||||||
|
password: SecureRandom.hex,
|
||||||
|
email: "#{SecureRandom.hex}@#{SecureRandom.hex}.com",
|
||||||
|
name: "",
|
||||||
|
username: UserNameSuggester.suggest(I18n.t(:anonymous).downcase),
|
||||||
|
active: true,
|
||||||
|
trust_level: 1,
|
||||||
|
trust_level_locked: true,
|
||||||
|
email_private_messages: false,
|
||||||
|
email_digests: false,
|
||||||
|
created_at: user.created_at
|
||||||
|
)
|
||||||
|
|
||||||
|
shadow.email_tokens.update_all confirmed: true
|
||||||
|
shadow.activate
|
||||||
|
|
||||||
|
|
||||||
|
UserCustomField.create!(user_id: user.id,
|
||||||
|
name: "shadow_id",
|
||||||
|
value: shadow.id)
|
||||||
|
|
||||||
|
UserCustomField.create!(user_id: shadow.id,
|
||||||
|
name: "master_id",
|
||||||
|
value: user.id)
|
||||||
|
|
||||||
|
shadow.reload
|
||||||
|
user.reload
|
||||||
|
|
||||||
|
shadow
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -213,6 +213,9 @@ en:
|
||||||
revert: "Revert"
|
revert: "Revert"
|
||||||
failed: "Failed"
|
failed: "Failed"
|
||||||
|
|
||||||
|
switch_to_anon: "Anonymous Mode"
|
||||||
|
switch_from_anon: "Exit Anonymous Mode"
|
||||||
|
|
||||||
banner:
|
banner:
|
||||||
close: "Dismiss this banner."
|
close: "Dismiss this banner."
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ en:
|
||||||
|
|
||||||
purge_reason: "Automatically deleted as abandoned, unactivated account"
|
purge_reason: "Automatically deleted as abandoned, unactivated account"
|
||||||
disable_remote_images_download_reason: "Remote images download was disabled because there wasn't enough disk space available."
|
disable_remote_images_download_reason: "Remote images download was disabled because there wasn't enough disk space available."
|
||||||
|
anonymous: "Anonymous"
|
||||||
|
|
||||||
errors: &errors
|
errors: &errors
|
||||||
format: ! '%{attribute} %{message}'
|
format: ! '%{attribute} %{message}'
|
||||||
|
@ -1088,6 +1089,8 @@ en:
|
||||||
public_user_custom_fields: "A whitelist of custom fields for a user that can be shown publicly."
|
public_user_custom_fields: "A whitelist of custom fields for a user that can be shown publicly."
|
||||||
staff_user_custom_fields: "A whitelist of custom fields for a user that can be shown to staff."
|
staff_user_custom_fields: "A whitelist of custom fields for a user that can be shown to staff."
|
||||||
enable_user_directory: "Provide a directory of users for browsing"
|
enable_user_directory: "Provide a directory of users for browsing"
|
||||||
|
allow_anonymous_posting: "Allow users to switch to anonymous mode"
|
||||||
|
anonymous_posting_min_trust_level: "Minimum trust level required to enable anonymous posting"
|
||||||
|
|
||||||
allow_profile_backgrounds: "Allow users to upload profile backgrounds."
|
allow_profile_backgrounds: "Allow users to upload profile backgrounds."
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,7 @@ Discourse::Application.routes.draw do
|
||||||
get "privacy" => "static#show", id: "privacy", as: 'privacy'
|
get "privacy" => "static#show", id: "privacy", as: 'privacy'
|
||||||
get "signup" => "list#latest"
|
get "signup" => "list#latest"
|
||||||
|
|
||||||
|
post "users/toggle-anon" => "users#toggle_anon"
|
||||||
post "users/read-faq" => "users#read_faq"
|
post "users/read-faq" => "users#read_faq"
|
||||||
get "users/search/users" => "users#search_users"
|
get "users/search/users" => "users#search_users"
|
||||||
get "users/account-created/" => "users#account_created"
|
get "users/account-created/" => "users#account_created"
|
||||||
|
|
|
@ -309,6 +309,12 @@ users:
|
||||||
enable_user_directory:
|
enable_user_directory:
|
||||||
client: true
|
client: true
|
||||||
default: true
|
default: true
|
||||||
|
allow_anonymous_posting:
|
||||||
|
default: false
|
||||||
|
client: true
|
||||||
|
anonymous_posting_min_trust_level:
|
||||||
|
default: 1
|
||||||
|
client: true
|
||||||
|
|
||||||
posting:
|
posting:
|
||||||
min_post_length:
|
min_post_length:
|
||||||
|
|
|
@ -309,6 +309,25 @@ describe UsersController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#toggle_anon' do
|
||||||
|
it 'allows you to toggle anon if enabled' do
|
||||||
|
SiteSetting.allow_anonymous_posting = true
|
||||||
|
|
||||||
|
user = log_in
|
||||||
|
user.trust_level = 1
|
||||||
|
user.save
|
||||||
|
|
||||||
|
post :toggle_anon
|
||||||
|
expect(response).to be_success
|
||||||
|
expect(session[:current_user_id]).to eq(AnonymousShadowCreator.get(user).id)
|
||||||
|
|
||||||
|
post :toggle_anon
|
||||||
|
expect(response).to be_success
|
||||||
|
expect(session[:current_user_id]).to eq(user.id)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#create' do
|
describe '#create' do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe AnonymousShadowCreator do
|
||||||
|
|
||||||
|
it "returns no shadow by default" do
|
||||||
|
AnonymousShadowCreator.get(Fabricate.build(:user)).should == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns no shadow if trust level is not met" do
|
||||||
|
SiteSetting.allow_anonymous_posting = true
|
||||||
|
AnonymousShadowCreator.get(Fabricate.build(:user, trust_level: 0)).should == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns a shadow for a legit user" do
|
||||||
|
SiteSetting.allow_anonymous_posting = true
|
||||||
|
user = Fabricate(:user, trust_level: 3)
|
||||||
|
|
||||||
|
shadow = AnonymousShadowCreator.get(user)
|
||||||
|
shadow2 = AnonymousShadowCreator.get(user)
|
||||||
|
|
||||||
|
shadow.id.should == shadow2.id
|
||||||
|
|
||||||
|
shadow.trust_level.should == 1
|
||||||
|
|
||||||
|
shadow.username.should == "anonymous"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue