Initial upload, docker environment

This commit is contained in:
Felix Albrigtsen 2023-01-21 18:39:28 +01:00
commit c1b4875f4e
16 changed files with 2421 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/phpdocker/postgres-data

70
README.md Normal file
View File

@ -0,0 +1,70 @@
# PVVMDB
## A new attempt to keep records of PVV members
The projects should keep track of some basic member information:
- Usernames of all existing users
- Basic contact information
- Membership payments
- Disk Quota payments
This will help us keep track of:
- Active and inactive members (based on payment of the membership fee)
- Total disk quota
- Date of registration
This information gives us the ability to lock inactive user accounts, and keep statistics of our userbase.
Locking inactive accounts is useful for security reasons and to incentivize actually paying the fee.
## Requirements
There are two recommended ways of running the application:
### Docker-compose / dev
The development environment is available through docker, as described below.
This includes a database and all required runtimes.
Requires:
- Docker
- Docker-compose
## Production / native
As the application is a normal PHP application, you will need:
- PHP (Tested with 8.2)
- A web server (e.g. nginx)
- php-pgsql
- A PostgreSQL server
## Development
The project is written in basic PHP, without external frameworks.
The dev environment is built with docker-compose, and contains a PostgreSQL database, php-fpm and nginx.
Start it by running `docker-compose up -d`.
You can then view the page at [localhost:3010](http://localhost:3010).
The database can be administered with [adminer](http://localhost:3010/adminer-4.8.1.php).
Some docs should probably be written in /docs
Some tools should probably be made in /utils
## TODO:
- Start Web interface
- Input methods:
- [ ] Web form
- [ ] Import from bank statements (PDF/CSV)
- [ ] Import from GNUCash
- Make admin system
- Save list of admins or integrate with www.pvv.ntnu.no/admin/
- Auth / login, one of:
- SSO with idp.pvv.ntnu.no
- PAM / Unix auth
- Integrate with PVV "New user" scripts
- Allow normal users to update their own contact info?
- ...

5
dev.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
# test -e composer.phar || curl -O https://getcomposer.org/composer.phar
php -S ${DOCKER_HOST:-[::1]}:${DOCKER_PORT:-1080} -d error_reporting=E_ALL -d display_errors=1 -t src/

32
docker-compose.yml Normal file
View File

@ -0,0 +1,32 @@
###############################################################################
# Generated on phpdocker.io #
###############################################################################
version: '3.1'
services:
postgres:
image: 'postgres:11.1-alpine'
working_dir: /docker
volumes:
- ./phpdocker/postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=pvvmdb
- POSTGRES_PASSWORD=pvvmdb
- POSTGRES_DB=pvvmdb
ports:
- '3014:5432'
webserver:
image: 'nginx:alpine'
working_dir: /docker
volumes:
- ./src:/docker
- ./phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- '3010:80'
php-fpm:
build: phpdocker/php-fpm
working_dir: /docker
volumes:
- ./src:/docker
- ./phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/8.2/fpm/conf.d/99-overrides.ini

BIN
docs/database_model.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

50
docs/database_model.puml Normal file
View File

@ -0,0 +1,50 @@
@startuml
entity "User" as user {
id: int
--
* username: string
name: string
phone: string
external_email: string
first_created: date
locked: boolean
comment: string
}
entity "Purchase" as purchase {
id: int
--
* _user_id_: int
* amount_paid: number
* date: date
comment: string
}
entity "Disk Purchase" as disk_purchase {
--
* size_mb: int
}
entity "Membership Type" as membership_type {
id: int
--
* name: string
* price: number
comment: string
}
entity "Membership Purchase" as membership_purchase {
--
* _membership_type_id_: int
}
user "1..1" -- "0..*" purchase : makes
disk_purchase --|> purchase
membership_purchase --|> purchase
membership_type "1..1" -- "0..*" membership_purchase : is
@enduml

208
phpdocker/README.html Normal file
View File

@ -0,0 +1,208 @@
<html>
<head>
<title>PHPDocker.io Readme</title>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
<style>
code {
background-color : #ddd;
padding : 2px 5px;
font-family : monospace;
font-size : 16px;
}
</style>
</head>
<body>
<div class="pure-g">
<div class="pure-u-1-24"></div>
<div class="pure-u-22-24">
<h1>PHPDocker.io generated environment</h1>
<h1>Add to your project</h1>
<p>Simply, unzip the file into your project, this will create <code>docker-compose.yml</code> on the root of your project and a folder
named <code>phpdocker</code> containing nginx and php-fpm config for it.</p>
<p>Ensure the webserver config on <code>phpdocker/nginx/nginx.conf</code> is correct for your project. PHPDocker.io will have
customised this file according to the front controller location relative to the docker-compose file you chose on the
generator (by default <code>public/index.php</code>).</p>
<p>Note: you may place the files elsewhere in your project. Make sure you modify the locations for the php-fpm dockerfile,
the php.ini overrides and nginx config on <code>docker-compose.yml</code> if you do so.</p>
<h1>How to run</h1>
<p>Dependencies:</p>
<ul>
<li>docker. See <a href="https://docs.docker.com/engine/installation">https://docs.docker.com/engine/installation</a></li>
<li>docker-compose. See <a href="https://docs.docker.com/compose/install/">docs.docker.com/compose/install</a></li>
</ul>
<p>Once you're done, simply <code>cd</code> to your project and run <code>docker-compose up -d</code>. This will initialise and start all the
containers, then leave them running in the background.</p>
<h2>Services exposed outside your environment</h2>
<p>You can access your application via <strong><code>localhost</code></strong>. Mailhog and nginx both respond to any hostname, in case you want to
add your own hostname on your <code>/etc/hosts</code></p>
<table>
<thead>
<tr>
<th>Service</th>
<th>Address outside containers</th>
</tr>
</thead>
<tbody>
<tr>
<td>Webserver</td>
<td><a href="http://localhost:3010">localhost:3010</a></td>
</tr>
<tr>
<td>PostgreSQL</td>
<td><strong>host:</strong> <code>localhost</code>; <strong>port:</strong> <code>3014</code></td>
</tr>
</tbody>
</table>
<h2>Hosts within your environment</h2>
<p>You'll need to configure your application to use any services you enabled:</p>
<table>
<thead>
<tr>
<th>Service</th>
<th>Hostname</th>
<th>Port number</th>
</tr>
</thead>
<tbody>
<tr>
<td>php-fpm</td>
<td>php-fpm</td>
<td>9000</td>
</tr>
<tr>
<td>Postgres</td>
<td>postgres</td>
<td>5432 (default)</td>
</tr>
</tbody>
</table>
<h1>Docker compose cheatsheet</h1>
<p><strong>Note:</strong> you need to cd first to where your docker-compose.yml file lives.</p>
<ul>
<li>Start containers in the background: <code>docker-compose up -d</code></li>
<li>Start containers on the foreground: <code>docker-compose up</code>. You will see a stream of logs for every container running.
ctrl+c stops containers.</li>
<li>Stop containers: <code>docker-compose stop</code></li>
<li>Kill containers: <code>docker-compose kill</code></li>
<li>View container logs: <code>docker-compose logs</code> for all containers or <code>docker-compose logs SERVICE_NAME</code> for the logs of
all containers in <code>SERVICE_NAME</code>.</li>
<li>Execute command inside of container: <code>docker-compose exec SERVICE_NAME COMMAND</code> where <code>COMMAND</code> is whatever you want
to run. Examples:
<ul>
<li>Shell into the PHP container, <code>docker-compose exec php-fpm bash</code></li>
<li>Run symfony console, <code>docker-compose exec php-fpm bin/console</code></li>
<li>Open a mysql shell, <code>docker-compose exec mysql mysql -uroot -pCHOSEN_ROOT_PASSWORD</code></li>
</ul></li>
</ul>
<h1>Application file permissions</h1>
<p>As in all server environments, your application needs the correct file permissions to work properly. You can change the
files throughout the container, so you won't care if the user exists or has the same ID on your host.</p>
<p><code>docker-compose exec php-fpm chown -R www-data:www-data /docker/public</code></p>
<h1>Recommendations</h1>
<p>It's hard to avoid file permission issues when fiddling about with containers due to the fact that, from your OS point
of view, any files created within the container are owned by the process that runs the docker engine (this is usually
root). Different OS will also have different problems, for instance you can run stuff in containers
using <code>docker exec -it -u $(id -u):$(id -g) CONTAINER_NAME COMMAND</code> to force your current user ID into the process, but
this will only work if your host OS is Linux, not mac. Follow a couple of simple rules and save yourself a world of
hurt.</p>
<ul>
<li>Run composer outside of the php container, as doing so would install all your dependencies owned by <code>root</code> within your
vendor folder.</li>
<li>Run commands (ie Symfony's console, or Laravel's artisan) straight inside of your container. You can easily open a
shell as described above and do your thing from there.</li>
</ul>
<h1>Simple basic Xdebug configuration with integration to PHPStorm</h1>
<h2>Xdebug 2</h2>
<p>To configure <strong>Xdebug 2</strong> you need add these lines in php-fpm/php-ini-overrides.ini:</p>
<h3>For linux:</h3>
<pre><code>xdebug.remote_enable = 1
xdebug.remote_connect_back = 1
xdebug.remote_autostart = 1
</code></pre>
<h3>For macOS and Windows:</h3>
<pre><code>xdebug.remote_enable = 1
xdebug.remote_host = host.docker.internal
xdebug.remote_autostart = 1
</code></pre>
<h2>Xdebug 3</h2>
<p>To configure <strong>Xdebug 3</strong> you need add these lines in php-fpm/php-ini-overrides.ini:</p>
<h3>For linux:</h3>
<pre><code>xdebug.mode = debug
xdebug.remote_connect_back = true
xdebug.start_with_request = yes
</code></pre>
<h3>For macOS and Windows:</h3>
<pre><code>xdebug.mode = debug
xdebug.remote_host = host.docker.internal
xdebug.start_with_request = yes
</code></pre>
<h2>Add the section “environment” to the php-fpm service in docker-compose.yml:</h2>
<pre><code>environment:
PHP_IDE_CONFIG: "serverName=Docker"
</code></pre>
<h3>Create a server configuration in PHPStorm:</h3>
<ul>
<li>In PHPStorm open Preferences | Languages &amp; Frameworks | PHP | Servers</li>
<li>Add new server</li>
<li>The “Name” field should be the same as the parameter “serverName” value in “environment” in docker-compose.yml (i.e. *
Docker* in the example above)</li>
<li>A value of the "port" field should be the same as first port(before a colon) in "webserver" service in
docker-compose.yml</li>
<li>Select "Use path mappings" and set mappings between a path to your project on a host system and the Docker container.</li>
<li>Finally, add “Xdebug helper” extension in your browser, set breakpoints and start debugging</li>
</ul>
</div>
<div class="pure-u-1-24"></div>
</div>
<script>
var tables = document.getElementsByTagName('table')
for (var i = 0; i < tables.length; i++) {
tables[i].className = 'pure-table'
}
</script>
</body>
</html>

144
phpdocker/README.md Normal file
View File

@ -0,0 +1,144 @@
PHPDocker.io generated environment
==================================
# Add to your project #
Simply, unzip the file into your project, this will create `docker-compose.yml` on the root of your project and a folder
named `phpdocker` containing nginx and php-fpm config for it.
Ensure the webserver config on `phpdocker/nginx/nginx.conf` is correct for your project. PHPDocker.io will have
customised this file according to the front controller location relative to the docker-compose file you chose on the
generator (by default `public/index.php`).
Note: you may place the files elsewhere in your project. Make sure you modify the locations for the php-fpm dockerfile,
the php.ini overrides and nginx config on `docker-compose.yml` if you do so.
# How to run #
Dependencies:
* docker. See [https://docs.docker.com/engine/installation](https://docs.docker.com/engine/installation)
* docker-compose. See [docs.docker.com/compose/install](https://docs.docker.com/compose/install/)
Once you're done, simply `cd` to your project and run `docker-compose up -d`. This will initialise and start all the
containers, then leave them running in the background.
## Services exposed outside your environment ##
You can access your application via **`localhost`**. Mailhog and nginx both respond to any hostname, in case you want to
add your own hostname on your `/etc/hosts`
Service|Address outside containers
-------|--------------------------
Webserver|[localhost:3010](http://localhost:3010)
PostgreSQL|**host:** `localhost`; **port:** `3014`
## Hosts within your environment ##
You'll need to configure your application to use any services you enabled:
Service|Hostname|Port number
------|---------|-----------
php-fpm|php-fpm|9000
Postgres|postgres|5432 (default)
# Docker compose cheatsheet #
**Note:** you need to cd first to where your docker-compose.yml file lives.
* Start containers in the background: `docker-compose up -d`
* Start containers on the foreground: `docker-compose up`. You will see a stream of logs for every container running.
ctrl+c stops containers.
* Stop containers: `docker-compose stop`
* Kill containers: `docker-compose kill`
* View container logs: `docker-compose logs` for all containers or `docker-compose logs SERVICE_NAME` for the logs of
all containers in `SERVICE_NAME`.
* Execute command inside of container: `docker-compose exec SERVICE_NAME COMMAND` where `COMMAND` is whatever you want
to run. Examples:
* Shell into the PHP container, `docker-compose exec php-fpm bash`
* Run symfony console, `docker-compose exec php-fpm bin/console`
* Open a mysql shell, `docker-compose exec mysql mysql -uroot -pCHOSEN_ROOT_PASSWORD`
# Application file permissions #
As in all server environments, your application needs the correct file permissions to work properly. You can change the
files throughout the container, so you won't care if the user exists or has the same ID on your host.
`docker-compose exec php-fpm chown -R www-data:www-data /docker/public`
# Recommendations #
It's hard to avoid file permission issues when fiddling about with containers due to the fact that, from your OS point
of view, any files created within the container are owned by the process that runs the docker engine (this is usually
root). Different OS will also have different problems, for instance you can run stuff in containers
using `docker exec -it -u $(id -u):$(id -g) CONTAINER_NAME COMMAND` to force your current user ID into the process, but
this will only work if your host OS is Linux, not mac. Follow a couple of simple rules and save yourself a world of
hurt.
* Run composer outside of the php container, as doing so would install all your dependencies owned by `root` within your
vendor folder.
* Run commands (ie Symfony's console, or Laravel's artisan) straight inside of your container. You can easily open a
shell as described above and do your thing from there.
# Simple basic Xdebug configuration with integration to PHPStorm
## Xdebug 2
To configure **Xdebug 2** you need add these lines in php-fpm/php-ini-overrides.ini:
### For linux:
```
xdebug.remote_enable = 1
xdebug.remote_connect_back = 1
xdebug.remote_autostart = 1
```
### For macOS and Windows:
```
xdebug.remote_enable = 1
xdebug.remote_host = host.docker.internal
xdebug.remote_autostart = 1
```
## Xdebug 3
To configure **Xdebug 3** you need add these lines in php-fpm/php-ini-overrides.ini:
### For linux:
```
xdebug.mode = debug
xdebug.remote_connect_back = true
xdebug.start_with_request = yes
```
### For macOS and Windows:
```
xdebug.mode = debug
xdebug.remote_host = host.docker.internal
xdebug.start_with_request = yes
```
## Add the section “environment” to the php-fpm service in docker-compose.yml:
```
environment:
PHP_IDE_CONFIG: "serverName=Docker"
```
### Create a server configuration in PHPStorm:
* In PHPStorm open Preferences | Languages & Frameworks | PHP | Servers
* Add new server
* The “Name” field should be the same as the parameter “serverName” value in “environment” in docker-compose.yml (i.e. *
Docker* in the example above)
* A value of the "port" field should be the same as first port(before a colon) in "webserver" service in
docker-compose.yml
* Select "Use path mappings" and set mappings between a path to your project on a host system and the Docker container.
* Finally, add “Xdebug helper” extension in your browser, set breakpoints and start debugging

View File

@ -0,0 +1,29 @@
server {
listen 80 default;
client_max_body_size 108M;
access_log /var/log/nginx/application.access.log;
root /docker/.;
index index.php;
# try to serve file directly, fallback to index.php
location / {
try_files $uri /index.php$is_args$args;
}
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}

View File

@ -0,0 +1,8 @@
FROM phpdockerio/php:8.2-fpm
WORKDIR "/docker"
RUN apt-get update; \
apt-get -y --no-install-recommends install \
php8.2-pgsql; \
apt-get clean; \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*

View File

@ -0,0 +1,2 @@
upload_max_filesize = 100M
post_max_size = 108M

1795
src/adminer-4.8.1.php Normal file

File diff suppressed because one or more lines are too long

8
src/db_config.php Normal file
View File

@ -0,0 +1,8 @@
<?php
$db_host = "postgres";
$db_name = "pvvmdb";
$db_user = "pvvmdb";
$db_pass= "pvvmdb";
?>

7
src/db_connect.php Normal file
View File

@ -0,0 +1,7 @@
<?php
include_once 'db_config.php';
$dbconn = pg_connect("host=$db_host dbname=$db_name user=$db_user password=$db_pass")
or die('Could not connect: ' . pg_last_error());
?>

16
src/index.php Normal file
View File

@ -0,0 +1,16 @@
<?php
include('./db_connect.php');
$res = pg_query($dbconn, "SELECT * FROM users");
if (!$res) {
echo "An error occurred.\n";
exit;
}
while ($row = pg_fetch_row($res)) {
echo "id: $row[0] username: $row[1]";
}
?>

45
utils/initdb.sql Normal file
View File

@ -0,0 +1,45 @@
CREATE TABLE IF NOT EXISTS "users" (
"id" serial PRIMARY KEY,
"name" varchar(255) NOT NULL,
"username" varchar(32) UNIQUE NOT NULL,
"phone" varchar(32),
"external_email" varchar(320),
"locked" boolean NOT NULL DEFAULT false,
"created_at" date NOT NULL DEFAULT CURRENT_DATE,
"comment" varchar(255)
);
CREATE TABLE IF NOT EXISTS "membership_types" (
"id" serial PRIMARY KEY,
"name" varchar(32) UNIQUE NOT NULL,
"description" varchar(400) NOT NULL,
"price" integer NOT NULL
);
CREATE TABLE IF NOT EXISTS "purchases" (
"id" serial PRIMARY KEY,
"user_id" integer NOT NULL,
"created_at" date NOT NULL DEFAULT CURRENT_DATE,
"amount_paid" integer NOT NULL,
"comment" varchar(400),
CONSTRAINT "purchases_user_id_fkey" FOREIGN KEY ("user_id")
REFERENCES "users" ("id") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE TABLE IF NOT EXISTS "disk_purchases" (
"size_mb" integer NOT NULL
) INHERITS ("purchases");
CREATE TABLE IF NOT EXISTS "membership_purchases" (
"membership_type" integer NOT NULL,
CONSTRAINT "membership_purchases_membership_type_fkey" FOREIGN KEY ("membership_type")
REFERENCES "membership_types" ("id") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
) INHERITS ("purchases");
INSERT INTO membership_types (name, description, price) VALUES
('Livstid', 'Livstidsmedlemskap, betales én gang, varer livet ut.', 1024),
('Årlig Kontingent', 'Årlig medlemskap, en fast sum betales hvert år.', 50);