Blob: app.lua

Blob id: 57bd421a3b3229378e3a33d4bb369efece0e7c85

Size: 4.1 KB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
local lapis = require("lapis")
local bcrypt = require("bcrypt")
local db = require("lapis.db")
local app = lapis.Application()
local respond_to = require("lapis.application").respond_to

app:enable("etlua")
app.layout = require "views.layout"

-- removes leading and trailing spaces
local function strip(str)
   return str:match( "^%s*(.-)%s*$" )
end

-- checks if str is number (not float)
local function isNumber(str)
    if not str:match("^%-?%d+$") then
	return false
    else
	return true
    end
end

-- opens and checks if file exists
local function file_exists(file)
  local f = io.open(file, "rb")
  if f then f:close() end
  return f ~= nil
end

-- returns a table with lines in file
local function lines_from(file)
  if not file_exists(file) then return {} end
  local lines = {}
  for line in io.lines(file) do
    lines[#lines + 1] = line
  end
  return lines
end


local function readTeamDesc()
    local lines = lines_from("team-description.txt")
    if lines then
	return lines[1]
    end
    return nil
end

app:get("index", "/", function(self)
    local res = db.query("SELECT * FROM asunnot")
    self.asunnot = res
    self.team_desc = readTeamDesc()
    return { render = true }
end)

app:post("edit-description", "/edit-description", function(self)
    if not self.session.user then
	return { redirect_to = "/" }
    end

    local new_desc = strip(self.params.description)
    if not file_exists("team-description.txt") then return {} end
    local f = io.open("team-description.txt", "w")

    if f == nil then
	return { redirect_to = "/" }
    end

    f:write(new_desc)
    f:close()
    return { redirect_to = "/" }
end)

app:match("kirjaudu", "/kirjaudu", respond_to({
  GET = function(self)
    self.err = self.params.error
    return { render = true }
  end,

  POST = function(self)
    local name = strip(self.params.name)
    local password = strip(self.params.password)

    if name == "" or password == "" then
	return { redirect_to = "/kirjaudu"}
    end

    local user = db.query("SELECT * FROM kayttajat WHERE nimi = ?", name)[1]
    if not user then
	return { redirect_to = self:url_for("kirjaudu", {}, { error = "Käyttäjää ei löytynyt " }) }
    end

    local ok, _ = pcall(function()
	assert(bcrypt.verify(password, user["salasana_hash"]))
    end)

    if user["nimi"] == name and ok then
	self.session.user = {}
	self.session.user.id = user["id"]
	self.session.user.name = user["nimi"]
    else
	return { redirect_to = self:url_for("kirjaudu", {}, { error = "Väärä salasana" }) }
    end

    return { redirect_to = "/hallintapaneeli" }
  end
}))

app:match("kirjaudu-ulos", "/kirjaudu-ulos", function(self)
    self.session.user = nil
    return { redirect_to = "/"}
end)

app:match("hallintapaneeli", "/hallintapaneeli", respond_to({
  before = function(self)
    if not self.session.user then
      self:write({ redirect_to = "/kirjaudu" })
    end
  end,

  GET = function()
    return { render = true }
  end,
  -- luo asunto entry ja muokkaa sivua
  POST = function(self)
    local address = strip(self.params.address)
    local picture_file = self.params.file
    local price = strip(self.params.price)

    local picture = ""
    -- write img binary to file, risky and not validation :D. all params are TRUSTED
    -- path traversal attacks possible
    -- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Disposition#Directives
    local out = io.open("./static/images/" .. picture_file.filename, "wb")
    if out == nil then
	return { redirect_to = "/" }
    end
    -- nginx limits the img size to 1mb by defaykt

    local data = picture_file.content
    data = string.gsub(data, "\r\n", "\n") -- for unix
    out:write(data)
    out:close()

    picture = "http://localhost:8080/static/images/" .. picture_file.filename

    if address == "" or picture == "" or price == "" then
	return { redirect_to = "/hallintapaneeli"}
    end

    if not isNumber(price) then
	return { redirect_to = "/hallintapaneeli"}
    end

    db.query("INSERT INTO asunnot (osoite, kuva, hinta) VALUES (?, ?, ?)", address, picture, price)
    return { redirect_to = "/" }
  end
}))


return app