Merge branch 'develop/0.1.0' into 'main'

remove obsolete kontor.py

See merge request tpeetz/kontor!17
This commit was merged in pull request #61.
This commit is contained in:
2025-04-30 17:31:18 +02:00
1043 changed files with 61259 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
.idea/
.theia/
.vscode/
__pycache__/
bonus/
icons/
icons-shadowless/
springboot/.factorypath
java-ee/.settings
java-ee/.project
kontor-schema/env
kontor-schema/kontor_schema.egg-info
kontor-gui/.pdm-python
kontor-gui/dist
fastapi/.coverage
db-password.txt
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) 2024 Kontor
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+9
View File
@@ -0,0 +1,9 @@
kontor_api := kontor-api
kontor_spring := kontor-spring
.PHONY: all $(kontor_spring) $(kontor_api)
all: $(kontor_spring) $(kontor_api)
$(kontor_spring) $(kontor_api):
$(MAKE) --directory=$@ $(TARGET)
+44
View File
@@ -0,0 +1,44 @@
services:
mariadb:
image: mariadb
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: kontor
MYSQL_USER: kontor
MYSQL_PASSWORD: kontor
MYSQL_DATABASE: kontor
ports:
- 3316:3306
networks:
- database
volumes:
- mariadb-storage:/var/lib/mysql:rw
kontor:
image: kontor
restart: unless-stopped
networks:
- database
- frontend
ports:
- 8000:8000
depends_on:
- mariadb
kontor-api:
image: kontor-api
restart: unless-stopped
networks:
- database
- frontend
ports:
- 8800:8800
depends_on:
- mariadb
networks:
database:
frontend:
volumes:
mariadb-storage:
+10
View File
@@ -0,0 +1,10 @@
APP_NAME="Kontor"
APP_VERSION="v0.1.0"
# HTTP Response Content-Type Header - Success
HTTP_CONTENT_TYPE="application/vnd.api+json"
# HTTP Response Content-Type Header - Error
HTTP_PROBLEM="application/problem+json"
HTTP_PORT=":8086"
+9
View File
@@ -0,0 +1,9 @@
.gradle/
docs/build/
bin/
build/
cover.out
coverage.html
coverage.xml
.settings/
.project
+116
View File
@@ -0,0 +1,116 @@
variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
before_script:
- source "/home/gitlab-runner/.sdkman/bin/sdkman-init.sh"
- sdk update
- sdk d java 11.0.12-open
stages:
- environment
- prepare
- build
- test
- analysis
- deploy
environment:
stage: environment
script:
- echo "PATH=$PATH:/usr/local/go/bin:/home/gitlab-runner/go/bin" >> build.env
artifacts:
reports:
dotenv: build.env
Prepare Go dependencies:
stage: prepare
script:
- go get -u github.com/spf13/cobra
- go get -u github.com/jstemmer/go-junit-report
- go get -u github.com/inconshreveable/mousetrap
- go get -u github.com/mitchellh/go-homedir
- go get github.com/boumenot/gocover-cobertura
- go get -u gotest.tools/gotestsum
- go get -u github.com/cryptix/wav
- go get -u golang.org/x/lint/golint
dependencies:
- environment
Create Documentation:
stage: build
script:
- chmod +x docs/gradlew
- cd docs; ./gradlew publish
Compile Go Application:
stage: build
script: make build
Test Go Application:
stage: test
script:
- gotestsum --junitfile report.xml --format testname -- -coverprofile=coverage.txt -covermode count ./...
- go vet ./... 2> govet-report.out
- gocover-cobertura < coverage.txt > coverage.xml
- golint ./... > golint-report.out
dependencies:
- environment
artifacts:
when: always
paths:
- coverage.xml
- report.xml
reports:
junit: report.xml
coverage_report:
coverage_format: cobertura
path: coverage.xml
Code analysis:
stage: analysis
script:
- go test -coverprofile cover.out ./... -json > report.json
- go vet ./... 2> govet-report.out
- golint ./... > golint-report.out
- echo "sonar.projectKey=kontor_kontor-go_AX-cQT62rXuu6JVRvr-z" >> sonar-project.properties
- echo "sonar.sources=." >> sonar-project.properties
- echo "sonar.exclusions=**/*_test.go" >> sonar-project.properties
- echo "sonar.tests=." >> sonar-project.properties
- echo "sonar.test.inclusions=**/*_test.go" >> sonar-project.properties
- echo "sonar.go.tests.reportPaths=report.json" >> sonar-project.properties
- echo "sonar.go.coverage.reportPaths=cover.out" >> sonar-project.properties
- echo "sonar.go.govet.reportPaths=govet-report.out" >> sonar-project.properties
- echo "sonar.go.golint.reportPaths=golint-report.out" >> sonar-project.properties
- /data/sonar-scanner/bin/sonar-scanner -Dsonar.projectVersion=$(git describe --abbrev=0) -Dsonar.host.url=https://sonar.thpeetz.de -Dsonar.login=319616a2761ac3e96a1c7aacc54976bfff4096a9
dependencies:
- environment
Deploy To Staging:
stage: deploy
script:
- make build
- ssh kontor /home/kontor/kontor-test_service stop
- rsync -av templates kontor:/home/kontor/staging
- rsync -av bin/kontor kontor:/home/kontor/staging
- ssh kontor /home/kontor/kontor-test_service start
environment:
name: staging
url: https://kontor-test.thpeetz.de
only:
- main
Deploy to Production:
stage: deploy
script:
- make build
- sudo service kontor stop
- rsync -av templates kontor:/home/kontor/production
- rsync -av bin/kontor kontor:/home/kontor/production
- sudo service kontor start
environment:
name: production
url: https://kontor.thpeetz.de
only:
- main
when: manual
+73
View File
@@ -0,0 +1,73 @@
# Go parameters
GOPATH=$(HOME)/go
#GOBIN=$(shell pwd)/bin
GOBIN=/usr/local/go/bin
GOCMD=$(GOBIN)/go
GOGET=$(GOCMD) get
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOTEST=$(GOCMD) test
GOCOVER=$(GOCMD) tool cover
COBERTURA=$(HOME)/go/bin/gocover-cobertura
GOLINT=$(GOBIN)/golint
GOVET=$(GOCMD) vet
# Project parameters
GONAME=kontor
GOFILE=cmd/kontor/main.go
#.PHONY: all deps clean clean-bin clean-doc
all: deps build
deps:
$(GOGET) -u -v github.com/jstemmer/go-junit-report
$(GOGET) -u -v github.com/tebeka/go2xunit
$(GOGET) -u -v github.com/t-yuki/gocover-cobertura
$(GOGET) -u -v github.com/spf13/cobra/cobra
$(GOGET) -u -v github.com/inconshreveable/mousetrap
$(GOGET) -u -v github.com/mitchellh/go-homedir
$(GOGET) -u -v github.com/golang/protobuf/proto
$(GOGET) -u -v github.com/gin-gonic/gin
$(GOGET) -u -v github.com/gin-gonic/gin/binding
$(GOGET) -u -v github.com/gin-gonic/gin/render
$(GOGET) -u -v github.com/gin-contrib/sse
$(GOGET) -u -v github.com/mattn/go-isatty
$(GOGET) -u -v github.com/ugorji/go/codec
$(GOGET) -u -v golang.org/x/crypto/bcrypt
$(GOGET) -u -v golang.org/x/crypto/blowfish
G$(GOGET) -u -v gopkg.in/yaml.v2
$(GOGET) -u -v gopkg.in/mgo.v2
$(GOGET) -u -v gopkg.in/mgo.v2/bson
build: bin/$(GONAME)
bin/$(GONAME): $(GOFILE)
@echo "Building $(GOFILE) to ./bin"
$(GOBUILD) -v -ldflags="-X main.version=$(shell git describe --always --long --dirty)" -o bin/$(GONAME) $(GOFILE)
install:
@echo using $(GOPATH)
$(GOCMD) install -v -ldflags="-X main.version=$(shell git describe --always --long --dirty)" ./...
test:
$(GOTEST) -v ./...
$(GOTEST) -coverprofile=cover.out ./...
$(GOCOVER) -html=cover.out -o coverage.html
$(COBERTURA) < cover.out > coverage.xml
$(GOLINT) ./...
$(GOVET) -v ./...
doc:
cd docs; ./gradlew build
clean: clean-doc clean-bin
clean-doc:
@echo "Cleaning Gradle build"
cd docs; ./gradlew clean
clean-bin:
@echo "Cleaning Go build"
rm -rf bin/
+4
View File
@@ -0,0 +1,4 @@
[![pipeline status](https://gitlab.thpeetz.de/kontor/kontor-go/badges/master/pipeline.svg)](https://gitlab.thpeetz.de/kontor/kontor-go/commits/master)
[![coverage report](https://gitlab.thpeetz.de/kontor/kontor-go/badges/master/coverage.svg)](https://gitlab.thpeetz.de/kontor/kontor-go/commits/master)
# Kontor
+36
View File
@@ -0,0 +1,36 @@
package main
import (
"database/sql"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
connectionString := "kontor:kontor@tcp(127.0.0.1:3306)/kontor?parseTime=true"
db, err := sql.Open("mysql", connectionString)
if err != nil {
log.Printf("setup database error: %v", err)
return
}
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
log.Println("Database connected")
rows, err := db.Query("SELECT id, created_date, last_modified_date, version, url, title, review FROM media_file")
if err != nil {
log.Fatal((err.Error()))
}
defer rows.Close()
var rec MediaFile
for rows.Next() {
err = rows.Scan(&rec.ID, &rec.CreatedDate, &rec.LastModifiedDate, &rec.Version, &rec.Url, &rec.Title, &rec.Review)
if err != nil {
log.Fatal(err.Error())
}
log.Println(rec, string(rec.Url), string(rec.Title))
}
}
+25
View File
@@ -0,0 +1,25 @@
package main
import (
"time"
"github.com/google/uuid"
)
type AbstractEntity struct {
ID uuid.UUID `gorm:"type:uuid;primary_key" json:"id"`
Version uint `json:"version"`
CreatedDate time.Time `json:"createdDate"`
LastModifiedDate time.Time `json:"lastModifiedDate"`
}
type MediaFile struct {
AbstractEntity
Url []byte `json:"url"`
Review []uint8 `json:"review"`
ShouldDownload []uint8 `json:"shouldDownload"`
Title []byte `json:"title"`
CloudLink string `json:"cloudLink"`
FileName string `json:"fileName"`
Path string `json:"path"`
}
+89
View File
@@ -0,0 +1,89 @@
package cmd
import (
"fmt"
"log"
"os"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/properties"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/setup"
"github.com/gin-gonic/gin"
"github.com/spf13/cobra"
)
var (
// Verbose defines the parameter verbose.
Verbose bool
// Version defines the version of the web application.
Version string
// Debug defines the debug parameter.
Debug bool
// Port defines the parameter port.
Port int
// TemplatesDir defines the root directory of template files.
TemplatesDir string
router *gin.Engine
)
var rootCmd = &cobra.Command{
Use: "kontor",
Short: "kontor",
Long: `kontor`,
Run: func(cmd *cobra.Command, args []string) {
// Set Gin to production mode
if Debug {
gin.SetMode(gin.DebugMode)
} else {
gin.SetMode(gin.ReleaseMode)
}
log.SetOutput(gin.DefaultWriter)
// Set the router as the default one provided by Gin
router = gin.Default()
// Process the templates at the start so that they don't have to be loaded
// from the disk again. This makes serving HTML pages very fast.
templatesDir := fmt.Sprintf("%s/**/*", TemplatesDir)
log.Printf("load template files from %v", templatesDir)
router.LoadHTMLGlob(templatesDir)
// Use Middleware logger
router.Use(gin.Logger())
// Initialize the routes
setup.InitializeRoutes(router)
// Clean up SetSessionStatus
setup.CleanupSessions()
// Check if at least one user configured
setup.CheckUserList()
// Check if data for TradeYourSportsCards is available
setup.CheckTradeYourSportsCardsData()
//properties.SetVersion(Version)
// Start serving the application
server := fmt.Sprintf("127.0.0.1:%d", Port)
router.Run(server)
},
}
// Execute parses the commandline and calls Execute on rootCmd.
func Execute(version string) {
rootCmd.Version = version
properties.SetVersion(version)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
rootCmd.PersistentFlags().BoolVarP(&Debug, "debug", "d", false, "debug modus")
rootCmd.PersistentFlags().IntVarP(&Port, "port", "p", 8500, "port number")
rootCmd.PersistentFlags().StringVarP(&TemplatesDir, "templates", "t", "templates", "path for template files")
}
+32
View File
@@ -0,0 +1,32 @@
package main
import (
"github.com/joho/godotenv"
application "gitlab.com/tpeetz-kontor/kontor-go/pkg/infrastructure/app"
"gitlab.com/tpeetz-kontor/kontor-go/pkg/infrastructure/kernel"
)
// init is invoked before main()
func init() {
// loads values from .env into the system
if err := godotenv.Load(); err != nil {
panic("No .env file found")
}
}
func main() {
// Create our application
app := kernel.Boot()
// Build our services
//ping.BuildPingService(app)
// Run our Application in a coroutine
go func() {
app.Run()
}()
// Wait for termination signals and shut down gracefully
application.WaitForShutdown(app)
}
+63
View File
@@ -0,0 +1,63 @@
<Comics>
<Publisher name="Marvel" id="1"/>
<Publisher name="Aspen" id="2"/>
<Publisher name="DC" id="3"/>
<Publisher name="Dynamite Entertainment" id="4"/>
<Publisher name="WildStorm" id="5"/>
<Publisher name="Bongo" id="6"/>
<Publisher name="Image" id="7"/>
<Publisher name="Dark Horse Comics" id="8"/>
<Publisher name="Cliffhanger" id="9"/>
<Artist name="Turner, Michael" id="1"/>
<Artist name="Whedon, Joss" id="4"/>
<Artist name="Land, Greg" id="3"/>
<Artist name="Bendis, Brian Michael" id="2"/>
<Comic title="X-Men" id="1" publisher_id="1" current_order="true" completed="false"/>
<Comic title="Red Sonja" id="3" publisher_id="4" current_order="true" completed="false"/>
<Comic title="X-23" id="2" publisher_id="1" current_order="false" completed="false"/>
<Comic title="Simpsons Comics" id="4" publisher_id="6" current_order="true" completed="false"/>
<Comic title="Futurama Comics" id="5" publisher_id="6" current_order="true" completed="false"/>
<Comic title="Bomb Queen III: The Good, The Bad and The Lovely" id="7" publisher_id="7" current_order="false" completed="true"/>
<Comic title="Bomb Queen IV: Suicide Bomber" id="8" publisher_id="7" current_order="true" completed="false"/>
<Comic title="Gen13" id="9" publisher_id="5" current_order="true" completed="false"/>
<Comic title="Bomb Queen II: Queen of Hearts" id="6" publisher_id="7" current_order="false" completed="true"/>
<Comic title="Iron &amp; The Maiden" id="10" publisher_id="2" current_order="true" completed="false"/>
<Comic title="Fathom" id="11" publisher_id="2" current_order="false" completed="false"/>
<Comic title="Soulfire" id="12" publisher_id="2" current_order="false" completed="false"/>
<Comic title="Star Wars: Rebellion" id="13" publisher_id="8" current_order="false" completed="false"/>
<Comic title="Star Wars: Knights of the Old Republic" id="14" publisher_id="8" current_order="false" completed="false"/>
<Comic title="Star Wars: Legacy" id="15" publisher_id="8" current_order="false" completed="false"/>
<Comic title="Star Wars: Dark Times" id="16" publisher_id="8" current_order="false" completed="false"/>
<Comic title="Samurai: Heaven and Earth" id="17" publisher_id="8" current_order="false" completed="false"/>
<Comic title="Battle Pope" id="18" publisher_id="7" current_order="true" completed="false"/>
<Comic title="Danger Girl" id="19" publisher_id="9" current_order="false" completed="true"/>
<Comic title="Marville" id="20" publisher_id="1" current_order="false" completed="true"/>
<StoryArc title="Test" id="1" comic_id="1"/>
<Issue number="0" id="3" comic_id="3" cover_id="3" gelesen="true"/>
<Issue number="1" id="2" comic_id="2" cover_id="1" gelesen="false"/>
<Issue number="1" id="6" comic_id="6" gelesen="false"/>
<Issue number="1" id="4" comic_id="3" gelesen="true"/>
<Issue number="2" id="5" comic_id="3" gelesen="true"/>
<Issue number="2" id="7" comic_id="6" gelesen="false"/>
<Issue number="3" id="8" comic_id="6" gelesen="false"/>
<Issue number="4" id="9" comic_id="6" gelesen="false"/>
<Issue number="1" id="10" comic_id="18" gelesen="false"/>
<Issue number="2" id="11" comic_id="18" gelesen="false"/>
<Issue number="3" id="12" comic_id="18" gelesen="false"/>
<Issue number="4" id="13" comic_id="18" gelesen="false"/>
<Issue number="5" id="14" comic_id="18" gelesen="false"/>
<Issue number="6" id="15" comic_id="18" gelesen="false"/>
<Issue number="7" id="16" comic_id="18" gelesen="false"/>
<Issue number="8" id="17" comic_id="18" gelesen="false"/>
<Issue number="9" id="18" comic_id="18" gelesen="false"/>
<Issue number="10" id="19" comic_id="18" gelesen="false"/>
<Issue number="11" id="20" comic_id="18" gelesen="false"/>
<Issue number="12" id="21" comic_id="18" gelesen="false"/>
<Issue number="1" id="22" comic_id="20" gelesen="false"/>
<Issue number="2" id="23" comic_id="20" gelesen="false"/>
<Issue number="3" id="24" comic_id="20" gelesen="false"/>
<Issue number="4" id="25" comic_id="20" gelesen="false"/>
<Issue number="5" id="26" comic_id="20" gelesen="false"/>
<Issue number="6" id="27" comic_id="20" gelesen="false"/>
<Issue number="7" id="28" comic_id="20" gelesen="false"/>
</Comics>
+7
View File
@@ -0,0 +1,7 @@
plugins {
alias(versionsLibs.plugins.asciidoctorConvention)
}
wrapper {
gradleVersion = "7.5"
}
+2
View File
@@ -0,0 +1,2 @@
description='Documentation for application kontor-go'
version=1.0.0-SNAPSHOT
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+240
View File
@@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+91
View File
@@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+1
View File
@@ -0,0 +1 @@
rootProject.name='kontor-go'
+31
View File
@@ -0,0 +1,31 @@
= Projektbeschreibung Kontor
:author: Thomas Peetz
:email: <thomas.peetz@ingenieurbuero-peetz.de>
:doctype: article
:toc: left
:sectnums:
== Einführung
=== Zweck
== Anforderungen
== Implementierung
=== Datenmodell
== Betrieb
[bibliography]
== Referenzen
- [[[1]]] Thomas Peetz, Betriebshandbuch IBTP
[index]
== Index
== Tabellenverzeichnis
[glossary]
== Glossar
+28
View File
@@ -0,0 +1,28 @@
module gitlab.com/tpeetz-kontor/kontor-go
go 1.22.2
require github.com/joho/godotenv v1.5.1
require (
github.com/felixge/httpsnoop v1.0.3 // indirect
go.uber.org/multierr v1.10.0 // indirect
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/google/uuid v1.6.0
github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1
github.com/jinzhu/gorm v1.9.16 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
go.uber.org/zap v1.27.0
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.21.1-0.20240531212143-b6235391adb3 // indirect
gorm.io/driver/mysql v1.5.7 // indirect
gorm.io/gorm v1.25.12 // indirect
)
+62
View File
@@ -0,0 +1,62 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.21.1-0.20240531212143-b6235391adb3 h1:SHq4Rl+B7WvyM4XODon1LXtP7gcG49+7Jubt1gWWswY=
golang.org/x/tools v0.21.1-0.20240531212143-b6235391adb3/go.mod h1:bqv7PJ/TtlrzgJKhOAGdDUkUltQapRik/UEHubLVBWo=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs=
+58
View File
@@ -0,0 +1,58 @@
---
# file: kontor-ansible.yml
- hosts: localhost
remote_user: root
tasks:
- name: create group kontor
group:
name: kontor
state: present
- name: create user kontor
user:
name: kontor
home: /home/kontor
shell: /bin/bash
state: present
# generate_ssh_key: yes
# ssh_key_bits: 4096
# ssh_key_file: .ssh/id_rsa
- name: create log directory
file:
path: /var/log/kontor
state: directory
owner: kontor
group: kontor
mode: 0775
recurse: true
- name: create run directory
file:
path: /var/run/kontor
state: directory
owner: kontor
group: kontor
mode: 0775
recurse: true
- name: create directory
file:
path: /home/kontor/production
state: directory
owner: kontor
group: kontor
mode: 0775
recurse: false
- name: copy binary
copy:
src: bin/kontor
dest: /home/kontor/production/kontor
mode: 0775
- name: copy templates
copy:
src: templates
dest: /home/kontor/production/kontor/templates
mode: 0775
+23
View File
@@ -0,0 +1,23 @@
package admin
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"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(), showDataUpload)
adminRoutes.POST("/data", auth.EnsureLoggedIn(), auth.EnsureAdminStatus(), validateDataUpload)
}
}
+18
View File
@@ -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"`
}
+123
View File
@@ -0,0 +1,123 @@
package admin
import (
"gitlab.thpeetz.de/kontor/kontor-go/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 = "kontor.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
}
+105
View File
@@ -0,0 +1,105 @@
package admin
import (
"gitlab.thpeetz.de/kontor/kontor-go/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()
}
}
+242
View File
@@ -0,0 +1,242 @@
package admin
import (
"io/ioutil"
"log"
"net/http"
"path/filepath"
"strconv"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/comics"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"github.com/gin-gonic/gin"
"github.com/smallfish/simpleyaml"
)
const (
// KontorUserAdministrationTitle defines the text of the page title
KontorUserAdministrationTitle = "Kontor User Administration"
// DataUploadTemplate defines the name of the template file for the data upload
DataUploadTemplate = "kontor/data-upload.html"
)
// 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.KontorDb}
// 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.KontorDb}
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.KontorDb}
if users, err := dao.FindAll(); err == nil && users != nil {
util.Render(c, gin.H{"title": KontorUserAdministrationTitle, "payload": users}, "kontor/users.html")
} else {
util.Render(c, gin.H{"title": KontorUserAdministrationTitle, "payload": users, "ErrorMessage": err}, "kontor/users.html")
}
}
func showUserDetails(c *gin.Context) {
userID := c.Param("userid")
var userDao = UserDAO{Db: dao.KontorDb}
if user, err := userDao.FindByID(userID); err == nil && &user != nil {
util.Render(c, gin.H{"title": KontorUserAdministrationTitle, "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": KontorUserAdministrationTitle, "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.KontorDb}
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()})
}
}
func showDataUpload(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")
util.Render(c, gin.H{"title": "Kontor Data Upload", "payload": nil}, DataUploadTemplate)
}
func validateDataUpload(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")
datafile, err := c.FormFile("datafile")
if err != nil {
c.HTML(http.StatusBadRequest, DataUploadTemplate, gin.H{
"ErrorTitle": "Data Upload Failed",
"ErrorMessage": err.Error()})
return
}
log.Printf("Data File: %v", datafile.Filename)
filename := filepath.Base(datafile.Filename)
if err := c.SaveUploadedFile(datafile, filename); err != nil {
c.HTML(http.StatusBadRequest, DataUploadTemplate, gin.H{
"ErrorTitle": "Data Upload Failed",
"ErrorMessage": err.Error()})
return
}
source, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
yaml, err := simpleyaml.NewYaml(source)
if err != nil {
panic(err)
}
if yaml.IsArray() {
size, err := yaml.GetArraySize()
if err != nil {
panic(err)
}
log.Printf("Found %d entries.\n", size)
var publisherDao comics.PublisherDAO
publisherDao.Db = dao.KontorDb
var artistDao comics.ArtistDAO
artistDao.Db = dao.KontorDb
var comicDao comics.ComicDAO
comicDao.Db = dao.KontorDb
publisherMap := make(map[int]string)
for index := 0; index < size; index++ {
entry := yaml.GetIndex(index)
if entry.IsMap() {
model, err := entry.Get("model").String()
if err != nil {
panic(err)
}
pk, _ := entry.Get("pk").Int()
switch model {
case "comics.publisher":
name, err := entry.Get("fields").Get("name").String()
if err != nil {
panic(err)
}
log.Printf(" %v %v %v\n", pk, model, name)
publisherMap[pk] = name
publisher := comics.Publisher{}
publisher.Name = name
info, _ := publisherDao.Upsert(publisher)
log.Printf("Publisher records changed: %d", info.Updated)
case "comics.artist":
name, err := entry.Get("fields").Get("name").String()
if err != nil {
panic(err)
}
log.Printf(" %v %v %v\n", pk, model, name)
artist := comics.Artist{}
artist.Name = name
info, _ := artistDao.Upsert(artist)
log.Printf("Artist records changed: %d", info.Updated)
case "comics.comic":
title, err := entry.Get("fields").Get("title").String()
if err != nil {
panic(err)
}
publisherID, err := entry.Get("fields").Get("publisher").Int()
publisher, err := publisherDao.FindByName(publisherMap[publisherID])
completed, err := entry.Get("fields").Get("completed").Bool()
if err != nil {
log.Printf("Error occured: %v", err)
}
log.Printf(" %v %v %v %v\n", pk, model, title, completed)
comic := comics.Comic{}
comic.Title = title
comic.Completed = completed
comic.Publisher = publisher.ID
info, _ := comicDao.Upsert(comic)
log.Printf("Comic records changed: %d", info.Updated)
}
//fmt.Printf("Entry %d: %v\n", index, entry)
}
}
}
util.Render(c, gin.H{"title": "Kontor Data Upload", "payload": nil}, DataUploadTemplate)
}
@@ -0,0 +1,19 @@
package comic
import (
"net/http"
"gitlab.com/tpeetz-kontor/kontor-go/cmd/pkg/context/comic/routing"
"gitlab.com/tpeetz-kontor/kontor-go/cmd/pkg/infrastructure/app"
)
func BuildComicService(app *app.Application) {
// Create our Handler
handler := routing.NewHandler(app)
// Create a sub router for this service
router := app.Router.Methods(http.MethodGet).Subrouter()
// Register our service routes
router.HandleFunc("/comics/comic", handler.ComicList).Name("comics:comicList")
}
+87
View File
@@ -0,0 +1,87 @@
package auth
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/properties"
"log"
"net/http"
"github.com/gin-gonic/gin"
"gopkg.in/mgo.v2/bson"
)
var sessionDao = SessionDAO{Db: dao.KontorDb}
// 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 session 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)
session, _ := sessionDao.GetSession(sessionID)
if gin.IsDebugging() {
log.Printf("setSessionData(%v): %v", sessionID, session)
}
data["is_logged_in"] = (session.Username != "")
data["is_admin"] = session.IsAdmin
data["version"] = properties.Version
}
+11
View File
@@ -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"`
}
+78
View File
@@ -0,0 +1,78 @@
package auth
import (
"gitlab.thpeetz.de/kontor/kontor-go/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 = "kontor.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
}
+103
View File
@@ -0,0 +1,103 @@
package auth
import (
"gitlab.thpeetz.de/kontor/kontor-go/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()
}
}
+12
View File
@@ -0,0 +1,12 @@
package comics
import (
"gopkg.in/mgo.v2/bson"
)
// Artist defines the data model for comic artists with id and name.
type Artist struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Model string `json:"model" bson:"model"`
}
+78
View File
@@ -0,0 +1,78 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"log"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// ArtistDAO extends the type BaseDAO.
type ArtistDAO struct {
Db dao.BaseDAO
}
const (
// ARTISTCOLLECTION defines the collection name for storing comic artists.
ARTISTCOLLECTION = "artist"
// ARTISTMODEL defines the name of the artist data model.
ARTISTMODEL = "kontor.comics.artist"
)
// FindAll retrieves the list of artists from the database.
func (m *ArtistDAO) FindAll() ([]Artist, error) {
m.Db.Connect()
var artists []Artist
err := m.Db.MongoDb.C(ARTISTCOLLECTION).Find(bson.M{"model": ARTISTMODEL}).All(&artists)
return artists, err
}
// FindByID returns an artists with given id or returns the error.
func (m *ArtistDAO) FindByID(id string) (Artist, error) {
m.Db.Connect()
var artist Artist
err := m.Db.MongoDb.C(ARTISTCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&artist)
return artist, err
}
// FindByName returns an artists with given name or returns the error.
func (m *ArtistDAO) FindByName(name string) (Artist, error) {
m.Db.Connect()
var artist Artist
err := m.Db.MongoDb.C(ARTISTCOLLECTION).Find(bson.M{"name": name, "model": ARTISTMODEL}).One(&artist)
return artist, err
}
// Insert an artist into database.
func (m *ArtistDAO) Insert(artist Artist) error {
m.Db.Connect()
artist.Model = ARTISTMODEL
err := m.Db.MongoDb.C(ARTISTCOLLECTION).Insert(&artist)
return err
}
// Upsert an artist into database.
func (m *ArtistDAO) Upsert(artist Artist) (*mgo.ChangeInfo, error) {
m.Db.Connect()
artist.Model = ARTISTMODEL
info, err := m.Db.MongoDb.C(ARTISTCOLLECTION).Upsert(bson.M{"name": artist.Name}, &artist)
return info, err
}
// Delete an existing artist.
func (m *ArtistDAO) Delete(artist Artist) error {
m.Db.Connect()
err := m.Db.MongoDb.C(ARTISTCOLLECTION).Remove(&artist)
if err != nil {
log.Printf("ArtistDao.Delete: %v", err)
}
return err
}
// Update an existing artist.
func (m *ArtistDAO) Update(artist Artist) error {
m.Db.Connect()
err := m.Db.MongoDb.C(ARTISTCOLLECTION).UpdateId(artist.ID, &artist)
return err
}
+96
View File
@@ -0,0 +1,96 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var artistModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Model", "string"},
}
func TestArtistModel(t *testing.T) {
m := Artist{}
if reflect.TypeOf(m).NumField() != len(artistModelTestTable) {
t.Fail()
}
for index, testData := range artistModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListArtists(t *testing.T) {
var (
artistDao = ArtistDAO{Db: dao.TestDb}
)
artists, err := artistDao.FindAll()
if err != nil {
t.Fail()
}
if artists != nil {
t.Fail()
}
}
func TestInsertArtist(t *testing.T) {
var (
artistDao = ArtistDAO{Db: dao.TestDb}
artist = Artist{}
artists []Artist
)
artist.ID = bson.NewObjectId()
artist.Name = "Turner, Michael"
err := artistDao.Insert(artist)
if err != nil {
t.Fail()
}
artists, _ = artistDao.FindAll()
if len(artists) != 1 {
t.Fail()
}
}
func TestUpsertArtist(t *testing.T) {
var (
artistDao = ArtistDAO{Db: dao.TestDb}
artist = Artist{}
)
artist.ID = bson.NewObjectId()
artist.Name = "Marz, Ron"
_, err := artistDao.Upsert(artist)
if err != nil {
t.Fail()
}
artists, _ := artistDao.FindAll()
if len(artists) != 2 {
t.Fail()
}
}
func TestDeleteArtist(t *testing.T) {
var (
artistDao = ArtistDAO{Db: dao.TestDb}
)
artists, err := artistDao.FindAll()
if err != nil {
t.Fail()
}
for _, artist := range artists {
artistDao.Delete(artist)
}
artists, _ = artistDao.FindAll()
if len(artists) != 0 {
t.Fail()
}
}
+23
View File
@@ -0,0 +1,23 @@
package comics
import (
"net/http"
"github.com/gin-gonic/gin"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
)
const (
// ArtistPublisherTemplate defines name of template file for comics publishers
ArtistPublisherTemplate = "comics/publishers.html"
)
func showArtistList(c *gin.Context) {
var dao = ArtistDAO{Db: dao.KontorDb}
if artists, err := dao.FindAll(); err == nil {
util.Render(c, gin.H{"title": "Comic Artists", "payload": artists}, "artists.html")
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
+15
View File
@@ -0,0 +1,15 @@
package comics
import (
"gopkg.in/mgo.v2/bson"
)
// Comic defines the data model for comic issues with id, title, publisher, order and completion status.
type Comic struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title"`
Publisher bson.ObjectId `json:"publisher" bson:"publisher,omitempty"`
CurrentOrder bool `json:"current_order" bson:"current_order"`
Completed bool `json:"completed" bson:"completed"`
Model string `json:"model" bson:"model"`
}
+75
View File
@@ -0,0 +1,75 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// ComicDAO extends the type BaseDAO.
type ComicDAO struct {
Db dao.BaseDAO
}
const (
// COMICCOLLECTION defines the collection name for storing comics.
COMICCOLLECTION = "comic"
// COMICMODEL defines the name of the comic data model.
COMICMODEL = "kontor.comics.comic"
)
// FindAll retrieves the list of comisc from the database.
func (m *ComicDAO) FindAll() ([]Comic, error) {
m.Db.Connect()
var comics []Comic
err := m.Db.MongoDb.C(COMICCOLLECTION).Find(bson.M{"model": COMICMODEL}).All(&comics)
return comics, err
}
// FindByID returns an comic with given id or returns the error.
func (m *ComicDAO) FindByID(id string) (Comic, error) {
m.Db.Connect()
var comic Comic
err := m.Db.MongoDb.C(COMICCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&comic)
return comic, err
}
// FindByName returns an comic with given name or returns the error.
func (m *ComicDAO) FindByName(name string) (Comic, error) {
m.Db.Connect()
var comic Comic
err := m.Db.MongoDb.C(COMICCOLLECTION).Find(bson.M{"name": name, "model": COMICMODEL}).One(&comic)
return comic, err
}
// Insert a comic into database.
func (m *ComicDAO) Insert(comic Comic) error {
m.Db.Connect()
comic.Model = COMICMODEL
err := m.Db.MongoDb.C(COMICCOLLECTION).Insert(&comic)
//util.PrintDebug("ComicDAO.Insert: %v", comic)
return err
}
// Upsert a comic into database.
func (m *ComicDAO) Upsert(comic Comic) (*mgo.ChangeInfo, error) {
m.Db.Connect()
comic.Model = COMICMODEL
info, err := m.Db.MongoDb.C(COMICCOLLECTION).Upsert(bson.M{"title": comic.Title}, &comic)
return info, err
}
// Delete an existing comic.
func (m *ComicDAO) Delete(comic Comic) error {
m.Db.Connect()
err := m.Db.MongoDb.C(COMICCOLLECTION).Remove(&comic)
return err
}
// Update an existing movie
func (m *ComicDAO) Update(comic Comic) error {
m.Db.Connect()
err := m.Db.MongoDb.C(COMICCOLLECTION).UpdateId(comic.ID, &comic)
return err
}
+88
View File
@@ -0,0 +1,88 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var comicModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Title", "string"},
{"Publisher", "string"},
{"CurrentOrder", "bool"},
{"Completed", "bool"},
{"Model", "string"},
}
func TestComicModel(t *testing.T) {
m := Comic{}
if reflect.TypeOf(m).NumField() != len(comicModelTestTable) {
t.Fail()
}
for index, testData := range comicModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListComics(t *testing.T) {
var (
comicDao = ComicDAO{Db: dao.TestDb}
)
comics, err := comicDao.FindAll()
if err != nil {
t.Fail()
}
if len(comics) != 0 {
t.Fail()
}
}
func TestInsertComic(t *testing.T) {
var (
comicDao = ComicDAO{Db: dao.TestDb}
comic = Comic{}
comics []Comic
)
comic.ID = bson.NewObjectId()
comic.Title = "Simpsons"
comicDao.Insert(comic)
comics, _ = comicDao.FindAll()
if len(comics) != 1 {
t.Fail()
}
}
func TestUpsertComic(t *testing.T) {
var (
comicDao = ComicDAO{Db: dao.TestDb}
comic = Comic{}
)
comic.ID = bson.NewObjectId()
comic.Title = "1602"
comicDao.Upsert(comic)
comics, _ := comicDao.FindAll()
if len(comics) != 2 {
t.Fail()
}
}
func TestDeleteComic(t *testing.T) {
var (
comicDao = ComicDAO{Db: dao.TestDb}
)
comics, _ := comicDao.FindAll()
for _, comic := range comics {
comicDao.Delete(comic)
}
comics, _ = comicDao.FindAll()
if len(comics) != 0 {
t.Fail()
}
}
+12
View File
@@ -0,0 +1,12 @@
package comics
import (
"gopkg.in/mgo.v2/bson"
)
// Publisher defines the data model for comic publishers with id and name.
type Publisher struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Model string `json:"model" bson:"model"`
}
+75
View File
@@ -0,0 +1,75 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// PublisherDAO extends the type BaseDAO.
type PublisherDAO struct {
Db dao.BaseDAO
}
const (
// PUBLISHERCOLLECTION defines the collection name for storing publishers.
PUBLISHERCOLLECTION = "publisher"
// PUBLISHERMODEL defines the name of the publisher data model.
PUBLISHERMODEL = "kontor.comics.publisher"
)
// FindAll retrieves the list of publishers from the database.
func (m *PublisherDAO) FindAll() ([]Publisher, error) {
m.Db.Connect()
var publishers []Publisher
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Find(bson.M{"model": PUBLISHERMODEL}).All(&publishers)
return publishers, err
}
// FindByID returns an publisher with given id or returns the error.
func (m *PublisherDAO) FindByID(id string) (Publisher, error) {
m.Db.Connect()
var publisher Publisher
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&publisher)
return publisher, err
}
// FindByName returns an comic with given name or returns the error.
func (m *PublisherDAO) FindByName(name string) (Publisher, error) {
m.Db.Connect()
var publisher Publisher
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Find(bson.M{"name": name, "model": PUBLISHERMODEL}).One(&publisher)
return publisher, err
}
// Insert a publisher into database.
func (m *PublisherDAO) Insert(publisher Publisher) error {
m.Db.Connect()
publisher.Model = PUBLISHERMODEL
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Insert(&publisher)
//util.PrintDebug("PublisherDAO.Insert: %v", publisher)
return err
}
// Upsert a publisher into database.
func (m *PublisherDAO) Upsert(publisher Publisher) (*mgo.ChangeInfo, error) {
m.Db.Connect()
publisher.Model = PUBLISHERMODEL
info, err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Upsert(bson.M{"name": publisher.Name}, &publisher)
return info, err
}
// Delete an existing publisher.
func (m *PublisherDAO) Delete(publisher Publisher) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Remove(&publisher)
return err
}
// Update an existing publisher.
func (m *PublisherDAO) Update(publisher Publisher) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).UpdateId(publisher.ID, &publisher)
return err
}
+87
View File
@@ -0,0 +1,87 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var publisherModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Model", "string"},
}
func TestPublisherModel(t *testing.T) {
m := Publisher{}
if reflect.TypeOf(m).NumField() != len(publisherModelTestTable) {
t.Fail()
}
for index, testData := range publisherModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListPublishers(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
)
publishers, err := publisherDao.FindAll()
if err != nil {
t.Fail()
}
if len(publishers) != 0 {
t.Fail()
}
}
func TestInsertPublisher(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
publisher = Publisher{}
publishers []Publisher
)
publisher.ID = bson.NewObjectId()
publisher.Name = "CrossGen"
publisherDao.Insert(publisher)
publishers, _ = publisherDao.FindAll()
if len(publishers) != 1 {
t.Fail()
}
}
func TestUpsertPublisher(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
publisher = Publisher{}
)
publisher.ID = bson.NewObjectId()
publisher.Name = "Marvel"
publisherDao.Upsert(publisher)
publishers, _ := publisherDao.FindAll()
if len(publishers) != 2 {
t.Fail()
}
}
func TestDeletePublisher(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
)
publishers, _ := publisherDao.FindAll()
for _, publisher := range publishers {
publisherDao.Delete(publisher)
}
publishers, _ = publisherDao.FindAll()
if len(publishers) != 0 {
t.Fail()
}
}
+70
View File
@@ -0,0 +1,70 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"net/http"
"github.com/gin-gonic/gin"
)
const (
// ComicsPublisherTemplate defines name of template file for comics publishers
ComicsPublisherTemplate = "comics/publishers.html"
// ComicsPublisherDetailsTemplate defines name of template file for comics publishers
ComicsPublisherDetailsTemplate = "comics/publisher.html"
)
func showPublisherList(c *gin.Context) {
var dao = PublisherDAO{Db: dao.KontorDb}
if publishers, err := dao.FindAll(); err == nil {
util.Render(c, gin.H{"title": "Comics Publisher List", "payload": publishers}, ComicsPublisherTemplate)
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
func showPublisherDetails(c *gin.Context) {
var dao = PublisherDAO{Db: dao.KontorDb}
publisherid := c.Param("publisher_id")
if publisher, err := dao.FindByID(publisherid); err == nil {
util.Render(c, gin.H{"title": "Comics Publisher", "payload": publisher, "action": util.SaveAction}, ComicsPublisherDetailsTemplate)
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
func showPublisherCreation(c *gin.Context) {
var publisher = Publisher{}
util.Render(c, gin.H{"title": "Comics Publisher Creation", "payload": publisher, "action": util.AddAction}, ComicsPublisherTemplate)
}
func validatePublisherDetails(c *gin.Context) {
name := c.PostForm("name")
action := c.PostForm("action")
publisherid := c.PostForm("publisherid")
var err error
var dao = PublisherDAO{Db: dao.KontorDb}
var publisher = Publisher{}
switch action {
case util.AddAction:
publisher.Name = name
_, err = dao.Upsert(publisher)
case util.SaveAction:
publisher, _ = dao.FindByID(publisherid)
publisher.Name = name
err = dao.Update(publisher)
case util.DeleteAction:
publisher, _ = dao.FindByID(publisherid)
err = dao.Delete(publisher)
}
if err == nil {
c.Redirect(http.StatusTemporaryRedirect, "/comics/publisher")
} else {
c.HTML(http.StatusBadRequest, "comics/publisher.html", gin.H{
"ErrorTitle": "Publisher Creation Failed",
"ErrorMessage": err.Error()})
}
}
+28
View File
@@ -0,0 +1,28 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"github.com/gin-gonic/gin"
)
// GetRoutes returns all routes for comic related data.
func GetRoutes(router *gin.Engine) {
comicRoutes := router.Group("/comics")
{
comicRoutes.GET("/", auth.EnsureLoggedIn(), showComicList)
comicRoutes.GET("/artist", auth.EnsureLoggedIn(), showArtistList)
comicRoutes.GET("/artist/view/:artist_id", auth.EnsureLoggedIn(), showArtistList)
comicRoutes.GET("/artist/create", auth.EnsureLoggedIn(), showArtistList)
comicRoutes.POST("/artist/create", auth.EnsureLoggedIn(), showArtistList)
comicRoutes.GET("/comic", auth.EnsureLoggedIn(), showComicList)
comicRoutes.GET("/comic/view/:comic_id", auth.EnsureLoggedIn(), showComic)
comicRoutes.GET("/comic/create", auth.EnsureLoggedIn(), showComicList)
comicRoutes.POST("/comic/create", auth.EnsureLoggedIn(), showComicList)
comicRoutes.GET("/publisher", auth.EnsureLoggedIn(), showPublisherList)
comicRoutes.POST("/publisher", auth.EnsureLoggedIn(), showPublisherList)
comicRoutes.GET("/publisher/view/:publisher_id", auth.EnsureLoggedIn(), showPublisherDetails)
comicRoutes.POST("/publisher/validate", auth.EnsureLoggedIn(), validatePublisherDetails)
comicRoutes.GET("/publisher/create", auth.EnsureLoggedIn(), showPublisherCreation)
}
}
+28
View File
@@ -0,0 +1,28 @@
package comics
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"net/http"
"github.com/gin-gonic/gin"
)
func showComicList(c *gin.Context) {
var dao = ComicDAO{Db: dao.KontorDb}
if comics, err := dao.FindAll(); err == nil {
util.Render(c, gin.H{"title": "Comics", "payload": comics}, "comics.html")
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
func showComic(c *gin.Context) {
var dao = ComicDAO{Db: dao.KontorDb}
comicID := c.Param("comic_id")
if comic, err := dao.FindByID(comicID); err == nil {
util.Render(c, gin.H{"title": "Comic Details", "payload": comic, "action": util.SaveAction}, "comic.html")
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
+15
View File
@@ -0,0 +1,15 @@
package responses
// Response is the Ping Response
type Response struct {
Message string `json:"message"`
}
type ComicList struct {
Comics []Comic `json:"comics"`
}
type Comic struct {
ID string `json:"id"`
Title string `json:"title"`
}
+33
View File
@@ -0,0 +1,33 @@
package routing
import (
"net/http"
"gitlab.com/tpeetz-kontor/kontor-go/cmd/pkg/context/comic/responses"
"gitlab.com/tpeetz-kontor/kontor-go/cmd/pkg/infrastructure/app"
responseFactory "gitlab.com/tpeetz-kontor/kontor-go/cmd/pkg/infrastructure/response"
)
// Handler is the http.Handler for this request
type Handler struct {
app *app.Application
}
// NewHandler will create a new Handler to handle this request
func NewHandler(app *app.Application) *Handler {
return &Handler{app}
}
// Handle will handle the incoming request
func (handler *Handler) ComicList(response http.ResponseWriter, request *http.Request) {
handler.app.Logger.Info("Ping Handler Dispatched.")
responseFactory.Send(
response,
http.StatusOK,
&responses.ComicList{
Comics: []responses.Comic{{ID: "123", Title: "Comic1"}, {ID: "123", Title: "Comic1"}},
},
handler.app.Config.HTTP.Content,
)
}
+31
View File
@@ -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 (
// KontorDb has the database connection to the productive MongoDB instance.
KontorDb = BaseDAO{Server: "localhost", Database: "kontor"}
// TestDb has the database connection to the test MongoDB instance.
TestDb = BaseDAO{Server: "localhost", Database: "kontor_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)
}
+51
View File
@@ -0,0 +1,51 @@
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) {
kontorDb := KontorDb
if kontorDb.Server != "localhost" {
t.Fail()
}
if kontorDb.Database != "kontor" {
t.Fail()
}
testDb := TestDb
if testDb.Server != "localhost" {
t.Fail()
}
if testDb.Database != "kontor_test" {
t.Fail()
}
}
+50
View File
@@ -0,0 +1,50 @@
package app
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gorilla/mux"
"gitlab.com/tpeetz-kontor/kontor-go/pkg/infrastructure/config"
"go.uber.org/zap"
)
// Application is our general purpose Application struct
type Application struct {
Server *http.Server
Router *mux.Router
Logger *zap.Logger
Config *config.Config
}
// Run will run the Application server
func (app *Application) Run() {
app.Logger.Info("App started...")
err := app.Server.ListenAndServe()
if err != nil {
fmt.Println(err)
}
}
// WaitForShutdown is a graceful way to handle server shutdown events
func WaitForShutdown(application *Application) {
// Create a channel to listen for OS signals
interruptChan := make(chan os.Signal, 1)
signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
// Block until we receive a signal to our channel
<-interruptChan
application.Logger.Info("Received shutdown signal, gracefully terminating")
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
application.Server.Shutdown(ctx)
os.Exit(0)
}
+48
View File
@@ -0,0 +1,48 @@
package config
import "os"
// AppConfig is the Application configuration struct
type AppConfig struct {
Name string
Version string
Token string
}
// HTTPConfig is the Application HTTP configuration
type HTTPConfig struct {
Content string
Problem string
Port string
}
// Config is the Configuration struct
type Config struct {
App AppConfig
HTTP HTTPConfig
}
// New returns a new Config Struct
func New() *Config {
return &Config{
App: AppConfig{
Name: env("APP_NAME", "Kontor"),
Version: env("APP_VERSION", "v1.0"),
Token: env("APP_TOKEN", ""),
},
HTTP: HTTPConfig{
Content: env("HTTP_CONTENT_TYPE", "application/json"),
Problem: env("HTTP_PROBLEM", "application/problem+json"),
Port: env("HTTP_PORT", ":8086"),
},
}
}
// env is a simple helper function to read an environment variable or return a default value
func env(key string, defaultValue string) string {
if value, exists := os.LookupEnv(key); exists {
return value
}
return defaultValue
}
+91
View File
@@ -0,0 +1,91 @@
package kernel
import (
"context"
"net/http"
"time"
"github.com/google/uuid"
gohandlers "github.com/gorilla/handlers"
"github.com/gorilla/mux"
"gitlab.com/tpeetz-kontor/kontor-go/pkg/infrastructure/app"
"gitlab.com/tpeetz-kontor/kontor-go/pkg/infrastructure/config"
"go.uber.org/zap"
)
// Boot the Application
func Boot() *app.Application {
// Configuration
config := bootConfig()
// Router
router := bootRouter()
// CORS
corsHandler := gohandlers.CORS(gohandlers.AllowedOrigins([]string{"*"}))
// Logger
logger := bootLogger()
defer logger.Sync() // flushes buffer, if any
// Create and return and Application
return &app.Application{
Server: &http.Server{
Addr: config.HTTP.Port,
Handler: corsHandler(requestIDMiddleware(router)),
IdleTimeout: 120 * time.Second,
ReadTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
},
Router: router,
Logger: logger,
Config: config,
}
}
func bootConfig() *config.Config {
return config.New()
}
func bootRouter() *mux.Router {
return mux.NewRouter()
}
func bootLogger() *zap.Logger {
logger, logError := zap.NewProduction()
if logError != nil {
panic(logError)
}
return logger
}
// ContextKey is used for context.Context value. The value requires a key that is not primitive type.
type ContextKey string
// ContextKeyRequestID is the ContextKey for RequestID
const ContextKeyRequestID ContextKey = "requestID"
func requestIDMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
id := uuid.New()
ctx = context.WithValue(ctx, ContextKeyRequestID, id.String())
r = r.WithContext(ctx)
bootLogger().Debug("Incoming request",
zap.String("method", r.Method),
zap.String("uri", r.RequestURI),
zap.String("addr", r.RemoteAddr), zap.String("id", id.String()),
)
next.ServeHTTP(w, r)
bootLogger().Debug("Finished handling http req. %s",
zap.String("id", id.String()))
})
}
@@ -0,0 +1,20 @@
package response
import (
"encoding/json"
"net/http"
)
// Response is a generic HTTP Response Struct
type Response struct {
Data string `json:"data"`
}
// Send a HTTP Response
func Send(responseWriter http.ResponseWriter, code int, payload interface{}, contentType string) {
response, _ := json.Marshal(payload)
responseWriter.Header().Set("Content-Type", contentType)
responseWriter.WriteHeader(code)
responseWriter.Write(response)
}
+12
View File
@@ -0,0 +1,12 @@
package library
import (
"gopkg.in/mgo.v2/bson"
)
// Author defines the data model for library authors with id and name.
type Author struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Model string `json:"model" bson:"model,omitempty"`
}
+74
View File
@@ -0,0 +1,74 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// AuthorDAO extends the type BaseDAO.
type AuthorDAO struct {
Db dao.BaseDAO
}
const (
// AUTHORCOLLECTION defines the collection name for storing authors.
AUTHORCOLLECTION = "author"
// AUTHORMODEL defines the name of the author data model.
AUTHORMODEL = "kontor.library.author"
)
// FindAll retrieves the list of authors from the database.
func (m *AuthorDAO) FindAll() ([]Author, error) {
m.Db.Connect()
var authors []Author
err := m.Db.MongoDb.C(AUTHORCOLLECTION).Find(bson.M{"model": AUTHORMODEL}).All(&authors)
return authors, err
}
// FindByID returns an author with given id or returns the error.
func (m *AuthorDAO) FindByID(id string) (Author, error) {
m.Db.Connect()
var author Author
err := m.Db.MongoDb.C(AUTHORCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&author)
return author, err
}
// FindByName returns an author with given name or returns the error.
func (m *AuthorDAO) FindByName(name string) (Author, error) {
m.Db.Connect()
var author Author
err := m.Db.MongoDb.C(AUTHORCOLLECTION).Find(bson.M{"name": name, "model": AUTHORMODEL}).One(&author)
return author, err
}
// Insert a author into database.
func (m *AuthorDAO) Insert(author Author) error {
m.Db.Connect()
author.Model = AUTHORMODEL
err := m.Db.MongoDb.C(AUTHORCOLLECTION).Insert(&author)
return err
}
// Upsert a author into database.
func (m *AuthorDAO) Upsert(author Author) (*mgo.ChangeInfo, error) {
m.Db.Connect()
author.Model = AUTHORMODEL
info, err := m.Db.MongoDb.C(AUTHORCOLLECTION).Upsert(bson.M{"name": author.Name}, &author)
return info, err
}
// Delete an existing author.
func (m *AuthorDAO) Delete(author Author) error {
m.Db.Connect()
err := m.Db.MongoDb.C(AUTHORCOLLECTION).Remove(&author)
return err
}
// Update an existing author.
func (m *AuthorDAO) Update(author Author) error {
m.Db.Connect()
err := m.Db.MongoDb.C(AUTHORCOLLECTION).UpdateId(author.ID, &author)
return err
}
+99
View File
@@ -0,0 +1,99 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var authorModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Model", "string"},
}
func TestAuthorModel(t *testing.T) {
m := Author{}
if reflect.TypeOf(m).NumField() != len(authorModelTestTable) {
t.Fail()
}
for index, testData := range authorModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListAuthors(t *testing.T) {
var (
authorDao = AuthorDAO{Db: dao.TestDb}
)
authors, err := authorDao.FindAll()
if err != nil {
t.Fail()
}
if len(authors) != 0 {
t.Fail()
}
}
func TestInsertAuthor(t *testing.T) {
var (
authorDao = AuthorDAO{Db: dao.TestDb}
author = Author{}
authors []Author
)
author.ID = bson.NewObjectId()
author.Name = "Packt Publishing"
err := authorDao.Insert(author)
if err != nil {
t.Fail()
}
authors, err = authorDao.FindAll()
if len(authors) != 1 {
t.Fail()
}
}
func TestUpsertAuthor(t *testing.T) {
var (
authorDao = AuthorDAO{Db: dao.TestDb}
)
var author = Author{}
author.ID = bson.NewObjectId()
author.Name = "Hansa Verlag"
authorDao.Upsert(author)
authors, err := authorDao.FindAll()
if err != nil {
t.Fail()
}
if len(authors) != 2 {
t.Fail()
}
}
func TestDeleteAuthor(t *testing.T) {
var (
authorDao = AuthorDAO{Db: dao.TestDb}
)
authors, err := authorDao.FindAll()
if err != nil {
t.Fail()
}
for _, author := range authors {
authorDao.Delete(author)
}
authors, err = authorDao.FindAll()
if err != nil {
t.Fail()
}
if len(authors) != 0 {
t.Fail()
}
}
+18
View File
@@ -0,0 +1,18 @@
package library
import (
"gopkg.in/mgo.v2/bson"
)
// Book defines the data model for library books with id, title, author, publisher,
// isbn, year and edition.
type Book struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title"`
Author string `json:"author" bson:"author"`
Publisher bson.ObjectId `json:"publisher" bson:"publisher,omitempty"`
Isbn string `json:"isbn" bson:"isbn,omitempty"`
Year int `json:"year" bson:"year,omitempty"`
Edition string `json:"edition" bson:"edition,omitempty"`
Model string `json:"model" bson:"model,omitempty"`
}
+74
View File
@@ -0,0 +1,74 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// BookDAO extends the type BaseDAO.
type BookDAO struct {
Db dao.BaseDAO
}
const (
// BOOKCOLLECTION defines the collection name for storing books.
BOOKCOLLECTION = "book"
// BOOKMODEL defines the name of the book data model.
BOOKMODEL = "kontor.library.book"
)
// FindAll retrieves the list of books from the database.
func (m *BookDAO) FindAll() ([]Book, error) {
m.Db.Connect()
var books []Book
err := m.Db.MongoDb.C(BOOKCOLLECTION).Find(bson.M{"model": BOOKMODEL}).All(&books)
return books, err
}
// FindByID returns an book with given id or returns the error.
func (m *BookDAO) FindByID(id string) (Book, error) {
m.Db.Connect()
var book Book
err := m.Db.MongoDb.C(BOOKCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&book)
return book, err
}
// FindByTitle returns a book with given title or returns the error.
func (m *BookDAO) FindByTitle(title string) (Book, error) {
m.Db.Connect()
var book Book
err := m.Db.MongoDb.C(BOOKCOLLECTION).Find(bson.M{"title": title, "model": BOOKMODEL}).One(&book)
return book, err
}
// Insert a book into database.
func (m *BookDAO) Insert(book Book) error {
m.Db.Connect()
book.Model = BOOKMODEL
err := m.Db.MongoDb.C(BOOKCOLLECTION).Insert(&book)
return err
}
// Upsert a book into database.
func (m *BookDAO) Upsert(book Book) (*mgo.ChangeInfo, error) {
m.Db.Connect()
book.Model = BOOKMODEL
info, err := m.Db.MongoDb.C(BOOKCOLLECTION).Upsert(bson.M{"title": book.Title}, &book)
return info, err
}
// Delete an existing book.
func (m *BookDAO) Delete(book Book) error {
m.Db.Connect()
err := m.Db.MongoDb.C(BOOKCOLLECTION).Remove(&book)
return err
}
// Update an existing book.
func (m *BookDAO) Update(book Book) error {
m.Db.Connect()
err := m.Db.MongoDb.C(BOOKCOLLECTION).UpdateId(book.ID, &book)
return err
}
+107
View File
@@ -0,0 +1,107 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var bookModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Title", "string"},
{"Author", "string"},
{"Publisher", "string"},
{"Isbn", "string"},
{"Year", "int"},
{"Edition", "string"},
{"Model", "string"},
}
func TestBookModel(t *testing.T) {
m := Book{}
if reflect.TypeOf(m).NumField() != len(bookModelTestTable) {
t.Fail()
}
for index, testData := range bookModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListBooks(t *testing.T) {
var (
bookDao = BookDAO{Db: dao.TestDb}
)
books, err := bookDao.FindAll()
if err != nil {
t.Fail()
}
if len(books) != 0 {
t.Fail()
}
}
func TestInsertBook(t *testing.T) {
var (
bookDao = BookDAO{Db: dao.TestDb}
book = Book{}
books []Book
)
book.ID = bson.NewObjectId()
book.Title = "Packt Publishing"
err := bookDao.Insert(book)
if err != nil {
t.Fail()
}
books, err = bookDao.FindAll()
if err != nil {
t.Fail()
}
if len(books) != 1 {
t.Fail()
}
}
func TestUpsertBook(t *testing.T) {
var (
bookDao = BookDAO{Db: dao.TestDb}
book = Book{}
)
book.ID = bson.NewObjectId()
book.Title = "Hansa Verlag"
bookDao.Upsert(book)
books, err := bookDao.FindAll()
if err != nil {
t.Fail()
}
if len(books) != 2 {
t.Fail()
}
}
func TestDeleteBook(t *testing.T) {
var (
bookDao = BookDAO{Db: dao.TestDb}
)
books, err := bookDao.FindAll()
if err != nil {
t.Fail()
}
for _, book := range books {
bookDao.Delete(book)
}
books, err = bookDao.FindAll()
if err != nil {
t.Fail()
}
if len(books) != 0 {
t.Fail()
}
}
+12
View File
@@ -0,0 +1,12 @@
package library
import (
"gopkg.in/mgo.v2/bson"
)
// Publisher defines the data model for library publishers with id and name.
type Publisher struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Model string `json:"model" bson:"model"`
}
+74
View File
@@ -0,0 +1,74 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// PublisherDAO extends the type BaseDAO.
type PublisherDAO struct {
Db dao.BaseDAO
}
const (
// PUBLISHERCOLLECTION defines the collection name for storing publishers.
PUBLISHERCOLLECTION = "publisher"
// PUBLISHERMODEL defines the name of the publisher data model.
PUBLISHERMODEL = "kontor.library.publisher"
)
// FindAll retrieves the list of publishers from the database.
func (m *PublisherDAO) FindAll() ([]Publisher, error) {
m.Db.Connect()
var publishers []Publisher
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Find(bson.M{"model": PUBLISHERMODEL}).All(&publishers)
return publishers, err
}
// FindByID returns an publisher with given id or returns the error.
func (m *PublisherDAO) FindByID(id string) (Publisher, error) {
m.Db.Connect()
var publisher Publisher
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&publisher)
return publisher, err
}
// FindByName returns an comic with given name or returns the error.
func (m *PublisherDAO) FindByName(name string) (Publisher, error) {
m.Db.Connect()
var publisher Publisher
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Find(bson.M{"name": name, "model": PUBLISHERMODEL}).One(&publisher)
return publisher, err
}
// Insert a publisher into database.
func (m *PublisherDAO) Insert(publisher Publisher) error {
m.Db.Connect()
publisher.Model = PUBLISHERMODEL
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Insert(&publisher)
return err
}
// Upsert a publisher into database.
func (m *PublisherDAO) Upsert(publisher Publisher) (*mgo.ChangeInfo, error) {
m.Db.Connect()
publisher.Model = PUBLISHERMODEL
info, err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Upsert(bson.M{"name": publisher.Name}, &publisher)
return info, err
}
// Delete an existing publisher.
func (m *PublisherDAO) Delete(publisher Publisher) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).Remove(&publisher)
return err
}
// Update an existing publisher.
func (m *PublisherDAO) Update(publisher Publisher) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PUBLISHERCOLLECTION).UpdateId(publisher.ID, &publisher)
return err
}
+103
View File
@@ -0,0 +1,103 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var publisherModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Model", "string"},
}
func TestPublisherModel(t *testing.T) {
m := Publisher{}
if reflect.TypeOf(m).NumField() != len(publisherModelTestTable) {
t.Fail()
}
for index, testData := range publisherModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListPublishers(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
)
publishers, err := publisherDao.FindAll()
if err != nil {
t.Fail()
}
if len(publishers) != 0 {
t.Fail()
}
}
func TestInsertPublisher(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
publisher = Publisher{}
publishers []Publisher
)
publisher.ID = bson.NewObjectId()
publisher.Name = "Packt Publishing"
err := publisherDao.Insert(publisher)
if err != nil {
t.Fail()
}
publishers, err = publisherDao.FindAll()
if err != nil {
t.Fail()
}
if len(publishers) != 1 {
t.Fail()
}
}
func TestUpsertPublisher(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
publisher = Publisher{}
)
publisher.ID = bson.NewObjectId()
publisher.Name = "Hansa Verlag"
publisherDao.Upsert(publisher)
publishers, err := publisherDao.FindAll()
if err != nil {
t.Fail()
}
if len(publishers) != 2 {
t.Fail()
}
}
func TestDeletePublisher(t *testing.T) {
var (
publisherDao = PublisherDAO{Db: dao.TestDb}
)
publishers, err := publisherDao.FindAll()
if err != nil {
t.Fail()
}
for _, publisher := range publishers {
publisherDao.Delete(publisher)
}
publishers, err = publisherDao.FindAll()
if err != nil {
t.Fail()
}
if len(publishers) != 0 {
t.Fail()
}
}
+68
View File
@@ -0,0 +1,68 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"net/http"
"github.com/gin-gonic/gin"
)
const (
// LibraryPublisherTemplate defines name of template file for comics publishers
LibraryPublisherTemplate = "library/publishers.html"
)
func showPublisherList(c *gin.Context) {
var dao = PublisherDAO{Db: dao.KontorDb}
if publishers, err := dao.FindAll(); err == nil {
util.Render(c, gin.H{"title": "Library Publisher List", "payload": publishers}, LibraryPublisherTemplate)
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
func showPublisherDetails(c *gin.Context) {
var dao = PublisherDAO{Db: dao.KontorDb}
publisherid := c.Param("publisher_id")
if publisher, err := dao.FindByID(publisherid); err == nil {
util.Render(c, gin.H{"title": "Library Publisher", "payload": publisher, "action": util.SaveAction}, LibraryPublisherTemplate)
} else {
c.AbortWithError(http.StatusNotFound, err)
}
}
func showPublisherCreation(c *gin.Context) {
var publisher = Publisher{}
util.Render(c, gin.H{"title": "Library Publisher Creation", "payload": publisher, "action": util.AddAction}, LibraryPublisherTemplate)
}
func validatePublisherDetails(c *gin.Context) {
name := c.PostForm("name")
action := c.PostForm("action")
publisherid := c.PostForm("publisherid")
var err error
var dao = PublisherDAO{Db: dao.KontorDb}
var publisher = Publisher{}
switch action {
case util.AddAction:
publisher.Name = name
_, err = dao.Upsert(publisher)
case util.SaveAction:
publisher, _ = dao.FindByID(publisherid)
publisher.Name = name
err = dao.Update(publisher)
case util.DeleteAction:
publisher, _ = dao.FindByID(publisherid)
err = dao.Delete(publisher)
}
if err == nil {
c.Redirect(http.StatusTemporaryRedirect, "/library/publisher")
} else {
c.HTML(http.StatusBadRequest, "library/publisher.html", gin.H{
"ErrorTitle": "Publisher Creation Failed",
"ErrorMessage": err.Error()})
}
}
+22
View File
@@ -0,0 +1,22 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"github.com/gin-gonic/gin"
)
// GetRoutes returns all routes for library related data.
func GetRoutes(router *gin.Engine) {
libraryRoutes := router.Group("/library")
{
libraryRoutes.GET("/", auth.EnsureLoggedIn(), showBookList)
libraryRoutes.GET("/book", auth.EnsureLoggedIn(), showBookList)
libraryRoutes.GET("/author", auth.EnsureLoggedIn(), showAuthorList)
libraryRoutes.GET("/publisher", auth.EnsureLoggedIn(), showPublisherList)
libraryRoutes.POST("/publisher", auth.EnsureLoggedIn(), showPublisherList)
libraryRoutes.GET("/publisher/view/:publisher_id", auth.EnsureLoggedIn(), showPublisherDetails)
libraryRoutes.POST("/publisher/validate", auth.EnsureLoggedIn(), validatePublisherDetails)
libraryRoutes.GET("/publisher/create", auth.EnsureLoggedIn(), showPublisherCreation)
}
}
+24
View File
@@ -0,0 +1,24 @@
package library
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"github.com/gin-gonic/gin"
)
func showAuthorList(c *gin.Context) {
var authorDao = AuthorDAO{Db: dao.KontorDb}
if authors, err := authorDao.FindAll(); err == nil {
util.Render(c, gin.H{"title": "Author List", "payload": authors}, "library/authors.html")
}
}
func showBookList(c *gin.Context) {
var bookDao = BookDAO{Db: dao.KontorDb}
if books, err := bookDao.FindAll(); err == nil {
util.Render(c, gin.H{"title": "Book List", "payload": books}, "library/books.html")
} else {
util.Render(c, gin.H{"title": "Kontor", "payload": nil}, "kontor/index.html")
}
}
+13
View File
@@ -0,0 +1,13 @@
package office
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"github.com/gin-gonic/gin"
)
// GetRoutes returns all routes for office related data.
func GetRoutes(router *gin.Engine) {
officeRoutes := router.Group("/office")
officeRoutes.GET("/", auth.EnsureLoggedIn(), showIndexPage)
}
+11
View File
@@ -0,0 +1,11 @@
package office
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"github.com/gin-gonic/gin"
)
func showIndexPage(c *gin.Context) {
util.Render(c, gin.H{"title": "Home Office", "payload": nil}, "office/index.html")
}
+25
View File
@@ -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
}
+20
View File
@@ -0,0 +1,20 @@
package setup
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/tysc"
"log"
)
// CheckTradeYourSportsCardsData checks if the TYSC releated data is available.
func CheckTradeYourSportsCardsData() {
log.Printf("Check data for TradeYourSportsCards module")
var sport = tysc.SportDAO{Db: dao.KontorDb}
sport.Upsert(tysc.Sport{Name: "Football"})
football, _ := sport.FindByName("Football")
sport.Upsert(tysc.Sport{Name: "Baseball"})
sport.Upsert(tysc.Sport{Name: "Basketball"})
sport.Upsert(tysc.Sport{Name: "Hockey"})
var position = tysc.PositionDAO{Db: dao.KontorDb}
position.Upsert(tysc.Position{Name: "WR", Description: "Wide Receiver", Sport: football.ID})
}
+38
View File
@@ -0,0 +1,38 @@
package setup
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/admin"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/comics"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/library"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/office"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/tradingcards"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/tysc"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"github.com/gin-gonic/gin"
)
// InitializeRoutes setup the routes for Kontor 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)
comics.GetRoutes(router)
library.GetRoutes(router)
office.GetRoutes(router)
tradingcards.GetRoutes(router)
tysc.GetRoutes(router)
}
+15
View File
@@ -0,0 +1,15 @@
package setup
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
)
// CleanupSessions removes all sessions from database.
func CleanupSessions() {
sessionDao := auth.SessionDAO{Db: dao.KontorDb}
sessions, _ := sessionDao.FindAll()
for _, session := range sessions {
sessionDao.Delete(session)
}
}
+20
View File
@@ -0,0 +1,20 @@
package setup
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/admin"
"gitlab.thpeetz.de/kontor/kontor-go/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.KontorDb}
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)
}
}
+13
View File
@@ -0,0 +1,13 @@
package tradingcards
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"github.com/gin-gonic/gin"
)
// GetRoutes returns all routes for tradingcards related data.
func GetRoutes(router *gin.Engine) {
tradingCardsRoutes := router.Group("/tradingcards")
tradingCardsRoutes.GET("/", auth.EnsureLoggedIn(), showIndexPage)
}
+11
View File
@@ -0,0 +1,11 @@
package tradingcards
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/util"
"github.com/gin-gonic/gin"
)
func showIndexPage(c *gin.Context) {
util.Render(c, gin.H{"title": "Trading Cards", "payload": nil}, "tradingcards/index.html")
}
+20
View File
@@ -0,0 +1,20 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// Card defines the data model for TYSC cards.
type Card struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Player bson.ObjectId `json:"player" bson:"player,omitempty"`
Team bson.ObjectId `json:"team" bson:"team,omitempty"`
Manufacturer bson.ObjectId `json:"manufacturer" bson:"manufacturer,omitempty"`
CardSet bson.ObjectId `json:"cardset" bson:"cardset,omitempty"`
ParallelSet bson.ObjectId `json:"parallelset" bson:"paralelset,omitempty"`
InsertSet bson.ObjectId `json:"insertset" bson:"insertset,omitempty"`
Rookie bool `json:"rookie" bson:"rookie,omitempty"`
Year int `json:"year" bson:"year,omitempty"`
Number int `json:"number" bson:"number,omitempty"`
Model string `json:"model" bson:"model,omitempty"`
}
+66
View File
@@ -0,0 +1,66 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// CardDAO extends the type BaseDAO.
type CardDAO struct {
Db dao.BaseDAO
}
const (
// CARDCOLLECTION defines the collection name for storing cards.
CARDCOLLECTION = "card"
// CARDMODEL defines the name of the card data model.
CARDMODEL = "kontor.tysc.card"
)
// FindAll retrieves the list of cards from the database.
func (m *CardDAO) FindAll() ([]Card, error) {
m.Db.Connect()
var cards []Card
err := m.Db.MongoDb.C(CARDCOLLECTION).Find(bson.M{"model": CARDMODEL}).All(&cards)
return cards, err
}
// FindByID returns an card with given id or returns the error.
func (m *CardDAO) FindByID(id string) (Card, error) {
m.Db.Connect()
var card Card
err := m.Db.MongoDb.C(CARDCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&card)
return card, err
}
// Insert a card into database.
func (m *CardDAO) Insert(card Card) error {
m.Db.Connect()
card.Model = CARDMODEL
err := m.Db.MongoDb.C(CARDCOLLECTION).Insert(&card)
return err
}
// Upsert a card into database.
func (m *CardDAO) Upsert(card Card) (*mgo.ChangeInfo, error) {
m.Db.Connect()
card.Model = CARDMODEL
info, err := m.Db.MongoDb.C(CARDCOLLECTION).Upsert(bson.M{"number": card.Number}, &card)
return info, err
}
// Update an existing card.
func (m *CardDAO) Update(card Card) error {
m.Db.Connect()
err := m.Db.MongoDb.C(CARDCOLLECTION).UpdateId(card.ID, &card)
return err
}
// Delete an existing card.
func (m *CardDAO) Delete(card Card) error {
m.Db.Connect()
err := m.Db.MongoDb.C(CARDCOLLECTION).Remove(&card)
return err
}
+110
View File
@@ -0,0 +1,110 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var cardModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Player", "string"},
{"Team", "string"},
{"Manufacturer", "string"},
{"CardSet", "string"},
{"ParallelSet", "string"},
{"InsertSet", "string"},
{"Rookie", "bool"},
{"Year", "int"},
{"Number", "int"},
{"Model", "string"},
}
func TestCardModel(t *testing.T) {
m := Card{}
if reflect.TypeOf(m).NumField() != len(cardModelTestTable) {
t.Fail()
}
for index, testData := range cardModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListCards(t *testing.T) {
var (
cardDao = CardDAO{Db: dao.TestDb}
)
cards, err := cardDao.FindAll()
if err != nil {
t.Fail()
}
if len(cards) != 0 {
t.Fail()
}
}
func TestInsertCard(t *testing.T) {
var (
cardDao = CardDAO{Db: dao.TestDb}
card = Card{}
cards []Card
)
card.ID = bson.NewObjectId()
card.Number = 1
err := cardDao.Insert(card)
if err != nil {
t.Fail()
}
cards, err = cardDao.FindAll()
if err != nil {
t.Fail()
}
if len(cards) != 1 {
t.Fail()
}
}
func TestUpsertCard(t *testing.T) {
var (
cardDao = CardDAO{Db: dao.TestDb}
card = Card{}
)
card.ID = bson.NewObjectId()
card.Number = 2
cardDao.Upsert(card)
cards, err := cardDao.FindAll()
if err != nil {
t.Fail()
}
if len(cards) != 2 {
t.Fail()
}
}
func TestDeleteCard(t *testing.T) {
var (
cardDao = CardDAO{Db: dao.TestDb}
)
cards, err := cardDao.FindAll()
if err != nil {
t.Fail()
}
for _, card := range cards {
cardDao.Delete(card)
}
cards, err = cardDao.FindAll()
if err != nil {
t.Fail()
}
if len(cards) != 0 {
t.Fail()
}
}
+13
View File
@@ -0,0 +1,13 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// CardSet defines the data model for TYSC card sets with id, name and manufacturer.
type CardSet struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Manufacturer bson.ObjectId `json:"manufacturer" bson:"manufacturer,omitempty"`
Model string `json:"model" bson:"model,omitempty"`
}
+82
View File
@@ -0,0 +1,82 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// CardSetDAO extends the type BaseDAO.
type CardSetDAO struct {
Db dao.BaseDAO
}
const (
// CARDSETCOLLECTION defines the collection name for storing cards sets.
CARDSETCOLLECTION = "cardSet"
// CARDSETMODEL defines the name of the card set data model.
CARDSETMODEL = "kontor.tysc.cardSet"
)
// FindAll retrieves the list of card sets from the database.
func (m *CardSetDAO) FindAll() ([]CardSet, error) {
m.Db.Connect()
var cardSets []CardSet
err := m.Db.MongoDb.C(CARDSETCOLLECTION).Find(bson.M{"model": CARDSETMODEL}).All(&cardSets)
return cardSets, err
}
// FindByID returns a card set with given id or returns the error.
func (m *CardSetDAO) FindByID(id string) (CardSet, error) {
m.Db.Connect()
var cardSet CardSet
err := m.Db.MongoDb.C(CARDSETCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&cardSet)
return cardSet, err
}
// FindByManufacturer returns a card set with given manufacturer or returns the error.
func (m *CardSetDAO) FindByManufacturer(manufacturer string) ([]CardSet, error) {
m.Db.Connect()
var cardSets []CardSet
err := m.Db.MongoDb.C(CARDSETCOLLECTION).Find(bson.M{"model": CARDSETMODEL, "manufacturer": bson.ObjectIdHex(manufacturer)}).All(&cardSets)
return cardSets, err
}
// FindByName returns a card set with given name or returns the error.
func (m *CardSetDAO) FindByName(name string) (CardSet, error) {
m.Db.Connect()
var cardSet CardSet
err := m.Db.MongoDb.C(CARDSETCOLLECTION).Find(bson.M{"name": name, "model": CARDSETMODEL}).One(&cardSet)
return cardSet, err
}
// Insert an card set into database.
func (m *CardSetDAO) Insert(cardSet CardSet) error {
m.Db.Connect()
cardSet.Model = CARDSETMODEL
err := m.Db.MongoDb.C(CARDSETCOLLECTION).Insert(&cardSet)
return err
}
// Upsert an card set into database.
func (m *CardSetDAO) Upsert(cardSet CardSet) (*mgo.ChangeInfo, error) {
m.Db.Connect()
cardSet.Model = CARDSETMODEL
info, err := m.Db.MongoDb.C(CARDSETCOLLECTION).Upsert(bson.M{"name": cardSet.Name}, &cardSet)
return info, err
}
// Update an existing card set.
func (m *CardSetDAO) Update(cardSet CardSet) error {
m.Db.Connect()
err := m.Db.MongoDb.C(CARDSETCOLLECTION).UpdateId(cardSet.ID, &cardSet)
return err
}
// Delete an existing card set.
func (m *CardSetDAO) Delete(cardSet CardSet) error {
m.Db.Connect()
err := m.Db.MongoDb.C(CARDSETCOLLECTION).Remove(&cardSet)
return err
}
+103
View File
@@ -0,0 +1,103 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var cardsetModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Manufacturer", "string"},
{"Model", "string"},
}
func TestCardSetModel(t *testing.T) {
m := CardSet{}
if reflect.TypeOf(m).NumField() != len(cardsetModelTestTable) {
t.Fail()
}
for index, testData := range cardsetModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListCardSets(t *testing.T) {
var (
cardsetDao = CardSetDAO{Db: dao.TestDb}
)
cardSets, err := cardsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(cardSets) != 0 {
t.Fail()
}
}
func TestInsertCardSet(t *testing.T) {
var (
cardsetDao = CardSetDAO{Db: dao.TestDb}
cardSet = CardSet{}
cardSets []CardSet
)
cardSet.ID = bson.NewObjectId()
cardSet.Name = "test"
err := cardsetDao.Insert(cardSet)
if err != nil {
t.Fail()
}
cardSets, err = cardsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(cardSets) != 1 {
t.Fail()
}
}
func TestUpsertCardSet(t *testing.T) {
var (
cardsetDao = CardSetDAO{Db: dao.TestDb}
cardSet = CardSet{}
)
cardSet.ID = bson.NewObjectId()
cardSet.Name = "test2"
cardsetDao.Upsert(cardSet)
cardSets, err := cardsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(cardSets) != 2 {
t.Fail()
}
}
func TestDeleteCardSet(t *testing.T) {
var (
cardsetDao = CardSetDAO{Db: dao.TestDb}
)
cardSets, err := cardsetDao.FindAll()
if err != nil {
t.Fail()
}
for _, cardSet := range cardSets {
cardsetDao.Delete(cardSet)
}
cardSets, err = cardsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(cardSets) != 0 {
t.Fail()
}
}
+13
View File
@@ -0,0 +1,13 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// InsertSet defines the data model for TYSC inserts sets with id, name and manufacturer.
type InsertSet struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Manufacturer bson.ObjectId `json:"manufacturer" bson:"manufacturer,omitempty"`
Model string `json:"model" bson:"model,omitempty"`
}
+82
View File
@@ -0,0 +1,82 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// InsertSetDAO extends the type BaseDAO.
type InsertSetDAO struct {
Db dao.BaseDAO
}
const (
// INSERTSETCOLLECTION defines the collection name for storing insert sets.
INSERTSETCOLLECTION = "insertSet"
// INSERTSETMODEL defines the name of the insert set data model.
INSERTSETMODEL = "kontor.tysc.insertSet"
)
// FindAll retrieves the list of cards from the database.
func (m *InsertSetDAO) FindAll() ([]InsertSet, error) {
m.Db.Connect()
var insertSets []InsertSet
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).Find(bson.M{"model": INSERTSETMODEL}).All(&insertSets)
return insertSets, err
}
// FindByID returns an card with given id or returns the error.
func (m *InsertSetDAO) FindByID(id string) (InsertSet, error) {
m.Db.Connect()
var insertSet InsertSet
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&insertSet)
return insertSet, err
}
// FindByManufacturer returns a insert set with given manufacturer or returns the error.
func (m *InsertSetDAO) FindByManufacturer(manufacturer string) ([]InsertSet, error) {
m.Db.Connect()
var insertSets []InsertSet
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).Find(bson.M{"model": INSERTSETMODEL, "manufacturer": bson.ObjectIdHex(manufacturer)}).All(&insertSets)
return insertSets, err
}
// FindByName returns a insert set with given name or returns the error.
func (m *InsertSetDAO) FindByName(name string) (InsertSet, error) {
m.Db.Connect()
var insertSet InsertSet
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).Find(bson.M{"name": name, "model": INSERTSETMODEL}).One(&insertSet)
return insertSet, err
}
// Insert an insert set into database.
func (m *InsertSetDAO) Insert(insertSet InsertSet) error {
m.Db.Connect()
insertSet.Model = INSERTSETMODEL
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).Insert(&insertSet)
return err
}
// Upsert an insert set into database.
func (m *InsertSetDAO) Upsert(insertSet InsertSet) (*mgo.ChangeInfo, error) {
m.Db.Connect()
insertSet.Model = INSERTSETMODEL
info, err := m.Db.MongoDb.C(INSERTSETCOLLECTION).Upsert(bson.M{"name": insertSet.Name}, &insertSet)
return info, err
}
// Update an existing insert set.
func (m *InsertSetDAO) Update(insertSet InsertSet) error {
m.Db.Connect()
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).UpdateId(insertSet.ID, &insertSet)
return err
}
// Delete an existing insert set.
func (m *InsertSetDAO) Delete(insertSet InsertSet) error {
m.Db.Connect()
err := m.Db.MongoDb.C(INSERTSETCOLLECTION).Remove(&insertSet)
return err
}
+103
View File
@@ -0,0 +1,103 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var insertsetModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Manufacturer", "string"},
{"Model", "string"},
}
func TestInsertSetModel(t *testing.T) {
m := InsertSet{}
if reflect.TypeOf(m).NumField() != len(insertsetModelTestTable) {
t.Fail()
}
for index, testData := range insertsetModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListInsertSets(t *testing.T) {
var (
insertsetDao = InsertSetDAO{Db: dao.TestDb}
)
insertSets, err := insertsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(insertSets) != 0 {
t.Fail()
}
}
func TestInsertInsertSet(t *testing.T) {
var (
insertsetDao = InsertSetDAO{Db: dao.TestDb}
insertSet = InsertSet{}
insertSets []InsertSet
)
insertSet.ID = bson.NewObjectId()
insertSet.Name = "test"
err := insertsetDao.Insert(insertSet)
if err != nil {
t.Fail()
}
insertSets, err = insertsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(insertSets) != 1 {
t.Fail()
}
}
func TestUpsertInsertSet(t *testing.T) {
var (
insertsetDao = InsertSetDAO{Db: dao.TestDb}
insertSet = InsertSet{}
)
insertSet.ID = bson.NewObjectId()
insertSet.Name = "test2"
insertsetDao.Upsert(insertSet)
insertSets, err := insertsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(insertSets) != 2 {
t.Fail()
}
}
func TestDeleteInsertSet(t *testing.T) {
var (
insertsetDao = InsertSetDAO{Db: dao.TestDb}
)
insertSets, err := insertsetDao.FindAll()
if err != nil {
t.Fail()
}
for _, insertSet := range insertSets {
insertsetDao.Delete(insertSet)
}
insertSets, err = insertsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(insertSets) != 0 {
t.Fail()
}
}
+12
View File
@@ -0,0 +1,12 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// Manufacturer defines the data model for TYSC manufacturers with id, and name.
type Manufacturer struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Model string `json:"model" bson:"model,omitempty"`
}
+74
View File
@@ -0,0 +1,74 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// ManufacturerDAO extends the type BaseDAO.
type ManufacturerDAO struct {
Db dao.BaseDAO
}
const (
// MANUFACTURERCOLLECTION defines the collection name for storing manufacturers.
MANUFACTURERCOLLECTION = "manufacturer"
// MANUFACTURERMODEL defines the name of the manufacturer data model.
MANUFACTURERMODEL = "kontor.tysc.manufacturer"
)
// FindAll retrieves the list of manufacturers from the database.
func (m *ManufacturerDAO) FindAll() ([]Manufacturer, error) {
m.Db.Connect()
var manufacturers []Manufacturer
err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).Find(bson.M{"model": MANUFACTURERMODEL}).All(&manufacturers)
return manufacturers, err
}
// FindByID returns a manufacturer with given id or returns the error.
func (m *ManufacturerDAO) FindByID(id string) (Manufacturer, error) {
m.Db.Connect()
var manufacturer Manufacturer
err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&manufacturer)
return manufacturer, err
}
// FindByName returns a manufacturer with given name or returns the error.
func (m *ManufacturerDAO) FindByName(name string) (Manufacturer, error) {
m.Db.Connect()
var manufacturer Manufacturer
err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).Find(bson.M{"name": name, "model": MANUFACTURERMODEL}).One(&manufacturer)
return manufacturer, err
}
// Insert a manufacturer into database.
func (m *ManufacturerDAO) Insert(manufacturer Manufacturer) error {
m.Db.Connect()
manufacturer.Model = MANUFACTURERMODEL
err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).Insert(&manufacturer)
return err
}
// Upsert a manufacturer into database.
func (m *ManufacturerDAO) Upsert(manufacturer Manufacturer) (*mgo.ChangeInfo, error) {
m.Db.Connect()
manufacturer.Model = MANUFACTURERMODEL
info, err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).Upsert(bson.M{"name": manufacturer.Name}, &manufacturer)
return info, err
}
// Update an existing manufacturer.
func (m *ManufacturerDAO) Update(manufacturer Manufacturer) error {
m.Db.Connect()
err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).UpdateId(manufacturer.ID, &manufacturer)
return err
}
// Delete an existing manufacturer.
func (m *ManufacturerDAO) Delete(manufacturer Manufacturer) error {
m.Db.Connect()
err := m.Db.MongoDb.C(MANUFACTURERCOLLECTION).Remove(&manufacturer)
return err
}
+102
View File
@@ -0,0 +1,102 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var manufacturerModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Model", "string"},
}
func TestManufacturerModel(t *testing.T) {
m := Manufacturer{}
if reflect.TypeOf(m).NumField() != len(manufacturerModelTestTable) {
t.Fail()
}
for index, testData := range manufacturerModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListManufacturers(t *testing.T) {
var (
manufacturerDao = ManufacturerDAO{Db: dao.TestDb}
)
manufacturers, err := manufacturerDao.FindAll()
if err != nil {
t.Fail()
}
if len(manufacturers) != 0 {
t.Fail()
}
}
func TestInsertManufacturer(t *testing.T) {
var (
manufacturerDao = ManufacturerDAO{Db: dao.TestDb}
manufacturer = Manufacturer{}
manufacturers []Manufacturer
)
manufacturer.ID = bson.NewObjectId()
manufacturer.Name = "test"
err := manufacturerDao.Insert(manufacturer)
if err != nil {
t.Fail()
}
manufacturers, err = manufacturerDao.FindAll()
if err != nil {
t.Fail()
}
if len(manufacturers) != 1 {
t.Fail()
}
}
func TestUpsertManufacturer(t *testing.T) {
var (
manufacturerDao = ManufacturerDAO{Db: dao.TestDb}
manufacturer = Manufacturer{}
)
manufacturer.ID = bson.NewObjectId()
manufacturer.Name = "test2"
manufacturerDao.Upsert(manufacturer)
manufacturers, err := manufacturerDao.FindAll()
if err != nil {
t.Fail()
}
if len(manufacturers) != 2 {
t.Fail()
}
}
func TestDeleteManufacturer(t *testing.T) {
var (
manufacturerDao = ManufacturerDAO{Db: dao.TestDb}
)
manufacturers, err := manufacturerDao.FindAll()
if err != nil {
t.Fail()
}
for _, manufacturer := range manufacturers {
manufacturerDao.Delete(manufacturer)
}
manufacturers, err = manufacturerDao.FindAll()
if err != nil {
t.Fail()
}
if len(manufacturers) != 0 {
t.Fail()
}
}
+13
View File
@@ -0,0 +1,13 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// ParallelSet defines the data model for TYSC parallel sets with id, name and manufacturer.
type ParallelSet struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Manufacturer bson.ObjectId `json:"manufacturer" bson:"manufacturer,omitempty"`
Model string `json:"model" bson:"model,omitempty"`
}
+82
View File
@@ -0,0 +1,82 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// ParallelSetDAO extends the type BaseDAO.
type ParallelSetDAO struct {
Db dao.BaseDAO
}
const (
// PARALLELSETCOLLECTION defines the collection name for storing parallel sets.
PARALLELSETCOLLECTION = "parallelSet"
// PARALLELSETMODEL defines the name of the parallel set data model.
PARALLELSETMODEL = "kontor.tysc.parallelSet"
)
// FindAll retrieves the list of parallel sets from the database.
func (m *ParallelSetDAO) FindAll() ([]ParallelSet, error) {
m.Db.Connect()
var parallelSets []ParallelSet
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).Find(bson.M{"model": PARALLELSETMODEL}).All(&parallelSets)
return parallelSets, err
}
// FindByID returns a parallel set with given id or returns the error.
func (m *ParallelSetDAO) FindByID(id string) (ParallelSet, error) {
m.Db.Connect()
var parallelSet ParallelSet
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&parallelSet)
return parallelSet, err
}
// FindByManufacturer returns a paralle set with given manufacturer or returns the error.
func (m *ParallelSetDAO) FindByManufacturer(manufacturer string) ([]ParallelSet, error) {
m.Db.Connect()
var parallelSets []ParallelSet
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).Find(bson.M{"model": PARALLELSETMODEL, "manufacturer": bson.ObjectIdHex(manufacturer)}).All(&parallelSets)
return parallelSets, err
}
// FindByName returns a parallel set with given name or returns the error.
func (m *ParallelSetDAO) FindByName(name string) (ParallelSet, error) {
m.Db.Connect()
var parallelSet ParallelSet
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).Find(bson.M{"name": name, "model": PARALLELSETMODEL}).One(&parallelSet)
return parallelSet, err
}
// Insert a parallel set into database.
func (m *ParallelSetDAO) Insert(parallelSet ParallelSet) error {
m.Db.Connect()
parallelSet.Model = PARALLELSETMODEL
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).Insert(&parallelSet)
return err
}
// Upsert a parallel set into database.
func (m *ParallelSetDAO) Upsert(parallelSet ParallelSet) (*mgo.ChangeInfo, error) {
m.Db.Connect()
parallelSet.Model = PARALLELSETMODEL
info, err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).Upsert(bson.M{"name": parallelSet.Name}, &parallelSet)
return info, err
}
// Update an existing parallel set.
func (m *ParallelSetDAO) Update(parallelSet ParallelSet) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).UpdateId(parallelSet.ID, &parallelSet)
return err
}
// Delete an existing parallel set.
func (m *ParallelSetDAO) Delete(parallelSet ParallelSet) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PARALLELSETCOLLECTION).Remove(&parallelSet)
return err
}
+103
View File
@@ -0,0 +1,103 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var parallelsetModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Manufacturer", "string"},
{"Model", "string"},
}
func TestParallelSetModel(t *testing.T) {
m := ParallelSet{}
if reflect.TypeOf(m).NumField() != len(parallelsetModelTestTable) {
t.Fail()
}
for index, testData := range parallelsetModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListParallelSets(t *testing.T) {
var (
parallelsetDao = ParallelSetDAO{Db: dao.TestDb}
)
parallelSets, err := parallelsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(parallelSets) != 0 {
t.Fail()
}
}
func TestInsertParallelSet(t *testing.T) {
var (
parallelsetDao = ParallelSetDAO{Db: dao.TestDb}
parallelSet = ParallelSet{}
parallelSets []ParallelSet
)
parallelSet.ID = bson.NewObjectId()
parallelSet.Name = "test"
err := parallelsetDao.Insert(parallelSet)
if err != nil {
t.Fail()
}
parallelSets, err = parallelsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(parallelSets) != 1 {
t.Fail()
}
}
func TestUpsertParallelSet(t *testing.T) {
var (
parallelsetDao = ParallelSetDAO{Db: dao.TestDb}
parallelSet = ParallelSet{}
)
parallelSet.ID = bson.NewObjectId()
parallelSet.Name = "test2"
parallelsetDao.Upsert(parallelSet)
parallelSets, err := parallelsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(parallelSets) != 2 {
t.Fail()
}
}
func TestDeleteParallelSet(t *testing.T) {
var (
parallelsetDao = ParallelSetDAO{Db: dao.TestDb}
)
parallelSets, err := parallelsetDao.FindAll()
if err != nil {
t.Fail()
}
for _, parallelSet := range parallelSets {
parallelsetDao.Delete(parallelSet)
}
parallelSets, err = parallelsetDao.FindAll()
if err != nil {
t.Fail()
}
if len(parallelSets) != 0 {
t.Fail()
}
}
+13
View File
@@ -0,0 +1,13 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// Player defines the data model for TYSC players with id, first and lastname.
type Player struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Firstname string `json:"firstname" bson:"firstname"`
Lastname string `json:"lastname" bson:"lastname"`
Model string `json:"model" bson:"model,omitempty"`
}
+74
View File
@@ -0,0 +1,74 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// PlayerDAO extends the type BaseDAO.
type PlayerDAO struct {
Db dao.BaseDAO
}
const (
// PLAYERCOLLECTION defines the collection name for storing players.
PLAYERCOLLECTION = "player"
// PLAYERMODEL defines the name of the player data model.
PLAYERMODEL = "kontor.tysc.player"
)
// FindAll retrieves the list of players from the database.
func (m *PlayerDAO) FindAll() ([]Player, error) {
m.Db.Connect()
var players []Player
err := m.Db.MongoDb.C(PLAYERCOLLECTION).Find(bson.M{"model": PLAYERMODEL}).All(&players)
return players, err
}
// FindByID returns a player with given id or returns the error.
func (m *PlayerDAO) FindByID(id string) (Player, error) {
m.Db.Connect()
var player Player
err := m.Db.MongoDb.C(PLAYERCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&player)
return player, err
}
// FindByLastName returns a player with given last name or returns the error.
func (m *PlayerDAO) FindByLastName(lastname string) (Player, error) {
m.Db.Connect()
var player Player
err := m.Db.MongoDb.C(PLAYERCOLLECTION).Find(bson.M{"lastname": lastname, "model": PLAYERMODEL}).One(&player)
return player, err
}
// Insert a player into database.
func (m *PlayerDAO) Insert(player Player) error {
m.Db.Connect()
player.Model = PLAYERMODEL
err := m.Db.MongoDb.C(PLAYERCOLLECTION).Insert(&player)
return err
}
// Upsert a player into database.
func (m *PlayerDAO) Upsert(player Player) (*mgo.ChangeInfo, error) {
m.Db.Connect()
player.Model = PLAYERMODEL
info, err := m.Db.MongoDb.C(PLAYERCOLLECTION).Upsert(bson.M{"lastname": player.Lastname}, &player)
return info, err
}
// Update an existing player.
func (m *PlayerDAO) Update(player Player) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PLAYERCOLLECTION).UpdateId(player.ID, &player)
return err
}
// Delete an existing player.
func (m *PlayerDAO) Delete(player Player) error {
m.Db.Connect()
err := m.Db.MongoDb.C(PLAYERCOLLECTION).Remove(&player)
return err
}
+103
View File
@@ -0,0 +1,103 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var playerModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Firstname", "string"},
{"Lastname", "string"},
{"Model", "string"},
}
func TestPlayerModel(t *testing.T) {
m := Player{}
if reflect.TypeOf(m).NumField() != len(playerModelTestTable) {
t.Fail()
}
for index, testData := range playerModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListPlayers(t *testing.T) {
var (
playerDao = PlayerDAO{Db: dao.TestDb}
)
players, err := playerDao.FindAll()
if err != nil {
t.Fail()
}
if players != nil {
t.Fail()
}
}
func TestInsertPlayer(t *testing.T) {
var (
playerDao = PlayerDAO{Db: dao.TestDb}
player = Player{}
players []Player
)
player.ID = bson.NewObjectId()
player.Lastname = "test"
err := playerDao.Insert(player)
if err != nil {
t.Fail()
}
players, err = playerDao.FindAll()
if err != nil {
t.Fail()
}
if len(players) != 1 {
t.Fail()
}
}
func TestUpsertPlayer(t *testing.T) {
var (
playerDao = PlayerDAO{Db: dao.TestDb}
player = Player{}
)
player.ID = bson.NewObjectId()
player.Lastname = "test2"
playerDao.Upsert(player)
players, err := playerDao.FindAll()
if err != nil {
t.Fail()
}
if len(players) != 2 {
t.Fail()
}
}
func TestDeletePlayer(t *testing.T) {
var (
playerDao = PlayerDAO{Db: dao.TestDb}
)
players, err := playerDao.FindAll()
if err != nil {
t.Fail()
}
for _, player := range players {
playerDao.Delete(player)
}
players, err = playerDao.FindAll()
if err != nil {
t.Fail()
}
if len(players) != 0 {
t.Fail()
}
}
+14
View File
@@ -0,0 +1,14 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// Position defines the data model for TYSC positions with id, name, description and sport.
type Position struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Description string `json:"description" bson:"description"`
Sport bson.ObjectId `json:"sport" bson:"sport,omitempty"`
Model string `json:"model" bson:"model,omitempty"`
}
+74
View File
@@ -0,0 +1,74 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// PositionDAO extends the type BaseDAO.
type PositionDAO struct {
Db dao.BaseDAO
}
const (
// POSITIONCOLLECTION defines the collection name for storing positions.
POSITIONCOLLECTION = "position"
// POSITIONMODEL defines the name of the position data model.
POSITIONMODEL = "kontor.tysc.position"
)
// FindAll retrieves the list of positions from the database.
func (m *PositionDAO) FindAll() ([]Position, error) {
m.Db.Connect()
var positions []Position
err := m.Db.MongoDb.C(POSITIONCOLLECTION).Find(bson.M{"model": POSITIONMODEL}).All(&positions)
return positions, err
}
// FindByID returns a position with given id or returns the error.
func (m *PositionDAO) FindByID(id string) (Position, error) {
m.Db.Connect()
var position Position
err := m.Db.MongoDb.C(POSITIONCOLLECTION).FindId(bson.ObjectIdHex(id)).One(&position)
return position, err
}
// FindByName returns a position with given name or returns the error.
func (m *PositionDAO) FindByName(name string) (Position, error) {
m.Db.Connect()
var position Position
err := m.Db.MongoDb.C(POSITIONCOLLECTION).Find(bson.M{"name": name, "model": POSITIONMODEL}).One(&position)
return position, err
}
// Insert a position into database.
func (m *PositionDAO) Insert(position Position) error {
m.Db.Connect()
position.Model = POSITIONMODEL
err := m.Db.MongoDb.C(POSITIONCOLLECTION).Insert(&position)
return err
}
// Upsert a position into database.
func (m *PositionDAO) Upsert(position Position) (*mgo.ChangeInfo, error) {
m.Db.Connect()
position.Model = POSITIONMODEL
info, err := m.Db.MongoDb.C(POSITIONCOLLECTION).Upsert(bson.M{"name": position.Name}, &position)
return info, err
}
// Update an existing position.
func (m *PositionDAO) Update(position Position) error {
m.Db.Connect()
err := m.Db.MongoDb.C(POSITIONCOLLECTION).UpdateId(position.ID, &position)
return err
}
// Delete an existing position.
func (m *PositionDAO) Delete(position Position) error {
m.Db.Connect()
err := m.Db.MongoDb.C(POSITIONCOLLECTION).Remove(&position)
return err
}
+104
View File
@@ -0,0 +1,104 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/dao"
"reflect"
"testing"
"gopkg.in/mgo.v2/bson"
)
var positionModelTestTable = []struct {
name string
typeName string
}{
{"Id", "string"},
{"Name", "string"},
{"Description", "string"},
{"Sport", "string"},
{"Model", "string"},
}
func TestPositionModel(t *testing.T) {
m := Position{}
if reflect.TypeOf(m).NumField() != len(positionModelTestTable) {
t.Fail()
}
for index, testData := range positionModelTestTable {
givenType := reflect.TypeOf(m).Field(index).Type.Kind().String()
if givenType != testData.typeName {
t.Fail()
}
}
}
func TestListPositions(t *testing.T) {
var (
positionDao = PositionDAO{Db: dao.TestDb}
)
positions, err := positionDao.FindAll()
if err != nil {
t.Fail()
}
if len(positions) != 0 {
t.Fail()
}
}
func TestInsertPosition(t *testing.T) {
var (
positionDao = PositionDAO{Db: dao.TestDb}
position = Position{}
positions []Position
)
position.ID = bson.NewObjectId()
position.Name = "test"
err := positionDao.Insert(position)
if err != nil {
t.Fail()
}
positions, err = positionDao.FindAll()
if err != nil {
t.Fail()
}
if len(positions) != 1 {
t.Fail()
}
}
func TestUpsertPosition(t *testing.T) {
var (
positionDao = PositionDAO{Db: dao.TestDb}
position = Position{}
)
position.ID = bson.NewObjectId()
position.Name = "test2"
positionDao.Upsert(position)
positions, err := positionDao.FindAll()
if err != nil {
t.Fail()
}
if len(positions) != 2 {
t.Fail()
}
}
func TestDeletePosition(t *testing.T) {
var (
positionDao = PositionDAO{Db: dao.TestDb}
)
positions, err := positionDao.FindAll()
if err != nil {
t.Fail()
}
for _, position := range positions {
positionDao.Delete(position)
}
positions, err = positionDao.FindAll()
if err != nil {
t.Fail()
}
if len(positions) != 0 {
t.Fail()
}
}
+22
View File
@@ -0,0 +1,22 @@
package tysc
import (
"gitlab.thpeetz.de/kontor/kontor-go/pkg/auth"
"github.com/gin-gonic/gin"
)
// GetRoutes returns all routes for TYSC related data.
func GetRoutes(router *gin.Engine) {
tyscRoutes := router.Group("/tysc")
tyscRoutes.GET("/", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/sport", auth.EnsureLoggedIn(), showSportList)
tyscRoutes.GET("/position", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/team", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/player", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/manufacturer", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/cardset", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/parallelset", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/insertset", auth.EnsureLoggedIn(), showIndexPage)
tyscRoutes.GET("/card", auth.EnsureLoggedIn(), showIndexPage)
}
+12
View File
@@ -0,0 +1,12 @@
package tysc
import (
"gopkg.in/mgo.v2/bson"
)
// Sport defines the data model for TYSC sports with id, and name.
type Sport struct {
ID bson.ObjectId `json:"_id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Model string `json:"model" bson:"model,omitempty"`
}

Some files were not shown because too many files have changed in this diff Show More