Import kontor-flask into directory flask #46
@@ -0,0 +1,6 @@
|
||||
.idea/
|
||||
__pycache__/
|
||||
bonus/
|
||||
icons/
|
||||
icons-shadowless/
|
||||
.vscode/
|
||||
@@ -0,0 +1,36 @@
|
||||
image: gradle:8.6-jdk21-alpine
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- publish
|
||||
|
||||
# Disable the Gradle daemon for Continuous Integration servers as correctness
|
||||
# is usually a priority over speed in CI environments. Using a fresh
|
||||
# runtime for each build is more reliable since the runtime is completely
|
||||
# isolated from any previous builds.
|
||||
variables:
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
||||
|
||||
before_script:
|
||||
- GRADLE_USER_HOME="$(pwd)/.gradle"
|
||||
- export GRADLE_USER_HOME
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- cd springboot
|
||||
- gradle assemble --no-daemon
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- cd springboot
|
||||
- gradle check --no-daemon
|
||||
|
||||
publish:
|
||||
stage: publish
|
||||
script:
|
||||
- cd springboot
|
||||
- gradle --no-daemon publish -PgitlabPackageRegistryUsername=gitlab-ci-token -PgitlabPackageRegistryPassword="$CI_JOB_TOKEN"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
__pycache__/
|
||||
.idea
|
||||
@@ -0,0 +1,2 @@
|
||||
# Kontor Flask
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from kontor import create_app
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = create_app()
|
||||
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||
@@ -0,0 +1,61 @@
|
||||
from flask import Flask, render_template
|
||||
from flask_jwt_extended import JWTManager
|
||||
|
||||
from kontor import config
|
||||
from kontor.extensions import db, ma
|
||||
from logging.config import dictConfig
|
||||
|
||||
dictConfig({
|
||||
'version': 1,
|
||||
'formatters': {'default': {
|
||||
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
|
||||
}},
|
||||
'handlers': {'wsgi': {
|
||||
'class': 'logging.StreamHandler',
|
||||
'stream': 'ext://flask.logging.wsgi_errors_stream',
|
||||
'formatter': 'default'
|
||||
}},
|
||||
'root': {
|
||||
'level': 'INFO',
|
||||
'handlers': ['wsgi']
|
||||
}
|
||||
})
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
def create_app(config_class=config.Config):
|
||||
app.config.from_object(config_class)
|
||||
|
||||
db.init_app(app)
|
||||
ma.init_app(app)
|
||||
# Initialize Flask extensions here
|
||||
app.config["JWT_SECRET_KEY"] = "super-secret" # Change this!
|
||||
jwt = JWTManager(app)
|
||||
|
||||
with app.app_context():
|
||||
# db.create_all()
|
||||
db.reflect()
|
||||
|
||||
# Register blueprints here
|
||||
from kontor.main import bp as main_bp
|
||||
app.register_blueprint(main_bp)
|
||||
from kontor.comics import comics_bp
|
||||
app.register_blueprint(comics_bp, url_prefix='/comics')
|
||||
from kontor.api import api_bp
|
||||
app.register_blueprint(api_bp, url_prefix='/api/v1')
|
||||
from kontor.comics import comics_api
|
||||
app.register_blueprint(comics_api, url_prefix='/api/v1/comics')
|
||||
|
||||
from kontor.media import media_bp
|
||||
app.register_blueprint(media_bp, url_prefix='/media')
|
||||
from kontor.media import media_api
|
||||
app.register_blueprint(media_api, url_prefix='/api/v1/media')
|
||||
# from kontor.auth.auth import auth_bp
|
||||
# from kontor.cart.cart import cart_bp
|
||||
# from kontor.general.general import general_bp
|
||||
# app.register_blueprint(auth_bp)
|
||||
# app.register_blueprint(cart_bp, url_prefix='/cart')
|
||||
# app.register_blueprint(general_bp)
|
||||
|
||||
return app
|
||||
@@ -0,0 +1,5 @@
|
||||
from flask import Blueprint
|
||||
|
||||
api_bp = Blueprint('api_bp', __name__)
|
||||
|
||||
from kontor.api import routes
|
||||
@@ -0,0 +1,30 @@
|
||||
from flask import jsonify, request
|
||||
from flask_jwt_extended import jwt_required, get_jwt_identity, create_access_token
|
||||
|
||||
from kontor.api import api_bp
|
||||
|
||||
|
||||
@api_bp.route('/')
|
||||
def index():
|
||||
modules = ['comics']
|
||||
return jsonify(modules)
|
||||
|
||||
|
||||
# Create a route to authenticate your users and return JWTs. The
|
||||
# create_access_token() function is used to actually generate the JWT.
|
||||
@api_bp.route("/login", methods=["POST"])
|
||||
def login():
|
||||
username = request.json.get("username", None)
|
||||
password = request.json.get("password", None)
|
||||
if username != "test" or password != "test":
|
||||
return jsonify({"msg": "Bad username or password"}), 401
|
||||
|
||||
access_token = create_access_token(identity=username)
|
||||
return jsonify(access_token=access_token)
|
||||
|
||||
|
||||
@api_bp.route('/protected', methods=['GET'])
|
||||
@jwt_required()
|
||||
def protected():
|
||||
current_user = get_jwt_identity()
|
||||
return {'message': f'Hello, {current_user}!'}
|
||||
@@ -0,0 +1,22 @@
|
||||
import bcrypt
|
||||
from flask import session
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
|
||||
from kontor import app
|
||||
from kontor.auth.models import User
|
||||
|
||||
auth = HTTPBasicAuth()
|
||||
|
||||
|
||||
@auth.verify_password
|
||||
def verify_password(username, password):
|
||||
if username is None:
|
||||
return False
|
||||
# Add your authentication logic here
|
||||
app.logger.info("login user %s", username)
|
||||
user = User.query.filter_by(user_name=username).first()
|
||||
app.logger.info("User: %s", user)
|
||||
app.logger.info("Stored Password: '%s' Hashed Password: '%s'", user.password, bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()))
|
||||
if 'user_name' in session and session['user_name'] == username:
|
||||
return True
|
||||
return False
|
||||
@@ -0,0 +1,45 @@
|
||||
from kontor.extensions import db, ma
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
|
||||
class User(db.Model):
|
||||
# __table__ = db.metadata.tables["publisher"]
|
||||
__tablename__ = "user"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
created_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
last_modified_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
version = db.Column(db.Integer)
|
||||
enabled = db.Column(db.SmallInteger)
|
||||
email = db.Column(db.String)
|
||||
first_name = db.Column(db.String)
|
||||
last_name = db.Column(db.String)
|
||||
user_name = db.Column(db.String)
|
||||
password = db.Column(db.String)
|
||||
token = db.Column(db.String)
|
||||
token_expired = db.Column(db.SmallInteger)
|
||||
|
||||
def is_token_valid(self):
|
||||
return self.review == 'b\x01'
|
||||
|
||||
def is_user_enabled(self):
|
||||
return self.should_download == 'b\x01'
|
||||
|
||||
class Role(db.Model):
|
||||
__tablename__ = "role"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
created_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
last_modified_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
version = db.Column(db.Integer)
|
||||
name = db.Column(db.String)
|
||||
|
||||
class AuthorizationMatrix(db.Model):
|
||||
__tablename__ = "authorization_matrix"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
created_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
last_modified_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
version = db.Column(db.Integer)
|
||||
role_id = db.Column(db.String, db.ForeignKey("role.id"))
|
||||
user_id = db.Column(db.String, db.ForeignKey("user.id"))
|
||||
@@ -0,0 +1,9 @@
|
||||
from flask import Blueprint
|
||||
|
||||
comics_bp = Blueprint('comics_bp', __name__,
|
||||
template_folder='templates',
|
||||
static_folder='static', static_url_path='assets')
|
||||
comics_api = Blueprint('comics_api', __name__)
|
||||
|
||||
from kontor.comics import routes
|
||||
from kontor.comics import api
|
||||
@@ -0,0 +1,28 @@
|
||||
from flask import Blueprint, render_template, jsonify
|
||||
|
||||
from kontor.comics import comics_api
|
||||
from kontor.models import Comic, comics_schema, Publisher, comic_schema, publisher_schema, publishers_schema
|
||||
|
||||
|
||||
@comics_api.route('/')
|
||||
def index():
|
||||
comics = Comic.query.all()
|
||||
return comics_schema.dump(comics)
|
||||
|
||||
|
||||
@comics_api.route('/comic/<string:comic_id>')
|
||||
def view(comic_id):
|
||||
comic = Comic.query.get(comic_id)
|
||||
return comic_schema.dump(comic)
|
||||
|
||||
|
||||
@comics_api.route('/publisher/')
|
||||
def publisher_all():
|
||||
publishers = Publisher.query.all()
|
||||
return publishers_schema.dump(publishers)
|
||||
|
||||
|
||||
@comics_api.route('/publisher/<string:id>')
|
||||
def publisher_detail(publisher_id):
|
||||
publisher = Publisher.query.get(publisher_id)
|
||||
return publisher_schema.dump(publisher)
|
||||
@@ -0,0 +1,16 @@
|
||||
from flask import Blueprint, render_template
|
||||
|
||||
from kontor.comics import comics_bp
|
||||
from kontor.models import Comic
|
||||
|
||||
|
||||
@comics_bp.route('/')
|
||||
def index():
|
||||
comics = Comic.query.all()
|
||||
return render_template('comics/list.html', comics=comics)
|
||||
|
||||
|
||||
@comics_bp.route('/comic/<string:comic_id>')
|
||||
def view(comic_id):
|
||||
comic = Comic.query.get(comic_id)
|
||||
return render_template('comics/view.html', comic=comic)
|
||||
@@ -0,0 +1,28 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<span class="title">
|
||||
<h1>{% block title %} Comics {% endblock %}</h1>
|
||||
</span>
|
||||
<div class="comics">
|
||||
<h2>Comics Blueprint</h2>
|
||||
{% for comic in comics %}
|
||||
<div class="comic">
|
||||
<b>
|
||||
<p class="name">
|
||||
<a href="{{ url_for('comics_bp.view', comic_id=comic.id)}}">{{ comic.title }}</a>
|
||||
</p>
|
||||
</b>
|
||||
<b><p class="identifier">{{ comic.publisher.name }}</p></b>
|
||||
<div class="date">
|
||||
<h4>Created</h4>
|
||||
<p>{{ comic.created_date }}</p>
|
||||
<h4>Modified</h4>
|
||||
<p>{{ comic.last_modified_date }}</p>
|
||||
</div>
|
||||
<p>Version: {{ comic.version }}</p>
|
||||
<p>Review: {{ comic.review }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<span class="title">
|
||||
<h1>{% block title %} Comics {% endblock %}</h1>
|
||||
</span>
|
||||
<div class="comics">
|
||||
<h2>Comics Blueprint</h2>
|
||||
<div class="comic">
|
||||
<b>
|
||||
<p class="name">
|
||||
<a href="{{ url_for('comics_bp.view', comic_id=comic.id)}}">{{ comic.title }}</a>
|
||||
</p>
|
||||
</b>
|
||||
<b>
|
||||
<p class="identifier">{{ comic.id }}</p>
|
||||
</b>
|
||||
<div class="date">
|
||||
<h4>Created</h4>
|
||||
<p>{{ comic.created_date }}</p>
|
||||
<h4>Modified</h4>
|
||||
<p>{{ comic.last_modified_date }}</p>
|
||||
</div>
|
||||
<p>Version: {{ comic.version }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
import os
|
||||
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class Config:
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY')
|
||||
# SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or 'sqlite:///' + os.path.join(basedir, 'kontor.db')
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or 'mariadb+mariadbconnector://kontor:kontor@localhost/kontor'
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
@@ -0,0 +1,5 @@
|
||||
import flask_sqlalchemy
|
||||
from flask_marshmallow import Marshmallow
|
||||
|
||||
db = flask_sqlalchemy.SQLAlchemy()
|
||||
ma = Marshmallow()
|
||||
@@ -0,0 +1,5 @@
|
||||
from flask import Blueprint
|
||||
|
||||
bp = Blueprint('main', __name__)
|
||||
|
||||
from kontor.main import routes
|
||||
@@ -0,0 +1,18 @@
|
||||
from flask import render_template, session
|
||||
|
||||
from kontor import app
|
||||
from kontor.main import bp
|
||||
from kontor.auth import auth
|
||||
|
||||
|
||||
@bp.route('/')
|
||||
@auth.login_required
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
@bp.route('/logout')
|
||||
def logout():
|
||||
app.logger.info("logout")
|
||||
auth.current_user()
|
||||
session['user_name'] = None
|
||||
return render_template('index.html')
|
||||
@@ -0,0 +1,9 @@
|
||||
from flask import Blueprint
|
||||
|
||||
media_bp = Blueprint('media_bp', __name__,
|
||||
template_folder='templates',
|
||||
static_folder='static', static_url_path='assets')
|
||||
media_api = Blueprint('media_api', __name__)
|
||||
|
||||
from kontor.media import routes
|
||||
from kontor.media import api
|
||||
@@ -0,0 +1,18 @@
|
||||
from flask import Blueprint, render_template, jsonify
|
||||
|
||||
from kontor import app
|
||||
from kontor.media import media_api
|
||||
from kontor.media.models import MediaFile, mediafile_schema, mediafiles_schema
|
||||
|
||||
|
||||
@media_api.route('/')
|
||||
def mediafile_list():
|
||||
app.logger.info("get all media files")
|
||||
files = MediaFile.query.all()
|
||||
return mediafiles_schema.dump(files)
|
||||
|
||||
|
||||
@media_api.route('/mediafile/<string:mediafile_id>')
|
||||
def mediafile_detail(file_id):
|
||||
file = MediaFile.query.get(file_id)
|
||||
return mediafile_schema.dump(file)
|
||||
@@ -0,0 +1,43 @@
|
||||
from kontor.extensions import db, ma
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
|
||||
class MediaFile(db.Model):
|
||||
# __table__ = db.metadata.tables["publisher"]
|
||||
__tablename__ = "media_file"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
created_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
last_modified_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
version = db.Column(db.Integer)
|
||||
title = db.Column(db.String)
|
||||
file_name = db.Column(db.String)
|
||||
url = db.Column(db.String)
|
||||
path = db.Column(db.String)
|
||||
cloud_link = db.Column(db.String)
|
||||
review = db.Column(db.SmallInteger)
|
||||
should_download = db.Column(db.Boolean)
|
||||
|
||||
def is_review(self):
|
||||
return self.review == 'b\x00'
|
||||
|
||||
def is_download(self):
|
||||
return self.should_download == 'b\x00'
|
||||
|
||||
|
||||
class MediaFileSchema(ma.SQLAlchemySchema):
|
||||
class Meta:
|
||||
model = MediaFile
|
||||
fields = ("id", "created_date", "last_modified_date", "version", "title", "file_name", "url", "path", "cloud_link", "review", "should_download", "_links")
|
||||
|
||||
# Smart hyperlinking
|
||||
_links = ma.Hyperlinks(
|
||||
{
|
||||
"self": ma.URLFor("media_api.mediafile_detail", values=dict(mediafile_id="<id>")),
|
||||
"collection": ma.URLFor("media_api.mediafile_list"),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
mediafile_schema = MediaFileSchema()
|
||||
mediafiles_schema = MediaFileSchema(many=True)
|
||||
@@ -0,0 +1,16 @@
|
||||
from flask import Blueprint, render_template
|
||||
|
||||
from kontor.media import media_bp
|
||||
from kontor.media.models import MediaFile
|
||||
|
||||
|
||||
@media_bp.route('/')
|
||||
def mediafile_list():
|
||||
files = MediaFile.query.all()
|
||||
return render_template('media/mediafile_list.html', mediafiles=files)
|
||||
|
||||
|
||||
@media_bp.route('/mediafile/<string:mediafile_id>')
|
||||
def mediafile_detail(mediafile_id):
|
||||
mediafile = MediaFile.query.get(mediafile_id)
|
||||
return render_template('media/mediafile_detail.html', mediafile=mediafile)
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<span class="title">
|
||||
<h1>{% block title %} MediaFile {% endblock %}</h1>
|
||||
</span>
|
||||
<div class="comics">
|
||||
<h2>MediaFile Blueprint</h2>
|
||||
<div class="comic">
|
||||
<b>
|
||||
<p class="name">
|
||||
<a href="{{ url_for('media_bp.mediafile_detail', mediafile_id=mediafile.id)}}">{{ mediafile.title }}</a>
|
||||
</p>
|
||||
</b>
|
||||
<b>
|
||||
<p class="identifier">{{ mediafile.id }}</p>
|
||||
</b>
|
||||
<div class="date">
|
||||
<h4>Created</h4>
|
||||
<p>{{ mediafile.created_date }}</p>
|
||||
<h4>Modified</h4>
|
||||
<p>{{ mediafile.last_modified_date }}</p>
|
||||
</div>
|
||||
<p>Version: {{ mediafile.version }}</p>
|
||||
<p>Review: {{ mediafile.is_review() }}</p>
|
||||
<p>Should Download: {{mediafile.is_download() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<span class="title">
|
||||
<h1>{% block title %} MediaFile {% endblock %}</h1>
|
||||
</span>
|
||||
<div class="comic">
|
||||
<h2>MediaFile Blueprint</h2>
|
||||
{% for mediafile in mediafiles %}
|
||||
<div class="comic">
|
||||
<b>
|
||||
<p class="name">
|
||||
<a href="{{ url_for('media_bp.mediafile_detail', mediafile_id=mediafile.id)}}">{{ mediafile.title }}</a>
|
||||
</p>
|
||||
</b>
|
||||
<b><p class="identifier">{{ mediafile.id }}</p></b>
|
||||
<div class="date">
|
||||
<h4>Created</h4>
|
||||
<p>{{ mediafile.created_date }}</p>
|
||||
<h4>Modified</h4>
|
||||
<p>{{ mediafile.last_modified_date }}</p>
|
||||
</div>
|
||||
<p>Version: {{ mediafile.version }}</p>
|
||||
<p>Review: {{ mediafile.is_review() }}</p>
|
||||
<p>Should Download: {{ mediafile.is_download() }}</p>
|
||||
<p>Links: {{ mediafile._links }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,49 @@
|
||||
from kontor.extensions import db, ma
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
|
||||
class Publisher(db.Model):
|
||||
# __table__ = db.metadata.tables["publisher"]
|
||||
__tablename__ = "publisher"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
created_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
last_modified_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
version = db.Column(db.Integer)
|
||||
name = db.Column(db.String)
|
||||
comics = db.relationship('Comic', back_populates='publisher', lazy='dynamic')
|
||||
|
||||
|
||||
class PublisherSchema(ma.SQLAlchemySchema):
|
||||
class Meta:
|
||||
model = Publisher
|
||||
|
||||
comics = ma.List(ma.HyperlinkRelated("comics_api.index"))
|
||||
|
||||
|
||||
publisher_schema = PublisherSchema()
|
||||
publishers_schema = PublisherSchema(many=True)
|
||||
|
||||
|
||||
class Comic(db.Model):
|
||||
# __table__ = db.metadata.tables["comic"]
|
||||
__tablename__ = "comic"
|
||||
__table_args__ = {'extend_existing': True}
|
||||
id = db.Column(db.String, primary_key=True)
|
||||
created_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
last_modified_date = db.Column(db.DateTime(timezone=True), server_default=func.now())
|
||||
version = db.Column(db.Integer)
|
||||
title = db.Column(db.String)
|
||||
publisher_id = db.Column(db.String, db.ForeignKey("publisher.id"))
|
||||
publisher = db.relationship("Publisher", back_populates="comics")
|
||||
|
||||
|
||||
class ComicSchema(ma.SQLAlchemyAutoSchema):
|
||||
class Meta:
|
||||
model = Comic
|
||||
include_fk = True
|
||||
publisher = ma.HyperlinkRelated("comics_api.publisher_detail")
|
||||
|
||||
|
||||
comic_schema = ComicSchema()
|
||||
comics_schema = ComicSchema(many=True)
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %} {% endblock %} - FlaskApp</title>
|
||||
<style>
|
||||
h2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 5px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.comic {
|
||||
flex: 20%;
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
background-color: #f3f3f3;
|
||||
inline-size: 100%;
|
||||
}
|
||||
|
||||
.identifier a {
|
||||
color: #00a36f;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.date {
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
background-color: #ffffff;
|
||||
color: #004835;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: #d64161;
|
||||
font-size: 3em;
|
||||
margin-left: 50px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #00a36f;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="{{ url_for('main.index') }}">Kontor</a>
|
||||
<a href="{{ url_for('comics_bp.index') }}">Comics</a>
|
||||
<a href="{{ url_for('media_bp.mediafile_list') }}">Media</a>
|
||||
</nav>
|
||||
<hr>
|
||||
<div class="content">
|
||||
{% block content %} {% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<span class="title"><h1>{% block title %} The Home Page of Kontor {% endblock %}</h1></span>
|
||||
<div class="content">
|
||||
<h2>This is the main Flask blueprint</h2>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,89 @@
|
||||
from datetime import datetime
|
||||
|
||||
import mariadb
|
||||
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
|
||||
from PySide6.QtGui import QColor
|
||||
|
||||
|
||||
class ComicTableModel(QAbstractTableModel):
|
||||
|
||||
def __init__(self, db_config, main_window):
|
||||
super().__init__()
|
||||
self.main_window = main_window
|
||||
self._data = []
|
||||
self.status_bar = main_window.statusBar
|
||||
self.mariadb_conn = mariadb.connect(
|
||||
host=db_config['mariadb']['host'],
|
||||
port=db_config['mariadb']['port'],
|
||||
user=db_config['mariadb']['user'],
|
||||
password=db_config['mariadb']['password'],
|
||||
database=db_config['mariadb']['database']
|
||||
)
|
||||
self.refresh()
|
||||
|
||||
def refresh(self):
|
||||
data = []
|
||||
cursor = self.mariadb_conn.cursor()
|
||||
cursor.execute("SELECT id, created_date, last_modified_date, title, publisher_id FROM comic")
|
||||
rows = cursor.fetchall()
|
||||
for row in rows:
|
||||
data.append(list(row))
|
||||
self.status_bar.showMessage(f"{len(rows)} Einträge geladen", 3000)
|
||||
self._data = data
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
# The length of the outer list.
|
||||
return len(self._data)
|
||||
|
||||
def headerData(self, col, orientation, role=Qt.ItemDataRole.DisplayRole):
|
||||
if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole:
|
||||
match col:
|
||||
case 0:
|
||||
return "ID"
|
||||
case 1:
|
||||
return "Created"
|
||||
case 2:
|
||||
return "Updated"
|
||||
case 3:
|
||||
return "Title"
|
||||
case 4:
|
||||
return "Verlag"
|
||||
if orientation == Qt.Orientation.Vertical and role == Qt.ItemDataRole.DisplayRole:
|
||||
return str(col + 1)
|
||||
|
||||
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
|
||||
value = self._data[index.row()][index.column()]
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
if isinstance(value, datetime):
|
||||
return value.strftime("%Y-%m-%d %M:%M:%S")
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
if isinstance(value, bytes):
|
||||
if value == b'\x01':
|
||||
return "True"
|
||||
return "False"
|
||||
return value
|
||||
if role == Qt.ItemDataRole.DecorationRole:
|
||||
if isinstance(value, bytes):
|
||||
# print('{}: {}'.format(value, type(value)))
|
||||
if value == b'\x01':
|
||||
return self.main_window.tick
|
||||
else:
|
||||
return self.main_window.cross
|
||||
|
||||
|
||||
def columnCount(self, index=QModelIndex()):
|
||||
# The following takes the first sub-list, and returns
|
||||
# the length (only works if all rows are an equal length)
|
||||
return len(self._data[0])
|
||||
|
||||
def setData(self, index, value, role=Qt.ItemDataRole.EditRole):
|
||||
if role == Qt.ItemDataRole.EditRole:
|
||||
self._data[index.row()][index.column()] = value
|
||||
if role == Qt.ItemDataRole.CheckStateRole:
|
||||
checked = value == Qt.CheckState.Checked
|
||||
self._data[index.row()][index.column()] = checked
|
||||
return True
|
||||
|
||||
def flags(self, index):
|
||||
return Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsUserTristate
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
import mariadb
|
||||
|
||||
|
||||
class KontorDB:
|
||||
|
||||
def __init__(self, db_config):
|
||||
self.db_conn = mariadb.connect(
|
||||
host=db_config['mariadb']['host'],
|
||||
port=db_config['mariadb']['port'],
|
||||
user=db_config['mariadb']['user'],
|
||||
password=db_config['mariadb']['password'],
|
||||
database=db_config['mariadb']['database']
|
||||
)
|
||||
|
||||
def get_table_id(self, table_name):
|
||||
cursor = self.db_conn.cursor()
|
||||
cursor.execute("SELECT id, created_date, last_modified_date FROM meta_data_table WHERE table_name=?", (table_name, ))
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
return row[0]
|
||||
|
||||
def get_table_names(self) -> list:
|
||||
tables_names = []
|
||||
cursor = self.db_conn.cursor()
|
||||
cursor.execute("SELECT id, table_name from meta_data_table")
|
||||
rows = cursor.fetchall()
|
||||
for (_, table_name) in rows:
|
||||
tables_names.append(table_name)
|
||||
cursor.close()
|
||||
return tables_names
|
||||
|
||||
def get_column_meta_data(self, table_id):
|
||||
cursor = self.db_conn.cursor()
|
||||
meta_data = {}
|
||||
cursor.execute("SELECT column_name, column_order, column_label FROM meta_data_column WHERE table_id=? AND is_shown is true ORDER bY column_order", (table_id, ))
|
||||
rows = cursor.fetchall()
|
||||
order = 0
|
||||
for (column_name, column_order, column_label) in rows:
|
||||
meta_data[order] = { 'column': column_name, 'label': column_label, 'order': column_order}
|
||||
order += 1
|
||||
cursor.close()
|
||||
# print(f"retrieved {len(rows)} columns, set {len(meta_data)} headers")
|
||||
return meta_data
|
||||
|
||||
def get_filters(self, table_id):
|
||||
cursor = self.db_conn.cursor()
|
||||
filters = {}
|
||||
cursor.execute("SELECT column_name, filter_label from meta_data_column WHERE table_id=? AND show_filter is true", (table_id, ))
|
||||
rows = cursor.fetchall()
|
||||
for row in rows:
|
||||
filters[row[0]] = {'label': row[1], 'widget': None}
|
||||
cursor.close()
|
||||
# print(f"retrieved {len(rows)} filters: {filters}")
|
||||
return filters
|
||||
|
||||
def get_data(self, table_name: str, columns: dict, where_clause: str) -> list:
|
||||
data = []
|
||||
cursor = self.db_conn.cursor()
|
||||
cursor.execute(self.get_statement(table_name, columns, where_clause))
|
||||
rows = cursor.fetchall()
|
||||
print(len(rows))
|
||||
for row in rows:
|
||||
# print(f"KontorDB.get_data: {row}")
|
||||
data.append(list(row))
|
||||
cursor.close()
|
||||
print(f"KontorDB.getData: return {len(data)}")
|
||||
return data
|
||||
|
||||
def get_statement(self, table: str, header: dict, where_clause):
|
||||
columns = ""
|
||||
for index, column in header.items():
|
||||
if index > 0:
|
||||
columns += ", "
|
||||
columns += column['column']
|
||||
if len(columns) == 0:
|
||||
columns = "*"
|
||||
statement = f"SELECT {columns} FROM {table} {where_clause}"
|
||||
print(f"{statement=}")
|
||||
return statement
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QHBoxLayout, QPushButton, QFileDialog, \
|
||||
QGroupBox, QCheckBox, QComboBox
|
||||
|
||||
|
||||
class ExportKontorDialog(QDialog):
|
||||
def __init__(self, parent=None, kontor_db=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.parent = parent
|
||||
self.kontor_db = kontor_db
|
||||
self.file_name = None
|
||||
self.tables = []
|
||||
self._table_options = {}
|
||||
|
||||
self.export_options = {"JSON": {"ext": ".json"}, "YAML": {"ext": ".yaml"}, "SQLite": {"ext": ".db"}}
|
||||
self.current_export_type = "JSON"
|
||||
|
||||
buttons = (QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(buttons)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
|
||||
self.label = QLabel()
|
||||
self.label.setText("Export DB to data.json")
|
||||
|
||||
self.combo_box = QComboBox()
|
||||
self.combo_box.addItems(["JSON", "YAML", "SQLite"])
|
||||
self.combo_box.currentTextChanged.connect(self.change_export_type)
|
||||
file_layout = QHBoxLayout()
|
||||
file_layout.addWidget(self.label)
|
||||
file_layout.addWidget(self.combo_box)
|
||||
file_button = QPushButton("Select file")
|
||||
file_button.clicked.connect(self.select_file)
|
||||
file_layout.addWidget(file_button)
|
||||
layout.addLayout(file_layout)
|
||||
|
||||
for table_name in self.kontor_db.get_table_names():
|
||||
check_box = QCheckBox(table_name)
|
||||
check_box.setChecked(True)
|
||||
self.tables.append(table_name)
|
||||
self._table_options[table_name] = check_box
|
||||
check_box.stateChanged.connect(self.change_selection)
|
||||
layout.addWidget(check_box)
|
||||
layout.addWidget(self.buttonBox)
|
||||
self.setLayout(layout)
|
||||
|
||||
def change_selection(self):
|
||||
self.tables.clear()
|
||||
for (name, box) in self._table_options.items():
|
||||
if box.isChecked():
|
||||
self.tables.append(name)
|
||||
|
||||
def change_export_type(self, text):
|
||||
self.current_export_type = text
|
||||
self.label.setText(f'Export DB to data.{self.export_options[text]["ext"]}')
|
||||
|
||||
def select_file(self):
|
||||
file_dialog = QFileDialog()
|
||||
file_dialog.setFileMode(QFileDialog.FileMode.AnyFile)
|
||||
file_dialog.setDefaultSuffix(self.export_options[self.current_export_type]["ext"])
|
||||
file_dialog.setNameFilter(f'*{self.export_options[self.current_export_type]["ext"]}')
|
||||
if file_dialog.exec():
|
||||
self.file_name = file_dialog.selectedFiles()[0]
|
||||
export_file = Path(self.file_name)
|
||||
self.file_name = export_file.with_suffix(self.export_options[self.current_export_type]["ext"])
|
||||
self.label.setText(f"Export DB to {self.file_name}")
|
||||
|
||||
def get_tables_to_export(self) -> list:
|
||||
return self.tables
|
||||
|
||||
|
||||
class ImportKontorDialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.file_name = None
|
||||
|
||||
QBtn = (QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(QBtn)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
self.label = QLabel()
|
||||
self.label.setText("Import DB from data.json")
|
||||
layout = QVBoxLayout()
|
||||
file_layout = QHBoxLayout()
|
||||
file_layout.addWidget(self.label)
|
||||
file_button = QPushButton("Select file")
|
||||
file_button.clicked.connect(self.select_file)
|
||||
file_layout.addWidget(file_button)
|
||||
layout.addLayout(file_layout)
|
||||
layout.addWidget(self.buttonBox)
|
||||
self.setLayout(layout)
|
||||
|
||||
def select_file(self):
|
||||
file_dialog = QFileDialog()
|
||||
file_dialog.setFileMode(QFileDialog.FileMode.ExistingFile)
|
||||
if file_dialog.exec():
|
||||
self.file_name = file_dialog.selectedFiles()[0]
|
||||
self.label.setText(f"Import DB from {self.file_name}")
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
"""
|
||||
PyQT6 GUI for Kontor
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
from PySide6.QtGui import QAction, QIcon
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QMenu, QMessageBox, QTabWidget, QTableView
|
||||
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow
|
||||
from platformdirs import PlatformDirs
|
||||
|
||||
from comic_model import ComicTableModel
|
||||
from dialogs import ExportKontorDialog, ImportKontorDialog
|
||||
from data import KontorDB
|
||||
from model_config import KontorModelConfig
|
||||
from table_model import KontorTableModel
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
|
||||
def __init__(self, config):
|
||||
super().__init__()
|
||||
|
||||
self.tick = QIcon('res/tick.png')
|
||||
self.cross = QIcon('res/cross.png')
|
||||
self.import_icon = QIcon("res/application-import.png")
|
||||
self.export_icon = QIcon("res/application-export.png")
|
||||
self.circle_icon = QIcon("res/arrow-circle-double.png")
|
||||
|
||||
self.setWindowTitle("Kontor")
|
||||
self.setMinimumSize(800, 500)
|
||||
self._create_actions()
|
||||
self._create_menubar()
|
||||
self._create_toolbars()
|
||||
self._create_statusbar()
|
||||
|
||||
self.data = []
|
||||
self.filter = {}
|
||||
self.kontor_db = KontorDB(config)
|
||||
self.central_widget = QWidget()
|
||||
parent_layout = QVBoxLayout()
|
||||
self.central_widget.setLayout(parent_layout)
|
||||
self.tabs = QTabWidget()
|
||||
self.tabs.addTab(self.generate_data_tab("comic"), "Comics")
|
||||
self.tabs.addTab(self.generate_data_tab("media_file"), "MediaFile")
|
||||
self.tabs.currentChanged.connect(self._tab_changed)
|
||||
#label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
parent_layout.addWidget(self.tabs)
|
||||
|
||||
self.setCentralWidget(self.central_widget)
|
||||
|
||||
def _create_actions(self):
|
||||
self.newAction = QAction("&New", self)
|
||||
self.aboutAction = QAction("&Über...", self)
|
||||
self.aboutAction.triggered.connect(self.about)
|
||||
self.importAction = QAction(self.import_icon, "&Import", self)
|
||||
self.importAction.triggered.connect(self.import_from_file)
|
||||
self.exportAction = QAction(self.export_icon, "&Export", self)
|
||||
self.exportAction.triggered.connect(self.export_to_file)
|
||||
self.refreshAction = QAction(self.circle_icon, "&Refresh", self)
|
||||
self.refreshAction.triggered.connect(self.refresh)
|
||||
self.updateTitleAction = QAction("&Update Titles", self)
|
||||
self.downloadAction = QAction("&Download Videos", self)
|
||||
self.exitAction = QAction("&Beenden", self)
|
||||
self.exitAction.setShortcut("Alt+F4")
|
||||
self.exitAction.triggered.connect(self.close)
|
||||
|
||||
def _create_menubar(self):
|
||||
menu_bar = self.menuBar()
|
||||
# File menu
|
||||
file_menu = QMenu("&Datei")
|
||||
menu_bar.addMenu(file_menu)
|
||||
file_menu.addAction(self.exitAction)
|
||||
# Kontor menu
|
||||
kontor_menu = QMenu("&Kontor")
|
||||
menu_bar.addMenu(kontor_menu)
|
||||
kontor_menu.addAction(self.importAction)
|
||||
kontor_menu.addAction(self.exportAction)
|
||||
media_file_menu = QMenu("&MediaFile")
|
||||
media_file_menu.addAction(self.updateTitleAction)
|
||||
media_file_menu.addAction(self.downloadAction)
|
||||
kontor_menu.addMenu(media_file_menu)
|
||||
# Help menu
|
||||
help_menu = QMenu("&Hilfe")
|
||||
menu_bar.addMenu(help_menu)
|
||||
help_menu.addAction(self.aboutAction)
|
||||
|
||||
def _create_toolbars(self):
|
||||
# Kontor toolbar
|
||||
kontor_tool_bar = self.addToolBar("Kontor")
|
||||
kontor_tool_bar.addAction(self.importAction)
|
||||
kontor_tool_bar.addAction(self.exportAction)
|
||||
kontor_tool_bar.addAction(self.refreshAction)
|
||||
|
||||
def _create_statusbar(self):
|
||||
self.statusBar = self.statusBar()
|
||||
self.statusBar.showMessage("Kontor ready", 6000)
|
||||
self.status_label = QLabel("")
|
||||
self.statusBar.addPermanentWidget(self.status_label)
|
||||
|
||||
def about(self):
|
||||
QMessageBox.about(self.central_widget, "Über Kontor", f"Python: 3.11\nKontor: 0.1.0")
|
||||
|
||||
def import_from_file(self):
|
||||
import_dlg = ImportKontorDialog(self)
|
||||
if import_dlg.exec():
|
||||
print(f"import DB from file {import_dlg.file_name}")
|
||||
else:
|
||||
print("no nothing for import")
|
||||
pass
|
||||
|
||||
def export_to_file(self):
|
||||
export_dlg = ExportKontorDialog(self, self.kontor_db)
|
||||
if export_dlg.exec():
|
||||
print(export_dlg.get_tables_to_export())
|
||||
print(f"export DB to {export_dlg.file_name}")
|
||||
self.statusBar.showMessage(f"export DB to {export_dlg.file_name}", 3000)
|
||||
else:
|
||||
self.statusBar.showMessage("Export cancelled", 3000)
|
||||
|
||||
def refresh(self):
|
||||
self.data[self.tabs.currentIndex()].refresh()
|
||||
|
||||
def _tab_changed(self, tab_index):
|
||||
self.data[tab_index].refresh()
|
||||
|
||||
def generate_data_tab(self, table_name):
|
||||
data_tab = QWidget()
|
||||
table_config = KontorModelConfig(self.kontor_db, self, table_name)
|
||||
model = KontorTableModel(table_config)
|
||||
layout = QVBoxLayout()
|
||||
self.data.append(model)
|
||||
data_tab.setLayout(layout)
|
||||
table_view = QTableView()
|
||||
table_view.setModel(model)
|
||||
layout.addLayout(table_config.get_filter_layout())
|
||||
layout.addWidget(table_view)
|
||||
model.refresh()
|
||||
return data_tab
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
dirs = PlatformDirs("kontor")
|
||||
database_config = Path(dirs.user_config_dir, 'database-config.yaml')
|
||||
with open(database_config, 'rt') as f:
|
||||
db_config = yaml.safe_load(f.read())
|
||||
window = MainWindow(db_config)
|
||||
window.show()
|
||||
app.exec()
|
||||
@@ -0,0 +1,58 @@
|
||||
import mariadb
|
||||
from PySide6.QtWidgets import QHBoxLayout, QCheckBox
|
||||
|
||||
from data import KontorDB
|
||||
|
||||
|
||||
class KontorModelConfig:
|
||||
|
||||
def __init__(self, kontor_db: KontorDB, main_window, table_name: str):
|
||||
self.header = {}
|
||||
self.filter = {}
|
||||
self.main_window = main_window
|
||||
self._table = table_name
|
||||
self._table_id = None
|
||||
self.kontor_db = kontor_db
|
||||
self.get_table_config()
|
||||
|
||||
def get_table_id(self):
|
||||
if self._table_id is not None:
|
||||
return
|
||||
self._table_id = self.kontor_db.get_table_id(self._table)
|
||||
|
||||
def get_table_config(self):
|
||||
if self._table_id is None:
|
||||
self.get_table_id()
|
||||
self.header = self.kontor_db.get_column_meta_data(self._table_id)
|
||||
self.filter = self.kontor_db.get_filters(self._table_id)
|
||||
|
||||
def get_filter(self) -> str:
|
||||
filter_rule = ""
|
||||
# print(self.filter["download"].isChecked())
|
||||
for column, filter_info in self.filter.items():
|
||||
# print(column, filter_info)
|
||||
if filter_info['widget'].isChecked():
|
||||
# print(column, filter_info, filter_rule, len(filter_rule))
|
||||
if len(filter_rule) < 1:
|
||||
filter_rule += "WHERE "
|
||||
if len(filter_rule) > 8:
|
||||
filter_rule += " AND "
|
||||
filter_rule += f"{column} is true"
|
||||
# print(f"{filter_rule=}")
|
||||
return filter_rule
|
||||
|
||||
def get_data(self) -> list:
|
||||
data = self.kontor_db.get_data(self._table, self.header, self.get_filter())
|
||||
print(f"KontorModelConfig.get_data: {len(data)}")
|
||||
return data
|
||||
|
||||
def get_filter_layout(self) -> QHBoxLayout:
|
||||
filter_layout = QHBoxLayout()
|
||||
for column, filter_info in self.filter.items():
|
||||
filter_checkbox = QCheckBox()
|
||||
filter_checkbox.setText(filter_info['label'])
|
||||
filter_checkbox.checkStateChanged.connect(self.main_window.refresh)
|
||||
self.filter[column]['widget'] = filter_checkbox
|
||||
filter_layout.addWidget(filter_checkbox)
|
||||
filter_layout.addStretch()
|
||||
return filter_layout
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 513 B |
Binary file not shown.
|
After Width: | Height: | Size: 524 B |
Binary file not shown.
|
After Width: | Height: | Size: 836 B |
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
@@ -0,0 +1,7 @@
|
||||
from PySide6.QtGui import QIcon
|
||||
|
||||
tick = QIcon('tick.png')
|
||||
cross = QIcon('cross.png')
|
||||
import_icon = QIcon("application-import.png")
|
||||
export_icon = QIcon("application-export.png")
|
||||
circle_icon = QIcon("arrow-circle-double.png")
|
||||
@@ -0,0 +1,83 @@
|
||||
from datetime import datetime
|
||||
|
||||
from PySide6.QtCore import QAbstractTableModel, QModelIndex
|
||||
from PySide6.QtGui import Qt
|
||||
|
||||
from model_config import KontorModelConfig
|
||||
|
||||
|
||||
class KontorTableModel(QAbstractTableModel):
|
||||
|
||||
def __init__(self, model_config: KontorModelConfig):
|
||||
super().__init__()
|
||||
self._main_window = model_config.main_window
|
||||
self._config = model_config
|
||||
self._data = []
|
||||
|
||||
def refresh(self):
|
||||
data = self._config.get_data()
|
||||
count = 0
|
||||
# print(data)
|
||||
if data is not None:
|
||||
self.beginResetModel()
|
||||
self._data.clear()
|
||||
self._data = data
|
||||
self.endResetModel()
|
||||
count = len(data)
|
||||
# print(data)
|
||||
# print(self._data)
|
||||
self.layoutChanged.emit()
|
||||
self._main_window.statusBar.showMessage(f"{count} Einträge geladen", 3000)
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
# The length of the outer list.
|
||||
if self._data is None:
|
||||
return 0
|
||||
return len(self._data)
|
||||
|
||||
def headerData(self, col, orientation, role=Qt.ItemDataRole.DisplayRole):
|
||||
if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole:
|
||||
return self._config.header[col]['label']
|
||||
if orientation == Qt.Orientation.Vertical and role == Qt.ItemDataRole.DisplayRole:
|
||||
return str(col+1)
|
||||
|
||||
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
|
||||
if self._data is None:
|
||||
return None
|
||||
value = self._data[index.row()][index.column()]
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
# print('{}: {}'.format(value, type(value)))
|
||||
if isinstance(value, datetime):
|
||||
return value.strftime("%Y-%m-%d %M:%M:%S")
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
if isinstance(value, bytes):
|
||||
if value == b'\x01':
|
||||
return self._main_window.tick
|
||||
else:
|
||||
return self._main_window.cross
|
||||
return str(value)
|
||||
if role == Qt.ItemDataRole.DecorationRole:
|
||||
if isinstance(value, bytes):
|
||||
# print('{}: {}'.format(value, type(value)))
|
||||
if value == b'\x01':
|
||||
return self._main_window.tick
|
||||
else:
|
||||
return self._main_window.cross
|
||||
|
||||
def columnCount(self, index=QModelIndex()):
|
||||
# The following takes the first sub-list, and returns
|
||||
# the length (only works if all rows are an equal length)
|
||||
# print(f"Header count: {len(self._config.get_header())}")
|
||||
return len(self._config.header)
|
||||
|
||||
def setData(self, index, value, role=Qt.ItemDataRole.EditRole):
|
||||
if role == Qt.ItemDataRole.EditRole:
|
||||
self._data[index.row()][index.column()] = value
|
||||
if role == Qt.ItemDataRole.CheckStateRole:
|
||||
checked = value == Qt.CheckState.Checked
|
||||
self._data[index.row()][index.column()] = checked
|
||||
return True
|
||||
|
||||
def flags(self, index):
|
||||
return Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsUserTristate
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
project kontor "Kontor" "0.1.0" 2024-12-05 +5m {
|
||||
timezone "Europe/Berlin"
|
||||
timeformat "%d.%m.%Y"
|
||||
numberformat "-" "" "" "," 1
|
||||
currencyformat "-" "" "" "," 0
|
||||
currency "EUR"
|
||||
|
||||
scenario plan "Plan" {
|
||||
scenario real "Realität"
|
||||
}
|
||||
}
|
||||
|
||||
resource gcpce "Google Cloud Compute Engine" {
|
||||
efficiency 0.0
|
||||
rate 0.25
|
||||
}
|
||||
|
||||
task flask "Kontor-Flask" {
|
||||
task import "Import repository kontor-flask into directory flask"
|
||||
}
|
||||
task springboot "Springboot Vaadin" {
|
||||
task import "Import repository kontor-spring into directory springboot"
|
||||
}
|
||||
|
||||
taskreport "Arbeitsliste" {
|
||||
formats html
|
||||
hidetask ~isleaf()
|
||||
sorttasks plan.end.up
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
.gradle/
|
||||
.settings/
|
||||
build/
|
||||
bin/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
.project
|
||||
.classpath
|
||||
.vscode/
|
||||
.idea/
|
||||
*.lock
|
||||
logs/
|
||||
frontend/generated
|
||||
frontend/index.html
|
||||
package*.json
|
||||
tsconfig.json
|
||||
types.d.ts
|
||||
node_modules/
|
||||
vite.*
|
||||
kontor*Db
|
||||
tags*
|
||||
kontorHSQLDB*
|
||||
.vs/
|
||||
.winget
|
||||
src/main/resources/application-local.properties
|
||||
src/main/resources/application-prod.properties
|
||||
src/main/resources/application-*.yml
|
||||
@@ -0,0 +1,3 @@
|
||||
# kontor-spring
|
||||
|
||||
Kontor Anwendung mit Spring Boot und Vaadin
|
||||
@@ -0,0 +1,240 @@
|
||||
buildscript {
|
||||
configurations.classpath {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'com.burgstaller' && details.requested.name == 'okhttp-digest' && details.requested.version == '1.10') {
|
||||
details.useTarget "io.github.rburgst:${details.requested.name}:1.21"
|
||||
details.because 'Dependency has moved'
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'application'
|
||||
id 'maven-publish'
|
||||
id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.0"
|
||||
id 'jvm-test-suite'
|
||||
id 'jacoco'
|
||||
id 'test-report-aggregation'
|
||||
id 'jacoco-report-aggregation'
|
||||
alias(libs.plugins.spring.boot)
|
||||
alias(libs.plugins.spring.dependencies)
|
||||
alias(libs.plugins.vaadin)
|
||||
alias(libs.plugins.lombok)
|
||||
alias(libs.plugins.asciidoctorPdf)
|
||||
alias(libs.plugins.asciidoctorConvert)
|
||||
alias(libs.plugins.asciidoctorGems)
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
ruby.gems()
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-addons") }
|
||||
}
|
||||
|
||||
sourceCompatibility = '17'
|
||||
|
||||
configurations {
|
||||
developmentOnly
|
||||
runtimeClasspath {
|
||||
extendsFrom developmentOnly
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.vaadin:vaadin-core'
|
||||
implementation 'com.vaadin:vaadin-spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
implementation 'org.springframework.security:spring-security-oauth2-jose'
|
||||
implementation 'org.springframework.security:spring-security-oauth2-resource-server'
|
||||
implementation 'com.h2database:h2'
|
||||
implementation libs.hsqldb
|
||||
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
|
||||
implementation 'com.sun.mail:javax.mail:1.6.2'
|
||||
implementation 'org.hibernate.orm:hibernate-community-dialects'
|
||||
testImplementation('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
}
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
testImplementation 'com.vaadin:vaadin-testbench-junit5'
|
||||
testImplementation 'io.projectreactor:reactor-test'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
asciidoctorGems libs.rouge
|
||||
//asciidoctorGems libs.diagram
|
||||
}
|
||||
|
||||
def pdfFile = layout.buildDirectory.file("docs/asciidocPdf/kontor-spring.pdf")
|
||||
def pdfArtifact = artifacts.add('archives', pdfFile.get().asFile) {
|
||||
type 'pdf'
|
||||
builtBy asciidoctorPdf
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
groupId = group + '.docs'
|
||||
artifactId = project.name
|
||||
artifact pdfArtifact
|
||||
}
|
||||
bootJava(MavenPublication) {
|
||||
artifact tasks.named("bootDistTar")
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
name = "gitlabPackageRegistry"
|
||||
url = uri("https://gitlab.com/api/v4/projects/64726715/packages/maven")
|
||||
credentials(PasswordCredentials)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final BUILD_DATE = new Date().format('dd.MM.yyyy').toString()
|
||||
|
||||
asciidoctorPdf {
|
||||
dependsOn asciidoctorGemsPrepare
|
||||
|
||||
baseDirFollowsSourceFile()
|
||||
|
||||
asciidoctorj {
|
||||
modules {
|
||||
diagram.use()
|
||||
}
|
||||
requires 'rouge'
|
||||
attributes 'build-gradle': file('build.gradle'),
|
||||
'endpoint-url': 'https://www.thpeetz.de',
|
||||
'source-highlighter': 'rouge',
|
||||
'imagesdir': './images',
|
||||
'toc': 'left',
|
||||
'toc-title': 'Inhaltsverzeichnis',
|
||||
'revdate': BUILD_DATE,
|
||||
'revnumber': { project.version.toString() },
|
||||
'revremark': 'Entwurf',
|
||||
'chapter-label': '',
|
||||
'icons': 'font',
|
||||
'idprefix': 'id_',
|
||||
'idseparator': '-',
|
||||
'docinfo1': ''
|
||||
}
|
||||
}
|
||||
|
||||
build.dependsOn asciidoctorPdf
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom libs.vaadin.bom.get().toString()
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass = 'de.thpeetz.kontor.Application'
|
||||
}
|
||||
|
||||
bootRun {
|
||||
args = ["--spring.profiles.active=${project.properties['profile'] ?: 'prod'}"]
|
||||
}
|
||||
|
||||
vaadin {
|
||||
productionMode = true
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
configureEach {
|
||||
useJUnitJupiter()
|
||||
dependencies {
|
||||
implementation project()
|
||||
implementation 'com.vaadin:vaadin-core'
|
||||
implementation 'com.vaadin:vaadin-spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'com.h2database:h2'
|
||||
implementation libs.hsqldb
|
||||
implementation libs.sqlite.jdbc
|
||||
//runtimeOnly 'com.mysql:mysql-connector-j'
|
||||
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
|
||||
implementation('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
}
|
||||
implementation 'org.springframework.security:spring-security-test'
|
||||
implementation 'com.vaadin:vaadin-testbench-junit5'
|
||||
implementation 'io.projectreactor:reactor-test'
|
||||
runtimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
}
|
||||
}
|
||||
test(JvmTestSuite) {
|
||||
testType = TestSuiteType.UNIT_TEST
|
||||
targets {
|
||||
all {
|
||||
testTask.configure {
|
||||
reports {
|
||||
junitXml {
|
||||
outputPerTestCase = true // defaults to false
|
||||
mergeReruns = true // defaults to false
|
||||
}
|
||||
}
|
||||
finalizedBy(jacocoTestReport)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
integrationTest(JvmTestSuite) {
|
||||
testType = "view-test"
|
||||
targets {
|
||||
all {
|
||||
testTask.configure {
|
||||
shouldRunAfter(test)
|
||||
finalizedBy(jacocoTestReport)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named('check') {
|
||||
dependsOn(testing.suites.integrationTest)
|
||||
dependsOn(testing.suites.test)
|
||||
dependsOn tasks.named('testAggregateTestReport', TestReport)
|
||||
dependsOn tasks.named('integrationTestAggregateTestReport', TestReport)
|
||||
}
|
||||
|
||||
|
||||
jacocoTestReport {
|
||||
dependsOn test, integrationTest
|
||||
reports {
|
||||
xml.required = true
|
||||
csv.required = false
|
||||
}
|
||||
}
|
||||
|
||||
reporting {
|
||||
reports {
|
||||
testAggregateTestReport(AggregateTestReport) {
|
||||
testType = TestSuiteType.UNIT_TEST
|
||||
}
|
||||
integrationTestAggregateTestReport(AggregateTestReport) {
|
||||
testType = "view-test"
|
||||
}
|
||||
integrationTestCodeCoverageReport(JacocoCoverageReport) {
|
||||
testType = "view-test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = "8.6"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
@media all and (max-width: 1100px) {
|
||||
.list-view.editing .toolbar,
|
||||
.list-view.editing .contact-grid {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
a[highlight] {
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
description='Kontor with Spring Boot'
|
||||
version=0.1.0-SNAPSHOT
|
||||
group=de.thpeetz
|
||||
@@ -0,0 +1,58 @@
|
||||
[versions]
|
||||
gradle = "8.6"
|
||||
args4j = "2.33"
|
||||
commonscli = "1.5.0"
|
||||
junit = "5.8.2"
|
||||
logback = "1.1.2"
|
||||
mockito = "1.9.5"
|
||||
picoli = "4.7.0"
|
||||
slf4j = "1.7.22"
|
||||
hsqldb = "2.7.1"
|
||||
sqlite = "3.25.2"
|
||||
spotbugs = "6.0.7"
|
||||
asciidoctor = "4.0.2"
|
||||
rouge = "3.15.0"
|
||||
#diagram = "2.2.2"
|
||||
diagram = "2.3.1"
|
||||
sonarqube = "3.3"
|
||||
cimtConventions = "1.0.0-SNAPSHOT"
|
||||
springboot = "3.2.5"
|
||||
springdependencies = "1.1.4"
|
||||
vaadin = "24.3.8"
|
||||
lombok = "8.6"
|
||||
|
||||
[libraries]
|
||||
args4j = { module = "args4j:args4j", version.ref = "args4j" }
|
||||
commonscli = { module = "commons-cli:commons-cli", version.ref = "commonscli" }
|
||||
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
||||
logbackCore = { module = "ch.qos.logback:logback-core", version.ref = "logback" }
|
||||
logbackClassic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
||||
mockito = { module = "org.mockito:mockito-all", version.ref = "mockito" }
|
||||
picocli = { module = "info.picocli:picocli", version.ref = "picoli" }
|
||||
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
hsqldb = { module = "org.hsqldb:hsqldb", version.ref = "hsqldb" }
|
||||
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }
|
||||
vaadin-bom = { module = "com.vaadin:vaadin-bom", version.ref = "vaadin" }
|
||||
asciidoctorGradleJvmGems = { module = "org.asciidoctor:asciidoctor-gradle-jvm-gems", version.ref= "asciidoctor" }
|
||||
asciidoctorGradleJvm = { module = "org.asciidoctor:asciidoctor-gradle-jvm", version.ref= "asciidoctor" }
|
||||
asciidoctorGradleJvmPdf = { module = "org.asciidoctor:asciidoctor-gradle-jvm-pdf", version.ref= "asciidoctor" }
|
||||
rouge = { module = "rubygems:rouge", version.ref = "rouge" }
|
||||
diagram = { module = "rubygems:asciidoctor-diagram", version.ref = "diagram" }
|
||||
|
||||
[bundles]
|
||||
logback = ["logbackCore", "logbackClassic"]
|
||||
|
||||
[plugins]
|
||||
spotbugs = { id = "com.github.spotbugs", version.ref = "spotbugs" }
|
||||
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
||||
asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor" }
|
||||
asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciidoctor" }
|
||||
asciidoctorGems = { id = "org.asciidoctor.jvm.gems", version.ref = "asciidoctor" }
|
||||
javaConvention = { id = "de.cimt.java-conventions", version.ref = "cimtConventions" }
|
||||
applicationConvention = { id = "de.cimt.application-conventions", version.ref = "cimtConventions" }
|
||||
libraryConvention = { id = "de.cimt.library-conventions", version.ref = "cimtConventions" }
|
||||
asciidoctorConvention = { id = "de.cimt.asciidoctor-conventions", version.ref = "cimtConventions" }
|
||||
spring-boot = { id = "org.springframework.boot", version.ref = "springboot"}
|
||||
spring-dependencies = { id = "io.spring.dependency-management", version.ref = "springdependencies" }
|
||||
vaadin = { id = "com.vaadin", version.ref = "vaadin" }
|
||||
lombok = { id = "io.freefair.lombok", version.ref = "lombok" }
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
#!/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/HEAD/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
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# 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
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
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
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
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
|
||||
|
||||
|
||||
# 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"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
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" "$@"
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
@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=.
|
||||
@rem This is normally unused
|
||||
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. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
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
|
||||
@@ -0,0 +1,24 @@
|
||||
pluginManagement {
|
||||
resolutionStrategy {
|
||||
eachPlugin {
|
||||
if (requested.id.id == 'org.springframework.boot') {
|
||||
useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
|
||||
}
|
||||
if (requested.id.id == 'org.gradle.toolchains.foojay-resolver') {
|
||||
useModule("org.gradle.toolchains.foojay-resolver-convention:0.4.0")
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven { setUrl("https://maven.vaadin.com/vaadin-prereleases") }
|
||||
maven { setUrl("https://repo.spring.io/milestone") }
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
}
|
||||
// plugins {
|
||||
// id 'com.vaadin' version "${vaadinVersion}"
|
||||
// }
|
||||
}
|
||||
|
||||
rootProject.name = 'kontor-spring'
|
||||
@@ -0,0 +1,509 @@
|
||||
= Projektbeschreibung kontor-spring: Entwicklungs- und Projekthandbuch
|
||||
:author: Thomas Peetz
|
||||
:email: <thomas.peetz@thpeetz.de>
|
||||
:doctype: book
|
||||
:sectnums:
|
||||
:sectnumlevels: 4
|
||||
:toc:
|
||||
:toclevels: 4
|
||||
:table-caption!:
|
||||
:counter: table-number: 0
|
||||
|
||||
[title="Dokumenthistorie", id="Table-{counter:table-number}", options="header"]
|
||||
|===
|
||||
| Version | Datum | Autor | Änderungsgrund / Bemerkungen
|
||||
| 1.0.0 | 16.05.2022 | Thomas Peetz | Ersterstellung
|
||||
|===
|
||||
|
||||
== Allgemeines
|
||||
|
||||
=== Zweck des Dokumentes
|
||||
|
||||
Das Entwicklungshandbuch beschreibt die Werkzeuge und die Vorgehensweise bei der Entwicklung
|
||||
im Projekt kontor-spring und der Erstellung der Dokumentation.
|
||||
|
||||
=== Verwendete Tools
|
||||
|
||||
==== Gitea
|
||||
|
||||
Für die Verwaltung des Sourcecode kommt ((Gitea))<<gitea>> zum Einsatz.
|
||||
Mit Gitea werden auch die Projektaufgaben verwaltet.
|
||||
|
||||
Das Projekt und das dazugehörige Git Repository sind unter der Adresse
|
||||
|
||||
https://gitea.thpeetz.de/kontor/kontor-spring
|
||||
|
||||
zu finden.
|
||||
|
||||
== Erstellung der Dokumentation
|
||||
|
||||
Die Dokumentation des Projektes wird mit ((Asciidoctor))<<asciidoctor>> geschrieben.
|
||||
Die Dokumente erhalten ihre Namen nach dem jeweiligen Hauptdokument.
|
||||
|
||||
=== Quellcode Verwaltung
|
||||
|
||||
Die Asciidoctor-Dateien haben die Endung `.adoc`.
|
||||
|
||||
=== Buildsystem
|
||||
|
||||
Zur Erstellung der PDF-Dateien aus den Asciidoctor-Dateien wird das Buildsystem ((Gradle))<<gradle>> verwendet.
|
||||
Die Dateien für die Dokumente liegen im Verzeichnis `src/docs/asciidoc`.
|
||||
|
||||
Der Gradle Build wird über die Datei `build.gradle` definiert.
|
||||
|
||||
|
||||
== Einführung
|
||||
|
||||
=== Zweck
|
||||
|
||||
=== Stakeholder des Systems
|
||||
|
||||
=== Systemumfang
|
||||
|
||||
==== Zielsetzung des Systems
|
||||
|
||||
=== Systemübersicht
|
||||
|
||||
==== Systemkontext
|
||||
|
||||
==== Systemarchitektur
|
||||
|
||||
==== Systemschnittstellen
|
||||
|
||||
===== Realisierte Schnittstellen
|
||||
|
||||
===== Verwendete Schnittstellen
|
||||
|
||||
==== Logisches Datenmodell
|
||||
|
||||
===== Benutzer ER-Diagramm
|
||||
|
||||
[mermaid, kontor-user-er, png]
|
||||
.Benutzer ER-Diagramm
|
||||
....
|
||||
erDiagram
|
||||
user {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string email
|
||||
boolean enabled
|
||||
string firstName
|
||||
string lastName
|
||||
string password
|
||||
string token
|
||||
boolean tokenExpired
|
||||
string userName UNIQUE
|
||||
}
|
||||
role {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
}
|
||||
authorization_matrix {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string user_id FK
|
||||
string role_id FK
|
||||
}
|
||||
module_data {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
boolean import_data
|
||||
string module_name UNIQUE
|
||||
}
|
||||
user ||--o{ authorization_matrix : "matrix"
|
||||
role ||--o{ authorization_matrix : "matrix"
|
||||
....
|
||||
|
||||
|
||||
===== Comics ER-Diagramm
|
||||
|
||||
[mermaid, kontor-comics-er, png]
|
||||
.Comics ER-Diagramm
|
||||
....
|
||||
erDiagram
|
||||
comic {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
boolean completed
|
||||
boolean currentOrder
|
||||
string title
|
||||
string publisher_id FK
|
||||
}
|
||||
volume {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
string comic_id FK
|
||||
}
|
||||
issue {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
boolean in_stock
|
||||
boolean is_read
|
||||
string issue_number
|
||||
string comic_id FK
|
||||
string volume_id FK
|
||||
}
|
||||
publisher {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
}
|
||||
artist {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
}
|
||||
story_arc {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
string comic_id FK
|
||||
}
|
||||
trade_paperback {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
int issueStart
|
||||
int issueEnd
|
||||
string name
|
||||
string comic_id FK
|
||||
}
|
||||
worktype {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
}
|
||||
comic_work {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string artist_id FK
|
||||
string comic_id FK
|
||||
string worktype_id FK
|
||||
}
|
||||
comic ||--o{ comic_work : "1"
|
||||
artist ||--o{ comic_work : "1"
|
||||
worktype ||--o{ comic-work : "1"
|
||||
publisher ||--o{ comic : "1"
|
||||
comic ||--o{ issue : "1"
|
||||
comic ||--o{ volume : "1"
|
||||
comic ||--o{ story_arc : "1"
|
||||
comic ||--o{ trade_paperback : "1"
|
||||
volume ||--o{ issue : "1"
|
||||
....
|
||||
|
||||
===== TYSC ER-Diagramm
|
||||
|
||||
[mermaid, kontor-tysc-er, png]
|
||||
.TYSC ER-Diagramm
|
||||
....
|
||||
erDiagram
|
||||
sport {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
}
|
||||
team {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
string short_name
|
||||
string sport_id FK
|
||||
}
|
||||
field_position {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
string short_name
|
||||
string sport_id FK
|
||||
}
|
||||
rooster {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
int year
|
||||
string player_id FK
|
||||
string position_id FK
|
||||
string team_id FK
|
||||
}
|
||||
player {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string first_name
|
||||
string last_name
|
||||
}
|
||||
vendor {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name
|
||||
}
|
||||
card_set {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
boolean insert_set
|
||||
string name
|
||||
boolean parallel_set
|
||||
string vendor_id FK
|
||||
}
|
||||
card {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
int cardNumber
|
||||
int year
|
||||
string card_set FK
|
||||
string rooster_id FK
|
||||
string vendor_id FK
|
||||
}
|
||||
sport ||--o{ team : "1"
|
||||
sport ||--o{ field_position : "1"
|
||||
field_position ||--o{ rooster : "1"
|
||||
player ||--o{ rooster : "1"
|
||||
team ||--o{ rooster : "1"
|
||||
vendor ||--o{ card : "1"
|
||||
card_set ||--o{ card : "1"
|
||||
rooster ||--o{ card : "1"
|
||||
....
|
||||
|
||||
===== Bookshelf ER-Diagramm
|
||||
|
||||
[mermaid, kontor-bookshelf-er, png]
|
||||
.Bookshelf ER-Diagramm
|
||||
....
|
||||
erDiagram
|
||||
article {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string title
|
||||
}
|
||||
book {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string isbn UNIQUE
|
||||
string title
|
||||
int year
|
||||
string publisher_id FK
|
||||
}
|
||||
bookshelf_publisher {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string name UNIQUE
|
||||
}
|
||||
author {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string first_name
|
||||
string last_name
|
||||
}
|
||||
article_author {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string article_id FK
|
||||
string author_id FK
|
||||
}
|
||||
book_author {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string book_id FK
|
||||
string author_id FK
|
||||
}
|
||||
publisher ||--o{ book : "1"
|
||||
article ||--o{ article_author : "1"
|
||||
author ||--o{ article_author : "1"
|
||||
book ||--o{ book_author : "1"
|
||||
author ||--o{ book_author : "1"
|
||||
....
|
||||
|
||||
===== Mail ER-Diagramm
|
||||
|
||||
[mermaid, kontor-mail-er, png]
|
||||
.Mail ER-Diagramm
|
||||
....
|
||||
erDiagram
|
||||
mail {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string subject
|
||||
string content
|
||||
datetime received_date
|
||||
datetime sent_date
|
||||
}
|
||||
mail_account {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string host
|
||||
string password
|
||||
int port
|
||||
string protocol
|
||||
boolean start_tls
|
||||
string user_name
|
||||
}
|
||||
mail_address {
|
||||
string id PK
|
||||
datetime created_date
|
||||
datetime last_modified_date
|
||||
int version
|
||||
string internet_address UNIQUE
|
||||
string personal
|
||||
string user_id FK
|
||||
}
|
||||
user ||--o{ mail_address : "1"
|
||||
....
|
||||
|
||||
==== Einschränkungen
|
||||
|
||||
== Anforderungen der Domäne
|
||||
|
||||
=== Systemfunktionen
|
||||
|
||||
==== Anwendungsfälle
|
||||
|
||||
==== Akteure
|
||||
|
||||
==== Zielgruppen
|
||||
|
||||
=== Anforderungen
|
||||
|
||||
==== Anforderungen an externe Schnittstellen
|
||||
|
||||
==== Funktionale Anforderungen
|
||||
|
||||
==== Qualitätsanforderungen
|
||||
|
||||
==== Randbedingungen
|
||||
|
||||
==== Weitere Anforderungen
|
||||
|
||||
==== Wartungs- und Supportinformationen
|
||||
|
||||
=== Verifikation
|
||||
|
||||
== Projektbeschreibung
|
||||
|
||||
=== Ausgangslage
|
||||
|
||||
//==== Rechtliche Vorgaben und Rahmenbedingungen
|
||||
//=== Rahmenbedingungen
|
||||
|
||||
//==== Vorhandene Regelungen
|
||||
|
||||
=== Projektziele
|
||||
|
||||
=== Projektabgrenzung
|
||||
|
||||
//=== Voraussichtliche Kosten
|
||||
|
||||
//=== Projektrisiken
|
||||
|
||||
//==== Produktivität
|
||||
|
||||
//==== Finanzielle Risiken
|
||||
|
||||
//==== Akzeptanz
|
||||
|
||||
== Projektorganisation
|
||||
|
||||
=== Projekt-Aufbauorganisation
|
||||
|
||||
=== Rollendefinition
|
||||
|
||||
//==== Projektauftraggeber
|
||||
|
||||
//==== Projektausschuss
|
||||
|
||||
//==== Beratung / Qualitätssicherung
|
||||
|
||||
==== Projekteiter
|
||||
|
||||
==== Projektteam
|
||||
|
||||
==== Liste der Stakeholder
|
||||
|
||||
=== Projektablauforganisation
|
||||
|
||||
==== Projekt-Phasen
|
||||
|
||||
===== Erstellung der Projektdokumentation
|
||||
|
||||
|
||||
== Verschiedenes
|
||||
|
||||
=== Erreichbarkeiten
|
||||
|
||||
[bibliography]
|
||||
== Referenzen
|
||||
|
||||
- [[[asciidoctor]]] http://asciidoctor.org
|
||||
- [[[gitea]]] http://www.gitea.org
|
||||
- [[[gradle]]] http://www.gradle.org
|
||||
- [[[jenkins]]] http://jenkins-ci.org
|
||||
|
||||
[glossary]
|
||||
== Glossar
|
||||
|
||||
[index]
|
||||
== Index
|
||||
|
||||
== Verzeichnisse
|
||||
|
||||
=== Abbildungsverzeichnis
|
||||
|
||||
=== Tabellenverzeichnis
|
||||
|
||||
<<Table-1, Tabelle 1>> <<Table-1>>
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Artist;
|
||||
|
||||
@SpringBootTest
|
||||
class ArtistViewTest {
|
||||
|
||||
@Autowired
|
||||
private ArtistView artistView;
|
||||
|
||||
@Test
|
||||
void formShownWhenArtistSelected() {
|
||||
Grid<Artist> grid = artistView.getGrid();
|
||||
Artist firstArtist = getFirstItem(grid);
|
||||
|
||||
ArtistForm form = artistView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstArtist);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstArtist.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Artist getFirstItem(Grid<Artist> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Artist> artists = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(5, count);
|
||||
return artists.get(0);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Artist;
|
||||
|
||||
@SpringBootTest
|
||||
class ArtistformTest {
|
||||
|
||||
private Artist artist1;
|
||||
private static final String ARTISTNAME= "Lee, Stan";
|
||||
|
||||
@BeforeEach
|
||||
void setupData() {
|
||||
artist1 = new Artist();
|
||||
artist1.setName(ARTISTNAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
void formFieldsPopulated() {
|
||||
ArtistForm form = new ArtistForm();
|
||||
form.setArtist(artist1);
|
||||
assertEquals(ARTISTNAME, form.name.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveEventHasCorrectValues() {
|
||||
ArtistForm form = new ArtistForm();
|
||||
Artist artist = new Artist();
|
||||
form.setArtist(artist);
|
||||
form.name.setValue(ARTISTNAME);
|
||||
|
||||
AtomicReference<Artist> savedArtistReference = new AtomicReference<>(null);
|
||||
form.addSaveListener(e -> {
|
||||
savedArtistReference.set(e.getArtist());
|
||||
});
|
||||
form.save.click();
|
||||
Artist savedArtist = savedArtistReference.get();
|
||||
assertEquals(ARTISTNAME, savedArtist.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteEventHasCorrectValues() {
|
||||
ArtistForm form = new ArtistForm();
|
||||
Artist artist = new Artist();
|
||||
form.setArtist(artist);
|
||||
form.name.setValue(ARTISTNAME);
|
||||
|
||||
AtomicReference<Artist> deletedArtistReference = new AtomicReference<>(null);
|
||||
form.addDeleteListener(e -> {
|
||||
deletedArtistReference.set(e.getArtist());
|
||||
});
|
||||
form.delete.click();
|
||||
Artist deletedArtist = deletedArtistReference.get();
|
||||
assertEquals(ARTISTNAME, deletedArtist.getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Comic;
|
||||
|
||||
@SpringBootTest
|
||||
public class ComicViewTest {
|
||||
|
||||
@Autowired
|
||||
private ComicView comicView;
|
||||
|
||||
@Test
|
||||
void formShownWhenComicSelected() {
|
||||
Grid<Comic> grid = comicView.getGrid();
|
||||
Comic firstComic = getFirstItem(grid);
|
||||
|
||||
ComicForm form = comicView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstComic);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstComic.getTitle(), form.title.getValue());
|
||||
}
|
||||
|
||||
private Comic getFirstItem(Grid<Comic> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Comic> comics = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(169, count);
|
||||
return comics.get(0);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.ComicWork;
|
||||
|
||||
@SpringBootTest
|
||||
class ComicWorkViewTest {
|
||||
|
||||
@Autowired
|
||||
private ComicWorkView comicWorkView;
|
||||
|
||||
@Test
|
||||
void formShownWhenComicSelected() {
|
||||
Grid<ComicWork> grid = comicWorkView.getGrid();
|
||||
ComicWork firstComicWork = getFirstItem(grid);
|
||||
|
||||
ComicWorkForm form = comicWorkView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstComicWork);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstComicWork.getComic(), form.comic.getValue());
|
||||
}
|
||||
|
||||
private ComicWork getFirstItem(Grid<ComicWork> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<ComicWork> comicWorks = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(18, count);
|
||||
return comicWorks.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Issue;
|
||||
|
||||
@SpringBootTest
|
||||
public class IssueViewTest {
|
||||
|
||||
@Autowired
|
||||
private IssueView issueView;
|
||||
|
||||
@Test
|
||||
void formShownWhenIssueSelected() {
|
||||
Grid<Issue> grid = issueView.getGrid();
|
||||
Issue firstIssue = getFirstItem(grid);
|
||||
|
||||
IssueForm form = issueView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstIssue);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstIssue.getIssueNumber(), form.issueNumber.getValue());
|
||||
}
|
||||
|
||||
private Issue getFirstItem(Grid<Issue> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Issue> issues = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(750, count);
|
||||
return issues.get(0);
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Publisher;
|
||||
|
||||
@SpringBootTest
|
||||
class PublisherViewTest {
|
||||
|
||||
@Autowired
|
||||
private PublisherView publisherView;
|
||||
|
||||
@Test
|
||||
void formShownWhenPublisherSelected() {
|
||||
Grid<Publisher> grid = publisherView.getGrid();
|
||||
Publisher firstPublisher = getFirstItem(grid);
|
||||
|
||||
PublisherForm form = publisherView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstPublisher);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstPublisher.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Publisher getFirstItem(Grid<Publisher> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Publisher> publishers = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(18, count);
|
||||
return publishers.get(0);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.StoryArc;
|
||||
|
||||
@SpringBootTest
|
||||
class StoryArcViewTest {
|
||||
|
||||
@Autowired
|
||||
private StoryArcView storyArcView;
|
||||
|
||||
@Test
|
||||
void formShownWhenStoryArcSelected() {
|
||||
Grid<StoryArc> grid = storyArcView.getGrid();
|
||||
StoryArc firstStoryArc = getFirstItem(grid);
|
||||
|
||||
StoryArcForm form = storyArcView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstStoryArc);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstStoryArc.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private StoryArc getFirstItem(Grid<StoryArc> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<StoryArc> storyArcs = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(3, count);
|
||||
return storyArcs.get(0);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.TradePaperback;
|
||||
import de.thpeetz.kontor.comics.data.Volume;
|
||||
|
||||
@SpringBootTest
|
||||
class TradePaperbackViewTest {
|
||||
|
||||
@Autowired
|
||||
private TradePaperbackView tradePaperbackView;
|
||||
|
||||
@Test
|
||||
void formShownWhenVolumeSelected() {
|
||||
Grid<TradePaperback> grid = tradePaperbackView.getGrid();
|
||||
|
||||
TradePaperback firstTradePaperback = getFirstItem(grid);
|
||||
|
||||
TradePaperBackForm form = tradePaperbackView.getForm();
|
||||
assertFalse(form.isVisible());
|
||||
|
||||
if (firstTradePaperback != null) {
|
||||
grid.asSingleSelect().setValue(firstTradePaperback);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstTradePaperback.getName(), form.name.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private TradePaperback getFirstItem(Grid<TradePaperback> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<TradePaperback> tradePaperbacks = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(40, count);
|
||||
return tradePaperbacks.get(0);
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Volume;
|
||||
|
||||
@SpringBootTest
|
||||
class VolumeViewTest {
|
||||
|
||||
@Autowired
|
||||
private VolumeView volumeView;
|
||||
|
||||
@Test
|
||||
void formShownWhenVolumeSelected() {
|
||||
Grid<Volume> grid = volumeView.getGrid();
|
||||
|
||||
Volume firstVolume = getFirstItem(grid);
|
||||
|
||||
VolumeForm form = volumeView.getForm();
|
||||
assertFalse(form.isVisible());
|
||||
|
||||
if (firstVolume != null) {
|
||||
grid.asSingleSelect().setValue(firstVolume);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstVolume.getName(), form.name.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Volume getFirstItem(Grid<Volume> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Volume> volumes = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(0, count);
|
||||
if (count > 0) {
|
||||
return volumes.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package de.thpeetz.kontor.comics.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Worktype;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootTest
|
||||
class WorktypeViewTest {
|
||||
|
||||
@Autowired
|
||||
private WorktypeView worktypeView;
|
||||
|
||||
@Test
|
||||
void formShownWhenWorktypeSelected() {
|
||||
Grid<Worktype> grid = worktypeView.getGrid();
|
||||
|
||||
Worktype firstWorktype = getFirstItem(grid);
|
||||
|
||||
WorktypeForm form = worktypeView.getForm();
|
||||
assertFalse(form.isVisible());
|
||||
|
||||
if (firstWorktype != null) {
|
||||
grid.asSingleSelect().setValue(firstWorktype);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstWorktype.getName(), form.name.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Worktype getFirstItem(Grid<Worktype> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Worktype> worktypes = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
log.info("found worktypes: {}", worktypes);
|
||||
assertEquals(3, count);
|
||||
return worktypes.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.CardSet;
|
||||
|
||||
@SpringBootTest
|
||||
class CardSetViewTest {
|
||||
|
||||
@Autowired
|
||||
private CardSetView cardSetView;
|
||||
|
||||
@Test
|
||||
void formShownWhenCardSetSelected() {
|
||||
Grid<CardSet> grid = cardSetView.getGrid();
|
||||
CardSet firstCardSet = getFirstItem(grid);
|
||||
|
||||
CardSetForm form = cardSetView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstCardSet);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstCardSet.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private CardSet getFirstItem(Grid<CardSet> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<CardSet> cardSets = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(15, count);
|
||||
return cardSets.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Card;
|
||||
|
||||
@SpringBootTest
|
||||
class CardViewTest {
|
||||
|
||||
@Autowired
|
||||
private CardView cardView;
|
||||
|
||||
@Test
|
||||
void formShownWhenCardSelected() {
|
||||
Grid<Card> grid = cardView.getGrid();
|
||||
Card firstCard = getFirstItem(grid);
|
||||
|
||||
CardForm form = cardView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstCard);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(String.valueOf(firstCard.getCardNumber()), form.cardNumber.getValue());
|
||||
}
|
||||
|
||||
private Card getFirstItem(Grid<Card> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Card> cards = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(10, count);
|
||||
return cards.get(0);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.FieldPosition;
|
||||
|
||||
@SpringBootTest
|
||||
class FieldPositionViewTest {
|
||||
|
||||
@Autowired
|
||||
private PositionView positionView;
|
||||
|
||||
@Test
|
||||
void formShownWhenPositionSelected() {
|
||||
Grid<FieldPosition> grid = positionView.getGrid();
|
||||
FieldPosition firstFieldPosition = getFirstItem(grid);
|
||||
|
||||
PositionForm form = positionView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstFieldPosition);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstFieldPosition.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private FieldPosition getFirstItem(Grid<FieldPosition> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<FieldPosition> positions = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(44, count);
|
||||
return positions.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Player;
|
||||
|
||||
@SpringBootTest
|
||||
class PlayerViewTest {
|
||||
|
||||
@Autowired
|
||||
private PlayerView playerView;
|
||||
|
||||
@Test
|
||||
void formShownWhenPlayerSelected() {
|
||||
Grid<Player> grid = playerView.getGrid();
|
||||
Player firstPlayer = getFirstItem(grid);
|
||||
|
||||
PlayerForm form = playerView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstPlayer);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstPlayer.getLastName(), form.lastName.getValue());
|
||||
assertEquals(firstPlayer.getFirstName(), form.firstName.getValue());
|
||||
}
|
||||
|
||||
private Player getFirstItem(Grid<Player> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Player> players = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(38, count);
|
||||
return players.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Rooster;
|
||||
|
||||
@SpringBootTest
|
||||
class RoosterViewTest {
|
||||
|
||||
@Autowired
|
||||
private RoosterView roosterView;
|
||||
|
||||
@Test
|
||||
void formShownWhenRoosterSelected() {
|
||||
Grid<Rooster> grid = roosterView.getGrid();
|
||||
Rooster firstRooster = getFirstItem(grid);
|
||||
|
||||
RoosterForm form = roosterView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstRooster);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstRooster.getYear(), form.year.getValue());
|
||||
}
|
||||
|
||||
private Rooster getFirstItem(Grid<Rooster> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Rooster> roosters = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(11, count);
|
||||
return roosters.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Sport;
|
||||
|
||||
@SpringBootTest
|
||||
class SportViewTest {
|
||||
|
||||
@Autowired
|
||||
private SportView sportView;
|
||||
|
||||
@Test
|
||||
void formShownWhenSportSelected() {
|
||||
Grid<Sport> grid = sportView.getGrid();
|
||||
Sport firstSport = getFirstItem(grid);
|
||||
|
||||
SportForm form = sportView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstSport);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstSport.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Sport getFirstItem(Grid<Sport> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Sport> sports = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(4, count);
|
||||
return sports.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Team;
|
||||
|
||||
@SpringBootTest
|
||||
class TeamViewTest {
|
||||
|
||||
@Autowired
|
||||
private TeamView teamView;
|
||||
|
||||
@Test
|
||||
void formShownWhenTeamSelected() {
|
||||
Grid<Team> grid = teamView.getGrid();
|
||||
Team firstTeam = getFirstItem(grid);
|
||||
|
||||
TeamForm form = teamView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstTeam);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstTeam.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Team getFirstItem(Grid<Team> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Team> teams = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(122, count);
|
||||
return teams.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.thpeetz.kontor.tysc.views;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
|
||||
import de.thpeetz.kontor.tysc.data.Vendor;
|
||||
|
||||
@SpringBootTest
|
||||
class VendorViewTest {
|
||||
|
||||
@Autowired
|
||||
private VendorView vendorView;
|
||||
|
||||
@Test
|
||||
void formShownWhenVendorSelected() {
|
||||
Grid<Vendor> grid = vendorView.getGrid();
|
||||
Vendor firstVendor = getFirstItem(grid);
|
||||
|
||||
VendorForm form = vendorView.getForm();
|
||||
|
||||
assertFalse(form.isVisible());
|
||||
grid.asSingleSelect().setValue(firstVendor);
|
||||
assertTrue(form.isVisible());
|
||||
assertEquals(firstVendor.getName(), form.name.getValue());
|
||||
}
|
||||
|
||||
private Vendor getFirstItem(Grid<Vendor> grid) {
|
||||
int count = grid.getListDataView().getItemCount();
|
||||
List<Vendor> vendors = grid.getListDataView().getItems().collect(Collectors.toList());
|
||||
assertEquals(9, count);
|
||||
return vendors.get(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
server.port=8085
|
||||
|
||||
spring.hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
||||
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
|
||||
spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver
|
||||
spring.datasource.url=jdbc:hsqldb:mem:itDb
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=sa
|
||||
|
||||
#spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
|
||||
#spring.datasource.driverClassName=org.sqlite.JDBC
|
||||
#spring.datasource.url=jdbc:sqlite:file:./kontorITDb?cache=shared
|
||||
#spring.datasource.username=sa
|
||||
#spring.datasource.password=sa
|
||||
|
||||
spring.jpa.defer-datasource-initialization = true
|
||||
#spring.jpa.hibernate.ddl-auto=create-drop
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=false
|
||||
spring.sql.init.mode=always
|
||||
|
||||
spring.mustache.check-template-location = false
|
||||
|
||||
logging.level.org.atmosphere=INFO
|
||||
logging.level.org.springframework.web=INFO
|
||||
logging.level.guru.springframework.controllers=DEBUG
|
||||
logging.level.org.hibernate=INFO
|
||||
logging.level.de.thpeetz=DEBUG
|
||||
|
||||
jwt.auth.secret=J6GOtcwC2NJI1l0VkHu20PacPFGTxpirBxWwynoHjsc=
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.thpeetz.kontor;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||
import com.vaadin.flow.server.PWA;
|
||||
import com.vaadin.flow.theme.Theme;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
@Slf4j
|
||||
@EnableJpaAuditing
|
||||
@SpringBootApplication
|
||||
@Theme(value = "kontor")
|
||||
@PWA(name = "Vaadin Kontor", shortName = "Kontor", offlinePath = "offline.html", offlineResources = { "images/offline.png" })
|
||||
public class Application implements AppShellConfigurator {
|
||||
|
||||
public static void main(String[] args) {
|
||||
log.info("Starting Kontor application");
|
||||
SpringApplication.run(Application.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package de.thpeetz.kontor.admin;
|
||||
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.sidenav.SideNavItem;
|
||||
import com.vaadin.flow.router.RouterLink;
|
||||
import de.thpeetz.kontor.admin.views.*;
|
||||
import de.thpeetz.kontor.comics.ComicConstants;
|
||||
import de.thpeetz.kontor.comics.views.ComicWorkView;
|
||||
|
||||
public class AdminConstants {
|
||||
|
||||
|
||||
private AdminConstants() {
|
||||
// private constructor to hide the implicit public one
|
||||
}
|
||||
|
||||
public static final String ADMIN_TITLE = "Verwaltung";
|
||||
public static final String AUTHORIZATION = "Berechtigungen";
|
||||
public static final String AUTHORIZATION_ROUTE = "/admin/authorization";
|
||||
public static final String DATA = "Daten";
|
||||
public static final String METADATA_ROUTE = "admin/metadata";
|
||||
public static final String ROLE = "Rollen";
|
||||
public static final String ROLE_ROUTE = "/admin/role";
|
||||
public static final String USER = "Benutzer";
|
||||
public static final String USER_ROUTE = "/admin/user";
|
||||
public static final String ADMIN = "admin";
|
||||
public static final String ADMIN_ROUTE = "/admin";
|
||||
|
||||
public static RouterLink getUserNavigation() {
|
||||
return new RouterLink(USER, UserView.class);
|
||||
}
|
||||
|
||||
public static RouterLink getRoleNavigation() {
|
||||
return new RouterLink(ROLE, RoleView.class);
|
||||
}
|
||||
|
||||
public static RouterLink getAuthorizationNavigation() {
|
||||
return new RouterLink(AUTHORIZATION, AuthorizationView.class);
|
||||
}
|
||||
|
||||
public static SideNavItem getAdminNavigation() {
|
||||
SideNavItem administration = new SideNavItem(ADMIN_TITLE, USER_ROUTE, VaadinIcon.GROUP.create());
|
||||
administration.addItem(new SideNavItem(USER, USER_ROUTE, VaadinIcon.USERS.create()));
|
||||
administration.addItem(new SideNavItem(ROLE, RoleView.class));
|
||||
SideNavItem data = new SideNavItem(DATA, AUTHORIZATION_ROUTE, VaadinIcon.DATABASE.create());
|
||||
data.addItem(new SideNavItem(ComicConstants.COMICWORK, ComicWorkView.class));
|
||||
data.addItem(new SideNavItem(AUTHORIZATION, AuthorizationView.class));
|
||||
data.addItem(new SideNavItem("Data Import", ModuleDataView.class));
|
||||
data.addItem(new SideNavItem("Meta Data", MetaDataView.class));
|
||||
administration.addItem(data);
|
||||
return administration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package de.thpeetz.kontor.admin;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "mail")
|
||||
public class MailProperties {
|
||||
|
||||
private String protocol;
|
||||
private String host;
|
||||
private Integer port;
|
||||
private String userName;
|
||||
private String password;
|
||||
private Boolean startTls;
|
||||
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Boolean getStartTls() {
|
||||
return startTls;
|
||||
}
|
||||
|
||||
public void setStartTls(Boolean startTls) {
|
||||
this.startTls = startTls;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("MailProperties{");
|
||||
sb.append("protocol='").append(protocol).append('\'');
|
||||
sb.append(", host='").append(host).append('\'');
|
||||
sb.append(", port=").append(port);
|
||||
sb.append(", starttls=").append(startTls);
|
||||
sb.append(", userName='").append(userName).append('\'');
|
||||
sb.append(", password='").append(password).append('\'');
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
package de.thpeetz.kontor.admin;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.*;
|
||||
import de.thpeetz.kontor.admin.services.AdminService;
|
||||
import de.thpeetz.kontor.admin.services.MetaDataService;
|
||||
import de.thpeetz.kontor.mailclient.data.MailAccount;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SetupModuleAdmin implements ApplicationListener<ContextRefreshedEvent> {
|
||||
boolean alreadySetup = false;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private AuthorizationMatrixRepository authorizationMatrixRepository;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Autowired
|
||||
private MailAccountRepository mailAccountRepository;
|
||||
|
||||
@Autowired
|
||||
private MailProperties mailProperties;
|
||||
|
||||
@Autowired
|
||||
private AdminService adminService;
|
||||
|
||||
@Autowired
|
||||
private MetaDataService metaDataService;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (alreadySetup) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create initial roles and users
|
||||
Role adminRole = adminService.addRole("ROLE_ADMIN");
|
||||
Role userRole = adminService.addRole("ROLE_USER");
|
||||
List<User> users = userRepository.findAll();
|
||||
if (users.isEmpty()) {
|
||||
User adminUser = initAdminUser();
|
||||
initMatrix(adminRole, adminUser);
|
||||
initMatrix(userRole, adminUser);
|
||||
}
|
||||
log.info("MailProperties: {}", mailProperties);
|
||||
initMail(mailProperties);
|
||||
|
||||
initMetaData();
|
||||
}
|
||||
|
||||
private void initMail(MailProperties mailProperties) {
|
||||
log.info("initMail: Host {} with User {}", mailProperties.getHost(), mailProperties.getUserName());
|
||||
if (mailProperties.getHost() == null || mailProperties.getHost().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
boolean addMailAccount = false;
|
||||
List<MailAccount> mailAccounts = mailAccountRepository.findAll();
|
||||
if (mailAccounts.isEmpty()) {
|
||||
addMailAccount = true;
|
||||
}
|
||||
for (MailAccount mailAccount : mailAccounts) {
|
||||
String accountUser = mailAccount.getUserName();
|
||||
String propertyUser = mailProperties.getUserName();
|
||||
String accountHost = mailAccount.getHost();
|
||||
String propertyHost = mailProperties.getHost();
|
||||
if (propertyHost.equals(accountHost) && propertyUser.equals(accountUser)) {
|
||||
log.debug("already configured: {}", mailAccount);
|
||||
} else {
|
||||
addMailAccount = true;
|
||||
}
|
||||
}
|
||||
if (addMailAccount) {
|
||||
log.info("add Mail Account: {}", mailProperties);
|
||||
MailAccount mailAccount = new MailAccount();
|
||||
mailAccount.setProtocol(mailProperties.getProtocol());
|
||||
mailAccount.setHost(mailProperties.getHost());
|
||||
mailAccount.setPort(mailProperties.getPort());
|
||||
mailAccount.setUserName(mailProperties.getUserName());
|
||||
mailAccount.setPassword(mailProperties.getPassword());
|
||||
mailAccount.setStartTls(mailProperties.getStartTls());
|
||||
mailAccountRepository.save(mailAccount);
|
||||
}
|
||||
}
|
||||
|
||||
private void initMatrix(Role role, User user) {
|
||||
log.info("initMatrix: Role {} for User {}", role.getName(), user.getUserName());
|
||||
Collection<AuthorizationMatrix> configuredRoles = authorizationMatrixRepository.findByUser(user);
|
||||
if (configuredRoles.stream().anyMatch(matrix -> matrix.getRole().getId().equals(role.getId()))) {
|
||||
log.info("Role {} already defined", role.getName());
|
||||
} else {
|
||||
log.info("add Role {} to User {}", role.getName(), user.getUserName());
|
||||
final AuthorizationMatrix adminMatrix = new AuthorizationMatrix();
|
||||
adminMatrix.setUser(user);
|
||||
adminMatrix.setRole(role);
|
||||
authorizationMatrixRepository.save(adminMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
private User initAdminUser() {
|
||||
log.info("initAdminUser");
|
||||
User admin = userRepository.findByUserName("admin");
|
||||
if (admin == null) {
|
||||
log.info("User admin not found, will be created.");
|
||||
admin = new User();
|
||||
admin.setFirstName("Admin");
|
||||
admin.setLastName("Administrator");
|
||||
admin.setUserName("admin");
|
||||
admin.setEmail("admin@example.org");
|
||||
admin.setPassword(passwordEncoder.encode("admin"));
|
||||
userRepository.save(admin);
|
||||
}
|
||||
return admin;
|
||||
}
|
||||
|
||||
private void initMetaData() {
|
||||
log.info("initMetaData");
|
||||
MetaDataTable mediaArticleTable = metaDataService.getTable("media_article");
|
||||
metaDataService.getColumn(mediaArticleTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "ID", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaArticleTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaArticleTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaArticleTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaArticleTable, "url", "link_url", "TEXT", "UNIQUE", 5, Boolean.TRUE, "URL", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaArticleTable, "review", "review", "BOOLEAN", null, 6, Boolean.TRUE, "Review", Boolean.TRUE, "Review");
|
||||
metaDataService.getColumn(mediaArticleTable, "title", "title", "TEXT", null, 7, Boolean.TRUE, "Title", Boolean.FALSE, null);
|
||||
MetaDataTable mediaVideoTable = metaDataService.getTable("media_video");
|
||||
metaDataService.getColumn(mediaVideoTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "ID", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "Version", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "url", "link_url", "TEXT", "UNIQUE", 5, Boolean.TRUE, "URL", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "review", "review", "BOOLEAN", null, 6, Boolean.TRUE, "Review", Boolean.TRUE, "Review");
|
||||
metaDataService.getColumn(mediaVideoTable, "should_download", "should_download", "BOOLEAN", null, 7, Boolean.TRUE, "Download", Boolean.TRUE, "Download");
|
||||
metaDataService.getColumn(mediaVideoTable, "title", "title", "TEXT", null, 8, Boolean.TRUE, "Title", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "file_name", "file_name", "TEXT", null, 9, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "path", "path", "TEXT", null, 10, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaVideoTable, "cloud_link", "cloud_link", "TEXT", null, 11, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable mediaFileTable = metaDataService.getTable("media_file");
|
||||
metaDataService.getColumn(mediaFileTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "ID", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "Created", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "Modified", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "Version", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "url", "link_url", "TEXT", "UNIQUE", 5, Boolean.TRUE, "URL", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "review", "review", "BOOLEAN", null, 6, Boolean.TRUE, "Review", Boolean.TRUE, "Review");
|
||||
metaDataService.getColumn(mediaFileTable, "should_download", "should_download", "BOOLEAN", null, 7, Boolean.TRUE, "Download", Boolean.TRUE, "Download");
|
||||
metaDataService.getColumn(mediaFileTable, "title", "title", "TEXT", null, 8, Boolean.TRUE, "Title", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "file_name", "file_name", "TEXT", null, 9, Boolean.TRUE, "Dateiname", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "path", "path", "TEXT", null, 10, Boolean.TRUE, "Verzeichnis", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(mediaFileTable, "cloud_link", "cloud_link", "TEXT", null, 11, Boolean.TRUE, "Cloud Link", Boolean.FALSE, null);
|
||||
MetaDataTable artistTable = metaDataService.getTable("artist");
|
||||
metaDataService.getColumn(artistTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(artistTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(artistTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(artistTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(artistTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable publisherTable = metaDataService.getTable("publisher");
|
||||
metaDataService.getColumn(publisherTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(publisherTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(publisherTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(publisherTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(publisherTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable comicTable = metaDataService.getTable("comic");
|
||||
metaDataService.getColumn(comicTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.TRUE, "ID", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicTable, "completed", "completed", "BOOLEAN", null, 5, Boolean.TRUE, "Complete", Boolean.TRUE, "Complete");
|
||||
metaDataService.getColumn(comicTable, "current_order", "current_order", "BOOLEAN", null, 6, Boolean.TRUE, "Bestellung", Boolean.TRUE, "Bestellung");
|
||||
metaDataService.getColumn(comicTable, "title", "title", "TEXT", "UNIQUE", 7, Boolean.TRUE, "Title", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicTable, "publisher_id", "publisher_id", "TEXT", null, 8, Boolean.TRUE, "Verlag", Boolean.FALSE, null);
|
||||
MetaDataTable issueTable = metaDataService.getTable("issue");
|
||||
metaDataService.getColumn(issueTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "in_stock", "in_stock", "BOOLEAN", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "is_read", "is_read", "BOOLEAN", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "issue_number", "issue_number", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "comic_id", "comic_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(issueTable, "volume_id", "volume_id", "TEXT", null, 9, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable volumeTable = metaDataService.getTable("volume");
|
||||
metaDataService.getColumn(volumeTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(volumeTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(volumeTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(volumeTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(volumeTable, "name", "name", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(volumeTable, "comic_id", "comic_id", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable tpbTable = metaDataService.getTable("trade_paperback");
|
||||
metaDataService.getColumn(tpbTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "issue_start", "issue_start", "LONG", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "issue_end", "issue_end", "LONG", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "name", "name", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(tpbTable, "comic_id", "comic_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable storyArcTable = metaDataService.getTable("story_arc");
|
||||
metaDataService.getColumn(storyArcTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(storyArcTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(storyArcTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(storyArcTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(storyArcTable, "name", "name", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(storyArcTable, "comic_id", "comic_id", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable worktypeTable = metaDataService.getTable("worktype");
|
||||
metaDataService.getColumn(worktypeTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(worktypeTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(worktypeTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(worktypeTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(worktypeTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable comicworkTable = metaDataService.getTable("comic_work");
|
||||
metaDataService.getColumn(comicworkTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicworkTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicworkTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicworkTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicworkTable, "artist_id", "artist_id", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicworkTable, "comic_id", "comic_id", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(comicworkTable, "work_type_id", "work_type_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable authorTable = metaDataService.getTable("author");
|
||||
metaDataService.getColumn(authorTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(authorTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(authorTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(authorTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(authorTable, "first_name", "first_name", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(authorTable, "last_name", "last_name", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable articleTable = metaDataService.getTable("article");
|
||||
metaDataService.getColumn(articleTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleTable, "title", "title", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable articleAuthorTable = metaDataService.getTable("article_author");
|
||||
metaDataService.getColumn(articleAuthorTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleAuthorTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleAuthorTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleAuthorTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleAuthorTable, "article_id", "article_id", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(articleAuthorTable, "author_id", "author_id", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable bookTable = metaDataService.getTable("book");
|
||||
metaDataService.getColumn(bookTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "isbn", "isbn", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "title", "title", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "year", "year", "LONG", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookTable, "publisher_id", "publisher_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable bookAuthorTable = metaDataService.getTable("book_author");
|
||||
metaDataService.getColumn(bookAuthorTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookAuthorTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookAuthorTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookAuthorTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookAuthorTable, "author_id", "author_id", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookAuthorTable, "book_id", "book_id", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable bookshelfPublisherTable = metaDataService.getTable("bookshelf_publisher");
|
||||
metaDataService.getColumn(bookshelfPublisherTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookshelfPublisherTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookshelfPublisherTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookshelfPublisherTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(bookshelfPublisherTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable sportTable = metaDataService.getTable("sport");
|
||||
metaDataService.getColumn(sportTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(sportTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(sportTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(sportTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(sportTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable playerTable = metaDataService.getTable("player");
|
||||
metaDataService.getColumn(playerTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(playerTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(playerTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(playerTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(playerTable, "first_name", "first_name", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(playerTable, "last_name", "last_name", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable teamTable = metaDataService.getTable("team");
|
||||
metaDataService.getColumn(teamTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(teamTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(teamTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(teamTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(teamTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(teamTable, "short_name", "short_name", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(teamTable, "sport_id", "sport_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable vendorTable = metaDataService.getTable("vendor");
|
||||
metaDataService.getColumn(vendorTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(vendorTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(vendorTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(vendorTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(vendorTable, "name", "name", "TEXT", "UNIQUE", 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable fieldPositionTable = metaDataService.getTable("field_position");
|
||||
metaDataService.getColumn(fieldPositionTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(fieldPositionTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(fieldPositionTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(fieldPositionTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(fieldPositionTable, "name", "name", "TEXT", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(fieldPositionTable, "short_name", "short_name", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(fieldPositionTable, "sport_id", "sport_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable roosterTable = metaDataService.getTable("rooster");
|
||||
metaDataService.getColumn(roosterTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "year", "year", "LONG", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "player_id", "player_id", "TEXT", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "position_id", "position_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(roosterTable, "team_id", "team_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable cardSetTable = metaDataService.getTable("card_set");
|
||||
metaDataService.getColumn(cardSetTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "insert_set", "insert_set", "BOOLEAN", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "parallel_set", "parallel_set", "BOOLEAN", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "name", "name", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardSetTable, "vendor_id", "vendor_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
MetaDataTable cardTable = metaDataService.getTable("card");
|
||||
metaDataService.getColumn(cardTable, "id", "identifier", "TEXT", "PRIMARY KEY", 1, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "created_date", "created", "TIMESTAMP", null, 2, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "last_modified_date", "modified", "TIMESTAMP", null, 3, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "version", "version", "LONG", null, 4, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "card_number", "card_number", "LONG", null, 5, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "year", "year", "LONG", null, 6, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "card_set_id", "card_set_id", "TEXT", null, 7, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "rooster_id", "rooster_id", "TEXT", null, 8, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
metaDataService.getColumn(cardTable, "vendor_id", "vendor_id", "TEXT", null, 9, Boolean.FALSE, "", Boolean.FALSE, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
public class AuthorizationMatrix extends AbstractEntity {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
@NotNull
|
||||
private User user;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "role_id")
|
||||
@NotNull
|
||||
private Role role;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("AuthorizationMatrix{");
|
||||
sb.append("user=").append(user.getUserName());
|
||||
sb.append(", role=").append(role.getName());
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface AuthorizationMatrixRepository extends JpaRepository<AuthorizationMatrix, String> {
|
||||
|
||||
List<AuthorizationMatrix> findByUser(User user);
|
||||
|
||||
List<AuthorizationMatrix> findByRole(Role role);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.mailclient.data.MailAccount;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
public interface MailAccountRepository extends JpaRepository<MailAccount, String> {
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(
|
||||
indexes = @Index(columnList = "columnName, table_id"),
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = {"table_id", "columnOrder"})
|
||||
)
|
||||
public class MetaDataColumn extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
private String columnName;
|
||||
|
||||
private String columnSyncName;
|
||||
|
||||
private String columnType;
|
||||
|
||||
@Nullable
|
||||
private String columnModifier;
|
||||
|
||||
private Integer columnOrder;
|
||||
|
||||
private Boolean isShown;
|
||||
|
||||
private String columnLabel;
|
||||
|
||||
private Boolean showFilter;
|
||||
|
||||
private String filterLabel;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "table_id")
|
||||
@NotNull
|
||||
private MetaDataTable table;
|
||||
|
||||
public String getTableName() {
|
||||
return table.getTableName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MetaDataColumnRepository extends JpaRepository<MetaDataColumn, String> {
|
||||
|
||||
List<MetaDataColumn> findByTable(MetaDataTable table);
|
||||
|
||||
@Query("select m from MetaDataColumn m " +
|
||||
"where lower(m.columnName) like lower(concat('%', :searchTerm, '%')) or lower(m.columnLabel) like lower(concat('%', :searchTerm, '%'))")
|
||||
List<MetaDataColumn> search(@Param("searchTerm") String searchTerm);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(
|
||||
indexes = @Index(columnList = "tableName"),
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = {"tableName"})
|
||||
)
|
||||
public class MetaDataTable extends AbstractEntity {
|
||||
|
||||
@NotNull
|
||||
private String tableName;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "table")
|
||||
private List<MetaDataColumn> tableColumns = new LinkedList<>();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MetaDataTableRepository extends JpaRepository<MetaDataTable, String> {
|
||||
|
||||
MetaDataTable findByTableName(String tableName);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(
|
||||
indexes = @Index(columnList = "moduleName"),
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = {"moduleName"})
|
||||
)
|
||||
public class ModuleData extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String moduleName;
|
||||
|
||||
private Boolean importData;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ModuleDataRepository extends JpaRepository<ModuleData, String> {
|
||||
|
||||
@Query("select m from ModuleData m where lower(m.moduleName) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<ModuleData> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
ModuleData findByModuleName(String moduleName);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
public class Role extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
private String name;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "role")
|
||||
@Nullable
|
||||
private List<AuthorizationMatrix> matrix;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface RoleRepository extends JpaRepository<Role, String> {
|
||||
|
||||
@Query("select r from Role r " +
|
||||
"where lower(r.name) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<Role> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
@Query("select r from Role r " +
|
||||
"where lower(r.name) like lower(:name) ")
|
||||
Role findByName(@Param("name") String name);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"}))
|
||||
public class User extends AbstractEntity {
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
@NotEmpty
|
||||
private String userName;
|
||||
|
||||
private String email;
|
||||
|
||||
private String password;
|
||||
|
||||
private boolean enabled;
|
||||
|
||||
private boolean tokenExpired;
|
||||
|
||||
private String token;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
|
||||
@Nullable
|
||||
private List<AuthorizationMatrix> matrix = new LinkedList<>();
|
||||
|
||||
public String getFullName() {
|
||||
StringBuilder fullNamBuilder = new StringBuilder();
|
||||
if (firstName != null) {
|
||||
fullNamBuilder.append(firstName);
|
||||
}
|
||||
if (lastName != null) {
|
||||
if (fullNamBuilder.length() > 0) {
|
||||
fullNamBuilder.append(" ");
|
||||
}
|
||||
fullNamBuilder.append(lastName);
|
||||
}
|
||||
return fullNamBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.thpeetz.kontor.admin.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, String> {
|
||||
|
||||
@Query("select u from User u " +
|
||||
"where lower(u.lastName) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<User> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
User findByUserName(String userName);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package de.thpeetz.kontor.admin.services;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.AuthorizationMatrix;
|
||||
import de.thpeetz.kontor.admin.data.AuthorizationMatrixRepository;
|
||||
import de.thpeetz.kontor.admin.data.Role;
|
||||
import de.thpeetz.kontor.admin.data.RoleRepository;
|
||||
import de.thpeetz.kontor.admin.data.User;
|
||||
import de.thpeetz.kontor.admin.data.UserRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AdminService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
private final RoleRepository roleRepository;
|
||||
private final AuthorizationMatrixRepository authorizationMatrixRepository;
|
||||
|
||||
public AdminService(UserRepository userRepository, RoleRepository roleRepository,
|
||||
AuthorizationMatrixRepository authorizationMatrixRepository) {
|
||||
this.userRepository = userRepository;
|
||||
this.roleRepository = roleRepository;
|
||||
this.authorizationMatrixRepository = authorizationMatrixRepository;
|
||||
}
|
||||
|
||||
public List<User> findAllUsers() {
|
||||
return userRepository.findAll();
|
||||
}
|
||||
|
||||
public List<Role> findAllRoles() {
|
||||
return roleRepository.findAll();
|
||||
}
|
||||
|
||||
public Collection<Role> findAllRoles(String stringFilter) {
|
||||
if (stringFilter == null || stringFilter.isEmpty()) {
|
||||
return roleRepository.findAll();
|
||||
} else {
|
||||
return roleRepository.search(stringFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public Role addRole(String roleName) {
|
||||
Role role = roleRepository.findByName(roleName);
|
||||
if (role == null) {
|
||||
log.info("Role {} was not found, will create it.", roleName);
|
||||
role = new Role();
|
||||
role.setName(roleName);
|
||||
roleRepository.save(role);
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
public void saveRole(Role role) {
|
||||
if (role == null) {
|
||||
log.warn("Role is null. Can't save it.");
|
||||
}
|
||||
log.info("saveRole: role={}", role);
|
||||
roleRepository.save(role);
|
||||
}
|
||||
|
||||
public void deleteRole(Role role) {
|
||||
if (role == null) {
|
||||
log.warn("Role is null. Can't delete it.");
|
||||
}
|
||||
log.info("deleteRole: role={}", role);
|
||||
roleRepository.delete(role);
|
||||
}
|
||||
|
||||
public List<AuthorizationMatrix> findAllAuthorizationMatrices() {
|
||||
return authorizationMatrixRepository.findAll();
|
||||
}
|
||||
|
||||
public void saveAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
|
||||
if (authorizationMatrix == null) {
|
||||
log.warn("AuthorizationMatrix is null. Can't save it.");
|
||||
}
|
||||
log.info("saveAuthorizationMatrix: authorizationMatrix={}", authorizationMatrix);
|
||||
authorizationMatrixRepository.save(authorizationMatrix);
|
||||
}
|
||||
|
||||
public void deleteAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
|
||||
if (authorizationMatrix == null) {
|
||||
log.warn("AuthorizationMatrix is null. Can't delete it.");
|
||||
}
|
||||
log.info("deleteAuthorizationMatrix: authorizationMatrix={}", authorizationMatrix);
|
||||
authorizationMatrixRepository.delete(authorizationMatrix);
|
||||
}
|
||||
|
||||
public String getUserFullName(String userName) {
|
||||
log.debug("get Fullname für user {}", userName);
|
||||
User user = userRepository.findByUserName(userName);
|
||||
if (user == null) {
|
||||
log.info("keinen Eintrag für {} gefunden", userName);
|
||||
return userName;
|
||||
} else {
|
||||
log.info("Voller Name des User {}: {}", userName, user.getFullName());
|
||||
return user.getFullName();
|
||||
}
|
||||
}
|
||||
|
||||
public User getUser(String userName) {
|
||||
log.debug("get User {}", userName);
|
||||
return userRepository.findByUserName(userName);
|
||||
}
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package de.thpeetz.kontor.admin.services;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service("userDetailsService")
|
||||
public class KontorUserDetailsService implements UserDetailsService {
|
||||
|
||||
private static SecureRandom random = new SecureRandom();
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private RoleRepository roleRepository;
|
||||
|
||||
@Autowired
|
||||
private AuthorizationMatrixRepository authorizationMatrixRepository;
|
||||
|
||||
public Collection<User> findAllUsers(String stringFilter) {
|
||||
if (stringFilter == null || stringFilter.isEmpty()) {
|
||||
return userRepository.findAll();
|
||||
} else {
|
||||
return userRepository.search(stringFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveUser(User user) {
|
||||
if (user == null) {
|
||||
log.warn("User is null. Can't save it.");
|
||||
}
|
||||
log.info("saveUser: user={}", user);
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
public void saveUser(User user, List<Role> roles) {
|
||||
if (user == null) {
|
||||
log.warn("User is null. Can't save it.");
|
||||
}
|
||||
log.info("First save user: {}", user);
|
||||
user = userRepository.save(user);
|
||||
List<Role> copy = roles.stream().collect(Collectors.toList());
|
||||
List<AuthorizationMatrix> permissions = user.getMatrix();
|
||||
permissions.forEach(matrix -> {
|
||||
if (roles.contains(matrix.getRole())) {
|
||||
log.info("Role {} already assigned", matrix.getRole());
|
||||
copy.remove(matrix.getRole());
|
||||
} else {
|
||||
log.info("Role {} has to be removed", matrix.getRole());
|
||||
authorizationMatrixRepository.delete(matrix);
|
||||
}
|
||||
});
|
||||
log.info("remaining roles: {}", copy);
|
||||
for (Role role : copy) {
|
||||
AuthorizationMatrix matrix = new AuthorizationMatrix();
|
||||
matrix.setUser(user);
|
||||
matrix.setRole(role);
|
||||
authorizationMatrixRepository.save(matrix);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteUser(User user) {
|
||||
if (user == null) {
|
||||
log.warn("User is null. Can't delete it.");
|
||||
}
|
||||
log.info("deleteUser: user={}", user);
|
||||
userRepository.delete(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
|
||||
|
||||
log.info("loadUserByUsername: userName={}", userName);
|
||||
User user = userRepository.findByUserName(userName);
|
||||
if (user == null) {
|
||||
log.info("User not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<? extends GrantedAuthority> authorities = getAuthorities(user);
|
||||
log.info("User {} hat Rolen: {}", userName, authorities);
|
||||
return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(),
|
||||
authorities);
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> getAuthorities(User user) {
|
||||
return authorizationMatrixRepository.findByUser(user).stream()
|
||||
.map(matrix -> matrix.getRole().getName())
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public String getRememberedUser(String id) {
|
||||
log.info("getRememberedUser: id={}", id);
|
||||
return "admin";
|
||||
}
|
||||
|
||||
public String rememberUser(String username) {
|
||||
String randomId = new BigInteger(130, random).toString(32);
|
||||
log.info("rememberUser: username={}", username);
|
||||
return randomId;
|
||||
}
|
||||
|
||||
public void removeRememberedUser(String id) {
|
||||
log.info("removeRememberedUser: id={}", id);
|
||||
}
|
||||
|
||||
public List<Role> findAllRoles() {
|
||||
return roleRepository.findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.thpeetz.kontor.admin.services;
|
||||
|
||||
import de.thpeetz.kontor.mailclient.data.MailAccount;
|
||||
import de.thpeetz.kontor.admin.data.MailAccountRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MailService {
|
||||
|
||||
private final MailAccountRepository mailAccountRepository;
|
||||
|
||||
public MailService(MailAccountRepository mailAccountRepository) {
|
||||
this.mailAccountRepository = mailAccountRepository;
|
||||
}
|
||||
|
||||
public List<MailAccount> findAllMailAccounts() {
|
||||
return mailAccountRepository.findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package de.thpeetz.kontor.admin.services;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.MetaDataColumn;
|
||||
import de.thpeetz.kontor.admin.data.MetaDataColumnRepository;
|
||||
import de.thpeetz.kontor.admin.data.MetaDataTable;
|
||||
import de.thpeetz.kontor.admin.data.MetaDataTableRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MetaDataService {
|
||||
|
||||
private final MetaDataTableRepository metaDataTableRepository;
|
||||
|
||||
private final MetaDataColumnRepository metaDataColumnRepository;
|
||||
|
||||
public MetaDataService(MetaDataTableRepository metaDataTableRepository, MetaDataColumnRepository metaDataColumnRepository) {
|
||||
this.metaDataTableRepository = metaDataTableRepository;
|
||||
this.metaDataColumnRepository = metaDataColumnRepository;
|
||||
}
|
||||
|
||||
public MetaDataTable getTable(String tableName) {
|
||||
MetaDataTable table = metaDataTableRepository.findByTableName(tableName);
|
||||
if (table == null) {
|
||||
log.info("Metadata for table {} not found, will create it", tableName);
|
||||
table = new MetaDataTable();
|
||||
table.setTableName(tableName);
|
||||
metaDataTableRepository.save(table);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
public void getColumn(MetaDataTable table, String columnName, String columnSyncName, String columnType, String columnModifier, Integer columnOrder, Boolean isShown, String columnLabel, Boolean showFilter, String filterLabel) {
|
||||
if (table.getTableColumns().stream().anyMatch(column -> column.getColumnName().equals(columnName))) {
|
||||
log.debug("Column {} with name {} of table {} found, check Values", columnOrder, columnName, table.getTableName());
|
||||
MetaDataColumn column = table.getTableColumns().get(columnOrder.intValue()-1);
|
||||
if (!column.getColumnName().equals(columnName)) {
|
||||
log.debug("columnName has to be changed to {}", columnName);
|
||||
column.setColumnName(columnName);
|
||||
}
|
||||
if (!column.getColumnSyncName().equals(columnSyncName)) {
|
||||
log.debug("columnSyncName has to be changed to {}", columnSyncName);
|
||||
column.setColumnSyncName(columnSyncName);
|
||||
}
|
||||
if (!column.getColumnType().equals(columnType)) {
|
||||
log.debug("columnType has to be changed to {}", columnType);
|
||||
column.setColumnType(columnType);
|
||||
}
|
||||
if (columnModifier != null && !column.getColumnModifier().equals(columnModifier)) {
|
||||
log.debug("columnModifier has to be changed to {}", columnModifier);
|
||||
column.setColumnModifier(columnModifier);
|
||||
}
|
||||
if (isShown != null && !isShown.equals(column.getIsShown())) {
|
||||
log.debug("isShown has to be change to {}}", isShown);
|
||||
column.setIsShown(isShown);
|
||||
}
|
||||
if (columnLabel != null && !columnLabel.equals(column.getColumnLabel())) {
|
||||
log.debug("columnLabel has to be change to {}}", columnLabel);
|
||||
column.setColumnLabel(columnLabel);
|
||||
}
|
||||
if (showFilter != null &&!showFilter.equals(column.getShowFilter())) {
|
||||
log.debug("showFilter has to be change to {}}", showFilter);
|
||||
column.setShowFilter(showFilter);
|
||||
}
|
||||
if (filterLabel != null && !filterLabel.equals(column.getFilterLabel())) {
|
||||
log.debug("filterLabel has to be change to {}}", filterLabel);
|
||||
column.setFilterLabel(filterLabel);
|
||||
}
|
||||
metaDataColumnRepository.save(column);
|
||||
} else {
|
||||
log.info("Column {} of table {} not found, will create it", columnName, table.getTableName());
|
||||
MetaDataColumn column = new MetaDataColumn();
|
||||
column.setTable(table);
|
||||
column.setColumnName(columnName);
|
||||
column.setColumnSyncName(columnSyncName);
|
||||
column.setColumnType(columnType);
|
||||
column.setColumnModifier(columnModifier);
|
||||
column.setColumnOrder(columnOrder);
|
||||
column.setIsShown(Boolean.FALSE);
|
||||
metaDataColumnRepository.save(column);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MetaDataColumn> findAllMetaDataColumns(String stringFilter) {
|
||||
if (stringFilter == null || stringFilter.isEmpty()) {
|
||||
log.debug("Found " + metaDataColumnRepository.count()+ " entries");
|
||||
return metaDataColumnRepository.findAll();
|
||||
} else {
|
||||
List<MetaDataColumn> results = metaDataColumnRepository.search(stringFilter);
|
||||
log.debug("Found " + results.size() + " entries");
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteMetaDataColumn(MetaDataColumn metaDataColumn) {
|
||||
if (metaDataColumn == null) {
|
||||
log.warn("MetaDataColumn is null, can't delete it");
|
||||
return;
|
||||
}
|
||||
log.debug("deleteMetaDataColumn: MetaDataColumn={}", metaDataColumn);
|
||||
metaDataColumnRepository.delete(metaDataColumn);
|
||||
}
|
||||
|
||||
public void saveMetaDataColumn(MetaDataColumn metaDataColumn) {
|
||||
if (metaDataColumn == null) {
|
||||
log.warn("MetaDataColumn is null, can't save it");
|
||||
return;
|
||||
}
|
||||
log.debug("saveMetaDataColumn: MetaDataColumn={}", metaDataColumn);
|
||||
metaDataColumnRepository.save(metaDataColumn);
|
||||
}
|
||||
|
||||
public List<MetaDataTable> findAllTables() {
|
||||
return metaDataTableRepository.findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package de.thpeetz.kontor.admin.services;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.ModuleData;
|
||||
import de.thpeetz.kontor.admin.data.ModuleDataRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ModuleService {
|
||||
|
||||
private final ModuleDataRepository moduleDataRepository;
|
||||
|
||||
public ModuleService(ModuleDataRepository moduleDataRepository) {
|
||||
this.moduleDataRepository = moduleDataRepository;
|
||||
}
|
||||
|
||||
public List<ModuleData> findAll(String stringFilter) {
|
||||
if (stringFilter == null || stringFilter.isEmpty()) {
|
||||
return moduleDataRepository.findAll();
|
||||
} else {
|
||||
return moduleDataRepository.search(stringFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public ModuleData findByName(String moduleName) {
|
||||
if (moduleName == null || moduleName.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return moduleDataRepository.findByModuleName(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean importData(String moduleName) {
|
||||
ModuleData module = moduleDataRepository.findByModuleName(moduleName);
|
||||
if (module != null) {
|
||||
return module.getImportData();
|
||||
} else {
|
||||
log.info("Module {} not found, should import data", moduleName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDataImported(String moduleName) {
|
||||
ModuleData module = moduleDataRepository.findByModuleName(moduleName);
|
||||
if (module == null) {
|
||||
log.info("Module {} not found, will create it", moduleName);
|
||||
module = new ModuleData();
|
||||
module.setModuleName(moduleName);
|
||||
module.setImportData(false);
|
||||
moduleDataRepository.save(module);
|
||||
} else {
|
||||
log.info("Module {} found, change import data", module);
|
||||
module.setImportData(false);
|
||||
moduleDataRepository.save(module);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveModuleData(ModuleData moduleData) {
|
||||
if (moduleData == null) {
|
||||
log.warn("ModuleData is null, can't save it.");
|
||||
} else {
|
||||
moduleDataRepository.save(moduleData);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteModuleData(ModuleData moduleData) {
|
||||
if (moduleData == null) {
|
||||
log.warn("ModuleData is null, can't delete it.");
|
||||
} else {
|
||||
moduleDataRepository.delete(moduleData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package de.thpeetz.kontor.admin.views;
|
||||
|
||||
import com.vaadin.flow.component.applayout.AppLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||
|
||||
import de.thpeetz.kontor.admin.AdminConstants;
|
||||
import de.thpeetz.kontor.admin.services.AdminService;
|
||||
import de.thpeetz.kontor.common.views.KontorLayoutUtil;
|
||||
import de.thpeetz.kontor.security.SecurityService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class AdminLayout extends AppLayout {
|
||||
|
||||
private final AdminService adminService;
|
||||
|
||||
private final SecurityService securityService;
|
||||
|
||||
public AdminLayout(AdminService adminService, SecurityService securityService) {
|
||||
this.adminService = adminService;
|
||||
this.securityService = securityService;
|
||||
|
||||
KontorLayoutUtil layout = new KontorLayoutUtil(this, adminService, securityService);
|
||||
layout.setSecondaryNavigation(getSecondaryNavigation());
|
||||
layout.createHeader(AdminConstants.ADMIN_TITLE);
|
||||
}
|
||||
|
||||
private HorizontalLayout getSecondaryNavigation() {
|
||||
HorizontalLayout navigation = new HorizontalLayout();
|
||||
navigation.addClassNames(LumoUtility.JustifyContent.CENTER, LumoUtility.Gap.SMALL, LumoUtility.Height.MEDIUM);
|
||||
navigation.add(AdminConstants.getUserNavigation(), AdminConstants.getRoleNavigation(),
|
||||
AdminConstants.getAuthorizationNavigation());
|
||||
return navigation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package de.thpeetz.kontor.admin.views;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.vaadin.flow.component.ComponentEvent;
|
||||
import com.vaadin.flow.component.ComponentEventListener;
|
||||
import com.vaadin.flow.component.Key;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.button.ButtonVariant;
|
||||
import com.vaadin.flow.component.combobox.ComboBox;
|
||||
import com.vaadin.flow.component.formlayout.FormLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.data.binder.BeanValidationBinder;
|
||||
import com.vaadin.flow.data.binder.Binder;
|
||||
|
||||
import de.thpeetz.kontor.admin.data.AuthorizationMatrix;
|
||||
import de.thpeetz.kontor.admin.data.Role;
|
||||
import de.thpeetz.kontor.admin.data.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class AuthorizationForm extends FormLayout {
|
||||
|
||||
ComboBox<User> user = new ComboBox<>("User");
|
||||
ComboBox<Role> role = new ComboBox<>("Role");
|
||||
|
||||
Button save = new Button("Save");
|
||||
Button delete = new Button("Delete");
|
||||
Button close = new Button("Cancel");
|
||||
|
||||
Binder<AuthorizationMatrix> binder = new BeanValidationBinder<>(AuthorizationMatrix.class);
|
||||
|
||||
public AuthorizationForm(List<User> users, List<Role> roles) {
|
||||
addClassName("authorizationmatrix-form");
|
||||
binder.bindInstanceFields(this);
|
||||
|
||||
user.setItems(users);
|
||||
user.setItemLabelGenerator(User::getUserName);
|
||||
role.setItems(roles);
|
||||
role.setItemLabelGenerator(Role::getName);
|
||||
add(user, role, createButtonsLayout());
|
||||
}
|
||||
|
||||
private HorizontalLayout createButtonsLayout() {
|
||||
save.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
delete.addThemeVariants(ButtonVariant.LUMO_ERROR);
|
||||
close.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
|
||||
|
||||
save.addClickShortcut(Key.ENTER);
|
||||
close.addClickShortcut(Key.ESCAPE);
|
||||
|
||||
save.addClickListener(event -> validateAndSave());
|
||||
delete.addClickListener(event -> fireEvent(new DeleteEvent(this, binder.getBean())));
|
||||
close.addClickListener(event -> fireEvent(new CloseEvent(this)));
|
||||
|
||||
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
|
||||
return new HorizontalLayout(save, delete, close);
|
||||
}
|
||||
|
||||
private void validateAndSave() {
|
||||
if (binder.isValid()) {
|
||||
fireEvent(new SaveEvent(this, binder.getBean()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
|
||||
binder.setBean(authorizationMatrix);
|
||||
}
|
||||
|
||||
public abstract static class AuthorizationFormEvent extends ComponentEvent<AuthorizationForm> {
|
||||
private AuthorizationMatrix authorizationMatrix;
|
||||
|
||||
protected AuthorizationFormEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
|
||||
super(source, false);
|
||||
this.authorizationMatrix = authorizationMatrix;
|
||||
}
|
||||
|
||||
public AuthorizationMatrix getAuthorizationMatrix() {
|
||||
return authorizationMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SaveEvent extends AuthorizationFormEvent {
|
||||
SaveEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
|
||||
super(source, authorizationMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteEvent extends AuthorizationFormEvent {
|
||||
DeleteEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
|
||||
super(source, authorizationMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CloseEvent extends AuthorizationFormEvent {
|
||||
CloseEvent(AuthorizationForm source) {
|
||||
super(source, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDeleteListener(ComponentEventListener<DeleteEvent> listener) {
|
||||
addListener(DeleteEvent.class, listener);
|
||||
}
|
||||
|
||||
public void addSaveListener(ComponentEventListener<SaveEvent> listener) {
|
||||
addListener(SaveEvent.class, listener);
|
||||
}
|
||||
|
||||
public void addCloseListener(ComponentEventListener<CloseEvent> listener) {
|
||||
addListener(CloseEvent.class, listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package de.thpeetz.kontor.admin.views;
|
||||
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
import com.vaadin.flow.component.Component;
|
||||
import com.vaadin.flow.component.button.Button;
|
||||
import com.vaadin.flow.component.grid.Grid;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
|
||||
import de.thpeetz.kontor.admin.AdminConstants;
|
||||
import de.thpeetz.kontor.admin.data.AuthorizationMatrix;
|
||||
import de.thpeetz.kontor.admin.services.AdminService;
|
||||
import de.thpeetz.kontor.common.views.MainLayout;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@SpringComponent
|
||||
@Scope("prototype")
|
||||
@RolesAllowed("ROLE_ADMIN")
|
||||
@Route(value = AdminConstants.AUTHORIZATION_ROUTE, layout = MainLayout.class)
|
||||
@PageTitle("Authorization | Admin | Kontor")
|
||||
public class AuthorizationView extends VerticalLayout {
|
||||
|
||||
Grid<AuthorizationMatrix> grid = new Grid<>(AuthorizationMatrix.class);
|
||||
AuthorizationForm form;
|
||||
AdminService service;
|
||||
|
||||
public AuthorizationView(AdminService service) {
|
||||
this.service = service;
|
||||
addClassName("authoriaztionmatrix-view");
|
||||
setSizeFull();
|
||||
configureGrid();
|
||||
configureForm();
|
||||
|
||||
add(getToolbar(), getContent());
|
||||
updateList();
|
||||
}
|
||||
|
||||
private void configureGrid() {
|
||||
grid.addClassName("authorizationmatrix-grid");
|
||||
grid.setSizeFull();
|
||||
grid.setColumns("user.userName", "role.name");
|
||||
grid.getColumns().forEach(col -> col.setAutoWidth(true));
|
||||
grid.asSingleSelect().addValueChangeListener(event -> editAuthorizationMatrix(event.getValue()));
|
||||
}
|
||||
|
||||
private void configureForm() {
|
||||
form = new AuthorizationForm(service.findAllUsers(), service.findAllRoles());
|
||||
form.setWidth("25em");
|
||||
form.addSaveListener(this::saveAuthorizationMatrix);
|
||||
form.addDeleteListener(this::deleteAuthorizationMatrix);
|
||||
form.addCloseListener(e -> closeEditor());
|
||||
}
|
||||
|
||||
private void saveAuthorizationMatrix(AuthorizationForm.SaveEvent event) {
|
||||
AuthorizationMatrix authorizationMatrix = event.getAuthorizationMatrix();
|
||||
service.saveAuthorizationMatrix(authorizationMatrix);
|
||||
updateList();
|
||||
closeEditor();
|
||||
}
|
||||
|
||||
private void deleteAuthorizationMatrix(AuthorizationForm.DeleteEvent event) {
|
||||
service.deleteAuthorizationMatrix(event.getAuthorizationMatrix());
|
||||
updateList();
|
||||
closeEditor();
|
||||
}
|
||||
|
||||
private Component getContent() {
|
||||
HorizontalLayout content = new HorizontalLayout(grid, form);
|
||||
content.setFlexGrow(2, grid);
|
||||
content.setFlexGrow(1, form);
|
||||
content.addClassName("content");
|
||||
content.setSizeFull();
|
||||
return content;
|
||||
}
|
||||
|
||||
private HorizontalLayout getToolbar() {
|
||||
Button addAuthorizationMaxtrixButton = new Button("Add permssion", click -> addAuthorizationMatrix());
|
||||
HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton);
|
||||
toolbar.addClassName("toolbar");
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
public void editAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
|
||||
if (authorizationMatrix == null) {
|
||||
closeEditor();
|
||||
} else {
|
||||
form.setAuthorizationMatrix(authorizationMatrix);
|
||||
form.setVisible(true);
|
||||
addClassName("editing");
|
||||
}
|
||||
}
|
||||
|
||||
public void closeEditor() {
|
||||
form.setAuthorizationMatrix(null);
|
||||
form.setVisible(false);
|
||||
removeClassName("editing");
|
||||
}
|
||||
|
||||
private void addAuthorizationMatrix() {
|
||||
grid.asSingleSelect().clear();
|
||||
editAuthorizationMatrix(new AuthorizationMatrix());
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
grid.setItems(service.findAllAuthorizationMatrices());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package de.thpeetz.kontor.admin.views;
|
||||
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.login.LoginForm;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Route("login")
|
||||
@PageTitle("Login | Vaadin Kontor")
|
||||
@AnonymousAllowed
|
||||
public class LoginView extends VerticalLayout implements BeforeEnterObserver {
|
||||
|
||||
private final LoginForm login = new LoginForm();
|
||||
|
||||
public LoginView() {
|
||||
addClassName("login-view");
|
||||
setSizeFull();
|
||||
setAlignItems(Alignment.CENTER);
|
||||
setJustifyContentMode(JustifyContentMode.CENTER);
|
||||
|
||||
login.setAction("login");
|
||||
|
||||
add(new H1("Vaadin Kontor"));
|
||||
add(new Span("Username: user, Password: password"));
|
||||
add(new Span("Username: admin, Password: password"));
|
||||
add(login);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
|
||||
log.info("beforeEnter: {}", beforeEnterEvent.getLocation());
|
||||
log.info("beforeEnter: {}", SecurityContextHolder.getContext().getAuthentication());
|
||||
// inform the user about an authentication error
|
||||
if (beforeEnterEvent.getLocation()
|
||||
.getQueryParameters()
|
||||
.getParameters()
|
||||
.containsKey("error")) {
|
||||
login.setError(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user