authorization: only public entries without login #21

Merged
cws merged 1 commits from 6_public_tag into master 2020-03-18 18:08:22 +00:00
5 changed files with 85 additions and 23 deletions
Showing only changes of commit 7f077cfe31 - Show all commits

View File

@ -6,9 +6,10 @@ import (
"strings" "strings"
"time" "time"
"code.chrissexton.org/cws/cabinet/db"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"code.chrissexton.org/cws/cabinet/db"
) )
type Entry struct { type Entry struct {
@ -94,27 +95,49 @@ func GetByID(db *db.Database, id int64) (Entry, error) {
return e, e.populateTags() return e, e.populateTags()
} }
func Search(db *db.Database, query string) ([]*Entry, error) { func SearchByTag(db *db.Database, query string, tags []string) ([]*Entry, error) {
entries := []*Entry{} entries := []*Entry{}
log.Debug().Str("query", query).Msg("searching") query = fmt.Sprintf("%%%s%%", query)
if query != "" { log.Debug().Str("tag query", query).Int("len(tags)", len(tags)).Msg("searching")
q := `select * from entries where content like ? order by updated desc`
err := db.Select(&entries, q, "%"+query+"%") if len(tags) > 0 {
q := `select e.*
from entries e
inner join tags t
on e.id=t.entry_id
where
t.name in (?)
AND content like ?
order by updated desc`
q, args, err := sqlx.In(q, tags, query)
if err != nil {
return nil, err
}
err = db.Select(&entries, q, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
q := `select * from entries order by updated desc` q := `select e.*
err := db.Select(&entries, q) from entries e
where
content like ?
order by updated desc`
err := db.Select(&entries, q, query)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
for _, e := range entries { for _, e := range entries {
e.db = db e.db = db
e.Title = e.GenerateTitle() e.Title = e.GenerateTitle()
e.populateTags() e.populateTags()
} }
return entries, nil return entries, nil
} }
@ -277,3 +300,12 @@ func (e *Entry) Create() error {
tx.Commit() tx.Commit()
return nil return nil
} }
func (e *Entry) HasTag(tag string) bool {
for _, t := range e.Tags {
if strings.ToLower(tag) == strings.ToLower(t) {
return true
}
}
return false
}

View File

@ -33,6 +33,15 @@
components: { components: {
Error Error
}, },
created() {
if (!this.$store.state.key) {
let key = this.$cookies.get('key')
if (key) {
this.$store.commit('setKey', key)
return
}
}
},
methods: { methods: {
newFile: function() { newFile: function() {
this.$store.dispatch('newFile') this.$store.dispatch('newFile')

View File

@ -80,11 +80,6 @@ export default {
// because it has not been created yet when this guard is called! // because it has not been created yet when this guard is called!
next(vm => { next(vm => {
if (!vm.$store.state.key) { if (!vm.$store.state.key) {
let key = vm.$cookies.get('key')
if (key) {
vm.$store.commit('setKey', key)
return
}
vm.$router.push({name: "login", params: {returnTo: vm.$route.path}}) vm.$router.push({name: "login", params: {returnTo: vm.$route.path}})
} }
}) })

View File

@ -111,12 +111,17 @@ func (web *Web) newEntry(w http.ResponseWriter, r *http.Request) {
func (web *Web) allEntries(w http.ResponseWriter, r *http.Request) { func (web *Web) allEntries(w http.ResponseWriter, r *http.Request) {
query := "" query := ""
tags := []string{}
if !web.AuthCheck(r) {
tags = append(tags, "public")
}
items, ok := r.URL.Query()["query"] items, ok := r.URL.Query()["query"]
if ok { if ok {
query = items[0] query = items[0]
} }
entries, err := entry.Search(web.db, query) entries, err := entry.SearchByTag(web.db, query, tags)
if err != nil { if err != nil {
log.Error().Msgf("Error querying: %w", err)
w.WriteHeader(500) w.WriteHeader(500)
fmt.Fprint(w, err) fmt.Fprint(w, err)
return return
@ -143,6 +148,12 @@ func (web *Web) getEntry(w http.ResponseWriter, r *http.Request) {
return return
} }
if !web.AuthCheck(r) && !entry.HasTag("public") {
w.WriteHeader(401)
fmt.Fprint(w, "not allowed")
return
}
resp, err := json.Marshal(entry) resp, err := json.Marshal(entry)
if err != nil { if err != nil {
w.WriteHeader(500) w.WriteHeader(500)

View File

@ -38,27 +38,42 @@ func New(addr string, db *db.Database, static http.FileSystem) *Web {
} }
type AuthMiddleware struct { type AuthMiddleware struct {
web *Web
db *db.Database db *db.Database
} }
func NewAuthMiddleware(web *Web) AuthMiddleware {
return AuthMiddleware{
web: web,
db: web.db,
}
}
func (aw *AuthMiddleware) Middleware(next http.Handler) http.Handler { func (aw *AuthMiddleware) Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := r.Header.Get("X-Auth-Key") if aw.web.AuthCheck(r) {
u, err := auth.GetByKey(aw.db, key) next.ServeHTTP(w, r)
if key == "" || err != nil {
w.WriteHeader(401)
fmt.Fprint(w, "invalid login")
return return
} }
log.Debug().Msgf("This shit is authed to user %s!", u.Name) w.WriteHeader(401)
next.ServeHTTP(w, r) fmt.Fprint(w, "invalid login")
}) })
} }
func (web *Web) AuthCheck(r *http.Request) bool {
key := r.Header.Get("X-Auth-Key")
u, err := auth.GetByKey(web.db, key)
if key == "" || err != nil {
return false
}
log.Debug().Msgf("This shit is authed to user %s!", u.Name)
return true
}
func (web *Web) routeSetup() http.Handler { func (web *Web) routeSetup() http.Handler {
r := mux.NewRouter() r := mux.NewRouter()
api := r.PathPrefix("/v1/").Subrouter() api := r.PathPrefix("/v1/").Subrouter()
auth := AuthMiddleware{web.db} auth := NewAuthMiddleware(web)
authedApi := r.PathPrefix("/v1/").Subrouter() authedApi := r.PathPrefix("/v1/").Subrouter()
authedApi.Use(auth.Middleware) authedApi.Use(auth.Middleware)