wrapper.go 7.1 KB

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