master.py: update forums with stateful logic

The create-forums function has been replaced with an [update] subcommand
of [forums]. This new function tries its best to keep existing forum
objects, which is especially important once content has been created.

Forums are identified by their URL. Changing the URL means the forum
needs to be recreated. If the URL doesn't changed, metadata is updated
without removing topics and subforums in that forum.

* Improve the update model for forums in master.py
* Fix a typo in the prefix for the tool projects subforum
* Add the admin and assoc boards for permission testing
This commit is contained in:
Lephe 2020-11-01 10:50:52 +01:00
parent cf9cb8a8c6
commit 75f3a90f20
Signed by untrusted user: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
2 changed files with 71 additions and 23 deletions

View File

@ -85,7 +85,7 @@
/projets/outils:
name: Projets pour d'autres plateformes
prefix: toolprojetcs
prefix: toolprojects
descr: Tous les projets tournant sur ordinateur, téléphone, ou toute autre
plateforme que la calculatrice.
@ -103,3 +103,18 @@
name: Discussion
prefix: discussion
descr: Sujets hors-sujet et discussion libre.
# Limited-access board
# Prefixes "admin" and "assoc" are reserved for this and require special
# privileges to list, read and edit topics and messages.
/admin:
name: Administration
prefix: admin
descr: Discussions sur l'administration du site, accessible uniquement aux
membres de l'équipe.
/creativecalc:
name: CreativeCalc
prefix: assoc
descr: Forum privé de l'association CreativeCalc, réservé aux membres.

View File

@ -24,7 +24,10 @@ Type a category name to see a list of elements. Available categories are:
'trophy-members' Trophies owned by members
'forums' Forum tree
Type a category name followed by 'clear' to remove all entries in the category.
For each category, an argument can be specified:
* 'clear' will remove all entries in the category (destroys a lot of data!)
* 'update' will update from the model in app/data/, when applicable
(currently available on: forums)
Type 'create-groups-and-privs' to recreate all groups and privileges to the
default. This function generates a minimal set of groups and members to prepare
@ -41,8 +44,6 @@ Type 'add-group <member> #<group-id>' to add a new member to a group.
Type 'create-trophies' to reset trophies and titles and their icons.
Type 'create-forums' to reset the forum tree.
Type 'enable-user' to enable a email-disabled account.
"""
@ -100,6 +101,10 @@ def forums(*args):
print("Removed all forums.")
return
if args == ("update",):
update_forums()
return
for f in Forum.query.all():
parent = f"in {f.parent.url}" if f.parent is not None else "root"
print(f"{f.url} ({parent}) [{f.prefix}]: {f.name}")
@ -218,17 +223,17 @@ def create_trophies_icons():
icon.save(os.path.join(dst, f"{name}.png"))
def create_forums():
# Clean up forums
forums("clear")
def update_forums():
# Get current forums
existing = Forum.query.all()
# Create the forum tree
# Get the list of forums we want to end up with
fr = []
success = 0
with open(os.path.join(app.root_path, "data", "forums.yaml")) as fp:
fr = yaml.safe_load(fp.read())
for url, f in fr.items():
for url, info in fr.items():
if url == "/":
parent = None
else:
@ -241,12 +246,33 @@ def create_forums():
print(f"error: no parent with url {parent_url} for {url}")
continue
f = Forum(url, f['name'], f['prefix'], f.get('descr', ''), parent)
descr = info.get("descr", "")
# Either change an existing forum endpoint (same URL) or create one
f = Forum.query.filter_by(url=url).first()
if f is not None:
# No need to change the parent (same URL implies same parent)
changes = (f.name != info["name"]) or (f.prefix != info["prefix"])\
or (f.descr != descr)
f.name = info["name"]
f.prefix = info["prefix"]
f.descr = descr
if changes:
print(f"[forum] Updated {url}")
else:
f = Forum(url, info["name"], info["prefix"], descr, parent)
print(f"[forum] Created {url}")
db.session.add(f)
success += 1
# Remove old forums
for f in existing:
if f.url not in fr:
f.delete()
print(f"[forum] Removed {f.url}")
db.session.commit()
print(f"Created {success} forums.")
def add_group(member, group):
if group[0] != "#":
@ -282,8 +308,6 @@ def enable_user(member):
# Main program
#
print(help_msg)
commands = {
"exit": lambda: sys.exit(0),
"members": members,
@ -294,21 +318,30 @@ commands = {
"create-groups-and-privs": create_groups_and_privs,
"create-trophies": create_trophies,
"create-trophies-icons": create_trophies_icons,
"create-forums": create_forums,
"add-group": add_group,
"enable-user": enable_user,
}
while True:
try:
print("@> ", end="")
cmd = input().split()
except EOFError:
sys.exit(0)
if not cmd:
continue
def execute(cmd):
if cmd[0] not in commands:
print(f"error: unknown command '{cmd[0]}'")
else:
commands[cmd[0]](*cmd[1:])
# If a command is specified on the command-line, use it and do not prompt
if len(sys.argv) > 1:
execute(sys.argv[1:])
sys.exit(0)
# Otherwise, prompt interactively
else:
print(help_msg)
while True:
try:
print("@> ", end="")
cmd = input().split()
except EOFError:
sys.exit(0)
if cmd:
execute(cmd)