Improved auth and logging

This commit is contained in:
Eduard Urbach 2017-06-15 15:50:39 +02:00
parent a6a3609ab7
commit c858a58123
7 changed files with 73 additions and 39 deletions

30
auth.go Normal file
View File

@ -0,0 +1,30 @@
package main
import (
"encoding/json"
"io/ioutil"
)
// APIKeys ...
type APIKeys struct {
Google struct {
ID string `json:"id"`
Secret string `json:"secret"`
} `json:"google"`
Facebook struct {
ID string `json:"id"`
Secret string `json:"secret"`
} `json:"facebook"`
}
var apiKeys APIKeys
func init() {
data, _ := ioutil.ReadFile("security/api-keys.json")
err := json.Unmarshal(data, &apiKeys)
if err != nil {
panic(err)
}
}

View File

@ -12,14 +12,6 @@ import (
"golang.org/x/oauth2/google" "golang.org/x/oauth2/google"
) )
// APIKeys ...
type APIKeys struct {
Google struct {
ID string `json:"id"`
Secret string `json:"secret"`
} `json:"google"`
}
// GoogleUser is the user data we receive from Google // GoogleUser is the user data we receive from Google
type GoogleUser struct { type GoogleUser struct {
Sub string `json:"sub"` Sub string `json:"sub"`
@ -35,13 +27,9 @@ type GoogleUser struct {
// EnableGoogleLogin enables Google login for the app. // EnableGoogleLogin enables Google login for the app.
func EnableGoogleLogin(app *aero.Application) { func EnableGoogleLogin(app *aero.Application) {
var api APIKeys
data, _ := ioutil.ReadFile("security/api-keys.json")
json.Unmarshal(data, &api)
conf := &oauth2.Config{ conf := &oauth2.Config{
ClientID: api.Google.ID, ClientID: apiKeys.Google.ID,
ClientSecret: api.Google.Secret, ClientSecret: apiKeys.Google.Secret,
RedirectURL: "https://beta.notify.moe/auth/google/callback", RedirectURL: "https://beta.notify.moe/auth/google/callback",
Scopes: []string{ Scopes: []string{
"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.email",
@ -75,6 +63,7 @@ func EnableGoogleLogin(app *aero.Application) {
// Construct the OAuth client // Construct the OAuth client
client := conf.Client(oauth2.NoContext, token) client := conf.Client(oauth2.NoContext, token)
// Fetch user data from Google
resp, err := client.Get("https://www.googleapis.com/oauth2/v3/userinfo") resp, err := client.Get("https://www.googleapis.com/oauth2/v3/userinfo")
if err != nil { if err != nil {
@ -84,6 +73,7 @@ func EnableGoogleLogin(app *aero.Application) {
defer resp.Body.Close() defer resp.Body.Close()
data, _ := ioutil.ReadAll(resp.Body) data, _ := ioutil.ReadAll(resp.Body)
// Construct a GoogleUser object
var googleUser GoogleUser var googleUser GoogleUser
err = json.Unmarshal(data, &googleUser) err = json.Unmarshal(data, &googleUser)
@ -91,6 +81,7 @@ func EnableGoogleLogin(app *aero.Application) {
return ctx.Error(http.StatusBadRequest, "Failed parsing user data (JSON)", err) return ctx.Error(http.StatusBadRequest, "Failed parsing user data (JSON)", err)
} }
// Try to find an existing user by the associated e-mail address
email := googleUser.Email email := googleUser.Email
user, getErr := arn.GetUserByEmail(email) user, getErr := arn.GetUserByEmail(email)
@ -98,8 +89,10 @@ func EnableGoogleLogin(app *aero.Application) {
return ctx.Error(http.StatusForbidden, "Email not registered", err) return ctx.Error(http.StatusForbidden, "Email not registered", err)
} }
// Login
session.Set("userId", user.ID) session.Set("userId", user.ID)
// Redirect back to frontpage
return ctx.Redirect("/") return ctx.Redirect("/")
}) })
} }

View File

@ -1,6 +1,8 @@
package main package main
import ( import (
"net/http"
"os"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -12,10 +14,10 @@ import (
func init() { func init() {
err := log.NewChannel("error") err := log.NewChannel("error")
err.AddOutput(log.File("logs/error.log")) err.AddOutput(log.File("logs/error.log"))
// err.AddOutput(os.Stderr) err.AddOutput(os.Stderr)
web := log.NewChannel("web") request := log.NewChannel("request")
web.AddOutput(log.File("logs/request.log")) request.AddOutput(log.File("logs/request.log"))
app.Use(func(ctx *aero.Context, next func()) { app.Use(func(ctx *aero.Context, next func()) {
start := time.Now() start := time.Now()
@ -25,11 +27,20 @@ func init() {
responseTimeString = strings.Repeat(" ", 8-len(responseTimeString)) + responseTimeString responseTimeString = strings.Repeat(" ", 8-len(responseTimeString)) + responseTimeString
// Log every request // Log every request
web.Info(ctx.RealIP(), ctx.StatusCode, responseTimeString, ctx.URI()) request.Info(ctx.RealIP(), ctx.StatusCode, responseTimeString, ctx.URI())
// Log all requests that failed
switch ctx.StatusCode {
case http.StatusOK, http.StatusFound, http.StatusMovedPermanently, http.StatusPermanentRedirect, http.StatusTemporaryRedirect:
// Ok.
default:
err.Error(http.StatusText(ctx.StatusCode), ctx.RealIP(), ctx.StatusCode, responseTimeString, ctx.URI())
}
// Notify us about long requests // Notify us about long requests
if responseTime >= 100*time.Millisecond { if responseTime >= 200*time.Millisecond {
err.Error("Unusually long response time", ctx.RealIP(), ctx.StatusCode, responseTimeString, ctx.URI()) err.Error("Long response time", ctx.RealIP(), ctx.StatusCode, responseTimeString, ctx.URI())
} }
}) })
} }

12
mixins/ForumTags.pixy Normal file
View File

@ -0,0 +1,12 @@
component ForumTags
.forum-tags.light-button-group
ForumTag("All", "")
ForumTag("General", "/general")
ForumTag("News", "/news")
ForumTag("Anime", "/anime")
ForumTag("Updates", "/update")
ForumTag("Suggestions", "/suggestion")
ForumTag("Bugs", "/bug")
component ForumTag(title string, suffix string)
a.light-button.forum-tag.ajax(href="/forum" + suffix)= title

View File

@ -1,2 +1,7 @@
.forum-tag
&.active
color white
background-color text-color
#load-more-threads #load-more-threads
margin-top 1rem margin-top 1rem

View File

@ -1,20 +1,3 @@
component Forums component Forums
h2.forum-header Forum h2.forum-header Forum
ForumTags ForumTags
component ForumTags
.forum-tags.light-button-group
ForumCategory("All", "")
ForumCategory("General", "/general")
ForumCategory("News", "/news")
ForumCategory("Anime", "/anime")
ForumCategory("Updates", "/update")
ForumCategory("Suggestions", "/suggestion")
ForumCategory("Bugs", "/bug")
component ForumCategory(title string, suffix string)
a.light-button.ajax(href="/forum" + suffix)= title
//- a.grid-cell.ajax(href="/forum/" + category)
//- .grid-text
//- GridIcon(arn.GetForumIcon(category))
//- span= title

View File

@ -1,6 +1,6 @@
component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, threads []*arn.Thread) component Profile(viewUser *arn.User, user *arn.User, animeList *arn.AnimeList, threads []*arn.Thread)
.profile .profile
img.profile-cover(src=viewUser.CoverImageURL()) img.profile-cover(src=viewUser.CoverImageURL(), alt="Cover image")
.image-container .image-container
ProfileImage(viewUser) ProfileImage(viewUser)