users.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. // Package users provides Lua functions for dealing with users and permissions
  2. package users
  3. import (
  4. "net/http"
  5. log "github.com/sirupsen/logrus"
  6. "github.com/xyproto/algernon/lua/convert"
  7. lua "github.com/xyproto/gopher-lua"
  8. "github.com/xyproto/pinterface"
  9. "github.com/xyproto/simplejwt"
  10. )
  11. // Load makes functions related to users and permissions available to Lua scripts
  12. func Load(w http.ResponseWriter, req *http.Request, L *lua.LState, userstate pinterface.IUserState) {
  13. // Check if the current user has "user rights", returns bool
  14. // Takes no arguments
  15. L.SetGlobal("UserRights", L.NewFunction(func(L *lua.LState) int {
  16. L.Push(lua.LBool(userstate.UserRights(req)))
  17. return 1 // number of results
  18. }))
  19. // Check if the given username exists, returns bool
  20. // Takes a username
  21. L.SetGlobal("HasUser", L.NewFunction(func(L *lua.LState) int {
  22. username := L.ToString(1)
  23. L.Push(lua.LBool(userstate.HasUser(username)))
  24. return 1 // number of results
  25. }))
  26. // Check if the given unconfirmed username exists, returns bool
  27. // Takes a username
  28. L.SetGlobal("HasUnconfirmedUser", L.NewFunction(func(L *lua.LState) int {
  29. username := L.ToString(1)
  30. found := false
  31. unconfirmedUsernames, err := userstate.AllUnconfirmedUsernames()
  32. if err != nil {
  33. log.Warn("Could not read the lsit of unconfirmed usernames.")
  34. L.Push(lua.LBool(false))
  35. return 1 // number of results
  36. }
  37. for _, unconfirmedUsername := range unconfirmedUsernames {
  38. if unconfirmedUsername == username {
  39. found = true
  40. break
  41. }
  42. }
  43. L.Push(lua.LBool(found))
  44. return 1 // number of results
  45. }))
  46. // GenerateToken generates a JWT token given a subject and the number of seconds the token should last
  47. L.SetGlobal("GenerateToken", L.NewFunction(func(L *lua.LState) int {
  48. subject := L.ToString(1)
  49. seconds := int(L.ToNumber(2))
  50. L.Push(lua.LString(simplejwt.SimpleGenerate(subject, seconds)))
  51. return 1 // number of results
  52. }))
  53. // VaildateToken checks if the given token is valid and returns the subject. Returns an empty string if not.
  54. L.SetGlobal("ValidateToken", L.NewFunction(func(L *lua.LState) int {
  55. token := L.ToString(1)
  56. L.Push(lua.LString(simplejwt.SimpleValidate(token)))
  57. return 1 // number of results
  58. }))
  59. // SetTokenSecret sets the secret that will be used when generating and validating JWT tokens
  60. L.SetGlobal("SetTokenSecret", L.NewFunction(func(L *lua.LState) int {
  61. secret := L.ToString(1)
  62. simplejwt.SetSecret(secret)
  63. return 0 // number of results
  64. }))
  65. // Get the value from the given boolean field, returns bool
  66. // Takes a username and field name
  67. L.SetGlobal("BooleanField", L.NewFunction(func(L *lua.LState) int {
  68. username := L.ToString(1)
  69. fieldname := L.ToString(2)
  70. L.Push(lua.LBool(userstate.BooleanField(username, fieldname)))
  71. return 1 // number of results
  72. }))
  73. // Save a value as a boolean field, returns nothing
  74. // Takes a username, field name and boolean value
  75. L.SetGlobal("SetBooleanField", L.NewFunction(func(L *lua.LState) int {
  76. username := L.ToString(1)
  77. fieldname := L.ToString(2)
  78. value := L.ToBool(3)
  79. userstate.SetBooleanField(username, fieldname, value)
  80. return 0 // number of results
  81. }))
  82. // Check if a given username is confirmed, returns a bool
  83. // Takes a username
  84. L.SetGlobal("IsConfirmed", L.NewFunction(func(L *lua.LState) int {
  85. username := L.ToString(1)
  86. L.Push(lua.LBool(userstate.IsConfirmed(username)))
  87. return 1 // number of results
  88. }))
  89. // Check if a given username is logged in, returns a bool
  90. // Takes a username
  91. L.SetGlobal("IsLoggedIn", L.NewFunction(func(L *lua.LState) int {
  92. username := L.ToString(1)
  93. L.Push(lua.LBool(userstate.IsLoggedIn(username)))
  94. return 1 // number of results
  95. }))
  96. // Check if the current user has "admin rights", returns a bool
  97. // Takes no arguments.
  98. L.SetGlobal("AdminRights", L.NewFunction(func(L *lua.LState) int {
  99. L.Push(lua.LBool(userstate.AdminRights(req)))
  100. return 1 // number of results
  101. }))
  102. // Check if a given username is an admin, returns a bool
  103. // Takes a username
  104. L.SetGlobal("IsAdmin", L.NewFunction(func(L *lua.LState) int {
  105. username := L.ToString(1)
  106. L.Push(lua.LBool(userstate.IsAdmin(username)))
  107. return 1 // number of results
  108. }))
  109. // Get the username stored in a cookie, or an empty string
  110. // Takes no arguments
  111. L.SetGlobal("UsernameCookie", L.NewFunction(func(L *lua.LState) int {
  112. username, err := userstate.UsernameCookie(req)
  113. var result lua.LString
  114. if err != nil {
  115. result = lua.LString("")
  116. } else {
  117. result = lua.LString(username)
  118. }
  119. L.Push(result)
  120. return 1 // number of results
  121. }))
  122. // Store the username in a cookie, returns true if successful
  123. // Takes a username
  124. L.SetGlobal("SetUsernameCookie", L.NewFunction(func(L *lua.LState) int {
  125. username := L.ToString(1)
  126. L.Push(lua.LBool(nil == userstate.SetUsernameCookie(w, username)))
  127. return 1 // number of results
  128. }))
  129. // Clear the user cookie. The result depends on the browser.
  130. L.SetGlobal("ClearCookie", L.NewFunction(func(L *lua.LState) int {
  131. userstate.ClearCookie(w)
  132. return 0 // number of results
  133. }))
  134. // Get the username stored in a cookie, or an empty string
  135. // Takes no arguments
  136. L.SetGlobal("AllUsernames", L.NewFunction(func(L *lua.LState) int {
  137. usernames, err := userstate.AllUsernames()
  138. var table *lua.LTable
  139. if err != nil {
  140. table = L.NewTable()
  141. } else {
  142. table = convert.Strings2table(L, usernames)
  143. }
  144. L.Push(table)
  145. return 1 // number of results
  146. }))
  147. // Get the email for a given username, or an empty string
  148. // Takes a username
  149. L.SetGlobal("Email", L.NewFunction(func(L *lua.LState) int {
  150. username := L.ToString(1)
  151. email, err := userstate.Email(username)
  152. var result lua.LString
  153. if err != nil {
  154. result = lua.LString("")
  155. } else {
  156. result = lua.LString(email)
  157. }
  158. L.Push(result)
  159. return 1 // number of results
  160. }))
  161. // Get the password hash for a given username, or an empty string
  162. // Takes a username
  163. L.SetGlobal("PasswordHash", L.NewFunction(func(L *lua.LState) int {
  164. username := L.ToString(1)
  165. pw, err := userstate.PasswordHash(username)
  166. var result lua.LString
  167. if err != nil {
  168. result = lua.LString("")
  169. } else {
  170. result = lua.LString(pw)
  171. }
  172. L.Push(result)
  173. return 1 // number of results
  174. }))
  175. // Get all unconfirmed usernames
  176. // Takes no arguments
  177. L.SetGlobal("AllUnconfirmedUsernames", L.NewFunction(func(L *lua.LState) int {
  178. usernames, err := userstate.AllUnconfirmedUsernames()
  179. var table *lua.LTable
  180. if err != nil {
  181. table = L.NewTable()
  182. } else {
  183. table = convert.Strings2table(L, usernames)
  184. }
  185. L.Push(table)
  186. return 1 // number of results
  187. }))
  188. // Get the existing confirmation code for a given user, or an empty string.
  189. L.SetGlobal("ConfirmationCode", L.NewFunction(func(L *lua.LState) int {
  190. username := L.ToString(1)
  191. pw, err := userstate.ConfirmationCode(username)
  192. if err != nil {
  193. log.Error(err)
  194. L.Push(lua.LString(""))
  195. return 1 // number of results
  196. }
  197. L.Push(lua.LString(pw))
  198. return 1 // number of results
  199. }))
  200. // Add a user to the list of unconfirmed users, returns nothing
  201. // Takes a username and a confirmation code
  202. L.SetGlobal("AddUnconfirmed", L.NewFunction(func(L *lua.LState) int {
  203. username := L.ToString(1)
  204. confirmationCode := L.ToString(2)
  205. userstate.AddUnconfirmed(username, confirmationCode)
  206. return 0 // number of results
  207. }))
  208. // Remove a user from the list of unconfirmed users, returns nothing
  209. // Takes a username
  210. L.SetGlobal("RemoveUnconfirmed", L.NewFunction(func(L *lua.LState) int {
  211. username := L.ToString(1)
  212. userstate.RemoveUnconfirmed(username)
  213. return 0 // number of results
  214. }))
  215. // Mark a user as confirmed, returns nothing
  216. // Takes a username
  217. L.SetGlobal("MarkConfirmed", L.NewFunction(func(L *lua.LState) int {
  218. username := L.ToString(1)
  219. userstate.MarkConfirmed(username)
  220. return 0 // number of results
  221. }))
  222. // Removes a user, returns nothing
  223. // Takes a username
  224. L.SetGlobal("RemoveUser", L.NewFunction(func(L *lua.LState) int {
  225. username := L.ToString(1)
  226. userstate.RemoveUser(username)
  227. return 0 // number of results
  228. }))
  229. // Make a user an admin, returns nothing
  230. // Takes a username
  231. L.SetGlobal("SetAdminStatus", L.NewFunction(func(L *lua.LState) int {
  232. username := L.ToString(1)
  233. userstate.SetAdminStatus(username)
  234. return 0 // number of results
  235. }))
  236. // Make an admin user a regular user, returns nothing
  237. // Takes a username
  238. L.SetGlobal("RemoveAdminStatus", L.NewFunction(func(L *lua.LState) int {
  239. username := L.ToString(1)
  240. userstate.RemoveAdminStatus(username)
  241. return 0 // number of results
  242. }))
  243. // Add a user, returns nothing
  244. // Takes a username, password and email
  245. L.SetGlobal("AddUser", L.NewFunction(func(L *lua.LState) int {
  246. username := L.ToString(1)
  247. password := L.ToString(2)
  248. email := L.ToString(3)
  249. userstate.AddUser(username, password, email)
  250. return 0 // number of results
  251. }))
  252. // Set a user as logged in on the server (not cookie), returns nothing
  253. // Takes a username
  254. L.SetGlobal("SetLoggedIn", L.NewFunction(func(L *lua.LState) int {
  255. username := L.ToString(1)
  256. userstate.SetLoggedIn(username)
  257. return 0 // number of results
  258. }))
  259. // Set a user as logged out on the server (not cookie), returns nothing
  260. // Takes a username
  261. L.SetGlobal("SetLoggedOut", L.NewFunction(func(L *lua.LState) int {
  262. username := L.ToString(1)
  263. userstate.SetLoggedOut(username)
  264. return 0 // number of results
  265. }))
  266. // Log in a user, both on the server and with a cookie.
  267. // Returns true of successful.
  268. // Takes a username
  269. L.SetGlobal("Login", L.NewFunction(func(L *lua.LState) int {
  270. username := L.ToString(1)
  271. L.Push(lua.LBool(nil == userstate.Login(w, username)))
  272. return 1 // number of results
  273. }))
  274. // Logs out a user, on the server (which is enough). Returns nothing
  275. // Takes a username
  276. L.SetGlobal("Logout", L.NewFunction(func(L *lua.LState) int {
  277. username := L.ToString(1)
  278. userstate.Logout(username)
  279. return 0 // number of results
  280. }))
  281. // Get the current username, from the cookie
  282. // Takes nothing
  283. L.SetGlobal("Username", L.NewFunction(func(L *lua.LState) int {
  284. username := userstate.Username(req)
  285. L.Push(lua.LString(username))
  286. return 1 // number of results
  287. }))
  288. // Get the current cookie timeout
  289. // Takes a username
  290. L.SetGlobal("CookieTimeout", L.NewFunction(func(L *lua.LState) int {
  291. username := L.ToString(1)
  292. L.Push(lua.LNumber(userstate.CookieTimeout(username)))
  293. return 1 // number of results
  294. }))
  295. // Set the current cookie timeout
  296. // Takes a timeout number, measured in seconds
  297. L.SetGlobal("SetCookieTimeout", L.NewFunction(func(L *lua.LState) int {
  298. timeout := int64(L.ToNumber(1))
  299. userstate.SetCookieTimeout(timeout)
  300. return 0 // number of results
  301. }))
  302. // Get the current cookie secret
  303. // Takes nothing, returns a string
  304. L.SetGlobal("CookieSecret", L.NewFunction(func(L *lua.LState) int {
  305. L.Push(lua.LString(userstate.CookieSecret()))
  306. return 1 // number of results
  307. }))
  308. // Set the current cookie secret
  309. // Takes a string, returns nothing
  310. L.SetGlobal("SetCookieSecret", L.NewFunction(func(L *lua.LState) int {
  311. secret := L.ToString(1)
  312. userstate.SetCookieSecret(secret)
  313. return 0 // number of results
  314. }))
  315. // Get the current password hashing algorithm (bcrypt, bcrypt+ or sha256)
  316. // Takes nothing
  317. L.SetGlobal("PasswordAlgo", L.NewFunction(func(L *lua.LState) int {
  318. algorithm := userstate.PasswordAlgo()
  319. L.Push(lua.LString(algorithm))
  320. return 1 // number of results
  321. }))
  322. // Set the current password hashing algorithm (bcrypt, bcrypt+ or sha256)
  323. // Takes a string
  324. L.SetGlobal("SetPasswordAlgo", L.NewFunction(func(L *lua.LState) int {
  325. algorithm := L.ToString(1)
  326. userstate.SetPasswordAlgo(algorithm)
  327. return 0 // number of results
  328. }))
  329. // Change the password for a user
  330. L.SetGlobal("SetPassword", L.NewFunction(func(L *lua.LState) int {
  331. username := L.ToString(1)
  332. password := L.ToString(2)
  333. userstate.SetPassword(username, password)
  334. return 0 // number of results
  335. }))
  336. // Hash the password, returns a string
  337. // Takes a username and password (username can be used for salting)
  338. L.SetGlobal("HashPassword", L.NewFunction(func(L *lua.LState) int {
  339. username := L.ToString(1)
  340. password := L.ToString(2)
  341. L.Push(lua.LString(userstate.HashPassword(username, password)))
  342. return 1 // number of results
  343. }))
  344. // Check if a given username and password is correct, returns a bool
  345. // Takes a username and password
  346. L.SetGlobal("CorrectPassword", L.NewFunction(func(L *lua.LState) int {
  347. username := L.ToString(1)
  348. password := L.ToString(2)
  349. L.Push(lua.LBool(userstate.CorrectPassword(username, password)))
  350. return 1 // number of results
  351. }))
  352. // Checks if a confirmation code is already in use, returns a bool
  353. // Takes a confirmation code
  354. L.SetGlobal("AlreadyHasConfirmationCode", L.NewFunction(func(L *lua.LState) int {
  355. confirmationCode := L.ToString(1)
  356. L.Push(lua.LBool(userstate.AlreadyHasConfirmationCode(confirmationCode)))
  357. return 1 // number of results
  358. }))
  359. // Find a username based on a given confirmation code, or returns an empty string
  360. // Takes a confirmation code
  361. L.SetGlobal("FindUserByConfirmationCode", L.NewFunction(func(L *lua.LState) int {
  362. confirmationCode := L.ToString(1)
  363. username, err := userstate.FindUserByConfirmationCode(confirmationCode)
  364. var result lua.LString
  365. if err != nil {
  366. log.Warn(err)
  367. result = lua.LString("")
  368. } else {
  369. result = lua.LString(username)
  370. }
  371. L.Push(result)
  372. return 1 // number of results
  373. }))
  374. // Mark a user as confirmed, returns nothing
  375. // Takes a username
  376. L.SetGlobal("Confirm", L.NewFunction(func(L *lua.LState) int {
  377. username := L.ToString(1)
  378. userstate.Confirm(username)
  379. return 0 // number of results
  380. }))
  381. // Mark a user as confirmed, returns true if successful.
  382. // Takes a confirmation code.
  383. L.SetGlobal("ConfirmUserByConfirmationCode", L.NewFunction(func(L *lua.LState) int {
  384. confirmationCode := L.ToString(1)
  385. L.Push(lua.LBool(nil == userstate.ConfirmUserByConfirmationCode(confirmationCode)))
  386. return 1 // number of results
  387. }))
  388. // Set the minimum confirmation code length
  389. // Takes the minimum number of characters
  390. L.SetGlobal("SetMinimumConfirmationCodeLength", L.NewFunction(func(L *lua.LState) int {
  391. length := int(L.ToNumber(1))
  392. userstate.SetMinimumConfirmationCodeLength(length)
  393. return 0 // number of results
  394. }))
  395. // Generates and returns a unique confirmation code, or an empty string
  396. // Takes no parameters
  397. L.SetGlobal("GenerateUniqueConfirmationCode", L.NewFunction(func(L *lua.LState) int {
  398. confirmationCode, err := userstate.GenerateUniqueConfirmationCode()
  399. var result lua.LString
  400. if err != nil {
  401. result = lua.LString("")
  402. } else {
  403. result = lua.LString(confirmationCode)
  404. }
  405. L.Push(result)
  406. return 1 // number of results
  407. }))
  408. }