0.1 5d00907

user.go RawHistoryFolder

1package queries
2
3import (
4	"database/sql"
5	"fmt"
6
7	"github.com/bnema/gordon/internal/db"
8	"github.com/bnema/gordon/internal/server"
9	"github.com/google/uuid"
10)
11
12func generateUUID() string {
13	return uuid.New().String()
14}
15
16// UserInfo holds the essential information for a Github user.
17type GithubUserInfo struct {
18	Login      string `json:"login"`
19	AvatarURL  string `json:"avatar_url"`
20	ProfileURL string `json:"html_url"`
21	Emails     []string
22}
23
24// CreateUser creates a new user along with the associated account, provider, and session.
25func CreateUser(a *server.App, accessToken string, browserInfo string, userInfo *GithubUserInfo) error {
26	// Check if a user already exists. If so, return an error.
27	if exists, err := CheckDBUserExists(a); err != nil || exists {
28		return fmt.Errorf("error checking user or user already exists: %v", err)
29	}
30
31	user, err := createDBUser(a, userInfo)
32	if err != nil {
33		return err
34	}
35
36	// update the global state
37	a.DBTables.User.ID = user.ID
38	a.DBTables.User.Name = user.Name
39	a.DBTables.User.Email = user.Email
40
41	account, err := createDBAccount(a)
42	if err != nil {
43		return err
44	}
45
46	// update the global state
47	a.DBTables.Account.ID = account.ID
48	a.DBTables.Account.UserID = account.UserID
49
50	err = createDBGitHubProvider(a, userInfo)
51	if err != nil {
52		return err
53	}
54
55	return createDBSession(a, browserInfo, accessToken, account.ID)
56}
57
58func createDBUser(a *server.App, userInfo *GithubUserInfo) (*db.User, error) {
59	user := &db.User{
60		ID:    generateUUID(),
61		Name:  userInfo.Login,
62		Email: userInfo.Emails[0],
63	}
64
65	_, err := a.DB.Exec(
66		"INSERT INTO user (id, name, email) VALUES (?, ?, ?)",
67		user.ID, user.Name, user.Email,
68	)
69	return user, err
70}
71
72func CheckDBUserExists(a *server.App) (bool, error) {
73	var userID string
74	err := a.DB.QueryRow("SELECT id FROM user").Scan(&userID)
75	if err != nil {
76		if err == sql.ErrNoRows {
77			return false, nil
78		}
79		return false, err
80	}
81
82	if userID != "" {
83		return true, nil
84	}
85
86	return false, nil
87}
88
89// If there is already a user, we compare the login and email to see if it is the same user
90func CheckDBUserIsGood(a *server.App, userInfo *GithubUserInfo) (bool, error) {
91	login := userInfo.Login
92	email := userInfo.Emails[0]
93
94	// Check if the user exists based on github login and email
95	query := "SELECT user.id, user.name, user.email FROM user INNER JOIN account ON user.id = account.user_id INNER JOIN provider ON account.id = provider.account_id WHERE provider.login = ? AND provider.email = ?"
96	err := a.DB.QueryRow(query, login, email).Scan(&a.DBTables.User.ID, &a.DBTables.User.Name, &a.DBTables.User.Email)
97	if err != nil {
98		if err == sql.ErrNoRows {
99			return false, nil
100		}
101		return false, err
102	}
103
104	if a.DBTables.User.ID != "" {
105		return true, nil
106	}
107
108	return false, nil
109}
110
111func UpdateUser(a *server.App, accessToken string, browserInfo string, userInfo *GithubUserInfo) (*db.User, error) {
112
113	err := CreateOrUpdateDBSession(a, accessToken, browserInfo)
114	if err != nil {
115		return nil, fmt.Errorf("could not create or update session: %w", err)
116	}
117
118	user := a.DBTables.User
119
120	query := "SELECT user.id, user.name, user.email FROM user INNER JOIN account ON user.id = account.user_id INNER JOIN provider ON account.id = provider.account_id WHERE provider.login = ? AND provider.email = ?"
121	err = a.DB.QueryRow(query, userInfo.Login, userInfo.Emails[0]).Scan(&user.ID, &user.Name, &user.Email)
122	if err != nil {
123		return nil, err
124	}
125
126	return &user, nil
127
128}
129
130func GetAccountCount(a *server.App) (int, error) {
131	var count int
132	err := a.DB.QueryRow("SELECT COUNT(*) FROM account").Scan(&count)
133	if err != nil {
134		return 0, err
135	}
136
137	return count, nil
138}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close