Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit

Permalink
Add admin notifications for new Mastodon versions (mastodon#26582)
Browse files Browse the repository at this point in the history
  • Loading branch information
ClearlyClaire authored Sep 1, 2023
1 parent be991f1 commit 16681e0
Show file tree
Hide file tree
Showing 39 changed files with 892 additions and 8 deletions.
18 changes: 18 additions & 0 deletions app/controllers/admin/software_updates_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Admin
class SoftwareUpdatesController < BaseController
before_action :check_enabled!

def index
authorize :software_update, :index?
@software_updates = SoftwareUpdate.all.sort_by(&:gem_version)
end

private

def check_enabled!
not_found unless SoftwareUpdate.check_enabled?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { FormattedMessage } from 'react-intl';

export const CriticalUpdateBanner = () => (
<div className='warning-banner'>
<div className='warning-banner__message'>
<h1>
<FormattedMessage
id='home.pending_critical_update.title'
defaultMessage='Critical security update available!'
/>
</h1>
<p>
<FormattedMessage
id='home.pending_critical_update.body'
defaultMessage='Please update your Mastodon server as soon as possible!'
/>{' '}
<a href='/admin/software_updates'>
<FormattedMessage
id='home.pending_critical_update.link'
defaultMessage='See updates'
/>
</a>
</p>
</div>
</div>
);
14 changes: 10 additions & 4 deletions app/javascript/mastodon/features/home_timeline/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/an
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
import AnnouncementsContainer from 'mastodon/features/getting_started/containers/announcements_container';
import { me } from 'mastodon/initial_state';
import { me, criticalUpdatesPending } from 'mastodon/initial_state';

import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
import { expandHomeTimeline } from '../../actions/timelines';
Expand All @@ -23,6 +23,7 @@ import ColumnHeader from '../../components/column_header';
import StatusListContainer from '../ui/containers/status_list_container';

import { ColumnSettings } from './components/column_settings';
import { CriticalUpdateBanner } from './components/critical_update_banner';
import { ExplorePrompt } from './components/explore_prompt';

const messages = defineMessages({
Expand Down Expand Up @@ -156,8 +157,9 @@ class HomeTimeline extends PureComponent {
const { intl, hasUnread, columnId, multiColumn, tooSlow, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props;
const pinned = !!columnId;
const { signedIn } = this.context.identity;
const banners = [];

let announcementsButton, banner;
let announcementsButton;

if (hasAnnouncements) {
announcementsButton = (
Expand All @@ -173,8 +175,12 @@ class HomeTimeline extends PureComponent {
);
}

if (criticalUpdatesPending) {
banners.push(<CriticalUpdateBanner key='critical-update-banner' />);
}

if (tooSlow) {
banner = <ExplorePrompt />;
banners.push(<ExplorePrompt key='explore-prompt' />);
}

return (
Expand All @@ -196,7 +202,7 @@ class HomeTimeline extends PureComponent {

{signedIn ? (
<StatusListContainer
prepend={banner}
prepend={banners}
alwaysPrepend
trackScroll={!pinned}
scrollKey={`home_timeline-${columnId}`}
Expand Down
2 changes: 2 additions & 0 deletions app/javascript/mastodon/initial_state.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
* @typedef InitialState
* @property {Record<string, Account>} accounts
* @property {InitialStateLanguage[]} languages
* @property {boolean=} critical_updates_pending
* @property {InitialStateMeta} meta
*/

Expand Down Expand Up @@ -140,6 +141,7 @@ export const useBlurhash = getMeta('use_blurhash');
export const usePendingItems = getMeta('use_pending_items');
export const version = getMeta('version');
export const languages = initialState?.languages;
export const criticalUpdatesPending = initialState?.critical_updates_pending;
// @ts-expect-error
export const statusPageUrl = getMeta('status_page_url');
export const sso_redirect = getMeta('sso_redirect');
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/mastodon/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@
"home.explore_prompt.body": "Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. If that feels too quiet, you may want to:",
"home.explore_prompt.title": "This is your home base within Mastodon.",
"home.hide_announcements": "Hide announcements",
"home.pending_critical_update.body": "Please update your Mastodon server as soon as possible!",
"home.pending_critical_update.link": "See updates",
"home.pending_critical_update.title": "Critical security update available!",
"home.show_announcements": "Show announcements",
"interaction_modal.description.favourite": "With an account on Mastodon, you can favorite this post to let the author know you appreciate it and save it for later.",
"interaction_modal.description.follow": "With an account on Mastodon, you can follow {name} to receive their posts in your home feed.",
Expand Down
5 changes: 5 additions & 0 deletions app/javascript/styles/mastodon/admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ $content-width: 840px;
}
}

.warning a {
color: $gold-star;
font-weight: 700;
}

.simple-navigation-active-leaf a {
color: $primary-text-color;
background-color: $ui-highlight-color;
Expand Down
18 changes: 17 additions & 1 deletion app/javascript/styles/mastodon/components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8860,7 +8860,8 @@ noscript {
}
}

.dismissable-banner {
.dismissable-banner,
.warning-banner {
position: relative;
margin: 10px;
margin-bottom: 5px;
Expand Down Expand Up @@ -8938,6 +8939,21 @@ noscript {
}
}

.warning-banner {
border: 1px solid $warning-red;
background: rgba($warning-red, 0.15);

&__message {
h1 {
color: $warning-red;
}

a {
color: $primary-text-color;
}
}
}

.image {
position: relative;
overflow: hidden;
Expand Down
5 changes: 5 additions & 0 deletions app/javascript/styles/mastodon/tables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
border-top: 1px solid $ui-base-color;
text-align: start;
background: darken($ui-base-color, 4%);

&.critical {
font-weight: 700;
color: $gold-star;
}
}

& > thead > tr > th {
Expand Down
1 change: 1 addition & 0 deletions app/lib/admin/system_check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

class Admin::SystemCheck
ACTIVE_CHECKS = [
Admin::SystemCheck::SoftwareVersionCheck,
Admin::SystemCheck::MediaPrivacyCheck,
Admin::SystemCheck::DatabaseSchemaCheck,
Admin::SystemCheck::SidekiqProcessCheck,
Expand Down
27 changes: 27 additions & 0 deletions app/lib/admin/system_check/software_version_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

class Admin::SystemCheck::SoftwareVersionCheck < Admin::SystemCheck::BaseCheck
include RoutingHelper

def skip?
!current_user.can?(:view_devops) || !SoftwareUpdate.check_enabled?
end

def pass?
software_updates.empty?
end

def message
if software_updates.any?(&:urgent?)
Admin::SystemCheck::Message.new(:software_version_critical_check, nil, admin_software_updates_path, true)
else
Admin::SystemCheck::Message.new(:software_version_patch_check, nil, admin_software_updates_path)
end
end

private

def software_updates
@software_updates ||= SoftwareUpdate.pending_to_a.filter { |update| update.urgent? || update.patch_type? }
end
end
16 changes: 16 additions & 0 deletions app/mailers/admin_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ def new_trends(links, tags, statuses)
end
end

def new_software_updates
locale_for_account(@me) do
mail subject: default_i18n_subject(instance: @instance)
end
end

def new_critical_software_updates
headers['Priority'] = 'urgent'
headers['X-Priority'] = '1'
headers['Importance'] = 'high'

locale_for_account(@me) do
mail subject: default_i18n_subject(instance: @instance)
end
end

private

def process_params
Expand Down
40 changes: 40 additions & 0 deletions app/models/software_update.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: software_updates
#
# id :bigint(8) not null, primary key
# version :string not null
# urgent :boolean default(FALSE), not null
# type :integer default("patch"), not null
# release_notes :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
#

class SoftwareUpdate < ApplicationRecord
self.inheritance_column = nil

enum type: { patch: 0, minor: 1, major: 2 }, _suffix: :type

def gem_version
Gem::Version.new(version)
end

class << self
def check_enabled?
ENV['UPDATE_CHECK_URL'] != ''
end

def pending_to_a
return [] unless check_enabled?

all.to_a.filter { |update| update.gem_version > Mastodon::Version.gem_version }
end

def urgent_pending?
pending_to_a.any?(&:urgent?)
end
end
end
1 change: 1 addition & 0 deletions app/models/user_settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class KeyError < Error; end
setting :pending_account, default: true
setting :trends, default: true
setting :appeal, default: true
setting :software_updates, default: 'critical', in: %w(none critical patch all)
end

namespace :interactions do
Expand Down
7 changes: 7 additions & 0 deletions app/policies/software_update_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class SoftwareUpdatePolicy < ApplicationPolicy
def index?
role.can?(:view_devops)
end
end
6 changes: 5 additions & 1 deletion app/presenters/initial_state_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
class InitialStatePresenter < ActiveModelSerializers::Model
attributes :settings, :push_subscription, :token,
:current_account, :admin, :owner, :text, :visibility,
:disabled_account, :moved_to_account
:disabled_account, :moved_to_account, :critical_updates_pending

def role
current_account&.user_role
end

def critical_updates_pending
role&.can?(:view_devops) && SoftwareUpdate.urgent_pending?
end
end
2 changes: 2 additions & 0 deletions app/serializers/initial_state_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class InitialStateSerializer < ActiveModel::Serializer
:media_attachments, :settings,
:languages

attribute :critical_updates_pending, if: -> { object&.role&.can?(:view_devops) && SoftwareUpdate.check_enabled? }

has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer
has_one :role, serializer: REST::RoleSerializer

Expand Down
Loading

0 comments on commit 16681e0

Please sign in to comment.