Commit 592130083bf076a6253b7da2dd15759d3a5f29e4

Authored by Miguel Barão
1 parent a4925cb4
Exists in master and in 1 other branch dev

- fixed user path expansion

Showing 3 changed files with 71 additions and 14 deletions   Show diff stats
README.md
... ... @@ -18,16 +18,25 @@ This can be done using the system package management, downloaded from [http://ww
18 18 - `./configure --prefix=$HOME/.local/bin`
19 19 - `make && make install`
20 20  
  21 +This will install python locally under `~/.local/bin`. Make sure to add it to your `PATH` (edit `~/.profile` in OSX or FreeBSD).
  22 +
21 23 Next install pip (if not yet installed):
22 24  
23   - python36 -m ensurepip --user
  25 + python3.6 -m ensurepip --user
24 26  
25 27 This will install pip in your account under `~/.local/bin`.
26 28 In the end you should be able to run `pip3 --version` and `python3 -c "import sqlite3"` without errors (sometimes `pip3` is `pip`, `pip3.6` or `pip-3.6`).
27 29  
28 30 Install additional python packages locally on the user area:
29 31  
30   - pip install --user tornado sqlalchemy pyyaml pygments markdown bcrypt networkx
  32 + pip3 install --user \
  33 + tornado \
  34 + sqlalchemy \
  35 + pyyaml \
  36 + pygments \
  37 + markdown \
  38 + bcrypt \
  39 + networkx
31 40  
32 41 These are usually installed under
33 42  
... ... @@ -46,23 +55,71 @@ Replace USER by your bitbucket username:
46 55 cd path/to/some/directory
47 56 git clone https://USER@bitbucket.org/USER/aprendizations.git
48 57  
49   -A directory aprendizations will be created with the software:
  58 +A directory `aprendizations` will be created with the software:
50 59  
51 60 cd aprendizations
52 61  
53 62 ## Configuration
54 63  
  64 +### Database
  65 +
55 66 First we need to create a database:
56 67  
57   - ./initdb.py # initialize with a single user `0` and empty password
  68 + ./initdb.py # initialize user `0` and empty password
  69 + ./initdb.py --pw alibaba # initialize user `0` and given password
58 70 ./initdb.py --help # for the available options
59 71  
  72 +### SSL Certificates
  73 +
60 74 We also need certificates for https. Generate selfsigned certificates using openssl:
61 75  
62   - cd certs
63 76 openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
64   - cd ..
  77 +
  78 +and place them in `aprendizations/certs`.
  79 +
  80 +### Testing
65 81  
66 82 Run a demonstration:
67 83  
68   - ./serve.py
  84 + ./serve.py demo/demo.yaml
  85 +
  86 +and open a browser at `https://127.0.0.1:8443`.
  87 +
  88 +### Firewall configuration
  89 +
  90 +Ports 80 and 443 are only usable by root. For security reasons it is better to run the server as a regular user on higher ports like 8080 for http and 8443 for https. In this case, we should configure port forwarding in the firewall to redirect incoming tcp traffic from 80 to 8080 and 443 to 8443.
  91 +
  92 +#### FreeBSD and pf
  93 +
  94 +Edit `/etc/pf.conf`:
  95 +
  96 + ext_if="em0"
  97 + rdr on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080
  98 + rdr on $ext_if proto tcp from any to any port 443 -> 127.0.0.1 port 8443
  99 +
  100 +or `ext_if="vtnet0"` for guest additions under virtual box.
  101 +
  102 +Edit `rc.conf`
  103 +
  104 + pf_enable="YES"
  105 + pf_flags=""
  106 + pf_rules="/etc/pf.conf"
  107 +
  108 + # optional logging:
  109 + pflog_enable="YES"
  110 + pflog_flags=""
  111 + pflog_logfile="/var/log/pflog"
  112 +
  113 +Reboot.
  114 +
  115 +## Troubleshooting
  116 +
  117 +#### UnicodeEncodeError
  118 +
  119 +The server should not generate this error, but when using external scripts to generate questions or to correct, these scripts can print unicode strings to stdout. If the terminal does not support unicode, python will generate this exception.
  120 +
  121 +To correct in FreeBSD, edit `~/.login_conf` to use UTF-8, for example:
  122 +
  123 + me:\
  124 + :charset=UTF-8:\
  125 + :lang=en_US.UTF-8:
... ...
app.py
... ... @@ -178,14 +178,14 @@ class LearnApp(object):
178 178  
179 179 # Builds factories for each node
180 180 for n in g.nodes_iter():
181   - fullpath = path.join(prefix, n)
182   - # if name is directory defaults to "prefix/questions.yaml"
  181 + fullpath = path.expanduser(path.join(prefix, n))
183 182 if path.isdir(fullpath):
184   - filename = path.join(fullpath, "questions.yaml")
  183 + # if directory defaults to "prefix/questions.yaml"
  184 + fullpath = path.join(fullpath, "questions.yaml")
185 185  
186   - if path.isfile(filename):
187   - logger.info(f'Loading questions from "{filename}"')
188   - questions = load_yaml(filename, default=[])
  186 + if path.isfile(fullpath):
  187 + logger.info(f'Loading questions from "{fullpath}"')
  188 + questions = load_yaml(fullpath, default=[])
189 189 for q in questions:
190 190 q['path'] = fullpath
191 191  
... ...
questions.py
... ... @@ -406,7 +406,7 @@ class QFactory(object):
406 406 # i.e. a question object (radio, checkbox, ...).
407 407 # -----------------------------------------------------------------------
408 408 def generate(self):
409   - logger.debug(f'generate "{self.question["ref"]}"')
  409 + logger.debug(f'Generating "{self.question["ref"]}"')
410 410 # Shallow copy so that script generated questions will not replace
411 411 # the original generators
412 412 q = self.question.copy()
... ...