Add PagePolicy and PagePolicyKey tables, some indexes and flags on Page table.
Schema changes; please run migration tool on existing Page table to continue using:
from playhouse.migrate import SqliteMigrator, migrate
migrator = SqliteMigrator(database)
migrate(
migrator.drop_column('page', 'is_redirect'),
migrator.add_column('page', 'flags', BitField())
)
This commit is contained in:
parent
6b1c57726d
commit
53559dc4f2
1 changed files with 89 additions and 15 deletions
102
app.py
102
app.py
|
|
@ -47,6 +47,18 @@ UPLOAD_DIR = APP_BASE_DIR + '/media'
|
||||||
|
|
||||||
DATABASE_DIR = APP_BASE_DIR + "/database"
|
DATABASE_DIR = APP_BASE_DIR + "/database"
|
||||||
|
|
||||||
|
#### misc. helpers ####
|
||||||
|
|
||||||
|
def _makelist(l):
|
||||||
|
if isinstance(l, (str, bytes, bytearray)):
|
||||||
|
return [l]
|
||||||
|
elif hasattr(l, '__iter__'):
|
||||||
|
return list(l)
|
||||||
|
elif l:
|
||||||
|
return [l]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
#### DATABASE SCHEMA ####
|
#### DATABASE SCHEMA ####
|
||||||
|
|
||||||
database = SqliteDatabase(DATABASE_DIR + '/data.sqlite')
|
database = SqliteDatabase(DATABASE_DIR + '/data.sqlite')
|
||||||
|
|
@ -55,11 +67,18 @@ class BaseModel(Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
database = database
|
database = database
|
||||||
|
|
||||||
|
# Used for PagePolicy
|
||||||
|
def _passphrase_hash(pp):
|
||||||
|
pp_bin = pp.encode('utf-8')
|
||||||
|
h = str(len(pp_bin)) + ':' + hashlib.sha256(pp_bin).hexdigest()
|
||||||
|
return h
|
||||||
|
|
||||||
class Page(BaseModel):
|
class Page(BaseModel):
|
||||||
url = CharField(64, unique=True, null=True)
|
url = CharField(64, unique=True, null=True)
|
||||||
title = CharField(256)
|
title = CharField(256, index=True)
|
||||||
is_redirect = BooleanField()
|
touched = DateTimeField(index=True)
|
||||||
touched = DateTimeField()
|
flags = BitField()
|
||||||
|
is_redirect = flags.flag(1)
|
||||||
@property
|
@property
|
||||||
def latest(self):
|
def latest(self):
|
||||||
if self.revisions:
|
if self.revisions:
|
||||||
|
|
@ -94,6 +113,21 @@ class Page(BaseModel):
|
||||||
@property
|
@property
|
||||||
def prop(self):
|
def prop(self):
|
||||||
return PagePropertyDict(self)
|
return PagePropertyDict(self)
|
||||||
|
def unlock(self, perm, pp, sec):
|
||||||
|
## XX complete later!
|
||||||
|
policies = self.policies.where(Policy.type << _makelist(perm))
|
||||||
|
if not policies.exists():
|
||||||
|
return True
|
||||||
|
for policy in policies:
|
||||||
|
if policy.verify(pp, sec):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
def is_locked(self, perm):
|
||||||
|
policies = self.policies.where(Policy.type << _makelist(perm))
|
||||||
|
return policies.exists()
|
||||||
|
def is_classified(self):
|
||||||
|
return self.is_locked(POLICY_CLASSIFY)
|
||||||
|
|
||||||
|
|
||||||
class PageText(BaseModel):
|
class PageText(BaseModel):
|
||||||
content = BlobField()
|
content = BlobField()
|
||||||
|
|
@ -125,11 +159,11 @@ class PageText(BaseModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
class PageRevision(BaseModel):
|
class PageRevision(BaseModel):
|
||||||
page = FK(Page, backref='revisions')
|
page = FK(Page, backref='revisions', index=True)
|
||||||
user_id = IntegerField(default=0)
|
user_id = IntegerField(default=0)
|
||||||
comment = CharField(256, default='')
|
comment = CharField(1024, default='')
|
||||||
textref = FK(PageText)
|
textref = FK(PageText)
|
||||||
pub_date = DateTimeField()
|
pub_date = DateTimeField(index=True)
|
||||||
length = IntegerField()
|
length = IntegerField()
|
||||||
@property
|
@property
|
||||||
def text(self):
|
def text(self):
|
||||||
|
|
@ -138,8 +172,8 @@ class PageRevision(BaseModel):
|
||||||
return md(self.text)
|
return md(self.text)
|
||||||
|
|
||||||
class PageTag(BaseModel):
|
class PageTag(BaseModel):
|
||||||
page = ForeignKeyField(Page, backref='tags')
|
page = FK(Page, backref='tags', index=True)
|
||||||
name = CharField(64)
|
name = CharField(64, index=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
indexes = (
|
indexes = (
|
||||||
(('page', 'name'), True),
|
(('page', 'name'), True),
|
||||||
|
|
@ -148,7 +182,7 @@ class PageTag(BaseModel):
|
||||||
return PageTag.select().where(PageTag.name == self.name).count()
|
return PageTag.select().where(PageTag.name == self.name).count()
|
||||||
|
|
||||||
class PageProperty(BaseModel):
|
class PageProperty(BaseModel):
|
||||||
page = ForeignKeyField(Page, backref='page_meta')
|
page = ForeignKeyField(Page, backref='page_meta', index=True)
|
||||||
key = CharField(64)
|
key = CharField(64)
|
||||||
value = CharField(8000)
|
value = CharField(8000)
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -199,14 +233,49 @@ class PagePropertyDict(object):
|
||||||
return PageProperty.select().where((PageProperty.page == self._page) &
|
return PageProperty.select().where((PageProperty.page == self._page) &
|
||||||
(PageProperty.key == key)).exists()
|
(PageProperty.key == key)).exists()
|
||||||
|
|
||||||
|
# Store keys for PagePolicy.
|
||||||
|
# Experimental.
|
||||||
|
class PagePolicyKey(BaseModel):
|
||||||
|
passphrase = CharField()
|
||||||
|
sec_code = IntegerField()
|
||||||
|
class Meta:
|
||||||
|
indexes = (
|
||||||
|
(('passphrase','sec_code'), True),
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_plain(cls, pp, sec):
|
||||||
|
PagePolicyKey.create(passphrase=_passphrase_hash(pp), sec_code=sec)
|
||||||
|
def verify(self, pp, sec):
|
||||||
|
h = _passphrase_hash(pp)
|
||||||
|
return self.passphrase == h and self.sec_code == sec
|
||||||
|
|
||||||
|
POLICY_ADMIN = 1
|
||||||
|
POLICY_READ = 2
|
||||||
|
POLICY_EDIT = 3
|
||||||
|
POLICY_META = 4
|
||||||
|
POLICY_CLASSIFY = 5
|
||||||
|
|
||||||
|
# Manage policies for pages (e.g., reading or editing).
|
||||||
|
# Experimental.
|
||||||
|
class PagePolicy(BaseModel):
|
||||||
|
page = FK(Page, backref='policies', index=True, null=True)
|
||||||
|
type = IntegerField()
|
||||||
|
key = FK(PagePolicyKey, backref='applied_to')
|
||||||
|
sitewide = IntegerField(default=0)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
indexes = (
|
||||||
|
(('page', 'key'), True),
|
||||||
|
)
|
||||||
|
|
||||||
class Upload(BaseModel):
|
class Upload(BaseModel):
|
||||||
name = CharField(256)
|
name = CharField(256)
|
||||||
url_name = CharField(256, null=True)
|
url_name = CharField(256, null=True)
|
||||||
filetype = SmallIntegerField()
|
filetype = SmallIntegerField()
|
||||||
filesize = IntegerField()
|
filesize = IntegerField()
|
||||||
upload_date = DateTimeField()
|
upload_date = DateTimeField(index=True)
|
||||||
md5 = CharField(32)
|
md5 = CharField(32, index=True)
|
||||||
@property
|
@property
|
||||||
def filepath(self):
|
def filepath(self):
|
||||||
return '{0}/{1}/{2}{3}.{4}'.format(self.md5[:1], self.md5[:2], self.id,
|
return '{0}/{1}/{2}{3}.{4}'.format(self.md5[:1], self.md5[:2], self.id,
|
||||||
|
|
@ -257,7 +326,7 @@ class Upload(BaseModel):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
database.create_tables([Page, PageText, PageRevision, PageTag, PageProperty, Upload])
|
database.create_tables([Page, PageText, PageRevision, PageTag, PageProperty, PagePolicyKey, PagePolicy, Upload])
|
||||||
|
|
||||||
#### WIKI SYNTAX ####
|
#### WIKI SYNTAX ####
|
||||||
|
|
||||||
|
|
@ -438,13 +507,18 @@ def error_404(body):
|
||||||
return render_template('notfound.html'), 404
|
return render_template('notfound.html'), 404
|
||||||
|
|
||||||
|
|
||||||
# Helpers for page editing.
|
# Middle point during page editing.
|
||||||
def savepoint(form, is_preview=False):
|
def savepoint(form, is_preview=False):
|
||||||
if is_preview:
|
if is_preview:
|
||||||
preview = md(form['text'])
|
preview = md(form['text'])
|
||||||
else:
|
else:
|
||||||
preview = None
|
preview = None
|
||||||
return render_template('edit.html', pl_url=form['url'], pl_title=form['title'], pl_text=form['text'], pl_tags=form['tags'], preview=preview)
|
pl_js_info = dict()
|
||||||
|
pl_js_info['editing'] = dict(
|
||||||
|
original_text = None, # TODO
|
||||||
|
preview_text = form['text'],
|
||||||
|
)
|
||||||
|
return render_template('edit.html', pl_url=form['url'], pl_title=form['title'], pl_text=form['text'], pl_tags=form['tags'], preview=preview, pl_js_info=pl_js_info)
|
||||||
|
|
||||||
@app.route('/create/', methods=['GET', 'POST'])
|
@app.route('/create/', methods=['GET', 'POST'])
|
||||||
def create():
|
def create():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue