Переглянути джерело

add website to repo

tags/current_release
adam j hartz 5 місяці тому
джерело
коміт
e796fdaae3

BIN
website/__STATIC__/cc-by-sa.png Переглянути файл


+ 93
- 0
website/__STATIC__/main.template Переглянути файл

@@ -0,0 +1,93 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<!-- This page was generated by CAT-SOOP (v{cs_version}).  miau. -->
5
+
6
+<meta charset="UTF-8">
7
+<title>{cs_title}</title>
8
+<link rel="icon" href="{cs_icon_url}" type="image/gif" />
9
+
10
+<!-- jQuery and Bootstrap -->
11
+<script src="BASE/scripts/jquery.js"></script>
12
+<link rel="stylesheet" href="BASE/themes/bootstrap.css" />
13
+<script src="BASE/scripts/bootstrap.js"></script>
14
+
15
+<!-- automatically adjust the top padding so that the whole page is visible even if the navbar's height changes -->
16
+<script type="text/javascript">
17
+var set_top_margin = function(){{
18
+    $("#myPage").css('padding-top', $('#cs_main_navbar').height());
19
+}}
20
+
21
+$(document).ready(set_top_margin);
22
+$('#cs_main_navbar').resize(set_top_margin);
23
+var catsoop = {{}};
24
+</script>
25
+
26
+<!-- Additional styling specific for course-->
27
+<link rel="stylesheet" type="text/css" href="{cs_theme}" />
28
+
29
+<!-- load in katex and mathjax, and CAT-SOOP-specific math rendering  -->
30
+<script type="text/javascript" src="BASE/scripts/katex/katex.min.js"></script>
31
+<link rel="stylesheet" type="text/css" href="BASE/scripts/katex/katex.min.css" />
32
+<script type="text/javascript" src="BASE/scripts/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
33
+<script type="text/javascript" src="BASE/scripts/cs_math.js"></script>
34
+
35
+<!-- CAT-SOOP Hashing -->
36
+<script type="text/javascript" src="BASE/scripts/cs_hash.js"></script>
37
+
38
+<!-- Syntax Highlighting -->
39
+<link rel="stylesheet" href="BASE/scripts/highlight/styles/catsoop.css">
40
+<script type="text/javascript" src="BASE/scripts/highlight/highlight.pack.js"></script>
41
+<script type="text/javascript">
42
+hljs.initHighlightingOnLoad();
43
+</script>
44
+
45
+{cs_scripts}
46
+
47
+<meta name="viewport" content="width=device-width, initial-scale=1" />
48
+</head>
49
+<body id="myPage">
50
+
51
+<nav class="navbar navbar-default navbar-fixed-top" id="cs_main_navbar">
52
+  <div class="container">
53
+    <div class="navbar-header">
54
+      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
55
+        <span class="icon-bar"></span>
56
+        <span class="icon-bar"></span>
57
+        <span class="icon-bar"></span>
58
+      </button>
59
+      <div class="navbar-brand"><a href="{cs_home_link}">{cs_header}</a></div><div class="navbar-brand"><div class="logininfo">{cs_welcome_message}</div></div>
60
+    </div>
61
+    <div class="collapse navbar-collapse" id="myNavbar">
62
+      <ul class="nav navbar-nav navbar-right">
63
+          {cs_top_menu}
64
+      </ul>
65
+    </div>
66
+  </div>
67
+</nav>
68
+  <center>
69
+  <h1>{cs_content_header}</h1>
70
+  </center>
71
+
72
+<div class="container">
73
+  <div class="row">
74
+    <div class="col-md-2"></div>
75
+    <div class="col-md-8">
76
+      {cs_content}
77
+      {cs_footnotes}
78
+    </div>
79
+    <div class="col-md-2"></div>
80
+  </div>
81
+</div>
82
+<div id="bottom_menu">
83
+  {cs_bottom_menu}
84
+</div>
85
+
86
+<div id="footer">
87
+    {cs_footer}
88
+    Powered by <a href='https://catsoop.mit.edu'>CAT-SOOP</a> v{cs_version}<br/>
89
+    (<a href="BASE/cs_util/license" target="_blank">View License</a>, <a href="BASE/cs_util/source.zip{cs_source_qstring}" download>Download Source Code</a>)
90
+<pre class="catsooplogo" style="font-size:50%;">{cs_base_logo_text}</pre>
91
+    </div>
92
+</body>
93
+</html>

+ 59
- 0
website/content.md Переглянути файл

