Commit 592130083bf076a6253b7da2dd15759d3a5f29e4
1 parent
a4925cb4
Exists in
master
and in
1 other branch
- 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,16 +18,25 @@ This can be done using the system package management, downloaded from [http://ww | ||
18 | - `./configure --prefix=$HOME/.local/bin` | 18 | - `./configure --prefix=$HOME/.local/bin` |
19 | - `make && make install` | 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 | Next install pip (if not yet installed): | 23 | Next install pip (if not yet installed): |
22 | 24 | ||
23 | - python36 -m ensurepip --user | 25 | + python3.6 -m ensurepip --user |
24 | 26 | ||
25 | This will install pip in your account under `~/.local/bin`. | 27 | This will install pip in your account under `~/.local/bin`. |
26 | 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`). | 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 | Install additional python packages locally on the user area: | 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 | These are usually installed under | 41 | These are usually installed under |
33 | 42 | ||
@@ -46,23 +55,71 @@ Replace USER by your bitbucket username: | @@ -46,23 +55,71 @@ Replace USER by your bitbucket username: | ||
46 | cd path/to/some/directory | 55 | cd path/to/some/directory |
47 | git clone https://USER@bitbucket.org/USER/aprendizations.git | 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 | cd aprendizations | 60 | cd aprendizations |
52 | 61 | ||
53 | ## Configuration | 62 | ## Configuration |
54 | 63 | ||
64 | +### Database | ||
65 | + | ||
55 | First we need to create a database: | 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 | ./initdb.py --help # for the available options | 70 | ./initdb.py --help # for the available options |
59 | 71 | ||
72 | +### SSL Certificates | ||
73 | + | ||
60 | We also need certificates for https. Generate selfsigned certificates using openssl: | 74 | We also need certificates for https. Generate selfsigned certificates using openssl: |
61 | 75 | ||
62 | - cd certs | ||
63 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes | 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 | Run a demonstration: | 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,14 +178,14 @@ class LearnApp(object): | ||
178 | 178 | ||
179 | # Builds factories for each node | 179 | # Builds factories for each node |
180 | for n in g.nodes_iter(): | 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 | if path.isdir(fullpath): | 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 | for q in questions: | 189 | for q in questions: |
190 | q['path'] = fullpath | 190 | q['path'] = fullpath |
191 | 191 |
questions.py
@@ -406,7 +406,7 @@ class QFactory(object): | @@ -406,7 +406,7 @@ class QFactory(object): | ||
406 | # i.e. a question object (radio, checkbox, ...). | 406 | # i.e. a question object (radio, checkbox, ...). |
407 | # ----------------------------------------------------------------------- | 407 | # ----------------------------------------------------------------------- |
408 | def generate(self): | 408 | def generate(self): |
409 | - logger.debug(f'generate "{self.question["ref"]}"') | 409 | + logger.debug(f'Generating "{self.question["ref"]}"') |
410 | # Shallow copy so that script generated questions will not replace | 410 | # Shallow copy so that script generated questions will not replace |
411 | # the original generators | 411 | # the original generators |
412 | q = self.question.copy() | 412 | q = self.question.copy() |