diff --git a/app/controllers/settings/users_controller.rb b/app/controllers/settings/users_controller.rb new file mode 100644 index 000000000..e93f54f88 --- /dev/null +++ b/app/controllers/settings/users_controller.rb @@ -0,0 +1,23 @@ +class Settings::UsersController < ApplicationController + before_action :get_user, except: [:index] + + def index + @users = policy_scope(Federails::Actor).where(entity_type: "User") + render layout: "settings" + end + + def show + render layout: "settings" + end + + private + + def get_user + @user = policy_scope(User).find_param(params[:id]) + authorize @user + end + + def user_params + params.require(:user).permit + end +end diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index ffbedbaf4..f21985b15 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -1,2 +1,5 @@ module SettingsHelper + def masked_email(email) + email.gsub(/(?<=^.)[^@]*|(?<=@.).*(?=\.[^.]+$)/, "****") + end end diff --git a/app/policies/federails/actor_policy.rb b/app/policies/federails/actor_policy.rb new file mode 100644 index 000000000..ded3777b1 --- /dev/null +++ b/app/policies/federails/actor_policy.rb @@ -0,0 +1,27 @@ +class Federails::ActorPolicy < ApplicationPolicy + def index? + all_of( + SiteSettings.multiuser_enabled?, + @user.is_moderator? + ) + end + + def show? + index? + end + + def edit? + index? + end + + def update? + index? + end + + def destroy? + index? + end + + class Scope < ApplicationPolicy::Scope + end +end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index b7198b237..e074ff7c4 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -1,7 +1,7 @@ class UserPolicy < ApplicationPolicy def index? all_of( - user&.is_administrator?, + user&.is_moderator?, none_of( SiteSettings.demo_mode_enabled? ) @@ -12,7 +12,7 @@ def show? all_of( one_of( user == record, - user&.is_administrator? + user&.is_moderator? ) ) end @@ -22,7 +22,7 @@ def create? SiteSettings.multiuser_enabled?, one_of( SiteSettings.registration_enabled?, - user&.is_administrator? + user&.is_moderator? ), none_of( SiteSettings.demo_mode_enabled? @@ -41,7 +41,7 @@ def destroy? all_of( one_of( user == record, - user&.is_administrator? + user&.is_moderator? ), SiteSettings.multiuser_enabled?, none_of( diff --git a/app/views/layouts/settings.html.erb b/app/views/layouts/settings.html.erb index 3bcde304b..c6a441770 100644 --- a/app/views/layouts/settings.html.erb +++ b/app/views/layouts/settings.html.erb @@ -9,13 +9,16 @@ <%= link_to t(".libraries"), settings_libraries_path, class: "nav-link" %> + <% unless SiteSettings.demo_mode_enabled? %> diff --git a/app/views/settings/users/index.html.erb b/app/views/settings/users/index.html.erb new file mode 100644 index 000000000..1c87d2a98 --- /dev/null +++ b/app/views/settings/users/index.html.erb @@ -0,0 +1,26 @@ +

<%= t(".title") %>

+ +

<%= t(".description") %>

+ + + + + + <%= content_tag :th, User.human_attribute_name(:auth_uid) if SiteSettings.oidc_enabled? %> + <%= content_tag :th, t(".local") if SiteSettings.federation_enabled? %> + <%= content_tag :th, t(".fediverse_address") if SiteSettings.federation_enabled? %> + + + + <% @users.each do |user| %> + + + + <%= content_tag :td, (user.entity.auth_uid ? "✅" : "❌") if SiteSettings.oidc_enabled? %> + <%= content_tag :td, (user.local? ? "✅" : "❌") if SiteSettings.federation_enabled? %> + <%= content_tag :td, user.at_address if SiteSettings.federation_enabled? %> + + + + <% end %> +
<%= User.human_attribute_name(:username) %><%= User.human_attribute_name(:email) %><%= User.human_attribute_name(:roles) %>
<%= user.entity.is_a?(User) ? user.entity.username : user.username %><%= user.entity.is_a?(User) ? masked_email(user.entity.email) : nil %><%= user.entity.roles.map(&:name).join(", ") if user.entity.is_a?(User) %><%= link_to safe_join([icon("search", t(".view")), t(".view")], " "), settings_user_path(user.entity), class: "btn btn-primary" %>
diff --git a/app/views/settings/users/show.html.erb b/app/views/settings/users/show.html.erb new file mode 100644 index 000000000..6db08a9bb --- /dev/null +++ b/app/views/settings/users/show.html.erb @@ -0,0 +1,44 @@ +

<%= t(".title", username: @user.username) %>

+ + + + + + + + + + + + + + + + + + + + + + <% if SiteSettings.oidc_enabled? %> + + + + + <% end %> + <% if SiteSettings.federation_enabled? %> + + + + + <% else %> + + + + + <% end %> + + + + +
<%= User.human_attribute_name(:username) %><%= @user.username %>
<%= User.human_attribute_name(:email) %><%= @user.email %>
<%= User.human_attribute_name(:created_at) %><%= @user.created_at.to_fs(:long) %>
<%= User.human_attribute_name(:updated_at) %><%= @user.updated_at.to_fs(:long) %>
<%= User.human_attribute_name(:interface_language) %><%= @user.interface_language.present? ? I18nData.languages(@user.interface_language)[@user.interface_language.to_s]&.capitalize : t("devise.registrations.general_settings.interface_language.autodetect") %>
<%= User.human_attribute_name(:auth_uid) %><%= (user.auth_uid ? "✅" : "❌") %>
<%= t("settings.users.index.fediverse_address") %><%= @user.actor.at_address %>
<%= User.human_attribute_name(:public_id) %><%= @user.public_id %>
<%= User.human_attribute_name(:roles) %><%= @user.roles.map(&:name).join(", ") %>
diff --git a/config/locales/settings/en.yml b/config/locales/settings/en.yml index 5bf20f4a1..d4948fabc 100644 --- a/config/locales/settings/en.yml +++ b/config/locales/settings/en.yml @@ -68,3 +68,12 @@ en: label: Create tags from model directory name update: success: Settings saved. + users: + index: + description: View and edit registered user accounts. + fediverse_address: Fediverse address + local: Local + title: Manage Users + view: View + show: + title: 'User details: %{username}' diff --git a/config/routes.rb b/config/routes.rb index fce930f9e..87a2d090d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -31,7 +31,20 @@ get "/activity" => "activity#index", :as => :activity end - mount Federails::Engine => "/" if SiteSettings.multiuser_enabled? || SiteSettings.federation_enabled? || Rails.env.test? + if SiteSettings.multiuser_enabled? || Rails.env.test? + authenticate :user, lambda { |u| u.is_moderator? } do + namespace :settings do + resources :users + end + end + mount Federails::Engine => "/" if SiteSettings.federation_enabled? || Rails.env.test? + + get "/follow" => "follows#index", :as => :follow + get "/authorize_interaction" => "follows#new", :as => :new_follow + post "/remote_follow" => "follows#remote_follow", :as => :remote_follow + post "/perform_remote_follow" => "follows#perform_remote_follow", :as => :perform_remote_follow + post "/follow_remote_actor/:id" => "follows#follow_remote_actor", :as => :follow_remote_actor + end root to: "home#index" @@ -44,12 +57,6 @@ end end - get "/follow" => "follows#index", :as => :follow - get "/authorize_interaction" => "follows#new", :as => :new_follow - post "/remote_follow" => "follows#remote_follow", :as => :remote_follow - post "/perform_remote_follow" => "follows#perform_remote_follow", :as => :perform_remote_follow - post "/follow_remote_actor/:id" => "follows#follow_remote_actor", :as => :follow_remote_actor - concern :followable do |options| if SiteSettings.multiuser_enabled? resources :follows, {only: [:create]}.merge(options) do diff --git a/spec/requests/settings/users_spec.rb b/spec/requests/settings/users_spec.rb new file mode 100644 index 000000000..9d607919c --- /dev/null +++ b/spec/requests/settings/users_spec.rb @@ -0,0 +1,19 @@ +require "rails_helper" + +RSpec.describe "/settings/users", :multiuser do + describe "GET /index", :as_moderator do + it "renders a successful response" do + create(:user) + get "/settings/users" + expect(response).to be_successful + end + end + + describe "GET /show", :as_moderator do + it "renders a successful response" do + user = create(:user) + get "/settings/users/#{user.to_param}" + expect(response).to be_successful + end + end +end