Compare commits
No commits in common. "b9842ddd5e5a8e3fcbd1803d71d02f62cf5b1df1" and "8b6ae897a5cd3e5d36a60234022ec48fa4d54c18" have entirely different histories.
b9842ddd5e
...
8b6ae897a5
@ -17,7 +17,3 @@ func (app *application) home(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (app *application) notImplemented(w http.ResponseWriter, r *http.Request) {
|
func (app *application) notImplemented(w http.ResponseWriter, r *http.Request) {
|
||||||
views.ComingSoon("Coming Soon", app.newCommonData(r)).Render(r.Context(), w)
|
views.ComingSoon("Coming Soon", app.newCommonData(r)).Render(r.Context(), w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ping(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Write([]byte("OK"))
|
|
||||||
}
|
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.32bit.cafe/32bitcafe/guestbook/internal/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPing(t *testing.T) {
|
|
||||||
app := newTestApplication(t)
|
|
||||||
ts := newTestServer(t, app.routes())
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
code, _, body := ts.get(t, "/ping")
|
|
||||||
|
|
||||||
assert.Equal(t, code, http.StatusOK)
|
|
||||||
assert.Equal(t, body, "OK")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetGuestbookView(t *testing.T) {
|
|
||||||
app := newTestApplication(t)
|
|
||||||
ts := newTestServer(t, app.routes())
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
urlPath string
|
|
||||||
wantCode int
|
|
||||||
wantBody string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Valid id",
|
|
||||||
urlPath: fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(1)),
|
|
||||||
wantCode: http.StatusOK,
|
|
||||||
wantBody: "Guestbook for Example",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Non-existent ID",
|
|
||||||
urlPath: fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(2)),
|
|
||||||
wantCode: http.StatusNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "String ID",
|
|
||||||
urlPath: "/websites/abcd/guestbook",
|
|
||||||
wantCode: http.StatusNotFound,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
code, _, body := ts.get(t, tt.urlPath)
|
|
||||||
assert.Equal(t, code, tt.wantCode)
|
|
||||||
if tt.wantBody != "" {
|
|
||||||
assert.StringContains(t, body, tt.wantBody)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.32bit.cafe/32bitcafe/guestbook/internal/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUserSignup(t *testing.T) {
|
|
||||||
app := newTestApplication(t)
|
|
||||||
ts := newTestServer(t, app.routes())
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
_, _, body := ts.get(t, "/users/register")
|
|
||||||
validCSRFToken := extractCSRFToken(t, body)
|
|
||||||
|
|
||||||
const (
|
|
||||||
validName = "John"
|
|
||||||
validPassword = "validPassword"
|
|
||||||
validEmail = "john@example.com"
|
|
||||||
formTag = `<form action="/users/register" method="post">`
|
|
||||||
)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
userName string
|
|
||||||
userEmail string
|
|
||||||
userPassword string
|
|
||||||
csrfToken string
|
|
||||||
wantCode int
|
|
||||||
wantFormTag string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Valid submission",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: validEmail,
|
|
||||||
userPassword: validPassword,
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusSeeOther,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Missing token",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: validEmail,
|
|
||||||
userPassword: validPassword,
|
|
||||||
wantCode: http.StatusBadRequest,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Empty name",
|
|
||||||
userName: "",
|
|
||||||
userEmail: validEmail,
|
|
||||||
userPassword: validPassword,
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusUnprocessableEntity,
|
|
||||||
wantFormTag: formTag,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Empty email",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: "",
|
|
||||||
userPassword: validPassword,
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusUnprocessableEntity,
|
|
||||||
wantFormTag: formTag,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Empty password",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: validEmail,
|
|
||||||
userPassword: "",
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusUnprocessableEntity,
|
|
||||||
wantFormTag: formTag,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Invalid email",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: "asdfasdf",
|
|
||||||
userPassword: validPassword,
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusUnprocessableEntity,
|
|
||||||
wantFormTag: formTag,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Invalid password",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: validEmail,
|
|
||||||
userPassword: "asdfasd",
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusUnprocessableEntity,
|
|
||||||
wantFormTag: formTag,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Duplicate email",
|
|
||||||
userName: validName,
|
|
||||||
userEmail: "dupe@example.com",
|
|
||||||
userPassword: validPassword,
|
|
||||||
csrfToken: validCSRFToken,
|
|
||||||
wantCode: http.StatusUnprocessableEntity,
|
|
||||||
wantFormTag: formTag,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(*testing.T) {
|
|
||||||
form := url.Values{}
|
|
||||||
form.Add("username", tt.userName)
|
|
||||||
form.Add("email", tt.userEmail)
|
|
||||||
form.Add("password", tt.userPassword)
|
|
||||||
form.Add("csrf_token", tt.csrfToken)
|
|
||||||
code, _, body := ts.postForm(t, "/users/register", form)
|
|
||||||
assert.Equal(t, code, tt.wantCode)
|
|
||||||
if tt.wantFormTag != "" {
|
|
||||||
assert.StringContains(t, body, tt.wantFormTag)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -21,9 +21,9 @@ import (
|
|||||||
type application struct {
|
type application struct {
|
||||||
sequence uint16
|
sequence uint16
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
websites models.WebsiteModelInterface
|
websites *models.WebsiteModel
|
||||||
users models.UserModelInterface
|
users *models.UserModel
|
||||||
guestbookComments models.GuestbookCommentModelInterface
|
guestbookComments *models.GuestbookCommentModel
|
||||||
sessionManager *scs.SessionManager
|
sessionManager *scs.SessionManager
|
||||||
formDecoder *schema.Decoder
|
formDecoder *schema.Decoder
|
||||||
debug bool
|
debug bool
|
||||||
|
@ -11,8 +11,6 @@ func (app *application) routes() http.Handler {
|
|||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.Handle("GET /static/", http.FileServerFS(ui.Files))
|
mux.Handle("GET /static/", http.FileServerFS(ui.Files))
|
||||||
|
|
||||||
mux.HandleFunc("GET /ping", ping)
|
|
||||||
|
|
||||||
dynamic := alice.New(app.sessionManager.LoadAndSave, noSurf, app.authenticate)
|
dynamic := alice.New(app.sessionManager.LoadAndSave, noSurf, app.authenticate)
|
||||||
standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders)
|
standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders)
|
||||||
|
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"html"
|
|
||||||
"io"
|
|
||||||
"log/slog"
|
|
||||||
"net/http"
|
|
||||||
"net/http/cookiejar"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"regexp"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.32bit.cafe/32bitcafe/guestbook/internal/models/mocks"
|
|
||||||
"github.com/alexedwards/scs/v2"
|
|
||||||
"github.com/gorilla/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newTestApplication(t *testing.T) *application {
|
|
||||||
formDecoder := schema.NewDecoder()
|
|
||||||
formDecoder.IgnoreUnknownKeys(true)
|
|
||||||
|
|
||||||
sessionManager := scs.New()
|
|
||||||
sessionManager.Lifetime = 12 * time.Hour
|
|
||||||
sessionManager.Cookie.Secure = true
|
|
||||||
|
|
||||||
return &application{
|
|
||||||
logger: slog.New(slog.NewTextHandler(io.Discard, nil)),
|
|
||||||
sessionManager: sessionManager,
|
|
||||||
websites: &mocks.WebsiteModel{},
|
|
||||||
users: &mocks.UserModel{},
|
|
||||||
guestbookComments: &mocks.GuestbookCommentModel{},
|
|
||||||
formDecoder: formDecoder,
|
|
||||||
timezones: getAvailableTimezones(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type testServer struct {
|
|
||||||
*httptest.Server
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTestServer(t *testing.T, h http.Handler) *testServer {
|
|
||||||
ts := httptest.NewTLSServer(h)
|
|
||||||
jar, err := cookiejar.New(nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
ts.Client().Jar = jar
|
|
||||||
ts.Client().CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
||||||
return http.ErrUseLastResponse
|
|
||||||
}
|
|
||||||
return &testServer{ts}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ts *testServer) get(t *testing.T, urlPath string) (int, http.Header, string) {
|
|
||||||
rs, err := ts.Client().Get(ts.URL + urlPath)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer rs.Body.Close()
|
|
||||||
body, err := io.ReadAll(rs.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
body = bytes.TrimSpace(body)
|
|
||||||
|
|
||||||
return rs.StatusCode, rs.Header, string(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ts *testServer) postForm(t *testing.T, urlPath string, form url.Values) (int, http.Header, string) {
|
|
||||||
rs, err := ts.Client().PostForm(ts.URL+urlPath, form)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer rs.Body.Close()
|
|
||||||
body, err := io.ReadAll(rs.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
body = bytes.TrimSpace(body)
|
|
||||||
return rs.StatusCode, rs.Header, string(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
var csrfTokenRX = regexp.MustCompile(`<input type="hidden" name="csrf_token" value="(.+?)">`)
|
|
||||||
|
|
||||||
func extractCSRFToken(t *testing.T, body string) string {
|
|
||||||
matches := csrfTokenRX.FindStringSubmatch(body)
|
|
||||||
if len(matches) < 2 {
|
|
||||||
t.Fatal("no csrf token found in body")
|
|
||||||
}
|
|
||||||
return html.UnescapeString(matches[1])
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package assert
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Equal[T comparable](t *testing.T, actual, expected T) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if actual != expected {
|
|
||||||
t.Errorf("got: %v; want %v", actual, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringContains(t *testing.T, actual, expectedSubstring string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if !strings.Contains(actual, expectedSubstring) {
|
|
||||||
t.Errorf("got: %q; expected to contain: %q", actual, expectedSubstring)
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,15 +24,6 @@ type GuestbookCommentModel struct {
|
|||||||
DB *sql.DB
|
DB *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type GuestbookCommentModelInterface interface {
|
|
||||||
Insert(shortId uint64, guestbookId, parentId int64, authorName, authorEmail, authorSite, commentText, pageUrl string, isPublished bool) (int64, error)
|
|
||||||
Get(shortId uint64) (GuestbookComment, error)
|
|
||||||
GetAll(guestbookId int64) ([]GuestbookComment, error)
|
|
||||||
GetDeleted(guestbookId int64) ([]GuestbookComment, error)
|
|
||||||
GetUnpublished(guestbookId int64) ([]GuestbookComment, error)
|
|
||||||
UpdateComment(comment *GuestbookComment) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) Insert(shortId uint64, guestbookId, parentId int64, authorName,
|
func (m *GuestbookCommentModel) Insert(shortId uint64, guestbookId, parentId int64, authorName,
|
||||||
authorEmail, authorSite, commentText, pageUrl string, isPublished bool) (int64, error) {
|
authorEmail, authorSite, commentText, pageUrl string, isPublished bool) (int64, error) {
|
||||||
stmt := `INSERT INTO guestbook_comments (ShortId, GuestbookId, ParentId, AuthorName,
|
stmt := `INSERT INTO guestbook_comments (ShortId, GuestbookId, ParentId, AuthorName,
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
package mocks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.32bit.cafe/32bitcafe/guestbook/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
var mockGuestbookComment = models.GuestbookComment{
|
|
||||||
ID: 1,
|
|
||||||
ShortId: 1,
|
|
||||||
GuestbookId: 1,
|
|
||||||
AuthorName: "John Test",
|
|
||||||
AuthorEmail: "test@example.com",
|
|
||||||
AuthorSite: "example.com",
|
|
||||||
CommentText: "Hello, world",
|
|
||||||
Created: time.Now(),
|
|
||||||
IsPublished: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
type GuestbookCommentModel struct{}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) Insert(shortId uint64, guestbookId, parentId int64, authorName,
|
|
||||||
authorEmail, authorSite, commentText, pageUrl string, isPublished bool) (int64, error) {
|
|
||||||
return 2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) Get(shortId uint64) (models.GuestbookComment, error) {
|
|
||||||
switch shortId {
|
|
||||||
case 1:
|
|
||||||
return mockGuestbookComment, nil
|
|
||||||
default:
|
|
||||||
return models.GuestbookComment{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) GetAll(guestbookId int64) ([]models.GuestbookComment, error) {
|
|
||||||
switch guestbookId {
|
|
||||||
case 1:
|
|
||||||
return []models.GuestbookComment{mockGuestbookComment}, nil
|
|
||||||
case 2:
|
|
||||||
return []models.GuestbookComment{}, nil
|
|
||||||
default:
|
|
||||||
return []models.GuestbookComment{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) GetDeleted(guestbookId int64) ([]models.GuestbookComment, error) {
|
|
||||||
switch guestbookId {
|
|
||||||
default:
|
|
||||||
return []models.GuestbookComment{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) GetUnpublished(guestbookId int64) ([]models.GuestbookComment, error) {
|
|
||||||
switch guestbookId {
|
|
||||||
default:
|
|
||||||
return []models.GuestbookComment{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GuestbookCommentModel) UpdateComment(comment *models.GuestbookComment) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
package mocks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.32bit.cafe/32bitcafe/guestbook/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
var mockUser = models.User{
|
|
||||||
ID: 1,
|
|
||||||
ShortId: 1,
|
|
||||||
Username: "tester",
|
|
||||||
Email: "test@example.com",
|
|
||||||
Deleted: false,
|
|
||||||
IsBanned: false,
|
|
||||||
Created: time.Now(),
|
|
||||||
Settings: mockUserSettings,
|
|
||||||
}
|
|
||||||
|
|
||||||
var mockUserSettings = models.UserSettings{
|
|
||||||
LocalTimezone: time.UTC,
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserModel struct {
|
|
||||||
Settings map[string]models.Setting
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) InitializeSettingsMap() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Insert(shortId uint64, username string, email string, password string, settings models.UserSettings) error {
|
|
||||||
switch email {
|
|
||||||
case "dupe@example.com":
|
|
||||||
return models.ErrDuplicateEmail
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Get(shortId uint64) (models.User, error) {
|
|
||||||
switch shortId {
|
|
||||||
case 1:
|
|
||||||
return mockUser, nil
|
|
||||||
default:
|
|
||||||
return models.User{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) GetById(id int64) (models.User, error) {
|
|
||||||
switch id {
|
|
||||||
case 1:
|
|
||||||
return mockUser, nil
|
|
||||||
default:
|
|
||||||
return models.User{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) GetAll() ([]models.User, error) {
|
|
||||||
return []models.User{mockUser}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Authenticate(email, password string) (int64, error) {
|
|
||||||
if email == "test@example.com" && password == "password" {
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
return 0, models.ErrInvalidCredentials
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) Exists(id int64) (bool, error) {
|
|
||||||
switch id {
|
|
||||||
case 1:
|
|
||||||
return true, nil
|
|
||||||
default:
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) GetSettings(userId int64) (models.UserSettings, error) {
|
|
||||||
return mockUserSettings, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) UpdateUserSettings(userId int64, settings models.UserSettings) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) UpdateSetting(userId int64, setting models.Setting, value string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package mocks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.32bit.cafe/32bitcafe/guestbook/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
var mockGuestbook = models.Guestbook{
|
|
||||||
ID: 1,
|
|
||||||
ShortId: 1,
|
|
||||||
UserId: 1,
|
|
||||||
WebsiteId: 1,
|
|
||||||
Created: time.Now(),
|
|
||||||
IsActive: true,
|
|
||||||
Settings: models.GuestbookSettings{
|
|
||||||
IsCommentingEnabled: true,
|
|
||||||
IsVisible: true,
|
|
||||||
FilteredWords: make([]string, 0),
|
|
||||||
AllowRemoteHostAccess: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var mockWebsite = models.Website{
|
|
||||||
ID: 1,
|
|
||||||
ShortId: 1,
|
|
||||||
Name: "Example",
|
|
||||||
SiteUrl: "example.com",
|
|
||||||
AuthorName: "John Test",
|
|
||||||
UserId: 1,
|
|
||||||
Created: time.Now(),
|
|
||||||
Guestbook: mockGuestbook,
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebsiteModel struct{}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) Insert(shortId uint64, userId int64, siteName, siteUrl, authorName string) (int64, error) {
|
|
||||||
return 2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) Get(shortId uint64) (models.Website, error) {
|
|
||||||
switch shortId {
|
|
||||||
case 1:
|
|
||||||
return mockWebsite, nil
|
|
||||||
default:
|
|
||||||
return models.Website{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) GetAllUser(userId int64) ([]models.Website, error) {
|
|
||||||
return []models.Website{mockWebsite}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) GetById(id int64) (models.Website, error) {
|
|
||||||
switch id {
|
|
||||||
case 1:
|
|
||||||
return mockWebsite, nil
|
|
||||||
default:
|
|
||||||
return models.Website{}, models.ErrNoRecord
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) GetAll() ([]models.Website, error) {
|
|
||||||
return []models.Website{mockWebsite}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) InitializeSettingsMap() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) UpdateGuestbookSettings(guestbookId int64, settings models.GuestbookSettings) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) UpdateSetting(guestbookId int64, setting models.Setting, value string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -35,18 +35,6 @@ type UserModel struct {
|
|||||||
Settings map[string]Setting
|
Settings map[string]Setting
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserModelInterface interface {
|
|
||||||
InitializeSettingsMap() error
|
|
||||||
Insert(shortId uint64, username string, email string, password string, settings UserSettings) error
|
|
||||||
Get(shortId uint64) (User, error)
|
|
||||||
GetById(id int64) (User, error)
|
|
||||||
GetAll() ([]User, error)
|
|
||||||
Authenticate(email, password string) (int64, error)
|
|
||||||
Exists(id int64) (bool, error)
|
|
||||||
UpdateUserSettings(userId int64, settings UserSettings) error
|
|
||||||
UpdateSetting(userId int64, setting Setting, value string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *UserModel) InitializeSettingsMap() error {
|
func (m *UserModel) InitializeSettingsMap() error {
|
||||||
if m.Settings == nil {
|
if m.Settings == nil {
|
||||||
m.Settings = make(map[string]Setting)
|
m.Settings = make(map[string]Setting)
|
||||||
|
@ -90,16 +90,6 @@ func (m *WebsiteModel) InitializeSettingsMap() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteModelInterface interface {
|
|
||||||
Insert(shortId uint64, userId int64, siteName, siteUrl, authorName string) (int64, error)
|
|
||||||
Get(shortId uint64) (Website, error)
|
|
||||||
GetAllUser(userId int64) ([]Website, error)
|
|
||||||
GetAll() ([]Website, error)
|
|
||||||
InitializeSettingsMap() error
|
|
||||||
UpdateGuestbookSettings(guestbookId int64, settings GuestbookSettings) error
|
|
||||||
UpdateSetting(guestbookId int64, setting Setting, value string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *WebsiteModel) Insert(shortId uint64, userId int64, siteName, siteUrl, authorName string) (int64, error) {
|
func (m *WebsiteModel) Insert(shortId uint64, userId int64, siteName, siteUrl, authorName string) (int64, error) {
|
||||||
stmt := `INSERT INTO websites (ShortId, Name, SiteUrl, AuthorName, UserId, Created)
|
stmt := `INSERT INTO websites (ShortId, Name, SiteUrl, AuthorName, UserId, Created)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)`
|
VALUES (?, ?, ?, ?, ?, ?)`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user