blob: 857045ca2546f50ef7a39f4baeb11ef804d724ca [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 (
13 errorUniqueConstraintViolation = 2067
14)
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 {
gio81246f02024-07-10 12:02:15 +040026 CreateUser(username string, password []byte) error
27 GetUserPassword(username string) ([]byte, error)
gioa60f0de2024-07-08 10:49:48 +040028 GetApps() ([]string, error)
gio81246f02024-07-10 12:02:15 +040029 GetUserApps(username string) ([]string, error)
30 CreateApp(name, username string) error
31 GetAppOwner(name string) (string, error)
gioa60f0de2024-07-08 10:49:48 +040032 CreateCommit(name, hash, message string) error
33 GetCommitHistory(name string) ([]Commit, error)
34}
35
36func NewStore(cf soft.RepoIO, db *sql.DB) (Store, error) {
37 s := &storeImpl{cf, db}
38 if err := s.init(); err != nil {
39 return nil, err
40 }
41 return s, nil
42}
43
44type storeImpl struct {
45 cf soft.RepoIO
46 db *sql.DB
47}
48
49func (s *storeImpl) init() error {
50 _, err := s.db.Exec(`
gio81246f02024-07-10 12:02:15 +040051 CREATE TABLE IF NOT EXISTS users (
52 username TEXT PRIMARY KEY,
53 password BLOB
54 );
gioa60f0de2024-07-08 10:49:48 +040055 CREATE TABLE IF NOT EXISTS apps (
gio81246f02024-07-10 12:02:15 +040056 name TEXT PRIMARY KEY,
57 username TEXT
gioa60f0de2024-07-08 10:49:48 +040058 );
59 CREATE TABLE IF NOT EXISTS commits (
60 app_name TEXT,
61 hash TEXT,
62 message TEXT
63 );
64 `)
65 return err
66
67}
68
gio81246f02024-07-10 12:02:15 +040069func (s *storeImpl) CreateUser(username string, password []byte) error {
70 query := `INSERT INTO users (username, password) VALUES (?, ?)`
71 _, err := s.db.Exec(query, username, password)
72 if err != nil {
73 sqliteErr, ok := err.(*sqlite3.Error)
74 if ok && sqliteErr.ExtendedCode() == errorUniqueConstraintViolation {
75 return ErrorAlreadyExists
76 }
77 }
gioa60f0de2024-07-08 10:49:48 +040078 return err
79}
80
gio81246f02024-07-10 12:02:15 +040081func (s *storeImpl) GetUserPassword(username string) ([]byte, error) {
82 query := `SELECT password FROM users WHERE username = ?`
83 row := s.db.QueryRow(query, username)
84 if err := row.Err(); err != nil {
85 return nil, err
86 }
87 ret := []byte{}
88 if err := row.Scan(&ret); err != nil {
89 return nil, err
90 }
91 return ret, nil
92}
93
94func (s *storeImpl) CreateApp(name, username string) error {
95 query := `INSERT INTO apps (name, username) VALUES (?, ?)`
96 _, err := s.db.Exec(query, name, username)
97 return err
98}
99
100func (s *storeImpl) GetAppOwner(name string) (string, error) {
101 query := `SELECT username FROM apps WHERE name = ?`
102 row := s.db.QueryRow(query, name)
103 if err := row.Err(); err != nil {
104 return "", err
105 }
106 var ret string
107 if err := row.Scan(&ret); err != nil {
108 return "", err
109 }
110 return ret, nil
111}
112
gioa60f0de2024-07-08 10:49:48 +0400113func (s *storeImpl) GetApps() ([]string, error) {
114 query := `SELECT name FROM apps`
115 rows, err := s.db.Query(query)
116 if err != nil {
117 return nil, err
118 }
119 defer rows.Close()
120 ret := []string{}
121 for rows.Next() {
122 if err := rows.Err(); err != nil {
123 return nil, err
124 }
125 var name string
126 if err := rows.Scan(&name); err != nil {
127 return nil, err
128 }
129 ret = append(ret, name)
130
131 }
132 return ret, nil
133}
134
gio81246f02024-07-10 12:02:15 +0400135func (s *storeImpl) GetUserApps(username string) ([]string, error) {
136 query := `SELECT name FROM apps WHERE username = ?`
137 rows, err := s.db.Query(query, username)
138 if err != nil {
139 return nil, err
140 }
141 defer rows.Close()
142 ret := []string{}
143 for rows.Next() {
144 if err := rows.Err(); err != nil {
145 return nil, err
146 }
147 var name string
148 if err := rows.Scan(&name); err != nil {
149 return nil, err
150 }
151 ret = append(ret, name)
152
153 }
154 return ret, nil
155}
156
gioa60f0de2024-07-08 10:49:48 +0400157func (s *storeImpl) CreateCommit(name, hash, message string) error {
158 query := `INSERT INTO commits (app_name, hash, message) VALUES (?, ?, ?)`
159 _, err := s.db.Exec(query, name, hash, message)
160 return err
161}
162
163func (s *storeImpl) GetCommitHistory(name string) ([]Commit, error) {
164 query := `SELECT hash, message FROM commits WHERE app_name = ?`
165 rows, err := s.db.Query(query, name)
166 if err != nil {
167 return nil, err
168 }
169 defer rows.Close()
170 ret := []Commit{}
171 for rows.Next() {
172 if err := rows.Err(); err != nil {
173 return nil, err
174 }
175 var c Commit
176 if err := rows.Scan(&c.Hash, &c.Message); err != nil {
177 return nil, err
178 }
179 ret = append(ret, c)
180
181 }
182 return ret, nil
183}