Skip to content

Commit

Permalink
Merge pull request #329 from karlomikus/develop
Browse files Browse the repository at this point in the history
Major release v4
  • Loading branch information
karlomikus authored Sep 20, 2024
2 parents 514e9c0 + 7a8d978 commit ee8a2a4
Show file tree
Hide file tree
Showing 343 changed files with 8,820 additions and 11,085 deletions.
3 changes: 3 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ DB_CONNECTION=sqlite
DB_FOREIGN_KEYS=true

# Drivers
LOG_CHANNEL=stderr
LOG_LEVEL=warning
CACHE_DRIVER=redis
FILESYSTEM_DISK=local
Expand All @@ -25,6 +26,8 @@ REDIS_PORT=6379
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=
MEILISEARCH_KEY=
MEILISEARCH_API_KEY=
MEILISEARCH_API_KEY_UID=

# Mail
# MAIL_MAILER=
Expand Down
2 changes: 2 additions & 0 deletions .env.testing
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ DB_DATABASE=":memory:"
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://meilisearch:7700
MEILISEARCH_KEY=masterKeyThatIsReallyReallyLong4Real
MEILISEARCH_API_KEY=
MEILISEARCH_API_KEY_UID=

SPEC_PATH=./docs

Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Install libvips
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libvips42
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.3'
extensions: bcmath, intl, ffi
ini-values: ffi.enable=true, zend.max_allowed_stack_size=-1

- uses: actions/checkout@v4

Expand Down
93 changes: 93 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,96 @@
# v4.0.0
This is a new major release. Here's a quick summary of the more interesting changes:

- Docker image is now run as an unprivileged user by default. This has various implications, so please check the migration guide for more info
- Improved API endpoint naming and structure
- Added public Bar Assistant JSON schema specification for cocktail recipes
- Data exporting is now available in multiple formats

