Added ability to set password for groups
• Added: - ability to set password for groups - GroupPasswordModal - checks for if has password - rate limiting in rack_attack
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import {
|
||||
joinGroup,
|
||||
checkGroupPassword,
|
||||
checkGroupPasswordReset,
|
||||
} from '../../actions/groups'
|
||||
import ModalLayout from './modal_layout'
|
||||
import Button from '../button'
|
||||
import Input from '../input'
|
||||
import Text from '../text'
|
||||
|
||||
class GroupPasswordModal extends ImmutablePureComponent {
|
||||
|
||||
state = {
|
||||
text: '',
|
||||
isError: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { url } = this.props
|
||||
this.props.onCheckGroupPasswordReset()
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.group !== prevProps.group) {
|
||||
this.props.onCheckGroupPasswordReset()
|
||||
}
|
||||
if (this.props.passwordCheckIsError && prevProps.passwordCheckIsLoading) {
|
||||
this.setState({ isError: true })
|
||||
}
|
||||
if (this.props.passwordCheckIsSuccess) {
|
||||
this.props.onClose()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.onCheckGroupPasswordReset()
|
||||
}
|
||||
|
||||
handlePasswordChange = (value) => {
|
||||
this.setState({
|
||||
text: value,
|
||||
isError: false,
|
||||
})
|
||||
}
|
||||
|
||||
handleOnClick = () => {
|
||||
this.props.onCheckGroupPassword(this.props.group.get('id'), this.state.text)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
group,
|
||||
onClose,
|
||||
passwordCheckIsLoading,
|
||||
passwordCheckIsError,
|
||||
passwordCheckIsSuccess,
|
||||
} = this.props
|
||||
const { text, isError } = this.state
|
||||
|
||||
if (!group) {
|
||||
//loading
|
||||
return <div/>
|
||||
}
|
||||
|
||||
const hasPassword = group.get('has_password')
|
||||
const isPrivate = group.get('is_private')
|
||||
|
||||
const instructions = isPrivate ? 'Enter the group password and then your join request will be sent to the group admin.' : 'Enter the group password to join the group.'
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
width={360}
|
||||
>
|
||||
<div className={_s.d}>
|
||||
<div className={[_s.d, _s.my10].join(' ')}>
|
||||
{
|
||||
isError &&
|
||||
<Text color='error' className={[_s.pb15, _s.px15].join(' ')}>There was an error submitting the form.</Text>
|
||||
}
|
||||
<Input
|
||||
isDisabled={passwordCheckIsLoading}
|
||||
type='text'
|
||||
value={text}
|
||||
placeholder='•••••••••••'
|
||||
id='group-password'
|
||||
title='Enter group password'
|
||||
onChange={this.handlePasswordChange}
|
||||
/>
|
||||
|
||||
<Text className={[_s.my10, _s.ml15].join(' ')} size='small' color='secondary'>
|
||||
{instructions}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
isDisabled={passwordCheckIsLoading}
|
||||
onClick={this.handleOnClick}
|
||||
icon={passwordCheckIsLoading ? 'loading' : null}
|
||||
iconSize='20px'
|
||||
className={[_s.aiCenter, _s.jcCenter].join(' ')}
|
||||
>
|
||||
<Text color='inherit' className={_s.px10}>{intl.formatMessage(messages.submit)}</Text>
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'group.password_required', defaultMessage: 'Group password required' },
|
||||
submit: { id: 'report.submit', defaultMessage: 'Submit' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
passwordCheckIsLoading: state.getIn(['group_lists', 'passwordCheck', 'isLoading'], false),
|
||||
passwordCheckIsError: state.getIn(['group_lists', 'passwordCheck', 'isError'], false),
|
||||
passwordCheckIsSuccess: state.getIn(['group_lists', 'passwordCheck', 'isSuccess'], false),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onCheckGroupPassword(groupId, password) {
|
||||
dispatch(checkGroupPassword(groupId, password))
|
||||
},
|
||||
onCheckGroupPasswordReset() {
|
||||
dispatch(checkGroupPasswordReset())
|
||||
},
|
||||
onJoinGroup(groupId) {
|
||||
dispatch(joinGroup(groupId))
|
||||
},
|
||||
})
|
||||
|
||||
GroupPasswordModal.propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onError: PropTypes.func.isRequired,
|
||||
onCheckGroupPassword: PropTypes.func.isRequired,
|
||||
onCheckGroupPasswordReset: PropTypes.func.isRequired,
|
||||
onJoinGrouponJoinGroup: PropTypes.func.isRequired,
|
||||
passwordCheckIsLoading: PropTypes.bool.isRequired,
|
||||
passwordCheckIsError: PropTypes.bool.isRequired,
|
||||
passwordCheckIsSuccess: PropTypes.bool.isRequired,
|
||||
}
|
||||
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(GroupPasswordModal))
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
MODAL_EMBED,
|
||||
MODAL_GROUP_CREATE,
|
||||
MODAL_GROUP_DELETE,
|
||||
MODAL_GROUP_PASSWORD,
|
||||
MODAL_HASHTAG_TIMELINE_SETTINGS,
|
||||
MODAL_HOME_TIMELINE_SETTINGS,
|
||||
MODAL_HOTKEYS,
|
||||
@@ -51,6 +52,7 @@ import {
|
||||
GroupCreateModal,
|
||||
GroupDeleteModal,
|
||||
GroupMembersModal,
|
||||
GroupPasswordModal,
|
||||
GroupRemovedAccountsModal,
|
||||
HashtagTimelineSettingsModal,
|
||||
HomeTimelineSettingsModal,
|
||||
@@ -84,6 +86,7 @@ MODAL_COMPONENTS[MODAL_EDIT_PROFILE] = EditProfileModal
|
||||
MODAL_COMPONENTS[MODAL_EMBED] = EmbedModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_CREATE] = GroupCreateModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_DELETE] = GroupDeleteModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_PASSWORD] = GroupPasswordModal
|
||||
MODAL_COMPONENTS[MODAL_HASHTAG_TIMELINE_SETTINGS] = HashtagTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_HOME_TIMELINE_SETTINGS] = HomeTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_HOTKEYS] = HotkeysModal
|
||||
|
||||
@@ -35,7 +35,7 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
||||
)
|
||||
}
|
||||
|
||||
const isAdmin = relationships ? relationships.get('admin') : false
|
||||
const isAdminOrMod = relationships ? (relationships.get('admin') || relationships.get('moderator')) : false
|
||||
const groupId = !!group ? group.get('id') : ''
|
||||
const slug = !!group ? !!group.get('slug') ? `g/${group.get('slug')}` : undefined : undefined
|
||||
const isPrivate = !!group ? group.get('is_private') : false
|
||||
@@ -129,18 +129,18 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
||||
<Text size='small' color='inherit' className={_s.px5}>?</Text>
|
||||
</Button>
|
||||
</GroupInfoPanelRow>
|
||||
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
<GroupInfoPanelRow title={intl.formatMessage(messages.members)} icon='group'>
|
||||
<Button
|
||||
isText
|
||||
color={isAdmin ? 'brand' : 'primary'}
|
||||
color={isAdminOrMod ? 'brand' : 'primary'}
|
||||
backgroundColor='none'
|
||||
className={_s.mlAuto}
|
||||
to={isAdmin ? `/groups/${groupId}/members` : undefined}
|
||||
to={isAdminOrMod ? `/groups/${groupId}/members` : undefined}
|
||||
>
|
||||
<Text color='inherit' weight={isAdmin ? 'medium' : 'normal'} size='normal' className={isAdmin ? _s.underline_onHover : undefined}>
|
||||
<Text color='inherit' weight={isAdminOrMod ? 'medium' : 'normal'} size='normal' className={isAdminOrMod ? _s.underline_onHover : undefined}>
|
||||
{shortNumberFormat(group.get('member_count'))}
|
||||
|
||||
{intl.formatMessage(messages.members)}
|
||||
@@ -186,9 +186,14 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
||||
{
|
||||
tags.map((tag) => (
|
||||
<div className={[_s.mr5, _s.mb5].join(' ')}>
|
||||
<Text size='small' className={[_s.bgSecondary, _s.radiusSmall, _s.px10, _s.py2, _s.lineHeight15].join(' ')}>
|
||||
{tag}
|
||||
</Text>
|
||||
<NavLink
|
||||
to={`/groups/browse/tags/${slugify(tag)}`}
|
||||
className={_s.noUnderline}
|
||||
>
|
||||
<Text size='small' className={[_s.bgSecondary, _s.radiusSmall, _s.px10, _s.py2, _s.lineHeight15].join(' ')}>
|
||||
{tag}
|
||||
</Text>
|
||||
</NavLink>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user