blob: 8ea086021b25256241a66e5a1f1f8f8463aca179 [file] [log] [blame]
gioa60f0de2024-07-08 10:49:48 +04001package welcome
2
3import (
4 "database/sql"
gio81246f02024-07-10 12:02:15 +04005 "errors"
6
7 "github.com/ncruces/go-sqlite3"
gioa60f0de2024-07-08 10:49:48 +04008
9 "github.com/giolekva/pcloud/core/installer/soft"
10)
11
gio81246f02024-07-10 12:02:15 +040012const (
gio11617ac2024-07-15 16:09:04 +040013 errorConstraintPrimaryKeyViolation = 1555
gio81246f02024-07-10 12:02:15 +040014)
15
16var (
17 ErrorAlreadyExists = errors.New("already exists")
18)
19
gioa60f0de2024-07-08 10:49:48 +040020type Commit struct {
21 Hash string
22 Message string
23}
24
25type Store interface {
giocafd4e62024-07-31 10:53:40 +040026 CreateUser(username string, password []byte, network string) error
gio81246f02024-07-10 12:02:15 +040027 GetUserPassword(username string) ([]byte, error)
gio11617ac2024-07-15 16:09:04 +040028 GetUserNetwork(username string) (string, error)
gioa60f0de2024-07-08 10:49:48 +040029 GetApps() ([]string, error)
gio81246f02024-07-10 12:02:15 +040030 GetUserApps(username string) ([]string, error)
31 CreateApp(name, username string) error
32 GetAppOwner(name string) (string, error)
gioa60f0de2024-07-08 10:49:48 +040033 CreateCommit(name, hash, message string) error
34 GetCommitHistory(name string) ([]Commit, error)
35}
36
37func NewStore(cf soft.RepoIO, db *sql.DB) (Store, error) {
38 s := &storeImpl{cf, db}
39 if err := s.init(); err != nil {
40 return nil, err
41 }
42 return s, nil
43}
44
45type storeImpl struct {
46 cf soft.RepoIO
47 db *sql.DB
48}
49
50func (s *storeImpl) init() error {
51 _, err := s.db.Exec(`
gio81246f02024-07-10 12:02:15 +040052 CREATE TABLE IF NOT EXISTS users (
53 username TEXT PRIMARY KEY,
gio11617ac2024-07-15 16:09:04 +040054 password BLOB,
gio11617ac2024-07-15 16:09:04 +040055 network TEXT
gio81246f02024-07-10 12:02:15 +040056 );
gioa60f0de2024-07-08 10:49:48 +040057 CREATE TABLE IF NOT EXISTS apps (
gio81246f02024-07-10 12:02:15 +040058 name TEXT PRIMARY KEY,
59 username TEXT
gioa60f0de2024-07-08 10:49:48 +040060 );
61 CREATE TABLE IF NOT EXISTS commits (
62 app_name TEXT,
63 hash TEXT,
64 message TEXT
65 );
66 `)
67 return err
68
69}
70
giocafd4e62024-07-31 10:53:40 +040071func (s *storeImpl) CreateUser(username string, password []byte, network string) error {
72 query := `INSERT INTO users (username, password, network) VALUES (?, ?, ?)`
73 _, err := s.db.Exec(query, username, password, network)
gio81246f02024-07-10 12:02:15 +040074 if err != nil {
75 sqliteErr, ok := err.(*sqlite3.Error)
gio11617ac2024-07-15 16:09:04 +040076 if ok && sqliteErr.ExtendedCode() == errorConstraintPrimaryKeyViolation {
gio81246f02024-07-10 12:02:15 +040077 return ErrorAlreadyExists
78 }
79 }
gioa60f0de2024-07-08 10:49:48 +040080 return err
81}
82
gio81246f02024-07-10 12:02:15 +040083func (s *storeImpl) GetUserPassword(username string) ([]byte, error) {
84 query := `SELECT password FROM users WHERE username = ?`
85 row := s.db.QueryRow(query, username)
86 if err := row.Err(); err != nil {
87 return nil, err
88 }
89 ret := []byte{}
90 if err := row.Scan(&ret); err != nil {
91 return nil, err
92 }
93 return ret, nil
94}
95
gio11617ac2024-07-15 16:09:04 +040096func (s *storeImpl) GetUserNetwork(username string) (string, error) {
97 query := `SELECT network FROM users WHERE username = ?`
98 row := s.db.QueryRow(query, username)
99 if err := row.Err(); err != nil {
100 return "", err
101 }
102 var ret string
103 if err := row.Scan(&ret); err != nil {
104 if errors.Is(sql.ErrNoRows, err) {
105 return "", nil
106 }
107 return "", err
108 }
109 return ret, nil
110}
111
gio81246f02024-07-10 12:02:15 +0400112func (s *storeImpl) CreateApp(name, username string) error {
113 query := `INSERT INTO apps (name, username) VALUES (?, ?)`
114 _, err := s.db.Exec(query, name, username)
115 return err
116}
117
118func (s *storeImpl) GetAppOwner(name string) (string, error) {
119 query := `SELECT username FROM apps WHERE name = ?`
120 row := s.db.QueryRow(query, name)
121 if err := row.Err(); err != nil {
122 return "", err
123 }
124 var ret string
125 if err := row.Scan(&ret); err != nil {
126 return "", err
127 }
128 return ret, nil
129}
130
gioa60f0de2024-07-08 10:49:48 +0400131func (s *storeImpl) GetApps() ([]string, error) {
132 query := `SELECT name FROM apps`
133 rows, err := s.db.Query(query)
134 if err != nil {
135 return nil, err
136 }
137 defer rows.Close()
138 ret := []string{}
139 for rows.Next() {
140 if err := rows.Err(); err != nil {
141 return nil, err
142 }
143 var name string
144 if err := rows.Scan(&name); err != nil {
145 return nil, err
146 }
147 ret = append(ret, name)
148
149 }
150 return ret, nil
151}
152
gio81246f02024-07-10 12:02:15 +0400153func (s *storeImpl) GetUserApps(username string) ([]string, error) {
154 query := `SELECT name FROM apps WHERE username = ?`
155 rows, err := s.db.Query(query, username)
156 if err != nil {
157 return nil, err
158 }
159 defer rows.Close()
160 ret := []string{}
161 for rows.Next() {
162 if err := rows.Err(); err != nil {
163 return nil, err
164 }
165 var name string
166 if err := rows.Scan(&name); err != nil {
167 return nil, err
168 }
169 ret = append(ret, name)
170
171 }
172 return ret, nil
173}
174
gioa60f0de2024-07-08 10:49:48 +0400175func (s *storeImpl) CreateCommit(name, hash, message string) error {
176 query := `INSERT INTO commits (app_name, hash, message) VALUES (?, ?, ?)`
177 _, err := s.db.Exec(query, name, hash, message)
178 return err
179}
180
181func (s *storeImpl) GetCommitHistory(name string) ([]Commit, error) {
182 query := `SELECT hash, message FROM commits WHERE app_name = ?`
183 rows, err := s.db.Query(query, name)
184 if err != nil {
185 return nil, err
186 }
187 defer rows.Close()
188 ret := []Commit{}
189 for rows.Next() {
190 if err := rows.Err(); err != nil {
191 return nil, err
192 }
193 var c Commit
194 if err := rows.Scan(&c.Hash, &c.Message); err != nil {
195 return nil, err
196 }
197 ret = append(ret, c)
198
199 }
200 return ret, nil
201}