auth_sqlite.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package auth
  2. import (
  3. "database/sql"
  4. "golang.org/x/crypto/bcrypt"
  5. )
  6. /*
  7. SELECT * FROM user;
  8. SELECT * FROM access;
  9. INSERT INTO user VALUES ('phil','$2a$06$.4W0LI5mcxzxhpjUvpTaNeu0MhRO0T7B.CYnmAkRnlztIy7PrSODu', 'admin');
  10. INSERT INTO user VALUES ('ben','$2a$06$skJK/AecWCUmiCjr69ke.Ow/hFA616RdvJJPxnI221zyohsRlyXL.', 'user');
  11. INSERT INTO user VALUES ('marian','$2a$10$8U90swQIatvHHI4sw0Wo7.OUy6dUwzMcoOABi6BsS4uF0x3zcSXRW', 'user');
  12. INSERT INTO access VALUES ('ben','alerts',1,1);
  13. INSERT INTO access VALUES ('marian','alerts',1,0);
  14. INSERT INTO access VALUES ('','announcements',1,0);
  15. INSERT INTO access VALUES ('','write-all',1,1);
  16. */
  17. const (
  18. bcryptCost = 11
  19. )
  20. // Auther-related queries
  21. const (
  22. createAuthTablesQueries = `
  23. BEGIN;
  24. CREATE TABLE IF NOT EXISTS user (
  25. user TEXT NOT NULL PRIMARY KEY,
  26. pass TEXT NOT NULL,
  27. role TEXT NOT NULL
  28. );
  29. CREATE TABLE IF NOT EXISTS access (
  30. user TEXT NOT NULL,
  31. topic TEXT NOT NULL,
  32. read INT NOT NULL,
  33. write INT NOT NULL,
  34. PRIMARY KEY (topic, user)
  35. );
  36. CREATE TABLE IF NOT EXISTS schema_version (
  37. id INT PRIMARY KEY,
  38. version INT NOT NULL
  39. );
  40. COMMIT;
  41. `
  42. selectUserQuery = `SELECT pass, role FROM user WHERE user = ?`
  43. selectTopicPermsQuery = `
  44. SELECT read, write
  45. FROM access
  46. WHERE user IN ('', ?) AND topic = ?
  47. ORDER BY user DESC
  48. `
  49. )
  50. // Manager-related queries
  51. const (
  52. insertUser = `INSERT INTO user (user, pass, role) VALUES (?, ?, ?)`
  53. updateUserPass = `UPDATE user SET pass = ? WHERE user = ?`
  54. updateUserRole = `UPDATE user SET role = ? WHERE user = ?`
  55. upsertAccess = `
  56. INSERT INTO access (user, topic, read, write)
  57. VALUES (?, ?, ?, ?)
  58. ON CONFLICT (user, topic) DO UPDATE SET read=excluded.read, write=excluded.write
  59. `
  60. deleteUser = `DELETE FROM user WHERE user = ?`
  61. deleteAllAccess = `DELETE FROM access WHERE user = ?`
  62. deleteAccess = `DELETE FROM access WHERE user = ? AND topic = ?`
  63. )
  64. type SQLiteAuth struct {
  65. db *sql.DB
  66. defaultRead bool
  67. defaultWrite bool
  68. }
  69. var _ Auther = (*SQLiteAuth)(nil)
  70. var _ Manager = (*SQLiteAuth)(nil)
  71. func NewSQLiteAuth(filename string, defaultRead, defaultWrite bool) (*SQLiteAuth, error) {
  72. db, err := sql.Open("sqlite3", filename)
  73. if err != nil {
  74. return nil, err
  75. }
  76. if err := setupNewAuthDB(db); err != nil {
  77. return nil, err
  78. }
  79. return &SQLiteAuth{
  80. db: db,
  81. defaultRead: defaultRead,
  82. defaultWrite: defaultWrite,
  83. }, nil
  84. }
  85. func setupNewAuthDB(db *sql.DB) error {
  86. if _, err := db.Exec(createAuthTablesQueries); err != nil {
  87. return err
  88. }
  89. // FIXME schema version
  90. return nil
  91. }
  92. func (a *SQLiteAuth) Authenticate(username, password string) (*User, error) {
  93. rows, err := a.db.Query(selectUserQuery, username)
  94. if err != nil {
  95. return nil, err
  96. }
  97. defer rows.Close()
  98. var hash, role string
  99. if rows.Next() {
  100. if err := rows.Scan(&hash, &role); err != nil {
  101. return nil, err
  102. } else if err := rows.Err(); err != nil {
  103. return nil, err
  104. }
  105. }
  106. if err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)); err != nil {
  107. return nil, err
  108. }
  109. return &User{
  110. Name: username,
  111. Role: Role(role),
  112. }, nil
  113. }
  114. func (a *SQLiteAuth) Authorize(user *User, topic string, perm Permission) error {
  115. if user.Role == RoleAdmin {
  116. return nil // Admin can do everything
  117. }
  118. // Select the read/write permissions for this user/topic combo. The query may return two
  119. // rows (one for everyone, and one for the user), but prioritizes the user. The value for
  120. // user.Name may be empty (= everyone).
  121. rows, err := a.db.Query(selectTopicPermsQuery, user.Name, topic)
  122. if err != nil {
  123. return err
  124. }
  125. defer rows.Close()
  126. if !rows.Next() {
  127. return a.resolvePerms(a.defaultRead, a.defaultWrite, perm)
  128. }
  129. var read, write bool
  130. if err := rows.Scan(&read, &write); err != nil {
  131. return err
  132. } else if err := rows.Err(); err != nil {
  133. return err
  134. }
  135. return a.resolvePerms(read, write, perm)
  136. }
  137. func (a *SQLiteAuth) resolvePerms(read, write bool, perm Permission) error {
  138. if perm == PermissionRead && read {
  139. return nil
  140. } else if perm == PermissionWrite && write {
  141. return nil
  142. }
  143. return ErrUnauthorized
  144. }
  145. func (a *SQLiteAuth) AddUser(username, password string, role Role) error {
  146. hash, err := bcrypt.GenerateFromPassword([]byte(password), bcryptCost)
  147. if err != nil {
  148. return err
  149. }
  150. if _, err = a.db.Exec(insertUser, username, hash, role); err != nil {
  151. return err
  152. }
  153. return nil
  154. }
  155. func (a *SQLiteAuth) RemoveUser(username string) error {
  156. if _, err := a.db.Exec(deleteUser, username); err != nil {
  157. return err
  158. }
  159. if _, err := a.db.Exec(deleteAllAccess, username); err != nil {
  160. return err
  161. }
  162. return nil
  163. }
  164. func (a *SQLiteAuth) ChangePassword(username, password string) error {
  165. hash, err := bcrypt.GenerateFromPassword([]byte(password), bcryptCost)
  166. if err != nil {
  167. return err
  168. }
  169. if _, err := a.db.Exec(updateUserPass, hash, username); err != nil {
  170. return err
  171. }
  172. return nil
  173. }
  174. func (a *SQLiteAuth) ChangeRole(username string, role Role) error {
  175. if _, err := a.db.Exec(updateUserRole, string(role), username); err != nil {
  176. return err
  177. }
  178. return nil
  179. }
  180. func (a *SQLiteAuth) AllowAccess(username string, topic string, read bool, write bool) error {
  181. if _, err := a.db.Exec(upsertAccess, username, topic, read, write); err != nil {
  182. return err
  183. }
  184. return nil
  185. }
  186. func (a *SQLiteAuth) ResetAccess(username string, topic string) error {
  187. if topic == "" {
  188. if _, err := a.db.Exec(deleteAllAccess, username); err != nil {
  189. return err
  190. }
  191. } else {
  192. if _, err := a.db.Exec(deleteAccess, username, topic); err != nil {
  193. return err
  194. }
  195. }
  196. return nil
  197. }