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 4070 additions and 1028 deletions
File moved
File moved
# Authors # Authors
- [Benjamin Bellamy](https://code.podlibre.org/benjamin) <ben@podlibre.org> - [Benjamin Bellamy](https://code.castopod.org/benjamin) <ben@castopod.org>
- [Yassine Doghri](https://code.podlibre.org/yassine) <yassine@podlibre.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. ...@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at 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. and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the
......
# Setup your development environment <!-- omit in toc --> # Setup your development environment
## Table of contents <!-- omit in toc -->
- [Introduction](#introduction)
- [Pre-requisites](#pre-requisites)
- [(recommended) Develop inside the app Container with VSCode](#recommended-develop-inside-the-app-container-with-vscode)
- [(not-recommended) Develop outside the app container](#not-recommended-develop-outside-the-app-container)
- [Install Castopod Host's dependencies](#install-castopod-hosts-dependencies)
- [Initialize and populate database](#initialize-and-populate-database)
- [Start hacking](#start-hacking)
- [Going Further](#going-further)
- [Useful docker / docker-compose commands](#useful-docker--docker-compose-commands)
- [Known issues](#known-issues)
- [Allocation failed - JavaScript heap out of memory](#allocation-failed---javascript-heap-out-of-memory)
- [Files created inside container are attributed to root locally (Linux)](#files-created-inside-container-are-attributed-to-root-locally-linux)
## Introduction ## Introduction
Castopod Host is a web app based on the `php` framework Castopod is a web app based on the `php` framework
[CodeIgniter 4](https://codeigniter.com). [CodeIgniter 4](https://codeigniter.com).
To setup a dev environment, we use [Docker](https://www.docker.com/). A 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 `docker-compose.yml` and `Dockerfile` are included in the project's root folder
to help you kickstart your contribution. to help you kickstart your contribution.
> Know that you don't need any prior knowledge of Docker to follow the next > You don't need any prior knowledge of Docker to follow the next steps.
> steps. However, if you wish to use your own environment, feel free to do so! > However, if you wish to use your own environment, feel free to do so!
## Pre-requisites ## Setup instructions
0. Install [docker](https://docs.docker.com/get-docker). ### 1. Pre-requisites
1. Clone Castopod Host project by running: 0. Install [Docker](https://docs.docker.com/get-docker).
1. Clone the Castopod repository by running:
```bash ```bash
git clone https://code.podlibre.org/podlibre/castopod-host.git git clone https://code.castopod.org/adaures/castopod.git
``` ```
2. Create a `.env` file with the minimum required config to connect the app to 2. Create a `.env` file with the minimum required config to connect the app to
...@@ -42,6 +29,8 @@ to help you kickstart your contribution. ...@@ -42,6 +29,8 @@ to help you kickstart your contribution.
```ini ```ini
CI_ENVIRONMENT="development" 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. # By default, this is set to true in the app config.
# For development, this must be set to false as it is # For development, this must be set to false as it is
...@@ -49,39 +38,56 @@ to help you kickstart your contribution. ...@@ -49,39 +38,56 @@ to help you kickstart your contribution.
app.forceGlobalSecureRequests=false app.forceGlobalSecureRequests=false
app.baseURL="http://localhost:8080/" app.baseURL="http://localhost:8080/"
app.mediaBaseURL="http://localhost:8080/"
admin.gateway="cp-admin" admin.gateway="cp-admin"
auth.gateway="cp-auth" auth.gateway="cp-auth"
database.default.hostname="mariadb" database.default.hostname="mariadb"
database.default.database="castopod" database.default.database="castopod"
database.default.username="podlibre" database.default.username="castopod"
database.default.password="castopod" database.default.password="castopod"
database.default.DBPrefix="dev_"
analytics.salt="DEV_ANALYTICS_SALT"
cache.handler="redis" cache.handler="redis"
cache.redis.host = "redis" cache.redis.host="redis"
# You may not want to use redis as your cache handler # You may not want to use redis as your cache handler
# Comment/remove the two lines above and uncomment # Comment/remove the two lines above and uncomment
# the next line for file caching. # the next line for file caching.
# -----------------------
#cache.handler="file" #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
``` ```
> _NB._ You can tweak your environment by setting more environment variables > [!NOTE]
> in your custom `.env` file. See the `env` for examples or the > 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) > [CodeIgniter4 User Guide](https://codeigniter.com/user_guide/index.html)
> for more info. > for more info.
3. (for docker desktop) Add the repository you've cloned to docker desktop's 3. (for Docker desktop) Add the repository you've cloned to Docker desktop's
`Settings` > `Resources` > `File Sharing` `Settings` > `Resources` > `File Sharing`
## (recommended) Develop inside the app Container with VSCode ### 2. (recommended) Develop inside the app container with VSCode
If you're working in VSCode, you can take advantage of the `.devcontainer/` If you're working in VSCode, you can take advantage of the `.devcontainer/`
folder. It defines a development environment (dev container) with preinstalled folder. It defines a development environment (dev container) with preinstalled
requirements and VSCode extensions so you don't have to worry about them. All requirements and VSCode extensions so you don't have to worry about them. All
required services will be loaded automagically! required services will be loaded automagically! 🪄
1. Install the VSCode extension 1. Install the VSCode extension
[Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
...@@ -90,21 +96,21 @@ required services will be loaded automagically! ...@@ -90,21 +96,21 @@ required services will be loaded automagically!
> The VSCode window will reload inside the dev container. Expect several > The VSCode window will reload inside the dev container. Expect several
> minutes during first load as it is building all necessary services. > minutes during first load as it is building all necessary services.
**Note**: The dev container will start by running Castopod Host's php server. **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 During development, you will have to start [Vite](https://vitejs.dev)'s dev
server for compiling the typescript code and styles: server for compiling the typescript code and styles:
```bash ```bash
# run Vite dev server # run Vite dev server
npm run dev pnpm run dev
``` ```
If there is any issue with the php server not running, you can restart them If there is any issue with the PHP server not running, you can restart them
using the following commands: using the following commands:
```bash ```bash
# run Castopod host server # run Castopod server
php spark serve --host 0.0.0.0 php spark serve - 0.0.0.0
``` ```
3. You're all set! 🎉 3. You're all set! 🎉
...@@ -119,23 +125,43 @@ required services will be loaded automagically! ...@@ -119,23 +125,43 @@ required services will be loaded automagically!
# Composer is installed # Composer is installed
composer -V composer -V
# npm is installed # pnpm is installed
npm -v pnpm -v
# git is installed # git is installed
git version git version
``` ```
For more info, see For more info, see
[VSCode Remote Containers](https://code.visualstudio.com/docs/remote/containers) [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:
## (not-recommended) Develop outside the app container - username: **castopod**
- password: **castopod**
### 2-alt. Develop outside the app container
You do not wish to use the VSCode devcontainer? No problem! You do not wish to use the VSCode devcontainer? No problem!
1. Start docker containers manually: 1. Start the Docker containers manually:
Go to project's root folder and run: Go to the project's root folder and run:
```bash ```bash
# starts all services declared in docker-compose.yml file # starts all services declared in docker-compose.yml file
...@@ -150,19 +176,21 @@ You do not wish to use the VSCode devcontainer? No problem! ...@@ -150,19 +176,21 @@ You do not wish to use the VSCode devcontainer? No problem!
``` ```
> The `docker-compose up -d` command will boot 4 containers in the > The `docker-compose up -d` command will boot 5 containers in the
> background: > background:
> >
> - `castopod-host_app`: a php based container with Castopod Host > - `castopod_app`: a php based container with Castopod requirements
> requirements installed > installed
> - `castopod-host_redis`: a [redis](https://redis.io/) database to handle > - `castopod_redis`: a [redis](https://redis.io/) database to handle queries
> queries and pages caching > and pages caching
> - `castopod-host_mariadb`: a [mariadb](https://mariadb.org/) server for > - `castopod_mariadb`: a [mariadb](https://mariadb.org/) server for
> persistent data > persistent data
> - `castopod-host_phpmyadmin`: a phpmyadmin server to visualize the mariadb > - `castopod_phpmyadmin`: a phpmyadmin server to visualize the mariadb
> database. > database.
> - `castopod_s3`: a mock s3 server to work on the s3 fileManager
2. Run any command by prefixing them with `docker-compose run --rm app`: 2. Run any command inside the containers by prefixing them with
`docker-compose run --rm app`:
```bash ```bash
# use PHP # use PHP
...@@ -171,14 +199,18 @@ You do not wish to use the VSCode devcontainer? No problem! ...@@ -171,14 +199,18 @@ You do not wish to use the VSCode devcontainer? No problem!
# use Composer # use Composer
docker-compose run --rm app composer -V docker-compose run --rm app composer -V
# use npm # use pnpm
docker-compose run --rm app npm -v docker-compose run --rm app pnpm -v
# use git # use git
docker-compose run --rm app git version docker-compose run --rm app git version
``` ```
## Install Castopod Host's dependencies ---
## Going Further
### Install Castopod's dependencies
1. Install php dependencies with [Composer](https://getcomposer.org/) 1. Install php dependencies with [Composer](https://getcomposer.org/)
...@@ -186,48 +218,44 @@ You do not wish to use the VSCode devcontainer? No problem! ...@@ -186,48 +218,44 @@ You do not wish to use the VSCode devcontainer? No problem!
composer install composer install
``` ```
> **Note:** > [!NOTE]
>
> The php dependencies aren't included in the repository. Composer will check > 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 `composer.json` and `composer.lock` files to download the packages with
> the right versions. The dependencies will live under the `vendor/` folder. > the right versions. The dependencies will live under the `vendor/` folder.
> For more info, check out the > For more info, check out the
> [Composer documentation](https://getcomposer.org/doc/). > [Composer documentation](https://getcomposer.org/doc/).
2. Install javascript dependencies with [npm](https://www.npmjs.com/) 2. Install JavaScript dependencies with [pnpm](https://pnpm.io/)
```bash ```bash
npm install pnpm install
``` ```
> **Note:** > [!NOTE]
> > The JavaScript dependencies aren't included in the repository. Pnpm will
> The javascript dependencies aren't included in the repository. Npm will > check the `package.json` and `pnpm-lock.yaml` files to download the
> check the `package.json` and `package.lock` files to download the packages > packages with the right versions. The dependencies will live under the
> with the right versions. The dependencies will live under the `node_module` > `node_module` folder. For more info, check out the
> folder. For more info, check out the > [PNPM documentation](https://pnpm.io/motivation).
> [NPM documentation](https://docs.npmjs.com/).
3. Generate static assets: 3. Generate static assets:
```bash ```bash
# build all static assets at once # build all static assets at once
npm run build:static pnpm run build:static
# build specific assets # build specific assets
npm run build:icons pnpm run build:icons
npm run build:svg pnpm run build:svg
``` ```
> **Note:** > [!NOTE]
>
> The static assets generated live under the `public/assets` folder, it > The static assets generated live under the `public/assets` folder, it
> includes javascript, styles, images, fonts, icons and svg files. > includes JavaScript, styles, images, fonts, icons and svg files.
## Initialize and populate database ### Initialize and populate database
> **Note:** > [!TIP]
>
> You may skip this section if you go through the install wizard (go to > You may skip this section if you go through the install wizard (go to
> `/cp-install`). > `/cp-install`).
...@@ -249,7 +277,7 @@ You do not wish to use the VSCode devcontainer? No problem! ...@@ -249,7 +277,7 @@ You do not wish to use the VSCode devcontainer? No problem!
```bash ```bash
# Populates all required data # Populates all required data
php spark db:seed AppSeeder php spark db:seed DevSeeder
``` ```
You may choose to add data separately: You may choose to add data separately:
...@@ -261,97 +289,119 @@ You do not wish to use the VSCode devcontainer? No problem! ...@@ -261,97 +289,119 @@ You do not wish to use the VSCode devcontainer? No problem!
# Populates all Languages # Populates all Languages
php spark db:seed LanguageSeeder php spark db:seed LanguageSeeder
# Populates all podcasts platforms # Adds a superadmin with [admin@castopod.local / castopod] credentials
php spark db:seed PlatformSeeder php spark db:seed DevSuperadminSeeder
# Populates all Authentication data (roles definition…)
php spark db:seed AuthSeeder
``` ```
3. (optionnal) Populate the database with test data: 3. (optional) Populate the database with test data:
```bash - Populate with fake podcast analytics:
# Populates test data (login: admin / password: AGUehL3P)
php spark db:seed TestSeeder
# Populates with fake podcast analytics ```bash
php spark db:seed FakePodcastsAnalyticsSeeder php spark db:seed FakePodcastsAnalyticsSeeder
# Populates with fake website analytics
php spark db:seed FakeWebsiteAnalyticsSeeder
``` ```
TestSeeder will add an active superadmin user with the following credentials: - Populate with fake website analytics:
- username: **admin**
- password: **AGUehL3P**
## Start hacking ```bash
php spark db:seed FakeWebsiteAnalyticsSeeder
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:
- [localhost:8080](http://localhost:8080/) for the Castopod Host app
- [localhost:8888](http://localhost:8888/) for the phpmyadmin interface:
- username: **podlibre** ### Useful docker / docker-compose commands
- password: **castopod**
--- - Monitor the app container:
## Going Further ```bash
docker-compose logs --tail 50 --follow --timestamps app
```
### Useful docker / docker-compose commands - Interact with the Redis server using included redis-cli command:
```bash ```bash
# monitor the app container docker exec -it castopod_redis redis-cli
docker-compose logs --tail 50 --follow --timestamps app ```
# interact with redis server using included redis-cli command - Monitor the Redis container:
docker exec -it castopod-host_redis redis-cli
# monitor the redis container ```bash
docker-compose logs --tail 50 --follow --timestamps redis docker-compose logs --tail 50 --follow --timestamps redis
```
# monitor the mariadb container - Monitor the mariadb container:
```bash
docker-compose logs --tail 50 --follow --timestamps mariadb docker-compose logs --tail 50 --follow --timestamps mariadb
```
- Monitor the phpmyadmin container:
# monitor the phpmyadmin container ```bash
docker-compose logs --tail 50 --follow --timestamps phpmyadmin docker-compose logs --tail 50 --follow --timestamps phpmyadmin
```
- Restart docker containers:
# restart docker containers ```bash
docker-compose restart docker-compose restart
```
- Destroy all containers, opposite of `up` command:
# Destroy all containers, opposite of `up` command ```bash
docker-compose down docker-compose down
```
# Rebuild app container - Rebuild app container:
```bash
docker-compose build app docker-compose build app
``` ```
Check [docker](https://docs.docker.com/engine/reference/commandline/docker/) and Check [Docker](https://docs.docker.com/engine/reference/commandline/docker/) and
[docker-compose](https://docs.docker.com/compose/reference/) documentations for [docker-compose](https://docs.docker.com/compose/reference/) documentations for
more insights. 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 ## Known issues
### Allocation failed - JavaScript heap out of memory ### Allocation failed - JavaScript heap out of memory
This happens when running `npm install`. This happens when running `pnpm install`.
👉 By default, docker might not have access to enough RAM. Allocate more memory 👉 By default, docker might not have access to enough RAM. Allocate more memory
and run `npm install` again. and run `pnpm install` again.
### Files created inside container are attributed to root locally (Linux) ### (Linux) Files created inside container are attributed to root locally
You may use Linux user namespaces to fix this on your machine: You may use Linux user namespaces to fix this on your machine:
> **Note:** > [!NOTE]
>
> Replace "username" with your local username > Replace "username" with your local username
1. Go to `/etc/docker/daemon.json` and add: 1. Go to `/etc/docker/daemon.json` and add:
...@@ -376,7 +426,7 @@ You may use Linux user namespaces to fix this on your machine: ...@@ -376,7 +426,7 @@ You may use Linux user namespaces to fix this on your machine:
username:100000:65536 username:100000:65536
``` ```
3. Restart docker: 3. Restart Docker:
```bash ```bash
sudo systemctl restart docker sudo systemctl restart docker
......
# 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! 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 Please take a moment to review this document in order to make the contribution
process easy and effective for everyone involved. process easy and effective for everyone involved.
...@@ -11,17 +19,34 @@ developers managing and developing this open source project. In return, they ...@@ -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 should reciprocate that respect in addressing your issue or assessing patches
and features. and features.
⚠️ Note that **any** contribution made on a repository other than ## Translating Castopod
[the original repository](https://code.podlibre.org/podlibre/castopod-host) will
not be accepted. 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 ## Using the issue tracker
The [issue tracker](https://code.podlibre.org/podlibre/castopod-host/-/issues) The [issue tracker](https://code.castopod.org/adaures/castopod/-/issues) is the
is the preferred channel for [bug reports](#bug-reports), preferred channel for [bug reports](#bug-reports),
[features requests](#feature-requests) and [features requests](#feature-requests) and
[submitting pull requests](#pull-requests). [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 ## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository. 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 ...@@ -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 experience the problem? What would you expect to be the outcome? All these
details will help people to fix any potential bugs. details will help people to fix any potential bugs.
> [Issue templates](https://docs.gitlab.com/ee/user/project/description_templates.html#using-the-templates) > [!NOTE]
> have been created for this project. You may use them to help you follow those > [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. > guidelines.
## Feature requests ## Feature requests
...@@ -72,33 +98,33 @@ accurate comments, etc.) and any other requirements (such as test coverage). ...@@ -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 Adhering to the following process is the best way to get your work included in
the project: the project:
1. [Fork](https://docs.gitlab.com/ee/gitlab-basics/fork-project.html) the 1. [Fork](https://docs.gitlab.com/ee/user/project/repository/forking_workflow.html)
project, clone your fork, and configure the remotes: the project, clone your fork, and configure the remotes:
```bash ```bash
# Clone your fork of the repo into the current directory # Clone your fork of the repo into the current directory
git clone https://code.podlibre.org/<your-username>/castopod-host.git git clone https://code.castopod.org/<your-username>/castopod.git
# Navigate to the newly cloned directory # Navigate to the newly cloned directory
cd castopod-host cd castopod
# Assign the original repo to a remote called "upstream" # Assign the original repo to a remote called "upstream"
git remote add upstream https://code.podlibre.org/podlibre/castopod-host.git git remote add upstream https://code.castopod.org/adaures/castopod.git
``` ```
2. If you cloned a while ago, get the latest changes from upstream: 2. If you cloned a while ago, get the latest changes from upstream:
```bash ```bash
git checkout main git checkout main
git pull upstream main git pull upstream main
``` ```
3. Create a new topic branch (off the `main` branch) to contain your feature, 3. Create a new topic branch (off the `main` branch) to contain your feature,
change, or fix: change, or fix:
```bash ```bash
git checkout -b <topic-branch-name> git checkout -b <topic-branch-name>
``` ```
4. Commit your changes in logical chunks. Please adhere to these 4. Commit your changes in logical chunks. Please adhere to these
[git commit message guidelines](https://conventionalcommits.org/) or your [git commit message guidelines](https://conventionalcommits.org/) or your
...@@ -108,22 +134,23 @@ git checkout -b <topic-branch-name> ...@@ -108,22 +134,23 @@ git checkout -b <topic-branch-name>
5. Locally merge (or rebase) the upstream dev branch into your topic branch: 5. Locally merge (or rebase) the upstream dev branch into your topic branch:
```bash ```bash
git pull [--rebase] upstream main git pull [--rebase] upstream main
``` ```
6. Push your topic branch up to your fork: 6. Push your topic branch up to your fork:
```bash ```bash
git push origin <topic-branch-name> 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) 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. with a clear title and description.
**IMPORTANT**: By submitting a patch, you agree to allow the project owners to > [!IMPORTANT]
license your work under the terms of the > By submitting a patch, you agree to allow the project owners to license your
[GNU AGPLv3](https://code.podlibre.org/podlibre/castopod-host/-/blob/main/LICENSE). > work under the terms of the
> [GNU AGPLv3](https://code.castopod.org/adaures/castopod/-/blob/develop/LICENSE.md).
## Collaborating guidelines ## 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) PHP dependencies can be found in the [composer.json](./composer.json) file.
([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))
Javascript dependencies: ## Javascript dependencies
- [rollup](https://rollupjs.org/) Javascript dependencies can be found in the [package.json](./package.json) file.
([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))
- [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))
Other: ## Other dependencies
- [Kumbh Sans](https://fonts.google.com/specimen/Kumbh+Sans) - [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)) ([Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL))
...@@ -56,9 +18,9 @@ Other: ...@@ -56,9 +18,9 @@ Other:
([Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL)) ([Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL))
- [RemixIcon](https://remixicon.com/) - [RemixIcon](https://remixicon.com/)
([Apache License 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License)) ([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)) ([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) - [OPAWG/podcast-rss-useragents](https://github.com/opawg/podcast-rss-useragents)
([by Open Podcast Analytics Working Group](https://github.com/opawg)) ([by Open Podcast Analytics Working Group](https://github.com/opawg))
([MIT license](https://github.com/opawg/podcast-rss-useragents/blob/master/LICENSE)) ([MIT license](https://github.com/opawg/podcast-rss-useragents/blob/master/LICENSE))
......
# 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) with **JPEG**,
**PNG** and **WEBP** libraries.
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: `CREATE`, `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.
<IfModule authz_core_module> <IfModule authz_core_module> Require all denied </IfModule>
Require all denied <IfModule !authz_core_module> Deny from all </IfModule>
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>
<?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,18 +2,17 @@ ...@@ -2,18 +2,17 @@
declare(strict_types=1); declare(strict_types=1);
use App\Libraries\View;
use ViewThemes\Theme; use ViewThemes\Theme;
/** /**
* The goal of this file is to allow developers a location where they can overwrite core procedural functions and * 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. * execution.
* *
* This can be looked at as a `master helper` file that is loaded early on, and may also contain additional functions * 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 * 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')) { if (! function_exists('view')) {
...@@ -28,12 +27,17 @@ if (! function_exists('view')) { ...@@ -28,12 +27,17 @@ if (! function_exists('view')) {
*/ */
function view(string $name, array $data = [], array $options = []): string function view(string $name, array $data = [], array $options = []): string
{ {
if (array_key_exists('theme', $options)) {
Theme::setTheme($options['theme']);
}
$path = Theme::path(); $path = Theme::path();
/** @var CodeIgniter\View\View $renderer */ /** @var CodeIgniter\View\View $renderer */
$renderer = single_service('renderer', $path); $renderer = single_service('renderer', $path);
$saveData = config(View::class)->saveData; $saveData = config('View')
->saveData;
if (array_key_exists('saveData', $options)) { if (array_key_exists('saveData', $options)) {
$saveData = (bool) $options['saveData']; $saveData = (bool) $options['saveData'];
......
...@@ -5,7 +5,7 @@ declare(strict_types=1); ...@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Config; namespace Config;
use CodeIgniter\Config\BaseConfig; use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\FileHandler; use Override;
class App extends BaseConfig class App extends BaseConfig
{ {
...@@ -14,38 +14,34 @@ class App extends BaseConfig ...@@ -14,38 +14,34 @@ class App extends BaseConfig
* Base Site URL * Base Site URL
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* URL to your CodeIgniter root. Typically this will be your base URL, * URL to your CodeIgniter root. Typically, this will be your base URL,
* WITH a trailing slash: * WITH a trailing slash:
* *
* http://example.com/ * E.g., http://example.com/
*
* If this is not set then CodeIgniter will try guess the protocol, domain
* and path to your installation. However, you should always configure this
* explicitly and never rely on auto-guessing, especially in production
* environments.
*/ */
public string $baseURL = 'http://localhost:8080/'; public string $baseURL = 'http://localhost:8080/';
/** /**
* -------------------------------------------------------------------------- * Allowed Hostnames in the Site URL other than the hostname in the baseURL.
* Media Base URL * If you want to accept multiple Hostnames, set this.
* --------------------------------------------------------------------------
* *
* URL to your media root. Typically this will be your base URL, * E.g.,
* WITH a trailing slash: * When your site URL ($baseURL) is 'http://example.com/', and your site
* also accepts 'http://media.example.com/' and 'http://accounts.example.com/':
* ['media.example.com', 'accounts.example.com']
* *
* http://cdn.example.com/ * @var list<string>
*/ */
public string $mediaBaseURL = 'http://localhost:8080/'; public array $allowedHostnames = [];
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Index File * Index File
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* Typically this will be your index.php file, unless you've renamed it to * Typically, this will be your `index.php` file, unless you've renamed it to
* something else. If you are using mod_rewrite to remove the page set this * something else. If you have configured your web server to remove this file
* variable so that it is blank. * from your site URIs, set this variable to an empty string.
*/ */
public string $indexPage = ''; public string $indexPage = '';
...@@ -54,18 +50,42 @@ class App extends BaseConfig ...@@ -54,18 +50,42 @@ class App extends BaseConfig
* URI PROTOCOL * URI PROTOCOL
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* *
* This item determines which getServer global should be used to retrieve the * This item determines which server global should be used to retrieve the
* URI string. The default setting of 'REQUEST_URI' works for most servers. * URI string. The default setting of 'REQUEST_URI' works for most servers.
* If your links do not seem to work, try one of the other delicious flavors: * If your links do not seem to work, try one of the other delicious flavors:
* *
* 'REQUEST_URI' Uses $_SERVER['REQUEST_URI'] * 'REQUEST_URI': Uses $_SERVER['REQUEST_URI']
* 'QUERY_STRING' Uses $_SERVER['QUERY_STRING'] * 'QUERY_STRING': Uses $_SERVER['QUERY_STRING']
* 'PATH_INFO' Uses $_SERVER['PATH_INFO'] * 'PATH_INFO': Uses $_SERVER['PATH_INFO']
* *
* WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
*/ */
public string $uriProtocol = 'REQUEST_URI'; public string $uriProtocol = 'REQUEST_URI';
/*
*--------------------------------------------------------------------------
* Allowed URL Characters
*--------------------------------------------------------------------------
*
* This lets you specify which characters are permitted within your URLs.
* When someone tries to submit a URL with disallowed characters they will
* get a warning message.
*
* As a security measure you are STRONGLY encouraged to restrict URLs to
* as few characters as possible.
*
* By default, only these are allowed: `a-z 0-9~%.:_-`
*
* Set an empty string to allow all characters -- but only if you are insane.
*
* The configured value is actually a regular expression character group
* and it will be used as: '/\A[<permittedURIChars>]+\z/iu'
*
* DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
*
*/
public string $permittedURIChars = 'a-z 0-9~%.:_\-@';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Default Locale * Default Locale
...@@ -99,9 +119,23 @@ class App extends BaseConfig ...@@ -99,9 +119,23 @@ class App extends BaseConfig
* by the application in descending order of priority. If no match is * by the application in descending order of priority. If no match is
* found, the first locale will be used. * found, the first locale will be used.
* *
* @var string[] * IncomingRequest::setLocale() also uses this list.
*/ *
public array $supportedLocales = ['en', 'fr']; * @var list<string>
*/
public array $supportedLocales = [
'en',
'fr',
'pl',
'de',
'pt-br',
'nn-no',
'es',
'zh-hans',
'ca',
'br',
'sr-latn',
];
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
...@@ -110,6 +144,9 @@ class App extends BaseConfig ...@@ -110,6 +144,9 @@ class App extends BaseConfig
* *
* The default timezone that will be used in your application to display * The default timezone that will be used in your application to display
* dates with the date helper, and can be retrieved through app_timezone() * dates with the date helper, and can be retrieved through app_timezone()
*
* @see https://www.php.net/manual/en/timezones.php for list of timezones
* supported by PHP.
*/ */
public string $appTimezone = 'UTC'; public string $appTimezone = 'UTC';
...@@ -133,170 +170,10 @@ class App extends BaseConfig ...@@ -133,170 +170,10 @@ class App extends BaseConfig
* If true, this will force every request made to this application to be * If true, this will force every request made to this application to be
* made via a secure connection (HTTPS). If the incoming request is not * made via a secure connection (HTTPS). If the incoming request is not
* secure, the user will be redirected to a secure version of the page * secure, the user will be redirected to a secure version of the page
* and the HTTP Strict Transport Security header will be set. * and the HTTP Strict Transport Security (HSTS) header will be set.
*/ */
public bool $forceGlobalSecureRequests = true; public bool $forceGlobalSecureRequests = true;
/**
* --------------------------------------------------------------------------
* Session Driver
* --------------------------------------------------------------------------
*
* The session storage driver to use:
* - `CodeIgniter\Session\Handlers\FileHandler`
* - `CodeIgniter\Session\Handlers\DatabaseHandler`
* - `CodeIgniter\Session\Handlers\MemcachedHandler`
* - `CodeIgniter\Session\Handlers\RedisHandler`
*/
public string $sessionDriver = FileHandler::class;
/**
* --------------------------------------------------------------------------
* Session Cookie Name
* --------------------------------------------------------------------------
*
* The session cookie name, must contain only [0-9a-z_-] characters
*/
public string $sessionCookieName = 'ci_session';
/**
* --------------------------------------------------------------------------
* Session Expiration
* --------------------------------------------------------------------------
*
* The number of SECONDS you want the session to last.
* Setting to 0 (zero) means expire when the browser is closed.
*/
public int $sessionExpiration = 7200;
/**
* --------------------------------------------------------------------------
* Session Save Path
* --------------------------------------------------------------------------
*
* The location to save sessions to and is driver dependent.
*
* For the 'files' driver, it's a path to a writable directory.
* WARNING: Only absolute paths are supported!
*
* For the 'database' driver, it's a table name.
* Please read up the manual for the format with other session drivers.
*
* IMPORTANT: You are REQUIRED to set a valid save path!
*/
public string $sessionSavePath = WRITEPATH . 'session';
/**
* --------------------------------------------------------------------------
* Session Match IP
* --------------------------------------------------------------------------
*
* Whether to match the user's IP address when reading the session data.
*
* WARNING: If you're using the database driver, don't forget to update
* your session table's PRIMARY KEY when changing this setting.
*/
public bool $sessionMatchIP = false;
/**
* --------------------------------------------------------------------------
* Session Time to Update
* --------------------------------------------------------------------------
*
* How many seconds between CI regenerating the session ID.
*/
public int $sessionTimeToUpdate = 300;
/**
* --------------------------------------------------------------------------
* Session Regenerate Destroy
* --------------------------------------------------------------------------
*
* Whether to destroy session data associated with the old session ID
* when auto-regenerating the session ID. When set to FALSE, the data
* will be later deleted by the garbage collector.
*/
public bool $sessionRegenerateDestroy = false;
/**
* --------------------------------------------------------------------------
* Cookie Prefix
* --------------------------------------------------------------------------
*
* Set a cookie name prefix if you need to avoid collisions.
*
* @deprecated use Config\Cookie::$prefix property instead.
*/
public string $cookiePrefix = '';
/**
* --------------------------------------------------------------------------
* Cookie Domain
* --------------------------------------------------------------------------
*
* Set to `.your-domain.com` for site-wide cookies.
*
* @deprecated use Config\Cookie::$domain property instead.
*/
public string $cookieDomain = '';
/**
* --------------------------------------------------------------------------
* Cookie Path
* --------------------------------------------------------------------------
*
* Typically will be a forward slash.
*
* @deprecated use Config\Cookie::$path property instead.
*/
public string $cookiePath = '/';
/**
* --------------------------------------------------------------------------
* Cookie Secure
* --------------------------------------------------------------------------
*
* Cookie will only be set if a secure HTTPS connection exists.
*
* @deprecated use Config\Cookie::$secure property instead.
*/
public bool $cookieSecure = false;
/**
* --------------------------------------------------------------------------
* Cookie HttpOnly
* --------------------------------------------------------------------------
*
* Cookie will only be accessible via HTTP(S) (no JavaScript).
*
* @deprecated use Config\Cookie::$httponly property instead.
*/
public bool $cookieHTTPOnly = true;
/**
* --------------------------------------------------------------------------
* Cookie SameSite
* --------------------------------------------------------------------------
*
* Configure cookie SameSite setting. Allowed values are:
* - None
* - Lax
* - Strict
* - ''
*
* Alternatively, you can use the constant names:
* - `Cookie::SAMESITE_NONE`
* - `Cookie::SAMESITE_LAX`
* - `Cookie::SAMESITE_STRICT`
*
* Defaults to `Lax` for compatibility with modern browsers. Setting `''`
* (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$cookieSecure` must also be set.
*
* @deprecated use Config\Cookie::$samesite property instead.
*/
public string $cookieSameSite = 'Lax';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Reverse Proxy IPs * Reverse Proxy IPs
...@@ -304,103 +181,21 @@ class App extends BaseConfig ...@@ -304,103 +181,21 @@ class App extends BaseConfig
* *
* If your server is behind a reverse proxy, you must whitelist the proxy * If your server is behind a reverse proxy, you must whitelist the proxy
* IP addresses from which CodeIgniter should trust headers such as * IP addresses from which CodeIgniter should trust headers such as
* HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify * X-Forwarded-For or Client-IP in order to properly identify
* the visitor's IP address. * the visitor's IP address.
* *
* You can use both an array or a comma-separated list of proxy addresses, * You need to set a proxy IP address or IP address with subnets and
* as well as specifying whole subnets. Here are a few examples: * the HTTP header for the client IP address.
* *
* Comma-separated: '10.0.1.200,192.168.5.0/24' * Here are some examples:
* Array: ['10.0.1.200', '192.168.5.0/24'] * [
* '10.0.1.200' => 'X-Forwarded-For',
* '192.168.5.0/24' => 'X-Real-IP',
* ]
* *
* @var string|string[] * @var array<string, string>|string
*/ */
public string | array $proxyIPs = ''; public $proxyIPs = [];
/**
* --------------------------------------------------------------------------
* CSRF Token Name
* --------------------------------------------------------------------------
*
* The token name.
*
* @deprecated Use `Config\Security` $tokenName property instead of using this property.
*/
public string $CSRFTokenName = 'csrf_test_name';
/**
* --------------------------------------------------------------------------
* CSRF Header Name
* --------------------------------------------------------------------------
*
* The header name.
*
* @deprecated Use `Config\Security` $headerName property instead of using this property.
*/
public string $CSRFHeaderName = 'X-CSRF-TOKEN';
/**
* --------------------------------------------------------------------------
* CSRF Cookie Name
* --------------------------------------------------------------------------
*
* The cookie name.
*
* @deprecated Use `Config\Security` $cookieName property instead of using this property.
*/
public string $CSRFCookieName = 'csrf_cookie_name';
/**
* --------------------------------------------------------------------------
* CSRF Expire
* --------------------------------------------------------------------------
*
* The number in seconds the token should expire.
*
* @deprecated Use `Config\Security` $expire property instead of using this property.
*/
public int $CSRFExpire = 7200;
/**
* --------------------------------------------------------------------------
* CSRF Regenerate
* --------------------------------------------------------------------------
*
* Regenerate token on every submission?
*
* @deprecated Use `Config\Security` $regenerate property instead of using this property.
*/
public bool $CSRFRegenerate = true;
/**
* --------------------------------------------------------------------------
* CSRF Redirect
* --------------------------------------------------------------------------
*
* Redirect to previous page with error on failure?
*
* @deprecated Use `Config\Security` $redirect property instead of using this property.
*/
public bool $CSRFRedirect = true;
/**
* --------------------------------------------------------------------------
* CSRF SameSite
* --------------------------------------------------------------------------
*
* Setting for CSRF SameSite cookie token. Allowed values are:
* - None
* - Lax
* - Strict
* - ''
*
* Defaults to `Lax` as recommended in this link:
*
* @see https://portswigger.net/web-security/csrf/samesite-cookies
*
* @deprecated Use `Config\Security` $samesite property instead of using this property.
*/
public string $CSRFSameSite = 'Lax';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
...@@ -420,14 +215,6 @@ class App extends BaseConfig ...@@ -420,14 +215,6 @@ class App extends BaseConfig
*/ */
public bool $CSPEnabled = false; public bool $CSPEnabled = false;
/**
* --------------------------------------------------------------------------
* Media root folder
* --------------------------------------------------------------------------
* Defines the root folder for media files storage
*/
public string $mediaRoot = 'media';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Instance / Site Config * Instance / Site Config
...@@ -437,18 +224,63 @@ class App extends BaseConfig ...@@ -437,18 +224,63 @@ class App extends BaseConfig
public string $siteTitleSeparator = ' | '; public string $siteTitleSeparator = ' | ';
public string $siteDescription = 'Castopod Host is an open-source hosting platform made for podcasters who want engage and interact with their audience.'; public string $siteDescription = 'Castopod is an open-source hosting platform made for podcasters who want engage and interact with their audience.';
/** /**
* @var array<int|string, string> * @var array<int|string, string>
*/ */
public array $siteIcon = [ public array $siteIcon = [
'ico' => '/favicon.ico', 'ico' => '/favicon.ico',
'64' => '/icon-64.png', '64' => '/icon-64.png',
'180' => '/icon-180.png', '180' => '/icon-180.png',
'192' => '/icon-192.png', '192' => '/icon-192.png',
'512' => '/icon-512.png', '512' => '/icon-512.png',
]; ];
public string $theme = 'pine'; public string $theme = 'pine';
/**
* Storage limit in Gigabytes
*/
public ?int $storageLimit = null;
/**
* Bandwidth limit (per month) in Gigabytes
*/
public ?int $bandwidthLimit = null;
public ?string $legalNoticeURL = null;
/**
* AuthToken Config Constructor
*/
public function __construct()
{
parent::__construct();
if (is_string($this->proxyIPs)) {
$array = json_decode($this->proxyIPs, true);
if (is_array($array)) {
$this->proxyIPs = $array;
}
}
}
/**
* Override parent initEnvValue() to allow for direct setting to array properties values from ENV
*
* In order to set array properties via ENV vars we need to set the property to a string value first.
*
* @param mixed $property
*/
#[Override]
protected function initEnvValue(&$property, string $name, string $prefix, string $shortPrefix): void
{
// if attempting to set property from ENV, first set to empty string
if ($name === 'proxyIPs' && $this->getEnvValue($name, $prefix, $shortPrefix) !== null) {
$property = '';
}
parent::initEnvValue($property, $name, $prefix, $shortPrefix);
}
} }
...@@ -16,6 +16,8 @@ use CodeIgniter\Config\AutoloadConfig; ...@@ -16,6 +16,8 @@ use CodeIgniter\Config\AutoloadConfig;
* *
* NOTE: If you use an identical key in $psr4 or $classmap, then * NOTE: If you use an identical key in $psr4 or $classmap, then
* the values in this file will overwrite the framework's values. * the values in this file will overwrite the framework's values.
*
* @immutable
*/ */
class Autoload extends AutoloadConfig class Autoload extends AutoloadConfig
{ {
...@@ -27,38 +29,39 @@ class Autoload extends AutoloadConfig ...@@ -27,38 +29,39 @@ class Autoload extends AutoloadConfig
* their location on the file system. These are used by the autoloader * their location on the file system. These are used by the autoloader
* to locate files the first time they have been instantiated. * to locate files the first time they have been instantiated.
* *
* The '/app' and '/system' directories are already mapped for you. * The 'Config' (APPPATH . 'Config') and 'CodeIgniter' (SYSTEMPATH) are
* you may change the name of the 'App' namespace if you wish, * already mapped for you.
*
* You may change the name of the 'App' namespace if you wish,
* but this should be done prior to creating any namespaced classes, * but this should be done prior to creating any namespaced classes,
* else you will need to modify all of those classes for this to work. * else you will need to modify all of those classes for this to work.
* *
* Prototype: * @var array<string, list<string>|string>
*
* $psr4 = [
* 'CodeIgniter' => SYSTEMPATH,
* 'App' => APPPATH
* ];
*
* @var array<string, string>
*/ */
public $psr4 = [ public $psr4 = [
APP_NAMESPACE => APPPATH, APP_NAMESPACE => APPPATH,
'Modules' => ROOTPATH . 'modules/', 'Modules' => ROOTPATH . 'modules/',
'Modules\Admin' => ROOTPATH . 'modules/Admin/', 'Modules\Admin' => ROOTPATH . 'modules/Admin/',
'Modules\Auth' => ROOTPATH . 'modules/Auth/', 'Modules\Analytics' => ROOTPATH . 'modules/Analytics/',
'Modules\Analytics' => ROOTPATH . 'modules/Analytics/', 'Modules\Api\Rest\V1' => ROOTPATH . 'modules/Api/Rest/V1',
'Modules\Install' => ROOTPATH . 'modules/Install/', 'Modules\Auth' => ROOTPATH . 'modules/Auth/',
'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/', 'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse/',
'Config' => APPPATH . 'Config/', 'Modules\Install' => ROOTPATH . 'modules/Install/',
'ViewComponents' => APPPATH . 'Libraries/ViewComponents/', 'Modules\Media' => ROOTPATH . 'modules/Media/',
'ViewThemes' => APPPATH . 'Libraries/ViewThemes/', 'Modules\MediaClipper' => ROOTPATH . 'modules/MediaClipper/',
'MediaClipper' => APPPATH . 'Libraries/MediaClipper/', 'Modules\Platforms' => ROOTPATH . 'modules/Platforms/',
'Themes' => ROOTPATH . 'themes', 'Modules\Plugins' => ROOTPATH . 'modules/Plugins/',
'Modules\PodcastImport' => ROOTPATH . 'modules/PodcastImport/',
'Modules\PremiumPodcasts' => ROOTPATH . 'modules/PremiumPodcasts/',
'Modules\Update' => ROOTPATH . 'modules/Update/',
'Modules\WebSub' => ROOTPATH . 'modules/WebSub/',
'Themes' => ROOTPATH . 'themes',
'ViewComponents' => APPPATH . 'Libraries/ViewComponents/',
'ViewThemes' => APPPATH . 'Libraries/ViewThemes/',
]; ];
/** /**
* ------------------------------------------------------------------- * -------------------------------------------------------------------
* Class Map
* ------------------------------------------------------------------- * -------------------------------------------------------------------
* The class map provides a map of class names and their exact * The class map provides a map of class names and their exact
* location on the drive. Classes loaded in this manner will have * location on the drive. Classes loaded in this manner will have
...@@ -85,12 +88,25 @@ class Autoload extends AutoloadConfig ...@@ -85,12 +88,25 @@ class Autoload extends AutoloadConfig
* or for loading functions. * or for loading functions.
* *
* Prototype: * Prototype:
* ``` *
* $files = [ * $files = [
* '/path/to/my/file.php', * '/path/to/my/file.php',
* ]; * ];
* ``` *
* @var array<int, string> * @var list<string>
*/
public $files = [];
/**
* -------------------------------------------------------------------
* Helpers
* -------------------------------------------------------------------
* Prototype:
* $helpers = [
* 'form',
* ];
*
* @var list<string>
*/ */
public $files = [APPPATH . 'Libraries/ViewComponents/Helpers/view_components_helper.php']; public $helpers = ['auth', 'setting', 'plugins'];
} }
...@@ -9,8 +9,10 @@ declare(strict_types=1); ...@@ -9,8 +9,10 @@ declare(strict_types=1);
* In development, we want to show as many errors as possible to help * In development, we want to show as many errors as possible to help
* make sure they don't make it to production. And save us hours of * make sure they don't make it to production. And save us hours of
* painful debugging. * painful debugging.
*
* If you set 'display_errors' to '1', CI4's detailed error report will show.
*/ */
error_reporting(-1); error_reporting(E_ALL);
ini_set('display_errors', '1'); ini_set('display_errors', '1');
/** /**
......
...@@ -8,9 +8,13 @@ declare(strict_types=1); ...@@ -8,9 +8,13 @@ declare(strict_types=1);
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* Don't show ANY in production environments. Instead, let the system catch * Don't show ANY in production environments. Instead, let the system catch
* it and display a generic error message. * it and display a generic error message.
*
* If you set 'display_errors' to '1', CI4's detailed error report will show.
*/ */
error_reporting(E_ALL & ~E_DEPRECATED);
// If you want to suppress more types of errors.
// error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
ini_set('display_errors', '0'); ini_set('display_errors', '0');
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
......
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
declare(strict_types=1); declare(strict_types=1);
/*
* The environment testing is reserved for PHPUnit testing. It has special
* conditions built into the framework at various places to assist with that.
* You can’t use it for your development.
*/
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* ERROR DISPLAY * ERROR DISPLAY
...@@ -10,7 +16,7 @@ declare(strict_types=1); ...@@ -10,7 +16,7 @@ declare(strict_types=1);
* make sure they don't make it to production. And save us hours of * make sure they don't make it to production. And save us hours of
* painful debugging. * painful debugging.
*/ */
error_reporting(-1); error_reporting(E_ALL);
ini_set('display_errors', '1'); ini_set('display_errors', '1');
/** /**
......
...@@ -18,5 +18,5 @@ class CURLRequest extends BaseConfig ...@@ -18,5 +18,5 @@ class CURLRequest extends BaseConfig
* If true, all the options won't be reset between requests. * If true, all the options won't be reset between requests.
* It may cause an error request with unnecessary headers. * It may cause an error request with unnecessary headers.
*/ */
public bool $shareOptions = true; public bool $shareOptions = false;
} }