implement discovery of micropub config and auth

This commit is contained in:
James Ravenscroft 2022-02-06 12:06:19 +00:00
parent b9498c66f7
commit 476a88ea2a
10 changed files with 201 additions and 25 deletions

View File

@ -21,6 +21,9 @@ func Init(env string) {
config.SetDefault("indieauth.oauthCookieName","indiescrobble-oauth")
config.SetDefault("indieauth.sessionSubject", "IndieScrobble Session")
config.SetDefault("server.database.driver", "sqlite")
config.SetDefault("server.database.dsn", "indiescrobble.db")
config.SetConfigType("yaml")
config.SetConfigName(env)
config.AddConfigPath("../config/")
@ -28,6 +31,10 @@ func Init(env string) {
err = config.ReadInConfig()
if err != nil {
log.Fatal("error on parsing configuration file")
}
if config.GetString("jwt.signKey") == ""{
log.Fatal("You must set a JWT sign key (jwt.signKey in config yaml)")
}
@ -35,9 +42,7 @@ func Init(env string) {
config.BindEnv("server.port","PORT")
if err != nil {
log.Fatal("error on parsing configuration file")
}
}
func relativePath(basedir string, path *string) {

View File

@ -1,6 +1,5 @@
server:
port: ":8081"
port: "8081"
static_path: ./static
jwt:

View File

@ -10,6 +10,7 @@ import (
"time"
"git.jamesravey.me/ravenscroftj/indiescrobble/config"
"git.jamesravey.me/ravenscroftj/indiescrobble/models"
"github.com/gin-gonic/gin"
"github.com/go-chi/jwtauth/v5"
"github.com/hacdias/indieauth"
@ -34,32 +35,36 @@ func NewIndieAuthManager() *IndieAuthManager{
return iam
}
func (iam *IndieAuthManager) GetCurrentUser(c *gin.Context) string {
func (iam *IndieAuthManager) GetCurrentUser(c *gin.Context) *models.BaseUser {
jwt, err := c.Cookie("jwt")
if err != nil {
return ""
return nil
}else{
tok, err := iam.jwtAuth.Decode(jwt)
if err != nil{
log.Printf("Failed to decode jwt: %v", err)
return ""
return nil
}
val, present := tok.Get("user")
me, present := tok.Get("user")
if !present{
return nil
}
indietok, present := tok.Get("token")
fmt.Printf("indie token current user: %v", indietok)
if present {
return fmt.Sprintf("%v", val)
}else{
return ""
if !present{
return nil
}
user := models.BaseUser{Me: me.(string), Token: indietok.(string)}
return &user
}
}
@ -176,6 +181,7 @@ func (iam *IndieAuthManager) Logout(c *gin.Context) {
http.SetCookie(c.Writer, cookie)
// redirect back to index
c.Redirect(http.StatusSeeOther, "/")
}

View File

@ -3,7 +3,9 @@ package controllers
import (
"net/http"
"git.jamesravey.me/ravenscroftj/indiescrobble/models"
"git.jamesravey.me/ravenscroftj/indiescrobble/scrobble"
"git.jamesravey.me/ravenscroftj/indiescrobble/services/micropub"
"github.com/gin-gonic/gin"
)
@ -12,6 +14,9 @@ func Scrobble(c *gin.Context){
err := c.Request.ParseForm()
// this is an authed endpoint so 'user' must be set and if not panicking is fair
currentUser := c.MustGet("user").(*models.BaseUser)
if err != nil{
c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{
"message": err,
@ -51,8 +56,9 @@ func Scrobble(c *gin.Context){
}
}
c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{
"user": c.GetString("user"),
"user": currentUser,
"scrobbleType": scrobbleType,
"scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType],
"scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType],
@ -62,3 +68,47 @@ func Scrobble(c *gin.Context){
})
}
func PreviewScrobble(c *gin.Context){
err := c.Request.ParseForm()
// this is an authed endpoint so 'user' must be set and if not panicking is fair
currentUser := c.MustGet("user").(*models.BaseUser)
if err != nil{
c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{
"message": err,
})
}
scrobbleType := c.Request.Form.Get("type")
searchEngine := scrobble.NewSearchProvider(scrobbleType)
itemID := c.Request.Form.Get("item")
item, err := searchEngine.SearchProvider.GetItem(itemID)
if err != nil{
c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{
"message": err,
})
return
}
discovery := micropub.MicropubDiscoveryService{}
discovery.Discover(currentUser.Me, currentUser.Token )
c.HTML(http.StatusOK, "preview.tmpl", gin.H{
"user": currentUser,
"scrobbleType": scrobbleType,
"scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType],
"item": item,
"when": c.Request.Form.Get("when"),
"rating": c.Request.Form.Get("rating"),
"content": c.Request.Form.Get("content"),
})
}

9
go.mod
View File

@ -4,7 +4,9 @@ go 1.17
require (
github.com/0xAX/notificator v0.0.0-20210731104411-c42e3d4a43ee // indirect
github.com/PuerkitoBio/goquery v1.8.0 // indirect
github.com/StalkR/imdb v1.0.7 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/codegangsta/envy v0.0.0-20141216192214-4b78388c8ce4 // indirect
github.com/codegangsta/gin v0.0.0-20211113050330-71f90109db02 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
@ -16,12 +18,15 @@ require (
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.10.0 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/goccy/go-json v0.9.4 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.0 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hacdias/indieauth v1.7.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
@ -33,6 +38,7 @@ require (
github.com/magiconair/properties v1.8.5 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/mattn/go-sqlite3 v1.14.11 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
@ -58,5 +64,8 @@ require (
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.66.3 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gorm.io/driver/mysql v1.2.3 // indirect
gorm.io/driver/sqlite v1.2.6 // indirect
gorm.io/gorm v1.22.5 // indirect
willnorris.com/go/webmention v0.0.0-20211028201829-b0044f1a24d0 // indirect
)

22
go.sum
View File

@ -40,9 +40,12 @@ github.com/0xAX/notificator v0.0.0-20210731104411-c42e3d4a43ee h1:LgokYDTCpaZBHt
github.com/0xAX/notificator v0.0.0-20210731104411-c42e3d4a43ee/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
github.com/StalkR/httpcache v1.0.0/go.mod h1:yvbaYwH6w1USHPqgspMSwumbLwWE+B7jIZgfLYkTw1M=
github.com/StalkR/imdb v1.0.7 h1:T9ra3IObhWoNB2I2CNT6EFe8sTQH56adKJdEQi1q0Ig=
github.com/StalkR/imdb v1.0.7/go.mod h1:nxQmP4/nGtTVICl2+UmwhCnosVwVClmksdyptjE5Lj8=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -92,6 +95,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/goccy/go-json v0.7.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI=
github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
@ -166,6 +171,12 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
@ -203,6 +214,9 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ=
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -579,6 +593,14 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.2.3 h1:cZqzlOfg5Kf1VIdLC1D9hT6Cy9BgxhExLj/2tIgUe7Y=
gorm.io/driver/mysql v1.2.3/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo=
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk=
gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU=
gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -37,6 +37,7 @@ func NewRouter() *gin.Engine {
// add scrobble endpoints
authed.GET("/scrobble", controllers.Scrobble)
authed.POST("/scrobble/preview", controllers.PreviewScrobble)

View File

@ -2,12 +2,37 @@ package server
import (
"fmt"
"log"
"git.jamesravey.me/ravenscroftj/indiescrobble/config"
"git.jamesravey.me/ravenscroftj/indiescrobble/models"
"gorm.io/driver/mysql"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func Init() {
config := config.GetConfig()
var dialect gorm.Dialector
if config.GetString("server.database.driver") == "sqlite" {
dialect = sqlite.Open(config.GetString("server.database.dsn"))
}else{
dialect = mysql.Open(config.GetString("server.database.dsn"))
}
db, err := gorm.Open(dialect, &gorm.Config{})
if err != nil{
log.Fatalf("%v\n", err)
}
db.AutoMigrate(&models.User{})
r := NewRouter()
r.LoadHTMLGlob("templates/*.tmpl")
r.Run( fmt.Sprintf("%v:%v", config.GetString("server.host"), config.GetString("server.port")))

54
templates/preview.tmpl Normal file
View File

@ -0,0 +1,54 @@
{{ define "preview.tmpl" }}
<!DOCTYPE html>
<html lang="en">
{{ template "head.tmpl" . }}
<body>
{{ template "header.tmpl" . }}
<main>
{{ $scrobbleType := .scrobbleType }}
{{ if .user }}
Logged in as {{.user}} <a href="/logout"><button>Log Out</button></a>
{{end}}
<form method="POST" action="/scrobble/preview">
<p><a href="/">Add A Post</a> &gt; <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> &gt; {{.item.GetDisplayName}}</p>
<h3>Preview Post: {{.item.GetDisplayName}}</h3>
<div class="float-left">
{{if .item.GetThumbnailURL}}
<img class="thumbnail" src="{{.item.GetThumbnailURL}}"/>
{{end}}
</div>
<div>
<label>When: <b>{{.when}}</b></label> <input type="hidden" name="when" value="{{.when}}" /><br/>
<label>Rating: (out of 5)</label> <b>{{.rating}}</b> <input type="hidden" name="rating" value="{{.rating}}"/> <br/>
<label>Note/Content: </label> <br>
<pre>{{.content}}</pre>
<input type="hidden" name="content" value="{{.content}}"/>
<br/>
<button type="submit">Submit Post &gt; &gt;</button>
</div>
</form>
</main>
</body>
</html>
{{end}}

View File

@ -8,14 +8,12 @@
{{ $scrobbleType := .scrobbleType }}
{{ if .user }}
Logged in as {{.user}} <a href="/logout"><button>Log Out</button></a>
{{ if .user.Me }}
Logged in as {{.user.Me}} <a href="/logout"><button>Log Out</button></a>
{{end}}
<form method="GET" action="/scrobble">
{{if .searchResults}}
<p><a href="/">Add A Post</a> &gt; <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> &gt; {{.searchEngine}} Results</p>
@ -34,6 +32,8 @@
{{ else if .item}}
<form method="POST" action="/scrobble/preview">
<p><a href="/">Add A Post</a> &gt; <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> &gt; {{.item.GetDisplayName}}</p>
<h3>{{.item.GetDisplayName}}</h3>
@ -49,9 +49,9 @@
<div>
<label>When: </label> <input type="datetime-local" name='datetime'/><br/>
<label>When: </label> <input type="datetime-local" name='when'/><br/>
<label>Rating: (out of 5)</label> <input type="number" name='datetime'/><br/>
<label>Rating: (out of 5)</label> <input type="number" name='rating'/><br/>
<label>Note/Content: </label> <br>
<textarea rows="6" name='content'></textarea>
@ -60,11 +60,14 @@
<button type="submit">Preview &gt; &gt;</button>
</div>
<input type="hidden" name="item" value="{{.item.GetID}}"/>
<input type="hidden" name="type" value="{{.scrobbleType}}"/>
</form>
{{ else }}
<form method="GET" action="/scrobble">
<h2><a href="/">Add A Post</a> Add {{ .scrobbleTypeName }}</h2>
<p>Search <b>{{.searchEngine}}</b> for items to scrobble<p>
@ -73,11 +76,13 @@
<button type="submit">Next &gt;&gt;</button>
{{end}}
<input type="hidden" name="type" value="{{.scrobbleType}}"/>
</form>
{{end}}
</main>
</body>
</html>