wrapper.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. package wrapper
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "html/template"
  7. "net/http"
  8. "os"
  9. "strconv"
  10. "time"
  11. "golang-fave/consts"
  12. "golang-fave/engine/mysqlpool"
  13. "golang-fave/engine/sqlw"
  14. "golang-fave/logger"
  15. "golang-fave/utils"
  16. "github.com/vladimirok5959/golang-server-sessions/session"
  17. )
  18. type Tx = sqlw.Tx
  19. var ErrNoRows = sqlw.ErrNoRows
  20. type Wrapper struct {
  21. l *logger.Logger
  22. W http.ResponseWriter
  23. R *http.Request
  24. S *session.Session
  25. Host string
  26. Port string
  27. CurrHost string
  28. DConfig string
  29. DHtdocs string
  30. DLogs string
  31. DTemplate string
  32. DTmp string
  33. IsBackend bool
  34. ConfMysqlExists bool
  35. UrlArgs []string
  36. CurrModule string
  37. CurrSubModule string
  38. MSPool *mysqlpool.MySqlPool
  39. DB *sqlw.DB
  40. User *utils.MySql_user
  41. }
  42. 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 {
  43. return &Wrapper{
  44. l: l,
  45. W: w,
  46. R: r,
  47. S: s,
  48. Host: host,
  49. Port: port,
  50. CurrHost: chost,
  51. DConfig: dirConfig,
  52. DHtdocs: dirHtdocs,
  53. DLogs: dirLogs,
  54. DTemplate: dirTemplate,
  55. DTmp: dirTmp,
  56. UrlArgs: []string{},
  57. CurrModule: "",
  58. CurrSubModule: "",
  59. MSPool: mp,
  60. }
  61. }
  62. func (this *Wrapper) LogAccess(msg string, vars ...interface{}) {
  63. this.l.Log(msg, this.R, false, vars...)
  64. }
  65. func (this *Wrapper) LogError(msg string, vars ...interface{}) {
  66. this.l.Log(msg, this.R, true, vars...)
  67. }
  68. func (this *Wrapper) dbReconnect() error {
  69. if !utils.IsMySqlConfigExists(this.DConfig + string(os.PathSeparator) + "mysql.json") {
  70. return errors.New("can't read database configuration file")
  71. }
  72. mc, err := utils.MySqlConfigRead(this.DConfig + string(os.PathSeparator) + "mysql.json")
  73. if err != nil {
  74. return err
  75. }
  76. this.DB, err = sqlw.Open("mysql", mc.User+":"+mc.Password+"@tcp("+mc.Host+":"+mc.Port+")/"+mc.Name)
  77. if err != nil {
  78. return err
  79. }
  80. this.MSPool.Set(this.CurrHost, this.DB)
  81. return nil
  82. }
  83. func (this *Wrapper) UseDatabase() error {
  84. this.DB = this.MSPool.Get(this.CurrHost)
  85. if this.DB == nil {
  86. if err := this.dbReconnect(); err != nil {
  87. return err
  88. }
  89. }
  90. if err := this.DB.Ping(); err != nil {
  91. this.DB.Close()
  92. if err := this.dbReconnect(); err != nil {
  93. return err
  94. }
  95. if err := this.DB.Ping(); err != nil {
  96. this.DB.Close()
  97. return err
  98. }
  99. }
  100. // Max 30 minutes and max 2 connection per host
  101. this.DB.SetConnMaxLifetime(time.Minute * 30)
  102. this.DB.SetMaxIdleConns(2)
  103. this.DB.SetMaxOpenConns(2)
  104. return nil
  105. }
  106. func (this *Wrapper) LoadSessionUser() bool {
  107. if this.S.GetInt("UserId", 0) <= 0 {
  108. return false
  109. }
  110. if this.DB == nil {
  111. return false
  112. }
  113. user := &utils.MySql_user{}
  114. err := this.DB.QueryRow(`
  115. SELECT
  116. id,
  117. first_name,
  118. last_name,
  119. email,
  120. password,
  121. admin,
  122. active
  123. FROM
  124. users
  125. WHERE
  126. id = ?
  127. LIMIT 1;`,
  128. this.S.GetInt("UserId", 0),
  129. ).Scan(
  130. &user.A_id,
  131. &user.A_first_name,
  132. &user.A_last_name,
  133. &user.A_email,
  134. &user.A_password,
  135. &user.A_admin,
  136. &user.A_active,
  137. )
  138. if err != nil {
  139. return false
  140. }
  141. if user.A_id != this.S.GetInt("UserId", 0) {
  142. return false
  143. }
  144. this.User = user
  145. return true
  146. }
  147. func (this *Wrapper) Write(data string) {
  148. this.W.Write([]byte(data))
  149. }
  150. func (this *Wrapper) MsgSuccess(msg string) {
  151. this.Write(fmt.Sprintf(
  152. `fave.ShowMsgSuccess('Success!', '%s', false);`,
  153. utils.JavaScriptVarValue(msg)))
  154. }
  155. func (this *Wrapper) MsgError(msg string) {
  156. this.Write(fmt.Sprintf(
  157. `fave.ShowMsgError('Error!', '%s', true);`,
  158. utils.JavaScriptVarValue(msg)))
  159. }
  160. func (this *Wrapper) RenderToString(tcont []byte, data interface{}) string {
  161. tmpl, err := template.New("template").Parse(string(tcont))
  162. if err != nil {
  163. return err.Error()
  164. }
  165. var tpl bytes.Buffer
  166. if err := tmpl.Execute(&tpl, data); err != nil {
  167. return err.Error()
  168. }
  169. return tpl.String()
  170. }
  171. func (this *Wrapper) RenderFrontEnd(tname string, data interface{}, status int) {
  172. tmplFuncs := template.FuncMap{
  173. "plus": func(a, b int) int {
  174. return a + b
  175. },
  176. "minus": func(a, b int) int {
  177. return a - b
  178. },
  179. "multiply": func(a, b int) int {
  180. return a * b
  181. },
  182. "divide": func(a, b int) int {
  183. return a / b
  184. },
  185. "repeat": func(a string, n int) template.HTML {
  186. out := ""
  187. for i := 1; i <= n; i++ {
  188. out += a
  189. }
  190. return template.HTML(out)
  191. },
  192. }
  193. tmpl, err := template.New(tname+".html").Funcs(tmplFuncs).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(),
  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. }