Source code for the new video and image gallery site of my little one.
The Web site is intended to run on a RaspberryPi and due to its hardware limitations it is critically important to pick solutions that are not too resource-hungry. For this reason we have opted for nginx.
File: /etc/nginx/sites-available/tunia.duckdns.org
server {
listen 80; ## listen for ipv4; this line is default and implied
root /srv/WebRoot/tunia.duckdns.org/html;
index index.html;
server_name tunia.duckdns.org;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html;
}
location /photo/ {
alias /srv/Shared/Media/Pictures/Natalia/;
}
location /thumbnail/ {
alias "/srv/Shared/Media/Pictures/Natalia - low res/";
}
location /video/ {
alias /srv/Shared/Media/Video/Natalia/;
}
rewrite ^/videos/?$ /videos.html break;
}
We are going to use CouchDB and synchronise and persist data from it within the browser using a JavaScript library called PouchDB. The goal is to achieve a native app-like experience, without all the syncing headaches by delegating the hard work to PouchDB.
- Apache CouchDB
- Either the
add-cors-to-couchdb
Node.js module or manually adding CORS-related entries to the CouchDB's config file calledlocal.ini
Most of the below configuration changes can be done either via the Fauxton Web interface or directly in the CouchDB configuration file: /usr/local/etc/couchdb/local.ini
- Adding server admin user to disable public access to the database which is the default setting.
- Adding a database user (after adding the user you should see a corresponding document in the system _users database). Like all other operations in CouchDB, this can be done through their API:
curl -X PUT http://127.0.0.1:5984/_users/org.couchdb.user:natalie_www \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name": "natalie_www", "password": "topSecret", "roles": [], "type": "user"}'
// To verify:
curl -X POST http://127.0.0.1:5984/_session -d 'name=natalie_www&password=topSecret'
- Leave
WWW-Authenticate
commented out - Preventing non-authenticated users from creating database users (for some reason, this is a default behaviour in CouchDB). Consider adding the following
throw
directive right at the beginning of the!is_server_or_database_admin
check in the default_auth
design document:
throw({forbidden : 'Users can only be created by server or DB admins in this specific CouchDB installation'})
Credit: https://serverfault.com/a/742854/142176
- Enabling CORS to make it possible for PouchDB to talk to the CouchDB database server:
enable_cors = true
require_valid_user = true
[cors]
headers = accept, authorization, content-type, origin, referer
methods = GET, PUT, POST, HEAD, DELETE
credentials = true
origins = [* for all hosts or a particular URL]
- Create a database called natalie_gallery
Create the following document (it will be shown under design docs
in Fauxton)
{
"_id": "_design/natalie_gallery",
"language": "javascript",
"validate_doc_update": "
// The code below needs to be written in one line!
function(newDoc, oldDoc, userCtx, secObj) {
var ddoc = this;
secObj.admins = secObj.admins || {};
secObj.admins.names = secObj.admins.names || [];
secObj.admins.roles = secObj.admins.roles || [];
var isDbAdmin = false;
if(~ userCtx.roles.indexOf(\"_admin\"))
isDbAdmin = true;
if(~ secObj.admins.names.indexOf(userCtx.name))
isDbAdmin = true;
for(var i = 0; i < userCtx.roles; i++)
if(~ secObj.admins.roles.indexOf(userCtx.roles[i]))
isDbAdmin = true;
if(isDbAdmin)
log(\"Admin change on read-only db: \" + newDoc._id);
else
throw({forbidden: \"This database is read-only\"});
}"
}
Please note, you might need to write the body of the JavaScript function above in one line, otherwise Fauxton might complain.
A sample entry in the natalie_gallery database:
{
"_id": "20130101232300", // yyyymmddhhmmss
"title_pl": "Image title in Polish",
"title_en": "Image title in English",
"file_name": "File-name.jpg",
"gallery": "2013-01" // yyyy-mm
}
$ curl -d @<JSON file path> \
-X POST \
-H "Content-Type: application/json" \
http://<CouchDB host name>:5984/natalie_gallery/_bulk_docs
The format of the JSON file being imported is an object containing the docs
key which holds an array of JSON documents.
I am intending to use the following technologies:
- Yeoman with webapp generator,
- Grunt,
- Bower,
- PouchDB,
- jQuery Template,
- jQuery Swipebox,
- Girder or Gridism (the latter is less Sass-friendly though),
- Vanilla JavaScript.
$ yo webapp // with Sass ticked
$ npm install
$ bower install
$ grunt build
$ grunt serve // for development purposes
You can build the Web server and CouchDB Docker containers with Docker Compose. Please note, the current Nginx configuration file doesn't have a concept of image file storage - it merely proxies image and video file requests to the production URLs.
cd <application root directory>
docker-compose up -d
docker ps # Note down CouchDB Docker contained ID
docker exec <CouchDB container Docker ID> replicate_couchdb
docker exec <CouchDB container Docker ID> create_couchdb_reader