init.go 6.18 KB
Newer Older
zauberstuhl's avatar
zauberstuhl committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
package app
//
// GangGo Application Server
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

import (
21 22
  "io/ioutil"
  "encoding/json"
zauberstuhl's avatar
zauberstuhl committed
23
  "github.com/revel/revel"
zauberstuhl's avatar
zauberstuhl committed
24 25 26
  "git.feneas.org/ganggo/ganggo/app/helpers"
  "git.feneas.org/ganggo/ganggo/app/models"
  "git.feneas.org/ganggo/ganggo/app/jobs"
27
  run "github.com/revel/modules/jobs/app/jobs"
zauberstuhl's avatar
zauberstuhl committed
28
  federation "git.feneas.org/ganggo/federation"
29
  "net/http"
zauberstuhl's avatar
zauberstuhl committed
30 31
  "strings"
  "fmt"
32
  "time"
33
  "github.com/getsentry/raven-go"
zauberstuhl's avatar
zauberstuhl committed
34 35
)

36 37 38
// will be set on compile time
var AppVersion = "v0"

zauberstuhl's avatar
zauberstuhl committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
func InitDB() {
  revel.Config.SetSection("ganggo")
  driver, found := revel.Config.String("db.driver")
  if !found {
    panic("Datbase config missing")
  }
  user, found := revel.Config.String("db.user")
  if !found {
    panic("Datbase config missing")
  }
  password, found := revel.Config.String("db.password")
  if !found {
    panic("Datbase config missing")
  }
  database, found := revel.Config.String("db.database")
  if !found {
    panic("Datbase config missing")
  }
  host, found := revel.Config.String("db.host")
  if !found {
    panic("Datbase config missing")
  }
61 62 63 64
  dsn, found := revel.Config.String("db.dsn")
  if !found {
    panic("Datbase config missing")
  }
zauberstuhl's avatar
zauberstuhl committed
65 66

  models.DB.Driver = driver
67
  models.DB.Url = fmt.Sprintf(dsn, user, password, host, database)
zauberstuhl's avatar
zauberstuhl committed
68 69 70
  models.InitDB()
}

zauberstuhl's avatar
zauberstuhl committed
71 72 73 74 75
func InitSocialRelay() {
  // register the pod at the-federation.info
  // this is required for using the social-relay
  revel.Config.SetSection("ganggo")
  subscribe := revel.Config.BoolDefault("relay.subscribe", false)
76 77 78 79 80 81 82 83 84 85 86 87 88
  address, found := revel.Config.String("address")
  if !revel.DevMode && subscribe && found {
    result := struct{Error string `json:"error"`}{}
    endpoint := fmt.Sprintf(revel.Config.StringDefault(
      "relay.endpoint", "https://the-federation.info/register/%s",
    ), address)

    err := federation.FetchJson("GET", endpoint, nil, &result)
    if err != nil {
      revel.AppLog.Error("InitSocialRelay failed",
        "result", result, "err", err)
    } else {
      revel.AppLog.Info("InitSocialRelay registration", "result", result)
zauberstuhl's avatar
zauberstuhl committed
89
    }
90 91 92
  } else {
    revel.AppLog.Info("InitSocialRelay skipped",
      "devMode", revel.DevMode, "subscribe", subscribe)
zauberstuhl's avatar
zauberstuhl committed
93 94 95
  }
}

zauberstuhl's avatar
zauberstuhl committed
96 97 98 99 100 101 102
func init() {
  // Filters is the default set of global filters.
  revel.Filters = []revel.Filter{
    revel.PanicFilter,             // Recover from panics and display an error page instead.
    revel.RouterFilter,            // Use the routing table to select the right Action
    revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
    revel.ParamsFilter,            // Parse parameters into Controller.Params.
103
    JsonParamsFilter,
zauberstuhl's avatar
zauberstuhl committed
104 105 106 107 108 109 110 111 112 113 114 115
    revel.SessionFilter,           // Restore and write the session cookie.
    revel.FlashFilter,             // Restore and write the flash cookie.
    revel.ValidationFilter,        // Restore kept validation errors and save new ones from cookie.
    revel.I18nFilter,              // Resolve the requested language
    HeaderFilter,                  // Add some security based headers
    revel.InterceptorFilter,       // Run interceptors around the action.
    revel.CompressFilter,          // Compress the result.
    revel.ActionInvoker,           // Invoke the action.
  }

  // register startup functions with OnAppStart
  revel.OnAppStart(InitDB)
zauberstuhl's avatar
zauberstuhl committed
116
  revel.OnAppStart(InitSocialRelay)
117

118
  revel.OnAppStart(func() {
Ghost User's avatar
Ghost User committed
119 120 121 122 123 124 125 126 127 128 129 130 131
    revel.Config.SetSection("ganggo")

    // configure the federation library
    host := revel.Config.StringDefault("proto", "http://") +
      revel.Config.StringDefault("address", "localhost:9000")
    apiVersion := revel.Config.StringDefault("api.version", "v0")
    federation.SetConfig(federation.Config{
      Host: host, ApiVersion: apiVersion,
      GuidURLFormat: host + "/posts/%s",
      ApURLFormat: host + "/api/" + apiVersion + "/ap/%s",
    })

    // set custom logger options
132 133 134
    federation.SetLogger(helpers.AppLogWrapper{
      Name: "federation",
    })
Ghost User's avatar
Ghost User committed
135

136 137 138 139 140
    // if sentry credentials exists
    // send reports to upstream
    sentryDSN, found := revel.Config.String("sentry.DSN")
    if found {
      raven.SetDSN(sentryDSN)
141
      raven.SetRelease(AppVersion)
142 143
      revel.RootLog.SetHandler(helpers.SentryLogHandler{})
    }
144
  })
zauberstuhl's avatar
zauberstuhl committed
145

146 147 148
  // register jobs running on an interval
  revel.OnAppStart(func() {
    run.Every(24*time.Hour, jobs.Session{})
149 150 151 152 153 154 155 156

    revel.Config.SetSection("ganggo")
    if revel.Config.BoolDefault("telegram.enabled", false) {
      host := revel.Config.StringDefault("proto", "http://") +
        revel.Config.StringDefault("address", "localhost:9000")
      token := revel.Config.StringDefault("telegram.token", "")
      run.Now(jobs.TelegramWebhook{Token: token, Url: host})
    }
157
  })
zauberstuhl's avatar
zauberstuhl committed
158 159 160 161 162 163 164 165 166 167 168 169 170 171
}

// TODO turn this into revel.HeaderFilter
// should probably also have a filter for CSRF
// not sure if it can go in the same filter or not
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
  // Add some common security headers
  c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
  c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
  c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")

  fc[0](c, fc[1:]) // Execute the next filter stage.
}

172 173 174
var JsonParamsFilter = func(c *revel.Controller, fc []revel.Filter) {
  if strings.Contains(c.Request.ContentType, "application/json") {
    data := map[string]string{}
175 176
    request := c.Request.In.GetRaw().(*http.Request)
    content, _ := ioutil.ReadAll(request.Body)
177 178 179 180 181 182 183 184
    json.Unmarshal(content, &data)
    for k, v := range data {
      revel.TRACE.Println("application/json", k, v)
      c.Params.Values.Set(k, v)
    }
  }
  fc[0](c, fc[1:])
}