wrapper.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. package wrapper
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "html/template"
  7. "net/http"
  8. "os"
  9. "path/filepath"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "golang-fave/cblocks"
  14. "golang-fave/consts"
  15. "golang-fave/engine/basket"
  16. "golang-fave/engine/mysqlpool"
  17. "golang-fave/engine/sqlw"
  18. "golang-fave/engine/wrapper/config"
  19. "golang-fave/logger"
  20. "golang-fave/utils"
  21. "github.com/vladimirok5959/golang-server-sessions/session"
  22. )
  23. type Tx = sqlw.Tx
  24. var ErrNoRows = sqlw.ErrNoRows
  25. type Wrapper struct {
  26. l *logger.Logger
  27. W http.ResponseWriter
  28. R *http.Request
  29. S *session.Session
  30. c *cblocks.CacheBlocks
  31. Host string
  32. Port string
  33. CurrHost string
  34. DConfig string
  35. DHtdocs string
  36. DLogs string
  37. DTemplate string
  38. DTmp string
  39. IsBackend bool
  40. ConfMysqlExists bool
  41. UrlArgs []string
  42. CurrModule string
  43. CurrSubModule string
  44. MSPool *mysqlpool.MySqlPool
  45. ShopBasket *basket.Basket
  46. Config *config.Config
  47. DB *sqlw.DB
  48. User *utils.MySql_user
  49. }
  50. func New(l *logger.Logger, w http.ResponseWriter, r *http.Request, s *session.Session, c *cblocks.CacheBlocks, host, port, chost, dirConfig, dirHtdocs, dirLogs, dirTemplate, dirTmp string, mp *mysqlpool.MySqlPool, sb *basket.Basket) *Wrapper {
  51. conf := config.ConfigNew()
  52. if err := conf.ConfigRead(dirConfig + string(os.PathSeparator) + "config.json"); err != nil {
  53. l.Log("Host config file: %s", r, true, err.Error())
  54. }
  55. return &Wrapper{
  56. l: l,
  57. W: w,
  58. R: r,
  59. S: s,
  60. c: c,
  61. Host: host,
  62. Port: port,
  63. CurrHost: chost,
  64. DConfig: dirConfig,
  65. DHtdocs: dirHtdocs,
  66. DLogs: dirLogs,
  67. DTemplate: dirTemplate,
  68. DTmp: dirTmp,
  69. UrlArgs: []string{},
  70. CurrModule: "",
  71. CurrSubModule: "",
  72. MSPool: mp,
  73. ShopBasket: sb,
  74. Config: conf,
  75. }
  76. }
  77. func (this *Wrapper) LogAccess(msg string, vars ...interface{}) {
  78. this.l.Log(msg, this.R, false, vars...)
  79. }
  80. func (this *Wrapper) LogError(msg string, vars ...interface{}) {
  81. this.l.Log(msg, this.R, true, vars...)
  82. }
  83. func (this *Wrapper) LogCpError(err *error) *error {
  84. if *err != nil {
  85. this.LogError("%s", *err)
  86. }
  87. return err
  88. }
  89. func (this *Wrapper) dbReconnect() error {
  90. if !utils.IsMySqlConfigExists(this.DConfig + string(os.PathSeparator) + "mysql.json") {
  91. return errors.New("can't read database configuration file")
  92. }
  93. mc, err := utils.MySqlConfigRead(this.DConfig + string(os.PathSeparator) + "mysql.json")
  94. if err != nil {
  95. return err
  96. }
  97. this.DB, err = sqlw.Open("mysql", mc.User+":"+mc.Password+"@tcp("+mc.Host+":"+mc.Port+")/"+mc.Name)
  98. if err != nil {
  99. return err
  100. }
  101. this.MSPool.Set(this.CurrHost, this.DB)
  102. return nil
  103. }
  104. func (this *Wrapper) UseDatabase() error {
  105. this.DB = this.MSPool.Get(this.CurrHost)
  106. if this.DB == nil {
  107. if err := this.dbReconnect(); err != nil {
  108. return err
  109. }
  110. }
  111. if err := this.DB.Ping(); err != nil {
  112. this.DB.Close()
  113. if err := this.dbReconnect(); err != nil {
  114. return err
  115. }
  116. if err := this.DB.Ping(); err != nil {
  117. this.DB.Close()
  118. return err
  119. }
  120. }
  121. // Max 60 minutes and max 4 connection per host
  122. this.DB.SetConnMaxLifetime(time.Minute * 60)
  123. this.DB.SetMaxIdleConns(4)
  124. this.DB.SetMaxOpenConns(4)
  125. return nil
  126. }
  127. func (this *Wrapper) LoadSessionUser() bool {
  128. if this.S.GetInt("UserId", 0) <= 0 {
  129. return false
  130. }
  131. if this.DB == nil {
  132. return false
  133. }
  134. user := &utils.MySql_user{}
  135. err := this.DB.QueryRow(`
  136. SELECT
  137. id,
  138. first_name,
  139. last_name,
  140. email,
  141. password,
  142. admin,
  143. active
  144. FROM
  145. users
  146. WHERE
  147. id = ?
  148. LIMIT 1;`,
  149. this.S.GetInt("UserId", 0),
  150. ).Scan(
  151. &user.A_id,
  152. &user.A_first_name,
  153. &user.A_last_name,
  154. &user.A_email,
  155. &user.A_password,
  156. &user.A_admin,
  157. &user.A_active,
  158. )
  159. if *this.LogCpError(&err) != nil {
  160. return false
  161. }
  162. if user.A_id != this.S.GetInt("UserId", 0) {
  163. return false
  164. }
  165. this.User = user
  166. return true
  167. }
  168. func (this *Wrapper) Write(data string) {
  169. this.W.Write([]byte(data))
  170. }
  171. func (this *Wrapper) MsgSuccess(msg string) {
  172. this.Write(fmt.Sprintf(
  173. `fave.ShowMsgSuccess('Success!', '%s', false);`,
  174. utils.JavaScriptVarValue(msg)))
  175. }
  176. func (this *Wrapper) MsgError(msg string) {
  177. this.Write(fmt.Sprintf(
  178. `fave.ShowMsgError('Error!', '%s', true);`,
  179. utils.JavaScriptVarValue(msg)))
  180. }
  181. func (this *Wrapper) RenderToString(tcont []byte, data interface{}) string {
  182. tmpl, err := template.New("template").Parse(string(tcont))
  183. if err != nil {
  184. return err.Error()
  185. }
  186. var tpl bytes.Buffer
  187. if err := tmpl.Execute(&tpl, data); err != nil {
  188. return err.Error()
  189. }
  190. return tpl.String()
  191. }
  192. func (this *Wrapper) RenderFrontEnd(tname string, data interface{}, status int) {
  193. tmpl, err := template.New(tname+".html").Funcs(utils.TemplateAdditionalFuncs()).ParseFiles(
  194. this.DTemplate+string(os.PathSeparator)+tname+".html",
  195. this.DTemplate+string(os.PathSeparator)+"header.html",
  196. this.DTemplate+string(os.PathSeparator)+"sidebar-left.html",
  197. this.DTemplate+string(os.PathSeparator)+"sidebar-right.html",
  198. this.DTemplate+string(os.PathSeparator)+"footer.html",
  199. )
  200. if err != nil {
  201. utils.SystemErrorPageTemplate(this.W, err)
  202. return
  203. }
  204. var tpl bytes.Buffer
  205. err = tmpl.Execute(&tpl, consts.TmplData{
  206. System: utils.GetTmplSystemData("", ""),
  207. Data: data,
  208. })
  209. if err != nil {
  210. utils.SystemErrorPageTemplate(this.W, err)
  211. return
  212. }
  213. this.W.WriteHeader(status)
  214. this.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
  215. this.W.Header().Set("Content-Type", "text/html; charset=utf-8")
  216. this.W.Write(tpl.Bytes())
  217. }
  218. func (this *Wrapper) RenderBackEnd(tcont []byte, data interface{}) {
  219. tmpl, err := template.New("template").Parse(string(tcont))
  220. if err != nil {
  221. utils.SystemErrorPageEngine(this.W, err)
  222. return
  223. }
  224. this.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
  225. this.W.Header().Set("Content-Type", "text/html; charset=utf-8")
  226. var tpl bytes.Buffer
  227. err = tmpl.Execute(this.W, consts.TmplData{
  228. System: utils.GetTmplSystemData(this.CurrModule, this.CurrSubModule),
  229. Data: data,
  230. })
  231. if err != nil {
  232. utils.SystemErrorPageEngine(this.W, err)
  233. return
  234. }
  235. this.W.Write(tpl.Bytes())
  236. }
  237. func (this *Wrapper) GetCurrentPage(max int) int {
  238. curr := 1
  239. page := this.R.URL.Query().Get("p")
  240. if page != "" {
  241. if i, err := strconv.Atoi(page); err == nil {
  242. if i < 1 {
  243. curr = 1
  244. } else if i > max {
  245. curr = max
  246. } else {
  247. curr = i
  248. }
  249. }
  250. }
  251. return curr
  252. }
  253. func (this *Wrapper) ConfigSave() error {
  254. return this.Config.ConfigWrite(this.DConfig + string(os.PathSeparator) + "config.json")
  255. }
  256. func (this *Wrapper) SendEmail(email, subject, message string) error {
  257. if _, err := this.DB.Exec(
  258. `INSERT INTO notify_mail SET
  259. id = NULL,
  260. email = ?,
  261. subject = ?,
  262. message = ?,
  263. error = '',
  264. datetime = ?,
  265. status = 2
  266. ;`,
  267. email,
  268. subject,
  269. message,
  270. utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
  271. ); err != nil {
  272. return err
  273. }
  274. return nil
  275. }
  276. func (this *Wrapper) GetSessionId() string {
  277. cookie, err := this.R.Cookie("session")
  278. if err == nil && len(cookie.Value) == 40 {
  279. return cookie.Value
  280. }
  281. return ""
  282. }
  283. func (this *Wrapper) RecreateProductXmlFile() error {
  284. trigger := strings.Join([]string{this.DTmp, "trigger.xml.run"}, string(os.PathSeparator))
  285. if !utils.IsFileExists(trigger) {
  286. if _, err := os.Create(trigger); err != nil {
  287. return err
  288. }
  289. }
  290. return nil
  291. }
  292. func (this *Wrapper) RecreateProductImgFiles() error {
  293. trigger := strings.Join([]string{this.DTmp, "trigger.img.run"}, string(os.PathSeparator))
  294. if !utils.IsFileExists(trigger) {
  295. if _, err := os.Create(trigger); err != nil {
  296. return err
  297. }
  298. }
  299. return nil
  300. }
  301. func (this *Wrapper) RemoveProductImageThumbnails(product_id, filename string) error {
  302. pattern := this.DHtdocs + string(os.PathSeparator) + strings.Join([]string{"products", "images", product_id, filename}, string(os.PathSeparator))
  303. if files, err := filepath.Glob(pattern); err != nil {
  304. return err
  305. } else {
  306. for _, file := range files {
  307. if err := os.Remove(file); err != nil {
  308. return errors.New(fmt.Sprintf("[upload delete] Thumbnail file (%s) delete error: %s", file, err.Error()))
  309. }
  310. }
  311. }
  312. return this.RecreateProductImgFiles()
  313. }