Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
chee committed Nov 16, 2020
0 parents commit 177550f
Show file tree
Hide file tree
Showing 20 changed files with 827 additions and 0 deletions.
195 changes: 195 additions & 0 deletions .gitignore
@@ -0,0 +1,195 @@
### https://raw.github.com/github/gitignore/218a941be92679ce67d0484547e3e142b2f5f6f0/Python.gitignore

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/


### https://raw.github.com/github/gitignore/218a941be92679ce67d0484547e3e142b2f5f6f0/Global/Emacs.gitignore

# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*

# Org-mode
.org-id-locations
*_archive

# flymake-mode
*_flymake.*

# eshell files
/eshell/history
/eshell/lastdir

# elpa packages
/elpa/

# reftex files
*.rel

# AUCTeX auto folder
/auto/

# cask packages
.cask/
dist/

# Flycheck
flycheck_*.el

# server auth directory
/server/

# projectiles files
.projectile

# directory configuration
.dir-locals.el

# network security
/network-security.data



13 changes: 13 additions & 0 deletions app/__init__.py
@@ -0,0 +1,13 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
from .config import Config

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)

from . import routes, models
8 changes: 8 additions & 0 deletions app/config.py
@@ -0,0 +1,8 @@
import os
basedir = os.path.abspath(os.path.dirname(__file__))


class Config(object):
SECRET_KEY = os.environ.get('CC0_SECRET_KEY')
SQLALCHEMY_DATABASE_URI = os.environ.get("CC0_SQLALCHEMY_DATABASE_URI") or f"sqlite:///{os.path.join(basedir, 'app.db')}"
SQLALCHEMY_TRACK_MODIFICATIONS = False
23 changes: 23 additions & 0 deletions app/forms.py
@@ -0,0 +1,23 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, ValidationError, URL
from .models import CopyrightHolder

class LoginForm(FlaskForm):
name = StringField('username', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
remember = BooleanField('🍪')
submit = SubmitField('login')

class RegistrationForm(FlaskForm):
name = StringField('username', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
legal_name = StringField('legal name', validators=[DataRequired()])
website = StringField('website url', validators=[DataRequired(), URL()])
submit = SubmitField('register')

def validate_name(self, username):
user = CopyrightHolder.query.filter_by(username=username.data).first()

if user is not None or user in ["login", "register", "logout"]:
raise ValidationError('sorry, username in use')
50 changes: 50 additions & 0 deletions app/models.py
@@ -0,0 +1,50 @@
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from . import db
from . import login

@login.user_loader
def load_user(id):
return CopyrightHolder.query.get(int(id))

class CopyrightHolder(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(128), index=True, unique=True)
legal_name = db.Column(db.String(128), index=True)
password_hash = db.Column(db.String(128))
email = db.Column(db.String(128), index=True, unique=True)
website = db.Column(db.String(256), index=True, unique=True)
collections = db.relationship('Collection', backref='copyright_holder', lazy='dynamic')

def __repr__(self):
return f'<CopyrightHolder {self.username} ("{self.legal_name}" <{self.email}>)>'

def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def is_admin(self):
return self.id == 1

class Collection(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, unique=True)
description = db.Column(db.String(256))
slug = db.Column(db.String(128), index=True)
copyright_holder_id = db.Column(db.Integer, db.ForeignKey('copyright_holder.id'))
password_hash = db.Column(db.String(128))
pieces = db.relationship('Piece', backref='collection', lazy='dynamic')
def __repr__(self):
return f'<Collection {self.name}>'

class Piece(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), index=True, unique=True)
description = db.Column(db.String(256))
url = db.Column(db.String(128))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
type = db.Column(db.String(10), index=True)
collection_id = db.Column(db.Integer, db.ForeignKey('collection.id'))
def __repr__(self):
return f'<Piece {self.name}>'
72 changes: 72 additions & 0 deletions app/routes.py
@@ -0,0 +1,72 @@
from flask import render_template, flash, redirect, url_for
from flask_login import current_user, login_user
from . import app
from . import db
from .forms import LoginForm, RegistrationForm
from .models import CopyrightHolder, Collection, Piece

from os import scandir
from os.path import join, dirname

@app.route('/')
def index():
return render_template("index.html",
collections=Collection.query.all())

@app.route('/logout')
def logout():
return render_template("base.html")

@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
ch = CopyrightHolder(
username=form.name.data,
legal_name=form.legal_name.data
)
ch.set_password(form.password.data)
db.session.add(ch)
db.session.commit()
flash(f"{ch} created")
return redirect(url_for('index'))
return render_template('register.html', title="make user", form=form)

@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():
copyright_holder = CopyrightHolder.query.filter_by(username=form.name.data).first()
if copyright_holder is None or not copyright_holder.check_password(form.password.data):
flash('bad name or wrong pass')
return redirect(url_for('login'))
login_user(copyright_holder, remember=form.remember.data)
return redirect(url_for('index'))
return render_template('login.html', title="login", form=form)

@app.route('/<username>')
def copyright_holder(username):
ch = CopyrightHolder.query.filter_by(username=username).first()
if ch is None:
return "404"
return render_template("copyright_holder.html",
copyright_holder=ch)

@app.route('/<username>/new')
def new_collection(username):
return render_template("base.html")


@app.route('/<username>/<slug>')
def collection(username, slug):
collection = Collection.query.filter_by(slug=slug).first()
if collection is None:
return "404"
return render_template("collection.html",
copyright_holder=collection)

@app.route('/<username>/<slug>/new')
def new_piece(username, slug):
return render_template("base.html")

0 comments on commit 177550f

Please sign in to comment.