diff --git a/app/client/mobile/src/constants/Strings.ts b/app/client/mobile/src/constants/Strings.ts
index 77c1834a..3531554c 100644
--- a/app/client/mobile/src/constants/Strings.ts
+++ b/app/client/mobile/src/constants/Strings.ts
@@ -31,6 +31,7 @@ const Strings = [
monthEnd: 'dd/mm',
error: 'Error',
tryAgain: 'Please try again.',
+ allDevices: 'Logout of all devices',
// seal wizard
sealUnset: 'Generate a key to enable end-to-end encrypted topics.',
@@ -246,6 +247,7 @@ const Strings = [
monthEnd: 'jj/mm',
error: 'Erreur',
tryAgain: 'Veuillez réessayer.',
+ allDevices: 'Déconnexion de tous les appareils',
messages: 'Messages',
sealUnset:
@@ -461,6 +463,7 @@ const Strings = [
monthEnd: 'dd/mm',
error: 'Error',
tryAgain: 'Inténtalo de nuevo.',
+ allDevices: 'Cerrar sesión en todos los dispositivos',
sealUnset:
'Genere una clave para habilitar temas cifrados de un extremo a otro.',
@@ -673,6 +676,7 @@ const Strings = [
monthEnd: 'dd/mm',
error: 'Fehler',
tryAgain: 'Bitte versuche es erneut.',
+ allDevices: 'Abmelden aller Geräte',
sealUnset:
'Generieren Sie einen Schlüssel, um Ende-zu-Ende-verschlüsselte Themen zu ermöglichen.',
@@ -1038,6 +1042,7 @@ const Strings = [
start: 'Crie Uma Conversa',
started: 'Iniciar',
+ allDevices: 'Sair de todos os dispositivos',
deleteMessage: 'Apagar Mensagem',
blockMessage: 'Bloquear Mensagem',
reportMessage: 'Denunciar Mensagem',
@@ -1183,6 +1188,7 @@ const Strings = [
guest: 'Гость',
leave: 'Покинуть',
members: 'Участники',
+ allDevices: 'Выход из всех устройств',
editSubject: 'Редактировать тему',
topicMembers: 'Участники темы',
leaveTopic: 'Покинуть тему',
diff --git a/app/client/mobile/src/context/useAppContext.hook.ts b/app/client/mobile/src/context/useAppContext.hook.ts
index 1b0caed0..a57e620c 100644
--- a/app/client/mobile/src/context/useAppContext.hook.ts
+++ b/app/client/mobile/src/context/useAppContext.hook.ts
@@ -77,12 +77,18 @@ export function useAppContext() {
);
updateState({session: login});
},
- accountLogout: async () => {
+ accountLogout: async (all: boolean) => {
if (state.session) {
- await sdk.current.logout(state.session, false);
+ await sdk.current.logout(state.session, all);
updateState({session: null});
}
},
+ accountRemove: async () => {
+ if (state.session) {
+ await sdk.current.remove(state.session);
+ updateState({ session: null });
+ }
+ },
accountCreate: async (
handle: string,
password: string,
diff --git a/app/client/mobile/src/settings/Settings.styled.ts b/app/client/mobile/src/settings/Settings.styled.ts
index b5b40ad3..a2ea1b45 100644
--- a/app/client/mobile/src/settings/Settings.styled.ts
+++ b/app/client/mobile/src/settings/Settings.styled.ts
@@ -28,6 +28,9 @@ export const styles = StyleSheet.create({
height: '100%',
gap: 8,
},
+ remove: {
+ backgroundColor: Colors.danger,
+ },
surface: {
padding: 16,
},
@@ -211,6 +214,14 @@ export const styles = StyleSheet.create({
fontSize: 16,
flexGrow: 1,
},
+ allControl: {
+ flexShrink: 1,
+ flexGrow: 1,
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingTop: 16,
+ },
control: {
flexShrink: 1,
flexGrow: 1,
diff --git a/app/client/mobile/src/settings/Settings.tsx b/app/client/mobile/src/settings/Settings.tsx
index b2d67d7a..ff40ac70 100644
--- a/app/client/mobile/src/settings/Settings.tsx
+++ b/app/client/mobile/src/settings/Settings.tsx
@@ -18,6 +18,10 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
const [auth, setAuth] = useState(false);
const [clear, setClear] = useState(false);
const [change, setChange] = useState(false);
+ const [logout, setLogout] = useState(false);
+ const [remove, setRemove] = useState(false);
+ const [applyingLogout, setApplyingLogout] = useState(false);
+ const [applyingRemove, setApplyingRemove] = useState(false);
const [sealDelete, setSealDelete] = useState(false);
const [sealReset, setSealReset] = useState(false);
const [sealConfig, setSealConfig] = useState(false);
@@ -70,6 +74,38 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
}
}
+ const applyRemove = async () => {
+ if (!applyingRemove) {
+ setApplyingRemove(true);
+ try {
+ await actions.remove();
+ setRemove(false);
+ }
+ catch (err) {
+ console.log(err);
+ setRemove(false);
+ setAlert(true);
+ }
+ setApplyingRemove(false);
+ }
+ }
+
+ const applyLogout = async () => {
+ if (!applyingLogout) {
+ setApplyingLogout(true);
+ try {
+ await actions.logout();
+ setLogout(false);
+ }
+ catch (err) {
+ console.log(err);
+ setLogout(false);
+ setAlert(true);
+ }
+ setApplyingLogout(false);
+ }
+ }
+
const setMfa = async (flag: boolean) => {
if (!savingAuth) {
setSavingAuth(true);
@@ -404,7 +440,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
- manageSeal}>
+ setLogout(true)}>
{state.strings.logout}
@@ -415,7 +451,7 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
- manageSeal}>
+ setRemove(true)}>
{state.strings.deleteAccount}
@@ -941,6 +977,75 @@ export function Settings({ showLogout }: { showLogout: boolean }) {
+ setLogout(false)}>
+
+
+
+
+ { state.strings.loggingOut }
+ setLogout(false)} />
+
+
+ {state.strings.allDevices}
+
+
+
+
+
+
+
+
+
+
+
+ setRemove(false)}>
+
+
+
+
+ { state.strings.deleteAccount }
+ setRemove(false)} />
+
+ }
+ onChangeText={value => actions.setRemove(value)}
+ />
+
+
+
+
+
+
+
+
+
>
);
diff --git a/app/client/mobile/src/settings/useSettings.hook.ts b/app/client/mobile/src/settings/useSettings.hook.ts
index 7739c78f..c0307745 100644
--- a/app/client/mobile/src/settings/useSettings.hook.ts
+++ b/app/client/mobile/src/settings/useSettings.hook.ts
@@ -19,6 +19,7 @@ export function useSettings() {
all: false,
password: '',
confirm: '',
+ remove: '',
username: '',
taken: false,
checked: true,
@@ -192,6 +193,9 @@ export function useSettings() {
logout: async () => {
await app.actions.accountLogout(state.all)
},
+ remove: async () => {
+ await app.actions.accountRemove()
+ },
setHandle: (handle: string) => {
updateState({ handle, taken: false, checked: false })
clearTimeout(debounce.current)
@@ -216,6 +220,9 @@ export function useSettings() {
setConfirm: (confirm: string) => {
updateState({ confirm })
},
+ setRemove: (remove: string) => {
+ updateState({ remove });
+ },
setName: (name: string) => {
updateState({ name })
},
diff --git a/app/client/web/src/context/useAppContext.hook.ts b/app/client/web/src/context/useAppContext.hook.ts
index c9fb2ad7..a2b01700 100644
--- a/app/client/web/src/context/useAppContext.hook.ts
+++ b/app/client/web/src/context/useAppContext.hook.ts
@@ -56,9 +56,9 @@ export function useAppContext() {
)
updateState({ session: login })
},
- accountLogout: async () => {
+ accountLogout: async (all: boolean) => {
if (state.session) {
- await sdk.current.logout(state.session, false)
+ await sdk.current.logout(state.session, all)
updateState({ session: null })
}
},
diff --git a/app/sdk/src/api.ts b/app/sdk/src/api.ts
index c777c024..1df6fb00 100644
--- a/app/sdk/src/api.ts
+++ b/app/sdk/src/api.ts
@@ -53,6 +53,7 @@ export interface Settings {
unlockSeal(password: string): Promise;
updaterSeal(password: string): Promise;
forgetSeal(): Promise;
+ deleteAccount(): Promise;
addConfigListener(ev: (config: Config) => void): void;
removeConfigListener(ev: (config: Config) => void): void;
diff --git a/app/sdk/src/index.ts b/app/sdk/src/index.ts
index 4359e3f7..f93cc385 100644
--- a/app/sdk/src/index.ts
+++ b/app/sdk/src/index.ts
@@ -5,6 +5,7 @@ import { type Logging, ConsoleLogging } from './logging';
import { type Store, OfflineStore, OnlineStore, NoStore } from './store';
import { setLogin } from './net/setLogin';
import { clearLogin } from './net/clearLogin';
+import { removeAccount } from './net/removeAccount';
import { setAccess } from './net/setAccess';
import { addAccount } from './net/addAccount';
import { setAdmin } from './net/setAdmin';
@@ -79,6 +80,24 @@ export class DatabagSDK {
return new SessionModule(this.store, this.crypto, this.log, guid, appToken, node, secure, created);
}
+ public async remove(session: Session): Promise {
+ const sessionModule = session as SessionModule;
+ const params = await sessionModule.close();
+ try {
+ await this.store.clearLogin();
+ }
+ catch(err) {
+ this.log.error(err);
+ }
+ try {
+ const { node, secure, token } = params;
+ await removeAccount(node, secure, token);
+ }
+ catch(err) {
+ this.log.error(err);
+ }
+ }
+
public async logout(session: Session, all: boolean): Promise {
const sessionModule = session as SessionModule;
const params = await sessionModule.close();
diff --git a/app/sdk/src/net/removeAccount.ts b/app/sdk/src/net/removeAccount.ts
new file mode 100644
index 00000000..1fd469d3
--- /dev/null
+++ b/app/sdk/src/net/removeAccount.ts
@@ -0,0 +1,7 @@
+import { checkResponse, fetchWithTimeout } from './fetchUtil';
+
+export async function removeAccount(node: string, secure: boolean, token: string): Promise {
+ const endpoint = `http${secure ? 's' : ''}://${node}/profile?agent=${token}`;
+ const { status } = await fetchWithTimeout(endpoint, { method: 'DELETE' })
+ checkResponse(status);
+}