db.go (view raw)
1package main
2
3import (
4 "crypto/rand"
5 "database/sql"
6 "io"
7 "io/ioutil"
8 "log"
9 "os"
10 "path"
11 "path/filepath"
12 "sort"
13 "time"
14)
15
16var DB *sql.DB
17
18func initializeDB() {
19 var err error
20 DB, err = sql.Open("sqlite3", c.DBFile)
21 if err != nil {
22 log.Fatal(err)
23 }
24 createTablesIfDNE()
25}
26
27type File struct { // also folders
28 Creator string
29 Name string // includes folder
30 UpdatedTime time.Time
31 TimeAgo string
32 IsText bool
33 Children []File
34 Host string
35}
36
37func fileFromPath(fullPath string) File {
38 info, _ := os.Stat(fullPath)
39 creatorFolder := getCreator(fullPath)
40 isText := isTextFile(fullPath)
41 updatedTime := info.ModTime()
42 return File{
43 Name: getLocalPath(fullPath),
44 Creator: path.Base(creatorFolder),
45 UpdatedTime: updatedTime,
46 IsText: isText,
47 TimeAgo: timeago(&updatedTime),
48 Host: c.Host,
49 }
50
51}
52
53type User struct {
54 Username string
55 Email string
56 Active bool
57 Admin bool
58 CreatedAt int // timestamp
59 Reference string
60}
61
62func getActiveUserNames() ([]string, error) {
63 rows, err := DB.Query(`SELECT username from user WHERE active is true order by username`)
64 if err != nil {
65 return nil, err
66 }
67 var users []string
68 for rows.Next() {
69 var user string
70 err = rows.Scan(&user)
71 if err != nil {
72 return nil, err
73 }
74 users = append(users, user)
75 }
76
77 return users, nil
78}
79
80func getUserByName(username string) (*User, error) {
81 var user User
82 row := DB.QueryRow(`SELECT username, email, active, admin, created_at, reference from user WHERE username = ?`, username)
83 err := row.Scan(&user.Username, &user.Email, &user.Active, &user.Admin, &user.CreatedAt, &user.Reference)
84 if err != nil {
85 return nil, err
86 }
87 return &user, nil
88}
89
90func getUsers() ([]User, error) {
91 rows, err := DB.Query(`SELECT username, email, active, admin, created_at, reference from user ORDER BY created_at DESC`)
92 if err != nil {
93 return nil, err
94 }
95 var users []User
96 for rows.Next() {
97 var user User
98 err = rows.Scan(&user.Username, &user.Email, &user.Active, &user.Admin, &user.CreatedAt, &user.Reference)
99 if err != nil {
100 return nil, err
101 }
102 users = append(users, user)
103 }
104 return users, nil
105}
106
107func getIndexFiles(admin bool) ([]*File, error) { // cache this function
108 result := []*File{}
109 err := filepath.Walk(c.FilesDirectory, func(thepath string, info os.FileInfo, err error) error {
110 if err != nil {
111 log.Printf("Failure accessing a path %q: %v\n", thepath, err)
112 return err // think about
113 }
114 if !admin && info.IsDir() && info.Name() == HiddenFolder {
115 return filepath.SkipDir
116 }
117 // make this do what it should
118 if !info.IsDir() {
119 res := fileFromPath(thepath)
120 result = append(result, &res)
121 }
122 return nil
123 })
124 if err != nil {
125 return nil, err
126 }
127 sort.Slice(result, func(i, j int) bool {
128 return result[i].UpdatedTime.After(result[j].UpdatedTime)
129 })
130 if len(result) > 50 {
131 result = result[:50]
132 }
133 return result, nil
134} // todo clean up paths
135
136func getMyFilesRecursive(p string, creator string) ([]File, error) {
137 result := []File{}
138 files, err := ioutil.ReadDir(p)
139 if err != nil {
140 return nil, err
141 }
142 for _, file := range files {
143 fullPath := path.Join(p, file.Name())
144 f := fileFromPath(fullPath)
145 if file.IsDir() {
146 f.Children, err = getMyFilesRecursive(path.Join(p, file.Name()), creator)
147 }
148 result = append(result, f)
149 }
150 return result, nil
151}
152
153func createTablesIfDNE() {
154 _, err := DB.Exec(`CREATE TABLE IF NOT EXISTS user (
155 id INTEGER PRIMARY KEY NOT NULL,
156 username TEXT NOT NULL UNIQUE,
157 email TEXT NOT NULL UNIQUE,
158 password_hash TEXT NOT NULL,
159 reference TEXT NOT NULL default "",
160 active boolean NOT NULL DEFAULT false,
161 admin boolean NOT NULL DEFAULT false,
162 created_at INTEGER DEFAULT (strftime('%s', 'now'))
163);
164
165CREATE TABLE IF NOT EXISTS cookie_key (
166 value TEXT NOT NULL
167);`)
168 if err != nil {
169 log.Fatal(err)
170 }
171}
172
173// Generate a cryptographically secure key for the cookie store
174func generateCookieKeyIfDNE() []byte {
175 rows, err := DB.Query("SELECT value FROM cookie_key LIMIT 1")
176 defer rows.Close()
177 if err != nil {
178 log.Fatal(err)
179 }
180 if rows.Next() {
181 var cookie []byte
182 err := rows.Scan(&cookie)
183 if err != nil {
184 log.Fatal(err)
185 }
186 return cookie
187 } else {
188 k := make([]byte, 32)
189 _, err := io.ReadFull(rand.Reader, k)
190 if err != nil {
191 log.Fatal(err)
192 }
193 _, err = DB.Exec("insert into cookie_key values (?)", k)
194 if err != nil {
195 log.Fatal(err)
196 }
197 return k
198 }
199}