mirror of
https://github.com/ddworken/hishtory.git
synced 2025-08-18 10:49:54 +02:00
Rework ff98a7907c
to use the newly added EntryId column rather than deleting based on the start time
This commit is contained in:
@@ -152,14 +152,8 @@ func (db *DB) DumpRequestDeleteForUserAndDevice(ctx context.Context, userID, dev
|
|||||||
func (db *DB) ApplyDeletionRequestsToBackend(ctx context.Context, request *shared.DeletionRequest) (int64, error) {
|
func (db *DB) ApplyDeletionRequestsToBackend(ctx context.Context, request *shared.DeletionRequest) (int64, error) {
|
||||||
tx := db.WithContext(ctx).Where("false")
|
tx := db.WithContext(ctx).Where("false")
|
||||||
for _, message := range request.Messages.Ids {
|
for _, message := range request.Messages.Ids {
|
||||||
// Note that this won't do server-side deletion of pre-saved history entries. This is an inherent
|
// Note that we do an OR with date or the ID matching since the ID is not always recorded for older history entries.
|
||||||
// limitation of our current DB schema. This is sub-par, since it means that even after deletion, clients
|
tx = tx.Or(db.WithContext(ctx).Where("user_id = ? AND device_id = ? AND (date = ? OR id = ?)", request.UserId, message.DeviceId, message.EndTime, message.EntryId))
|
||||||
// may still receive deleted history entries. But, a well-behaved client will immediately delete
|
|
||||||
// these (never writing them to disk) and mark them as received, so this won't happen again.
|
|
||||||
//
|
|
||||||
// TODO: This could be improved upon if we added a HistoryEntry.EntryId field, backfilled it, added
|
|
||||||
// it to EncHistoryEntry, and then used that as a key for deletion.
|
|
||||||
tx = tx.Or(db.WithContext(ctx).Where("user_id = ? AND device_id = ? AND date = ?", request.UserId, message.DeviceId, message.EndTime))
|
|
||||||
}
|
}
|
||||||
result := tx.Delete(&shared.EncHistoryEntry{})
|
result := tx.Delete(&shared.EncHistoryEntry{})
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
|
@@ -87,7 +87,7 @@ func deleteOnRemoteInstances(ctx context.Context, historyEntries []*data.History
|
|||||||
|
|
||||||
for _, entry := range historyEntries {
|
for _, entry := range historyEntries {
|
||||||
deletionRequest.Messages.Ids = append(deletionRequest.Messages.Ids,
|
deletionRequest.Messages.Ids = append(deletionRequest.Messages.Ids,
|
||||||
shared.MessageIdentifier{StartTime: entry.StartTime, EndTime: entry.EndTime, DeviceId: entry.DeviceId},
|
shared.MessageIdentifier{DeviceId: entry.DeviceId, EndTime: entry.EndTime, EntryId: entry.EntryId},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return lib.SendDeletionRequest(deletionRequest)
|
return lib.SendDeletionRequest(deletionRequest)
|
||||||
|
@@ -605,9 +605,9 @@ func HandleDeletionRequests(ctx context.Context, deletionRequests []*shared.Dele
|
|||||||
db := hctx.GetDb(ctx)
|
db := hctx.GetDb(ctx)
|
||||||
for _, request := range deletionRequests {
|
for _, request := range deletionRequests {
|
||||||
for _, entry := range request.Messages.Ids {
|
for _, entry := range request.Messages.Ids {
|
||||||
// Note that entry.StartTime is not always present (for legacy reasons) and entry.EndTime is also
|
// Note that entry.EndTime is not always present (for pre-saved entries). And likewise,
|
||||||
// not always present (for pre-saved entries). So we just check that one of them matches.
|
// entry.EntryId is not always present for older entries. So we just check that one of them matches.
|
||||||
tx := db.Where("device_id = ? AND (start_time = ? OR end_time = ?)", entry.DeviceId, entry.StartTime, entry.EndTime)
|
tx := db.Where("device_id = ? AND (end_time = ? OR entry_id = ?)", entry.DeviceId, entry.EndTime, entry.EntryId)
|
||||||
res := tx.Delete(&data.HistoryEntry{})
|
res := tx.Delete(&data.HistoryEntry{})
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
return fmt.Errorf("DB error: %w", res.Error)
|
return fmt.Errorf("DB error: %w", res.Error)
|
||||||
|
@@ -602,7 +602,7 @@ func deleteHistoryEntry(ctx context.Context, entry data.HistoryEntry) error {
|
|||||||
SendTime: time.Now(),
|
SendTime: time.Now(),
|
||||||
}
|
}
|
||||||
dr.Messages.Ids = append(dr.Messages.Ids,
|
dr.Messages.Ids = append(dr.Messages.Ids,
|
||||||
shared.MessageIdentifier{StartTime: entry.StartTime, EndTime: entry.EndTime, DeviceId: entry.DeviceId},
|
shared.MessageIdentifier{DeviceId: entry.DeviceId, EndTime: entry.EndTime, EntryId: entry.EntryId},
|
||||||
)
|
)
|
||||||
return lib.SendDeletionRequest(dr)
|
return lib.SendDeletionRequest(dr)
|
||||||
}
|
}
|
||||||
|
@@ -15,12 +15,14 @@ type EncHistoryEntry struct {
|
|||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
// Note that EncHistoryEntry.Date == HistoryEntry.EndTime
|
// Note that EncHistoryEntry.Date == HistoryEntry.EndTime
|
||||||
Date time.Time `json:"time"`
|
Date time.Time `json:"time"`
|
||||||
EncryptedId string `json:"id"`
|
// Note that EncHistoryEntry.EncryptedId == HistoryEntry.Id (for entries created after pre-saving support)
|
||||||
|
EncryptedId string `json:"encrypted_id"`
|
||||||
ReadCount int `json:"read_count"`
|
ReadCount int `json:"read_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Manually created the indices:
|
Manually created the indices:
|
||||||
|
CREATE INDEX CONCURRENTLY entry_id_idx ON enc_history_entries USING btree(encrypted_id);
|
||||||
CREATE INDEX CONCURRENTLY device_id_idx ON enc_history_entries USING btree(device_id);
|
CREATE INDEX CONCURRENTLY device_id_idx ON enc_history_entries USING btree(device_id);
|
||||||
CREATE INDEX CONCURRENTLY read_count_idx ON enc_history_entries USING btree(read_count);
|
CREATE INDEX CONCURRENTLY read_count_idx ON enc_history_entries USING btree(read_count);
|
||||||
CREATE INDEX CONCURRENTLY redact_idx ON enc_history_entries USING btree(user_id, device_id, date);
|
CREATE INDEX CONCURRENTLY redact_idx ON enc_history_entries USING btree(user_id, device_id, date);
|
||||||
@@ -82,7 +84,7 @@ type MessageIdentifiers struct {
|
|||||||
Ids []MessageIdentifier `json:"message_ids"`
|
Ids []MessageIdentifier `json:"message_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identifies a single history entry based on the device that recorded the entry, and the end time. Note that
|
// Identifies a single history entry based on the device that recorded the entry, and additional metadata. Note that
|
||||||
// this does not include the command itself since that would risk including the sensitive data that is meant
|
// this does not include the command itself since that would risk including the sensitive data that is meant
|
||||||
// to be deleted
|
// to be deleted
|
||||||
type MessageIdentifier struct {
|
type MessageIdentifier struct {
|
||||||
@@ -90,9 +92,11 @@ type MessageIdentifier struct {
|
|||||||
DeviceId string `json:"device_id"`
|
DeviceId string `json:"device_id"`
|
||||||
// The timestamp when the command finished running. Serialized as "date" for legacy compatibility.
|
// The timestamp when the command finished running. Serialized as "date" for legacy compatibility.
|
||||||
EndTime time.Time `json:"date"`
|
EndTime time.Time `json:"date"`
|
||||||
// The timestamp when the command started running.
|
// The entry ID of the command.
|
||||||
// Note this field was added as part of supporting pre-saving commands, so older clients do not set this field
|
// Note this field was added as part of supporting pre-saving commands, so older clients do not set this field
|
||||||
StartTime time.Time `json:"start_time"`
|
// And even for new clients, it may contain a per-device entry ID. For pre-saved entries, this is guaranteed to
|
||||||
|
// be present.
|
||||||
|
EntryId string `json:"entry_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageIdentifiers) Scan(value interface{}) error {
|
func (m *MessageIdentifiers) Scan(value interface{}) error {
|
||||||
|
Reference in New Issue
Block a user