github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/convos_posts.go (about) 1 package common 2 3 import ( 4 "crypto/aes" 5 "crypto/cipher" 6 "crypto/rand" 7 "encoding/hex" 8 "io" 9 ) 10 11 var ConvoPostProcess ConvoPostProcessor = NewDefaultConvoPostProcessor() 12 13 type ConvoPostProcessor interface { 14 OnLoad(co *ConversationPost) (*ConversationPost, error) 15 OnSave(co *ConversationPost) (*ConversationPost, error) 16 } 17 18 type DefaultConvoPostProcessor struct { 19 } 20 21 func NewDefaultConvoPostProcessor() *DefaultConvoPostProcessor { 22 return &DefaultConvoPostProcessor{} 23 } 24 25 func (pr *DefaultConvoPostProcessor) OnLoad(co *ConversationPost) (*ConversationPost, error) { 26 return co, nil 27 } 28 29 func (pr *DefaultConvoPostProcessor) OnSave(co *ConversationPost) (*ConversationPost, error) { 30 return co, nil 31 } 32 33 type AesConvoPostProcessor struct { 34 } 35 36 func NewAesConvoPostProcessor() *AesConvoPostProcessor { 37 return &AesConvoPostProcessor{} 38 } 39 40 func (pr *AesConvoPostProcessor) OnLoad(co *ConversationPost) (*ConversationPost, error) { 41 if co.Post != "aes" { 42 return co, nil 43 } 44 key, _ := hex.DecodeString(Config.ConvoKey) 45 46 ciphertext, err := hex.DecodeString(co.Body) 47 if err != nil { 48 return nil, err 49 } 50 51 block, err := aes.NewCipher(key) 52 if err != nil { 53 return nil, err 54 } 55 56 aesgcm, err := cipher.NewGCM(block) 57 if err != nil { 58 return nil, err 59 } 60 61 nonceSize := aesgcm.NonceSize() 62 if len(ciphertext) < nonceSize { 63 return nil, err 64 } 65 66 nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:] 67 plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil) 68 if err != nil { 69 return nil, err 70 } 71 72 lco := *co 73 lco.Body = string(plaintext) 74 return &lco, nil 75 } 76 77 func (pr *AesConvoPostProcessor) OnSave(co *ConversationPost) (*ConversationPost, error) { 78 key, _ := hex.DecodeString(Config.ConvoKey) 79 block, err := aes.NewCipher(key) 80 if err != nil { 81 return nil, err 82 } 83 84 nonce := make([]byte, 12) 85 if _, err := io.ReadFull(rand.Reader, nonce); err != nil { 86 return nil, err 87 } 88 89 aesgcm, err := cipher.NewGCM(block) 90 if err != nil { 91 return nil, err 92 } 93 ciphertext := aesgcm.Seal(nil, nonce, []byte(co.Body), nil) 94 95 lco := *co 96 lco.Body = hex.EncodeToString(ciphertext) 97 lco.Post = "aes" 98 return &lco, nil 99 } 100 101 type ConversationPost struct { 102 ID int 103 CID int 104 Body string 105 Post string // aes, '' 106 CreatedBy int 107 } 108 109 // TODO: Should we run OnLoad on this? Or maybe add a FetchMeta method to avoid having to decode the message when it's not necessary? 110 func (co *ConversationPost) Fetch() error { 111 return convoStmts.fetchPost.QueryRow(co.ID).Scan(&co.CID, &co.Body, &co.Post, &co.CreatedBy) 112 } 113 114 func (co *ConversationPost) Update() error { 115 lco, err := ConvoPostProcess.OnSave(co) 116 if err != nil { 117 return err 118 } 119 //GetHookTable().VhookNoRet("convo_post_update", lco) 120 _, err = convoStmts.editPost.Exec(lco.Body, lco.Post, lco.ID) 121 return err 122 } 123 124 func (co *ConversationPost) Create() (int, error) { 125 lco, err := ConvoPostProcess.OnSave(co) 126 if err != nil { 127 return 0, err 128 } 129 //GetHookTable().VhookNoRet("convo_post_create", lco) 130 res, err := convoStmts.createPost.Exec(lco.CID, lco.Body, lco.Post, lco.CreatedBy) 131 if err != nil { 132 return 0, err 133 } 134 135 lastID, err := res.LastInsertId() 136 return int(lastID), err 137 } 138 139 func (co *ConversationPost) Delete() error { 140 _, err := convoStmts.deletePost.Exec(co.ID) 141 return err 142 }