Improved auth and logging
This commit is contained in:
parent
a6a3609ab7
commit
c858a58123
30
auth.go
Normal file
30
auth.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
21
google.go
21
google.go
@ -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("/")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
23
logger.go
23
logger.go
@ -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
12
mixins/ForumTags.pixy
Normal 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
|
@ -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
|
@ -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
|
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user