Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hiding Database URL #621

Open
wants to merge 6 commits into
base: production2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 124 additions & 51 deletions src/dashboard/Settings/Collaborators.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ export default class Collaborators extends React.Component {
super();

const defaultFeaturesPermissions = {
'coreSettings' : 'Read',
'manageParseServer' : 'Read',
'logs' : 'Read',
'cloudCode' : 'Write',
'jobs' : 'Write',
'webHostLiveQuery' : 'Write',
'verificationEmails' : 'Write',
'oauth' : 'Write',
'twitterOauth' : 'Write',
'pushAndroidSettings' : 'Write',
'pushIOSSettings' : 'Write'
'coreSettings': 'Read',
'manageParseServer': 'Read',
'logs': 'Read',
'cloudCode': 'Write',
'jobs': 'Write',
'webHostLiveQuery': 'Write',
'verificationEmails': 'Write',
'oauth': 'Write',
'twitterOauth': 'Write',
'pushAndroidSettings': 'Write',
'pushIOSSettings': 'Write'
}

this.defaultFeaturesPermissions = defaultFeaturesPermissions
Expand All @@ -88,7 +88,10 @@ export default class Collaborators extends React.Component {
lastSuccess: '',
currentEmailInput: '',
inviteCollab: false,
showBtnCollaborator: false
showBtnCollaborator: false,
permissions: {},
collaboratorUsage: '',
maxCollaborators: ''
};
}

Expand All @@ -101,15 +104,16 @@ export default class Collaborators extends React.Component {
handleAdd() {
//TODO: Show some in-progress thing while the collaborator is being validated, or maybe have some sort of
//async validator in the parent form. Currently if you mash the add button, they same collaborator gets added many times.
this.setState({lastError: '', lastSuccess: '', showBtnCollaborator: false });
this.setState({ lastError: '', lastSuccess: '', showBtnCollaborator: false });
return this.context.validateCollaborator(this.state.currentEmail).then((response) => {
// lastError logic assumes we only have 1 input field
if (response.success) {
this.setState({
showDialog: true,
toAdd: true,
lastError: '',
inviteCollab: false
inviteCollab: false,
collaboratorUsage: this.context.settings.fields.fields.collaboratorUsage
});
return true;
} else if (response.error) {
Expand All @@ -134,7 +138,7 @@ export default class Collaborators extends React.Component {
{message}
{this.state.inviteCollab ?
<span> -&nbsp;
<a onClick={() => {this.setState({showDialog: true})}} className={styles.sendInviteBtn}>Send Invite</a>
<a onClick={() => { this.setState({ showDialog: true }) }} className={styles.sendInviteBtn}>Send Invite</a>
</span>
: null}
</div>
Expand All @@ -145,7 +149,7 @@ export default class Collaborators extends React.Component {
sendInvite(featuresPermission, classesPermission, owner) {
return this.context.sendEmailToInviteCollaborator(this.state.currentEmail, featuresPermission, classesPermission, owner).then((response) => {
if (response.status === 200) {
this.setState({ lastError: '', inviteCollab: false, showDialog: false, lastSuccess: 'The invite has been sent!', currentEmail: '', showBtnCollaborator: false, waiting_collaborators: response.data.response });
this.setState({ lastError: '', inviteCollab: false, showDialog: false, lastSuccess: 'The invite has been sent!', currentEmail: '', showBtnCollaborator: false, waiting_collaborators: response.data.response, collaboratorUsage: response.data.data.collaboratorUsage });
setTimeout(() => {
this.setState({ lastSuccess: '' })
}, 5000);
Expand All @@ -156,7 +160,7 @@ export default class Collaborators extends React.Component {
});
}
}).catch(error => {
this.setState({showDialog: false, lastError: error.response.data.error || error.message || error.error, inviteCollab: false });
this.setState({ showDialog: false, lastError: error.response.data.error || error.message || error.error, inviteCollab: false });
});
}

Expand All @@ -169,7 +173,8 @@ export default class Collaborators extends React.Component {
showDialog: false,
lastSuccess: `The permission to ${this.state.currentEmailInput} has been updated!`,
currentEmailInput: '',
waiting_collaborators: response.data.response });
waiting_collaborators: response.data.response
});
setTimeout(() => {
this.setState({ lastSuccess: '' })
}, 5000);
Expand All @@ -180,18 +185,19 @@ export default class Collaborators extends React.Component {
});
}
}).catch(error => {
this.setState({showDialog: false, lastError: error.response.data.error || error.message || error.error, inviteCollab: false });
this.setState({ showDialog: false, lastError: error.response.data.error || error.message || error.error, inviteCollab: false });
});
}

