180 lines
3.7 KiB
Go
180 lines
3.7 KiB
Go
package entries
|
|
|
|
import (
|
|
"errors"
|
|
"maxwarden/query"
|
|
"maxwarden/security"
|
|
"maxwarden/users"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Secret struct {
|
|
ID string
|
|
Description string
|
|
URL string
|
|
Notes string
|
|
Username string
|
|
Password string
|
|
Created time.Time
|
|
Modified time.Time
|
|
}
|
|
|
|
type EntryFilter struct {
|
|
Filter query.Filter
|
|
MasterKey string
|
|
UserId int32
|
|
}
|
|
|
|
func OrderByDescription(secret []Secret, desc bool) []Secret {
|
|
sort.Slice(secret, func(i, j int) bool {
|
|
if desc {
|
|
return strings.ToLower(secret[i].Description) > strings.ToLower(secret[j].Description)
|
|
} else {
|
|
return strings.ToLower(secret[i].Description) < strings.ToLower(secret[j].Description)
|
|
}
|
|
})
|
|
return secret
|
|
}
|
|
|
|
func Filter(f EntryFilter) ([]Secret, error) {
|
|
user, _ := users.FetchById(f.UserId)
|
|
|
|
// we need to do the rest in memory because the data is encrypted, so we need to decrypt the data
|
|
secrets, decErr := security.DecryptData[[]Secret](user.Data, f.MasterKey)
|
|
if decErr != nil {
|
|
return nil, decErr
|
|
}
|
|
|
|
if secrets == nil {
|
|
return nil, errors.New("secrets list is null")
|
|
}
|
|
|
|
output := []Secret{}
|
|
|
|
// decrypt data inside each entry retrieved
|
|
for _, v := range *secrets {
|
|
search := f.Filter.Search["description"]
|
|
if search != "" {
|
|
search = strings.ToLower(search)
|
|
searchable := strings.ToLower(v.Description)
|
|
|
|
if strings.Contains(searchable, search) {
|
|
output = append(output, v)
|
|
}
|
|
} else {
|
|
output = append(output, v)
|
|
}
|
|
}
|
|
|
|
//order by
|
|
output = OrderByDescription(output, f.Filter.OrderDescending)
|
|
|
|
// pagination
|
|
output = query.PaginateSlice(output, f.Filter)
|
|
|
|
return output, nil
|
|
}
|
|
|
|
// linear search because that's the only option
|
|
func FetchSecretFromID(userId int32, masterKey string, secretId string) (Secret, error) {
|
|
user, _ := users.FetchById(userId)
|
|
|
|
secrets, decErr := security.DecryptData[[]Secret](user.Data, masterKey)
|
|
if decErr != nil {
|
|
return Secret{}, decErr
|
|
}
|
|
|
|
if secrets == nil {
|
|
return Secret{}, errors.New("secrets are nil")
|
|
}
|
|
|
|
for _, v := range *secrets {
|
|
if v.ID == secretId {
|
|
return v, nil
|
|
}
|
|
}
|
|
|
|
return Secret{}, errors.New("no secret found")
|
|
}
|
|
|
|
func DeleteSecret(userId int32, masterKey string, secretId string) error {
|
|
user, _ := users.FetchById(userId)
|
|
|
|
secrets, decErr := security.DecryptData[[]Secret](user.Data, masterKey)
|
|
if decErr != nil {
|
|
return decErr
|
|
}
|
|
|
|
if secrets == nil {
|
|
return errors.New("attempt to range over null secret array")
|
|
}
|
|
|
|
output := []Secret{}
|
|
|
|
for _, v := range *secrets {
|
|
if v.ID != secretId {
|
|
output = append(output, v)
|
|
}
|
|
}
|
|
|
|
enc, _ := security.EncryptData(&output, masterKey)
|
|
user.Data = enc
|
|
|
|
_, userErr := users.Update(user)
|
|
|
|
return userErr
|
|
}
|
|
|
|
func Update(userId int32, masterKey string, secret Secret) error {
|
|
user, _ := users.FetchById(userId)
|
|
|
|
secrets, _ := security.DecryptData[[]Secret](user.Data, masterKey)
|
|
if secrets == nil {
|
|
return errors.New("user secrets are null")
|
|
}
|
|
|
|
secret.Modified = time.Now()
|
|
|
|
// linear search and replace
|
|
for i, v := range *secrets {
|
|
if v.ID == secret.ID {
|
|
created := (*secrets)[i].Created
|
|
secret.Created = created
|
|
|
|
(*secrets)[i] = secret
|
|
}
|
|
}
|
|
|
|
enc, _ := security.EncryptData(secrets, masterKey)
|
|
|
|
user.Data = enc
|
|
_, updateErr := users.Update(user)
|
|
|
|
return updateErr
|
|
}
|
|
|
|
func Add(userId int32, masterKey string, secret Secret) error {
|
|
user, _ := users.FetchById(userId)
|
|
|
|
secrets, _ := security.DecryptData[[]Secret](user.Data, masterKey)
|
|
if secrets == nil {
|
|
return errors.New("user secrets are null")
|
|
}
|
|
|
|
secret.ID = uuid.New().String()
|
|
secret.Modified = time.Now()
|
|
secret.Created = time.Now()
|
|
|
|
*secrets = append(*secrets, secret)
|
|
|
|
enc, _ := security.EncryptData(secrets, masterKey)
|
|
|
|
user.Data = enc
|
|
_, updateErr := users.Update(user)
|
|
|
|
return updateErr
|
|
} |