[Migration guide](https://docs.barassistant.app/setup/migrate-to-40/)

## Breaking changes
- Minimal PHP version is now 8.3
- Removed `imagick` PHP extension
- New extensions required: `ffi`
- Removed importing cocktails from collections
- Removed importing data from Bar Assistant v2
- List all cocktails and ingredients endpoints don't have default includes anymore
- Refer to OpenAPI documentation for a list of available includes
- Shelf
- Moved `/shelf/ingredients` to `/users/{id}/ingredients`
- Changed response schema, now returns `IngredientBasic`
- Supports pagination
- Moved `/shelf/cocktails` to `/users/{id}/cocktails`
- Changed response schema, now returns `CocktailBasic`
- Supports pagination
- Moved `/shelf/cocktails/favorites` to `/users/{id}/cocktails/favorites`
- Changed response schema, now returns `CocktailBasic`
- Supports pagination
- Removed `cocktails` property from `Ingredient` schema
- Use `/ingredients/{id}/cocktails` endpoint instead
- Supports pagination
- Moved `/ingredients/recommend` to `/users/{id}/ingredients/recommend`
- Grouped `/login`, `/logout`, `/register`, `/forgot-password`, `/reset-password` and `/verify/{id}/{hash}` endpoints into `/auth`
- Shopping list
- Moved `/shopping-list` to `/users/{id}/shopping-list`
- Updated `ShoppingList` schema
- Collections
- Removed PUT `/collections/{id}/cocktails/{cocktailId}` endpoint
- Removed `/collections/{id}/share` endpoint
- Removed DELETE `/collections/{id}/cocktails/{cocktailId}` endpoint
- Removed PUT `/collections/{id}/cocktails/{cocktailId}` endpoint
- Changed POST `/collections/{id}/cocktails` endpoint to PUT `/collections/{id}/cocktails`
- Moved GET `/collections/shared` to GET `/bars/{id}/collections`
- Ratings
- Moved `/ratings/cocktails/{id}` to `/cocktails/{id}/ratings`
- Changed POST ratings response status code to 201
- Menu
- Changed `price` attribute in menu request from `string` to `integer`
- Exports
- Added POST `/exports/{id}/download` endpoint
- Used to generate a download link for an export
- Added GET `/exports/{id}/download` endpoint
- Now requires a token and an expiration date
- Authorization is not required anymore
- Used to download an export
- Import
- Importing now requires a valid JSON schema
- Removed `save` parameter from `/import/cocktail` endpoint
- Removed `main_image_id` from cocktail model
- Use `images.sort` instead
- Removed `main_image_id` from ingredient model
- Use `images.sort` instead
- Stats
- Moved `/stats` to `/bars/{id}/stats`

## New
- Introduced `Bar-Assistant-Bar-Id` header to specify bar id
- Used for all endpoints that require bar id
- You can still send `bar_id` query parameter when needed, but it is considered deprecated
- Added `/ingredients/{id}/cocktails` endpoint, lists all cocktails that use this ingredient
- Includes cocktails that use this ingredient as a substitute
- Added `/ingredients/{id}/substitutes` endpoint, lists all ingredients that are used as a substitute for this ingredient in cocktail recipes
- Introduced new export recipe schema
- Added `quantity` to shopping list ingredients
- Images are now converted to WebP format before saving to disk
- Added `/images` endpoint, this endpoint is used to list all user uploaded images
- Bar search tokens are now saved in database
- Added `/import/scrape` endpoint
- This endpoint is used to extract recipe data from a website
- Result is a JSON schema that can be imported via `/import/cocktail` endpoint
- Images in response are now base64 encoded. This allows more flexibility in image handling for the clients
- Added `used_as_substitute_for` and `can_be_substituted_with` to ingredient response

## Changes
- Recommended ingredients now take complex ingredients into consideration
- Image processing moved from Imagick to Vips
- This now requires `libvips` to be installed on the server
- You can install it via `apt-get install -y --no-install-recommends libvips42`
- This now requires `ffi` PHP extension to be installed, and some .ini tweaks
- Meilisearch client API keys are now generated via artisan command
- All dates in responses are now in ISO 8601 format
- You can now update slug of existing bar

# v3.19.1
## Fixes
- Fix missing base data in recipes export
Expand Down
101 changes: 43 additions & 58 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,92 +1,77 @@
FROM php:8.2-fpm AS php-base
FROM alpine:latest AS datapack

ARG PGID=1000
ENV PGID=${PGID}
ARG PUID=1000
ENV PUID=${PUID}
RUN apk add --no-cache git

# Add php extension manager
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
WORKDIR /app/data

RUN git clone --depth 1 --branch datapack https://github.com/bar-assistant/data.git .

RUN rm -r .git

FROM serversideup/php:8.3-fpm-nginx AS php-base

ENV S6_CMD_WAIT_FOR_SERVICES=1
ENV APP_BASE_DIR=/var/www/cocktails
ENV NGINX_WEBROOT=/var/www/cocktails/public

USER root

RUN install-php-extensions bcmath intl ffi

RUN apt update \
&& apt-get install -y \
git \
unzip \
sqlite3 \
bash \
cron \
&& chmod +x /usr/local/bin/install-php-extensions \
&& install-php-extensions imagick opcache redis zip pcntl bcmath intl \
&& echo "access.log = /dev/null" >> /usr/local/etc/php-fpm.d/www.conf \
&& apt-get install -y --no-install-recommends libvips42 \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Add composer
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer

# Configure php
COPY ./resources/docker/dist/php.ini $PHP_INI_DIR/php.ini

WORKDIR /var/www/cocktails
USER www-data

CMD ["php-fpm"]
WORKDIR ${APP_BASE_DIR}

FROM php-base AS dist

ENV PHP_OPCACHE_ENABLE=1
ENV PHP_OPCACHE_MAX_ACCELERATED_FILES=20000
ENV PHP_OPCACHE_MEMORY_CONSUMPTION=256
ARG BAR_ASSISTANT_VERSION
ENV BAR_ASSISTANT_VERSION=${BAR_ASSISTANT_VERSION:-develop}

RUN apt update \
&& apt-get install -y \
nginx \
gosu \
supervisor \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --chmod=755 ./resources/docker/dist/init.sh /etc/entrypoint.d/99-bass.sh

WORKDIR /var/www/cocktails
COPY --chmod=755 --chown=www-data:www-data ./resources/docker/dist/nginx.conf /etc/nginx/server-opts.d/99-bass.conf

COPY . .
USER root

ADD https://github.com/bar-assistant/data.git ./resources/data
RUN docker-php-serversideup-s6-init

RUN composer install --optimize-autoloader --no-dev
USER www-data

# Configure nginx
COPY ./resources/docker/dist/nginx.conf /etc/nginx/sites-enabled/default
COPY ./resources/docker/dist/php.ini /usr/local/etc/php/conf.d/zzz-bass-php.ini

# Add container entrypoint script
COPY ./resources/docker/dist/entrypoint.sh /usr/local/bin/entrypoint
COPY --chown=www-data:www-data . .

RUN chmod +x /usr/local/bin/entrypoint \
&& chmod +x /var/www/cocktails/resources/docker/dist/run.sh \
&& sed -i "s/{{VERSION}}/$BAR_ASSISTANT_VERSION/g" ./docs/open-api-spec.yml \
&& mkdir -p /var/www/cocktails/storage/bar-assistant/ \
&& echo "* * * * * www-data cd /var/www/cocktails && php artisan schedule:run >> /dev/null 2>&1" >> /etc/crontab \
&& chown -R www-data:www-data /var/www/cocktails
COPY --from=datapack --chown=www-data:www-data /app/data ./resources/data

EXPOSE 3000
RUN composer install --optimize-autoloader --no-dev \
&& sed -i "s/{{VERSION}}/$BAR_ASSISTANT_VERSION/g" ./docs/openapi-generated.yaml \
&& cp .env.dist .env

VOLUME ["/var/www/cocktails/storage/bar-assistant"]
VOLUME ["$APP_BASE_DIR/storage/bar-assistant"]

ENTRYPOINT ["entrypoint"]
FROM php-base AS dev

FROM php-base AS localdev
USER root

RUN useradd -G www-data,root -u $PUID -d /home/developer developer
RUN mkdir -p /home/developer/.composer && \
chown -R developer:developer /home/developer
ARG USER_ID=1000
ARG GROUP_ID=1000

RUN install-php-extensions xdebug

RUN echo "* * * * * developer cd /var/www/cocktails && php artisan schedule:run >> /dev/null 2>&1" >> /etc/crontab

USER developer

WORKDIR /var/www/cocktails
RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \
docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID --service nginx

EXPOSE 9000
RUN docker-php-serversideup-s6-init

CMD ["php-fpm"]
USER www-data
38 changes: 30 additions & 8 deletions app/Console/Commands/BarExportRecipes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@
use Throwable;
use Kami\Cocktail\Models\Bar;
use Illuminate\Console\Command;
use Kami\Cocktail\External\Export\ToDataPack;
use Kami\Cocktail\Models\Export;
use Illuminate\Support\Facades\DB;

use function Laravel\Prompts\search;

use Kami\Cocktail\External\ExportTypeEnum;
use Kami\Cocktail\External\Export\ToDataPack;
use Kami\Cocktail\External\Export\ToRecipeType;
use Kami\Cocktail\External\ForceUnitConvertEnum;

class BarExportRecipes extends Command
{
Expand All @@ -17,16 +24,16 @@ class BarExportRecipes extends Command
*
* @var string
*/
protected $signature = 'bar:export-recipes {barId} {--t|type=yml : Export type}';
protected $signature = 'bar:export-recipes {barId?} {--t|type=datapack : Export type} {--u|units= : Force unit conversion when possible (none, ml, oz, cl)}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Export all recipe data (ingredients, cocktails, base data) from a single bar';
protected $description = 'Export data from a single bar. Available export types: datapack, schema, markdown, json-ld, xml, yaml';

public function __construct(private readonly ToDataPack $exporter)
public function __construct(private readonly ToDataPack $datapackExporter, private readonly ToRecipeType $recipeExporter)
{
parent::__construct();
}
Expand All @@ -37,9 +44,20 @@ public function __construct(private readonly ToDataPack $exporter)
public function handle(): int
{
$barId = (int) $this->argument('barId');
$type = $this->option('type') ?? 'yml';

$type = ExportTypeEnum::tryFrom($type);
if ($barId === 0) {
$barId = search(
'Search bars by name',
fn (string $value) => strlen($value) > 0
? DB::table('bars')->orderBy('name')->where('name', 'like', '%' . $value . '%')->pluck('name', 'id')->toArray()
: [],
scroll: 10,
required: true
);
}

$type = ExportTypeEnum::tryFrom($this->option('type') ?? 'datapack');
$units = ForceUnitConvertEnum::tryFrom($this->option('units') ?? 'none');

try {
$bar = Bar::findOrFail($barId);
Expand All @@ -49,9 +67,13 @@ public function handle(): int
return Command::FAILURE;
}

$this->output->info(sprintf('Starting recipe export from bar: %s - "%s"', $bar->id, $bar->name));
$this->line(sprintf('Starting new export (%s | %s) from bar: %s - "%s"', $type->value, $units->value, $bar->id, $bar->name));

$filename = $this->exporter->process($barId, null, $type);
if ($type === ExportTypeEnum::Datapack) {
$filename = $this->datapackExporter->process($bar->id, Export::generateFilename('datapack'), $units);
} else {
$filename = $this->recipeExporter->process($bar->id, Export::generateFilename($type->getFilenameContext()), $type, $units);
}

$this->output->success('Data exported to file: ' . $filename);

Expand Down
Loading

0 comments on commit ee8a2a4

Please sign in to comment.