Users database

This commit is contained in:
Meutel 2017-09-09 17:12:37 +02:00
parent d844432641
commit 9a50ccd2fc
7 changed files with 75 additions and 21 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ calibre.db
bouquins.json
Gopkg.lock
vendor/
users.db

View File

@ -8,6 +8,7 @@ Bouquins in Go
* tests
* auth downloads
* csrf
* userdb commands (init, migrate, add/remove user/email)
## Minify JS
@ -47,6 +48,7 @@ Options:
* calibre-path path to calibre data
* db-path path to calibre SQLite database (default <calibre-path>/metadata.db)
* user-db-path path to users SQLite database (default ./users.db)
* bind-address HTTP socket bind address
* prod (boolean) use minified javascript/CSS
* cookie-secret random string for cookie encryption
@ -55,3 +57,9 @@ Options:
* name provider name
* client-id OAuth client ID
* client-secret OAuth secret
## Users SQL
CREATE TABLE accounts (id varchar(36) PRIMARY KEY NOT NULL, name varchar(255) NOT NULL);
CREATE TABLE authentifiers (id varchar(36) NOT NULL, authentifier varchar(320) PRIMARY KEY NOT NULL, FOREIGN KEY(id) REFERENCES account(id));

View File

@ -127,11 +127,12 @@ func (app *Bouquins) CallbackPage(res http.ResponseWriter, req *http.Request) er
if err != nil {
return err
}
// FIXME list allowed users
if userEmail == "meutel@gmail.com" || userEmail == "meutel+github@meutel.net" {
app.SessionSet(sessionUser, "Meutel", res, req)
log.Println("User logged in", userEmail)
return RedirectHome(res, req)
user, err := Account(userEmail)
if err != nil {
log.Println("Error loading user", err)
return fmt.Errorf("Unknown user")
}
return fmt.Errorf("Unknown user")
app.SessionSet(sessionUser, user.DisplayName, res, req)
log.Println("User logged in", user.DisplayName)
return RedirectHome(res, req)
}

View File

@ -71,6 +71,7 @@ type Conf struct {
DbPath string `json:"db-path"`
CalibrePath string `json:"calibre-path"`
Prod bool `json:"prod"`
UserDbPath string `json:"user-db-path"`
CookieSecret string `json:"cookie-secret"`
ExternalURL string `json:"external-url"`
ProvidersConf []ProviderConf `json:"providers"`
@ -85,12 +86,20 @@ type ProviderConf struct {
// Bouquins contains application common resources: templates, database
type Bouquins struct {
Tpl *template.Template
DB *sql.DB
Tpl *template.Template
*sql.DB
UserDB *sql.DB
*Conf
OAuthConf map[string]*oauth2.Config
Cookies *sessions.CookieStore
}
// UserAccount is an user account
type UserAccount struct {
ID string // UUID
DisplayName string
}
// Series is a book series.
type Series struct {
ID int64 `json:"id,omitempty"`

View File

@ -104,6 +104,8 @@ const (
AND authors.id != ? ORDER BY authors.id`
sqlAuthor = "SELECT name FROM authors WHERE id = ?"
sqlAccount = "SELECT accounts.id, name FROM accounts, authentifiers WHERE authentifiers.id = accounts.id AND authentifiers.authentifier = ?"
defaultLimit = 10
qtBook QueryType = iota
@ -162,7 +164,10 @@ var queries = map[Query]string{
Query{qtAuthorBooks, false, false}: sqlAuthorBooks,
Query{qtAuthorCoauthors, false, false}: sqlAuthorAuthors,
}
var stmts = make(map[Query]*sql.Stmt)
var (
stmts = make(map[Query]*sql.Stmt)
stmtAccount *sql.Stmt
)
// QueryType is a type of query, with variants for sort and order
type QueryType uint
@ -214,6 +219,13 @@ func (app *Bouquins) PrepareAll() error {
}
stmts[q] = stmt
}
// users.db
var err error
stmtAccount, err = app.UserDB.Prepare(sqlAccount)
if err != nil {
log.Println(err, sqlAccount)
errcount++
}
if errcount > 0 {
return fmt.Errorf("%d errors on queries, see logs", errcount)
}

11
bouquins/dbusers.go Normal file
View File

@ -0,0 +1,11 @@
package bouquins
// Account returns user account from authentifier
func Account(authentifier string) (*UserAccount, error) {
account := new(UserAccount)
err := stmtAccount.QueryRow(authentifier).Scan(&account.ID, &account.DisplayName)
if err != nil {
return nil, err
}
return account, nil
}

36
main.go
View File

@ -15,8 +15,6 @@ import (
"meutel.net/meutel/go-bouquins/bouquins"
)
var db *sql.DB
// ReadConfig loads configuration file and initialize default value
func ReadConfig() (*bouquins.Conf, error) {
conf := new(bouquins.Conf)
@ -39,13 +37,16 @@ func ReadConfig() (*bouquins.Conf, error) {
if conf.DbPath == "" {
conf.DbPath = conf.CalibrePath + "/metadata.db"
}
if conf.UserDbPath == "" {
conf.UserDbPath = "./users.db"
}
if conf.BindAddress == "" {
conf.BindAddress = ":9000"
}
return conf, err
}
func initApp() *bouquins.Conf {
func initApp() *bouquins.Bouquins {
log.SetFlags(log.LstdFlags | log.Lshortfile)
conf, err := ReadConfig()
if err != nil {
@ -56,23 +57,33 @@ func initApp() *bouquins.Conf {
if err != nil {
log.Fatalln(err)
}
db, err = sql.Open("sqlite3", conf.DbPath)
db, err := sql.Open("sqlite3", conf.DbPath)
if err != nil {
log.Fatalln(err)
}
userdb, err := sql.Open("sqlite3", conf.UserDbPath)
if err != nil {
log.Fatalln(err)
}
oauthConf := make(map[string]*oauth2.Config)
for _, provider := range bouquins.Providers {
oauthConf[provider.Name()] = provider.Config(conf)
app := &bouquins.Bouquins{
Tpl: tpl,
DB: db,
UserDB: userdb,
Conf: conf,
OAuthConf: make(map[string]*oauth2.Config),
Cookies: sessions.NewCookieStore([]byte(conf.CookieSecret)),
}
for _, provider := range bouquins.Providers {
app.OAuthConf[provider.Name()] = provider.Config(conf)
}
app := &bouquins.Bouquins{Tpl: tpl, DB: db, OAuthConf: oauthConf, Cookies: sessions.NewCookieStore([]byte(conf.CookieSecret))}
err = app.PrepareAll()
if err != nil {
log.Fatalln(err)
}
assets(conf.CalibrePath)
router(app)
return conf
return app
}
func assets(calibre string) {
@ -109,7 +120,8 @@ func router(app *bouquins.Bouquins) {
}
func main() {
conf := initApp()
defer db.Close()
http.ListenAndServe(conf.BindAddress, nil)
app := initApp()
defer app.DB.Close()
defer app.UserDB.Close()
http.ListenAndServe(app.Conf.BindAddress, nil)
}