mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
feat: set html base path from server base path
refactor: services
This commit is contained in:
parent
d6e9f0295a
commit
c171d31f30
131
main.go
131
main.go
@ -1,29 +1,21 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/gorilla/securecookie"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gobuffalo/packr/v2"
|
"github.com/gobuffalo/packr/v2"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"github.com/joho/godotenv"
|
|
||||||
"github.com/rubenv/sql-migrate"
|
|
||||||
ini "gopkg.in/ini.v1"
|
|
||||||
|
|
||||||
"github.com/muety/wakapi/middlewares"
|
"github.com/muety/wakapi/middlewares"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
"github.com/muety/wakapi/routes"
|
"github.com/muety/wakapi/routes"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
|
"github.com/rubenv/sql-migrate"
|
||||||
|
|
||||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||||
@ -45,103 +37,8 @@ var (
|
|||||||
|
|
||||||
// TODO: Refactor entire project to be structured after business domains
|
// TODO: Refactor entire project to be structured after business domains
|
||||||
|
|
||||||
func readConfig() *models.Config {
|
|
||||||
if err := godotenv.Load(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
env := utils.LookupFatal("ENV")
|
|
||||||
dbType := utils.LookupFatal("WAKAPI_DB_TYPE")
|
|
||||||
dbUser := utils.LookupFatal("WAKAPI_DB_USER")
|
|
||||||
dbPassword := utils.LookupFatal("WAKAPI_DB_PASSWORD")
|
|
||||||
dbHost := utils.LookupFatal("WAKAPI_DB_HOST")
|
|
||||||
dbName := utils.LookupFatal("WAKAPI_DB_NAME")
|
|
||||||
dbPortStr := utils.LookupFatal("WAKAPI_DB_PORT")
|
|
||||||
defaultUserName := utils.LookupFatal("WAKAPI_DEFAULT_USER_NAME")
|
|
||||||
defaultUserPassword := utils.LookupFatal("WAKAPI_DEFAULT_USER_PASSWORD")
|
|
||||||
dbPort, err := strconv.Atoi(dbPortStr)
|
|
||||||
|
|
||||||
cfg, err := ini.Load("config.ini")
|
|
||||||
if err != nil {
|
|
||||||
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"))
|
|
||||||
if err != nil {
|
|
||||||
port = cfg.Section("server").Key("port").MustInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
basePath := cfg.Section("server").Key("base_path").MustString("/")
|
|
||||||
if strings.HasSuffix(basePath, "/") {
|
|
||||||
basePath = basePath[:len(basePath)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanUp := cfg.Section("app").Key("cleanup").MustBool(false)
|
|
||||||
|
|
||||||
// Read custom languages
|
|
||||||
customLangs := make(map[string]string)
|
|
||||||
languageKeys := cfg.Section("languages").Keys()
|
|
||||||
for _, k := range languageKeys {
|
|
||||||
customLangs[k.Name()] = k.MustString("unknown")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read language colors
|
|
||||||
// Source: https://raw.githubusercontent.com/ozh/github-colors/master/colors.json
|
|
||||||
var colors = make(map[string]string)
|
|
||||||
var rawColors map[string]struct {
|
|
||||||
Color string `json:"color"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := ioutil.ReadFile("data/colors.json")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &rawColors); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range rawColors {
|
|
||||||
colors[strings.ToLower(k)] = v.Color
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Read keys from env, so that users are not logged out every time the server is restarted
|
|
||||||
secureCookie := securecookie.New(
|
|
||||||
securecookie.GenerateRandomKey(64),
|
|
||||||
securecookie.GenerateRandomKey(32),
|
|
||||||
)
|
|
||||||
|
|
||||||
return &models.Config{
|
|
||||||
Env: env,
|
|
||||||
Port: port,
|
|
||||||
Addr: addr,
|
|
||||||
BasePath: basePath,
|
|
||||||
DbHost: dbHost,
|
|
||||||
DbPort: uint(dbPort),
|
|
||||||
DbUser: dbUser,
|
|
||||||
DbPassword: dbPassword,
|
|
||||||
DbName: dbName,
|
|
||||||
DbDialect: dbType,
|
|
||||||
DbMaxConn: dbMaxConn,
|
|
||||||
CleanUp: cleanUp,
|
|
||||||
SecureCookie: secureCookie,
|
|
||||||
DefaultUserName: defaultUserName,
|
|
||||||
DefaultUserPassword: defaultUserPassword,
|
|
||||||
CustomLanguages: customLangs,
|
|
||||||
LanguageColors: colors,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Read Config
|
config = models.GetConfig()
|
||||||
config = readConfig()
|
|
||||||
|
|
||||||
// Enable line numbers in logging
|
// Enable line numbers in logging
|
||||||
if config.IsDev() {
|
if config.IsDev() {
|
||||||
@ -159,7 +56,7 @@ func main() {
|
|||||||
db.DB().SetMaxOpenConns(int(config.DbMaxConn))
|
db.DB().SetMaxOpenConns(int(config.DbMaxConn))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
log.Fatal("Could not connect to database.")
|
log.Fatal("could not connect to database")
|
||||||
}
|
}
|
||||||
// TODO: Graceful shutdown
|
// TODO: Graceful shutdown
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
@ -169,16 +66,11 @@ func main() {
|
|||||||
migrateDo(db)
|
migrateDo(db)
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
aliasService = &services.AliasService{Config: config, Db: db}
|
aliasService = services.NewAliasService(db)
|
||||||
heartbeatService = &services.HeartbeatService{Config: config, Db: db}
|
heartbeatService = services.NewHeartbeatService(db)
|
||||||
userService = &services.UserService{Config: config, Db: db}
|
userService = services.NewUserService(db)
|
||||||
summaryService = &services.SummaryService{Config: config, Db: db, HeartbeatService: heartbeatService, AliasService: aliasService}
|
summaryService = services.NewSummaryService(db, heartbeatService, aliasService)
|
||||||
aggregationService = &services.AggregationService{Config: config, Db: db, UserService: userService, SummaryService: summaryService, HeartbeatService: heartbeatService}
|
aggregationService = services.NewAggregationService(db, userService, summaryService, heartbeatService)
|
||||||
|
|
||||||
svcs := []services.Initializable{aliasService, heartbeatService, userService, summaryService, aggregationService}
|
|
||||||
for _, s := range svcs {
|
|
||||||
s.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom migrations and initial data
|
// Custom migrations and initial data
|
||||||
addDefaultUser()
|
addDefaultUser()
|
||||||
@ -192,10 +84,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handlers
|
// Handlers
|
||||||
heartbeatHandler := routes.NewHeartbeatHandler(config, heartbeatService)
|
heartbeatHandler := routes.NewHeartbeatHandler(heartbeatService)
|
||||||
summaryHandler := routes.NewSummaryHandler(config, summaryService)
|
summaryHandler := routes.NewSummaryHandler(summaryService)
|
||||||
healthHandler := routes.NewHealthHandler(db)
|
healthHandler := routes.NewHealthHandler(db)
|
||||||
indexHandler := routes.NewIndexHandler(config, userService)
|
indexHandler := routes.NewIndexHandler(userService)
|
||||||
|
|
||||||
// Setup Routers
|
// Setup Routers
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
@ -208,7 +100,6 @@ func main() {
|
|||||||
loggingMiddleware := middlewares.NewLoggingMiddleware().Handler
|
loggingMiddleware := middlewares.NewLoggingMiddleware().Handler
|
||||||
corsMiddleware := handlers.CORS()
|
corsMiddleware := handlers.CORS()
|
||||||
authenticateMiddleware := middlewares.NewAuthenticateMiddleware(
|
authenticateMiddleware := middlewares.NewAuthenticateMiddleware(
|
||||||
config,
|
|
||||||
userService,
|
userService,
|
||||||
[]string{"/api/health"},
|
[]string{"/api/health"},
|
||||||
).Handler
|
).Handler
|
||||||
|
@ -21,9 +21,9 @@ type AuthenticateMiddleware struct {
|
|||||||
whitelistPaths []string
|
whitelistPaths []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthenticateMiddleware(config *models.Config, userService *services.UserService, whitelistPaths []string) *AuthenticateMiddleware {
|
func NewAuthenticateMiddleware(userService *services.UserService, whitelistPaths []string) *AuthenticateMiddleware {
|
||||||
return &AuthenticateMiddleware{
|
return &AuthenticateMiddleware{
|
||||||
config: config,
|
config: models.GetConfig(),
|
||||||
userSrvc: userService,
|
userSrvc: userService,
|
||||||
cache: cache.New(1*time.Hour, 2*time.Hour),
|
cache: cache.New(1*time.Hour, 2*time.Hour),
|
||||||
whitelistPaths: whitelistPaths,
|
whitelistPaths: whitelistPaths,
|
||||||
|
124
models/config.go
124
models/config.go
@ -1,6 +1,18 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "github.com/gorilla/securecookie"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/gorilla/securecookie"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cfg *Config
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Env string
|
Env string
|
||||||
@ -27,3 +39,113 @@ type Config struct {
|
|||||||
func (c *Config) IsDev() bool {
|
func (c *Config) IsDev() bool {
|
||||||
return c.Env == "dev"
|
return c.Env == "dev"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetConfig(config *Config) {
|
||||||
|
cfg = config
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfig() *Config {
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func LookupFatal(key string) string {
|
||||||
|
v, ok := os.LookupEnv(key)
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("missing env variable '%s'", key)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func readConfig() *Config {
|
||||||
|
if err := godotenv.Load(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
env := LookupFatal("ENV")
|
||||||
|
dbType := LookupFatal("WAKAPI_DB_TYPE")
|
||||||
|
dbUser := LookupFatal("WAKAPI_DB_USER")
|
||||||
|
dbPassword := LookupFatal("WAKAPI_DB_PASSWORD")
|
||||||
|
dbHost := LookupFatal("WAKAPI_DB_HOST")
|
||||||
|
dbName := LookupFatal("WAKAPI_DB_NAME")
|
||||||
|
dbPortStr := LookupFatal("WAKAPI_DB_PORT")
|
||||||
|
defaultUserName := LookupFatal("WAKAPI_DEFAULT_USER_NAME")
|
||||||
|
defaultUserPassword := LookupFatal("WAKAPI_DEFAULT_USER_PASSWORD")
|
||||||
|
dbPort, err := strconv.Atoi(dbPortStr)
|
||||||
|
|
||||||
|
cfg, err := ini.Load("config.ini")
|
||||||
|
if err != nil {
|
||||||
|
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"))
|
||||||
|
if err != nil {
|
||||||
|
port = cfg.Section("server").Key("port").MustInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
basePath := cfg.Section("server").Key("base_path").MustString("/")
|
||||||
|
if strings.HasSuffix(basePath, "/") {
|
||||||
|
basePath = basePath[:len(basePath)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanUp := cfg.Section("app").Key("cleanup").MustBool(false)
|
||||||
|
|
||||||
|
// Read custom languages
|
||||||
|
customLangs := make(map[string]string)
|
||||||
|
languageKeys := cfg.Section("languages").Keys()
|
||||||
|
for _, k := range languageKeys {
|
||||||
|
customLangs[k.Name()] = k.MustString("unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read language colors
|
||||||
|
// Source: https://raw.githubusercontent.com/ozh/github-colors/master/colors.json
|
||||||
|
var colors = make(map[string]string)
|
||||||
|
var rawColors map[string]struct {
|
||||||
|
Color string `json:"color"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile("data/colors.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, &rawColors); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range rawColors {
|
||||||
|
colors[strings.ToLower(k)] = v.Color
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Read keys from env, so that users are not logged out every time the server is restarted
|
||||||
|
secureCookie := securecookie.New(
|
||||||
|
securecookie.GenerateRandomKey(64),
|
||||||
|
securecookie.GenerateRandomKey(32),
|
||||||
|
)
|
||||||
|
|
||||||
|
return &Config{
|
||||||
|
Env: env,
|
||||||
|
Port: port,
|
||||||
|
Addr: addr,
|
||||||
|
BasePath: basePath,
|
||||||
|
DbHost: dbHost,
|
||||||
|
DbPort: uint(dbPort),
|
||||||
|
DbUser: dbUser,
|
||||||
|
DbPassword: dbPassword,
|
||||||
|
DbName: dbName,
|
||||||
|
DbDialect: dbType,
|
||||||
|
DbMaxConn: dbMaxConn,
|
||||||
|
CleanUp: cleanUp,
|
||||||
|
SecureCookie: secureCookie,
|
||||||
|
DefaultUserName: defaultUserName,
|
||||||
|
DefaultUserPassword: defaultUserPassword,
|
||||||
|
CustomLanguages: customLangs,
|
||||||
|
LanguageColors: colors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
5
models/models.go
Normal file
5
models/models.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SetConfig(readConfig())
|
||||||
|
}
|
@ -16,10 +16,10 @@ type HeartbeatHandler struct {
|
|||||||
heartbeatSrvc *services.HeartbeatService
|
heartbeatSrvc *services.HeartbeatService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHeartbeatHandler(config *models.Config, heartbearService *services.HeartbeatService) *HeartbeatHandler {
|
func NewHeartbeatHandler(heartbeatService *services.HeartbeatService) *HeartbeatHandler {
|
||||||
return &HeartbeatHandler{
|
return &HeartbeatHandler{
|
||||||
config: config,
|
config: models.GetConfig(),
|
||||||
heartbeatSrvc: heartbearService,
|
heartbeatSrvc: heartbeatService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ type IndexHandler struct {
|
|||||||
var loginDecoder = schema.NewDecoder()
|
var loginDecoder = schema.NewDecoder()
|
||||||
var signupDecoder = schema.NewDecoder()
|
var signupDecoder = schema.NewDecoder()
|
||||||
|
|
||||||
func NewIndexHandler(config *models.Config, userService *services.UserService) *IndexHandler {
|
func NewIndexHandler(userService *services.UserService) *IndexHandler {
|
||||||
return &IndexHandler{
|
return &IndexHandler{
|
||||||
config: config,
|
config: models.GetConfig(),
|
||||||
userSrvc: userService,
|
userSrvc: userService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package routes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/muety/wakapi/models"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -22,6 +23,9 @@ func loadTemplates() {
|
|||||||
"date": utils.FormatDateHuman,
|
"date": utils.FormatDateHuman,
|
||||||
"title": strings.Title,
|
"title": strings.Title,
|
||||||
"capitalize": utils.Capitalize,
|
"capitalize": utils.Capitalize,
|
||||||
|
"getBasePath": func() string {
|
||||||
|
return models.GetConfig().BasePath
|
||||||
|
},
|
||||||
})
|
})
|
||||||
templates = make(map[string]*template.Template)
|
templates = make(map[string]*template.Template)
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@ type SummaryHandler struct {
|
|||||||
config *models.Config
|
config *models.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSummaryHandler(config *models.Config, summaryService *services.SummaryService) *SummaryHandler {
|
func NewSummaryHandler(summaryService *services.SummaryService) *SummaryHandler {
|
||||||
return &SummaryHandler{
|
return &SummaryHandler{
|
||||||
cummarySrvc: summaryService,
|
cummarySrvc: summaryService,
|
||||||
config: config,
|
config: models.GetConfig(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,14 +22,22 @@ type AggregationService struct {
|
|||||||
HeartbeatService *HeartbeatService
|
HeartbeatService *HeartbeatService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewAggregationService(db *gorm.DB, userService *UserService, summaryService *SummaryService, heartbeatService *HeartbeatService) *AggregationService {
|
||||||
|
return &AggregationService{
|
||||||
|
Config: models.GetConfig(),
|
||||||
|
Db: db,
|
||||||
|
UserService: userService,
|
||||||
|
SummaryService: summaryService,
|
||||||
|
HeartbeatService: heartbeatService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type AggregationJob struct {
|
type AggregationJob struct {
|
||||||
UserID string
|
UserID string
|
||||||
From time.Time
|
From time.Time
|
||||||
To time.Time
|
To time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *AggregationService) Init() {}
|
|
||||||
|
|
||||||
// Schedule a job to (re-)generate summaries every day shortly after midnight
|
// Schedule a job to (re-)generate summaries every day shortly after midnight
|
||||||
// TODO: Make configurable
|
// TODO: Make configurable
|
||||||
func (srv *AggregationService) Schedule() {
|
func (srv *AggregationService) Schedule() {
|
||||||
|
@ -13,9 +13,14 @@ type AliasService struct {
|
|||||||
Db *gorm.DB
|
Db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
var userAliases sync.Map
|
func NewAliasService(db *gorm.DB) *AliasService {
|
||||||
|
return &AliasService{
|
||||||
|
Config: models.GetConfig(),
|
||||||
|
Db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (srv *AliasService) Init() {}
|
var userAliases sync.Map
|
||||||
|
|
||||||
func (srv *AliasService) LoadUserAliases(userId string) error {
|
func (srv *AliasService) LoadUserAliases(userId string) error {
|
||||||
var aliases []*models.Alias
|
var aliases []*models.Alias
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package services
|
|
||||||
|
|
||||||
type Initializable interface {
|
|
||||||
Init()
|
|
||||||
}
|
|
@ -21,7 +21,12 @@ type HeartbeatService struct {
|
|||||||
Db *gorm.DB
|
Db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *HeartbeatService) Init() {}
|
func NewHeartbeatService(db *gorm.DB) *HeartbeatService {
|
||||||
|
return &HeartbeatService{
|
||||||
|
Config: models.GetConfig(),
|
||||||
|
Db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (srv *HeartbeatService) InsertBatch(heartbeats []*models.Heartbeat) error {
|
func (srv *HeartbeatService) InsertBatch(heartbeats []*models.Heartbeat) error {
|
||||||
var batch []interface{}
|
var batch []interface{}
|
||||||
|
@ -21,15 +21,21 @@ type SummaryService struct {
|
|||||||
AliasService *AliasService
|
AliasService *AliasService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewSummaryService(db *gorm.DB, heartbeatService *HeartbeatService, aliasService *AliasService) *SummaryService {
|
||||||
|
return &SummaryService{
|
||||||
|
Config: models.GetConfig(),
|
||||||
|
Cache: cache.New(24*time.Hour, 24*time.Hour),
|
||||||
|
Db: db,
|
||||||
|
HeartbeatService: heartbeatService,
|
||||||
|
AliasService: aliasService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Interval struct {
|
type Interval struct {
|
||||||
Start time.Time
|
Start time.Time
|
||||||
End time.Time
|
End time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *SummaryService) Init() {
|
|
||||||
srv.Cache = cache.New(24*time.Hour, 24*time.Hour)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (srv *SummaryService) Construct(from, to time.Time, user *models.User, recompute bool) (*models.Summary, error) {
|
func (srv *SummaryService) Construct(from, to time.Time, user *models.User, recompute bool) (*models.Summary, error) {
|
||||||
var existingSummaries []*models.Summary
|
var existingSummaries []*models.Summary
|
||||||
var cacheKey string
|
var cacheKey string
|
||||||
|
@ -13,7 +13,12 @@ type UserService struct {
|
|||||||
Db *gorm.DB
|
Db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *UserService) Init() {}
|
func NewUserService(db *gorm.DB) *UserService {
|
||||||
|
return &UserService{
|
||||||
|
Config: models.GetConfig(),
|
||||||
|
Db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (srv *UserService) GetUserById(userId string) (*models.User, error) {
|
func (srv *UserService) GetUserById(userId string) (*models.User, error) {
|
||||||
u := &models.User{}
|
u := &models.User{}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func LookupFatal(key string) string {
|
|
||||||
v, ok := os.LookupEnv(key)
|
|
||||||
if !ok {
|
|
||||||
log.Fatalf("missing env variable '%s'", key)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Wakapi – Coding Statistics</title>
|
<title>Wakapi – Coding Statistics</title>
|
||||||
<base href="/">
|
<base href="{{ getBasePath }}">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
|
||||||
<link rel="icon" data-emoji="📊" type="image/png">
|
<link rel="icon" data-emoji="📊" type="image/png">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
|
||||||
|
Loading…
Reference in New Issue
Block a user