summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/client/gateway/gateway.go4
-rw-r--r--internal/client/ui/core/core.go2
-rw-r--r--internal/client/ui/core/state/state.go25
-rw-r--r--internal/client/ui/core/usersettings/usersettings.go42
-rw-r--r--internal/data/users.sql.go11
-rw-r--r--internal/server/api/api.go18
-rw-r--r--internal/server/server.go10
-rw-r--r--query/users.sql2
8 files changed, 101 insertions, 13 deletions
diff --git a/internal/client/gateway/gateway.go b/internal/client/gateway/gateway.go
index f543d82..68c26b2 100644
--- a/internal/client/gateway/gateway.go
+++ b/internal/client/gateway/gateway.go
@@ -148,7 +148,7 @@ func handlePacketStream() {
payload, err := pkt.DecodedPayload()
assert.NoError(err, "server should always provide a decodeable packet")
- log.Printf("received streamed packet %v: %v\n", payload.Type(), payload)
+ // log.Printf("received streamed packet %v: %v\n", payload.Type(), payload)
ui.Program.Send(payload)
}
}
@@ -189,7 +189,7 @@ func Send(request packet.Payload) tea.Cmd {
if err != nil {
log.Println("request send error:", err)
} else {
- log.Println("request sent successfully:", request)
+ // log.Println("request sent successfully:", request)
}
return RequestSentMsg{
request: request,
diff --git a/internal/client/ui/core/core.go b/internal/client/ui/core/core.go
index 8c0a336..7e42619 100644
--- a/internal/client/ui/core/core.go
+++ b/internal/client/ui/core/core.go
@@ -388,6 +388,7 @@ func (m *Model) updateConnected(message tea.Msg) tea.Cmd {
} else {
log.Println("received error:", msg.Error)
gateway.Disconnect()
+ state.Reset()
return ui.Transition(ui.NewAuth())
}
}
@@ -490,6 +491,7 @@ func (m *Model) updateAuthenticated(message tea.Msg) tea.Cmd {
err := "new connection from another location, closing this one"
if err == msg.Error {
gateway.Disconnect()
+ state.Reset()
return ui.Transition(ui.NewAuth())
}
diff --git a/internal/client/ui/core/state/state.go b/internal/client/ui/core/state/state.go
index 16b92a9..97a6de8 100644
--- a/internal/client/ui/core/state/state.go
+++ b/internal/client/ui/core/state/state.go
@@ -84,6 +84,29 @@ var Data UserData = UserData{
var UserID *snowflake.ID = nil
+func Reset() {
+ UserID = nil
+ Data = UserData{
+ Networks: []snowflake.ID{},
+ Signals: []snowflake.ID{},
+ }
+ State = state{
+ ChatState: map[snowflake.ID]ChatState{},
+ LastFrequency: map[snowflake.ID]snowflake.ID{},
+ Messages: map[snowflake.ID]*btree.BTreeG[data.Message]{},
+ Networks: map[snowflake.ID]data.Network{},
+ Frequencies: map[snowflake.ID][]data.Frequency{},
+ Members: map[snowflake.ID]map[snowflake.ID]data.Member{},
+ Users: map[snowflake.ID]data.User{},
+ TrustedUsers: map[snowflake.ID]ed25519.PublicKey{},
+ BlockedUsers: map[snowflake.ID]struct{}{},
+ BlockingUsers: map[snowflake.ID]struct{}{},
+ LastReadMessages: map[snowflake.ID]*snowflake.ID{},
+ RemoteNotifications: map[snowflake.ID]int{},
+ LocalNotifications: map[snowflake.ID]int{},
+ }
+}
+
func UpdateNetworks(info *packet.NetworksInfo) {
networks := State.Networks
@@ -382,7 +405,7 @@ func SendFinalData() {
// HACK: Give a small grace period for the writes to be processed
// Tweak this value as needed
- time.Sleep(20 * time.Millisecond)
+ // time.Sleep(20 * time.Millisecond)
// TODO:
// I think the issue is that it's random which of these 2 requests goes
diff --git a/internal/client/ui/core/usersettings/usersettings.go b/internal/client/ui/core/usersettings/usersettings.go
index c833b5c..f7664fc 100644
--- a/internal/client/ui/core/usersettings/usersettings.go
+++ b/internal/client/ui/core/usersettings/usersettings.go
@@ -18,12 +18,14 @@ package usersettings
import (
"errors"
+ "log"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/kyren223/eko/internal/client/config"
"github.com/kyren223/eko/internal/client/gateway"
+ "github.com/kyren223/eko/internal/client/ui"
"github.com/kyren223/eko/internal/client/ui/colors"
"github.com/kyren223/eko/internal/client/ui/core/state"
"github.com/kyren223/eko/internal/client/ui/field"
@@ -46,6 +48,17 @@ var (
Render("Update User Settings")
}
+ blurredDelete = func() string {
+ return lipgloss.NewStyle().Padding(0, 1).
+ Background(colors.DarkGray).Foreground(colors.Red).
+ Render("Delete User Permanently")
+ }
+ focusedDelete = func() string {
+ return lipgloss.NewStyle().Padding(0, 1).
+ Background(colors.Red).Foreground(colors.Black).
+ Render("Delete User Permanently")
+ }
+
highlightedStyle = func() lipgloss.Style {
return lipgloss.NewStyle().Padding(0, 0).
Background(colors.BackgroundHighlight).Foreground(colors.White)
@@ -57,6 +70,7 @@ const (
Description
PrivateField
UpdateField
+ DeleteField
FieldCount
)
@@ -65,6 +79,7 @@ type Model struct {
description field.Model
privateDM bool
update string
+ delete string
selected int
nameWidth int
@@ -126,6 +141,7 @@ func New() Model {
description: description,
privateDM: !user.IsPublicDM,
update: blurredUpdate(),
+ delete: blurredDelete(),
selected: 0,
nameWidth: nameWidth,
}
@@ -158,6 +174,12 @@ func (m Model) View() string {
Align(lipgloss.Center).
Render(m.update)
+ del := lipgloss.NewStyle().
+ Width(m.nameWidth).
+ Background(colors.Background).
+ Align(lipgloss.Center).
+ Render(m.delete)
+
configFile := "Config File: " + highlightedStyle().Render(config.ConfigFile)
configFile = lipgloss.NewStyle().
Background(colors.Background).Foreground(colors.White).
@@ -172,7 +194,7 @@ func (m Model) View() string {
Render(analyticsOptOut)
content := flex.NewVertical(
- analyticsOptOut, configFile, name, description, private, update,
+ analyticsOptOut, configFile, name, description, private, update, del,
).WithGap(1).View()
return lipgloss.NewStyle().
@@ -225,6 +247,7 @@ func (m *Model) updateFocus() tea.Cmd {
m.name.Blur()
m.description.Blur()
m.update = blurredUpdate()
+ m.delete = blurredDelete()
switch m.selected {
case NameField:
return m.name.Focus()
@@ -235,6 +258,9 @@ func (m *Model) updateFocus() tea.Cmd {
case UpdateField:
m.update = focusedUpdate()
return nil
+ case DeleteField:
+ m.delete = focusedDelete()
+ return nil
default:
assert.Never("missing switch statement field in update focus", "selected", m.selected)
return nil
@@ -247,6 +273,20 @@ func (m *Model) Select() tea.Cmd {
return nil
}
+ if m.selected == DeleteField {
+ log.Println("DELETING CLIENT")
+ // PERMA DELETE USER and return to login screen
+ state.Reset()
+ return tea.Batch(func() tea.Msg {
+ msg := gateway.Send(&packet.SetUserData{
+ Data: nil,
+ User: &data.User{IsDeleted: true},
+ })() // Important, call this function to block
+ gateway.Disconnect()
+ return msg
+ }, ui.Transition(ui.NewAuth()))
+ }
+
if m.selected != UpdateField {
return nil
}
diff --git a/internal/data/users.sql.go b/internal/data/users.sql.go
index 97d622e..078af15 100644
--- a/internal/data/users.sql.go
+++ b/internal/data/users.sql.go
@@ -45,12 +45,17 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e
const deleteUser = `-- name: DeleteUser :exec
UPDATE users SET
- is_deleted = true
+ is_deleted = true, public_key = ?, name = "Deleted User"
WHERE id = ? AND is_deleted = false
`
-func (q *Queries) DeleteUser(ctx context.Context, id snowflake.ID) error {
- _, err := q.db.ExecContext(ctx, deleteUser, id)
+type DeleteUserParams struct {
+ PublicKey ed25519.PublicKey
+ ID snowflake.ID
+}
+
+func (q *Queries) DeleteUser(ctx context.Context, arg DeleteUserParams) error {
+ _, err := q.db.ExecContext(ctx, deleteUser, arg.PublicKey, arg.ID)
return err
}
diff --git a/internal/server/api/api.go b/internal/server/api/api.go
index 35ca44c..5f11070 100644
--- a/internal/server/api/api.go
+++ b/internal/server/api/api.go
@@ -842,6 +842,24 @@ func SetUserData(ctx context.Context, sess *session.Session, request *packet.Set
var userPtr *data.User = nil
if request.User != nil {
+ if request.User.IsDeleted {
+ // Delete user
+
+ pubKey, _, err := ed25519.GenerateKey(nil)
+ assert.NoError(err, "random should never fail")
+ err = queries.DeleteUser(ctx, data.DeleteUserParams{
+ PublicKey: pubKey,
+ ID: sess.ID(),
+ })
+ if err != nil {
+ slog.ErrorContext(ctx, "database error", "error", err)
+ return &ErrInternalError
+ }
+
+ sess.Close() // Close connection and respond with nothing
+ return nil
+ }
+
name := request.User.Name
if len(name) > packet.MaxUsernameBytes {
return &packet.Error{Error: fmt.Sprintf(
diff --git a/internal/server/server.go b/internal/server/server.go
index 48d7d38..15c3a7a 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -60,7 +60,7 @@ const (
RateLimitCountThresholdMalicious = 10
)
-func getTlsConfig() *tls.Config {
+func getTLSConfig() *tls.Config {
path, ok := os.LookupEnv(CertFile)
if !ok {
// DEV MODE ONLY, DUMMY CERT
@@ -219,7 +219,7 @@ func (s *server) Node() *snowflake.Node {
func (s *server) Run() {
slog.Info("starting eko-server...")
- listener, err := tls.Listen("tcp4", ":"+strconv.Itoa(int(s.Port)), getTlsConfig())
+ listener, err := tls.Listen("tcp4", ":"+strconv.Itoa(int(s.Port)), getTLSConfig())
if err != nil {
slog.Error("error starting server", "error", err)
assert.Abort("see logs")
@@ -286,7 +286,7 @@ func (server *server) handleConnection(conn net.Conn) {
defer conn.Close()
var writerWg sync.WaitGroup
- done := make(chan struct{})
+ writeDone := make(chan struct{})
framer := packet.NewFramer()
sess := session.NewSession(server, addr, cancel, &writerWg)
@@ -306,7 +306,7 @@ func (server *server) handleConnection(conn net.Conn) {
// Writer
go func() {
- defer close(done)
+ defer close(writeDone)
defer conn.Close() // To unblock reader
writeQueue := sess.Read()
@@ -406,7 +406,7 @@ func (server *server) handleConnection(conn net.Conn) {
close(framer.Out) // stop processing
slog.InfoContext(ctx, "reader done, closed framer")
- <-done
+ <-writeDone
}
func processPacket(ctx context.Context, sess *session.Session, pkt packet.Packet) bool {
diff --git a/query/users.sql b/query/users.sql
index 50ec9af..ce075cd 100644
--- a/query/users.sql
+++ b/query/users.sql
@@ -16,7 +16,7 @@ RETURNING *;
-- name: DeleteUser :exec
UPDATE users SET
- is_deleted = true
+ is_deleted = true, public_key = ?, name = "Deleted User", description = ""
WHERE id = ? AND is_deleted = false;
-- name: SetUserData :one