diff --git a/app/mobile/src/api/removeProfile.js b/app/mobile/src/api/removeProfile.js new file mode 100644 index 00000000..ad906598 --- /dev/null +++ b/app/mobile/src/api/removeProfile.js @@ -0,0 +1,7 @@ +import { checkResponse, fetchWithTimeout } from './fetchUtil'; + +export async function removeProfile(server, token) { + let profile = await fetchWithTimeout(`https://${server}/profile?agent=${token}`, { method: 'DELETE' }); + checkResponse(profile) +} + diff --git a/app/mobile/src/context/useAppContext.hook.js b/app/mobile/src/context/useAppContext.hook.js index 04a9d8b2..774ac13e 100644 --- a/app/mobile/src/context/useAppContext.hook.js +++ b/app/mobile/src/context/useAppContext.hook.js @@ -1,6 +1,7 @@ import { useEffect, useState, useRef, useContext } from 'react'; import { getAvailable } from 'api/getAvailable'; import { setLogin } from 'api/setLogin'; +import { removeProfile } from 'api/removeProfile'; import { setAccountAccess } from 'api/setAccountAccess'; import { addAccount } from 'api/addAccount'; import { getUsername } from 'api/getUsername'; @@ -48,7 +49,8 @@ export function useAppContext() { await profile.actions.setSession(access); await card.actions.setSession(access); await channel.actions.setSession(access); - updateState({ session: true, loginTimestamp: access.created }); + updateState({ session: true, server: access.server, appToken: access.appToken, + loginTimestamp: access.created }); setWebsocket(access.server, access.appToken); } @@ -85,6 +87,11 @@ export function useAppContext() { await clearSession(); await store.actions.clearSession(); }, + remove: async () => { + await removeProfile(state.server, state.appToken); + await clearSession(); + await store.actions.clearSession(); + }, } const setWebsocket = (server, token) => { diff --git a/app/mobile/src/dashboard/Dashboard.jsx b/app/mobile/src/dashboard/Dashboard.jsx index 51b860eb..aa015bfb 100644 --- a/app/mobile/src/dashboard/Dashboard.jsx +++ b/app/mobile/src/dashboard/Dashboard.jsx @@ -14,9 +14,6 @@ export function Dashboard(props) { const { config, server, token } = location.state; const { state, actions } = useDashboard(config, server, token); -console.log(state.createToken); -console.log(state.accessToken); - const saveConfig = async () => { try { await actions.saveConfig(); diff --git a/app/mobile/src/session/profile/Profile.jsx b/app/mobile/src/session/profile/Profile.jsx index fa724b1a..da23fe68 100644 --- a/app/mobile/src/session/profile/Profile.jsx +++ b/app/mobile/src/session/profile/Profile.jsx @@ -65,6 +65,21 @@ export function Profile() { } } + const remove = async () => { + Alert.alert( + "Deleting Account", + "Confirm?", + [ + { text: "Cancel", + onPress: () => {}, + }, + { text: "Delete", onPress: () => { + actions.remove(); + }} + ] + ); + } + const logout = async () => { Alert.alert( "Logging Out", @@ -172,6 +187,10 @@ export function Profile() { Logout + + + Delete + ); }; diff --git a/app/mobile/src/session/profile/Profile.styled.js b/app/mobile/src/session/profile/Profile.styled.js index c11f7b43..47236e62 100644 --- a/app/mobile/src/session/profile/Profile.styled.js +++ b/app/mobile/src/session/profile/Profile.styled.js @@ -136,6 +136,22 @@ export const styles = StyleSheet.create({ color: Colors.white, paddingLeft: 8, }, + delete: { + marginTop: 32, + borderRadius: 4, + backgroundColor: Colors.error, + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + paddingLeft: 8, + paddingRight: 8, + paddingTop: 8, + paddingBottom: 8, + }, + deleteText: { + color: Colors.white, + paddingLeft: 8, + }, switch: { false: Colors.grey, true: Colors.background, diff --git a/app/mobile/src/session/profile/useProfile.hook.js b/app/mobile/src/session/profile/useProfile.hook.js index 9de5ca40..3af7c03f 100644 --- a/app/mobile/src/session/profile/useProfile.hook.js +++ b/app/mobile/src/session/profile/useProfile.hook.js @@ -76,6 +76,10 @@ export function useProfile() { app.actions.logout(); navigate('/'); }, + remove: async () => { + await app.actions.remove(); + navigate('/'); + }, setVisible: async (searchable) => { updateState({ searchable }); await account.actions.setSearchable(searchable); diff --git a/net/server/internal/api_removeProfile.go b/net/server/internal/api_removeProfile.go new file mode 100644 index 00000000..f011bb6b --- /dev/null +++ b/net/server/internal/api_removeProfile.go @@ -0,0 +1,89 @@ +package databag + +import ( + "databag/internal/store" + "gorm.io/gorm" + "net/http" + "os" +) + +//RemoveProfile removes account +func RemoveProfile(w http.ResponseWriter, r *http.Request) { + + account, code, err := ParamAgentToken(r, true) + if err != nil { + PrintMsg(r) + ErrResponse(w, code, err) + return + } + + err = store.DB.Transaction(func(tx *gorm.DB) error { + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Tag{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.TagSlot{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Asset{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Topic{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.TopicSlot{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.ChannelSlot{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Channel{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Article{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.ArticleSlot{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.CardSlot{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Card{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Group{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.GroupData{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.Group{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.App{}).Error; res != nil { + return res + } + if res := tx.Where("account_id = ?", account.ID).Delete(&store.AccountToken{}).Error; res != nil { + return res + } + if res := tx.Delete(&store.AccountDetail{}, account.AccountDetailID).Error; res != nil { + return res + } + if res := tx.Delete(account).Error; res != nil { + return res + } + return nil + }) + if err != nil { + ErrResponse(w, http.StatusInternalServerError, err) + return + } + + // delete asset files + path := getStrConfigValue(CNFAssetPath, APPDefaultPath) + "/" + account.GUID + if err = os.RemoveAll(path); err != nil { + ErrMsg(err) + } + + WriteResponse(w, nil) +} diff --git a/net/server/internal/routers.go b/net/server/internal/routers.go index 54cf3e1d..d846a3d2 100644 --- a/net/server/internal/routers.go +++ b/net/server/internal/routers.go @@ -734,6 +734,13 @@ var endpoints = routes{ SetProfileImage, }, + route{ + "RemoveProfile", + strings.ToUpper("Delete"), + "/profile", + RemoveProfile, + }, + route{ "Status", strings.ToUpper("Get"),