Added the ability to delete users

This commit is contained in:
2025-07-21 13:46:40 +03:00
parent 3fcaf10033
commit 5f6845c399
8 changed files with 101 additions and 13 deletions

View File

@@ -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,

View File

@@ -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())
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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(

View File

@@ -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 {

View File

@@ -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