stations.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import { Elysia } from 'elysia'
  2. import { Eta } from "eta"
  3. const eta = new Eta({ views: "./templates" })
  4. import Auth from '../../../utils/auth';
  5. import Meteostanice from '../../../utils/meteostanice';
  6. import validateTurnstile from '../../../utils/validateTurnstile';
  7. import normalizeEmail from '../../../utils/normalizeEmail';
  8. export default (langName, lang) => new Elysia({ prefix: "/stations" })
  9. .get("/", async ({ cookie, redirect, set }) => {
  10. const token = cookie.session.value
  11. const session = await Auth.getSession(token)
  12. if (!session) {
  13. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  14. }
  15. const user = Auth.getUser(session.email)
  16. const meteostanice = Meteostanice.getOwned(session.email)
  17. set.headers['content-type'] = 'text/html; charset=utf8'
  18. return eta.render(`${langName}/panel/stations/index`, { user, meteostanice })
  19. })
  20. .get("/add", async ({ cookie, redirect, set }) => {
  21. const token = cookie.session.value
  22. const session = await Auth.getSession(token)
  23. if (!session) {
  24. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  25. }
  26. const user = Auth.getUser(session.email)
  27. set.headers['content-type'] = 'text/html; charset=utf8'
  28. return eta.render(`${langName}/panel/stations/add`, { siteKey: process.env.TURNSTILE_SITE_KEY, user })
  29. })
  30. .post("/add", async ({ request, server, cookie, redirect, body, set }) => {
  31. const clientIP = request.headers.get('x-forwarded-for') ?? server.requestIP(request).address
  32. const token = cookie.session.value
  33. const session = await Auth.getSession(token)
  34. if (!session) {
  35. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  36. }
  37. const user = Auth.getUser(session.email)
  38. const turnstileResponse = body?.["cf-turnstile-response"]
  39. if (!turnstileResponse) {
  40. set.headers['content-type'] = 'text/html; charset=utf8'
  41. return eta.render(`${langName}/panel/stations/add`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, error: "turnstile.noToken" })
  42. }
  43. const turnstileValid = await validateTurnstile(turnstileResponse, clientIP)
  44. if (!turnstileValid.success) {
  45. let errorMessage = `turnstile.unavailable`;
  46. if (turnstileValid["error-codes"]?.includes("invalid-input-response"))
  47. errorMessage = `turnstile.invalidResponse`
  48. if (turnstileValid["error-codes"]?.includes("timeout-or-duplicate"))
  49. errorMessage = `turnstile.keyUsedOrExpired`
  50. set.headers['content-type'] = 'text/html; charset=utf8'
  51. return eta.render(`${langName}/panel/stations/add`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, error: errorMessage })
  52. }
  53. let name = body?.name
  54. if (!name) name = "test"
  55. const description = body?.description
  56. Meteostanice.add(session.email, name, description)
  57. return redirect(`/${langName === "sk" ? `` : `${langName}/`}panel/stations`)
  58. })
  59. .get("/:station", async ({ cookie, redirect, set, params: { station } }) => {
  60. const token = cookie.session.value
  61. const session = await Auth.getSession(token)
  62. if (!session) {
  63. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  64. }
  65. const user = Auth.getUser(session.email)
  66. if (!station) {
  67. set.headers['content-type'] = 'text/html; charset=utf8'
  68. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  69. }
  70. const meteostanica = Meteostanice.get(session.email, station)
  71. if (!meteostanica) {
  72. set.headers['content-type'] = 'text/html; charset=utf8'
  73. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  74. }
  75. const data = Meteostanice.getData(meteostanica.id)
  76. set.headers['content-type'] = 'text/html; charset=utf8'
  77. return eta.render(`${langName}/panel/stations/station`, { user, meteostanica, data })
  78. })
  79. .get("/:station/edit", async ({ cookie, redirect, set, params: { station } }) => {
  80. const token = cookie.session.value
  81. const session = await Auth.getSession(token)
  82. if (!session) {
  83. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  84. }
  85. const user = Auth.getUser(session.email)
  86. if (!station) {
  87. set.headers['content-type'] = 'text/html; charset=utf8'
  88. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  89. }
  90. const meteostanica = Meteostanice.get(session.email, station)
  91. if (!meteostanica) {
  92. set.headers['content-type'] = 'text/html; charset=utf8'
  93. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  94. }
  95. set.headers['content-type'] = 'text/html; charset=utf8'
  96. return eta.render(`${langName}/panel/stations/edit`, { siteKey: process.env.TURNSTILE_SITE_KEY, user, meteostanica })
  97. })
  98. .post("/:station/edit", async ({ request, server, cookie, redirect, params: { station }, body, set }) => {
  99. const clientIP = request.headers.get('x-forwarded-for') ?? server.requestIP(request).address
  100. const token = cookie.session.value
  101. const session = await Auth.getSession(token)
  102. if (!session) {
  103. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  104. }
  105. const user = Auth.getUser(session.email)
  106. if (!station) {
  107. set.headers['content-type'] = 'text/html; charset=utf8'
  108. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  109. }
  110. const meteostanica = Meteostanice.get(session.email, station)
  111. if (!meteostanica) {
  112. set.headers['content-type'] = 'text/html; charset=utf8'
  113. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  114. }
  115. const turnstileResponse = body?.["cf-turnstile-response"]
  116. if (!turnstileResponse) {
  117. set.headers['content-type'] = 'text/html; charset=utf8'
  118. return eta.render(`${langName}/panel/stations/edit`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, meteostanica, error: "turnstile.noToken" })
  119. }
  120. const turnstileValid = await validateTurnstile(turnstileResponse, clientIP)
  121. if (!turnstileValid.success) {
  122. let errorMessage = `turnstile.unavailable`;
  123. if (turnstileValid["error-codes"]?.includes("invalid-input-response"))
  124. errorMessage = `turnstile.invalidResponse`
  125. if (turnstileValid["error-codes"]?.includes("timeout-or-duplicate"))
  126. errorMessage = `turnstile.keyUsedOrExpired`
  127. set.headers['content-type'] = 'text/html; charset=utf8'
  128. return eta.render(`${langName}/panel/stations/edit`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, meteostanica, error: errorMessage })
  129. }
  130. const newName = body?.name
  131. if (!newName) {
  132. set.headers['content-type'] = 'text/html; charset=utf8'
  133. return eta.render(`${langName}/panel/stations/edit`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, meteostanica, error: "noName" })
  134. }
  135. const newOwnerEmail = body?.owner
  136. if (!normalizeEmail(newOwnerEmail)) {
  137. set.headers['content-type'] = 'text/html; charset=utf8'
  138. return eta.render(`${langName}/panel/stations/edit`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, meteostanica, error: "invalidOwner" })
  139. }
  140. const newOwner = Auth.getUser(newOwnerEmail)
  141. if (!newOwner) {
  142. set.headers['content-type'] = 'text/html; charset=utf8'
  143. return eta.render(`${langName}/panel/stations/edit`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user, meteostanica, error: "ownerUserNotFound", errorDetails: { newOwnerEmail } })
  144. }
  145. const newDescription = body?.description
  146. Meteostanice.edit(meteostanica.id, newName, newDescription, newOwnerEmail)
  147. return redirect(`/${langName === "sk" ? `` : `${langName}/`}panel/stations/${meteostanica.id}`)
  148. })
  149. .get("/:station/resetWebsocketKey", async ({ cookie, redirect, set, params: { station } }) => {
  150. const token = cookie.session.value
  151. const session = await Auth.getSession(token)
  152. if (!session) {
  153. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  154. }
  155. const user = Auth.getUser(session.email)
  156. if (!station) {
  157. set.headers['content-type'] = 'text/html; charset=utf8'
  158. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  159. }
  160. const meteostanica = Meteostanice.get(session.email, station)
  161. if (!meteostanica) {
  162. set.headers['content-type'] = 'text/html; charset=utf8'
  163. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  164. }
  165. Meteostanice.resetWebsocketKey(meteostanica.id)
  166. return redirect(`/${langName === "sk" ? `` : `${langName}/`}panel/stations/${meteostanica.id}`)
  167. })
  168. .get("/:station/remove", async ({ cookie, redirect, set, params: { station } }) => {
  169. const token = cookie.session.value
  170. const session = await Auth.getSession(token)
  171. if (!session) {
  172. return redirect(`/${langName === "sk" ? `` : `${langName}/`}auth?error=loginNeeded`)
  173. }
  174. const user = Auth.getUser(session.email)
  175. if (!station) {
  176. set.headers['content-type'] = 'text/html; charset=utf8'
  177. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  178. }
  179. const meteostanica = Meteostanice.get(session.email, station)
  180. if (!meteostanica) {
  181. set.headers['content-type'] = 'text/html; charset=utf8'
  182. return eta.render(`${langName}/panel/stations/notFound`, { siteKey: process.env.TURNSTILE_SITE_KEY, lang, user })
  183. }
  184. Meteostanice.remove(meteostanica.id)
  185. return redirect(`/${langName === "sk" ? `` : `${langName}/`}panel/stations`)
  186. })