Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • devel
  • fo
  • fo-base
  • honza/add-contestant
  • honza/kolo-vs-soutez
  • honza/mr6
  • honza/mr7
  • honza/mra
  • honza/mrd
  • honza/mrf
  • honza/submit-images
  • jh-stress-test-wip
  • jirka/typing
  • jk/issue-196
  • jk/issue-96
  • master
  • mj/submit-images
  • shorten-schools
18 results

Target

Select target project
  • mj/mo-submit
1 result
Select Git revision
  • devel
  • fo
  • fo-base
  • honza/add-contestant
  • honza/kolo-vs-soutez
  • honza/mr6
  • honza/mr7
  • honza/mra
  • honza/mrd
  • honza/mrf
  • honza/submit-images
  • jh-stress-test-wip
  • jirka/typing
  • jk/issue-196
  • jk/issue-96
  • master
  • mj/submit-images
  • shorten-schools
18 results
Show changes

Commits on Source 6

- nastavit cestu k cookies - nastavit cestu k cookies
- poznámka u uživatele
- budeme znát roky narození? - budeme znát roky narození?
- uklidit v logování - uklidit v logování
- na import by bylo hezké mít testy - na import by bylo hezké mít testy
- pamatovat si IČO školy (kvůli Excelenci)?
- ostylovat login form - ostylovat login form
- export: lidská jména stavů
Nasazení: Nasazení:
- kontakt na správce - kontakt na správce
......
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import re
import sys
import mo.db as db import mo.db as db
import mo.util import mo.util
from mo.util import die
parser = argparse.ArgumentParser(description='Přidělí uživateli roli') parser = argparse.ArgumentParser(description='Přidělí uživateli roli')
parser.add_argument('--email', type=str, help='e-mailová adresa uživatele') parser.add_argument('--email', type=str, help='e-mailová adresa uživatele')
parser.add_argument('--uid', type=int, help='ID uživatele') parser.add_argument('--uid', type=int, help='ID uživatele')
parser.add_argument('--role', type=str, help='název role', required=True) parser.add_argument('--role', type=str, help='název role', required=True)
parser.add_argument('--place-id', type=int, help='omezení role na místo s daným ID') parser.add_argument('--place', type=str, help='omezení role na místo s daným kódem')
parser.add_argument('--cat', type=str, help='omezení role na danou kategorii') parser.add_argument('--cat', type=str, help='omezení role na danou kategorii')
parser.add_argument('--round', type=str, metavar='YY-R', help='omezení role na dané kolo') parser.add_argument('--year', type=int, help='omezení role na daný ročník')
parser.add_argument('--seq', type=int, help='omezení role na dané pořadí kola')
args = parser.parse_args() args = parser.parse_args()
session = db.get_session() session = db.get_session()
...@@ -29,58 +29,39 @@ else: ...@@ -29,58 +29,39 @@ else:
parser.error('Je nutné vybrat uživatele pomocí --email nebo --uid') parser.error('Je nutné vybrat uživatele pomocí --email nebo --uid')
if not user: if not user:
print("Tento uživatel neexistuje", file=sys.stderr) die("Tento uživatel neexistuje")
sys.exit(1)
if user.is_admin: if user.is_admin:
print("Tento uživatel je admin, nemá smysl přidělovat mu další práva", file=sys.stderr) die("Tento uživatel je admin, nemá smysl přidělovat mu další práva")
sys.exit(1)
if not user.is_org: if not user.is_org:
print("Tento uživatel není organizátor", file=sys.stderr) die("Tento uživatel není organizátor")
sys.exit(1)
role = getattr(db.RoleType, args.role, None) role = getattr(db.RoleType, args.role, None)
if role is None: if role is None:
print("Tato role neexistuje", file=sys.stderr) die("Tato role neexistuje")
sys.exit(1)
for_round = None if args.place:
if args.round: for_place = db.get_place_by_code(args.place)
m = re.fullmatch(r'(\d+)-(\d+)', args.round) if for_place is None:
if not m: die("Toto místo neexistuje")
parser.error('Chybná syntaxe --round')
if not args.cat:
parser.error('--round vyžaduje zadání kategorie')
round = session.query(db.Round).filter_by(year=int(m[1]), category=args.cat, level=int(m[2])).first()
if not round:
print("Toto kolo neexistuje", file=sys.stderr)
sys.exit(1)
for_round = round.round_id
if args.place_id:
for_place = args.place_id
else: else:
place = session.query(db.Place).filter_by(level=1).first() for_place = db.get_root_place()
assert place
for_place = place.place_id
assert for_place is not None
ur = db.UserRole( ur = db.UserRole(
user_id=user.user_id, user_id=user.user_id,
place_id=for_place, place=for_place,
role=role, role=role,
category=args.cat, category=args.cat,
round_id=for_round, year=args.year,
seq=args.seq,
) )
session.add(ur) session.add(ur)
session.flush() session.flush()
mo.util.log(db.LogType.user_role, ur.user_role_id, { mo.util.log(db.LogType.user_role, ur.user_role_id, {
'action': 'assigned', 'action': 'assigned',
'user_id': ur.user_id, 'new': db.row2dict(ur),
'place_id': ur.place_id,
'role': role.name,
'category': ur.category,
'round_id': ur.round_id,
}) })
session.commit() session.commit()
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import sys
import mo.db as db import mo.db as db
import mo.util import mo.util
from mo.util import die
parser = argparse.ArgumentParser(description='Založí soutěže pro dané kolo') parser = argparse.ArgumentParser(description='Založí soutěže pro dané kolo')
parser.add_argument(dest='round_id', type=int, help='ID kola') parser.add_argument(dest='round', type=str, metavar='YY-C-S', help='ID kola')
parser.add_argument('-n', '--dry-run', default=False, action='store_true', help='pouze ukáže, co by bylo provedeno') parser.add_argument('-n', '--dry-run', default=False, action='store_true', help='pouze ukáže, co by bylo provedeno')
args = parser.parse_args() args = parser.parse_args()
sess = db.get_session() sess = db.get_session()
round = sess.query(db.Round).get(args.round_id) round_code = mo.util.RoundCode.parse(args.round)
if not round: if round_code is None:
print("Kolo s tímto ID neexistuje!", file=sys.stderr) die("Chybná syntaxe kódu kola")
sys.exit(1) round = mo.util.get_round_by_code(round_code)
if round is None:
die("Kolo s tímto kódem neexistuje!")
regions = sess.query(db.Place).filter_by(level=round.level).all() regions = sess.query(db.Place).filter_by(level=round.level).all()
assert regions, "Neexistují žádná místa dané úrovně" assert regions, "Neexistují žádná místa dané úrovně"
for r in regions: for r in regions:
print(f"Zakládám pro místo {r.name}") print(f"Zakládám {round.round_code()} pro místo {r.name}")
if not args.dry_run: if not args.dry_run:
c = db.Contest(round=round, place=r) c = db.Contest(round=round, place=r)
sess.add(c) sess.add(c)
......
#!/usr/bin/env python3
import argparse
import mo.db as db
import mo.util
parser = argparse.ArgumentParser(description='Založí soutěžní kolo')
parser.add_argument('-y', '--year', type=int, required=True, help='ročník')
parser.add_argument('-c', '--cat', type=str, required=True, help='kategorie')
parser.add_argument('-s', '--seq', type=int, required=True, help='pořadí kola')
parser.add_argument('-l', '--level', type=int, required=True, help='úroveň v hierarchii oblastí')
parser.add_argument('-n', '--name', type=str, required=True, help='název kola')
args = parser.parse_args()
sess = db.get_session()
rnd = db.Round(
year=args.year,
category=args.cat,
seq=args.seq,
level=args.level,
name=args.name,
)
sess.add(rnd)
sess.flush()
mo.util.log(
type=db.LogType.round,
what=rnd.round_id,
details={
'action': 'created',
'new': db.row2dict(rnd),
},
)
sess.commit()
#!/usr/bin/env python3 #!/usr/bin/env python3
import mo.db as db import mo.db as db
import mo.users
import mo.util import mo.util
import argparse import argparse
...@@ -11,6 +12,7 @@ parser.add_argument(dest='first_name', help='křestní jméno (jedno nebo více) ...@@ -11,6 +12,7 @@ parser.add_argument(dest='first_name', help='křestní jméno (jedno nebo více)
parser.add_argument(dest='last_name', help='příjmení (jedno nebo více)') parser.add_argument(dest='last_name', help='příjmení (jedno nebo více)')
parser.add_argument('--org', default=False, action='store_true', help='přidělí uživateli organizátorská práva') parser.add_argument('--org', default=False, action='store_true', help='přidělí uživateli organizátorská práva')
parser.add_argument('--admin', default=False, action='store_true', help='přidělí uživateli správcovská práva') parser.add_argument('--admin', default=False, action='store_true', help='přidělí uživateli správcovská práva')
parser.add_argument('--passwd', type=str, help='nastaví počáteční heslo')
args = parser.parse_args() args = parser.parse_args()
...@@ -32,4 +34,8 @@ mo.util.log(db.LogType.user, user.user_id, { ...@@ -32,4 +34,8 @@ mo.util.log(db.LogType.user, user.user_id, {
'is_org': user.is_org, 'is_org': user.is_org,
'is_admin': user.is_admin 'is_admin': user.is_admin
}) })
if args.passwd is not None:
mo.users.set_password(user, args.passwd)
session.commit() session.commit()
...@@ -30,7 +30,6 @@ def import_schools(path: Path, nuts: str): ...@@ -30,7 +30,6 @@ def import_schools(path: Path, nuts: str):
with path.open('r') as file: with path.open('r') as file:
columns = parse_header(file.readline()) columns = parse_header(file.readline())
print(columns)
for line in file: for line in file:
f = line.split('\t') f = line.split('\t')
red_izo = f[columns['Red IZO']] red_izo = f[columns['Red IZO']]
......
#!/bin/bash
set -e
psql mo_osmo <db/drop-all.sql
psql mo_osmo <db/db.ddl
bin/init-regions
bin/init-schools
bin/create-user mj@ucw.cz Martin Mareš --admin --passwd brum
bin/create-user medved@ucw.cz Baltasis Lokys --org --passwd brum
bin/add-role --email medved@ucw.cz --role garant --cat P
bin/add-role --email medved@ucw.cz --role garant --cat A --place PB
bin/create-round -y 70 -c P -s 1 -n 'Školní kolo' -l 1
bin/create-round -y 70 -c P -s 2 -n 'Krajské kolo' -l 1
bin/create-round -y 70 -c P -s 3 -n 'Ústřední kolo' -l 0
bin/create-round -y 70 -c A -s 1 -n 'Školní kolo (domácí)' -l 1
bin/create-round -y 70 -c A -s 2 -n 'Školní kolo (klauzurní)' -l 1
bin/create-round -y 70 -c A -s 3 -n 'Krajské kolo' -l 1
bin/create-round -y 70 -c A -s 4 -n 'Ústřední kolo' -l 0
bin/create-contests 70-P-2
bin/create-contests 70-A-3
INSERT INTO rounds(year, category, seq, level, name) VALUES
(1, 70, 'A', 1, 'Krajské kolo' , 3 ),
(2, 70, 'A', 0, 'Ústrední kolo' , 4 ),
(3, 70, 'A', 4, 'Školní kolo (domácí)' , 1 ),
(5, 70, 'A', 4, 'Školní kolo (klauzurní)', 2 ),
(6, 70, 'P', 0, 'Školní kolo' , 1 ),
(7, 70, 'P', 1, 'Krajské kolo' , 2 ),
(8, 70, 'P', 0, 'Ústřední kolo' , 3 );
...@@ -279,7 +279,7 @@ class UserRole(Base): ...@@ -279,7 +279,7 @@ class UserRole(Base):
year = Column(Integer) year = Column(Integer)
seq = Column(Integer) seq = Column(Integer)
assigned_by = Column(Integer, ForeignKey('users.user_id')) assigned_by = Column(Integer, ForeignKey('users.user_id'))
assigned_at = Column(DateTime(True)) assigned_at = Column(DateTime(True), nullable=False, server_default=text("CURRENT_TIMESTAMP"))
user = relationship('User', primaryjoin='UserRole.user_id == User.user_id') user = relationship('User', primaryjoin='UserRole.user_id == User.user_id')
assigned_by_user = relationship('User', primaryjoin='UserRole.assigned_by == User.user_id') assigned_by_user = relationship('User', primaryjoin='UserRole.assigned_by == User.user_id')
......
# Různé # Různé
from dataclasses import dataclass
import datetime import datetime
import email.message import email.message
import email.headerregistry import email.headerregistry
import re import re
from sqlalchemy.orm import joinedload
import subprocess import subprocess
from typing import Any, Optional import sys
from typing import Any, Optional, NoReturn
import textwrap import textwrap
import mo.db as db import mo.db as db
...@@ -64,3 +65,30 @@ def send_password_reset_email(user: db.User, link: str): ...@@ -64,3 +65,30 @@ def send_password_reset_email(user: db.User, link: str):
if sm.returncode != 0: if sm.returncode != 0:
raise RuntimeError('Sendmail failed with return code {}'.format(sm.returncode)) raise RuntimeError('Sendmail failed with return code {}'.format(sm.returncode))
def die(msg: str) -> NoReturn:
print(msg, file=sys.stderr)
sys.exit(1)
@dataclass
class RoundCode:
year: int
cat: str
seq: int
def __str__(self):
return f'{self.year}-{self.cat}-{self.seq}'
@staticmethod
def parse(code: str) -> Optional['RoundCode']:
m = re.match(r'(\d+)-([A-Z0-9]+)-(\d+)', code)
if m:
return RoundCode(year=int(m[1]), cat=m[2], seq=int(m[3]))
else:
return None
def get_round_by_code(code: RoundCode) -> Optional[db.Round]:
return db.get_session().query(db.Round).filter_by(year=code.year, category=code.cat, seq=code.seq).one_or_none()