Compare commits
14 Commits
587b321205
...
comments
| Author | SHA1 | Date | |
|---|---|---|---|
| 50bf391450 | |||
| 8ad638f496 | |||
| 6838f603a1 | |||
| 32b1c4a3b4 | |||
| dff93fb807 | |||
| a5a3da62eb | |||
| 60c4e01778 | |||
| d64e7f4fa5 | |||
| bd735cb1e5 | |||
| 5a09d74670 | |||
| c9927f8301 | |||
| 7286199411 | |||
| c35e2b3ef0 | |||
| 6b338ce9ff |
@@ -1,4 +1,4 @@
|
|||||||
FROM python:3.13-bookworm
|
FROM python:3.14-bookworm
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y install apache2 apache2-dev
|
RUN apt-get -y install apache2 apache2-dev
|
||||||
COPY src/requirements.txt /var/www/jc/requirements.txt
|
COPY src/requirements.txt /var/www/jc/requirements.txt
|
||||||
|
|||||||
18
Jenkinsfile
vendored
18
Jenkinsfile
vendored
@@ -41,17 +41,19 @@ pipeline {
|
|||||||
stage('Security scan') {
|
stage('Security scan') {
|
||||||
when {
|
when {
|
||||||
expression {
|
expression {
|
||||||
return params.Build == true
|
return params.Build == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
sh "docker kill sectest || true"
|
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||||
sh "docker rm sectest || true"
|
sh "docker kill sectest || true"
|
||||||
sh "docker run -d --name sectest git.jakecharman.co.uk/jake/jakecharman.co.uk:$BUILD_NUMBER"
|
sh "docker rm sectest || true"
|
||||||
sh "docker exec sectest pip3 install pip-audit --break-system-packages"
|
sh "docker run -d --name sectest git.jakecharman.co.uk/jake/jakecharman.co.uk:$BUILD_NUMBER"
|
||||||
sh "docker exec sectest pip-audit"
|
sh "docker exec sectest pip3 install pip-audit --break-system-packages"
|
||||||
sh "docker stop sectest"
|
sh "docker exec sectest pip-audit"
|
||||||
sh "docker rm sectest"
|
sh "docker stop sectest"
|
||||||
|
sh "docker rm sectest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ LoadModule dir_module modules/mod_dir.so
|
|||||||
LoadModule alias_module modules/mod_alias.so
|
LoadModule alias_module modules/mod_alias.so
|
||||||
#LoadModule rewrite_module modules/mod_rewrite.somod_wsgi-express start-server
|
#LoadModule rewrite_module modules/mod_rewrite.somod_wsgi-express start-server
|
||||||
|
|
||||||
LoadModule wsgi_module /usr/local/lib/python3.13/site-packages/mod_wsgi/server/mod_wsgi-py313.cpython-313-x86_64-linux-gnu.so
|
LoadModule wsgi_module /usr/local/lib/python3.14/site-packages/mod_wsgi/server/mod_wsgi-py314.cpython-314-x86_64-linux-gnu.so
|
||||||
|
|
||||||
<IfModule unixd_module>
|
<IfModule unixd_module>
|
||||||
#
|
#
|
||||||
|
|||||||
6
src/.buildinfo.json
Normal file
6
src/.buildinfo.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"tag": "jc-ng-localtest:",
|
||||||
|
"date": "2025-11-02",
|
||||||
|
"host": "jake-e580",
|
||||||
|
"user": "jake"
|
||||||
|
}
|
||||||
30
src/comments.py
Normal file
30
src/comments.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
from os import path
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
from flask import request, Response, redirect
|
||||||
|
from index import app
|
||||||
|
from projects import md_directory, get_by_meta_key
|
||||||
|
|
||||||
|
database = '/tmp/db' #path.join(md_directory, 'comments.db')
|
||||||
|
with sqlite3.Connection(database) as db:
|
||||||
|
db.execute('CREATE TABLE IF NOT EXISTS comments (date INTEGER, article TEXT, name TEXT, comment TEXT)')
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
@app.route('/comments/<article>', methods=['GET', 'POST'])
|
||||||
|
def post_comments(article: str):
|
||||||
|
match request.method:
|
||||||
|
case 'POST':
|
||||||
|
if len(get_by_meta_key(md_directory, 'id', article)) == 0:
|
||||||
|
return Response(status=404)
|
||||||
|
with sqlite3.Connection(database) as db:
|
||||||
|
db.execute('INSERT INTO comments (date, article, name, comment) VALUES (?, ?, ?, ?)', (datetime.now(), article, request.form.get('name'), request.form.get('comment')))
|
||||||
|
db.commit()
|
||||||
|
return redirect(f'/projects/{article}')
|
||||||
|
case 'GET':
|
||||||
|
if len(get_by_meta_key(md_directory, 'id', article)) == 1:
|
||||||
|
with sqlite3.Connection(database) as db:
|
||||||
|
res = db.execute('SELECT * FROM comments WHERE `article` = ?', (article,))
|
||||||
|
return json.dumps([{'author': x[2], 'date': x[0], 'comment': x[3]} for x in res.fetchall()])
|
||||||
@@ -10,9 +10,10 @@ from flask import Flask, render_template, Response
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# These imports need to come after our app is defined as they add routes to it.
|
# These imports need to come after our app is defined as they add routes to it.
|
||||||
|
import sitemap # pylint: disable=wrong-import-position,unused-import
|
||||||
import projects # pylint: disable=wrong-import-position,unused-import
|
import projects # pylint: disable=wrong-import-position,unused-import
|
||||||
import contact # pylint: disable=wrong-import-position,unused-import
|
import contact # pylint: disable=wrong-import-position,unused-import
|
||||||
import sitemap # pylint: disable=wrong-import-position,unused-import
|
import comments # pylint: disable=wrong-import-position,unused-import
|
||||||
|
|
||||||
class DiscordLogger(logging.Handler):
|
class DiscordLogger(logging.Handler):
|
||||||
''' Simple logging handler to send a message to Discord '''
|
''' Simple logging handler to send a message to Discord '''
|
||||||
@@ -82,3 +83,6 @@ def error(code) -> str:
|
|||||||
return render_template('error.html',
|
return render_template('error.html',
|
||||||
error=f'{code}: {error_definitions.get(int(code))}',
|
error=f'{code}: {error_definitions.get(int(code))}',
|
||||||
description=error_desc.get(int(code)))
|
description=error_desc.get(int(code)))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run()
|
||||||
0
src/static/js/get_comments.js
Normal file
0
src/static/js/get_comments.js
Normal file
@@ -48,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#projects{
|
#projects{
|
||||||
align-items: center;
|
align-items: stretch;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -58,7 +58,6 @@
|
|||||||
|
|
||||||
.project{
|
.project{
|
||||||
width: 20vw;
|
width: 20vw;
|
||||||
height: 25vw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#top-nav{
|
#top-nav{
|
||||||
@@ -77,6 +76,9 @@
|
|||||||
#article>p>img{
|
#article>p>img{
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
#article>video{
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
#certs>a {
|
#certs>a {
|
||||||
max-width: 15%;
|
max-width: 15%;
|
||||||
@@ -95,18 +97,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.yt {
|
.yt {
|
||||||
width: 74%;
|
width: calc(66% - 40px);
|
||||||
height: 40vh;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery {
|
.gallery {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 35vh;
|
height: fit-content;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery * {
|
.gallery * {
|
||||||
height: inherit !important;
|
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gallery>img {
|
||||||
|
width: calc(33% - 40px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,12 +212,21 @@ label{
|
|||||||
|
|
||||||
#article{
|
#article{
|
||||||
padding: 0 10px 0 10px;
|
padding: 0 10px 0 10px;
|
||||||
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#article>p>img{
|
#article>p>img{
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto 0 auto;
|
margin: 0 auto 0 auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
max-height: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#article>video{
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto 0 auto;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 50vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre{
|
pre{
|
||||||
|
|||||||
@@ -6,5 +6,21 @@
|
|||||||
<hr />
|
<hr />
|
||||||
{{post|safe}}
|
{{post|safe}}
|
||||||
</section>
|
</section>
|
||||||
|
<section id="comments">
|
||||||
|
<h2>{{ comments | length }} comments</h2>
|
||||||
|
{% for comment in comments %}
|
||||||
|
<div class="comment">
|
||||||
|
<strong>{{ comment[2] }}</strong>
|
||||||
|
<p>{{ comment[3] }}</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<form action="/comments/{{ metadata.id }}" method="post">
|
||||||
|
<label for="name">Name:</label>
|
||||||
|
<input type="text" name="name" />
|
||||||
|
<label for="comment">Comment:</label>
|
||||||
|
<textarea name="comment"></textarea>
|
||||||
|
<input type="submit" name="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
Reference in New Issue
Block a user