local orbit = require "orbit" local toycms = ... -- Admin interface function admin(web, section_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/admin") })) else local params = {} if tonumber(section_id) then params.section = models.section:find(tonumber(section_id)) end return admin_layout(web, render_admin(web, params)) end end toycms:dispatch_get(admin, "/admin", "/admin/(%d+)") function login_get(web) return admin_layout(web, render_login(web, web.input)) end function login_post(web) local login = web.input.login local password = web.input.password local user = models.user:find_by_login{ login } if web:empty_param("link_to") then web.input.link_to = web:link("/") end if user then if password == user.password then web:set_cookie("user_id", user.id) web:set_cookie("password", user.password) return web:redirect(web.input.link_to) else return web:redirect(web:link("/login", { login = login, link_to = web.input.link_to, not_match = "1" })) end else return web:redirect(web:link("/login", { login = login, link_to = web.input.link_to, not_found = "1" })) end end toycms:dispatch_get(login_get, "/login") toycms:dispatch_post(login_post, "/login") function add_user_get(web) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/adduser") })) else return admin_layout(web, render_add_user(web, web.input)) end end function add_user_post(web) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/adduser") })) else local errors = {} if web:empty_param("login") then errors.login = strings.blank_user end if web:empty_param("password1") then errors.password = strings.blank_password end if web.input.password1 ~= web.input.password2 then errors.password = strings.password_mismatch end if web:empty_param("name") then errors.name = strings.blank_name end if not next(errors) then local user = models.user:new() user.login = web.input.login user.password = web.input.password1 user.name = web.input.name user:save() return web:redirect(web:link("/admin")) else for k, v in pairs(errors) do web.input["error_" .. k] = v end return web:redirect(web:link("/adduser", web.input)) end end end toycms:dispatch_get(add_user_get, "/adduser") toycms:dispatch_post(add_user_post, "/adduser") function edit_section_get(web, section_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/editsection") })) else section_id = tonumber(section_id) if section_id then web.input.section = models.section:find_by_id{ section_id } else web.input.section = models.section:new() end return admin_layout(web, render_edit_section(web, web.input)) end end function edit_section_post(web, section_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/editsection") })) else section_id = tonumber(section_id) local errors = {} if web:empty_param("title") then errors.title = strings.blank_title end if not next(errors) then local section if section_id then section = models.section:find_by_id{ section_id } else section = models.section:new() end section.title = web.input.title section.description = web.input.description section.tag = web.input.tag section:save() cache:nuke() return web:redirect(web:link("/editsection/" .. section.id)) else for k, v in pairs(errors) do web.input["error_" .. k] = v end if section_id then return web:redirect(web:link("/editsection/" .. section_id, web.input)) else return web:redirect(web:link("/editsection", web.input)) end end end end toycms:dispatch_get(edit_section_get, "/editsection", "/editsection/(%d+)") toycms:dispatch_post(edit_section_post, "/editsection", "/editsection/(%d+)") function delete_section(web, section_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/editsection/" .. section_id) })) else section_id = tonumber(section_id) local section = models.section:find(section_id) if section then section:delete() cache:nuke() return web:redirect(web:link("/admin")) end end end toycms:dispatch_post(delete_section, "/deletesection/(%d+)") function delete_post(web, post_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/editpost/" .. post_id) })) else post_id = tonumber(post_id) local post = models.post:find(post_id) if post then post:delete() cache:nuke() return web:redirect(web:link("/admin")) end end end toycms:dispatch_post(delete_post, "/deletepost/(%d+)") function edit_post_get(web, post_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/editpost") })) else post_id = tonumber(post_id) if post_id then web.input.post = models.post:find_by_id{ post_id } else web.input.post = models.post:new() end web.input.sections = models.section:find_all() return admin_layout(web, render_edit_post(web, web.input)) end end function edit_post_post(web, post_id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/editpost") })) else post_id = tonumber(post_id) local errors = {} if web:empty_param("title") then errors.title = strings.blank_title end if not next(errors) then local post if post_id then post = models.post:find_by_id{ post_id } else post = models.post:new() end post.title = web.input.title post.abstract = web.input.abstract post.image = web.input.image if web:empty_param("published_at") then post.published_at = nil else local day, month, year, hour, minute = string.match(web.input.published_at, "(%d+)-(%d+)-(%d+) (%d+):(%d+)") post.published_at = os.time({ day = day, month = month, year = year, hour = hour, min = minute }) end post.body = web.input.body post.section_id = tonumber(web.input.section_id) post.published = (not web:empty_param("published")) post.external_url = web.input.external_url post.in_home = (not web:empty_param("in_home")) post.user_id = check_user(web).id post.comment_status = web.input.comment_status post:save() cache:nuke() return web:redirect(web:link("/editpost/" .. post.id)) else for k, v in pairs(errors) do web.input["error_" .. k] = v end if post_id then return web:redirect(web:link("/editpost/" .. post_id, web.input)) else return web:redirect(web:link("/editpost", web.input)) end end end end toycms:dispatch_get(edit_post_get, "/editpost", "/editpost/(%d+)") toycms:dispatch_post(edit_post_post, "/editpost", "/editpost/(%d+)") function manage_comments(web) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/comments") })) else local params = {} local post_model = models.post params.for_mod = models.comment:find_all_by_approved{ false, order = "created_at desc", inject = { model = post_model, fields = { "title" } } } params.approved = models.comment:find_all_by_approved{ true, order = "created_at desc", inject = { model = post_model, fields = { "title" } } } return admin_layout(web, render_manage_comments(web, params)) end end toycms:dispatch_get(manage_comments, "/comments") function approve_comment(web, id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/comments#" .. id) })) else local comment = models.comment:find(tonumber(id)) if comment then comment.approved = true comment:save() local post = models.post:find(comment.post_id) post.n_comments = (post.n_comments or 0) + 1 post:save() cache:invalidate("/", "/xml", "/section/" .. post.section_id, "/section/" .. post.section_id .. "/xml", "/post/" .. post.id, "/post/" .. post.id .. "/xml", "/archive/" .. string.format("%Y/%m", post.published_at)) return web:redirect(web:link("/comments#" .. id)) end end end toycms:dispatch_post(approve_comment, "/comment/(%d+)/approve") function delete_comment(web, id) if not check_user(web) then return web:redirect(web:link("/login", { link_to = web:link("/comments#" .. id) })) else local comment = models.comment:find(tonumber(id)) if comment then if comment.approved then local post = models.post:find(comment.post_id) post.n_comments = post.n_comments - 1 post:save() cache:invalidate("/", "/xml", "/section/" .. post.section_id, "/section/" .. post.section_id .. "/xml", "/post/" .. post.id, "/post/" .. post.id .. "/xml", "/archive/" .. string.format("%Y/%m", post.published_at)) end comment:delete() return web:redirect(web:link("/comments")) end end end toycms:dispatch_post(delete_comment, "/comment/(%d+)/delete") toycms:dispatch_static("/admin_style%.css") local function error_message(msg) return "" .. msg .. "" end function admin_layout(web, inner_html) return html{ head{ title"ToyCMS Admin", meta{ ["http-equiv"] = "Content-Type", content = "text/html; charset=utf-8" }, link{ rel = 'stylesheet', type = 'text/css', href = web:static_link('/admin_style.css'), media = 'screen' } }, body{ div{ id = "container", div{ id = "header", title = "sitename", "ToyCMS Admin" }, div{ id = "mainnav", ul { li{ a{ href = web:link("/admin"), strings.admin_home } }, li{ a{ href = web:link("/adduser"), strings.new_user } }, li{ a{ href = web:link("/editsection"), strings.new_section } }, li{ a{ href = web:link("/editpost"), strings.new_post } }, li{ a{ href = web:link("/comments"), strings.manage_comments } }, } }, div{ id = "menu", _admin_menu(web, args) }, div{ id = "contents", inner_html }, div{ id = "footer", "Copyright 2007 Fabio Mascarenhas" } } } } end function _admin_menu(web) local res = {} local user = check_user(web) if user then res[#res + 1] = ul{ li{ strings.logged_as, (user.name or user.login) } } res[#res + 1] = h3(strings.sections) local section_list = {} local sections = models.section:find_all() for _, section in ipairs(sections) do section_list[#section_list + 1] = li{ a{ href=web:link("/admin/" .. section.id), section.title } } end res[#res + 1] = ul(table.concat(section_list,"\n")) end return table.concat(res, "\n") end function render_admin(web, params) local section_list local sections = models.section:find_all({ order = "id asc" }) if params.section then local section = params.section local res_section = {} res_section[#res_section + 1] = "
" for _, post in ipairs(posts) do local in_home, published = "", "" if post.in_home then in_home = " [HOME]" end if post.published then published = " [P]" end res_section[#res_section + 1] = a{ href = web:link("/editpost/" .. post.id), post.title } .. in_home .. published .. br() end res_section[#res_section + 1] = "
" res_section[#res_section + 1] = p{ a.button{ href = web:link("/editpost?section_id=" .. section.id), button{ strings.new_post } } } res_section[#res_section + 1] = "" for _, post in ipairs(posts) do local in_home, published = "", "" if post.in_home then in_home = " [HOME]" end if post.published then published = " [P]" end res_section[#res_section + 1] = a{ href = web:link("/editpost/" .. post.id), post.title } .. in_home .. published .. br() end res_section[#res_section + 1] = "
" res_section[#res_section + 1] = p{ a.button { href = web:link("/editpost?section_id=" .. section.id), button{ strings.new_post } } } res_section[#res_section + 1] = "