@@ -0,0 +1,59 @@
1
+<div style="text-align:center; width:100%;" margin-top:0px;>
2
+<pre style="font-weight:bold;line-height:1.1;background-color:transparent;border-color:transparent;font-size:16pt;text-align:left;display:inline-block; margin-top:0px;">
3
+\
4
+/    /\__/\
5
+\__=(  o_O )=
6
+(__________)
7
+ |_ |_ |_ |_
8
+</pre>
9
+</div>
10
+
11
+<center>
12
+<a class="btn btn-catsoop" href="https://hz.mit.edu/git/catsoop/catsoop/archive/current_release.zip">Download</a>
13
+<a class="btn btn-catsoop" href="COURSE/docs">Documentation</a>
14
+<a class="btn btn-catsoop" href="https://git.sr.ht/~adqm/catsoop">Repository</a>
15
+<a class="btn btn-catsoop" href="https://todo.sr.ht/~adqm/catsoop">Issue Tracker</a>
16
+</center>
17
+
18
+
19
+## WHAT IS IT?
20
+
21
+CAT-SOOP is a tool for automatic collection and assessment of online exercises,
22
+originally developed primarily for use in MIT's 6.01 (_Introduction to
23
+Electrical Engineering and Computer Science via Robotics_).  It has since been
24
+used in several courses at MIT and at Olin College.
25
+
26
+**More information:**
27
+
28
+* Web Site:
29
+    * <https://catsoop.mit.edu>
30
+    * Tor onion service: <http://5jqwpybqkwagsgmwskjoxawlfjl5j52nhvkmni7bwgwu37pmwrnbexyd.onion>
31
+
32
+* Repository Web Access: <https://git.sr.ht/~adqm/catsoop>
33
+
34
+* Clone Repository:
35
+    `git clone https://git.sr.ht/~adqm/catsoop`
36
+
37
+* IRC: `#catsoop` on OFTC (`irc.oftc.net`)
38
+
39
+* Mailing lists:
40
+
41
+    * `~adqm/catsoop@lists.sr.ht` for general-purpose discussion, questions, feedback ([archives/subscribe](https://lists.sr.ht/~adqm/catsoop))
42
+    * `~adqm/catsoop-announce@lists.sr.ht`, low volume list for announcing new versions, features, etc ([archives/subscribe](https://lists.sr.ht/~adqm/catsoop-announce))
43
+    * `~adqm/catsoop-dev@lists.sr.ht` for development-related discussion, including patch submission ([archives/subscribe](https://lists.sr.ht/~adqm/catsoop-dev))
44
+
45
+## CAN I USE IT FOR MY COURSE?
46
+
47
+Of course!  CAT-SOOP is [free/libre
48
+software](https://www.gnu.org/philosophy/free-sw.html), available under the
49
+terms of the [GNU Affero General Public License, version 3+](BASE/cs_util/license).
50
+Please note that the terms of this license apply to the CAT-SOOP system itself,
51
+to any third-party software included with CAT-SOOP, and to any plugins used by
52
+the system, but not to any course material hosted on a CAT-SOOP instance,
53
+unless explicitly stated otherwise.
54
+
55
+See the [documentation](COURSE/docs) for more information.
56
+
57
+## IS IT ANY GOOD?
58
+
59
+Yes.

+ 26
- 0
website/docs/about/content.md Переглянути файл

@@ -0,0 +1,26 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+@{todo}
6
+
7
+# Courses Using CAT-SOOP
8
+
9
+The following are some of the courses I know of that use (or have used) CAT-SOOP:
10
+
11
+* MIT 6.01: _Introduction to EECS via Robotics_
12
+* MIT 6.02: _Introduction to EECS via Communications Networks_
13
+* MIT 6.08: _Interconnected Embedded Systems_
14
+* MIT 6.145: _A Brief Introduction to Programming in Python_
15
+* MIT 6.002: _Circuits and Electronics_
16
+* MIT 6.003: _Signal Processing_
17
+* MIT 6.006: _Introduction to Algorithms_
18
+* MIT 6.009: _Fundamentals of Programming_
19
+* MIT 6.036: _Introduction to Machine Learning_
20
+* MIT 6.302: _Feedback System Design_
21
+* MIT 6.A01: _Mens et Manus_ Freshman Seminar
22
+* Olin College MTH 2132/SCI 2032: _Bayesian Inference and Reasoning_
23
+* Olin College ENGR2340: _Dynamics_
24
+* Olin College SCI2050: _The Art of Approximation in Science and Engineering_
25
+
26
+If you use CAT-SOOP in your class, please [let me know](mailto:hz@mit.edu)!

+ 3
- 0
website/docs/about/preload.py Переглянути файл

@@ -0,0 +1,3 @@
1
+cs_order = 0
2
+cs_long_name = "About CAT-SOOP"
3
+cs_title = 'About | %s' % (cs_title, )

+ 94
- 0
website/docs/api/content.py Переглянути файл

@@ -0,0 +1,94 @@
1
+import ast
2
+import inspect
3
+
4
+module = cs_form.get('p', 'catsoop')
5
+
6
+cs_problem_spec = []
7
+
8
+if not (module.startswith('catsoop.') or module == 'catsoop'):
9
+    module = 'catsoop'
10
+
11
+def _print(*args):
12
+    cs_problem_spec.extend(str(i) for i in args)
13
+    cs_problem_spec.append('\n')
14
+
15
+broke = False
16
+try:
17
+    module = __import__(module, fromlist='dummy')
18
+except:
19
+    broke = True
20
+
21
+if not broke:
22
+    if module != 'catsoop':
23
+        cs_content_header += ': <code>%s</code>' % module.__name__
24
+
25
+    if module.__file__.endswith('__init__.py'):
26
+        # this is a package; list its contents
27
+        if module.__doc__ is not None:
28
+            _print(module.__doc__)
29
+            _print()
30
+        _print('## Members:')
31
+        for child in sorted(dir(module)):
32
+            if child.startswith('_'):
33
+                continue
34
+            child_mod = getattr(module, child)
35
+            if not isinstance(child_mod, type(module)):
36
+                continue
37
+            docline =  ((child_mod.__doc__ or '').strip() or '\n').splitlines()[0]
38
+            _print('* [%s](CURRENT?p=%s): %s' % (child, child_mod.__name__, docline))
39
+    else:
40
+        with open(module.__file__) as f:
41
+            tree = ast.parse(f.read())
42
+        _docs = {}
43
+        for ix, node in enumerate(tree.body[:-1]):
44
+            nextnode = tree.body[ix+1]
45
+            if (isinstance(node, ast.Assign)
46
+                    and ix < len(tree.body)-1
47
+                    and isinstance(nextnode, ast.Expr)
48
+                    and isinstance(nextnode.value, ast.Str)
49
+                    and len(node.targets) == 1
50
+                    and isinstance(node.targets[0], ast.Name)):
51
+                _docs[node.targets[0].id] = nextnode.value.s
52
+
53
+        s = '<a href="%s/%s.py" target="_blank">View Source</a>' % (source_view_url_root,
54
+                                                                    module.__name__.replace('.','/'))
55
+        if module.__doc__ is not None:
56
+            _print(module.__doc__)
57
+            _print()
58
+        _print(s)
59
+
60
+        _print('## Members')
61
+        for vname in sorted(dir(module)):
62
+            if vname.startswith('_') or vname in getattr(module, '_nodoc', set()):
63
+                continue
64
+
65
+            x = getattr(module, vname)
66
+            if type(x) == type(module):
67
+                # this is a module, skip
68
+                continue
69
+
70
+            doc = x.__doc__
71
+            if x.__doc__ == type(x).__doc__:
72
+                doc = None
73
+            if vname in _docs:
74
+                doc = _docs[vname]
75
+
76
+            try:
77
+                lines, start = inspect.getsourcelines(x)
78
+                l = ', <a href="%s/%s.py#L%s" target="_blank">lines %s-%s</a>' % (source_view_url_root,
79
+                                                                                  module.__name__.replace('.','/'),
80
+                                                                                  start, start, start+len(lines)-1)
81
+            except:
82
+                l = ''
83
+            _print('<a name="%s"></a>' % vname)
84
+            _print()
85
+            _print('* <font size="+2">**%s**</font> (`%s`%s)' % (module.__name__ + '.' + vname, type(x).__name__, l))
86
+
87
+            if doc is not None:
88
+                _print()
89
+                _print()
90
+                _print('\n'.join('    %s' % (i[4:] if i.startswith('    ') else i) for i in doc.strip().splitlines()))
91
+            _print('<p>&nbsp;</p>')
92
+            _print()
93
+
94
+cs_problem_spec = [csm_language._md_format_string(globals(), ''.join(cs_problem_spec), False)]

+ 4
- 0
website/docs/api/preload.py Переглянути файл

@@ -0,0 +1,4 @@
1
+cs_long_name = 'API'
2
+cs_title = cs_content_header = 'CAT-SOOP API'
3
+
4
+source_view_url_root = 'https://git.sr.ht/~adqm/catsoop/tree/master'

+ 5
- 0
website/docs/authoring/content.md Переглянути файл

@@ -0,0 +1,5 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+@{todo}

+ 3
- 0
website/docs/authoring/preload.py Переглянути файл

@@ -0,0 +1,3 @@
1
+cs_order=3
2
+cs_long_name="Running a Course With CAT-SOOP"
3
+cs_title = 'Running a Course | %s' % (cs_title, )

+ 37
- 0
website/docs/content.md Переглянути файл

@@ -0,0 +1,37 @@
1
+<python>
2
+cs_content_header = "CAT-SOOP v14.x Documentation"
3
+</python>
4
+
5
+<center>
6
+<pre style="border-color:transparent; font-weight:bold; background-color:transparent;font-size:110%; color:inherit; line-height:1.1;display:inline-block;text-align:left;">
7
+\
8
+/    /\__/\
9
+\__=(  o_O )=
10
+(__________)
11
+ |_ |_ |_ |_
12
+</pre>
13
+</center>
14
+
15
+
16
+@{warning("""These docs are extremely sparse right now, and unfortunately, I have
17
+trouble finding the time to sit down and write documentation.
18
+
19
+If you have questions about using the software that aren't answered here,
20
+please send an e-mail to `~adqm/catsoop@lists.sr.ht`; I'm happy to answer
21
+questions, and I'll also try to work the result into the docs.
22
+
23
+Better yet, if you have used CAT-SOOP and are interested in contributing
24
+documentation, please see <a href="CURRENT/contributing">the section on
25
+contributing documentation</a> for more information.
26
+
27
+-Adam""")}
28
+
29
+## Contents
30
+
31
+<python>
32
+for i in sorted(cs_children, key=lambda i: cs_children[i].get('cs_order', 1000)):
33
+    if i == 'api':
34
+        cs_print("* [API Documentation](CURRENT/api?p=catsoop)")
35
+    else:
36
+        cs_print("* [%s](CURRENT/%s)" % (cs_children[i].get('cs_long_name', i), i))
37
+</python>

+ 54
- 0
website/docs/contributing/content.md Переглянути файл

@@ -0,0 +1,54 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+The easiest and best way to contribute to CAT-SOOP is to use it, to report any
6
+issues you find, and to tell your colleagues if you like it!
7
+
8
+Please see below for some guidelines about contributing more directly to
9
+CAT-SOOP, and please don't hesitate to reach out if you have questions.
10
+
11
+### Do you have a question about using CAT-SOOP?
12
+
13
+We're happy to help!  There are a couple of options for asking questions:
14
+
15
+* send an e-mail to `~adqm/catsoop@lists.sr.ht`, or
16
+* drop by the IRC room (`#catsoop` on `irc.oftc.net`), or
17
+* open an issue on the [issue tracker](https://todo.sr.ht/~adqm/catsoop).
18
+
19
+### Did you find a bug?
20
+
21
+**If you have found a security vulnerability, please do not post publicly.** In
22
+that case, please instead send e-mail to `~adqm/catsoop-security@lists.sr.ht`,
23
+or send e-mail directly to Adam (`hz@mit.edu`), optionally encrypting your
24
+message with [his public key](https://hz.mit.edu/hz_pubkey.asc).
25
+
26
+For other issues, as a first step, please ensure that they were not already
27
+reported by looking through the [issue
28
+tracker](https://todo.sr.ht/~adqm/catsoop).  If you're unable to find an open
29
+issue addressing the problem, feel free to report your issue in any of the ways
30
+described above.
31
+
32
+Regardless of how you report the issue, please be as descriptive as you can,
33
+and please try to include an example that demonstrates the issue if possible.
34
+
35
+If you have questions about the bug reporting process, or if are unsure whether
36
+you've found a bug, please don't hesitate to reach out via e-mail, IRC, or the
37
+issue tracker.
38
+
39
+### Do you intend to add a new feature, change an existing behavior, or fix a bug?
40
+
41
+A good place to start is to suggest your change in the
42
+`~adqm/catsoop-dev@lists.sr.ht` mailing list or in the IRC room, and to read
43
+through the [hacker's guide](CURRENT/hacking) for information on the process
44
+for contributing code, as well as information about coding style, tests, etc.
45
+
46
+#### Do you want to contribute to the documentation?
47
+
48
+We really appreciate it!
49
+
50
+If you are comfortable doing so, the best way to submit documentation changes
51
+is by the same process described above, as described in the [hacker's
52
+guide](CURRENT/hacking).
53
+But we'll accept documentation changes in any format!  Feel free just to e-mail
54
+your changes/suggestions (in any format) to `~adqm/catsoop-dev@lists.sr.ht`.

BIN
website/docs/contributing/hacking/__STATIC__/knight-vs-catsoop.jpg Переглянути файл


+ 15
- 0
website/docs/contributing/hacking/content.md Переглянути файл

@@ -0,0 +1,15 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+<center>
6
+<img src="CURRENT/knight-vs-catsoop.jpg" width="500" style="max-width:100%"/>
7
+</center>
8
+
9
+<p>&nbsp;</p>
10
+
11
+Welcome to the CAT-SOOP hacker's guide!  This document is intended to give you
12
+a brief overview of the CAT-SOOP code base, as well as the process for setting
13
+up a local testing copy, and for contributing changes back to CAT-SOOP.
14
+
15
+Once I write it, it will be great.

+ 2
- 0
website/docs/contributing/hacking/preload.py Переглянути файл

@@ -0,0 +1,2 @@
1
+cs_long_name="CAT-SOOP Hacker's Guide"
2
+cs_title = 'Hacking | %s' % (cs_title, )

+ 3
- 0
website/docs/contributing/preload.py Переглянути файл

@@ -0,0 +1,3 @@
1
+cs_order = 5
2
+cs_long_name="Contributing to CAT-SOOP"
3
+cs_title = 'Contributing | %s' % (cs_title, )

+ 5
- 0
website/docs/extending/content.md Переглянути файл

@@ -0,0 +1,5 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+@{todo}

+ 3
- 0
website/docs/extending/preload.py Переглянути файл

@@ -0,0 +1,3 @@
1
+cs_order = 4
2
+cs_long_name="Customizing, Extending, and Modifying CAT-SOOP"
3
+cs_title = 'Customizing | %s' % (cs_title, )

+ 136
- 0
website/docs/installing/content.md Переглянути файл

@@ -0,0 +1,136 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+This page is designed to help you get an instance of CAT-SOOP up and running.
6
+If you are setting things up on a local copy, following the instructions on
7
+this page should be enough.  If you are setting up a public-facing instance on
8
+a server you control, you should follow these instructions, and then continue
9
+by following the link at the bottom of this page for more information about
10
+server configuration.
11
+
12
+As a general rule, I only test using Debian GNU/Linux, but others have tested
13
+these instructions on Mac OSX and on Windows (Cygwin or LSW).
14
+
15
+<tableofcontents/>
16
+
17
+<section>Install Necessary Software</section>
18
+
19
+CAT-SOOP depends on Python (version 3.5+, with pip).
20
+
21
+You will need Python version 3.5+ on your system to run CAT-SOOP.  Many
22
+distributions have Python 3.5+ in their package managers, though it may be
23
+necessary to download the source from [the official Python
24
+site](https://www.python.org/).
25
+
26
+On Debian Stretch, you will need the `python3` and `python3-pip` packages (or a
27
+version of Python 3.5+ installed in some other way).
28
+
29
+<subsection>(Cygwin Only) Patch _pyio</subsection>
30
+
31
+As of the time of this writing (December 2017), the Python version available
32
+through Cygwin ships with a broken version of `_pyio`, which `cheroot` uses.
33
+In order to run CAT-SOOP on a Cygwin host, edit the file
34
+`/usr/lib/python3.6/_pyio.py` so that the first conditional (about
35
+`sys.platform`) reads as follows:
36
+
37
+```py
38
+if sys.platform == 'win32':
39
+    from msvcrt import setmode as _setmode
40
+elif sys.platform == 'cygwin':
41
+    import ctypes
42
+    _cygwin1 = ctypes.PyDLL('cygwin1.dll')
43
+    def _setmode(fd, mode):
44
+        return _cygwin1._setmode(ctypes.c_int(fd), ctypes.c_int(mode))
45
+else:
46
+    _setmode = None
47
+```
48
+
49
+<section>Download CAT-SOOP</section>
50
+
51
+There are several ways you can install CAT-SOOP (as of version 14.0).
52
+
53
+<subsection>Installation via pip</subsection>
54
+
55
+The easiest is pip, with a command like the following:
56
+
57
+```
58
+$ sudo pip3 install catsoop
59
+```
60
+
61
+<subsection>Manual Installation</subsection>
62
+
63
+Alternatively, you can clone the Git repository containing the source code:
64
+
65
+```
66
+git clone https://git.sr.ht/~adqm/catsoop
67
+```
68
+
69
+and then run:
70
+
71
+```
72
+$ sudo python3 setup.py install
73
+```
74
+
75
+from the source directory.  You can also run the unit tests by running:
76
+
77
+```
78
+$ sudo python3 setup.py test
79
+```
80
+
81
+
82
+<section>Configure CAT-SOOP</section>
83
+
84
+To configure CAT-SOOP, run the following command:
85
+
86
+```
87
+catsoop configure
88
+```
89
+
90
+and answer the questions it poses.
91
+
92
+
93
+<div class="callout callout-danger">
94
+<h4>Note</h4>
95
+If you are running a public-facing CAT-SOOP instance, you are <b>strongly
96
+encouraged</b> to enable encryption if the directory in which you are storing
97
+the logs is not already encrypted in some way (e.g., via <code>luks</code> or
98
+<code>gocryptfs</code> or <code>cryfs</code>, etc).
99
+</div>
100
+
101
+<section>Add Courses</section>
102
+
103
+The default location for CAT-SOOP courses is in
104
+`~/.local/share/catsoop/courses/`.  You should move (or symlink) your courses
105
+to that location.
106
+
107
+<section>Start CAT-SOOP</section>
108
+
109
+To start the server, you should run:
110
+
111
+```
112
+$ catsoop runserver
113
+```
114
+
115
+This will start the server listening on port 6010.  You should then be able to
116
+directy your browser to `http://localhost:6010` to see the CAT-SOOP instance.
117
+
118
+
119
+<section>(Optional) Sign Up for Mailing List</section>
120
+
121
+`~adqm/catsoop@lists.sr.ht` is a place to ask questions about CAT-SOOP usage.
122
+You can view the archives or subscribe
123
+[here](https://lists.sr.ht/~adqm/catsoop).
124
+
125
+`~adqm/catsoop-announce@lists.sr.ht` is a low-volume list used to announce
126
+updates to CAT-SOOP.  You can view the archives or subscribe
127
+[here](https://lists.sr.ht/~adqm/catsoop-announce).
128
+
129
+`~adqm/catsoop-dev@lists.sr.ht` is the place to submit patches, and/or
130
+questions about CAT-SOOP development.  Your can view the archives or subscribe
131
+[here](https://lists.sr.ht/~adqm/catsoop-dev).
132
+
133
+<section>Additional Configuration for Public-Facing Servers</section>
134
+
135
+If you are setting up a public-facing CAT-SOOP instance, see also [this page
136
+about additional server configuration](CURRENT/server_configuration).

+ 3
- 0
website/docs/installing/preload.py Переглянути файл

@@ -0,0 +1,3 @@
1
+cs_order = 2
2
+cs_long_name = "Installation and Configuration Quick-Start"
3
+cs_title = 'Install | %s' % (cs_title, )

+ 468
- 0
website/docs/installing/server_configuration/content.md Переглянути файл

@@ -0,0 +1,468 @@
1
+<python>
2
+cs_content_header = cs_long_name
3
+</python>
4
+
5
+This page describes a fairly typical CAT-SOOP setup, and assumes that you have
6
+already installed and configured CAT-SOOP as described on [this
7
+page](CURRENT/..).
8
+
9
+<tableofcontents/>
10
+
11
+<section>Check Web Settings</section>
12
+
13
+To start, double-check the following values in `config.py`:
14
+
15
+* `cs_url_root`, which is the URL of the root of the CAT-SOOP installation.
16
+* `cs_checker_websocket`, which tells CAT-SOOP where clients can make websocket connections to the checker.
17
+
18
+For example:
19
+
20
+```
21
+cs_url_root = 'http://localhost:6010'
22
+cs_checker_websocket = 'ws://localhost:6011'
23
+```
24
+
25
+Typically, on a public-facing server, `cs_url_root` will start with `https`,
26
+and `cs_checker_websocket` will start with `wss`.
27
+
28
+<div class="callout callout-warning">
29
+<h4>Double Check</h4>
30
+<p>Make sure that the <code>cs_fs_root</code> directory can be read from and written to by
31
+the web server's user.</p>
32
+<p>Make sure that the <code>cs_data_root</code> directory is <b>not</b> web-accessible, and that
33
+the web server's user has read/write access.</p>
34
+</div>
35
+
36
+By default, running `catsoop runserver` will start several processes.  The most
37
+important are the UWSGI server (default port `6010`) and the websocket server
38
+(default port `6011`).  You can change these ports by setting additional
39
+variables `cs_wsgi_server_port` and `cs_checker_server_port`, respectively, in
40
+your `config.py`.
41
+
42
+<section>Configure nginx</section>
43
+
44
+Next, we will configure nginx to redirect relevant traffic to the web server
45
+and the websocket server.
46
+
47
+Start by creating a new file in `/etc/nginx/sites-available` with the following
48
+content, which will configure nginx to route certain requests to CAT-SOOP, and
49
+to redirect all traffic to HTTPS.
50
+
51
+You can, of course, customize the endpoints (`/cat-soop` and `/reporter` in the
52
+example below) to change the base URL for both the WSGI server and the
53
+websocket server.
54
+
55
+<div class="callout callout-info">
56
+<h4>Note</h4>
57
+If you do not already have one and you are planning to make a public-facing
58
+server, you should acquire an SSL certificate.  If your server is running at
59
+MIT, you can follow the instructions <a
60
+href="http://kb.mit.edu/confluence/display/istcontrib/Obtaining+an+SSL+certificate+for+a+web+server"
61
+target="_blank">on this page</a>.  Otherwise, SSL/TLS Certificates are
62
+available gratis from <a href="https://letsencrypt.org/" target="_blank">Let's
63
+Encrypt</a>.
64
+</div>
65
+
66
+
67
+```
68
+# redirect all HTTP traffic to HTTPS
69
+server {
70
+	listen 80;
71
+	listen [::]:80;
72
+	return 301 https://$host$request_uri;
73
+}
74
+
75
+server {
76
+    # listen on port 443 (standard port for HTTPS traffic) and enable SSL
77
+	listen 443 ssl;
78
+	listen [::]:443 ssl;
79
+
80
+    # the following should reference your SSL cert and key file
81
+	ssl_certificate	    /path/to/certificate-chain.crt;
82
+	ssl_certificate_key /path/to/keyfile.key;
83
+
84
+    # by default, serve files from /var/www/html
85
+	root /var/www/html;
86
+
87
+    # set the server's name (change this to reflect your server's FQDN)
88
+	server_name your.server.com;
89
+
90
+    # try adding trailing slashes before 404'ing
91
+	location / {
92
+		try_files $uri $uri/ =404;
93
+	}
94
+
95
+    # ignore .ht* files
96
+	location ~ /\.ht {
97
+		deny all;
98
+	}
99
+
100
+    # the following will route requests to https://your.server.com/cat-soop
101
+    # to the uWSGI server.  change "cat-soop" in the following lines if you
102
+    # want to use a different URL.
103
+    location /cat-soop {
104
+            rewrite /cat-soop/?(.*) /$1 break;
105
+            proxy_http_version 1.1;
106
+            proxy_set_header Upgrade $http_upgrade;
107
+            proxy_set_header Connection 'upgrade';
108
+            proxy_set_header Host $host;
109
+            proxy_set_header X-Real-IP $remote_addr;
110
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
111
+            proxy_cache_bypass $http_upgrade;
112
+            proxy_pass http://localhost:6010/;
113
+    }
114
+
115
+    # the following will route websocket requests to
116
+    # wss://your.server.com/reporter to CAT-SOOP's websocket server.
117
+    location /reporter {
118
+            proxy_http_version 1.1;
119
+            proxy_set_header Upgrade $http_upgrade;
120
+            proxy_set_header Connection 'upgrade';
121
+            proxy_set_header Host $host;
122
+            proxy_set_header X-Real-IP $remote_addr;
123
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
124
+            proxy_cache_bypass $http_upgrade;
125
+            proxy_pass http://localhost:6011/;
126
+    }
127
+}
128
+```
129
+
130
+<div class="callout callout-warning">
131
+<h4>Double Check</h4>
132
+<p>Note that your <code>cs_url_root</code> and <code>cs_checker_websocket</code> should match the nginx configuration.  In the example above, we should have <code>cs_url_root = 'https://your.server.com/cat-soop'</code> and <code>cs_checker_websocket = wss://your.server.com/reporter</code> in the <code>config.py</code> file.</p> <p>
133
+Also, make sure the ports (<code>6010</code> and <code>6011</code> in the example above) match the port numbers you set in <code>config.py</code>, if any.
134
+</p>
135
+</div>
136
+
137
+
138
+<div class="callout callout-info">
139
+<h4>Note</h4>
140
+If you want the root of the webserver to point to the CAT-SOOP instance, you
141
+can remove the block labeled <code>location /</code> from the example above,
142
+change <code>location /cat-soop</code> to be <code>location /</code>, and
143
+comment out the <code>rewrite</code> line within that block.
144
+</div>
145
+
146
+<subsection>(Optional) Client Certificate Authentication</subsection>
147
+
148
+If you would like to enable authentication based on client certificates (instead of username/password), add the following line beneath the other `ssl_` configuration variables in the NGINX configuration file:
149
+
150
+```
151
+	ssl_client_certificate /path/to/client_ca.pem;
152
+	ssl_verify_client on;
153
+```
154
+
155
+where `/path/to/client_ca.pem` is the location on fisk of the CA with which client certificates are signed.
156
+
157
+<section>(Optional) Configure Workers</section>
158
+
159
+<subsection>Web Server</subsection>
160
+
161
+By default, CAT-SOOP uses [cheroot](https://github.com/cherrypy/cheroot) as its
162
+WSGI server.  However, for public-facing instances, we recommend using [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) instead of cheroot.  To
163
+do so, set `cs_wsgi_server = 'uwsgi'` in your `config.py` file.  To make uWSGI
164
+spawn multiple worker processes, set the `cs_wsgi_server_min_processes` and
165
+`cs_wsgi_server_max_processes` variables.  When using uWSGI, you do not need to
166
+do any special NGINX configuration for load balancing.
167
+
168
+Alternatively, if you prefer to use `cheroot`, you can cause CAT-SOOP to launch
169
+more than one worker by setting `cs_wsgi_server_port` to a _list_ of integers
170
+instead of a single integer.  In this case, you will also likely want to
171
+configure NGINX to balance the load between the different processes by
172
+following the instructions [on this
173
+page](http://nginx.org/en/docs/http/load_balancing.html) (and, importantly,
174
+including the `ip_hash;` directive so users' sessions are not lost).
175
+
176
+<subsection>Checker</subsection>
177
+
178
+By default, CAT-SOOP's checker will run at most 1 check at a time.  If you have
179
+the resources available, you can configure the checker to run multiple checks
180
+in parallel by setting `cs_checker_parallel_checks` to a larger (integer)
181
+number in your `config.py`.
182
+
183
+
184
+<section>Start CAT-SOOP</section>
185
+
186
+From within the `scripts` directory of the CAT-SOOP source, run the following
187
+command to start CAT-SOOP:
188
+
189
+```
190
+$ catsoop runserver
191
+```
192
+
193
+On a typical webserver, it is a good idea to run the command in a screen so
194
+that the process does not die when you hang up.  Alternatively, you can use
195
+`nohup`.  For example,
196
+
197
+```
198
+$ nohup catsoop runserver > /dev/null &
199
+```
200
+
201
+<section>Test Configuration</section>
202
+
203
+Direct your web browser to your `cs_url_root` and you should now see the
204
+CAT-SOOP default page!
205
+
206
+<section>(Optional) Configure Backups</section>
207
+
208
+All of CAT-SOOP's data are stored in files on disk in a directory called
209
+`__LOGS__` in the `cs_data_root` location specified above (by default,
210
+`~/.local/share/cat-soop`).  CAT-SOOP itself will not back these files up, but
211
+there are many strategies for backups using common utilities.
212
+
213
+I have used many approaches in the past, but my usual approach involves setting
214
+the `__LOGS__` directory up as a Mercurial or Git repository, and then setting
215
+up a cron job to commit all files in that repository and push to several
216
+locations.  This approach has several advantages over simply using `rsync` or
217
+`scp` to copy the folder to a remote machine.  In particular, it allows you to
218
+roll back to any past backup while keeping size down by only storing diffs
219
+(instead of storing a complete copy of each file for each backup).
220
+
221
+Here, we'll set up a backup using Git (which tends to be more efficient for
222
+this purpose, both in time and in memory, than Mercurial).  To set this up,
223
+first move yourself to the `__LOGS__` directory and run `git init`, followed by
224
+`git add -A .` and `git gc --aggressive`.  This will set your `__LOGS__`
225
+directory up as a Git repository.  You can then set up a cron job to commit all
226
+changes and push these changes to an arbitrary number of backup locations
227
+(local or remote).
228
+
229
+The following example script (`/home/catsoop/do_backup.sh`) was used by several
230
+classes in fall 2018.  It commits local changes to a Git repository, and it
231
+then pushes those changes to one local location (on a separate disk) and to one
232
+remote location.
233
+
234
+```bash
235
+#!/bin/bash
236
+cd /home/catsoop/cat-soop-data/__LOGS__;
237
+git add -A;
238
+git commit -m "$(date +'%Y-%m-%d:%H:%M')";
239
+git push /storage2/backup master;
240
+git push catsoop@cat-soop.org:backups/py master;
241
+```
242
+
243
+It can then be configured to run, for example, every hour at xx:05 and xx:35
244
+with the following crontab entry:
245
+
246
+```nohighlight
247
+5,35 * * * * /usr/bin/flock -n /tmp/backup.lockfile /home/catsoop/do_backup.sh 2>&1 >/dev/null
248
+```
249
+
250
+<section>(Optional) Set Up Local Python Sandbox</section>
251
+
252
+By default, Python code that needs to be sandboxed (for example, student code
253
+from the `pythonic` or `pythoncode` question types) will be sent to
254
+`cat-soop.org` to be run.
255
+
256
+It is fine to leave things this way if you'd like.  I will keep that service up
257
+as long as is feasible, and the sandbox doesn't log anything about the code it
258
+runs.  That said, you may also wish to set things up so that the code runs on
259
+your machine.  The main benefit of this approach is that you don't have to rely
260
+on an external service (network issues or our server's downtime won't affect
261
+you, and you have a sandbox to yourself instead of having to share with
262
+others).
263
+
264
+Our recommended sandboxing approach involves creating a Python virtual
265
+environment to run student code, and limiting that interpreter's permissions
266
+using [AppArmor](http://wiki.apparmor.net/index.php/Main_Page) and
267
+[bubblewrap](https://github.com/projectatomic/bubblewrap).  This approach will
268
+largely isolate the student code from the system on which it is running, and it
269
+will also limit other resources (memory usage, etc).
270
+
271
+<subsection>Installing Necessary Software</subsection>
272
+
273
+In order to set things up, you'll need to install both `virtualenv` and
274
+`AppArmor`.  On Debian Stretch, this can be done with the following commands:
275
+
276
+```
277
+$ sudo pip3 install virtualenv
278
+$ sudo apt install apparmor apparmor-utils apparmor-profiles
279
+```
280
+
281
+You'll also need to install `bubblewrap`.  The version of `bubblewrap` that is
282
+available in the Debian Stretch repositories does not support some of the
283
+features we want to use, so you should compile from source.  You can do so with
284
+the following sequence of commands (on Debian Stretch):
285
+
286
+```
287
+$ sudo apt build-dep bubblewrap
288
+$ git clone https://github.com/projectatomic/bubblewrap
289
+$ cd bubblewrap
290
+$ ./autogen.sh
291
+$ make
292
+$ sudo make install
293
+```
294
+
295
+This will make an executable called `bwrap`, which our sandbox will use.
296
+
297
+On Debian, you will also need to set a kernel parameter to allow unprivileged
298
+users to create new user namespaces:
299
+
300
+```
301
+$ sudo sysctl kernel.unprivileged_userns_clone=1
302
+```
303
+
304
+You should also set this parameter in `/etc/sysctl.conf` so it persists across
305
+reboots.
306
+
307
+<subsection>Virtual Environment</subsection>
308
+
309
+Now that we have all of the necessary software, we'll set up a virtual
310
+environment.  The sandboxed code will be run in this environment.  Pick a
311
+location (one that is readable by the user running the web server) and create a
312
+new virtual environment there with the Python interpreter you want the checkers
313
+to use.  In example below, we'll use the `/usr/bin/python3` interpreter, and
314
+we'll set up the virtual environment in `/home/catsoop/python3_sandbox`.
315
+
316
+```
317
+$ virtualenv --always-copy -p /usr/bin/python3 /home/catsoop/python3_sandbox
318
+```
319
+
320
+If you want to use a different Python version as the basis for the virtual
321
+environment, you can change the `-p` option.
322
+
323
+<subsubsection>Installing Packages to the Sandbox</subsubsection>
324
+
325
+If you would like your checkers to be able to use any packages outside the
326
+standard library, you can install them in the virtual environment using the
327
+`pip` executable within the virtual environment.  For most packages, you can
328
+simply use the `pip` executable from this new virtual environment to install
329
+them.  For example, to make `pillow` available within the sandbox, we could
330
+use:
331
+
332
+```
333
+$ /home/catsoop/python3_sandbox/bin/pip install pillow
334
+```
335
+
336
+However, some packages require special care when installing.  For example,
337
+`numpy` normally uses multiple processes when computing its results.  However,
338
+a desirable feature of the sandbox is that it prevents student code from
339
+launching new processes of any kind.  To get around this, it is possible to
340
+compile `numpy` for the sandbox with all optimizations disabled, for example:
341
+
342
+```
343
+$ sudo apt build-dep python3-numpy
344
+$ wget https://files.pythonhosted.org/packages/94/b8/09db804ddf3bb7b50767544ec8e559695b152cedd64830040a0f31d6aeda/numpy-1.14.4.zip
345
+$ unzip numpy-1.14.4.zip
346
+$ cd numpy-1.14.4
347
+$ BLAS=None LAPACK=None ATLAS=None /home/catsoop/python3_sandbox/bin/python3 setup.py install
348
+```
349
+
350
+<subsection>AppArmor</subsection>
351
+
352
+We'll use AppArmor to place some limits on our sandboxed Python interpreter.
353
+Before we can do so, we'll have to configure the Linux kernel to use AppArmor
354
+for security.  You can do this my modifying `/etc/default/grub`.  Within that
355
+file, you'll need to modify a line starting with `GRUB_CMDLINE_LINUX_DEFAULT`
356
+by adding `apparmor=1 security=apparmor` to the end of the arguments in quotes.
357
+For example, after making this modification, this line appears on my machine
358
+as:
359
+
360
+```
361
+GRUB_CMDLINE_LINUX_DEFAULT="quiet apparmor=1 security=apparmor"
362
+```
363
+
364
+After making this modification, you'll need to update GRUB and reboot for the
365
+changes to take effect:
366
+
367
+```
368
+$ sudo update-grub
369
+$ sudo reboot
370
+```
371
+
372
+After the reboot, you'll need to set up an AppArmor profile to limit your
373
+virtual environment's Python interpreter.  Create a file
374
+`/etc/apparmor.d/py3sandbox` containing the following, but replacing
375
+`/home/catsoop/python3_sandbox` with your sandbox location (if it is
376
+different), and tuning some of the other parameters if necessary:
377
+
378
+```
379
+#include <tunables/global>
380
+
381
+/home/catsoop/python3_sandbox/bin/python3.6 {
382
+    /** wrix,
383
+
384
+    set rlimit nproc <= 0,
385
+    set rlimit fsize <= 1M,
386
+    set rlimit as <= 500M,
387
+}
388
+```
389
+
390
+This file does a couple of things:
391
+
392
+* It allows access to the entire filesystem.  This might seem dangerous, but we'll use `bwrap` to handle the filesystem sandboxing (though you can modify the entries above to further restrict things).
393
+* It also introduces two resource limits:
394
+    * student code will not be allowed to spawn any new processes
395
+    * student code cannot write more than 1MB of data to files
396
+    * student code will not be allowed to use more than 500MB of memory
397
+
398
+All of these parameters are tunable, and other resources can also be limited,
399
+as documented [here](https://linux.die.net/man/2/setrlimit).
400
+
401
+Finally, enable the profile with the following command:
402
+
403
+```
404
+$ sudo aa-enforce /etc/apparmor.d/py3sandbox
405
+```
406
+
407
+You can then test your setup by running the Python interpreter (in our example,
408
+`/home/catsoop/python3_sandbox/bin/python3`) and trying to write more than 1M
409
+of data to a file:
410
+
411
+```py
412
+with open('/tmp/test', 'w') as f:
413
+    f.write('a'*(1204**2+1))
414
+```
415
+
416
+This should produce an error, since this interpreter is not allowed to write
417
+that much data to disk.
418
+
419
+<div class="callout callout-info">
420
+<h4>Note</h4>
421
+If you did use AppArmor to place additional restrictions on filesystem access,
422
+and if you later wish to install other Python packages for the sandboxed
423
+interpreter, you will first need to disable the AppArmor protections by
424
+running:
425
+<pre>
426
+$ sudo aa-disable /etc/apparmor.d/py3sandbox
427
+</pre>
428
+Then you can install the packages using the `pip` executable within the virtual
429
+environment, and re-enable the AppArmor protections afterwards by running:
430
+<pre>
431
+$ sudo aa-enforce /etc/apparmor.d/py3sandbox
432
+</pre>
433
+</div>
434
+</abstractions></abstractions></tunables>
435
+
436
+<subsection>CAT-SOOP Configuration</subsection>
437
+
438
+Now that we have those pieces set up, we'll need to configure CAT-SOOP to use
439
+this new sandbox.
440
+
441
+Add the following to your `preload.py` (so that all pages in the course inherit
442
+it), substituting your own values where appropriate:
443
+
444
+```python
445
+csq_python_sandbox = 'bwrap'
446
+
447
+# the following should match the line in /etc/apparmor.d/py3sandbox exactly
448
+csq_python_interpreter = '/home/catsoop/python3_sandbox/bin/python3.6'
449
+
450
+csq_bwrap_extra_ro_binds = [('/home/catsoop/python3_sandbox', '/home/catsoop/python3_sandbox')]
451
+```
452
+
453
+The `csq_bwrap_extra_ro_binds` variable tells bubblewrap to mount certain
454
+directories from the base system on the virtual filesystem available to the
455
+student's code in rea-only mode.  In our case, it is necessary to include the
456
+directory from which our Python executable is available.
457
+
458
+And that's it!  It is worth runing a few tests after implementing this, to make
459
+sure things are working properly.  For example, I would usually try to:
460
+
461
+* call `os.fork()` and/or use the `subprocess` module to start a child process
462
+* write too much data to a file
463
+* list the files in a directory not included in the sandbox (e.g., someone's home directory)
464
+* use too much memory
465
+* cause an infinite loop
466
+
467
+If the system properly stops the code from running in all of the examples above
468
+but works for a correct solution, then you're probably in good shape!

+ 2
- 0
website/docs/installing/server_configuration/preload.py Переглянути файл

@@ -0,0 +1,2 @@
1
+cs_long_name = "Server Configuration"
2
+cs_title = 'Server Configuration | %s' % (cs_title, )

+ 55
- 0
website/docs/preload.py Переглянути файл

@@ -0,0 +1,55 @@
1
+import os
2
+import subprocess
3
+
4
+from datetime import datetime
5
+
6
+cs_long_name = 'Documentation'
7
+
8
+docs_loc = os.path.join(cs_data_root, 'courses', cs_course, 'docs')
9
+cs_title = 'Documentation | CAT-SOOP'
10
+
11
+cs_top_menu = [{'text': 'Navigation', 'link': [
12
+
13
+    {'link': "COURSE", 'text': 'CAT-SOOP Home'},
14
+    {'link': "COURSE/docs", 'text': 'Docs Home'},
15
+    {'link': "COURSE/docs/about", 'text': 'About'},
16
+    {'link': "COURSE/docs/installing", 'text': 'Installing'},
17
+    {'link': "COURSE/docs/authoring", 'text': 'Authoring'},
18
+    {'link': "COURSE/docs/extending", 'text': 'Extending'},
19
+    {'link': "COURSE/docs/contributing", 'text': 'Contributing'},
20
+    {'link': "COURSE/docs/api/catsoop", 'text': 'API'},
21
+
22
+]}]
23
+
24
+def callout(note, header, style):
25
+    return """<div class="callout callout-%s">
26
+<h4>%s</h4>
27
+%s
28
+</div>""" % (style, header, csm_language._md_format_string(globals(), note))
29
+
30
+def note(x):
31
+    cs_print(callout(x, "Note", "info"))
32
+    return ''
33
+
34
+def warning(x):
35
+    cs_print(callout(x, "Warning", "danger"))
36
+    return ''
37
+
38
+def doublecheck(x):
39
+    cs_print(callout(x, "Double Check", "warning"))
40
+    return ''
41
+
42
+def aside(x):
43
+    cs_print(callout(x, "Aside", "warning"))
44
+    return ''
45
+
46
+todo = '''<div class="callout callout-danger">
47
+<p>
48
+  <b>This Page Needs Attention</b>
49
+</p>
50
+<p>
51
+  Contributions to documentation are more than welcome!
52
+  You can e-mail contributions (or questions) to
53
+  <code>~adqm/catsoop-dev@lists.sr.ht</code>.
54
+</p>
55
+</div>'''

+ 6
- 0
website/preload.py Переглянути файл

@@ -0,0 +1,6 @@
1
+cs_auth_required = False
2
+
3
+cs_breadcrumbs_skip_paths = {'docs/api'}
4
+
5
+cs_footer = """<a href="http://creativecommons.org/licenses/by-sa/4.0/" rel="license"><img alt="Creative Commons License" src="COURSE/cc-by-sa.png" style="border-width:0"></a><br/>The contents of this page are Copyright &copy; 2016-2019 by the CAT-SOOP Developers.<br/>They are licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.<br/>The original form of this web site is source code in the CAT-SOOP specification
6
+format.<br/>The source code is available in the Git repository at  <a href="https://git.sr.ht/~adqm/catsoop">https://git.sr.ht/~adqm/catsoop</a>.<br/><hr width="300" style="background-color:#000000;border-color:#000000" />"""

Завантаження…
Відмінити
Зберегти