Completed template system, added login/logout
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@
|
||||
},
|
||||
|
||||
"wiki": {
|
||||
"url": "https://wiki.aiterp.net",
|
||||
"url": "https://wiki.aiterp.net/w/api.php",
|
||||
"username": "AiteBot@AiteStory",
|
||||
"password": ""
|
||||
},
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/gisle/wrouter/response"
|
||||
|
||||
"git.aiterp.net/AiteRP/aitestory/model"
|
||||
"git.aiterp.net/AiteRP/aitestory/view"
|
||||
"git.aiterp.net/AiteRP/aitestory/viewmodel"
|
||||
|
||||
@@ -15,18 +19,71 @@ import (
|
||||
var ListController = wrouter.Router{}
|
||||
|
||||
func listIndex(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
|
||||
if req.Method != "GET" || strings.LastIndex(req.URL.Path, "/") >= len(path) {
|
||||
var err error
|
||||
if req.Method != "GET" || len(req.URL.Path) > len(path) {
|
||||
return false
|
||||
}
|
||||
|
||||
vm := viewmodel.PageList{}
|
||||
vm.Headers, err = model.ListHeaders()
|
||||
vm.Categories = model.PageCategories
|
||||
vm.Setup(user)
|
||||
|
||||
if err != nil {
|
||||
response.Text(w, 500, err.Error())
|
||||
return true
|
||||
}
|
||||
|
||||
view.Render(w, "index", 200, vm)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func listFiltered(category model.PageCategory) wrouter.FunctionHandlerFunc {
|
||||
return func(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
|
||||
var err error
|
||||
|
||||
if req.Method != "GET" || strings.LastIndex(req.URL.Path, "/") >= len(path) {
|
||||
return false
|
||||
}
|
||||
|
||||
tagName := strings.Replace(req.URL.Path[len(path):], "_", " ", -1)
|
||||
|
||||
vm := viewmodel.PageList{}
|
||||
|
||||
if tagName != "" {
|
||||
tag, err := model.FindTag("name", tagName)
|
||||
if err != nil {
|
||||
response.Text(w, 404, err.Error())
|
||||
return true
|
||||
}
|
||||
|
||||
vm.Headers, err = model.ListHeadersByTag(category.Key, tag)
|
||||
} else {
|
||||
vm.Headers, err = model.ListHeadersByCategory(category.Key)
|
||||
}
|
||||
|
||||
vm.Categories = model.PageCategories
|
||||
vm.ActiveCategory = category
|
||||
vm.Setup(user)
|
||||
|
||||
if err != nil {
|
||||
response.Text(w, 500, err.Error())
|
||||
return true
|
||||
}
|
||||
|
||||
view.Render(w, "index", 200, vm)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// story.aiterp.net/Ruins_of_Rakhana
|
||||
func init() {
|
||||
ListController.Function("/", listIndex)
|
||||
|
||||
ListController.Function("/", listFiltered(model.PageCategory{Key: ""}))
|
||||
for _, category := range model.PageCategories {
|
||||
ListController.Function(fmt.Sprintf("/%s/", strings.ToLower(category.Plural)), listFiltered(category))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.aiterp.net/AiteRP/aitestory/view"
|
||||
"git.aiterp.net/AiteRP/aitestory/viewmodel"
|
||||
"git.aiterp.net/gisle/wrouter"
|
||||
"git.aiterp.net/gisle/wrouter/auth"
|
||||
)
|
||||
|
||||
// UserController serves and handles the login form
|
||||
var UserController = wrouter.Router{}
|
||||
|
||||
func userLogin(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
|
||||
//var err error
|
||||
if (req.Method != "GET" && req.Method != "POST") || len(req.URL.Path) > len(path) {
|
||||
return false
|
||||
}
|
||||
|
||||
if req.Method == "GET" && user != nil {
|
||||
http.Redirect(w, req, "/", 302)
|
||||
return true
|
||||
}
|
||||
|
||||
ul := viewmodel.UserLogin{}
|
||||
|
||||
if req.Method == "POST" {
|
||||
req.ParseForm()
|
||||
|
||||
wa := WikiAthenticator{}
|
||||
newUser, err := wa.Login(req.Form.Get("username"), req.Form.Get("password"))
|
||||
if err == nil {
|
||||
sess := auth.OpenSession(newUser)
|
||||
|
||||
http.SetCookie(w, &http.Cookie{Name: auth.SessionCookieName, Value: sess.ID, Expires: sess.Time.Add(auth.SessionMaxTime), Path: "/", HttpOnly: true})
|
||||
http.Redirect(w, req, "/", 302)
|
||||
return true
|
||||
}
|
||||
ul.UserName = req.Form.Get("username")
|
||||
ul.Error = err.Error()
|
||||
}
|
||||
|
||||
ul.Setup(user)
|
||||
view.Render(w, "login", 200, ul)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func userLogout(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
|
||||
//var err error
|
||||
|
||||
if user != nil {
|
||||
auth.CloseSession(user.Session.ID)
|
||||
}
|
||||
|
||||
http.Redirect(w, req, "/", 302)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func init() {
|
||||
UserController.Function("/login", userLogin)
|
||||
UserController.Function("/logout", userLogout)
|
||||
}
|
||||
@@ -15,14 +15,17 @@ import (
|
||||
// to log in
|
||||
type WikiAthenticator struct{}
|
||||
|
||||
// ID is for a potential multi-login future
|
||||
func (wikiAuth *WikiAthenticator) ID() string {
|
||||
return "wiki"
|
||||
}
|
||||
|
||||
// Name is for a potential multi-login future
|
||||
func (wikiAuth *WikiAthenticator) Name() string {
|
||||
return "Wiki"
|
||||
}
|
||||
|
||||
// Find finds a user that has logged in at least once
|
||||
func (wikiAuth *WikiAthenticator) Find(username string) *auth.User {
|
||||
db := server.Main.DB
|
||||
|
||||
@@ -38,7 +41,7 @@ func (wikiAuth *WikiAthenticator) Find(username string) *auth.User {
|
||||
return nil
|
||||
}
|
||||
|
||||
user := auth.NewUser(wikiAuth, "", "member", nil)
|
||||
user := auth.NewUser(wikiAuth, "", "member", make(map[string]string, 4))
|
||||
role := "member"
|
||||
rows.Scan(&user.ID, &role)
|
||||
user.Data["role"] = role
|
||||
@@ -63,20 +66,19 @@ func (wikiAuth *WikiAthenticator) Login(username, password string) (*auth.User,
|
||||
}
|
||||
|
||||
// Look up the user
|
||||
rows, err := db.Query("SELECT id,role FROM `user` WHERE id=?", client.BasicAuthUser)
|
||||
rows, err := db.Query("SELECT id,role FROM `user` WHERE id=?", username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Login failed %v", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// If none was found, just create a new record with the role of member
|
||||
if !rows.Next() {
|
||||
_, err = db.Exec("INSERT INTO `user` (id, role) VALUES (?, 'member')", client.BasicAuthUser)
|
||||
_, err = db.Exec("INSERT INTO `user` (id, role) VALUES (?, 'member')", username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Login failed %v", err)
|
||||
}
|
||||
|
||||
return auth.NewUser(wikiAuth, client.BasicAuthUser, "member", nil), nil
|
||||
return auth.NewUser(wikiAuth, username, "member", nil), nil
|
||||
}
|
||||
|
||||
// If the user was found, read it in
|
||||
@@ -91,6 +93,7 @@ func (wikiAuth *WikiAthenticator) Login(username, password string) (*auth.User,
|
||||
return auth.NewUser(wikiAuth, userid, "member", nil), nil
|
||||
}
|
||||
|
||||
// Register just tells the user that they can't.
|
||||
func (wikiAuth *WikiAthenticator) Register(username, password string, data map[string]string) (*auth.User, error) {
|
||||
return nil, errors.New("Registration not allowed")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ func main() {
|
||||
router := &server.Main.Router
|
||||
|
||||
auth.Register(&controllers.WikiAthenticator{})
|
||||
router.Mount("/user", &controllers.UserController)
|
||||
router.Mount("/", &controllers.ListController)
|
||||
|
||||
router.Static("/ui/", server.Main.Config.Server.UI)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PageCategory represents a page category
|
||||
type PageCategory struct {
|
||||
Key string
|
||||
Plural string
|
||||
Icon string
|
||||
}
|
||||
|
||||
// URLRoot is the "folder" used for searching within the category
|
||||
func (category *PageCategory) URLRoot() string {
|
||||
return strings.ToLower(category.Plural)
|
||||
}
|
||||
|
||||
// PageCategories are used by the view model and page to enforce
|
||||
// a limited selection of categories. I may move it to a configuration
|
||||
// or the database, but for now I think this list is pretty fixed
|
||||
var PageCategories = []PageCategory{
|
||||
{"OoC", "OoC", "ooc"},
|
||||
{"Info", "Info", "info"},
|
||||
{"News", "News", "news"},
|
||||
{"Item", "Items", "item"},
|
||||
{"Document", "Documents", "document"},
|
||||
{"Background", "Background", "background"},
|
||||
{"Story", "Stories", "story"},
|
||||
}
|
||||
var pageCategories []string
|
||||
|
||||
// init setups pageCategories
|
||||
func init() {
|
||||
pageCategories := make([]string, len(PageCategories))
|
||||
for i, category := range PageCategories {
|
||||
pageCategories[i] = category.Key
|
||||
}
|
||||
}
|
||||
+92
-2
@@ -56,9 +56,42 @@ func ListHeaders() ([]Header, error) {
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// ListHeadersByTag lists all headers that has the tag
|
||||
func ListHeadersByTag(tag *Tag) ([]Header, error) {
|
||||
// ListHeadersByCategory grabs all the pages in the given category
|
||||
func ListHeadersByCategory(category string) ([]Header, error) {
|
||||
const query = `
|
||||
SELECT page.id,page.name,author,category,fictional_date,publish_date,edit_date,dated,tag.id,tag.type,tag.name
|
||||
FROM page
|
||||
LEFT JOIN page_tag ON (page.id = page_tag.page_id AND page_tag.primary = true)
|
||||
LEFT JOIN tag ON (tag.id = page_tag.tag_id)
|
||||
WHERE page.specific=false AND page.published=true AND page.unlisted=false AND page.category = ?;
|
||||
`
|
||||
|
||||
db := server.Main.DB
|
||||
|
||||
rows, err := db.Query(query, category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
results := make([]Header, 0, 64)
|
||||
header := Header{}
|
||||
for rows.Next() {
|
||||
err := parseHeader(&header, rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results = append(results, header)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// ListHeadersByTag lists all headers that has the tag. Leave the category empty
|
||||
// to not filter by it
|
||||
func ListHeadersByTag(category string, tag *Tag) ([]Header, error) {
|
||||
const query1 = `
|
||||
SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,page.dated,tag.id,tag.type,tag.name
|
||||
FROM page_tag
|
||||
RIGHT JOIN page ON page.id = page_tag.page_id
|
||||
@@ -66,6 +99,14 @@ func ListHeadersByTag(tag *Tag) ([]Header, error) {
|
||||
LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
|
||||
WHERE page_tag.tag_id=?
|
||||
`
|
||||
const query2 = `
|
||||
SELECT page.id,page.name,page.author,page.category,page.fictional_date,page.publish_date,page.edit_date,page.dated,tag.id,tag.type,tag.name
|
||||
FROM page_tag
|
||||
RIGHT JOIN page ON page.id = page_tag.page_id
|
||||
LEFT JOIN (page_tag AS pt2) ON (page.id = pt2.page_id AND pt2.primary = true)
|
||||
LEFT JOIN (tag AS tag) ON (tag.id = pt2.tag_id)
|
||||
WHERE page_tag.tag_id=? AND page.category=?
|
||||
`
|
||||
|
||||
if tag == nil {
|
||||
return nil, errors.New("no tag")
|
||||
@@ -73,6 +114,11 @@ func ListHeadersByTag(tag *Tag) ([]Header, error) {
|
||||
|
||||
db := server.Main.DB
|
||||
|
||||
query := query1
|
||||
if category != "" {
|
||||
query = query2
|
||||
}
|
||||
|
||||
rows, err := db.Query(query, tag.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -93,6 +139,50 @@ func ListHeadersByTag(tag *Tag) ([]Header, error) {
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// ListHeadersByTags searches for the first tag, then filters the result based on the
|
||||
// others. There is room for improvement in this function, but I'll have to judge whether
|
||||
// there will be a need for that.
|
||||
func ListHeadersByTags(category string, tags []Tag) ([]Header, error) {
|
||||
if len(tags) == 0 {
|
||||
return nil, errors.New("no tags")
|
||||
}
|
||||
|
||||
headers, err := ListHeadersByTag(category, &tags[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(headers) == 0 {
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
for _, tag := range tags[1:] {
|
||||
headers2, err := ListHeadersByTag(category, &tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results := make([]Header, 0, len(headers))
|
||||
for _, header := range headers {
|
||||
found := false
|
||||
for _, header2 := range headers2 {
|
||||
if header.ID == header2.ID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
results = append(results, header)
|
||||
}
|
||||
}
|
||||
|
||||
headers = results
|
||||
}
|
||||
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
func parseHeader(header *Header, rows *sql.Rows) error {
|
||||
var tagID, tagName, tagType string
|
||||
var fictionalDate, publishDate, editDate string
|
||||
|
||||
+2
-14
@@ -14,18 +14,6 @@ import (
|
||||
"github.com/russross/blackfriday"
|
||||
)
|
||||
|
||||
// PageCategories are used by the view model and page to enforce
|
||||
// a limited selection of categories. I may move it to a configuration
|
||||
var PageCategories = []string{
|
||||
"OoC",
|
||||
"Story",
|
||||
"Background",
|
||||
"Document",
|
||||
"News",
|
||||
"Item",
|
||||
"Info",
|
||||
}
|
||||
|
||||
// PageTypes describes how the source is rendered. For now it's only markdown,
|
||||
// but who knows what the future holds.
|
||||
var PageTypes = []string{
|
||||
@@ -62,7 +50,7 @@ type Page struct {
|
||||
|
||||
// Defaults fills in the default details for a page, suited for populating a form
|
||||
func (page *Page) Defaults() {
|
||||
page.Category = PageCategories[0]
|
||||
page.Category = PageCategories[0].Key
|
||||
|
||||
page.Dated = true
|
||||
page.Published = true
|
||||
@@ -220,7 +208,7 @@ func (page *Page) ParseForm(form url.Values) []error {
|
||||
errors := make([]error, 0, 4)
|
||||
page.cachedOutput = ""
|
||||
|
||||
err := formparser.Select(form.Get("category"), &page.Category, PageCategories, page.Category != "")
|
||||
err := formparser.Select(form.Get("category"), &page.Category, pageCategories, page.Category != "")
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("Category: %s", err))
|
||||
}
|
||||
|
||||
+2
-2
@@ -131,7 +131,7 @@ func TestPage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("ListHeadersByTag", func(t *testing.T) {
|
||||
headers, err := ListHeadersByTag(testPageTags[1])
|
||||
headers, err := ListHeadersByTag("", testPageTags[1])
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func TestPage(t *testing.T) {
|
||||
}
|
||||
|
||||
// Make a fake tag and make sure that doesn't return stuff
|
||||
headers, err = ListHeadersByTag(&Tag{ID: generate.ID()})
|
||||
headers, err = ListHeadersByTag("", &Tag{ID: generate.ID()})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/AiteRP/aitestory/server"
|
||||
"git.aiterp.net/gisle/wrouter/generate"
|
||||
@@ -108,6 +109,12 @@ func (tag *Tag) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hook returns the url friendly name, which is pretty much just
|
||||
// adding underscores to it.
|
||||
func (tag Tag) Hook() string {
|
||||
return strings.Replace(tag.Name, " ", "_", -1)
|
||||
}
|
||||
|
||||
// FindTag finds a tag by ID
|
||||
func FindTag(key string, id string) (*Tag, error) {
|
||||
db := server.Main.DB
|
||||
|
||||
+23
-1
@@ -96,7 +96,29 @@ func TestTag(t *testing.T) {
|
||||
t.Run("FindByID", func(t *testing.T) {
|
||||
tag, err := FindTag("id", id)
|
||||
if err != nil {
|
||||
t.Log("Failed to get tags:", err)
|
||||
t.Log("Failed to find tag:", err)
|
||||
t.Fail()
|
||||
}
|
||||
if tag == nil {
|
||||
t.Log("No tag found")
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("Tag found: %+v", tag)
|
||||
|
||||
if tag.Name != name || tag.ID != id {
|
||||
t.Error("Incorrect tag")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
testTag = tag
|
||||
})
|
||||
|
||||
t.Run("FindByName", func(t *testing.T) {
|
||||
tag, err := FindTag("name", name)
|
||||
if err != nil {
|
||||
t.Log("Failed to find tag:", err)
|
||||
t.Fail()
|
||||
}
|
||||
if tag == nil {
|
||||
|
||||
+17
-3
@@ -15,15 +15,22 @@ import (
|
||||
var wd, _ = os.Getwd()
|
||||
var rootPath = path.Join(wd, "./view/templates/")
|
||||
var cache = make(map[string]*template.Template)
|
||||
var argsCache = make(map[string][]string)
|
||||
|
||||
// Register registers a template and compiles it for rendering. This should be done
|
||||
// in the beginning since an error will terminate the server
|
||||
func Register(name string, base string) {
|
||||
tmpl, err := template.New(name).ParseFiles(path.Join(rootPath, name+".tmpl"), path.Join(rootPath, base+".tmpl"))
|
||||
func Register(name string, base string, fragments ...string) {
|
||||
for i, fragment := range fragments {
|
||||
fragments[i] = path.Join(rootPath, fragment+".tmpl")
|
||||
}
|
||||
|
||||
args := append([]string{path.Join(rootPath, name+".tmpl"), path.Join(rootPath, base+".tmpl")}, fragments...)
|
||||
tmpl, err := template.New(name).ParseFiles(args...)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to register %s: %s", name, err)
|
||||
}
|
||||
|
||||
argsCache[name] = args
|
||||
cache[name] = tmpl
|
||||
}
|
||||
|
||||
@@ -37,8 +44,14 @@ func Render(w http.ResponseWriter, name string, status int, viewModel interface{
|
||||
return
|
||||
}
|
||||
|
||||
tmpl, err := template.New(name).ParseFiles(argsCache[name]...)
|
||||
if err != nil {
|
||||
response.Text(w, 500, "Failed to run template "+name+": "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(status)
|
||||
err := tmpl.ExecuteTemplate(w, "base", viewModel)
|
||||
err = tmpl.ExecuteTemplate(w, "base", viewModel)
|
||||
if err != nil {
|
||||
log.Println("Template error:", err.Error())
|
||||
}
|
||||
@@ -56,4 +69,5 @@ func Run(w io.Writer, name string, viewModel interface{}) error {
|
||||
|
||||
func init() {
|
||||
Register("index", "base/default")
|
||||
Register("login", "base/default")
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
<script type="text/javascript" src="/ui/js/background.js"></script>
|
||||
|
||||
{{ template "head" }}
|
||||
{{ block "head" . }}{{end}}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -28,14 +28,11 @@
|
||||
|
||||
<div id="content-wrapper">
|
||||
<main>
|
||||
{{ template "content" }}
|
||||
{{ block "content" . }}{{end}}
|
||||
</main>
|
||||
|
||||
<nav class="main-menu">
|
||||
{{ template "menu" }}
|
||||
<ul>
|
||||
<li><a><div class="mg-icon">A</div><div class="mg-label">Login</div></a></li>
|
||||
</ul>
|
||||
{{ block "menu" . }}{{end}}
|
||||
</nav>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1,11 +1,33 @@
|
||||
{{ define "content" }}
|
||||
<article>
|
||||
<h1>Hello, World</h1>
|
||||
|
||||
</article>
|
||||
{{ end }}
|
||||
|
||||
{{ define "menu" }}
|
||||
<h1>Aite RP</h1>
|
||||
<a href="/"><h1>Aite RP</h1></a>
|
||||
|
||||
<ul>
|
||||
{{ range .Categories }}
|
||||
<li class="{{ if eq .Key $.ActiveCategory.Key }}selected{{end}}"><a href="/{{.URLRoot}}/{{$.ActiveTag.Hook}}"><div class="mg-icon">Π</div><div class="mg-label">{{.Plural}}</div></a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
{{ if $.User.LoggedIn }}
|
||||
<ul>
|
||||
<li><a href="/page/create"><div class="mg-icon">+</div><div class="mg-label">Create</div></a></li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="/user/logout"><div class="mg-icon">A</div><div class="mg-label">Logout</div></a></li>
|
||||
</ul>
|
||||
{{ else }}
|
||||
<ul>
|
||||
<li><a href="/user/login"><div class="mg-icon">A</div><div class="mg-label">Login</div></a></li>
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
|
||||
{{ end }}
|
||||
|
||||
{{ define "head" }}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{{ define "content" }}
|
||||
<article>
|
||||
<h1>Login</h1>
|
||||
<form action="/user/login", method="POST">
|
||||
<p class="red">{{$.Error}}</p>
|
||||
<input placeholder="Username" name="username" type="text" />
|
||||
<input placeholder="Password" name="password" type="password" />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</article>
|
||||
{{ end }}
|
||||
|
||||
{{ define "menu" }}
|
||||
<a href="/"><h1>Aite RP</h1></a>
|
||||
|
||||
<li><a href="/"><div class="mg-icon"><</div><div class="mg-label">Back</div></a></li>
|
||||
{{ end }}
|
||||
|
||||
{{ define "head" }}
|
||||
|
||||
{{ end }}
|
||||
+11
-9
@@ -2,7 +2,7 @@ package viewmodel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"log"
|
||||
|
||||
"git.aiterp.net/AiteRP/aitestory/server"
|
||||
"git.aiterp.net/gisle/wrouter/auth"
|
||||
@@ -10,20 +10,22 @@ import (
|
||||
|
||||
// Base is the basic information used to render the page
|
||||
type Base struct {
|
||||
UserID string
|
||||
UserName string
|
||||
UserRole string
|
||||
UserLoggedIn bool
|
||||
User struct {
|
||||
Name string
|
||||
Role string
|
||||
LoggedIn bool
|
||||
}
|
||||
ViewTitle string
|
||||
}
|
||||
|
||||
// InitBase initializes the base of the viewmodel
|
||||
func (base *Base) setupBase(user *auth.User, viewTitle string) {
|
||||
if user != nil {
|
||||
base.UserID = user.ID
|
||||
base.UserName = strings.SplitN(user.ID, ":", 2)[1]
|
||||
base.UserRole = user.Data["role"]
|
||||
base.UserLoggedIn = true
|
||||
log.Printf("%+v", user)
|
||||
|
||||
base.User.Name = user.ID
|
||||
base.User.Role = user.Data["role"]
|
||||
base.User.LoggedIn = true
|
||||
}
|
||||
|
||||
base.ViewTitle = fmt.Sprintf("%s - %s", viewTitle, server.Main.Config.View.Title)
|
||||
|
||||
@@ -9,8 +9,9 @@ import (
|
||||
type PageList struct {
|
||||
Base
|
||||
Headers []model.Header
|
||||
Category string
|
||||
ActiveTags []model.Tag
|
||||
ActiveCategory model.PageCategory
|
||||
Categories []model.PageCategory
|
||||
ActiveTag model.Tag
|
||||
FavoriteTags []model.Tag
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package viewmodel
|
||||
|
||||
import (
|
||||
"git.aiterp.net/gisle/wrouter/auth"
|
||||
)
|
||||
|
||||
// UserLogin is a view model for rendering the user login form
|
||||
type UserLogin struct {
|
||||
Base
|
||||
Error string
|
||||
UserName string
|
||||
Password string
|
||||
}
|
||||
|
||||
// Setup sets up the page model and the base, and should
|
||||
// be run after the details have been filled in.
|
||||
func (ul *UserLogin) Setup(user *auth.User) {
|
||||
ul.setupBase(user, "Login")
|
||||
}
|
||||
Reference in New Issue
Block a user