M app/javascript/mastodon/components/account.jsx => app/javascript/mastodon/components/account.jsx +3 -3
@@ 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 {
<DisplayName account={account} />
{!minimal && (
<div className='account__details'>
- <ShortNumber value={account.get('followers_count')} renderer={counterRenderer('followers')} /> {verification} {muteTimeRemaining}
+ <ShortNumber value={account.get('followers_count')} renderer={FollowersCounter} /> {verification} {muteTimeRemaining}
</div>
)}
</div>
M app/javascript/mastodon/components/animated_number.tsx => app/javascript/mastodon/components/animated_number.tsx +1 -1
@@ 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) {
M app/javascript/mastodon/components/autosuggest_hashtag.tsx => app/javascript/mastodon/components/autosuggest_hashtag.tsx +1 -1
@@ 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: {
R app/javascript/mastodon/components/common_counter.jsx => app/javascript/mastodon/components/counters.tsx +42 -57
@@ 1,60 1,45 @@
-// @ts-check
+import React from 'react';
+
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) => <strong>{displayNumber}</strong>
- : (displayNumber) => displayNumber;
+export const StatusesCounter = (
+ displayNumber: React.ReactNode,
+ pluralReady: number
+) => (
+ <FormattedMessage
+ id='account.statuses_counter'
+ defaultMessage='{count, plural, one {{counter} Post} other {{counter} Posts}}'
+ values={{
+ count: pluralReady,
+ counter: <strong>{displayNumber}</strong>,
+ }}
+ />
+);
+
+export const FollowingCounter = (
+ displayNumber: React.ReactNode,
+ pluralReady: number
+) => (
+ <FormattedMessage
+ id='account.following_counter'
+ defaultMessage='{count, plural, one {{counter} Following} other {{counter} Following}}'
+ values={{
+ count: pluralReady,
+ counter: <strong>{displayNumber}</strong>,
+ }}
+ />
+);
- switch (counterType) {
- case 'statuses': {
- return (displayNumber, pluralReady) => (
- <FormattedMessage
- id='account.statuses_counter'
- defaultMessage='{count, plural, one {{counter} Post} other {{counter} Posts}}'
- values={{
- count: pluralReady,
- counter: renderCounter(displayNumber),
- }}
- />
- );
- }
- case 'following': {
- return (displayNumber, pluralReady) => (
- <FormattedMessage
- id='account.following_counter'
- defaultMessage='{count, plural, one {{counter} Following} other {{counter} Following}}'
- values={{
- count: pluralReady,
- counter: renderCounter(displayNumber),
- }}
- />
- );
- }
- case 'followers': {
- return (displayNumber, pluralReady) => (
- <FormattedMessage
- id='account.followers_counter'
- defaultMessage='{count, plural, one {{counter} Follower} other {{counter} Followers}}'
- values={{
- count: pluralReady,
- counter: renderCounter(displayNumber),
- }}
- />
- );
- }
- default: throw Error(`Incorrect counter name: ${counterType}. Ensure it accepted by commonCounter function`);
- }
-}
+export const FollowersCounter = (
+ displayNumber: React.ReactNode,
+ pluralReady: number
+) => (
+ <FormattedMessage
+ id='account.followers_counter'
+ defaultMessage='{count, plural, one {{counter} Follower} other {{counter} Followers}}'
+ values={{
+ count: pluralReady,
+ counter: <strong>{displayNumber}</strong>,
+ }}
+ />
+);
D app/javascript/mastodon/components/dismissable_banner.jsx => app/javascript/mastodon/components/dismissable_banner.jsx +0 -55
@@ 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 (
- <div className='dismissable-banner'>
- <div className='dismissable-banner__message'>
- {children}
- </div>
-
- <div className='dismissable-banner__action'>
- <IconButton icon='times' title={intl.formatMessage(messages.dismiss)} onClick={this.handleDismiss} />
- </div>
- </div>
- );
- }
-
-}
-
-export default injectIntl(DismissableBanner);
A app/javascript/mastodon/components/dismissable_banner.tsx => app/javascript/mastodon/components/dismissable_banner.tsx +47 -0
@@ 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<PropsWithChildren<Props>> = ({
+ 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 (
+ <div className='dismissable-banner'>
+ <div className='dismissable-banner__message'>{children}</div>
+
+ <div className='dismissable-banner__action'>
+ <IconButton
+ icon='times'
+ title={intl.formatMessage(messages.dismiss)}
+ onClick={handleDismiss}
+ />
+ </div>
+ </div>
+ );
+};
M app/javascript/mastodon/components/hashtag.jsx => app/javascript/mastodon/components/hashtag.jsx +1 -1
@@ 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 {
M app/javascript/mastodon/components/server_banner.jsx => app/javascript/mastodon/components/server_banner.jsx +1 -1
@@ 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';
R app/javascript/mastodon/components/short_number.jsx => app/javascript/mastodon/components/short_number.tsx +59 -84
@@ 1,69 1,49 @@
-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
+type ShortNumberRenderer = (
+ displayNumber: JSX.Element,
+ pluralReady: number
+) => JSX.Element;
-/**
- * @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.
- */
+interface ShortNumberProps {
+ value: number;
+ renderer?: ShortNumberRenderer;
+ children?: ShortNumberRenderer;
+}
-/**
- * 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 }) {
+export const ShortNumberRenderer: React.FC<ShortNumberProps> = ({
+ 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.');
+ 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 != null ? children : renderer;
+ const customRenderer = children || renderer || null;
const displayNumber = <ShortNumberCounter value={shortNumber} />;
- return customRenderer != null
- ? customRenderer(displayNumber, pluralReady(value, division))
- : displayNumber;
-}
-
-ShortNumber.propTypes = {
- value: PropTypes.number.isRequired,
- renderer: PropTypes.func,
- children: PropTypes.func,
+ return (
+ customRenderer?.(displayNumber, pluralReady(value, division)) ||
+ displayNumber
+ );
};
+export const ShortNumber = memo(ShortNumberRenderer);
-/**
- * @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 }) {
+interface ShortNumberCounterProps {
+ value: number[];
+}
+const ShortNumberCounter: React.FC<ShortNumberCounterProps> = ({ value }) => {
const [rawNumber, unit, maxFractionDigits = 0] = value;
const count = (
@@ 73,43 53,38 @@ function ShortNumberCounter({ value }) {
/>
);
- let values = { count, rawNumber };
+ const values = { count, rawNumber };
switch (unit) {
- case DECIMAL_UNITS.THOUSAND: {
- return (
- <FormattedMessage
- id='units.short.thousand'
- defaultMessage='{count}K'
- values={values}
- />
- );
+ case DECIMAL_UNITS.THOUSAND: {
+ return (
+ <FormattedMessage
+ id='units.short.thousand'
+ defaultMessage='{count}K'
+ values={values}
+ />
+ );
+ }
+ case DECIMAL_UNITS.MILLION: {
+ return (
+ <FormattedMessage
+ id='units.short.million'
+ defaultMessage='{count}M'
+ values={values}
+ />
+ );
+ }
+ case DECIMAL_UNITS.BILLION: {
+ return (
+ <FormattedMessage
+ id='units.short.billion'
+ defaultMessage='{count}B'
+ values={values}
+ />
+ );
+ }
+ // Not sure if we should go farther - @Sasha-Sorokin
+ default:
+ return count;
}
- case DECIMAL_UNITS.MILLION: {
- return (
- <FormattedMessage
- id='units.short.million'
- defaultMessage='{count}M'
- values={values}
- />
- );
- }
- case DECIMAL_UNITS.BILLION: {
- return (
- <FormattedMessage
- id='units.short.billion'
- defaultMessage='{count}B'
- values={values}
- />
- );
- }
- // Not sure if we should go farther - @Sasha-Sorokin
- default: return count;
- }
-}
-
-ShortNumberCounter.propTypes = {
- value: PropTypes.arrayOf(PropTypes.number),
};
-
-export default memo(ShortNumber);
M app/javascript/mastodon/components/status_content.jsx => app/javascript/mastodon/components/status_content.jsx +1 -1
@@ 44,7 44,7 @@ class TranslateButton extends PureComponent {
}
return (
- <button className='status__content__read-more-button' onClick={onClick}>
+ <button className='status__content__translate-button' onClick={onClick}>
<FormattedMessage id='status.translate' defaultMessage='Translate' />
</button>
);
M => +5 -5
@@ 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 {
<NavLink isActive={this.isStatusesPageActive} activeClassName='active' to={`/@${account.get('acct')}`} title={intl.formatNumber(account.get('statuses_count'))}>
<ShortNumber
value={account.get('statuses_count')}
renderer={counterRenderer('statuses')}
renderer={StatusesCounter}
/>
</NavLink>
<NavLink exact activeClassName='active' to={`/@${account.get('acct')}/following`} title={intl.formatNumber(account.get('following_count'))}>
<ShortNumber
value={account.get('following_count')}
renderer={counterRenderer('following')}
renderer={FollowingCounter}
/>
</NavLink>
<NavLink exact activeClassName='active' to={`/@${account.get('acct')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
<ShortNumber
value={account.get('followers_count')}
renderer={counterRenderer('followers')}
renderer={FollowersCounter}
/>
</NavLink>
</div>
M => +1 -1
@@ 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';
M app/javascript/mastodon/features/directory/components/account_card.jsx => app/javascript/mastodon/features/directory/components/account_card.jsx +1 -1
@@ 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';
M app/javascript/mastodon/features/explore/components/story.jsx => app/javascript/mastodon/features/explore/components/story.jsx +1 -1
@@ 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 {
M app/javascript/mastodon/features/explore/links.jsx => app/javascript/mastodon/features/explore/links.jsx +1 -1
@@ 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';
M app/javascript/mastodon/features/explore/statuses.jsx => app/javascript/mastodon/features/explore/statuses.jsx +1 -1
@@ 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';
M app/javascript/mastodon/features/explore/tags.jsx => app/javascript/mastodon/features/explore/tags.jsx +1 -1
@@ 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';
M app/javascript/mastodon/features/firehose/index.jsx => app/javascript/mastodon/features/firehose/index.jsx +1 -1
@@ 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';
M app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx => app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx +1 -1
@@ 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 = () => (
M app/javascript/mastodon/features/public_timeline/index.jsx => app/javascript/mastodon/features/public_timeline/index.jsx +1 -1
@@ 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';
M app/javascript/styles/contrast/diff.scss => app/javascript/styles/contrast/diff.scss +2 -1
@@ 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,
M app/javascript/styles/mastodon/components.scss => app/javascript/styles/mastodon/components.scss +2 -1
@@ 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;
M config/brakeman.ignore => config/brakeman.ignore +28 -64
@@ 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"
}