Experimental Postgres support.

This commit is contained in:
Ferdinand Mütsch 2020-03-31 12:03:49 +02:00
parent b858a02ecd
commit 1510bcaa91
4 changed files with 45 additions and 25 deletions

View File

@ -1,4 +1,5 @@
ENV=prod
WAKAPI_DB_TYPE=mysql
WAKAPI_DB_USER=myuser
WAKAPI_DB_PASSWORD=mysecretpassword
WAKAPI_DB_HOST=localhost

View File

@ -8,13 +8,13 @@
## Prerequisites
### Server
* Go >= 1.13 (with `$GOPATH` properly set)
* A MySQL database
* An SQL database (MySQL or Postgres)
### Client
* [WakaTime plugin](https://wakatime.com/plugins) for your editor / IDE
## Usage
* Create an empty MySQL database
* Create an empty database
* Enable Go module support: `export GO111MODULE=on`
* Get code: `go get github.com/muety/wakapi`
* Go to project root: `cd "$GOPATH/src/github.com/muety/wakapi"`
@ -36,6 +36,8 @@
* To get the api key look in the logs `docker-compose logs | grep "API key"`
* The application should now be running on `localhost:3000`
### Build for specific platform
Example: `GOOS=darwin GOARCH=386 go build -o build/wakapi_1.1.0_$GOOS_$GOARCH github.com/muety/wakapi`
### User Accounts
* When starting wakapi for the first time, a default user _**admin**_ with password _**admin**_ is created. The corresponding API key is printed to the console.
@ -64,12 +66,6 @@ For the above example, you would need to add two aliases, like this:
It is recommended to use wakapi behind a **reverse proxy**, like [Caddy](https://caddyserver.com) or _nginx_ to enable **TLS encryption** (HTTPS).
However, if you want to expose your wakapi instance to the public anyway, you need to set `listen = 0.0.0.0` in `config.ini`
## Todo
* User sign up and log in
* Additional endpoints for retrieving statistics data
* Support for SQLite database
* Unit tests
## Important Note
**This is not an alternative to using WakaTime.** It is just a custom, non-commercial, self-hosted application to collect coding statistics using the already existing editor plugins provided by the WakaTime community. It was created for personal use only and with the purpose of keeping the sovereignity of your own data. However, if you like the official product, **please support the authors and buy an official WakaTime subscription!**

10
main.go
View File

@ -27,6 +27,7 @@ import (
"github.com/n1try/wakapi/utils"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres"
)
// TODO: Refactor entire project to be structured after business domains
@ -36,7 +37,9 @@ func readConfig() *models.Config {
log.Fatal(err)
}
// TODO: Use jinzhu/configor or so
env, _ := os.LookupEnv("ENV")
dbType, valid := os.LookupEnv("WAKAPI_DB_TYPE")
dbUser, valid := os.LookupEnv("WAKAPI_DB_USER")
dbPassword, valid := os.LookupEnv("WAKAPI_DB_PASSWORD")
dbHost, valid := os.LookupEnv("WAKAPI_DB_HOST")
@ -53,6 +56,10 @@ func readConfig() *models.Config {
log.Fatalf("Fail to read file: %v", err)
}
if dbType == "" {
dbType = "mysql"
}
dbMaxConn := cfg.Section("database").Key("max_connections").MustUint(1)
addr := cfg.Section("server").Key("listen").MustString("127.0.0.1")
port, err := strconv.Atoi(os.Getenv("PORT"))
@ -99,7 +106,7 @@ func readConfig() *models.Config {
DbUser: dbUser,
DbPassword: dbPassword,
DbName: dbName,
DbDialect: "mysql",
DbDialect: dbType,
DbMaxConn: dbMaxConn,
CleanUp: cleanUp,
CustomLanguages: customLangs,
@ -119,6 +126,7 @@ func main() {
if err != nil {
log.Fatal("Could not connect to database.")
}
// TODO: Graceful shutdown
defer db.Close()
// Migrate database schema

View File

@ -2,9 +2,8 @@ package utils
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"time"
"github.com/n1try/wakapi/models"
@ -32,18 +31,34 @@ func ParseUserAgent(ua string) (string, string, error) {
}
func MakeConnectionString(config *models.Config) string {
location, _ := time.LoadLocation("Local")
str := strings.Builder{}
str.WriteString(config.DbUser)
str.WriteString(":")
str.WriteString(config.DbPassword)
str.WriteString("@tcp(")
str.WriteString(config.DbHost)
str.WriteString(":")
str.WriteString(strconv.Itoa(int(config.DbPort)))
str.WriteString(")/")
str.WriteString(config.DbName)
str.WriteString("?charset=utf8&parseTime=true&loc=")
str.WriteString(location.String())
return str.String()
switch config.DbDialect {
case "mysql":
return mySqlConnectionString(config)
case "postgres":
return postgresConnectionString(config)
}
return ""
}
func mySqlConnectionString(config *models.Config) string {
location, _ := time.LoadLocation("Local")
return fmt.Sprintf(
"%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=true&loc=%s",
config.DbUser,
config.DbPassword,
config.DbHost,
config.DbPort,
config.DbName,
location.String(),
)
}
func postgresConnectionString(config *models.Config) string {
return fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s sslmode=disable",
config.DbHost,
config.DbPort,
config.DbUser,
config.DbName,
config.DbPassword,
)
}