handleRemoveInvite(collaborator) {
return this.context.removeInviteCollaborator(collaborator.userEmail).then((response) => {
this.setState({
waiting_collaborators: response.response
waiting_collaborators: response.response,
collaboratorUsage: response.data.collaboratorUsage ?? 0
})
});
}
handleEditInvitePermission(collaborator){
handleEditInvitePermission(collaborator) {
this.setState({
showDialog: true,
editInvitePermission: true,
Expand Down Expand Up @@ -253,7 +259,7 @@ export default class Collaborators extends React.Component {
return (
<PermissionsCollaboratorDialog
role='User'
email={this.state.currentEmail || this.state.currentEmailInput }
email={this.state.currentEmail || this.state.currentEmailInput}
description='Configure how this user can access the App features.'
advanced={false}
confirmText='Save'
Expand Down Expand Up @@ -334,7 +340,7 @@ export default class Collaborators extends React.Component {
editedCollab.classesPermission = classesPermission;
editedCollab.isEdited = true;
this.props.collaborators.forEach(c => {
if (c.userEmail === editedCollab.userEmail) {c = editedCollab}
if (c.userEmail === editedCollab.userEmail) { c = editedCollab }
newCollabs.push(c)
})
this.props.onEdit(editedCollab, newCollabs);
Expand All @@ -347,57 +353,88 @@ export default class Collaborators extends React.Component {
}
);
}
else if (this.state.inviteCollab){
else if (this.state.inviteCollab) {
this.sendInvite(featuresPermission, classesPermission, this.props.owner_email);
}
else if (this.state.editInvitePermission){
else if (this.state.editInvitePermission) {
this.editInvite(featuresPermission, classesPermission)
}
}} />
)
}

addCollaboratorField() {
const maxCollaborators = this.context.settings.fields.fields.maxCollaborators;
const collaboratorUsage = this.context.settings.fields.fields.collaboratorUsage || 0

return (
<Field
labelWidth={55}
label={<Label
dark={true}
text='Add new collaborator'
description={<span>Collaborators will have read/write access but cannot <br /> delete the app or add more collaborators.</span>} />}
input={<InlineSubmitInput
render={() => {
return <div style={{ width: '100%', padding: '0 1rem' }}><TextInput
placeholder="What&#39;s their email?"
value={this.state.currentEmail}
onChange={(value)=> {
this.setState({currentEmail: value, showBtnCollaborator: this.validateEmail(value)});
}}
/></div>
}}
showButton={this.state.showBtnCollaborator}
validate={(email) => {
if (this.state.showBtnCollaborator === true) {
return true;
label={
<Label
dark={true}
text='Add new collaborator'
description={
<span>
Collaborators will have read/write access but cannot
<br />
delete the app or add more collaborators.
</span>
}
return this.validateEmail(email);
}}
onSubmit={this.handleAdd.bind(this)}
submitButtonText='ADD' />}
/>
}
input={
<div style={{ width: '100%', padding: '0 1rem' }}>
{maxCollaborators !== true && maxCollaborators !== null && collaboratorUsage >= maxCollaborators ? (
<a
href="https://www.back4app.com/pricing/backend-as-a-service"
target="_blank"
rel="noopener noreferrer"
>
Add More Spots
</a>
) : (
<InlineSubmitInput
render={() => (
<TextInput
placeholder="What&#39;s their email?"
value={this.state.currentEmail}
onChange={(value) => {
this.setState({
currentEmail: value,
showBtnCollaborator: this.validateEmail(value),
});
}}
disabled={false}
/>
)}
showButton={this.state.showBtnCollaborator}
validate={(email) => {
if (this.state.showBtnCollaborator === true) {
return true;
}
return this.validateEmail(email);
}}
onSubmit={this.handleAdd.bind(this)}
submitButtonText="ADD"
/>
)}
</div>
}
theme={Field.Theme.BLUE}
/>
)
);
}

listAppOwnerEmail() {
return(
return (
<Field
labelWidth={55}
label={<Label text='App Owner' dark={true} />}
input={<div style={{ width: '100%', padding: '0 1rem' }}>
<TextInput
value={this.props.owner_email}
onChange={() => {}}
onChange={() => { }}
disabled={true}
/>
</div>}
Expand Down Expand Up @@ -455,8 +492,42 @@ export default class Collaborators extends React.Component {
}

render() {
const maxCollaborators = this.context.settings.fields.fields.maxCollaborators;
const collaboratorUsage = this.context.settings.fields.fields.collaboratorUsage || 0

return (
<Fieldset legend={this.props.legend} description={this.props.description}>
<Fieldset
legend={
this.props.legend
&& (
`${this.props.legend} ${maxCollaborators !== true && maxCollaborators !== null && maxCollaborators > 0
? `${collaboratorUsage} / ${maxCollaborators}`
: ''
}`
)
}
description={
<>
{maxCollaborators !== true && maxCollaborators !== null && maxCollaborators > 0 && (
<>
<strong>
{maxCollaborators - collaboratorUsage >= 0
? `${maxCollaborators - collaboratorUsage} remaining.`
: "You reached your plan limit"}
</strong>{' '}
Need more?{' '}
<strong>
<a href="https://www.back4app.com/pricing/backend-as-a-service" target="_blank" rel="noopener noreferrer">
Add More Spots
</a>
</strong>
<br />
</>
)}
{this.props.description}
</>
}
>
{this.props.viewer_email === this.props.owner_email ? this.addCollaboratorField() : this.listAppOwnerEmail()}
{this.state.lastSuccess !== '' ? this.displayMessage('green', this.state.lastSuccess) : null}
{this.state.lastError !== '' ? this.displayMessage('red', this.state.lastError) : null}
Expand Down Expand Up @@ -488,4 +559,6 @@ Collaborators.propTypes = {
onRemove: PropTypes.func.isRequired.describe(
'A function that will be called whenever a user removes a valid collaborator email. It receives the removed email and an updated array of all collaborators for this app.'
),
permissions: PropTypes.object.describe('App permissions'),
collaboratorUsage: PropTypes.number.describe('limit of collaborators'),
};
9 changes: 9 additions & 0 deletions src/dashboard/Settings/Fields/CollaboratorsFields.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@ import PropTypes from 'lib/PropTypes';
export const CollaboratorsFields = ({
collaborators,
waiting_collaborators,
permissions,
ownerEmail,
viewerEmail,
addCollaborator,
removeCollaborator,
editCollaborator,
collaboratorUsage,
maxCollaborators
}) => {
return <Collaborators
legend='Collaborators'
description='Team up and work together with other people.'
collaborators={collaborators}
waiting_collaborators={waiting_collaborators}
permissions={permissions}
collaboratorUsage={collaboratorUsage}
maxCollaborators={maxCollaborators}
owner_email={ownerEmail}
viewer_email={viewerEmail}
onAdd={addCollaborator}
Expand All @@ -26,6 +32,9 @@ export const CollaboratorsFields = ({
CollaboratorsFields.propTypes = {
collaborators: PropTypes.arrayOf(PropTypes.object).isRequired,
waiting_collaborators: PropTypes.any,
permissions: PropTypes.object,
collaboratorUsage: PropTypes.number,
maxCollaborators: PropTypes.number,
ownerEmail: PropTypes.string,
viewerEmail: PropTypes.viewerEmail,
addCollaborator: PropTypes.func.isRequired,
Expand Down
6 changes: 4 additions & 2 deletions src/dashboard/Settings/Fields/ManageAppFields.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const ManageAppFields = ({
mongoVersion,
errors,
isGDPR,
permissions,
databaseVersion,
useLatestDashboardVersion,
setUseLatestDashboardVersion,
Expand Down Expand Up @@ -74,7 +75,7 @@ export const ManageAppFields = ({
input={
<div style={{ flex: 1 }}>
{
(isGDPR !== true) &&
(isGDPR !== true && permissions.hideDatabaseURL !== true) &&
<div style={{ padding: '11px 0' }}>
<B4aKeyField name="Show Database" hidden={true} showKeyName={true} keyText="URI">
{databaseURL}
Expand Down Expand Up @@ -314,5 +315,6 @@ ManageAppFields.propTypes = {
databaseVersion: PropTypes.string.describe('Database version'),
mongoVersion: PropTypes.string.describe('Database version'),
errors: PropTypes.array.describe('An array of errors'),
isGDPR: PropTypes.bool.isRequired.describe('GDPR app identifier')
isGDPR: PropTypes.bool.isRequired.describe('GDPR app identifier'),
permissions: PropTypes.object.describe('App permissions')
}
2 changes: 2 additions & 0 deletions src/dashboard/Settings/GeneralSettings.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export default class GeneralSettings extends DashboardView {
parseVersion: this.context.settings.fields.fields.parseVersion,
mongoVersion: this.context.settings.fields.fields.mongoVersion,
databaseVersion: this.context.settings.fields.fields.databaseVersion,
permissions: this.context.settings.fields.fields.permissions,
clientPush: this.context.settings.fields.fields.clientPush,
clientClassCreation: this.context.settings.fields.fields.clientClassCreation,
useLatestDashboardVersion: this.context.useLatestDashboardVersion
Expand Down Expand Up @@ -168,6 +169,7 @@ export default class GeneralSettings extends DashboardView {
cleanUpSystemLog={() => this.setState({showPurgeSystemLogModal: true})}
cleanUpSystemLogMessage={this.state.cleanupSystemLogMessage}
isGDPR={this.context.custom && this.context.custom.isGDPR}
permissions={fields.permissions}
useLatestDashboardVersion={fields.useLatestDashboardVersion}
setUseLatestDashboardVersion={setField.bind(this, 'useLatestDashboardVersion')}/>
<DangerzoneFields
Expand Down
Loading
Loading