Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • adaures/castopod
  • mkljczk/castopod-host
  • spaetz/castopod-host
  • PatrykMis/castopod
  • jonas/castopod
  • ajeremias/castopod
  • misuzu/castopod
  • KrzysztofDomanczyk/castopod
  • Behel/castopod
  • nebulon/castopod
  • ewen/castopod
  • NeoluxConsulting/castopod
  • nateritter/castopod-og
  • prcutler/castopod
14 results
Show changes
Showing with 4186 additions and 907 deletions
File moved
File moved
# Authors
- [Benjamin Bellamy](https://code.podlibre.org/benjamin) <ben@podlibre.org>
- [Yassine Doghri](https://code.podlibre.org/yassine) <yassine@podlibre.org>
- [Benjamin Bellamy](https://code.castopod.org/benjamin) <ben@castopod.org>
- [Yassine Doghri](https://code.castopod.org/yassine) <yassine@castopod.org>
This diff is collapsed.
......@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[abuse@podlibre.org](mailto:abuse@podlibre.org). All complaints will be reviewed
[abuse@castopod.org](mailto:abuse@castopod.org). All complaints will be reviewed
and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
......
# Setup your development environment
## Introduction
Castopod is a web app based on the `php` framework
[CodeIgniter 4](https://codeigniter.com).
We use [Docker](https://www.docker.com/) to quickly setup a dev environment. A
`docker-compose.yml` and `Dockerfile` are included in the project's root folder
to help you kickstart your contribution.
> You don't need any prior knowledge of Docker to follow the next steps.
> However, if you wish to use your own environment, feel free to do so!
## Setup instructions
### 1. Pre-requisites
0. Install [Docker](https://docs.docker.com/get-docker).
1. Clone the Castopod repository by running:
```bash
git clone https://code.castopod.org/adaures/castopod.git
```
2. Create a `.env` file with the minimum required config to connect the app to
the database and use redis as a cache handler:
```ini
CI_ENVIRONMENT="development"
# If set to development, you must run `pnpm run dev` to start the static assets server
vite.environment="development"
# By default, this is set to true in the app config.
# For development, this must be set to false as it is
# on a local environment
app.forceGlobalSecureRequests=false
app.baseURL="http://localhost:8080/"
admin.gateway="cp-admin"
auth.gateway="cp-auth"
database.default.hostname="mariadb"
database.default.database="castopod"
database.default.username="castopod"
database.default.password="castopod"
database.default.DBPrefix="dev_"
analytics.salt="DEV_ANALYTICS_SALT"
cache.handler="redis"
cache.redis.host="redis"
# You may not want to use redis as your cache handler
# Comment/remove the two lines above and uncomment
# the next line for file caching.
# -----------------------
#cache.handler="file"
######################################
# Media config
######################################
media.baseURL="http://localhost:8080/"
# S3
# Uncomment to store s3 objects using adobe/s3mock service
# -----------------------
#media.fileManager="s3"
#media.s3.bucket="castopod"
#media.s3.endpoint="http://172.31.0.6:9090/"
#media.s3.pathStyleEndpoint=true
```
> [!NOTE]
> You can tweak your environment by setting more environment variables in
> your custom `.env` file. See the `env` for examples or the
> [CodeIgniter4 User Guide](https://codeigniter.com/user_guide/index.html)
> for more info.
3. (for Docker desktop) Add the repository you've cloned to Docker desktop's
`Settings` > `Resources` > `File Sharing`
### 2. (recommended) Develop inside the app container with VSCode
If you're working in VSCode, you can take advantage of the `.devcontainer/`
folder. It defines a development environment (dev container) with preinstalled
requirements and VSCode extensions so you don't have to worry about them. All
required services will be loaded automagically! 🪄
1. Install the VSCode extension
[Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
2. `Ctrl/Cmd + Shift + P` > `Open in container`
> The VSCode window will reload inside the dev container. Expect several
> minutes during first load as it is building all necessary services.
**Note**: The dev container will start by running Castopod's PHP server.
During development, you will have to start [Vite](https://vitejs.dev)'s dev
server for compiling the typescript code and styles:
```bash
# run Vite dev server
pnpm run dev
```
If there is any issue with the PHP server not running, you can restart them
using the following commands:
```bash
# run Castopod server
php spark serve - 0.0.0.0
```
3. You're all set! 🎉
You're now **inside the dev container**, you may use the VSCode console
(`Terminal` > `New Terminal`) to run any command:
```bash
# PHP is installed
php -v
# Composer is installed
composer -V
# pnpm is installed
pnpm -v
# git is installed
git version
```
For more info, see
[Developing inside a Container](https://code.visualstudio.com/docs/devcontainers/containers)
### 3. Start hacking
You're all set! Start working your magic by updating the project's files! Help
yourself to the
[CodeIgniter4 User Guide](https://codeigniter.com/user_guide/index.html) for
more insights.
To see your changes, go to:
- `http://localhost:8080/` for the Castopod website
- `http://localhost:8080/cp-admin` for the Castopod admin:
- email: **admin@castopod.local**
- password: **castopod**
- `http://localhost:8888/` for the phpmyadmin interface:
- username: **castopod**
- password: **castopod**
### 2-alt. Develop outside the app container
You do not wish to use the VSCode devcontainer? No problem!
1. Start the Docker containers manually:
Go to the project's root folder and run:
```bash
# starts all services declared in docker-compose.yml file
# -d option starts the containers in the background
docker-compose up -d
# See all running processes (you should see 3 processes running)
docker-compose ps
# Alternatively, you can check all docker processes
docker ps -a
```
> The `docker-compose up -d` command will boot 5 containers in the
> background:
>
> - `castopod_app`: a php based container with Castopod requirements
> installed
> - `castopod_redis`: a [redis](https://redis.io/) database to handle queries
> and pages caching
> - `castopod_mariadb`: a [mariadb](https://mariadb.org/) server for
> persistent data
> - `castopod_phpmyadmin`: a phpmyadmin server to visualize the mariadb
> database.
> - `castopod_s3`: a mock s3 server to work on the s3 fileManager
2. Run any command inside the containers by prefixing them with
`docker-compose run --rm app`:
```bash
# use PHP
docker-compose run --rm app php -v
# use Composer
docker-compose run --rm app composer -V
# use pnpm
docker-compose run --rm app pnpm -v
# use git
docker-compose run --rm app git version
```
---
## Going Further
### Install Castopod's dependencies
1. Install php dependencies with [Composer](https://getcomposer.org/)
```bash
composer install
```
> [!NOTE]
> The php dependencies aren't included in the repository. Composer will check
> the `composer.json` and `composer.lock` files to download the packages with
> the right versions. The dependencies will live under the `vendor/` folder.
> For more info, check out the
> [Composer documentation](https://getcomposer.org/doc/).
2. Install JavaScript dependencies with [pnpm](https://pnpm.io/)
```bash
pnpm install
```
> [!NOTE]
> The JavaScript dependencies aren't included in the repository. Pnpm will
> check the `package.json` and `pnpm-lock.yaml` files to download the
> packages with the right versions. The dependencies will live under the
> `node_module` folder. For more info, check out the
> [PNPM documentation](https://pnpm.io/motivation).
3. Generate static assets:
```bash
# build all static assets at once
pnpm run build:static
# build specific assets
pnpm run build:icons
pnpm run build:svg
```
> [!NOTE]
> The static assets generated live under the `public/assets` folder, it
> includes JavaScript, styles, images, fonts, icons and svg files.
### Initialize and populate database
> [!TIP]
> You may skip this section if you go through the install wizard (go to
> `/cp-install`).
1. Build the database with the migrate command:
```bash
# loads the database schema during first migration
php spark migrate -all
```
You may need to undo the migration (rollback):
```bash
# rolls back database schema (deletes all tables and their content)
php spark migrate:rollback
```
2. Populate the database with the required data:
```bash
# Populates all required data
php spark db:seed DevSeeder
```
You may choose to add data separately:
```bash
# Populates all categories
php spark db:seed CategorySeeder
# Populates all Languages
php spark db:seed LanguageSeeder
# Adds a superadmin with [admin@castopod.local / castopod] credentials
php spark db:seed DevSuperadminSeeder
```
3. (optional) Populate the database with test data:
- Populate with fake podcast analytics:
```bash
php spark db:seed FakePodcastsAnalyticsSeeder
```
- Populate with fake website analytics:
```bash
php spark db:seed FakeWebsiteAnalyticsSeeder
```
### Useful docker / docker-compose commands
- Monitor the app container:
```bash
docker-compose logs --tail 50 --follow --timestamps app
```
- Interact with the Redis server using included redis-cli command:
```bash
docker exec -it castopod_redis redis-cli
```
- Monitor the Redis container:
```bash
docker-compose logs --tail 50 --follow --timestamps redis
```
- Monitor the mariadb container:
```bash
docker-compose logs --tail 50 --follow --timestamps mariadb
```
- Monitor the phpmyadmin container:
```bash
docker-compose logs --tail 50 --follow --timestamps phpmyadmin
```
- Restart docker containers:
```bash
docker-compose restart
```
- Destroy all containers, opposite of `up` command:
```bash
docker-compose down
```
- Rebuild app container:
```bash
docker-compose build app
```
Check [Docker](https://docs.docker.com/engine/reference/commandline/docker/) and
[docker-compose](https://docs.docker.com/compose/reference/) documentations for
more insights.
### Updating Documentation
Castopod's documentation is written in Markdown and uses the Astro Starlight
framework. To update Castopod's documentation, including the Getting Started
guide and User Guide:
1. Change directories to the `docs` directory and install the dependencies:
```bash
cd docs/
pnpm i
```
2. Start the documentation development server:
```bash
pnpm run dev --host
```
3. The documentation development server runs on port 4321. In your browser visit
`http://localhost:4321/docs`. If the page displays a 404 Not Found error,
click on the Castopod logo in the upper left hand corner of the page and the
documentation should load.
4. Edit the Markdown files with your documentation updates. The Astro Starlight
development server will automatically update each time you save a change.
## Known issues
### Allocation failed - JavaScript heap out of memory
This happens when running `pnpm install`.
👉 By default, docker might not have access to enough RAM. Allocate more memory
and run `pnpm install` again.
### (Linux) Files created inside container are attributed to root locally
You may use Linux user namespaces to fix this on your machine:
> [!NOTE]
> Replace "username" with your local username
1. Go to `/etc/docker/daemon.json` and add:
```json
{
"userns-remap": "username"
}
```
2. Configure the subordinate uid/guid:
```bash
# in /etc/subuid
username:1000:1
username:100000:65536
```
```bash
# in /etc/subgid
username:1000:1
username:100000:65536
```
3. Restart Docker:
```bash
sudo systemctl restart docker
```
4. That's it! Now, the root user in the container will be mapped to the user on
your local machine, no more permission issues! 🎉
You can check
[this great article](https://www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/)
to know more about how it works.
# Contributing to Castopod Host
# Contributing to Castopod
Love Castopod Host and want to help? Thanks so much, there's something to do for
Love Castopod and want to help? Thanks so much, there's something to do for
everybody!
> [!NOTE]
> Castopod follows the [all contributors](https://allcontributors.org/)
> specification in an effort to **recognize any kind of contribution**, not just
> code!
> If you've made a contribution and do not appear in the
> [contributors](../index.md#contributors-✨) list, please
> [let us know](../index.md#contact) so we can correct our mistake! 🙂
Please take a moment to review this document in order to make the contribution
process easy and effective for everyone involved.
......@@ -11,17 +19,34 @@ developers managing and developing this open source project. In return, they
should reciprocate that respect in addressing your issue or assessing patches
and features.
⚠️ Note that **any** contribution made on a repository other than
[the original repository](https://code.podlibre.org/podlibre/castopod-host) will
not be accepted.
## Translating Castopod
We use [Crowdin](https://translate.castopod.org/) to manage translation files
for [Castopod](https://code.castopod.org/), the
[documentation](https://docs.castopod.org/) and the
[landing](https://castopod.org/) websites.
Whether you'd like to correct a translation error, validate new translations or
include your language to Castopod, head into the
[crowdin project](https://translate.castopod.org/) to get started.
> [!NOTE]
> To prevent degrading user experience, new languages are included to Castopod
> when they reach a certain threshold (~90%).
## Using the issue tracker
The [issue tracker](https://code.podlibre.org/podlibre/castopod-host/-/issues)
is the preferred channel for [bug reports](#bug-reports),
The [issue tracker](https://code.castopod.org/adaures/castopod/-/issues) is the
preferred channel for [bug reports](#bug-reports),
[features requests](#feature-requests) and
[submitting pull requests](#pull-requests).
## ⚠️ Security issues and vulnerabilities
If you encounter any security issue or vulnerability in the Castopod source,
please contact us directly by email at
[security@castopod.org](mailto:security@castopod.org)
## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository.
......@@ -45,8 +70,9 @@ your environment? What steps will reproduce the issue? What browser(s) and OS
experience the problem? What would you expect to be the outcome? All these
details will help people to fix any potential bugs.
> [Issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#using-the-templates)
> have been created for this project. You may use them to help you follow those
> [!NOTE]
> [Issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#using-the-templates) have
> been created for this project. You may use them to help you follow those
> guidelines.
## Feature requests
......@@ -72,33 +98,33 @@ accurate comments, etc.) and any other requirements (such as test coverage).
Adhering to the following process is the best way to get your work included in
the project:
1. [Fork](https://docs.gitlab.com/ee/gitlab-basics/fork-project.html) the
project, clone your fork, and configure the remotes:
1. [Fork](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html)
the project, clone your fork, and configure the remotes:
```bash
# Clone your fork of the repo into the current directory
git clone https://code.podlibre.org/<your-username>/castopod-host.git
```bash
# Clone your fork of the repo into the current directory
git clone https://code.castopod.org/<your-username>/castopod.git
# Navigate to the newly cloned directory
cd castopod-host
# Navigate to the newly cloned directory
cd castopod
# Assign the original repo to a remote called "upstream"
git remote add upstream https://code.podlibre.org/podlibre/castopod-host.git
```
# Assign the original repo to a remote called "upstream"
git remote add upstream https://code.castopod.org/adaures/castopod.git
```
2. If you cloned a while ago, get the latest changes from upstream:
```bash
git checkout main
git pull upstream main
```
```bash
git checkout main
git pull upstream main
```
3. Create a new topic branch (off the `main` branch) to contain your feature,
change, or fix:
```bash
git checkout -b <topic-branch-name>
```
```bash
git checkout -b <topic-branch-name>
```
4. Commit your changes in logical chunks. Please adhere to these
[git commit message guidelines](https://conventionalcommits.org/) or your
......@@ -108,22 +134,23 @@ git checkout -b <topic-branch-name>
5. Locally merge (or rebase) the upstream dev branch into your topic branch:
```bash
git pull [--rebase] upstream main
```
```bash
git pull [--rebase] upstream main
```
6. Push your topic branch up to your fork:
```bash
git push origin <topic-branch-name>
```
```bash
git push origin <topic-branch-name>
```
7. [Open a Pull Request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html#new-merge-request-from-a-fork)
with a clear title and description.
**IMPORTANT**: By submitting a patch, you agree to allow the project owners to
license your work under the terms of the
[GNU AGPLv3](https://code.podlibre.org/podlibre/castopod-host/-/blob/main/LICENSE).
> [!IMPORTANT]
> By submitting a patch, you agree to allow the project owners to license your
> work under the terms of the
> [GNU AGPLv3](https://code.castopod.org/adaures/castopod/-/blob/develop/LICENSE.md).
## Collaborating guidelines
......
# Castopod Host dependencies
# Castopod dependencies
Castopod Host uses the following components:
Castopod uses the following components:
PHP Dependencies:
## PHP Dependencies
- [CodeIgniter 4](https://codeigniter.com)
([MIT License](https://codeigniter.com/user_guide/license.html))
- [WhichBrowser/Parser-PHP](https://github.com/WhichBrowser/Parser-PHP)
([MIT License](https://github.com/WhichBrowser/Parser-PHP/blob/master/LICENSE))
- [GeoIP2 PHP API](https://github.com/maxmind/GeoIP2-php)
([Apache License 2.0](https://github.com/maxmind/GeoIP2-php/blob/master/LICENSE))
- [getID3](https://github.com/JamesHeinrich/getID3)
([GNU General Public License v3](https://github.com/JamesHeinrich/getID3/blob/2.0/licenses/license.gpl-30.txt))
- [myth-auth](https://github.com/lonnieezell/myth-auth)
([MIT license](https://github.com/lonnieezell/myth-auth/blob/develop/LICENSE.md))
- [commonmark](https://commonmark.thephpleague.com/)
([BSD 3-Clause "New" or "Revised" License](https://github.com/thephpleague/commonmark/blob/latest/LICENSE))
- [phpdotenv](https://github.com/vlucas/phpdotenv)
([ BSD-3-Clause License ](https://github.com/vlucas/phpdotenv/blob/master/LICENSE))
- [HTML To Markdown for PHP](https://github.com/thephpleague/html-to-markdown)
([MIT License](https://github.com/thephpleague/html-to-markdown/blob/master/LICENSE))
- [opawg/user-agents-php](https://github.com/opawg/user-agents-php)
([MIT License](https://github.com/podlibre/user-agents-php/blob/main/LICENSE))
- [podlibre/ipcat](https://github.com/podlibre/ipcat)
([GNU General Public License v3.0](https://github.com/podlibre/ipcat/blob/master/LICENSE))
- [podlibre/podcast-namespace](https://code.podlibre.org/podlibre/podcastnamespace)
([MIT License](https://code.podlibre.org/podlibre/podcastnamespace/-/blob/master/LICENSE))
- [phpseclib](https://phpseclib.com/)
([MIT License](https://github.com/phpseclib/phpseclib/blob/master/LICENSE))
- [codeigniter4-uuid](https://github.com/michalsn/codeigniter4-uuid)
([MIT License](https://github.com/michalsn/codeigniter4-uuid/blob/develop/LICENSE))
- [essence](https://github.com/essence/essence)
([The FreeBSD License](https://github.com/essence/essence/blob/master/LICENSE.txt))
PHP dependencies can be found in the [composer.json](./composer.json) file.
Javascript dependencies:
## Javascript dependencies
- [rollup](https://rollupjs.org/)
([MIT License](https://github.com/rollup/rollup/blob/master/LICENSE.md))
- [tailwindcss](https://tailwindcss.com/)
([MIT License](https://github.com/tailwindcss/tailwindcss/blob/master/LICENSE))
- [ProseMirror](https://prosemirror.net/)
([MIT License](https://github.com/ProseMirror/prosemirror/blob/master/LICENSE))
- [amCharts 4](https://github.com/amcharts/amcharts4)
([Free amCharts license](https://github.com/amcharts/amcharts4/blob/master/dist/script/LICENSE))
- [Choices.js](https://joshuajohnson.co.uk/Choices/)
([MIT License](https://github.com/jshjohnson/Choices/blob/master/LICENSE))
- [flatpickr](https://flatpickr.js.org/)
([MIT License](https://github.com/flatpickr/flatpickr/blob/master/LICENSE.md))
- [popperjs](https://popper.js.org/)
([MIT License](https://github.com/popperjs/popper-core/blob/master/LICENSE.md))
Javascript dependencies can be found in the [package.json](./package.json) file.
Other:
## Other dependencies
- [Kumbh Sans](https://fonts.google.com/specimen/Kumbh+Sans)
([Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL))
- [Montserrat](https://fonts.google.com/specimen/Montserrat)
- [Inter](https://fonts.google.com/specimen/Inter)
([Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL))
- [RemixIcon](https://remixicon.com/)
([Apache License 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License))
- [OPAWG/User agent list](https://github.com/opawg/user-agents)
- [OPAWG/User agent list](https://github.com/opawg/user-agents-v2)
([by Open Podcast Analytics Working Group](https://github.com/opawg))
([MIT license](https://github.com/opawg/user-agents/blob/master/LICENSE))
([MIT license](https://github.com/opawg/user-agents-v2/blob/master/LICENSE))
- [OPAWG/podcast-rss-useragents](https://github.com/opawg/podcast-rss-useragents)
([by Open Podcast Analytics Working Group](https://github.com/opawg))
([MIT license](https://github.com/opawg/podcast-rss-useragents/blob/master/LICENSE))
......
####################################################
# Castopod Host development Docker file
####################################################
# ⚠️ NOT optimized for production
# should be used only for development purposes
#---------------------------------------------------
FROM php:8.0-fpm
LABEL maintainer="Yassine Doghri <yassine@doghri.fr>"
COPY . /castopod-host
WORKDIR /castopod-host
# Install composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Install server requirements
RUN apt-get update \
# gnupg to sign commits with gpg
&& apt-get install --yes --no-install-recommends gnupg \
# npm through the nodejs package
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
&& apt-get update \
&& apt-get install --yes --no-install-recommends nodejs \
# update npm
&& npm install --global npm@7 \
&& apt-get update \
&& apt-get install --yes --no-install-recommends \
git \
openssh-client \
vim \
# cron for scheduled tasks
cron \
# unzip used by composer
unzip \
# required libraries to install php extensions using
# https://github.com/mlocati/docker-php-extension-installer (included in php's docker image)
libicu-dev \
libpng-dev \
libjpeg-dev \
zlib1g-dev \
libzip-dev \
# intl for Internationalization
&& docker-php-ext-install intl \
&& docker-php-ext-install zip \
# gd for image processing
&& docker-php-ext-configure gd --with-jpeg \
&& docker-php-ext-install gd \
# redis extension for cache
&& pecl install -o -f redis \
&& rm -rf /tmp/pear \
&& docker-php-ext-enable redis \
# mysqli for database access
&& docker-php-ext-install mysqli \
&& docker-php-ext-enable mysqli \
# configure php
&& echo "file_uploads = On\n" \
"memory_limit = 512M\n" \
"upload_max_filesize = 500M\n" \
"post_max_size = 512M\n" \
"max_execution_time = 300\n" \
> /usr/local/etc/php/conf.d/uploads.ini \
# This file lists processing purposes and the personal data gathered by
# Castopod.
# It is intended for hosting providers who want to provide a service
# based on Castopod, helping them to comply with GDPR requirements. Note
# that the services powered by Castopod may collect more data, HTTP logs
# in particular. As a hosting provider, you must inform your users of their
# rights and how their data are used and protected.
purpose:
Deduplicate number of audio file downloads made by the same listener
for analytics purposes
lawfulness: legitimate interest
data: (User IP address + Browser User Agent)
required: yes
visibility: none
description:
In order to produce analytics data comparable to the podcasting
ecosystem standards, the User IP address (REMOTE_ADDR) with the
browser User Agent (HTTP_USER_AGENT) are stored when an audio file
is downloaded.
mitigation:
The data (User IP address + Browser User Agent) is never stored in plain
format.
The data is concatenated with a cryptographic salt, the current date,
and the podcast or episode IDs.
The data is hashed (using sha1) after being concatenated and before
being stored.
The data is stored in a cache database (eg. Redis).
The data expires every day at midnight (server time).
purpose: Connect users to their accounts
lawfulness: legitimate interest
data: username
required: yes
visibility: authenticated users
description:
The username is used to identify users during the login process.
The username is only required for users accessing the admin area.
mitigation:
The username does not have to be a real or known identity.
data: user e-mail address
required: yes
visibility: administrators
description:
The e-mail address is used for administrative purposes, to identify users
during the login process and in case of forgotten password.
data: password
required: yes
visibility: private
description:
The password is used to check the identity of users during the login
process.
mitigation:
Only hashes (using the Argon2 key derivation function) of the passwords
are stored in the database (but they transit over the network).
purpose: Claim ownership of a podcast
lawfulness: legitimate interest
data: Podcast e-mail address
required: yes
visibility: public
description:
The podcast e-mail address is used to claim podcast ownership on other
platforms (such as Apple Podcasts).
mitigation:
The e-mail can be generic.
purpose: Grant access to premium content
lawfulness: legitimate interest
data: Subscriber's email address
required: yes
visibility: administrators
description:
The subscriber's e-mail address is used to provide credentials for
listening to premium content.
mitigation:
The e-mail can be generic.
# How to install Castopod Host <!-- omit in toc -->
_Castopod Host_ was thought-out to be easy to install. Whether using dedicated
or shared hosting, you can install it on most PHP-MySQL compatible web servers.
## Table of contents <!-- omit in toc -->
- [Install instructions](#install-instructions)
- [0. Pre-requisites](#0-pre-requisites)
- [(recommended) Install Wizard](#recommended-install-wizard)
- [(alternative) Manual configuration](#alternative-manual-configuration)
- [Web Server Requirements](#web-server-requirements)
- [PHP v8.0 or higher](#php-v80-or-higher)
- [MySQL compatible database](#mysql-compatible-database)
- [Privileges](#privileges)
- [(Optional) Other recommendations](#optional-other-recommendations)
- [Security concerns](#security-concerns)
## Install instructions
### 0. Pre-requisites
0. Get a Web Server with requirements installed
1. Create a MySQL database for Castopod Host with a user having access and
modification privileges (for more info, see
[Web Server Requirements](#web-server-requirements)).
2. Activate HTTPS on your domain with an _SSL certificate_.
3. Download and unzip the latest
[Castopod Host Package](https://code.podlibre.org/podlibre/castopod-host/-/releases)
onto the web server if you haven’t already.
- ⚠️ Set the web server document root to the `public/` sub-folder.
4. Add a cron task on your web server to run every minute (replace the paths
accordingly):
```php
* * * * * /path/to/php /path/to/castopod-host/public/index.php scheduled-activities
```
> ⚠️ Social features will not work properly if you do not set the task. It is
> used to broadcast social activities to the fediverse.
### (recommended) Install Wizard
1. Run the Castopod Host install script by going to the install wizard page
(`https://your_domain_name.com/cp-install`) in your favorite web browser.
2. Follow the instructions on your screen.
3. Start podcasting!
> **Note:**
>
> The install script writes a `.env` file in the package root. If you cannot go
> through the install wizard, you can
> [create and update the `.env` file manually](#alternative-manual-configuration).
### (alternative) Manual configuration
1. Rename the `.env.example` file to `.env` and update the default values with
your own.
2. Upload the `.env` file to the Castopod Host Package root on your server.
3. Go to `/cp-install` to finish the install process.
4. Start podcasting!
## Web Server Requirements
### PHP v8.0 or higher
PHP version 8.0 or higher is required, with the following extensions installed:
- [intl](https://php.net/manual/en/intl.requirements.php)
- [libcurl](https://php.net/manual/en/curl.requirements.php)
- [mbstring](https://php.net/manual/en/mbstring.installation.php)
- [gd](https://www.php.net/manual/en/image.installation.php)
Additionally, make sure that the following extensions are enabled in your PHP:
- json (enabled by default - don't turn it off)
- xml (enabled by default - don't turn it off)
- [mysqlnd](https://php.net/manual/en/mysqlnd.install.php)
### MySQL compatible database
> We recommend using [MariaDB](https://mariadb.org).
You will need the server hostname, database name, username and password to
complete the installation process. If you do not have these, please contact your
server administrator.
> NB. Castopod Host only works with supported MySQL compatible databases. It
> will break with MySQL v5.6 for example as its end of life was on February
> 5, 2021.
#### Privileges
User must have at least these privileges on the database for Castopod Host to
work: `ALTER`, `DELETE`, `EXECUTE`, `INDEX`, `INSERT`, `SELECT`, `UPDATE`.
### (Optional) Other recommendations
- Redis for better cache performances.
- CDN for static files caching and better performances.
- e-mail gateway for lost passwords.
## Security concerns
Castopod Host is built on top of Codeigniter, a PHP framework that encourages
[good security practices](https://codeigniter.com/user_guide/concepts/security.html).
To maximize your instance safety and prevent any malicious attack, we recommend
you update all your Castopod Host files permissions after installation (to avoid
any permission error):
- `writable/` folder must be **readable** and **writable**.
- `public/media/` folder must be **readable** and **writable**.
- any other file must be set to **readonly**.
For instance, if you are using Apache or NGINX with Ubuntu you may do the
following:
```bash
sudo chown -R root:root /path/to/castopod-host
sudo chown -R www-data:www-data /path/to/castopod-host/writable
sudo chown -R www-data:www-data /path/to/castopod-host/public/media
```
This diff is collapsed.
# How to update Castopod Host <!-- omit in toc -->
After installing _Castopod Host_, you may want to update your instance to the
latest version in order to enjoy the latest features ✨, bug fixes 🐛 and
performance improvements ⚡.
## Table of contents <!-- omit in toc -->
- [Manual update instructions](#manual-update-instructions)
- [Automatic update instructions](#automatic-update-instructions)
- [Frequently asked questions (FAQ)](#frequently-asked-questions-faq)
- [Where can I find my _Castopod Host_ version?](#where-can-i-find-my-castopod-host-version)
- [I haven't updated my instance in a long time… What should I do?](#i-havent-updated-my-instance-in-a-long-time-what-should-i-do)
- [Should I make a backup before updating?](#should-i-make-a-backup-before-updating)
## Manual update instructions
1. Go to the
[releases page](https://code.podlibre.org/podlibre/castopod-host/-/releases)
and see if your instance is up to date with the latest _Castopod Host_
version
- cf.
[Where can I find my _Castopod Host_ version?](#where-can-i-find-my-castopod-host-version)
2. Download the latest release package named `Castopod Host Package`, you may
choose between the `zip` or `tar.gz` archives
- ⚠️ Make sure you download the Castopod Host Package and **NOT** the Source
Code
3. On your server:
- Remove all files except `.env` and `public/media`
- Copy the new files from the downloaded package into your server
- Note: you may need to reset files permissions as during the install
process. Check
[Security Concerns section in INSTALL.md](./INSTALL.md#security-concerns).
4. Alpha releases may come with additional update instructions (see
[releases page](https://code.podlibre.org/podlibre/castopod-host/-/releases)).
They are usually database migration scripts in `.sql` format to update your
database schema.
- 👉 Make sure you run the scripts on your phpmyadmin panel or using command
line to update the database along with the package files!
- cf.
[I haven't updated my instance in a long time… What should I do?](#i-havent-updated-my-instance-in-a-long-time-what-should-i-do)
5. If you are using redis, clear your cache.
6. ✨ Enjoy your fresh instance, you're all done!
## Automatic update instructions
> Coming soon... 👀
## Frequently asked questions (FAQ)
### Where can I find my _Castopod Host_ version?
Go to your _Castopod Host_ admin panel, the version is displayed on the bottom
right corner.
Alternatively, you can find the version in the `app > Config > Constants.php`
file.
### I haven't updated my instance in a long time… What should I do?
No problem! Just get the latest release as described above. Only, when going
through the release instructions (4), perform them sequentially, from the oldest
to the newest.
> You may want to backup your instance depending on how long you haven't updated
> _Castopod Host_.
For example, if you're on `v1.0.0-alpha.42` and would like to upgrade to
`v1.0.0-alpha.58`:
0. (recommended) Make a backup of your files and database.
1. Download the latest release, overwrite your files whilst keeping `.env` and
`public/media`.
2. Go through each release update instructions sequentially (from oldest to
newest) starting with `v1.0.0-alpha.43`, `v1.0.0-alpha.44`,
`v1.0.0-alpha.45`, …, `v1.0.0-alpha.58`.
3. ✨ Enjoy your fresh instance, you're all done!
### Should I make a backup before updating?
We advise you do, so you don't lose everything if anything goes wrong!
More generally, we advise you make regular backups of your Castopod Host files
and database to prevent you from losing it all…
<IfModule authz_core_module>
Require all denied
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>
<IfModule authz_core_module> Require all denied </IfModule>
<IfModule !authz_core_module> Deny from all </IfModule>
<?php
declare(strict_types=1);
namespace App\Authorization;
use Myth\Auth\Authorization\FlatAuthorization as MythAuthFlatAuthorization;
class FlatAuthorization extends MythAuthFlatAuthorization
{
/**
* The group model to use. Usually the class noted below (or an extension thereof) but can be any compatible
* CodeIgniter Model.
*
* @var PermissionModel
*/
protected $permissionModel;
/**
* Checks a group to see if they have the specified permission.
*/
public function groupHasPermission(int | string $permission, int $groupId): bool
{
// Get the Permission ID
$permissionId = $this->getPermissionID($permission);
if (! is_numeric($permissionId)) {
return false;
}
return $this->permissionModel->doesGroupHavePermission($groupId, $permissionId);
}
/**
* Makes user part of given groups.
*
* @param array<string, string> $groups Either collection of ID or names
*/
public function setUserGroups(int $userId, array $groups = []): bool
{
// remove user from all groups before resetting it in new groups
$this->groupModel->removeUserFromAllGroups($userId);
if ($groups === []) {
return true;
}
foreach ($groups as $group) {
$this->addUserToGroup($userId, $group);
}
return true;
}
}
<?php
declare(strict_types=1);
namespace App\Authorization;
use Myth\Auth\Authorization\GroupModel as MythAuthGroupModel;
class GroupModel extends MythAuthGroupModel
{
/**
* @return mixed[]
*/
public function getContributorRoles(): array
{
return $this->select('auth_groups.*')
->like('name', 'podcast_', 'after')
->findAll();
}
/**
* @return mixed[]
*/
public function getUserRoles(): array
{
return $this->select('auth_groups.*')
->notLike('name', 'podcast_', 'after')
->findAll();
}
}
<?php
declare(strict_types=1);
namespace App\Authorization;
use Myth\Auth\Authorization\PermissionModel as MythAuthPermissionModel;
class PermissionModel extends MythAuthPermissionModel
{
/**
* Checks to see if a user, or one of their groups, has a specific permission.
*/
public function doesGroupHavePermission(int $groupId, int $permissionId): bool
{
// Check group permissions and take advantage of caching
$groupPerms = $this->getPermissionsForGroup($groupId);
return count($groupPerms) &&
array_key_exists($permissionId, $groupPerms);
}
/**
* Gets all permissions for a group in a way that can be easily used to check against:
*
* [ id => name, id => name ]
*
* @return array<int, string>
*/
public function getPermissionsForGroup(int $groupId): array
{
$cacheName = "group{$groupId}_permissions";
if (! ($found = cache($cacheName))) {
$groupPermissions = $this->db
->table('auth_groups_permissions')
->select('id, auth_permissions.name')
->join('auth_permissions', 'auth_permissions.id = permission_id', 'inner')
->where('group_id', $groupId)
->get()
->getResultObject();
$found = [];
foreach ($groupPermissions as $row) {
$found[$row->id] = strtolower($row->name);
}
cache()
->save($cacheName, $found, 300);
}
return $found;
}
}
<?php
declare(strict_types=1);
namespace App\Commands;
use App\Models\EpisodeModel;
use CodeIgniter\CLI\BaseCommand;
class EpisodesComputeDownloads extends BaseCommand
{
/**
* The Command's Group
*
* @var string
*/
protected $group = 'Episodes';
/**
* The Command's Name
*
* @var string
*/
protected $name = 'episodes:compute-downloads';
/**
* The Command's Description
*
* @var string
*/
protected $description = "Calculates all episodes downloads and stores results in episodes' downloads_count field.";
/**
* Actually execute a command.
*/
public function run(array $params): void
{
$episodesModel = new EpisodeModel();
$query = $episodesModel->builder()
->select('episodes.id as id, IFNULL(SUM(ape.hits),0) as downloads_count')
->join('analytics_podcasts_by_episode ape', 'episodes.id=ape.episode_id', 'left')
->groupBy('episodes.id');
$episodeModel2 = new EpisodeModel();
$episodeModel2->builder()
->setQueryAsData($query)
->onConstraint('id')
->updateBatch();
}
}
......@@ -2,13 +2,49 @@
declare(strict_types=1);
use ViewThemes\Theme;
/**
* The goal of this file is to allow developers a location where they can overwrite core procedural functions and
* replace them with their own. This file is loaded during the bootstrap process and is called during the frameworks
* replace them with their own. This file is loaded during the bootstrap process and is called during the framework's
* execution.
*
* This can be looked at as a `master helper` file that is loaded early on, and may also contain additional functions
* that you'd like to use throughout your entire application
*
* @link: https://codeigniter4.github.io/CodeIgniter4/
* @see: https://codeigniter.com/user_guide/extending/common.html
*/
if (! function_exists('view')) {
/**
* Grabs the current RendererInterface-compatible class and tells it to render the specified view. Simply provides a
* convenience method that can be used in Controllers, libraries, and routed closures.
*
* NOTE: Does not provide any escaping of the data, so that must all be handled manually by the developer.
*
* @param array<string, mixed> $data
* @param array<string, mixed> $options Unused - reserved for third-party extensions.
*/
function view(string $name, array $data = [], array $options = []): string
{
if (array_key_exists('theme', $options)) {
Theme::setTheme($options['theme']);
}
$path = Theme::path();
/** @var CodeIgniter\View\View $renderer */
$renderer = single_service('renderer', $path);
$saveData = config('View')
->saveData;
if (array_key_exists('saveData', $options)) {
$saveData = (bool) $options['saveData'];
unset($options['saveData']);
}
return $renderer->setData($data, 'raw')
->render($name, $options, $saveData);
}
}
<?php
declare(strict_types=1);
namespace Config;
use ActivityPub\Config\ActivityPub as ActivityPubBase;
use App\Libraries\NoteObject;
class ActivityPub extends ActivityPubBase
{
/**
* --------------------------------------------------------------------
* ActivityPub Objects
* --------------------------------------------------------------------
*/
public string $noteObject = NoteObject::class;
/**
* --------------------------------------------------------------------
* Default avatar and cover images
* --------------------------------------------------------------------
*/
public string $defaultAvatarImagePath = 'assets/images/castopod-avatar-default.jpg';
public string $defaultAvatarImageMimetype = 'image/jpeg';
public string $defaultCoverImagePath = 'assets/images/castopod-cover-default.jpg';
public string $defaultCoverImageMimetype = 'image/jpeg';
}