diff --git a/app/javascript/mastodon/components/account.jsx b/app/javascript/mastodon/components/account.jsx index dd5aff1d8..fd5ea6040 100644 --- a/app/javascript/mastodon/components/account.jsx +++ b/app/javascript/mastodon/components/account.jsx @@ -8,15 +8,15 @@ import { Link } from 'react-router-dom'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { counterRenderer } from 'mastodon/components/common_counter'; import { EmptyAccount } from 'mastodon/components/empty_account'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; import { VerifiedBadge } from 'mastodon/components/verified_badge'; import { me } from '../initial_state'; import { Avatar } from './avatar'; import Button from './button'; +import { FollowersCounter } from './counters'; import { DisplayName } from './display_name'; import { IconButton } from './icon_button'; import { RelativeTimestamp } from './relative_timestamp'; @@ -160,7 +160,7 @@ class Account extends ImmutablePureComponent { {!minimal && (
- {verification} {muteTimeRemaining} + {verification} {muteTimeRemaining}
)} diff --git a/app/javascript/mastodon/components/animated_number.tsx b/app/javascript/mastodon/components/animated_number.tsx index ad985a29e..3122d6421 100644 --- a/app/javascript/mastodon/components/animated_number.tsx +++ b/app/javascript/mastodon/components/animated_number.tsx @@ -4,7 +4,7 @@ import { TransitionMotion, spring } from 'react-motion'; import { reduceMotion } from '../initial_state'; -import ShortNumber from './short_number'; +import { ShortNumber } from './short_number'; const obfuscatedCount = (count: number) => { if (count < 0) { diff --git a/app/javascript/mastodon/components/autosuggest_hashtag.tsx b/app/javascript/mastodon/components/autosuggest_hashtag.tsx index c6798054d..59d66ec87 100644 --- a/app/javascript/mastodon/components/autosuggest_hashtag.tsx +++ b/app/javascript/mastodon/components/autosuggest_hashtag.tsx @@ -1,6 +1,6 @@ import { FormattedMessage } from 'react-intl'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; interface Props { tag: { diff --git a/app/javascript/mastodon/components/common_counter.jsx b/app/javascript/mastodon/components/common_counter.jsx deleted file mode 100644 index 23e1f2263..000000000 --- a/app/javascript/mastodon/components/common_counter.jsx +++ /dev/null @@ -1,60 +0,0 @@ -// @ts-check -import { FormattedMessage } from 'react-intl'; - -/** - * Returns custom renderer for one of the common counter types - * @param {"statuses" | "following" | "followers"} counterType - * Type of the counter - * @param {boolean} isBold Whether display number must be displayed in bold - * @returns {(displayNumber: JSX.Element, pluralReady: number) => JSX.Element} - * Renderer function - * @throws If counterType is not covered by this function - */ -export function counterRenderer(counterType, isBold = true) { - /** - * @type {(displayNumber: JSX.Element) => JSX.Element} - */ - const renderCounter = isBold - ? (displayNumber) => {displayNumber} - : (displayNumber) => displayNumber; - - switch (counterType) { - case 'statuses': { - return (displayNumber, pluralReady) => ( - - ); - } - case 'following': { - return (displayNumber, pluralReady) => ( - - ); - } - case 'followers': { - return (displayNumber, pluralReady) => ( - - ); - } - default: throw Error(`Incorrect counter name: ${counterType}. Ensure it accepted by commonCounter function`); - } -} diff --git a/app/javascript/mastodon/components/counters.tsx b/app/javascript/mastodon/components/counters.tsx new file mode 100644 index 000000000..e0c818f24 --- /dev/null +++ b/app/javascript/mastodon/components/counters.tsx @@ -0,0 +1,45 @@ +import React from 'react'; + +import { FormattedMessage } from 'react-intl'; + +export const StatusesCounter = ( + displayNumber: React.ReactNode, + pluralReady: number +) => ( + {displayNumber}, + }} + /> +); + +export const FollowingCounter = ( + displayNumber: React.ReactNode, + pluralReady: number +) => ( + {displayNumber}, + }} + /> +); + +export const FollowersCounter = ( + displayNumber: React.ReactNode, + pluralReady: number +) => ( + {displayNumber}, + }} + /> +); diff --git a/app/javascript/mastodon/components/dismissable_banner.jsx b/app/javascript/mastodon/components/dismissable_banner.jsx deleted file mode 100644 index 5aecc88b1..000000000 --- a/app/javascript/mastodon/components/dismissable_banner.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import PropTypes from 'prop-types'; -import { PureComponent } from 'react'; - -import { injectIntl, defineMessages } from 'react-intl'; - -import { bannerSettings } from 'mastodon/settings'; - -import { IconButton } from './icon_button'; - -const messages = defineMessages({ - dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' }, -}); - -class DismissableBanner extends PureComponent { - - static propTypes = { - id: PropTypes.string.isRequired, - children: PropTypes.node, - intl: PropTypes.object.isRequired, - }; - - state = { - visible: !bannerSettings.get(this.props.id), - }; - - handleDismiss = () => { - const { id } = this.props; - this.setState({ visible: false }, () => bannerSettings.set(id, true)); - }; - - render () { - const { visible } = this.state; - - if (!visible) { - return null; - } - - const { children, intl } = this.props; - - return ( -
-
- {children} -
- -
- -
-
- ); - } - -} - -export default injectIntl(DismissableBanner); diff --git a/app/javascript/mastodon/components/dismissable_banner.tsx b/app/javascript/mastodon/components/dismissable_banner.tsx new file mode 100644 index 000000000..d5cdb0750 --- /dev/null +++ b/app/javascript/mastodon/components/dismissable_banner.tsx @@ -0,0 +1,47 @@ +import type { PropsWithChildren } from 'react'; +import { useCallback, useState } from 'react'; + +import { defineMessages, useIntl } from 'react-intl'; + +import { bannerSettings } from 'mastodon/settings'; + +import { IconButton } from './icon_button'; + +const messages = defineMessages({ + dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' }, +}); + +interface Props { + id: string; +} + +export const DismissableBanner: React.FC> = ({ + id, + children, +}) => { + const [visible, setVisible] = useState(!bannerSettings.get(id)); + const intl = useIntl(); + + const handleDismiss = useCallback(() => { + setVisible(false); + bannerSettings.set(id, true); + }, [id]); + + if (!visible) { + return null; + } + + return ( +
+
{children}
+ +
+ +
+
+ ); +}; diff --git a/app/javascript/mastodon/components/hashtag.jsx b/app/javascript/mastodon/components/hashtag.jsx index 4a7b9ef71..14bb4ddc6 100644 --- a/app/javascript/mastodon/components/hashtag.jsx +++ b/app/javascript/mastodon/components/hashtag.jsx @@ -11,7 +11,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { Sparklines, SparklinesCurve } from 'react-sparklines'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; import { Skeleton } from 'mastodon/components/skeleton'; class SilentErrorBoundary extends Component { diff --git a/app/javascript/mastodon/components/server_banner.jsx b/app/javascript/mastodon/components/server_banner.jsx index 998237860..63eec5349 100644 --- a/app/javascript/mastodon/components/server_banner.jsx +++ b/app/javascript/mastodon/components/server_banner.jsx @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { fetchServer } from 'mastodon/actions/server'; import { ServerHeroImage } from 'mastodon/components/server_hero_image'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; import { Skeleton } from 'mastodon/components/skeleton'; import Account from 'mastodon/containers/account_container'; import { domain } from 'mastodon/initial_state'; diff --git a/app/javascript/mastodon/components/short_number.jsx b/app/javascript/mastodon/components/short_number.jsx deleted file mode 100644 index b7ac4f5fd..000000000 --- a/app/javascript/mastodon/components/short_number.jsx +++ /dev/null @@ -1,115 +0,0 @@ -import PropTypes from 'prop-types'; -import { memo } from 'react'; - -import { FormattedMessage, FormattedNumber } from 'react-intl'; - -import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers'; - -// @ts-check - -/** - * @callback ShortNumberRenderer - * @param {JSX.Element} displayNumber Number to display - * @param {number} pluralReady Number used for pluralization - * @returns {JSX.Element} Final render of number - */ - -/** - * @typedef {object} ShortNumberProps - * @property {number} value Number to display in short variant - * @property {ShortNumberRenderer} [renderer] - * Custom renderer for numbers, provided as a prop. If another renderer - * passed as a child of this component, this prop won't be used. - * @property {ShortNumberRenderer} [children] - * Custom renderer for numbers, provided as a child. If another renderer - * passed as a prop of this component, this one will be used instead. - */ - -/** - * Component that renders short big number to a shorter version - * @param {ShortNumberProps} param0 Props for the component - * @returns {JSX.Element} Rendered number - */ -function ShortNumber({ value, renderer, children }) { - const shortNumber = toShortNumber(value); - const [, division] = shortNumber; - - if (children != null && renderer != null) { - console.warn('Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.'); - } - - const customRenderer = children != null ? children : renderer; - - const displayNumber = ; - - return customRenderer != null - ? customRenderer(displayNumber, pluralReady(value, division)) - : displayNumber; -} - -ShortNumber.propTypes = { - value: PropTypes.number.isRequired, - renderer: PropTypes.func, - children: PropTypes.func, -}; - -/** - * @typedef {object} ShortNumberCounterProps - * @property {import('../utils/number').ShortNumber} value Short number - */ - -/** - * Renders short number into corresponding localizable react fragment - * @param {ShortNumberCounterProps} param0 Props for the component - * @returns {JSX.Element} FormattedMessage ready to be embedded in code - */ -function ShortNumberCounter({ value }) { - const [rawNumber, unit, maxFractionDigits = 0] = value; - - const count = ( - - ); - - let values = { count, rawNumber }; - - switch (unit) { - case DECIMAL_UNITS.THOUSAND: { - return ( - - ); - } - case DECIMAL_UNITS.MILLION: { - return ( - - ); - } - case DECIMAL_UNITS.BILLION: { - return ( - - ); - } - // Not sure if we should go farther - @Sasha-Sorokin - default: return count; - } -} - -ShortNumberCounter.propTypes = { - value: PropTypes.arrayOf(PropTypes.number), -}; - -export default memo(ShortNumber); diff --git a/app/javascript/mastodon/components/short_number.tsx b/app/javascript/mastodon/components/short_number.tsx new file mode 100644 index 000000000..010586c04 --- /dev/null +++ b/app/javascript/mastodon/components/short_number.tsx @@ -0,0 +1,90 @@ +import { memo } from 'react'; + +import { FormattedMessage, FormattedNumber } from 'react-intl'; + +import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers'; + +type ShortNumberRenderer = ( + displayNumber: JSX.Element, + pluralReady: number +) => JSX.Element; + +interface ShortNumberProps { + value: number; + renderer?: ShortNumberRenderer; + children?: ShortNumberRenderer; +} + +export const ShortNumberRenderer: React.FC = ({ + value, + renderer, + children, +}) => { + const shortNumber = toShortNumber(value); + const [, division] = shortNumber; + + if (children && renderer) { + console.warn( + 'Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.' + ); + } + + const customRenderer = children || renderer || null; + + const displayNumber = ; + + return ( + customRenderer?.(displayNumber, pluralReady(value, division)) || + displayNumber + ); +}; +export const ShortNumber = memo(ShortNumberRenderer); + +interface ShortNumberCounterProps { + value: number[]; +} +const ShortNumberCounter: React.FC = ({ value }) => { + const [rawNumber, unit, maxFractionDigits = 0] = value; + + const count = ( + + ); + + const values = { count, rawNumber }; + + switch (unit) { + case DECIMAL_UNITS.THOUSAND: { + return ( + + ); + } + case DECIMAL_UNITS.MILLION: { + return ( + + ); + } + case DECIMAL_UNITS.BILLION: { + return ( + + ); + } + // Not sure if we should go farther - @Sasha-Sorokin + default: + return count; + } +}; diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 688a45631..84a698810 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -44,7 +44,7 @@ class TranslateButton extends PureComponent { } return ( - ); diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx index b718e860d..5e30205b0 100644 --- a/app/javascript/mastodon/features/account/components/header.jsx +++ b/app/javascript/mastodon/features/account/components/header.jsx @@ -11,10 +11,10 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { Avatar } from 'mastodon/components/avatar'; import Button from 'mastodon/components/button'; -import { counterRenderer } from 'mastodon/components/common_counter'; +import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters'; import { Icon } from 'mastodon/components/icon'; import { IconButton } from 'mastodon/components/icon_button'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; import { autoPlayGif, me, domain } from 'mastodon/initial_state'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; @@ -451,21 +451,21 @@ class Header extends ImmutablePureComponent { diff --git a/app/javascript/mastodon/features/community_timeline/index.jsx b/app/javascript/mastodon/features/community_timeline/index.jsx index 7e3b9babe..2d94cabed 100644 --- a/app/javascript/mastodon/features/community_timeline/index.jsx +++ b/app/javascript/mastodon/features/community_timeline/index.jsx @@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet'; import { connect } from 'react-redux'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import { domain } from 'mastodon/initial_state'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; diff --git a/app/javascript/mastodon/features/directory/components/account_card.jsx b/app/javascript/mastodon/features/directory/components/account_card.jsx index cf1c63f9e..795979530 100644 --- a/app/javascript/mastodon/features/directory/components/account_card.jsx +++ b/app/javascript/mastodon/features/directory/components/account_card.jsx @@ -19,7 +19,7 @@ import { openModal } from 'mastodon/actions/modal'; import { Avatar } from 'mastodon/components/avatar'; import Button from 'mastodon/components/button'; import { DisplayName } from 'mastodon/components/display_name'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state'; import { makeGetAccount } from 'mastodon/selectors'; diff --git a/app/javascript/mastodon/features/explore/components/story.jsx b/app/javascript/mastodon/features/explore/components/story.jsx index 0a9fbb190..73ec99c14 100644 --- a/app/javascript/mastodon/features/explore/components/story.jsx +++ b/app/javascript/mastodon/features/explore/components/story.jsx @@ -5,7 +5,7 @@ import classNames from 'classnames'; import { Blurhash } from 'mastodon/components/blurhash'; import { accountsCountRenderer } from 'mastodon/components/hashtag'; -import ShortNumber from 'mastodon/components/short_number'; +import { ShortNumber } from 'mastodon/components/short_number'; import { Skeleton } from 'mastodon/components/skeleton'; export default class Story extends PureComponent { diff --git a/app/javascript/mastodon/features/explore/links.jsx b/app/javascript/mastodon/features/explore/links.jsx index 49c667f02..8b199bf47 100644 --- a/app/javascript/mastodon/features/explore/links.jsx +++ b/app/javascript/mastodon/features/explore/links.jsx @@ -7,7 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { connect } from 'react-redux'; import { fetchTrendingLinks } from 'mastodon/actions/trends'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import { LoadingIndicator } from 'mastodon/components/loading_indicator'; import Story from './components/story'; diff --git a/app/javascript/mastodon/features/explore/statuses.jsx b/app/javascript/mastodon/features/explore/statuses.jsx index eb2fe777a..3271929db 100644 --- a/app/javascript/mastodon/features/explore/statuses.jsx +++ b/app/javascript/mastodon/features/explore/statuses.jsx @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { debounce } from 'lodash'; import { fetchTrendingStatuses, expandTrendingStatuses } from 'mastodon/actions/trends'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import StatusList from 'mastodon/components/status_list'; import { getStatusList } from 'mastodon/selectors'; diff --git a/app/javascript/mastodon/features/explore/tags.jsx b/app/javascript/mastodon/features/explore/tags.jsx index f558b48a6..1a4d25969 100644 --- a/app/javascript/mastodon/features/explore/tags.jsx +++ b/app/javascript/mastodon/features/explore/tags.jsx @@ -7,7 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { connect } from 'react-redux'; import { fetchTrendingHashtags } from 'mastodon/actions/trends'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag'; import { LoadingIndicator } from 'mastodon/components/loading_indicator'; diff --git a/app/javascript/mastodon/features/firehose/index.jsx b/app/javascript/mastodon/features/firehose/index.jsx index 9ba4fd5b2..e5b47d3fe 100644 --- a/app/javascript/mastodon/features/firehose/index.jsx +++ b/app/javascript/mastodon/features/firehose/index.jsx @@ -10,7 +10,7 @@ import { addColumn } from 'mastodon/actions/columns'; import { changeSetting } from 'mastodon/actions/settings'; import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming'; import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import initialState, { domain } from 'mastodon/initial_state'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; diff --git a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx index a6993c641..2af85b6d5 100644 --- a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx +++ b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx @@ -5,7 +5,7 @@ import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router-dom'; import background from 'mastodon/../images/friends-cropped.png'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; export const ExplorePrompt = () => ( diff --git a/app/javascript/mastodon/features/public_timeline/index.jsx b/app/javascript/mastodon/features/public_timeline/index.jsx index 352baa833..3bfb25ba7 100644 --- a/app/javascript/mastodon/features/public_timeline/index.jsx +++ b/app/javascript/mastodon/features/public_timeline/index.jsx @@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet'; import { connect } from 'react-redux'; -import DismissableBanner from 'mastodon/components/dismissable_banner'; +import { DismissableBanner } from 'mastodon/components/dismissable_banner'; import { domain } from 'mastodon/initial_state'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; diff --git a/app/javascript/styles/contrast/diff.scss b/app/javascript/styles/contrast/diff.scss index 4fa1a0361..1c2386f02 100644 --- a/app/javascript/styles/contrast/diff.scss +++ b/app/javascript/styles/contrast/diff.scss @@ -15,7 +15,8 @@ .status__content a, .link-footer a, .reply-indicator__content a, -.status__content__read-more-button { +.status__content__read-more-button, +.status__content__translate-button { text-decoration: underline; &:hover, diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index c6dd5ce14..0d0d5a856 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -981,7 +981,8 @@ body > [data-popper-placement] { max-height: 22px * 15; // 15 lines is roughly above 500 characters } -.status__content__read-more-button { +.status__content__read-more-button, +.status__content__translate-button { display: block; font-size: 15px; line-height: 22px; diff --git a/config/brakeman.ignore b/config/brakeman.ignore index 80c5f6d4e..d89591cfe 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -18,6 +18,9 @@ }, "user_input": "id", "confidence": "Weak", + "cwe_id": [ + 89 + ], "note": "" }, { @@ -38,26 +41,9 @@ }, "user_input": "ids.join(\",\")", "confidence": "Weak", - "note": "" - }, - { - "warning_type": "Redirect", - "warning_code": 18, - "fingerprint": "5fad11cd67f905fab9b1d5739d01384a1748ebe78c5af5ac31518201925265a7", - "check_name": "Redirect", - "message": "Possible unprotected redirect", - "file": "app/controllers/remote_interaction_controller.rb", - "line": 24, - "link": "https://brakemanscanner.org/docs/warning_types/redirect/", - "code": "redirect_to(RemoteFollow.new(resource_params).interact_address_for(Status.find(params[:id])))", - "render_path": null, - "location": { - "type": "method", - "class": "RemoteInteractionController", - "method": "create" - }, - "user_input": "RemoteFollow.new(resource_params).interact_address_for(Status.find(params[:id]))", - "confidence": "High", + "cwe_id": [ + 89 + ], "note": "" }, { @@ -88,6 +74,9 @@ }, "user_input": "(Unresolved Model).new.strike", "confidence": "Weak", + "cwe_id": [ + 79 + ], "note": "" }, { @@ -108,26 +97,9 @@ }, "user_input": "SecureRandom.hex(16)", "confidence": "Medium", - "note": "" - }, - { - "warning_type": "Mass Assignment", - "warning_code": 105, - "fingerprint": "7631e93d0099506e7c3e5c91ba8d88523b00a41a0834ae30031a5a4e8bb3020a", - "check_name": "PermitAttributes", - "message": "Potentially dangerous key allowed for mass assignment", - "file": "app/controllers/api/v2/search_controller.rb", - "line": 28, - "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/", - "code": "params.permit(:type, :offset, :min_id, :max_id, :account_id)", - "render_path": null, - "location": { - "type": "method", - "class": "Api::V2::SearchController", - "method": "search_params" - }, - "user_input": ":account_id", - "confidence": "High", + "cwe_id": [ + 89 + ], "note": "" }, { @@ -137,7 +109,7 @@ "check_name": "PermitAttributes", "message": "Potentially dangerous key allowed for mass assignment", "file": "app/controllers/api/v1/admin/reports_controller.rb", - "line": 90, + "line": 88, "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/", "code": "params.permit(:resolved, :account_id, :target_account_id)", "render_path": null, @@ -148,6 +120,9 @@ }, "user_input": ":account_id", "confidence": "High", + "cwe_id": [ + 915 + ], "note": "" }, { @@ -157,7 +132,7 @@ "check_name": "PermitAttributes", "message": "Potentially dangerous key allowed for mass assignment", "file": "app/controllers/api/v1/notifications_controller.rb", - "line": 81, + "line": 77, "link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/", "code": "params.permit(:account_id, :types => ([]), :exclude_types => ([]))", "render_path": null, @@ -168,26 +143,9 @@ }, "user_input": ":account_id", "confidence": "High", - "note": "" - }, - { - "warning_type": "Redirect", - "warning_code": 18, - "fingerprint": "ba568ac09683f98740f663f3d850c31785900215992e8c090497d359a2563d50", - "check_name": "Redirect", - "message": "Possible unprotected redirect", - "file": "app/controllers/remote_follow_controller.rb", - "line": 21, - "link": "https://brakemanscanner.org/docs/warning_types/redirect/", - "code": "redirect_to(RemoteFollow.new(resource_params).subscribe_address_for(@account))", - "render_path": null, - "location": { - "type": "method", - "class": "RemoteFollowController", - "method": "create" - }, - "user_input": "RemoteFollow.new(resource_params).subscribe_address_for(@account)", - "confidence": "High", + "cwe_id": [ + 915 + ], "note": "" }, { @@ -218,6 +176,9 @@ }, "user_input": "(Unresolved Model).new.url", "confidence": "Weak", + "cwe_id": [ + 79 + ], "note": "" }, { @@ -238,9 +199,12 @@ }, "user_input": ":account_id", "confidence": "High", + "cwe_id": [ + 915 + ], "note": "" } ], - "updated": "2022-03-22 07:48:32 +0100", - "brakeman_version": "5.2.1" + "updated": "2023-07-05 14:34:42 -0400", + "brakeman_version": "5.4.1" }