now users can only view and delete their own posts
This commit is contained in:
parent
b108615af0
commit
92cf109746
21
comics.go
21
comics.go
|
@ -136,6 +136,8 @@ func (c *Comic) readRow(db * sql.Rows) error {
|
|||
}
|
||||
|
||||
func getComic(id int) (*Comic, error) {
|
||||
id -= 1
|
||||
|
||||
c := new(Comic)
|
||||
nferr := NoSuchComicErr.With(fmt.Sprintf("id \"%d\"", id))
|
||||
|
||||
|
@ -236,7 +238,7 @@ func comicView(w http.ResponseWriter, r * http.Request) {
|
|||
}
|
||||
|
||||
if len(comics) > 0 {
|
||||
c, err = getComic(i-1)
|
||||
c, err = getComic(i)
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
return404(w,r)
|
||||
|
@ -400,10 +402,19 @@ func return500(w http.ResponseWriter, r * http.Request) {
|
|||
returnError(w, r, http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
func newComic(title string, image string, description string, tags string) error {
|
||||
_, err := db.Exec("INSERT INTO comic(title, image, description, tags) VALUES(?, ?, ?, ?);",
|
||||
func newComic(title string, image string, description string, tags string) (int, error) {
|
||||
res, err := db.Exec("INSERT INTO comic(title, image, description, tags) VALUES(?, ?, ?, ?);",
|
||||
title, image, description, tags)
|
||||
return err
|
||||
if err != nil {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
id := int64(0)
|
||||
if id, err = res.LastInsertId(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int(id), err
|
||||
}
|
||||
|
||||
func deleteComic(id int) error {
|
||||
|
@ -437,7 +448,7 @@ func main() {
|
|||
if len(options.Title) < 1 {
|
||||
panic("missing -l")
|
||||
}
|
||||
err = newComic(options.Title, options.ImagePath, "", "")
|
||||
_, err = newComic(options.Title, options.ImagePath, "", "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
218
manager.go
218
manager.go
|
@ -20,9 +20,10 @@ import (
|
|||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var seededRand *rand.Rand = nil
|
||||
var secretKey string = ""
|
||||
var secretKeyHash string = ""
|
||||
var seededRand *rand.Rand = nil
|
||||
var secretKey string = ""
|
||||
var secretKeyHash string = ""
|
||||
var tokenSecondsDefault = 60 * 60 * 24 * 14
|
||||
|
||||
const userSquema string = `
|
||||
CREATE TABLE IF NOT EXISTS user (
|
||||
|
@ -38,6 +39,13 @@ CREATE TABLE IF NOT EXISTS token (
|
|||
username CHAR(20) NOT NULL
|
||||
);`
|
||||
|
||||
const isAuthorOfSquema string = `
|
||||
CREATE TABLE IF NOT EXISTS isauthorof (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
comicid INT NOT NULL,
|
||||
userid CHAR(20) NOT NULL
|
||||
);`
|
||||
|
||||
type User struct {
|
||||
ID string
|
||||
Name string
|
||||
|
@ -63,12 +71,107 @@ type TokenClaims struct {
|
|||
Username string
|
||||
}
|
||||
|
||||
type IsAuthorOf struct {
|
||||
ID int
|
||||
ComicID int
|
||||
UserID string
|
||||
}
|
||||
|
||||
type ViewHandler func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
func (u *User) byID(id string) error {
|
||||
rows, err := db.Query("SELECT * FROM user WHERE id = ?;", id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
return errors.New("no such entry found")
|
||||
}
|
||||
|
||||
return u.readRow(rows)
|
||||
}
|
||||
|
||||
func (a *IsAuthorOf) byComic(id int) error {
|
||||
rows, err := db.Query("SELECT * FROM isauthorof WHERE comicid = ?;", id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
return errors.New("no such entry found")
|
||||
}
|
||||
|
||||
return a.readRow(rows)
|
||||
}
|
||||
|
||||
func (c *Comic) getAuthor() (*User, error) {
|
||||
authorOf := &IsAuthorOf{}
|
||||
user := &User{}
|
||||
|
||||
err := authorOf.byComic(c.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = user.byID(authorOf.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (u *User) readRow(db * sql.Rows) error {
|
||||
return db.Scan(&u.ID, &u.Name, &u.Password)
|
||||
}
|
||||
|
||||
func getComicByID(id int) (*Comic, error) {
|
||||
comic := &Comic{}
|
||||
|
||||
rows, err := db.Query("SELECT * FROM comic WHERE id = ?;", id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
return nil, errors.New("no such comic found")
|
||||
}
|
||||
|
||||
err = comic.readRow(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return comic, nil
|
||||
}
|
||||
|
||||
func (u *User) getComics() ([]Comic, error) {
|
||||
authors, err := getAllIsAuthorOfs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
comics := []Comic{}
|
||||
for _, a := range authors {
|
||||
if a.UserID != u.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
c, err := getComicByID(a.ComicID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
comics = append(comics, *c)
|
||||
}
|
||||
|
||||
return comics, nil
|
||||
}
|
||||
|
||||
func (t *TokenClaims) readRow(db * sql.Rows) error {
|
||||
var e int64
|
||||
err := db.Scan(&t.ID, &e, &t.Username)
|
||||
|
@ -76,6 +179,10 @@ func (t *TokenClaims) readRow(db * sql.Rows) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (a *IsAuthorOf) readRow(db *sql.Rows) error {
|
||||
return db.Scan(&a.ID, &a.ComicID, &a.UserID)
|
||||
}
|
||||
|
||||
func generateToken(username string, seconds time.Duration) (string, *TokenClaims, error) {
|
||||
claims := TokenClaims{
|
||||
ID: randomString(20),
|
||||
|
@ -221,6 +328,53 @@ func getAllUsers() ([]User, error) {
|
|||
return users, nil
|
||||
}
|
||||
|
||||
func getAllIsAuthorOfs() ([]IsAuthorOf, error) {
|
||||
rows, err := db.Query("SELECT * FROM isauthorof ORDER BY id ASC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
authors := []IsAuthorOf{}
|
||||
for rows.Next() {
|
||||
i := IsAuthorOf{}
|
||||
err := i.readRow(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authors = append(authors, i)
|
||||
}
|
||||
|
||||
return authors, nil
|
||||
}
|
||||
|
||||
func addIsAuthorOf(userID string, comicID int) error {
|
||||
authors, err := getAllIsAuthorOfs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range authors {
|
||||
if a.ComicID == comicID && a.UserID == userID {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
_, err = db.Exec("INSERT INTO isauthorof(comicid, userid) VALUES(?, ?);",
|
||||
comicID, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
func removeComicFromIsAuthorOf(id int) error {
|
||||
_, err := db.Exec("DELETE FROM isauthorof WHERE comicid = ?;", id)
|
||||
return err
|
||||
}
|
||||
|
||||
func removeUserFromIsAuthorOf(id string) error {
|
||||
_, err := db.Exec("DELETE FROM isauthorof WHERE userid = ?;", id)
|
||||
return err
|
||||
}
|
||||
|
||||
func randomString(length int) string {
|
||||
charset := "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789"
|
||||
b := make([]byte, length)
|
||||
|
@ -296,7 +450,6 @@ func athenticateUserByPassword(username string, password string) (*User, error)
|
|||
return nil, errors.New("No such user \"" + username + "\" found")
|
||||
}
|
||||
|
||||
log.Println(user.ID)
|
||||
password = saltPassword(password, user.ID)
|
||||
if err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
return nil, err
|
||||
|
@ -335,12 +488,12 @@ func managerIndexView(w http.ResponseWriter, r * http.Request) {
|
|||
User: *user,
|
||||
}
|
||||
|
||||
comics, err := allComics()
|
||||
comics, err := user.getComics()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i, comic := range comics {
|
||||
for _, comic := range comics {
|
||||
context.Comics = append(context.Comics, struct {
|
||||
No int
|
||||
Title string
|
||||
|
@ -348,7 +501,7 @@ func managerIndexView(w http.ResponseWriter, r * http.Request) {
|
|||
Image string
|
||||
}{
|
||||
Title: comic.Title,
|
||||
No: i+1,
|
||||
No: comic.ID,
|
||||
Date: comic.DateTime,
|
||||
Image: comic.Image,
|
||||
})
|
||||
|
@ -364,18 +517,39 @@ func managerRemoveView(w http.ResponseWriter, r * http.Request) {
|
|||
path := strings.TrimRight(tmp, "/confirmed")
|
||||
isConfirmed := strings.TrimPrefix(strings.TrimPrefix(tmp, path), "/") == "confirmed"
|
||||
|
||||
user, _, err := getSessionUser(r)
|
||||
if err != nil {
|
||||
log.Println("failed to get session user: " + err.Error())
|
||||
return401(w, r)
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
i, err := strconv.Atoi(path)
|
||||
if err != nil {
|
||||
return404(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
comic, err := getComic(i-1)
|
||||
comic, err := getComicByID(i)
|
||||
if err != nil {
|
||||
return404(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
authorOf := &IsAuthorOf{}
|
||||
err = authorOf.byComic(i)
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
return500(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if authorOf.UserID != user.ID {
|
||||
return401(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if !isConfirmed {
|
||||
err = executeTemplate(w, "confirm", ConfirmContext{
|
||||
Action: fmt.Sprintf("Remove %s", comic.Title),
|
||||
|
@ -396,6 +570,11 @@ func managerRemoveView(w http.ResponseWriter, r * http.Request) {
|
|||
return500(w, r)
|
||||
return
|
||||
}
|
||||
err = removeComicFromIsAuthorOf(comic.ID)
|
||||
if err != nil {
|
||||
return500(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
@ -419,6 +598,14 @@ func managerPublishView(w http.ResponseWriter, r * http.Request) {
|
|||
}
|
||||
} ()
|
||||
|
||||
user, _, err := getSessionUser(r)
|
||||
if err != nil {
|
||||
log.Println("failed to get session user: " + err.Error())
|
||||
return401(w, r)
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
r.ParseMultipartForm(options.UploadSize * (1 << 20))
|
||||
file, handler, err := r.FormFile("image")
|
||||
if err != nil {
|
||||
|
@ -440,7 +627,13 @@ func managerPublishView(w http.ResponseWriter, r * http.Request) {
|
|||
defer f.Close()
|
||||
io.Copy(f, file)
|
||||
|
||||
err = newComic(title, filename, "", "")
|
||||
comicID, err := newComic(title, filename, "", "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Println(user.ID)
|
||||
err = addIsAuthorOf(user.ID, comicID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -478,7 +671,7 @@ func managerLoginView(w http.ResponseWriter, r * http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
token, claims, err := generateToken(user.Name, 60)
|
||||
token, claims, err := generateToken(user.Name, time.Duration(tokenSecondsDefault))
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("failed to generate token for \"%s\": %s", user.Name, err.Error()))
|
||||
return500(w, r)
|
||||
|
@ -536,6 +729,11 @@ func startManager(address string, port int, dbPath string, mediaPath string) err
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = db.Exec(isAuthorOfSquema)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = os.Stat(options.SecretPath)
|
||||
if os.IsNotExist(err) {
|
||||
secretKey = randomString(100)
|
||||
|
|
Loading…
Reference in New Issue