Import sources from Kontor
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/auth"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/util"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetRoutes sets the routes for the administrative data urls.
|
||||
func GetRoutes(router *gin.Engine) {
|
||||
adminRoutes := router.Group("/admin")
|
||||
{
|
||||
adminRoutes.GET("/", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), showAdminIndex)
|
||||
adminRoutes.GET("/user", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), showUserIndex)
|
||||
adminRoutes.POST("/user", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), showUserIndex)
|
||||
adminRoutes.GET("/user/view/:userid", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), showUserDetails)
|
||||
adminRoutes.POST("/user/view", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), validateUserCreation)
|
||||
adminRoutes.GET("/user/create", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), showUserCreation)
|
||||
adminRoutes.POST("/user/create", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), validateUserCreation)
|
||||
adminRoutes.GET("/data", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), util.ShowIndexPage)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// User defines the data model for application users with id,email, user name,
|
||||
// first and family name, password and admin status.
|
||||
type User struct {
|
||||
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
|
||||
Email string `json:"email" bson:"email,omitempty"`
|
||||
Username string `json:"username" bson:"username,omitempty"`
|
||||
Firstname string `json:"firstname" bson:"firstname,omitempty"`
|
||||
Lastname string `json:"lastname" bson:"lastname,omitempty"`
|
||||
Password string `json:"password" bson:"password,omitempty"`
|
||||
IsAdmin bool `json:"is_admin" bson:"is_admin,omitempty"`
|
||||
Model string `json:"model" bson:"model,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
"log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
mgo "gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// UserDAO extends the type BaseDAO.
|
||||
type UserDAO struct {
|
||||
Db dao.BaseDAO
|
||||
}
|
||||
|
||||
const (
|
||||
// USERCOLLECTION defines the collection name for storing application user data.
|
||||
USERCOLLECTION = "user"
|
||||
// USERMODEL defines the name of the user data model.
|
||||
USERMODEL = "kalorienmanager.admin.user"
|
||||
)
|
||||
|
||||
// HashPassword returns the encrypted password from password string.
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
// CheckPasswordHash returns if password correlates with pasword hash.
|
||||
func CheckPasswordHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// FindAll retrieves the list of users from the database.
|
||||
func (m *UserDAO) FindAll() ([]User, error) {
|
||||
m.Db.Connect()
|
||||
var users []User
|
||||
err := m.Db.MongoDb.C(USERCOLLECTION).Find(bson.M{"model": USERMODEL}).All(&users)
|
||||
return users, err
|
||||
}
|
||||
|
||||
// FindByID returns a user with given id or returns the error.
|
||||
func (m *UserDAO) FindByID(id string) (User, error) {
|
||||
m.Db.Connect()
|
||||
var user User
|
||||
err := m.Db.MongoDb.C(USERCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&user)
|
||||
return user, err
|
||||
}
|
||||
|
||||
// FindByUsername returns a user with given name or returns the error.
|
||||
func (m *UserDAO) FindByUsername(username string) (User, error) {
|
||||
m.Db.Connect()
|
||||
var user User
|
||||
err := m.Db.MongoDb.C(USERCOLLECTION).Find(bson.M{"username": username, "model": USERMODEL}).One(&user)
|
||||
return user, err
|
||||
}
|
||||
|
||||
// Insert a user into database.
|
||||
func (m *UserDAO) Insert(user User) error {
|
||||
m.Db.Connect()
|
||||
user.Model = USERMODEL
|
||||
err := m.Db.MongoDb.C(USERCOLLECTION).Insert(&user)
|
||||
return err
|
||||
}
|
||||
|
||||
// Upsert a user into database.
|
||||
func (m *UserDAO) Upsert(user User) (*mgo.ChangeInfo, error) {
|
||||
m.Db.Connect()
|
||||
user.Model = USERMODEL
|
||||
info, err := m.Db.MongoDb.C(USERCOLLECTION).Upsert(bson.M{"username": user.Username}, &user)
|
||||
return info, err
|
||||
}
|
||||
|
||||
// Update an existing user.
|
||||
func (m *UserDAO) Update(user User) error {
|
||||
m.Db.Connect()
|
||||
err := m.Db.MongoDb.C(USERCOLLECTION).UpdateId(user.ID, &user)
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete an existing user.
|
||||
func (m *UserDAO) Delete(user User) error {
|
||||
m.Db.Connect()
|
||||
err := m.Db.MongoDb.C(USERCOLLECTION).Remove(&user)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsUserValid checks if the username and password combination is valid
|
||||
func (m *UserDAO) IsUserValid(username, password string) bool {
|
||||
if gin.IsDebugging() {
|
||||
log.Printf("UserDAO.IsUserValid(%s)", username)
|
||||
}
|
||||
user, err := m.FindByUsername(username)
|
||||
if gin.IsDebugging() {
|
||||
log.Printf("UserDAO.IsUserValid: %v, %v", user, err)
|
||||
}
|
||||
if &user == nil || err != nil {
|
||||
return false
|
||||
}
|
||||
return CheckPasswordHash(password, user.Password)
|
||||
}
|
||||
|
||||
// IsUserAdmin checks if user identified by name has admin rights.
|
||||
func (m *UserDAO) IsUserAdmin(username string) bool {
|
||||
user, err := m.FindByUsername(username)
|
||||
if &user == nil || err != nil {
|
||||
return false
|
||||
}
|
||||
return user.IsAdmin
|
||||
}
|
||||
|
||||
// IsUsernameAvailable checks if the supplied username is available.
|
||||
func (m *UserDAO) IsUsernameAvailable(username string) bool {
|
||||
user, err := m.FindByUsername(username)
|
||||
if &user == nil || err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// adduser adds user in database. TODO is method necessary?
|
||||
func addUser(username, password, firstname, lastname string, isAdmin bool) (*User, error) {
|
||||
// passwordHash, _ := HashPassword(password)
|
||||
// var user = User{Username: username, Password: passwordHash, Firstname: firstname, Lastname: lastname, IsAdmin: isAdmin, Model: USERMODEL}
|
||||
// conn, err := util.GetCollection(USERCOLLECTION)
|
||||
// err = conn.Insert(&user)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return &user, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// changeuser changes user in database. TODO is method necessary?
|
||||
func changeUser(userid, username, password, firstname, lastname string, isAdmin bool) (*User, error) {
|
||||
// conn, err := util.GetCollection(USERCOLLECTION)
|
||||
// var user *User
|
||||
// err = conn.Find(bson.M{"_id": bson.ObjectIdHex(userid)}).One(&user)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// var change bson.M
|
||||
// if password != "" {
|
||||
// passwordHash, _ := HashPassword(password)
|
||||
// change = bson.M{"$set": bson.M{"username": username, "password": passwordHash, "firstname": firstname, "lastname": lastname, "is_admin": isAdmin}}
|
||||
// } else {
|
||||
// change = bson.M{"$set": bson.M{"username": username, "firstname": firstname, "lastname": lastname, "is_admin": isAdmin}}
|
||||
// }
|
||||
// err = conn.Update(bson.M{"_id": bson.ObjectIdHex(userid)}, change)
|
||||
// return user, nil
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
var userModelTestTable = []struct {
|
||||
name string
|
||||
typeName string
|
||||
}{
|
||||
{"Id", "string"},
|
||||
{"Email", "string"},
|
||||
{"Username", "string"},
|
||||
{"Firstname", "string"},
|
||||
{"Lastname", "string"},
|
||||
{"Password", "string"},
|
||||
{"IsAdmin", "bool"},
|
||||
{"Model", "string"},
|
||||
}
|
||||
|
||||
func TestUserModel(t *testing.T) {
|
||||
m := User{}
|
||||
if reflect.TypeOf(m).NumField() != len(userModelTestTable) {
|
||||
t.Fail()
|
||||
}
|
||||
for index, testData := range userModelTestTable {
|
||||
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
|
||||
if givenType != testData.typeName {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListUsers(t *testing.T) {
|
||||
var userDao = UserDAO{Db: dao.TestDb}
|
||||
users, err := userDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if users != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertUser(t *testing.T) {
|
||||
var (
|
||||
userDao = UserDAO{Db: dao.TestDb}
|
||||
user = User{}
|
||||
users []User
|
||||
)
|
||||
user.ID = bson.NewObjectId()
|
||||
user.Username = "test"
|
||||
err := userDao.Insert(user)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
users, err = userDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if len(users) != 1 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpsertUser(t *testing.T) {
|
||||
var (
|
||||
userDao = UserDAO{Db: dao.TestDb}
|
||||
user = User{}
|
||||
)
|
||||
user.ID = bson.NewObjectId()
|
||||
user.Username = "test2"
|
||||
userDao.Upsert(user)
|
||||
users, err := userDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if len(users) != 2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteUser(t *testing.T) {
|
||||
var (
|
||||
userDao = UserDAO{Db: dao.TestDb}
|
||||
)
|
||||
users, err := userDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
for _, user := range users {
|
||||
userDao.Delete(user)
|
||||
}
|
||||
users, err = userDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if len(users) != 0 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/auth"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/util"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ShowLoginPage renders login page.
|
||||
func ShowLoginPage(c *gin.Context) {
|
||||
// Call the render function with the name of the template to render
|
||||
util.Render(c, gin.H{"title": "Login"}, "login.html")
|
||||
}
|
||||
|
||||
// PerformLogin reads data from login form and validates input.
|
||||
func PerformLogin(c *gin.Context) {
|
||||
// Obtain the POSTed username and password values
|
||||
username := c.PostForm("username")
|
||||
password := c.PostForm("password")
|
||||
|
||||
var userDao = UserDAO{Db: dao.KalorienmanagerDb}
|
||||
|
||||
// Check if the username/password combination is valid
|
||||
if userDao.IsUserValid(username, password) {
|
||||
sessionInterface, _ := c.Get("session")
|
||||
sessionID := sessionInterface.(string)
|
||||
user, _ := userDao.FindByUsername(username)
|
||||
sessionDao := auth.SessionDAO{Db: dao.KalorienmanagerDb}
|
||||
session, _ := sessionDao.FindByID(sessionID)
|
||||
session.Username = username
|
||||
session.IsAdmin = user.IsAdmin
|
||||
sessionDao.Update(session)
|
||||
util.Render(c, gin.H{"title": "Successful Login", "InfoMessage": "Login successfull"}, "kontor/index.html")
|
||||
} else {
|
||||
// If the username/password combination is invalid,
|
||||
// show the error message on the login page
|
||||
c.HTML(http.StatusBadRequest, "login.html", gin.H{
|
||||
"ErrorTitle": "Login Failed",
|
||||
"ErrorMessage": "Invalid credentials provided"})
|
||||
}
|
||||
}
|
||||
|
||||
// Logout invalidates session.
|
||||
func Logout(c *gin.Context) {
|
||||
sessionInterface, _ := c.Get("session")
|
||||
sessionID := sessionInterface.(string)
|
||||
c.SetCookie("session", sessionID, -1, "", "", false, true)
|
||||
|
||||
// Redirect to the home page
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/")
|
||||
}
|
||||
|
||||
func showAdminIndex(c *gin.Context) {
|
||||
// Call the render function with the name of the template to render
|
||||
util.Render(c, gin.H{"title": "Kontor", "payload": nil}, "kontor/admin.html")
|
||||
}
|
||||
|
||||
func showUserIndex(c *gin.Context) {
|
||||
var dao = UserDAO{Db: dao.KalorienmanagerDb}
|
||||
if users, err := dao.FindAll(); err == nil && users != nil {
|
||||
util.Render(c, gin.H{"title": "Kontor User Administration", "payload": users}, "kontor/users.html")
|
||||
} else {
|
||||
util.Render(c, gin.H{"title": "Kontor User Administration", "payload": users, "ErrorMessage": err}, "kontor/users.html")
|
||||
}
|
||||
}
|
||||
|
||||
func showUserDetails(c *gin.Context) {
|
||||
userID := c.Param("userid")
|
||||
var userDao = UserDAO{Db: dao.KalorienmanagerDb}
|
||||
if user, err := userDao.FindByID(userID); err == nil && &user != nil {
|
||||
util.Render(c, gin.H{"title": "Kontor User Administration", "payload": user, "action": util.SaveAction}, "kontor/user-detail.html")
|
||||
} else {
|
||||
c.AbortWithError(http.StatusNotFound, err)
|
||||
}
|
||||
}
|
||||
|
||||
func showUserCreation(c *gin.Context) {
|
||||
var user = User{}
|
||||
util.Render(c, gin.H{"title": "Kontor User Administration", "payload": user, "action": util.AddAction}, "kontor/user-detail.html")
|
||||
}
|
||||
|
||||
func validateUserCreation(c *gin.Context) {
|
||||
// Obtain the POSTed username and password values
|
||||
username := c.PostForm("username")
|
||||
firstname := c.PostForm("firstname")
|
||||
lastname := c.PostForm("lastname")
|
||||
password := c.PostForm("password")
|
||||
adminFormVar := c.PostForm("admin")
|
||||
action := c.PostForm("action")
|
||||
userid := c.PostForm("userid")
|
||||
isAdmin, _ := strconv.ParseBool(adminFormVar)
|
||||
|
||||
var err error
|
||||
var dao = UserDAO{Db: dao.KalorienmanagerDb}
|
||||
var user = User{}
|
||||
|
||||
switch action {
|
||||
case util.AddAction:
|
||||
user.Username = username
|
||||
user.Firstname = firstname
|
||||
user.Lastname = lastname
|
||||
user.IsAdmin = isAdmin
|
||||
user.Password, _ = HashPassword(password)
|
||||
_, err = dao.Upsert(user)
|
||||
case util.SaveAction:
|
||||
user, _ = dao.FindByID(userid)
|
||||
user.Username = username
|
||||
user.Firstname = firstname
|
||||
user.Lastname = lastname
|
||||
user.IsAdmin = isAdmin
|
||||
user.Password, _ = HashPassword(password)
|
||||
err = dao.Update(user)
|
||||
case util.DeleteAction:
|
||||
user, _ = dao.FindByID(userid)
|
||||
err = dao.Delete(user)
|
||||
}
|
||||
if err == nil {
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/admin/user")
|
||||
} else {
|
||||
c.HTML(http.StatusBadRequest, "kontor/create-user.html", gin.H{
|
||||
"ErrorTitle": "User Creation Failed",
|
||||
"ErrorMessage": err.Error()})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/properties"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
var sessionDao = SessionDAO{Db: dao.KalorienmanagerDb}
|
||||
|
||||
// EnsureLoggedIn ensures that a request will be aborted with an error
|
||||
// if the user is not logged in
|
||||
func EnsureLoggedIn() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// If there's an error or if the token is empty
|
||||
// the user is not logged in
|
||||
sessionInterface, _ := c.Get("session")
|
||||
sessionID := sessionInterface.(string)
|
||||
if session, err := sessionDao.GetSession(sessionID); err != nil || session.Username == "" {
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/")
|
||||
//c.AbortWithStatus(http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureAdminStatus ensures that a request will be aborted with an error
|
||||
// if the user is not logged in
|
||||
func EnsureAdminStatus() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// If there's an error or if the token is empty
|
||||
// the user is not logged in
|
||||
sessionInterface, _ := c.Get("session")
|
||||
sessionID := sessionInterface.(string)
|
||||
if session, err := sessionDao.GetSession(sessionID); err != nil || !session.IsAdmin {
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/")
|
||||
//c.AbortWithStatus(http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureNotLoggedIn ensures that a request will be aborted with an error
|
||||
// if the user is already logged in
|
||||
func EnsureNotLoggedIn() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// If there's no error or if the token is not empty
|
||||
// the user is already logged in
|
||||
sessionInterface, _ := c.Get("session")
|
||||
sessionID := sessionInterface.(string)
|
||||
if session, err := sessionDao.GetSession(sessionID); err != nil || session.Username != "" {
|
||||
c.Redirect(http.StatusTemporaryRedirect, "/")
|
||||
//c.AbortWithStatus(http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetSessionStatus reads sessionId from cookie if available or create new session object
|
||||
// and sets cookie accordingly.
|
||||
func SetSessionStatus() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if sessionID, err := c.Cookie("session"); err == nil || sessionID != "" {
|
||||
c.Set("session", sessionID)
|
||||
} else {
|
||||
session, _ := sessionDao.GetSession(bson.NewObjectId().Hex())
|
||||
sessionID := session.ID.Hex()
|
||||
c.Set("session", sessionID)
|
||||
c.SetCookie("session", sessionID, 3600, "", "", false, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetSessionData populates sesion information with username, admin status of user and
|
||||
// application version.
|
||||
func SetSessionData(c *gin.Context, data gin.H) {
|
||||
sessionInterface, _ := c.Get("session")
|
||||
sessionID := sessionInterface.(string)
|
||||
// TODO move PrintDebug("setSessionData(): %v", sessionId)
|
||||
session, _ := sessionDao.GetSession(sessionID)
|
||||
// TODO move PrintDebug("setSessionData(): %v", *session)
|
||||
data["is_logged_in"] = (session.Username != "")
|
||||
data["is_admin"] = session.IsAdmin
|
||||
data["version"] = properties.Version
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package auth
|
||||
|
||||
import "gopkg.in/mgo.v2/bson"
|
||||
|
||||
// Session defines the data model for sessions with id,user name and admin status.
|
||||
type Session struct {
|
||||
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
|
||||
Username string `json:"username" bson:"username,omitempty"`
|
||||
IsAdmin bool `json:"is_admin" bson:"is_admin,omitempty"`
|
||||
Model string `json:"model" bson:"model,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
|
||||
mgo "gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// SessionDAO extends the type BaseDAO.
|
||||
type SessionDAO struct {
|
||||
Db dao.BaseDAO
|
||||
}
|
||||
|
||||
const (
|
||||
// SESSIONCOLLECTION defines the collection name for storing session data.
|
||||
SESSIONCOLLECTION = "session"
|
||||
// SESSIONMODEL defines the name of the session data model.
|
||||
SESSIONMODEL = "kalorienmanager.admin.session"
|
||||
)
|
||||
|
||||
// FindAll retrieves the list of sessions from the database.
|
||||
func (m *SessionDAO) FindAll() ([]Session, error) {
|
||||
m.Db.Connect()
|
||||
var sessions []Session
|
||||
err := m.Db.MongoDb.C(SESSIONCOLLECTION).Find(bson.M{"model": SESSIONMODEL}).All(&sessions)
|
||||
return sessions, err
|
||||
}
|
||||
|
||||
// FindByID returns a session with given id or returns the error.
|
||||
func (m *SessionDAO) FindByID(id string) (Session, error) {
|
||||
m.Db.Connect()
|
||||
var session Session
|
||||
err := m.Db.MongoDb.C(SESSIONCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&session)
|
||||
return session, err
|
||||
}
|
||||
|
||||
// Insert a session into database.
|
||||
func (m *SessionDAO) Insert(session Session) error {
|
||||
m.Db.Connect()
|
||||
session.Model = SESSIONMODEL
|
||||
err := m.Db.MongoDb.C(SESSIONCOLLECTION).Insert(&session)
|
||||
//log.PrintDebug("Insert: %v, %v\n", session, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Upsert a session into database.
|
||||
func (m *SessionDAO) Upsert(session Session) (*mgo.ChangeInfo, error) {
|
||||
m.Db.Connect()
|
||||
session.Model = SESSIONMODEL
|
||||
info, err := m.Db.MongoDb.C(SESSIONCOLLECTION).Upsert(bson.M{"_id": session.ID}, &session)
|
||||
return info, err
|
||||
}
|
||||
|
||||
// Update an existing session.
|
||||
func (m *SessionDAO) Update(session Session) error {
|
||||
m.Db.Connect()
|
||||
err := m.Db.MongoDb.C(SESSIONCOLLECTION).UpdateId(session.ID, &session)
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete an existing session.
|
||||
func (m *SessionDAO) Delete(session Session) error {
|
||||
m.Db.Connect()
|
||||
err := m.Db.MongoDb.C(SESSIONCOLLECTION).Remove(&session)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSession get a session by given id or create a new one, if nothing was found.
|
||||
func (m *SessionDAO) GetSession(id string) (*Session, error) {
|
||||
m.Db.Connect()
|
||||
session, err := m.FindByID(id)
|
||||
if err != nil {
|
||||
session = Session{ID: bson.ObjectIdHex(id), Username: "", IsAdmin: false}
|
||||
m.Insert(session)
|
||||
}
|
||||
return &session, nil
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
var sessionModelTestTable = []struct {
|
||||
name string
|
||||
typeName string
|
||||
}{
|
||||
{"Id", "string"},
|
||||
{"Username", "string"},
|
||||
{"IsAdmin", "bool"},
|
||||
{"Model", "string"},
|
||||
}
|
||||
|
||||
func TestSessionModel(t *testing.T) {
|
||||
m := Session{}
|
||||
if reflect.TypeOf(m).NumField() != len(sessionModelTestTable) {
|
||||
t.Fail()
|
||||
}
|
||||
for index, testData := range sessionModelTestTable {
|
||||
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
|
||||
if givenType != testData.typeName {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSessions(t *testing.T) {
|
||||
var (
|
||||
sessionDao = SessionDAO{Db: dao.TestDb}
|
||||
)
|
||||
sessions, err := sessionDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if sessions != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertSession(t *testing.T) {
|
||||
var (
|
||||
sessionDao = SessionDAO{Db: dao.TestDb}
|
||||
session = Session{}
|
||||
sessions []Session
|
||||
)
|
||||
session.ID = bson.NewObjectId()
|
||||
session.Username = "test"
|
||||
err := sessionDao.Insert(session)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
sessions, err = sessionDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if len(sessions) != 1 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpsertSession(t *testing.T) {
|
||||
var (
|
||||
sessionDao = SessionDAO{Db: dao.TestDb}
|
||||
session = Session{}
|
||||
)
|
||||
session.ID = bson.NewObjectId()
|
||||
session.Username = "test2"
|
||||
sessionDao.Upsert(session)
|
||||
sessions, err := sessionDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if len(sessions) != 2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteSession(t *testing.T) {
|
||||
var (
|
||||
sessionDao = SessionDAO{Db: dao.TestDb}
|
||||
)
|
||||
sessions, err := sessionDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
for _, session := range sessions {
|
||||
sessionDao.Delete(session)
|
||||
}
|
||||
sessions, err = sessionDao.FindAll()
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if len(sessions) != 0 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
mgo "gopkg.in/mgo.v2"
|
||||
)
|
||||
|
||||
// BaseDAO definess the connection parameters to a MongoDB instance.
|
||||
type BaseDAO struct {
|
||||
Server string
|
||||
Database string
|
||||
MongoDb *mgo.Database
|
||||
}
|
||||
|
||||
var (
|
||||
// KalorienmanagerDb has the database connection to the productive MongoDB instance.
|
||||
KalorienmanagerDb = BaseDAO{Server: "localhost", Database: "kalorienmanager"}
|
||||
// TestDb has the database connection to the test MongoDB instance.
|
||||
TestDb = BaseDAO{Server: "localhost", Database: "kalorienmanager_test"}
|
||||
)
|
||||
|
||||
// Connect instantiates the database session.
|
||||
func (m *BaseDAO) Connect() {
|
||||
session, err := mgo.Dial(m.Server)
|
||||
if err != nil {
|
||||
//util.PrintDebug("Connect: %v", err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
m.MongoDb = session.DB(m.Database)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var baseDaoTestTable = []struct {
|
||||
name string
|
||||
typeName string
|
||||
}{
|
||||
{"Server", "string"},
|
||||
{"Database", "string"},
|
||||
{"MongoDb", "ptr"},
|
||||
}
|
||||
|
||||
func TestCheckBaseDao(t *testing.T) {
|
||||
d := BaseDAO{}
|
||||
for index, testData := range baseDaoTestTable {
|
||||
givenType := reflect.TypeOf(d).Field(index).Type.Kind().String()
|
||||
if givenType != testData.typeName {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectDb(t *testing.T) {
|
||||
d := BaseDAO{}
|
||||
d.Connect()
|
||||
if d.MongoDb == nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDatabasesConfig(t *testing.T) {
|
||||
kalorienmanagerDb := KalorienmanagerDb
|
||||
if kalorienmanagerDb.Server != "localhost" {
|
||||
t.Fail()
|
||||
}
|
||||
if kalorienmanagerDb.Database != "kalorienmanager" {
|
||||
t.Fail()
|
||||
}
|
||||
testDb := TestDb
|
||||
if testDb.Server != "localhost" {
|
||||
t.Fail()
|
||||
}
|
||||
if testDb.Database != "kalorienmanager_test" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package properties
|
||||
|
||||
var (
|
||||
// Version defines the version of the web application kontor.
|
||||
Version = "undefined"
|
||||
// Debug defines the property debug to be used for more verbose output.
|
||||
Debug = false
|
||||
// Port defines port number under the web application is reachable.
|
||||
Port = 8500
|
||||
)
|
||||
|
||||
// SetVersion sets Version with given value.
|
||||
func SetVersion(value string) {
|
||||
Version = value
|
||||
}
|
||||
|
||||
// SetDebug sets Debug with given value.
|
||||
func SetDebug(value bool) {
|
||||
Debug = value
|
||||
}
|
||||
|
||||
// SetPort sets Port with given value.
|
||||
func SetPort(value int) {
|
||||
Port = value
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
"log"
|
||||
)
|
||||
|
||||
// CheckTradeYourSportsCardsData checks if the TYSC releated data is available.
|
||||
func CheckFoodData() {
|
||||
log.Printf("Check data for Food values")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/admin"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/auth"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/util"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// InitializeRoutes setup the routes for Kalorien Manager web application.
|
||||
func InitializeRoutes(router *gin.Engine) {
|
||||
|
||||
// Use the setUserStatus middleware for every route to set a flag
|
||||
// indicating whether the request was from an authenticated user or not
|
||||
router.Use(auth.SetSessionStatus())
|
||||
|
||||
// Handle the index route
|
||||
router.GET("/", util.ShowIndexPage)
|
||||
|
||||
userRoutes := router.Group("/user")
|
||||
{
|
||||
userRoutes.GET("/login", auth.EnsureNotLoggedIn(), admin.ShowLoginPage)
|
||||
userRoutes.POST("/login", auth.EnsureNotLoggedIn(), admin.PerformLogin)
|
||||
userRoutes.GET("/logout", auth.EnsureLoggedIn(), admin.Logout)
|
||||
}
|
||||
admin.GetRoutes(router)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/auth"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
)
|
||||
|
||||
// CleanupSessions removes all sessions from database.
|
||||
func CleanupSessions() {
|
||||
sessionDao := auth.SessionDAO{Db: dao.KalorienmanagerDb}
|
||||
sessions, _ := sessionDao.FindAll()
|
||||
for _, session := range sessions {
|
||||
sessionDao.Delete(session)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/admin"
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/dao"
|
||||
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
// CheckUserList ensures that at least the admin user is available.
|
||||
func CheckUserList() {
|
||||
var userDao = admin.UserDAO{Db: dao.KalorienmanagerDb}
|
||||
users, err := userDao.FindAll()
|
||||
if err == nil && len(users) == 0 {
|
||||
password, _ := admin.HashPassword("admin")
|
||||
id := bson.NewObjectId()
|
||||
user := admin.User{ID: id, Username: "admin", Password: password, Firstname: "Administrator", IsAdmin: true}
|
||||
userDao.Insert(user)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"gitlab.ingenieurbuero-peetz.de/tpeetz/kalorienmanager.git/pkg/auth"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
// SaveAction defines label of button.
|
||||
SaveAction = "Save"
|
||||
// AddAction defines label of button.
|
||||
AddAction = "Add"
|
||||
// DeleteAction defines label of button.
|
||||
DeleteAction = "Delete"
|
||||
)
|
||||
|
||||
// Render one of HTML, JSON or CSV based on the 'Accept' header of the request
|
||||
// If the header doesn't specify this, HTML is rendered, provided that
|
||||
// the template name is present
|
||||
func Render(c *gin.Context, data gin.H, templateName string) {
|
||||
auth.SetSessionData(c, data)
|
||||
switch c.Request.Header.Get("Accept") {
|
||||
case "application/json":
|
||||
c.JSON(http.StatusOK, data["payload"])
|
||||
case "application/xml":
|
||||
c.XML(http.StatusOK, data["payload"])
|
||||
default:
|
||||
c.HTML(http.StatusOK, templateName, data)
|
||||
}
|
||||
}
|
||||
|
||||
// ShowIndexPage render the index page of Kontor web application.
|
||||
func ShowIndexPage(c *gin.Context) {
|
||||
// Call the render function with the name of the template to render
|
||||
//log.Printf("Context: %v", c)
|
||||
Render(c, gin.H{"title": "Kalorienmanager", "payload": nil}, "index.html")
|
||||
}
|
||||
Reference in New Issue
Block a user