💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Gemigit › files › 8ce023ab0f31924a07f8a55675… captured on 2023-12-28 at 15:33:34. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 package db
1
2 import (
3 "crypto/rand"
4 "crypto/sha256"
5 "encoding/base64"
6 "time"
7 "log"
8 "errors"
9 )
10
11 func CanUsePassword(repo string, owner string, username string) (bool, error) {
12 row, err := db.Query(`SELECT securegit FROM user WHERE
13 UPPER(name) LIKE UPPER(?)`, username)
14 if err != nil {
15 log.Println(err)
16 return false, err
17 }
18 defer row.Close()
19 var secure int
20 if (!row.Next()) {
21 return false, errors.New("not found")
22 }
23 row.Scan(&secure)
24 if secure != 0 {
25 return false, nil
26 }
27 row.Close()
28
29 row, err = db.Query(`SELECT b.securegit FROM user a
30 INNER JOIN repo b ON a.userID = b.UserID WHERE
31 UPPER(a.name) LIKE UPPER(?) AND
32 UPPER(b.name) LIKE UPPER(?)`,
33 owner, repo)
34 if err != nil {
35 log.Println(err)
36 return false, err
37 }
38 if (!row.Next()) {
39 return false, errors.New("not found")
40 }
41 defer row.Close()
42 row.Scan(&secure)
43 return secure == 0, nil
44 }
45
46 func (user User) CreateToken(readOnly bool) (string, error) {
47 data := make([]byte, 32)
48 if _, err := rand.Read(data); err != nil {
49 return "", err
50 }
51 token := base64.RawStdEncoding.EncodeToString(data)
52 sum := sha256.Sum224(data)
53 hash := base64.RawStdEncoding.EncodeToString(sum[:])
54 _, err := db.Exec(`INSERT INTO
55 token(userID, token, hint, expiration, readonly)
56 VALUES(?, ?, ?, ?, ?);`,
57 user.ID, hash, token[0:4], time.Now().Unix() + 3600 * 24 * 30,
58 readOnly)
59 if err != nil {
60 return "", err
61 }
62
63 return token, nil
64 }
65
66 func (user User) RenewToken(tokenID int) (error) {
67 res, err := db.Exec(`UPDATE token SET expiration = ?
68 WHERE tokenID = ? AND userID = ?`,
69 time.Now().Unix() + 3600 * 24 * 30 + 1,
70 tokenID, user.ID)
71 if err != nil {
72 return err
73 }
74 rows, err := res.RowsAffected()
75 if err != nil {
76 return err
77 }
78 if rows < 1 {
79 return errors.New("invalid token id")
80 }
81 return nil
82 }
83
84 func (user User) DeleteToken(tokenID int) (error) {
85 row, err := db.Exec(
86 `DELETE FROM token WHERE tokenID = ? AND userID = ?`,
87 tokenID, user.ID)
88 if err != nil {
89 return err
90 }
91 count, err := row.RowsAffected()
92 if err != nil {
93 return err
94 }
95 if count < 1 {
96 return errors.New("invalid token")
97 }
98 return nil
99 }
100
101 func (user User) GetTokens() ([]Token, error) {
102 rows, err := db.Query(`SELECT tokenID, expiration, hint, readonly
103 FROM token WHERE userID = ?`, user.ID)
104 if err != nil {
105 log.Println(err)
106 return nil, errors.New("unexpected error")
107 }
108 defer rows.Close()
109
110 tokens := []Token{}
111 for rows.Next() {
112 var r Token
113 err = rows.Scan(&r.ID, &r.Expiration, &r.Hint, &r.ReadOnly)
114 if err != nil {
115 return nil, err
116 }
117 r.ExpirationFormat = time.Unix(r.Expiration, 0).UTC().
118 Format(time.RFC1123)
119 tokens = append(tokens, r)
120 }
121 return tokens, nil
122 }
123
124 func (user *User) ToggleSecure() error {
125 user.SecureGit = !user.SecureGit
126
127 _, err := db.Exec("UPDATE user SET securegit = ? " +
128 "WHERE userID = ?", user.SecureGit, user.ID)
129 if err != nil {
130 return err
131 }
132
133 users[user.Signature] = *user
134 return nil
135 }
136
137 func TokenAuth(username string, token string, wantWrite bool) error {
138 decoded, err := base64.RawStdEncoding.DecodeString(token)
139 if err != nil {
140 log.Println(err)
141 return errors.New("invalid token")
142 }
143 sum := sha256.Sum224(decoded)
144 hash := base64.RawStdEncoding.EncodeToString(sum[:])
145 row, err := db.Query(`SELECT b.expiration, b.readonly FROM user a
146 INNER JOIN token b ON a.userID = b.UserID WHERE
147 UPPER(a.name) LIKE UPPER(?) AND
148 UPPER(b.token) LIKE UPPER(?)`,
149 username, hash)
150 if err != nil {
151 log.Println(err)
152 return errors.New("unexpected error")
153 }
154 defer row.Close()
155 if !row.Next() {
156 return errors.New("invalid token")
157 }
158 var expiration int64
159 var readonly bool
160 row.Scan(&expiration, &readonly)
161 if expiration <= time.Now().Unix() {
162 return errors.New("token expired")
163 }
164 if wantWrite {
165 if readonly {
166 return errors.New("the token only has read access")
167 }
168 }
169 return nil
170 }
171