mirror of
https://github.com/Kyren223/eko.git
synced 2025-09-03 20:18:22 +00:00
Added the ability to delete users
This commit is contained in:
@@ -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,
|
||||
|
@@ -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())
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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(
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user