diff --git a/.gitignore b/.gitignore index c24b53a..777abf0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ __pycache__/ # custom config.yml -venv/ \ No newline at end of file +venv/ +bootstrap-4.6.0-dist/ \ No newline at end of file diff --git a/biscd/biscd/__init__.py b/biscd/biscd/__init__.py index 26c4fb7..32438ae 100644 --- a/biscd/biscd/__init__.py +++ b/biscd/biscd/__init__.py @@ -8,6 +8,7 @@ from .utils import ObjectView from flask import Flask from flask_bootstrap import Bootstrap +from flask_login import LoginManager def read_config(application): @@ -45,6 +46,8 @@ def setup_logging(application): app = Flask(__name__) config = read_config(app) bootstrap = Bootstrap(app) +login = LoginManager(app) +login.login_view = 'login' setup_logging(app) diff --git a/biscd/biscd/froms.py b/biscd/biscd/froms.py index 79ae3e7..516dc86 100644 --- a/biscd/biscd/froms.py +++ b/biscd/biscd/froms.py @@ -1,6 +1,30 @@ from flask_wtf import FlaskForm -from wtforms import StringField, SubmitField -from wtforms.validators import DataRequired +from wtforms import SubmitField, StringField, PasswordField, BooleanField +from wtforms.validators import DataRequired, Email, EqualTo, Length + +class LoginForm(FlaskForm): + username = StringField('Username', validators=[DataRequired()]) + password = PasswordField('Password', validators=[DataRequired()]) + remember_me = BooleanField('Remember Me') + submit = SubmitField('Sign In') + +class RegistrationForm(FlaskForm): + username = StringField('Username', validators=[DataRequired()]) + email = StringField('Email', validators=[DataRequired(), Email()]) + password = PasswordField('Password', validators=[DataRequired()]) + password2 = PasswordField( + 'Repeat Password', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Register') + + def validate_username(self, username): + user = User.query.filter_by(username=username.data).first() + if user is not None: + raise ValidationError('Please use a different username.') + + def validate_email(self, email): + user = User.query.filter_by(email=email.data).first() + if user is not None: + raise ValidationError('Please use a different email adress.') class NewProjectForm(FlaskForm): projectname = StringField('Project Name', validators=[DataRequired()]) diff --git a/biscd/biscd/models/__init__.py b/biscd/biscd/models/__init__.py index 5ce17c6..780340d 100644 --- a/biscd/biscd/models/__init__.py +++ b/biscd/biscd/models/__init__.py @@ -1 +1,3 @@ from .project import Project +from .user import User +from .yaml_serializable import YamlSerializable diff --git a/biscd/biscd/models/project.py b/biscd/biscd/models/project.py index 492d494..db868c0 100644 --- a/biscd/biscd/models/project.py +++ b/biscd/biscd/models/project.py @@ -1,63 +1,16 @@ from pathlib import Path -import yaml from biscd import config +from .yaml_serializable import YamlSerializable -class Project: - _storage_file = Path(config.config_dir()) / 'projects.yaml' - - storage = {} - - def __init__(self, name, branche='master'): - self.name = name - self.branche = branche - +class Project(YamlSerializable): @property - def config_dict(self): - project_dict = self.__dict__.copy() - project_dict.pop('name') - return {self.name: project_dict} - - def save(self): - projects = self._get_projects_from_file() - if self.name in ([*project][0] for project in projects): - projects[self.name] = self.config_dict - else: - projects.append(self.config_dict) - print(projects) - self._save_projects_to_file(projects) + def _storage_file(self): + return Path(config.config_dir()) / 'projects.yaml' - @classmethod - def get(cls, name): - project_dict = next(project for project in cls._get_projects_from_file() if [*project][0] == name) - if project_dict is None: - return None - project_name = [*project_dict][0] - project_dict = project_dict.get(project_name) - - project_dict['name'] = project_name - - project = cls('placeholder') - project.__dict__ = project_dict - return project - - - @classmethod - def list(cls): - projects = cls._get_projects_from_file() - project_list = [] - for project in projects: - name = [*project][0] - project_list.append(name) - return project_list - - @classmethod - def _get_projects_from_file(cls): - with open(cls._storage_file) as file: - projects = yaml.load(file, yaml.FullLoader).get('projects') - return projects + @property + def _yaml_object_name(self): + return 'projects' - @classmethod - def _save_projects_to_file(cls, projects): - projects_object = {'projects' : projects} - with open(cls._storage_file, 'w') as file: - yaml.dump(projects_object, file) + def __init__(self, name=None, branche='master'): + self.name = name + self.branche = branche \ No newline at end of file diff --git a/biscd/biscd/routes.py b/biscd/biscd/routes.py index eb37f6b..b87a22e 100644 --- a/biscd/biscd/routes.py +++ b/biscd/biscd/routes.py @@ -1,10 +1,12 @@ from flask import render_template, flash, abort +from flask_login import current_user, login_user, logout_user, login_required from biscd import app from .models import Project -from .froms import NewProjectForm +from .froms import NewProjectForm, LoginForm @app.route('/', methods=['GET', 'POST']) @app.route('/index', methods=['GET', 'POST']) +@login_required def index(): form = NewProjectForm() if form.validate_on_submit(): @@ -14,7 +16,45 @@ def index(): project_names = Project.list() return render_template('index.html', form=form, project_names=project_names) +@app.route('/login', methods=['GET', 'POST']) +def login(): + if current_user.is_authenticated: + return redirect(url_for('index')) + form = LoginForm() + if form.validate_on_submit(): + user = User.query.filter_by(username=form.username.data).first() + if user is None or not user.check_password(form.password.data): + flash('Invalid username or password') + return redirect(url_for('login')) + login_user(user, remember=form.remember_me.data) + next_page = request.args.get('next') + if not next_page or url_parse(next_page).netloc != '': + next_page = url_for('index') + return redirect(next_page) + return render_template('login.html', title='Sign In', form=form) + +@app.route('/logout') +def logout(): + logout_user() + return redirect(url_for('index')) + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if current_user.is_authenticated: + return redirect(url_for('index')) + form = RegistrationForm() + if form.validate_on_submit(): + user = User(username=form.username.data, email=form.email.data) + user.set_password(form.password.data) + db.session.add(user) + db.session.commit() + flash('Congratulations, you are now a registered user!') + return redirect(url_for('login')) + return render_template('register.html', title='Register', form=form) + + @app.route('/project/', methods=['GET', 'POST']) +@login_required def project_dashboard(project_name): print(project_name) project = Project.get(project_name) diff --git a/biscd/biscd/templates/base.html b/biscd/biscd/templates/base.html index 66aa861..0bcf176 100644 --- a/biscd/biscd/templates/base.html +++ b/biscd/biscd/templates/base.html @@ -22,7 +22,7 @@