diff --git a/src/components/App.js b/src/components/App.js index 576f574..3f9a228 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -60,7 +60,7 @@ class App extends Component { if (options.timeToClose > 0) { const delay = options.timeToClose * 60 * 1000; this.disconnectingEvent = setTimeout( - () => this.props.dispatch(AppUIActions.disconnectUser()), + () => window.location.reload(), delay ); } diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js index f9637ff..973e259 100644 --- a/src/components/Sidebar.js +++ b/src/components/Sidebar.js @@ -1,12 +1,10 @@ -import React, { useCallback } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import React from 'react'; +import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import { Link } from 'react-router-dom'; import { NavLink } from 'react-router-dom'; import moment from 'moment'; -import { disconnectUser } from 'slices/AppUISlice'; - import secretin from 'utils/secretin'; import Icon from 'components/utilities/Icon'; @@ -57,10 +55,6 @@ function exportDb() { } function Sidebar() { - const dispatch = useDispatch(); - const handleLogout = useCallback(() => { - dispatch(disconnectUser()); - }, [dispatch]); const currentUser = useSelector(state => state.AppUI.currentUser); const isOnline = useSelector(state => state.AppUI.online); return ( @@ -113,7 +107,10 @@ function Sidebar() {
  • - + window.location.reload()} + > Log out diff --git a/src/components/options/OptionsContainer.js b/src/components/options/OptionsContainer.js index 6c653a0..ef56e43 100644 --- a/src/components/options/OptionsContainer.js +++ b/src/components/options/OptionsContainer.js @@ -25,6 +25,15 @@ class OptionsContainer extends Component { constructor(props) { super(props); this.onChangeTimeToClose = this.onChangeTimeToClose.bind(this); + this.onChangeDefaultUsername = this.onChangeDefaultUsername.bind(this); + this.onSaveDefaultUsername = this.onSaveDefaultUsername.bind(this); + this.state = { + defaultUsername: props.options.defaultUsername, + }; + } + + onChangeDefaultUsername({ value }) { + this.setState({ defaultUsername: value }); } onChangeTimeToClose({ value }) { @@ -33,8 +42,18 @@ class OptionsContainer extends Component { }); } + onSaveDefaultUsername() { + this.props.actions.changeDefaultUsername({ + defaultUsername: this.state.defaultUsername, + }); + } + render() { - const { options, isOnline } = this.props; + const { + options, + isOnline, + options: { defaultUsername = '' }, + } = this.props; return (
    @@ -44,6 +63,37 @@ class OptionsContainer extends Component {
    +
    +

    Experience

    +
    + +
    + +
    +
    +
    +

    Security

    diff --git a/src/models/SecretDataRecord.js b/src/models/SecretDataRecord.js index 41e82be..889815b 100644 --- a/src/models/SecretDataRecord.js +++ b/src/models/SecretDataRecord.js @@ -1,5 +1,4 @@ import SecretFieldRecord from 'models/SecretFieldRecord'; -import { Utils } from 'secretin'; class SecretDataRecord { constructor(raw = {}) { @@ -22,12 +21,6 @@ class SecretDataRecord { static createWithDefaultFields(defaultFields) { return defaultFields.reduce((record, field) => { - if (field.type === 'password') { - return record.addNewField({ - ...field, - content: Utils.PasswordGenerator.generatePassword(), - }); - } return record.addNewField(field); }, new SecretDataRecord()); } diff --git a/src/slices/AppUISlice.js b/src/slices/AppUISlice.js index 8c19060..608d4ee 100644 --- a/src/slices/AppUISlice.js +++ b/src/slices/AppUISlice.js @@ -120,8 +120,7 @@ export const { } = AppUISlice.actions; export const disconnectUser = () => dispatch => { - secretin.currentUser.disconnect(); - dispatch(disconnectUserSuccess()); + window.location.reload(); }; export const createUser = ({ diff --git a/src/slices/EditSecretUISlice.js b/src/slices/EditSecretUISlice.js index 869c1a9..1987e52 100644 --- a/src/slices/EditSecretUISlice.js +++ b/src/slices/EditSecretUISlice.js @@ -3,13 +3,18 @@ import { createSlice } from '@reduxjs/toolkit'; import { showSecretSuccess } from 'slices/ShowSecretUISlice'; import { hideModal } from 'slices/ShowSecretUISlice'; import { updateSecretSuccess } from 'slices/MetadataSlice'; +import { disconnectUserSuccess } from 'slices/AppUISlice'; -export const EditSecretUISlice = createSlice({ - name: 'EditSecretUI', - initialState: { +function getInitialState() { + return { isEditing: false, data: null, - }, + }; +} + +export const EditSecretUISlice = createSlice({ + name: 'EditSecretUI', + initialState: getInitialState(), reducers: { updateData: (state, action) => { state.isEditing = false; @@ -36,6 +41,7 @@ export const EditSecretUISlice = createSlice({ [updateSecretSuccess]: state => { state.isEditing = false; }, + [disconnectUserSuccess]: getInitialState, }, }); diff --git a/src/slices/ImportSlice.js b/src/slices/ImportSlice.js index f69a5f7..0199582 100644 --- a/src/slices/ImportSlice.js +++ b/src/slices/ImportSlice.js @@ -1,6 +1,7 @@ import { createSlice } from '@reduxjs/toolkit'; import importers from 'utils/importers'; import { findKey } from 'lodash'; +import { disconnectUserSuccess } from 'slices/AppUISlice'; const getInitialState = () => ({ importType: '', @@ -80,6 +81,9 @@ export const ImportSlice = createSlice({ state.mandatoryFields[field.name].value = value; }, }, + extraReducers: { + [disconnectUserSuccess]: getInitialState, + }, }); // Action creators are generated for each case reducer function diff --git a/src/slices/MetadataSlice.js b/src/slices/MetadataSlice.js index 3fca334..48e7993 100644 --- a/src/slices/MetadataSlice.js +++ b/src/slices/MetadataSlice.js @@ -1,6 +1,7 @@ import secretin, { Errors } from 'utils/secretin'; import { createSlice } from '@reduxjs/toolkit'; import Secret from 'models/Secret'; +import { disconnectUserSuccess } from 'slices/AppUISlice'; import { createSecretSuccess, @@ -43,11 +44,15 @@ const _rebuildMetadata = (state, action) => { state.knownFriendList = Array.from(friendList).sort(); }; +function getInitialState() { + return { + metadata: [], + }; +} + export const MetadataSlice = createSlice({ name: 'Metadata', - initialState: { - metadata: [], - }, + initialState: getInitialState(), reducers: { loadMetadataSuccess: _rebuildMetadata, deleteSecretSuccess: _rebuildMetadata, @@ -82,6 +87,7 @@ export const MetadataSlice = createSlice({ extraReducers: { [createSecretSuccess]: _rebuildMetadata, [loginUserSuccess]: _rebuildMetadata, + [disconnectUserSuccess]: getInitialState, }, }); diff --git a/src/slices/NewSecretUISlice.js b/src/slices/NewSecretUISlice.js index 4549e95..27b9028 100644 --- a/src/slices/NewSecretUISlice.js +++ b/src/slices/NewSecretUISlice.js @@ -1,7 +1,9 @@ import { createSlice } from '@reduxjs/toolkit'; import SecretDataRecord from 'models/SecretDataRecord'; -import { createSecretSuccess } from 'slices/AppUISlice'; +import { createSecretSuccess, disconnectUserSuccess } from 'slices/AppUISlice'; +import secretin from 'utils/secretin'; +import { Utils } from 'secretin'; const getInitialState = () => ({ shown: false, @@ -23,6 +25,17 @@ export const NewSecretUISlice = createSlice({ state.title = `Untitled ${isFolder ? 'folder' : 'secret'}`; state.folder = folder; state.isFolder = isFolder; + const loginIndex = state.data.fields.findIndex( + fieldToUpdate => fieldToUpdate.label === 'login' + ); + const passwordIndex = state.data.fields.findIndex( + fieldToUpdate => fieldToUpdate.label === 'password' + ); + state.data.fields[loginIndex].content = + secretin.currentUser.options?.defaultUsername ?? ''; + state.data.fields[ + passwordIndex + ].content = Utils.PasswordGenerator.generatePassword(); }, hideModal: () => getInitialState(), changeTitle: (state, action) => { @@ -38,7 +51,8 @@ export const NewSecretUISlice = createSlice({ }, }, extraReducers: { - [createSecretSuccess]: () => getInitialState(), + [createSecretSuccess]: getInitialState, + [disconnectUserSuccess]: getInitialState, }, }); diff --git a/src/slices/OptionsSlice.js b/src/slices/OptionsSlice.js index 36ef15b..75692db 100644 --- a/src/slices/OptionsSlice.js +++ b/src/slices/OptionsSlice.js @@ -2,7 +2,11 @@ import { createSlice } from '@reduxjs/toolkit'; import secretin from 'utils/secretin'; import uuid from 'uuid'; -import { loginUserSuccess } from 'slices/AppUISlice'; +import { + loginUserSuccess, + createUserSuccess, + disconnectUserSuccess, +} from 'slices/AppUISlice'; const getInitialState = () => ({ options: {}, @@ -91,6 +95,11 @@ export const OptionsSlice = createSlice({ state.options.timeToClose = timeToClose; }, + changeDefaultUsernameSuccess: (state, action) => { + const { defaultUsername } = action.payload; + state.options.defaultUsername = defaultUsername; + }, + changeNewPass1: (state, action) => { const newPass1 = action.payload; state.newPass.newPass1 = newPass1.value; @@ -152,6 +161,8 @@ export const OptionsSlice = createSlice({ const { options } = action.payload; state.options = options; }, + [createUserSuccess]: getInitialState, + [disconnectUserSuccess]: getInitialState, }, }); @@ -169,6 +180,7 @@ export const { deactivateShortLoginSuccess, activateShortLoginSuccess, changeDelaySuccess, + changeDefaultUsernameSuccess, changeNewPass1, changeNewPass2, showChangePassword, @@ -282,6 +294,22 @@ export const toggleAutoLogout = ({ checked }) => (dispatch, getState) => { return dispatch(changeTimeToClose({ timeToClose: delay })); }; +export const changeDefaultUsername = ({ defaultUsername }) => ( + dispatch, + getState +) => { + secretin + .editOption('defaultUsername', defaultUsername) + .then(() => { + dispatch(changeDefaultUsernameSuccess({ defaultUsername })); + }) + .catch(() => { + // Currently the UI can't display this error anyway + // dispatch(changeDelayFailure()); + }); + return true; +}; + export const changeTimeToClose = ({ timeToClose }) => (dispatch, getState) => { secretin .editOption('timeToClose', timeToClose) diff --git a/src/slices/ShowSecretUISlice.js b/src/slices/ShowSecretUISlice.js index 159f5ee..2302b42 100644 --- a/src/slices/ShowSecretUISlice.js +++ b/src/slices/ShowSecretUISlice.js @@ -10,6 +10,8 @@ import { deleteSecretUserRightsSuccess, } from 'slices/MetadataSlice'; +import { disconnectUserSuccess } from 'slices/AppUISlice'; + const getInitialState = () => ({ secret: null, errors: {}, @@ -101,6 +103,7 @@ export const ShowSecretUISlice = createSlice({ state.isUpdating = false; state.errors = {}; }, + [disconnectUserSuccess]: getInitialState, }, }); diff --git a/src/stylesheets/components/options/OptionsContainer.sass b/src/stylesheets/components/options/OptionsContainer.sass index 1e357db..355718c 100644 --- a/src/stylesheets/components/options/OptionsContainer.sass +++ b/src/stylesheets/components/options/OptionsContainer.sass @@ -13,3 +13,6 @@ .options-section-subitem margin: 0 0 20px padding-left: 32px + +.options-section-subitem-save + margin: 10px 0 20px \ No newline at end of file