module_index.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  1. package modules
  2. import (
  3. "database/sql"
  4. _ "github.com/go-sql-driver/mysql"
  5. "fmt"
  6. "html"
  7. "net/http"
  8. "os"
  9. "strconv"
  10. "golang-fave/assets"
  11. "golang-fave/consts"
  12. "golang-fave/engine/builder"
  13. "golang-fave/engine/fetdata"
  14. "golang-fave/engine/wrapper"
  15. "golang-fave/utils"
  16. )
  17. func (this *Modules) RegisterModule_Index() *Module {
  18. return this.newModule(MInfo{
  19. WantDB: true,
  20. Mount: "index",
  21. Name: "Pages",
  22. Order: 0,
  23. Icon: assets.SysSvgIconPage,
  24. Sub: &[]MISub{
  25. {Mount: "default", Name: "List of pages", Show: true, Icon: assets.SysSvgIconList},
  26. {Mount: "add", Name: "Add new page", Show: true, Icon: assets.SysSvgIconPlus},
  27. {Mount: "modify", Name: "Modify page", Show: false},
  28. },
  29. }, func(wrap *wrapper.Wrapper) {
  30. // Front-end
  31. row := &utils.MySql_page{}
  32. err := wrap.DB.QueryRow(`
  33. SELECT
  34. id,
  35. user,
  36. name,
  37. alias,
  38. content,
  39. meta_title,
  40. meta_keywords,
  41. meta_description,
  42. UNIX_TIMESTAMP(datetime) as datetime,
  43. active
  44. FROM
  45. pages
  46. WHERE
  47. active = 1 and
  48. alias = ?
  49. LIMIT 1;`,
  50. wrap.R.URL.Path,
  51. ).Scan(
  52. &row.A_id,
  53. &row.A_user,
  54. &row.A_name,
  55. &row.A_alias,
  56. &row.A_content,
  57. &row.A_meta_title,
  58. &row.A_meta_keywords,
  59. &row.A_meta_description,
  60. &row.A_datetime,
  61. &row.A_active,
  62. )
  63. if err != nil && err != sql.ErrNoRows {
  64. // System error 500
  65. utils.SystemErrorPageEngine(wrap.W, err)
  66. return
  67. } else if err == sql.ErrNoRows {
  68. // User error 404 page
  69. wrap.W.WriteHeader(http.StatusNotFound)
  70. wrap.RenderFrontEnd("404", fetdata.New(wrap, nil, true))
  71. return
  72. }
  73. // Replace title with page name
  74. if row.A_meta_title == "" {
  75. row.A_meta_title = row.A_name
  76. }
  77. // Which template
  78. tmpl_name := "index"
  79. if wrap.R.URL.Path != "/" {
  80. tmpl_name = "page"
  81. }
  82. // Render template
  83. wrap.RenderFrontEnd(tmpl_name, fetdata.New(wrap, row, false))
  84. }, func(wrap *wrapper.Wrapper) (string, string, string) {
  85. content := ""
  86. sidebar := ""
  87. if wrap.CurrSubModule == "" || wrap.CurrSubModule == "default" {
  88. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  89. {Name: "List of pages"},
  90. })
  91. content += builder.DataTable(
  92. wrap,
  93. "pages",
  94. "id",
  95. "DESC",
  96. &[]builder.DataTableRow{
  97. {
  98. DBField: "id",
  99. },
  100. {
  101. DBField: "name",
  102. NameInTable: "Page / Alias",
  103. CallBack: func(values *[]string) string {
  104. name := `<a href="/cp/` + wrap.CurrModule + `/modify/` + (*values)[0] + `/">` + html.EscapeString((*values)[1]) + `</a>`
  105. alias := html.EscapeString((*values)[2])
  106. return `<div>` + name + `</div><div><small>` + alias + `</small></div>`
  107. },
  108. },
  109. {
  110. DBField: "alias",
  111. },
  112. {
  113. DBField: "datetime",
  114. DBExp: "UNIX_TIMESTAMP(`datetime`)",
  115. NameInTable: "Date / Time",
  116. Classes: "d-none d-md-table-cell",
  117. CallBack: func(values *[]string) string {
  118. t := int64(utils.StrToInt((*values)[3]))
  119. return `<div>` + utils.UnixTimestampToFormat(t, "02.01.2006") + `</div>` +
  120. `<div><small>` + utils.UnixTimestampToFormat(t, "15:04:05") + `</small></div>`
  121. },
  122. },
  123. {
  124. DBField: "active",
  125. NameInTable: "Active",
  126. Classes: "d-none d-sm-table-cell",
  127. CallBack: func(values *[]string) string {
  128. return builder.CheckBox(utils.StrToInt((*values)[4]))
  129. },
  130. },
  131. },
  132. func(values *[]string) string {
  133. return builder.DataTableAction(&[]builder.DataTableActionRow{
  134. {
  135. Icon: assets.SysSvgIconView,
  136. Href: (*values)[2],
  137. Hint: "View",
  138. Target: "_blank",
  139. },
  140. {
  141. Icon: assets.SysSvgIconEdit,
  142. Href: "/cp/" + wrap.CurrModule + "/modify/" + (*values)[0] + "/",
  143. Hint: "Edit",
  144. },
  145. {
  146. Icon: assets.SysSvgIconRemove,
  147. Href: "javascript:fave.ActionDataTableDelete(this,'index-delete','" +
  148. (*values)[0] + "','Are you sure want to delete page?');",
  149. Hint: "Delete",
  150. Classes: "delete",
  151. },
  152. })
  153. },
  154. "/cp/"+wrap.CurrModule+"/",
  155. nil,
  156. nil,
  157. )
  158. } else if wrap.CurrSubModule == "add" || wrap.CurrSubModule == "modify" {
  159. if wrap.CurrSubModule == "add" {
  160. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  161. {Name: "Add new page"},
  162. })
  163. } else {
  164. content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
  165. {Name: "Modify page"},
  166. })
  167. }
  168. data := utils.MySql_page{
  169. A_id: 0,
  170. A_user: 0,
  171. A_name: "",
  172. A_alias: "",
  173. A_content: "",
  174. A_meta_title: "",
  175. A_meta_keywords: "",
  176. A_meta_description: "",
  177. A_datetime: 0,
  178. A_active: 0,
  179. }
  180. if wrap.CurrSubModule == "modify" {
  181. if len(wrap.UrlArgs) != 3 {
  182. return "", "", ""
  183. }
  184. if !utils.IsNumeric(wrap.UrlArgs[2]) {
  185. return "", "", ""
  186. }
  187. err := wrap.DB.QueryRow(`
  188. SELECT
  189. id,
  190. user,
  191. name,
  192. alias,
  193. content,
  194. meta_title,
  195. meta_keywords,
  196. meta_description,
  197. active
  198. FROM
  199. pages
  200. WHERE
  201. id = ?
  202. LIMIT 1;`,
  203. utils.StrToInt(wrap.UrlArgs[2]),
  204. ).Scan(
  205. &data.A_id,
  206. &data.A_user,
  207. &data.A_name,
  208. &data.A_alias,
  209. &data.A_content,
  210. &data.A_meta_title,
  211. &data.A_meta_keywords,
  212. &data.A_meta_description,
  213. &data.A_active,
  214. )
  215. if err != nil {
  216. return "", "", ""
  217. }
  218. }
  219. btn_caption := "Add"
  220. if wrap.CurrSubModule == "modify" {
  221. btn_caption = "Save"
  222. }
  223. content += builder.DataForm(wrap, []builder.DataFormField{
  224. {
  225. Kind: builder.DFKHidden,
  226. Name: "action",
  227. Value: "index-modify",
  228. },
  229. {
  230. Kind: builder.DFKHidden,
  231. Name: "id",
  232. Value: utils.IntToStr(data.A_id),
  233. },
  234. {
  235. Kind: builder.DFKText,
  236. Caption: "Page name",
  237. Name: "name",
  238. Value: data.A_name,
  239. },
  240. {
  241. Kind: builder.DFKText,
  242. Caption: "Page alias",
  243. Name: "alias",
  244. Value: data.A_alias,
  245. Hint: "Example: /about-us/ or /about-us.html",
  246. },
  247. {
  248. Kind: builder.DFKTextArea,
  249. Caption: "Page content",
  250. Name: "content",
  251. Value: data.A_content,
  252. Classes: "autosize",
  253. },
  254. {
  255. Kind: builder.DFKText,
  256. Caption: "Meta title",
  257. Name: "meta_title",
  258. Value: data.A_meta_title,
  259. },
  260. {
  261. Kind: builder.DFKText,
  262. Caption: "Meta keywords",
  263. Name: "meta_keywords",
  264. Value: data.A_meta_keywords,
  265. },
  266. {
  267. Kind: builder.DFKTextArea,
  268. Caption: "Meta description",
  269. Name: "meta_description",
  270. Value: data.A_meta_description,
  271. },
  272. {
  273. Kind: builder.DFKCheckBox,
  274. Caption: "Active",
  275. Name: "active",
  276. Value: utils.IntToStr(data.A_active),
  277. },
  278. {
  279. Kind: builder.DFKMessage,
  280. },
  281. {
  282. Kind: builder.DFKSubmit,
  283. Value: btn_caption,
  284. Target: "add-edit-button",
  285. },
  286. })
  287. if wrap.CurrSubModule == "add" {
  288. sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Add</button>`
  289. } else {
  290. sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Save</button>`
  291. }
  292. }
  293. return this.getSidebarModules(wrap), content, sidebar
  294. })
  295. }
  296. func (this *Modules) RegisterAction_IndexModify() *Action {
  297. return this.newAction(AInfo{
  298. WantDB: true,
  299. Mount: "index-modify",
  300. WantAdmin: true,
  301. }, func(wrap *wrapper.Wrapper) {
  302. pf_id := wrap.R.FormValue("id")
  303. pf_name := wrap.R.FormValue("name")
  304. pf_alias := wrap.R.FormValue("alias")
  305. pf_content := wrap.R.FormValue("content")
  306. pf_meta_title := wrap.R.FormValue("meta_title")
  307. pf_meta_keywords := wrap.R.FormValue("meta_keywords")
  308. pf_meta_description := wrap.R.FormValue("meta_description")
  309. pf_active := wrap.R.FormValue("active")
  310. if pf_active == "" {
  311. pf_active = "0"
  312. }
  313. if !utils.IsNumeric(pf_id) {
  314. wrap.MsgError(`Inner system error`)
  315. return
  316. }
  317. if pf_name == "" {
  318. wrap.MsgError(`Please specify page name`)
  319. return
  320. }
  321. if pf_alias == "" {
  322. pf_alias = utils.GenerateAlias(pf_name)
  323. }
  324. if !utils.IsValidAlias(pf_alias) {
  325. wrap.MsgError(`Please specify correct page alias`)
  326. return
  327. }
  328. if pf_id == "0" {
  329. // Add new page
  330. _, err := wrap.DB.Query(
  331. `INSERT INTO pages SET
  332. user = ?,
  333. name = ?,
  334. alias = ?,
  335. content = ?,
  336. meta_title = ?,
  337. meta_keywords = ?,
  338. meta_description = ?,
  339. datetime = ?,
  340. active = ?
  341. ;`,
  342. wrap.User.A_id,
  343. pf_name,
  344. pf_alias,
  345. pf_content,
  346. pf_meta_title,
  347. pf_meta_keywords,
  348. pf_meta_description,
  349. utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
  350. pf_active,
  351. )
  352. if err != nil {
  353. wrap.MsgError(err.Error())
  354. return
  355. }
  356. wrap.Write(`window.location='/cp/';`)
  357. } else {
  358. // Update page
  359. _, err := wrap.DB.Query(
  360. `UPDATE pages SET
  361. name = ?,
  362. alias = ?,
  363. content = ?,
  364. meta_title = ?,
  365. meta_keywords = ?,
  366. meta_description = ?,
  367. active = ?
  368. WHERE
  369. id = ?
  370. ;`,
  371. pf_name,
  372. pf_alias,
  373. pf_content,
  374. pf_meta_title,
  375. pf_meta_keywords,
  376. pf_meta_description,
  377. pf_active,
  378. utils.StrToInt(pf_id),
  379. )
  380. if err != nil {
  381. wrap.MsgError(err.Error())
  382. return
  383. }
  384. wrap.Write(`window.location='/cp/index/modify/` + pf_id + `/';`)
  385. }
  386. })
  387. }
  388. func (this *Modules) RegisterAction_IndexDelete() *Action {
  389. return this.newAction(AInfo{
  390. WantDB: true,
  391. Mount: "index-delete",
  392. WantAdmin: true,
  393. }, func(wrap *wrapper.Wrapper) {
  394. pf_id := wrap.R.FormValue("id")
  395. if !utils.IsNumeric(pf_id) {
  396. wrap.MsgError(`Inner system error`)
  397. return
  398. }
  399. // Delete page
  400. _, err := wrap.DB.Query(
  401. `DELETE FROM pages WHERE id = ?;`,
  402. utils.StrToInt(pf_id),
  403. )
  404. if err != nil {
  405. wrap.MsgError(err.Error())
  406. return
  407. }
  408. // Reload current page
  409. wrap.Write(`window.location.reload(false);`)
  410. })
  411. }
  412. func (this *Modules) RegisterAction_IndexMysqlSetup() *Action {
  413. return this.newAction(AInfo{
  414. WantDB: false,
  415. Mount: "index-mysql-setup",
  416. }, func(wrap *wrapper.Wrapper) {
  417. pf_host := wrap.R.FormValue("host")
  418. pf_port := wrap.R.FormValue("port")
  419. pf_name := wrap.R.FormValue("name")
  420. pf_user := wrap.R.FormValue("user")
  421. pf_password := wrap.R.FormValue("password")
  422. if pf_host == "" {
  423. wrap.MsgError(`Please specify host for MySQL connection`)
  424. return
  425. }
  426. if pf_port == "" {
  427. wrap.MsgError(`Please specify host port for MySQL connection`)
  428. return
  429. }
  430. if _, err := strconv.Atoi(pf_port); err != nil {
  431. wrap.MsgError(`MySQL host port must be integer number`)
  432. return
  433. }
  434. if pf_name == "" {
  435. wrap.MsgError(`Please specify MySQL database name`)
  436. return
  437. }
  438. if pf_user == "" {
  439. wrap.MsgError(`Please specify MySQL user`)
  440. return
  441. }
  442. // Security, check if still need to run this action
  443. if wrap.ConfMysqlExists {
  444. wrap.MsgError(`CMS is already configured`)
  445. return
  446. }
  447. // Try connect to mysql
  448. db, err := sql.Open("mysql", pf_user+":"+pf_password+"@tcp("+pf_host+":"+pf_port+")/"+pf_name)
  449. if err != nil {
  450. wrap.MsgError(err.Error())
  451. return
  452. }
  453. defer db.Close()
  454. err = db.Ping()
  455. if err != nil {
  456. wrap.MsgError(err.Error())
  457. return
  458. }
  459. // Try to install all tables
  460. _, err = db.Query(fmt.Sprintf(
  461. `CREATE TABLE %s.users (
  462. id int(11) NOT NULL AUTO_INCREMENT COMMENT 'AI',
  463. first_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'User first name',
  464. last_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'User last name',
  465. email VARCHAR(64) NOT NULL COMMENT 'User email',
  466. password VARCHAR(32) NOT NULL COMMENT 'User password (MD5)',
  467. admin int(1) NOT NULL COMMENT 'Is admin user or not',
  468. active int(1) NOT NULL COMMENT 'Is active user or not',
  469. PRIMARY KEY (id)
  470. ) ENGINE = InnoDB;`,
  471. pf_name))
  472. if err != nil {
  473. wrap.MsgError(err.Error())
  474. return
  475. }
  476. _, err = db.Query(fmt.Sprintf(
  477. `ALTER TABLE %s.users ADD UNIQUE KEY email (email);`,
  478. pf_name))
  479. if err != nil {
  480. wrap.MsgError(err.Error())
  481. return
  482. }
  483. _, err = db.Query(fmt.Sprintf(
  484. `CREATE TABLE %s.pages (
  485. id int(11) NOT NULL AUTO_INCREMENT COMMENT 'AI',
  486. user int(11) NOT NULL COMMENT 'User id',
  487. name varchar(255) NOT NULL COMMENT 'Page name',
  488. alias varchar(255) NOT NULL COMMENT 'Page url part',
  489. content text NOT NULL COMMENT 'Page content',
  490. meta_title varchar(255) NOT NULL DEFAULT '' COMMENT 'Page meta title',
  491. meta_keywords varchar(255) NOT NULL DEFAULT '' COMMENT 'Page meta keywords',
  492. meta_description varchar(510) NOT NULL DEFAULT '' COMMENT 'Page meta description',
  493. datetime datetime NOT NULL COMMENT 'Creation date/time',
  494. active int(1) NOT NULL COMMENT 'Is active page or not',
  495. PRIMARY KEY (id)
  496. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`,
  497. pf_name))
  498. if err != nil {
  499. wrap.MsgError(err.Error())
  500. return
  501. }
  502. _, err = wrap.DB.Query(
  503. `INSERT INTO %s.pages SET
  504. id = ?,
  505. user = ?,
  506. name = ?,
  507. alias = ?,
  508. content = ?,
  509. datetime = ?,
  510. active = ?
  511. ;`,
  512. pf_name,
  513. 1,
  514. 1,
  515. "Home",
  516. "/",
  517. "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Feugiat in ante metus dictum at tempor commodo ullamcorper a. Et malesuada fames ac turpis egestas sed tempus urna et. Euismod elementum nisi quis eleifend. Nisi porta lorem mollis aliquam ut porttitor. Ac turpis egestas maecenas pharetra convallis posuere. Nunc non blandit massa enim nec dui. Commodo elit at imperdiet dui accumsan sit amet nulla. Viverra accumsan in nisl nisi scelerisque. Dui nunc mattis enim ut tellus. Molestie ac feugiat sed lectus vestibulum mattis ullamcorper. Faucibus ornare suspendisse sed nisi lacus. Nulla facilisi morbi tempus iaculis. Ut eu sem integer vitae justo eget magna fermentum iaculis. Ullamcorper sit amet risus nullam eget felis eget nunc. Volutpat sed cras ornare arcu dui vivamus. Eget magna fermentum iaculis eu non diam.</p><p>Arcu ac tortor dignissim convallis aenean et tortor. Vitae auctor eu augue ut lectus arcu. Ac turpis egestas integer eget aliquet nibh praesent. Interdum velit euismod in pellentesque massa placerat duis. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio ut enim blandit volutpat. Ac auctor augue mauris augue neque gravida. Ut lectus arcu bibendum at varius vel. Porttitor leo a diam sollicitudin tempor id eu nisl nunc. Dolor sit amet consectetur adipiscing elit duis tristique. Semper quis lectus nulla at volutpat diam ut. Sapien eget mi proin sed.</p><p>Ante metus dictum at tempor commodo ullamcorper a. Facilisis mauris sit amet massa vitae. Enim neque volutpat ac tincidunt vitae. Tempus quam pellentesque nec nam aliquam sem. Mollis aliquam ut porttitor leo a diam sollicitudin. Nunc pulvinar sapien et ligula ullamcorper. Dignissim suspendisse in est ante in nibh mauris. Eget egestas purus viverra accumsan in. Vitae tempus quam pellentesque nec nam aliquam sem et. Sodales ut etiam sit amet nisl. Aliquet risus feugiat in ante. Rhoncus urna neque viverra justo nec ultrices dui sapien. Sit amet aliquam id diam maecenas ultricies. Sed odio morbi quis commodo odio aenean sed adipiscing diam.</p>",
  518. utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
  519. 1,
  520. )
  521. if err != nil {
  522. wrap.MsgError(err.Error())
  523. return
  524. }
  525. _, err = wrap.DB.Query(
  526. `INSERT INTO %s.pages SET
  527. id = ?,
  528. user = ?,
  529. name = ?,
  530. alias = ?,
  531. content = ?,
  532. datetime = ?,
  533. active = ?
  534. ;`,
  535. pf_name,
  536. 2,
  537. 1,
  538. "Another",
  539. "/another/",
  540. "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Feugiat in ante metus dictum at tempor commodo ullamcorper a. Et malesuada fames ac turpis egestas sed tempus urna et. Euismod elementum nisi quis eleifend. Nisi porta lorem mollis aliquam ut porttitor. Ac turpis egestas maecenas pharetra convallis posuere. Nunc non blandit massa enim nec dui. Commodo elit at imperdiet dui accumsan sit amet nulla. Viverra accumsan in nisl nisi scelerisque. Dui nunc mattis enim ut tellus. Molestie ac feugiat sed lectus vestibulum mattis ullamcorper. Faucibus ornare suspendisse sed nisi lacus. Nulla facilisi morbi tempus iaculis. Ut eu sem integer vitae justo eget magna fermentum iaculis. Ullamcorper sit amet risus nullam eget felis eget nunc. Volutpat sed cras ornare arcu dui vivamus. Eget magna fermentum iaculis eu non diam.</p><p>Arcu ac tortor dignissim convallis aenean et tortor. Vitae auctor eu augue ut lectus arcu. Ac turpis egestas integer eget aliquet nibh praesent. Interdum velit euismod in pellentesque massa placerat duis. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio ut enim blandit volutpat. Ac auctor augue mauris augue neque gravida. Ut lectus arcu bibendum at varius vel. Porttitor leo a diam sollicitudin tempor id eu nisl nunc. Dolor sit amet consectetur adipiscing elit duis tristique. Semper quis lectus nulla at volutpat diam ut. Sapien eget mi proin sed.</p><p>Ante metus dictum at tempor commodo ullamcorper a. Facilisis mauris sit amet massa vitae. Enim neque volutpat ac tincidunt vitae. Tempus quam pellentesque nec nam aliquam sem. Mollis aliquam ut porttitor leo a diam sollicitudin. Nunc pulvinar sapien et ligula ullamcorper. Dignissim suspendisse in est ante in nibh mauris. Eget egestas purus viverra accumsan in. Vitae tempus quam pellentesque nec nam aliquam sem et. Sodales ut etiam sit amet nisl. Aliquet risus feugiat in ante. Rhoncus urna neque viverra justo nec ultrices dui sapien. Sit amet aliquam id diam maecenas ultricies. Sed odio morbi quis commodo odio aenean sed adipiscing diam.</p>",
  541. utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
  542. 1,
  543. )
  544. if err != nil {
  545. wrap.MsgError(err.Error())
  546. return
  547. }
  548. _, err = wrap.DB.Query(
  549. `INSERT INTO %s.pages SET
  550. id = ?,
  551. user = ?,
  552. name = ?,
  553. alias = ?,
  554. content = ?,
  555. datetime = ?,
  556. active = ?
  557. ;`,
  558. pf_name,
  559. 3,
  560. 1,
  561. "About",
  562. "/about/",
  563. "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Feugiat in ante metus dictum at tempor commodo ullamcorper a. Et malesuada fames ac turpis egestas sed tempus urna et. Euismod elementum nisi quis eleifend. Nisi porta lorem mollis aliquam ut porttitor. Ac turpis egestas maecenas pharetra convallis posuere. Nunc non blandit massa enim nec dui. Commodo elit at imperdiet dui accumsan sit amet nulla. Viverra accumsan in nisl nisi scelerisque. Dui nunc mattis enim ut tellus. Molestie ac feugiat sed lectus vestibulum mattis ullamcorper. Faucibus ornare suspendisse sed nisi lacus. Nulla facilisi morbi tempus iaculis. Ut eu sem integer vitae justo eget magna fermentum iaculis. Ullamcorper sit amet risus nullam eget felis eget nunc. Volutpat sed cras ornare arcu dui vivamus. Eget magna fermentum iaculis eu non diam.</p><p>Arcu ac tortor dignissim convallis aenean et tortor. Vitae auctor eu augue ut lectus arcu. Ac turpis egestas integer eget aliquet nibh praesent. Interdum velit euismod in pellentesque massa placerat duis. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. Nisl rhoncus mattis rhoncus urna neque viverra justo. Odio ut enim blandit volutpat. Ac auctor augue mauris augue neque gravida. Ut lectus arcu bibendum at varius vel. Porttitor leo a diam sollicitudin tempor id eu nisl nunc. Dolor sit amet consectetur adipiscing elit duis tristique. Semper quis lectus nulla at volutpat diam ut. Sapien eget mi proin sed.</p><p>Ante metus dictum at tempor commodo ullamcorper a. Facilisis mauris sit amet massa vitae. Enim neque volutpat ac tincidunt vitae. Tempus quam pellentesque nec nam aliquam sem. Mollis aliquam ut porttitor leo a diam sollicitudin. Nunc pulvinar sapien et ligula ullamcorper. Dignissim suspendisse in est ante in nibh mauris. Eget egestas purus viverra accumsan in. Vitae tempus quam pellentesque nec nam aliquam sem et. Sodales ut etiam sit amet nisl. Aliquet risus feugiat in ante. Rhoncus urna neque viverra justo nec ultrices dui sapien. Sit amet aliquam id diam maecenas ultricies. Sed odio morbi quis commodo odio aenean sed adipiscing diam.</p>",
  564. utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
  565. 1,
  566. )
  567. if err != nil {
  568. wrap.MsgError(err.Error())
  569. return
  570. }
  571. _, err = db.Query(fmt.Sprintf(
  572. `ALTER TABLE %s.pages ADD UNIQUE KEY alias (alias);`,
  573. pf_name))
  574. if err != nil {
  575. wrap.MsgError(err.Error())
  576. return
  577. }
  578. _, err = db.Query(fmt.Sprintf(
  579. `CREATE TABLE %s.blog_posts (
  580. id int(11) NOT NULL AUTO_INCREMENT COMMENT 'AI',
  581. user int(11) NOT NULL COMMENT 'User id',
  582. name varchar(255) NOT NULL COMMENT 'Post name',
  583. alias varchar(255) NOT NULL COMMENT 'Post alias',
  584. content text NOT NULL COMMENT 'Post content',
  585. datetime datetime NOT NULL COMMENT 'Creation date/time',
  586. active int(1) NOT NULL COMMENT 'Is active post or not',
  587. PRIMARY KEY (id)
  588. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`,
  589. pf_name))
  590. if err != nil {
  591. wrap.MsgError(err.Error())
  592. return
  593. }
  594. _, err = db.Query(fmt.Sprintf(
  595. `ALTER TABLE %s.blog_posts ADD UNIQUE KEY alias (alias);`,
  596. pf_name))
  597. if err != nil {
  598. wrap.MsgError(err.Error())
  599. return
  600. }
  601. _, err = db.Query(fmt.Sprintf(
  602. `CREATE TABLE %s.blog_cats (
  603. id int(11) NOT NULL AUTO_INCREMENT COMMENT 'AI',
  604. user int(11) NOT NULL COMMENT 'User id',
  605. name varchar(255) NOT NULL COMMENT 'Category name',
  606. alias varchar(255) NOT NULL COMMENT 'Category alias',
  607. lft int(11) NOT NULL COMMENT 'For nested set model',
  608. rgt int(11) NOT NULL COMMENT 'For nested set model',
  609. PRIMARY KEY (id)
  610. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`,
  611. pf_name))
  612. if err != nil {
  613. wrap.MsgError(err.Error())
  614. return
  615. }
  616. _, err = db.Query(fmt.Sprintf(
  617. `ALTER TABLE %s.blog_cats ADD UNIQUE KEY alias (alias);`,
  618. pf_name))
  619. if err != nil {
  620. wrap.MsgError(err.Error())
  621. return
  622. }
  623. _, err = db.Query(fmt.Sprintf(
  624. `INSERT INTO %s.blog_cats (id, user, name, alias, lft, rgt) VALUES (1, 0, 'ROOT', 'ROOT', 1, 2);`,
  625. pf_name))
  626. if err != nil {
  627. wrap.MsgError(err.Error())
  628. return
  629. }
  630. _, err = db.Query(fmt.Sprintf(
  631. `ALTER TABLE %s.blog_cats ADD KEY lft (lft), ADD KEY rgt (rgt);`,
  632. pf_name))
  633. if err != nil {
  634. wrap.MsgError(err.Error())
  635. return
  636. }
  637. // Save mysql config file
  638. err = utils.MySqlConfigWrite(wrap.DConfig+string(os.PathSeparator)+"mysql.json", pf_host, pf_port, pf_name, pf_user, pf_password)
  639. if err != nil {
  640. wrap.MsgError(err.Error())
  641. return
  642. }
  643. // Reload current page
  644. wrap.Write(`window.location.reload(false);`)
  645. })
  646. }
  647. func (this *Modules) RegisterAction_IndexFirstUser() *Action {
  648. return this.newAction(AInfo{
  649. WantDB: true,
  650. Mount: "index-first-user",
  651. }, func(wrap *wrapper.Wrapper) {
  652. pf_first_name := wrap.R.FormValue("first_name")
  653. pf_last_name := wrap.R.FormValue("last_name")
  654. pf_email := wrap.R.FormValue("email")
  655. pf_password := wrap.R.FormValue("password")
  656. if pf_email == "" {
  657. wrap.MsgError(`Please specify user email`)
  658. return
  659. }
  660. if !utils.IsValidEmail(pf_email) {
  661. wrap.MsgError(`Please specify correct user email`)
  662. return
  663. }
  664. if pf_password == "" {
  665. wrap.MsgError(`Please specify user password`)
  666. return
  667. }
  668. // Security, check if still need to run this action
  669. var count int
  670. err := wrap.DB.QueryRow(`
  671. SELECT
  672. COUNT(*)
  673. FROM
  674. users
  675. ;`,
  676. ).Scan(
  677. &count,
  678. )
  679. if err != nil {
  680. wrap.MsgError(err.Error())
  681. return
  682. }
  683. if count > 0 {
  684. wrap.MsgError(`CMS is already configured`)
  685. return
  686. }
  687. _, err = wrap.DB.Query(
  688. `INSERT INTO users SET
  689. id = 1,
  690. first_name = ?,
  691. last_name = ?,
  692. email = ?,
  693. password = MD5(?),
  694. admin = 1,
  695. active = 1
  696. ;`,
  697. pf_first_name,
  698. pf_last_name,
  699. pf_email,
  700. pf_password,
  701. )
  702. if err != nil {
  703. wrap.MsgError(err.Error())
  704. return
  705. }
  706. // Reload current page
  707. wrap.Write(`window.location.reload(false);`)
  708. })
  709. }
  710. func (this *Modules) RegisterAction_IndexUserSignIn() *Action {
  711. return this.newAction(AInfo{
  712. WantDB: true,
  713. Mount: "index-user-sign-in",
  714. }, func(wrap *wrapper.Wrapper) {
  715. pf_email := wrap.R.FormValue("email")
  716. pf_password := wrap.R.FormValue("password")
  717. if pf_email == "" {
  718. wrap.MsgError(`Please specify user email`)
  719. return
  720. }
  721. if !utils.IsValidEmail(pf_email) {
  722. wrap.MsgError(`Please specify correct user email`)
  723. return
  724. }
  725. if pf_password == "" {
  726. wrap.MsgError(`Please specify user password`)
  727. return
  728. }
  729. if wrap.S.GetInt("UserId", 0) > 0 {
  730. wrap.MsgError(`You already logined`)
  731. return
  732. }
  733. var user_id int
  734. err := wrap.DB.QueryRow(
  735. `SELECT
  736. id
  737. FROM
  738. users
  739. WHERE
  740. email = ? and
  741. password = MD5(?) and
  742. admin = 1 and
  743. active = 1
  744. LIMIT 1;`,
  745. pf_email,
  746. pf_password,
  747. ).Scan(
  748. &user_id,
  749. )
  750. if err != nil && err != sql.ErrNoRows {
  751. wrap.MsgError(err.Error())
  752. return
  753. }
  754. if err == sql.ErrNoRows {
  755. wrap.MsgError(`Incorrect email or password`)
  756. return
  757. }
  758. // Save to current session
  759. wrap.S.SetInt("UserId", user_id)
  760. // Reload current page
  761. wrap.Write(`window.location.reload(false);`)
  762. })
  763. }
  764. func (this *Modules) RegisterAction_IndexUserLogout() *Action {
  765. return this.newAction(AInfo{
  766. WantDB: true,
  767. Mount: "index-user-logout",
  768. WantUser: true,
  769. }, func(wrap *wrapper.Wrapper) {
  770. // Reset session var
  771. wrap.S.SetInt("UserId", 0)
  772. // Reload current page
  773. wrap.Write(`window.location.reload(false);`)
  774. })
  775. }
  776. func (this *Modules) RegisterAction_IndexUserUpdateProfile() *Action {
  777. return this.newAction(AInfo{
  778. WantDB: true,
  779. Mount: "index-user-update-profile",
  780. WantUser: true,
  781. }, func(wrap *wrapper.Wrapper) {
  782. pf_first_name := wrap.R.FormValue("first_name")
  783. pf_last_name := wrap.R.FormValue("last_name")
  784. pf_email := wrap.R.FormValue("email")
  785. pf_password := wrap.R.FormValue("password")
  786. if pf_email == "" {
  787. wrap.MsgError(`Please specify user email`)
  788. return
  789. }
  790. if !utils.IsValidEmail(pf_email) {
  791. wrap.MsgError(`Please specify correct user email`)
  792. return
  793. }
  794. if pf_password != "" {
  795. // Update with password if set
  796. _, err := wrap.DB.Query(
  797. `UPDATE users SET
  798. first_name = ?,
  799. last_name = ?,
  800. email = ?,
  801. password = MD5(?)
  802. WHERE
  803. id = ?
  804. ;`,
  805. pf_first_name,
  806. pf_last_name,
  807. pf_email,
  808. pf_password,
  809. wrap.User.A_id,
  810. )
  811. if err != nil {
  812. wrap.MsgError(err.Error())
  813. return
  814. }
  815. } else {
  816. // Update without password if not set
  817. _, err := wrap.DB.Query(
  818. `UPDATE users SET
  819. first_name = ?,
  820. last_name = ?,
  821. email = ?
  822. WHERE
  823. id = ?
  824. ;`,
  825. pf_first_name,
  826. pf_last_name,
  827. pf_email,
  828. wrap.User.A_id,
  829. )
  830. if err != nil {
  831. wrap.MsgError(err.Error())
  832. return
  833. }
  834. }
  835. // Reload current page
  836. wrap.Write(`window.location.reload(false);`)
  837. })
  838. }