diff --git a/web_hosting_manager/README.md b/web_hosting_manager/README.md index 5041c9a..4345736 100644 --- a/web_hosting_manager/README.md +++ b/web_hosting_manager/README.md @@ -68,6 +68,11 @@ To run the application without packaging run $ npm run build $ npm start ``` +#### Clear Access Data +#####macOs + Click `SAFE Hosting Manager -> Clear Access Data` from the menu. +#####Windows and Linux + Click `File -> Clear Access Data` from the menu. # License diff --git a/web_hosting_manager/app/actions/actionTypes.js b/web_hosting_manager/app/actions/actionTypes.js index 8cdcb3f..33bad11 100644 --- a/web_hosting_manager/app/actions/actionTypes.js +++ b/web_hosting_manager/app/actions/actionTypes.js @@ -1,4 +1,5 @@ const ACTION_TYPES = { + CLEAR_ACCESS_DATA: 'CLEAR_ACCESS_DATA', RESET: 'RESET', AUTH_REQUEST_SENT: 'AUTH_REQUEST_SENT', AUTH_REQUEST_SEND_FAILED: 'AUTH_REQUEST_SEND_FAILED', diff --git a/web_hosting_manager/app/actions/app.js b/web_hosting_manager/app/actions/app.js index 8c0aa1c..a27d41b 100644 --- a/web_hosting_manager/app/actions/app.js +++ b/web_hosting_manager/app/actions/app.js @@ -1,8 +1,10 @@ // @flow -import * as api from '../lib/api'; +import api from '../lib/api'; import { I18n } from 'react-redux-i18n'; import ACTION_TYPES from './actionTypes'; +import CONSTANTS from '../lib/constants'; +import * as utils from '../lib/utils'; const sendAuthRequest = () => { const action = api.authorise() ? ACTION_TYPES.AUTH_REQUEST_SENT : ACTION_TYPES.AUTH_REQUEST_SEND_FAILED; @@ -24,19 +26,14 @@ export const revoked = () => { }; export const connect = (authRes: String) => { - if (!authRes && !api.hasLocalAuthInfo()) { + if (!authRes && !utils.localAuthInfo.get()) { return sendAuthRequest(); } return (dispatch) => { return dispatch({ type: ACTION_TYPES.CONNECT, payload: api.connect(authRes) - .then((resType) => { - if (resType === api.AUTH_RES_TYPES.revoked) { - return dispatch(revoked()); - } - }) - }) + }); }; }; @@ -56,7 +53,7 @@ export const onAuthFailure = (error: Object) => { export const getAccessInfo = () => { return { type: ACTION_TYPES.FETCH_ACCESS_INFO, - payload: api.fetchAccessInfo() + payload: api.canAccessContainers() }; }; @@ -70,7 +67,7 @@ export const getPublicNames = () => { export const createPublicId = (publicId: string) => { return { type: ACTION_TYPES.CREATE_PUBLIC_ID, - payload: api.createPublicId(publicId) + payload: api.createPublicName(publicId) .then(() => { return api.fetchPublicNames(publicId); }) @@ -82,10 +79,10 @@ export const createContainerAndService = (publicId: string, service: string, const path = `${parentConatiner}/${publicId}/${conatinerName}`; return { type: ACTION_TYPES.CREATE_CONTAINER_AND_SERVICE, - payload: api.checkServiceExist(publicId, service, path) + payload: api.updateServiceIfExist(publicId, service, path) .then((exist) => { if (!exist) { - return api.createContainer(path) + return api.createServiceContainer(path) .then((name) => { return api.createService(publicId, service, name); }); @@ -99,7 +96,9 @@ export const createContainerAndService = (publicId: string, service: string, export const createService = (publicId: string, service: string, containerPath: string) => { return { type: ACTION_TYPES.CREATE_SERVICE, - payload: api.createService(publicId, service, containerPath) + payload: api.getServiceContainerMeta(containerPath) + .then((meta) => api.createService(publicId, service, meta.name)) + .then(() => api.fetchServices()) }; }; @@ -121,14 +120,14 @@ export const getServices = () => { export const getPublicContainers = () => { return { type: ACTION_TYPES.FETCH_PUBLIC_CONTAINERS, - payload: api.getPublicContainers() + payload: api.getPublicContainerKeys() }; }; export const remapService = (service: string, publicId: string, containerPath: string) => { return { type: ACTION_TYPES.REMAP_SERVICE, - payload: api.remapService(service, publicId, containerPath) + payload: api.remapService(publicId, service, containerPath) .then(() => api.fetchServices()) }; }; @@ -136,7 +135,7 @@ export const remapService = (service: string, publicId: string, containerPath: s export const getContainer = (containerPath: string) => { return { type: ACTION_TYPES.FETCH_CONTAINER, - payload: api.getContainer(containerPath) + payload: api.getServiceContainer(containerPath) }; }; @@ -157,7 +156,7 @@ export const upload = (localPath: string, networkPath: string) => { payload: error }); }; - api.upload(localPath, networkPath, progressCallback, errorCallback); + api.fileUpload(localPath, networkPath, progressCallback, errorCallback); dispatch({ type: ACTION_TYPES.UPLOAD_STARTED }); @@ -165,7 +164,7 @@ export const upload = (localPath: string, networkPath: string) => { }; export const cancelUpload = () => { - api.cancelUpload(); + api.cancelFileUpload(); const err = new Error(I18n.t('messages.uploadCancelled')); return { type: ACTION_TYPES.UPLOAD_FAILED, @@ -178,7 +177,7 @@ export const download = (networkPath: string) => { dispatch({ type: ACTION_TYPES.DOWNLOAD_STARTED }); - api.download(networkPath, (err, status) => { + api.fileDownload(networkPath, (err, status) => { if (err) { return dispatch({ type: ACTION_TYPES.DOWNLOAD_FAILED, @@ -194,7 +193,7 @@ export const download = (networkPath: string) => { }; export const cancelDownload = () => { - api.cancelDownload(); + api.cancelFileDownload(); const err = new Error(I18n.t('messages.downloadCancelled')); return { type: ACTION_TYPES.DOWNLOAD_FAILED, @@ -205,9 +204,9 @@ export const cancelDownload = () => { export const deleteItem = (containerPath, name) => { return { type: ACTION_TYPES.DELETE, - payload: api.deleteItem(`${containerPath}/${name}`) + payload: api.deleteFileOrDir(`${containerPath}/${name}`) .then(() => { - return api.getContainer(containerPath); + return api.getServiceContainer(containerPath); }) }; }; @@ -217,3 +216,10 @@ export const clearNotification = () => { type: ACTION_TYPES.CLEAR_NOTIFICATION } }; + +export const clearAccessData = () => { + utils.localAuthInfo.clear(); + return { + type: ACTION_TYPES.CLEAR_ACCESS_DATA + }; +}; diff --git a/web_hosting_manager/app/components/Auth.js b/web_hosting_manager/app/components/Auth.js index 2a153c1..ad15a82 100644 --- a/web_hosting_manager/app/components/Auth.js +++ b/web_hosting_manager/app/components/Auth.js @@ -5,28 +5,26 @@ import { I18n } from 'react-redux-i18n'; export default class Auth extends Component { componentDidMount() { - if (!this.props.isRevoked) { - this.props.connect(); - } + this.props.connect(); } componentWillUpdate(props) { - if (!this.props.isRevoked && props.fetchedServices && !props.serviceError) { + if (props.fetchedServices && !props.serviceError) { props.router.replace('/home'); } } componentDidUpdate() { - if (this.props.isConnected && !this.props.fetchedAccessInfo && !this.props.accessInfoError) { + if (this.props.isConnected && !this.props.fetchingAccessInfo && !this.props.fetchedAccessInfo && !this.props.accessInfoError) { return this.props.getAccessInfo(); } - if (this.props.fetchedAccessInfo && !this.props.fetchedPublicNames && !this.props.publicNameError) { + if (this.props.fetchedAccessInfo && !this.props.fetchingPublicNames && !this.props.fetchedPublicNames && !this.props.publicNameError) { return this.props.getPublicNames(); } - if (this.props.fetchedPublicNames && !this.props.fetchedPublicContainers && !this.props.publicContainersError) { + if (this.props.fetchedPublicNames && !this.props.fetchingPublicContainers && !this.props.fetchedPublicContainers && !this.props.publicContainersError) { return this.props.getPublicContainers(); } - if (this.props.fetchedPublicContainers && !this.props.fetchedServices && !this.props.serviceError) { + if (this.props.fetchedPublicContainers && !this.props.fetchingServices && !this.props.fetchedServices && !this.props.serviceError) { return this.props.getServices(); } } diff --git a/web_hosting_manager/app/components/CreateService.js b/web_hosting_manager/app/components/CreateService.js index 8321459..019696e 100644 --- a/web_hosting_manager/app/components/CreateService.js +++ b/web_hosting_manager/app/components/CreateService.js @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Button, Card, Input, Select, Icon } from 'antd'; import { I18n } from 'react-redux-i18n'; +import { domainCheck } from '../utils/app_utils'; import Nav from './Nav'; @@ -35,7 +36,8 @@ export default class CreateService extends Component { isCreatingContainerAndService: false }); } else if (this.props.creatingService && !nextProps.creatingService) { - this.props.router.goBack(); + const servicePath = this.state.isCreatingContainerAndService ? `_public/${this.props.params.publicId}/${this.state.containerName}` : this.containerName; + this.props.router.replace(`files/${this.state.serviceName}/${this.props.params.publicId}/${encodeURIComponent(servicePath)}`); } } @@ -63,6 +65,11 @@ export default class CreateService extends Component { containerError: containerNameErrorMsg }); valid = false; + } else if(!domainCheck(this.state.serviceName)) { + this.setState({ + serviceError: I18n.t('messages.serviceNameInvalid') + }); + valid = false; } return valid; } @@ -192,4 +199,4 @@ CreateService.propTypes = { createContainerAndService: PropTypes.func.isRequired, createService: PropTypes.func.isRequired, getPublicContainers: PropTypes.func.isRequired, -} +}; diff --git a/web_hosting_manager/app/components/Home.js b/web_hosting_manager/app/components/Home.js index 48e1c9e..8393ad5 100644 --- a/web_hosting_manager/app/components/Home.js +++ b/web_hosting_manager/app/components/Home.js @@ -5,6 +5,7 @@ import ReactDOM from 'react-dom'; import { I18n } from 'react-redux-i18n'; import { Link } from 'react-router'; import NetworkStatus from './NetworkStatus'; +import { domainCheck } from '../utils/app_utils'; import Nav from './Nav'; @@ -14,7 +15,8 @@ export default class Auth extends Component { this.state = { newPublicId: '', publicIdVisible: false, - showRemapModal: false + showRemapModal: false, + publicNameErr: '' }; this.remap = { containerName: '', @@ -31,9 +33,6 @@ export default class Auth extends Component { } componentWillUpdate(nextProps) { - if (nextProps.isRevoked) { - nextProps.router.replace('/'); - } if (nextProps.fetchingPublicContainers) { this.reloadingContainer = true; } @@ -54,6 +53,9 @@ export default class Auth extends Component { } createPublicId() { + if (!domainCheck(this.state.newPublicId)) { + return this.setState({ publicNameErr: I18n.t('messages.publicNameInvalid') }); + } if (this.props.creatingPublicId) { return; } @@ -61,8 +63,10 @@ export default class Auth extends Component { } cancelpublicId() { + this.setState({ publicNameErr: null }); this.refs.publicId.refs.input.value = ''; this.resetPublicIdModal(); + this.props.clearNotification(); } resetPublicIdModal() { @@ -102,7 +106,7 @@ export default class Auth extends Component { placeholder={I18n.t('label.enterPublicId')} onPressEnter={this.createPublicId.bind(this)} /> -
{this.props.creatingPublicId ? '' : this.props.publicIdError}
+
{this.props.creatingPublicId ? '' : this.props.publicIdError || this.state.publicNameErr}
@@ -174,6 +178,7 @@ export default class Auth extends Component { this.setState({ showRemapModal: false }); + this.props.clearNotification(); } showRemapModal(service, publicId) { @@ -200,7 +205,7 @@ export default class Auth extends Component { defaultValue={this.state.newPublicId} placeholder={I18n.t('messages.publicIdPlaceholder')} onPressEnter={this.createPublicId.bind(this)} /> -
{this.props.creatingPublicId ? '' : this.props.publicIdError}
+
{this.props.creatingPublicId ? '' : this.props.publicIdError || this.state.publicNameErr}