This commit is contained in:
Paul Schneider 2026-02-28 14:22:33 +00:00
commit d000f77098
13 changed files with 77 additions and 220 deletions

2
.gitignore vendored
View file

@ -42,3 +42,5 @@ builds/
/binaries/Debug/yavscd /binaries/Debug/yavscd
yavsc-pre yavsc-pre
*.env
generated/

37
contrib/Makefile Normal file
View file

@ -0,0 +1,37 @@
APP_PROJECTS=src/Org/Org.csproj src/Api/Api.csproj
SLNDIR=..
generated/%.service: template.service %.env .env
envsubst < template.service > $@
copy-service-Org: $(DESTDIR)/etc/systemd/system/Org.service
$(DESTDIR)/etc/systemd/system/%.service: generated/%.service
sudo cp $^ $@
sudo systemctl daemon-reload
build_publish:
for f in $(APP_PROJECTS); do \
ASPNETCORE_ENV=$(CONFIGURATION) dotnet publish $(SLNDIR)/$$f ; \
done
rmep: build_publish
sudo systemctl stop yavsc-api
sudo systemctl stop yavsc-org
for f in Api Org; do
pushd $(SLNDIR)/src/$$prj
SOURCE_DIR=bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish/
mv $(SOURCE_DIR)/appsettings.json $(SOURCE_DIR)/appsettings.new.json
sudo cp -a $(SOURCE_DIR)/* $(DESTDIR)
sudo chown -R $(USER_AND_GROUP) $(DESTDIR)
sudo sync
popd
done
sudo systemctl start yavsc-org
sudo systemctl start yavsc-api
showConfig:
@echo CONFIGURATION: $(CONFIGURATION)
@echo DESTDIR: $(DESTDIR)
reinstall: copy-service-Org copy-service-Api rmep

View file

@ -1,8 +0,0 @@
#!/bin/sh
dnx gen controller -async -outDir ApiControllers -api -dc ApplicationDbContext -m "$1" -name "$2ApiController"
# dnx gen controller -outDir Controllers -dc ApplicationDbContext -udl -m {model} -name {name}Controller
# dnx gen controller -outDir Controllers -dc ApplicationDbContext -udl -m Yavsc.Models.Booking.MusicianSettings -name InstrumentationController -async -scripts

View file

@ -1,8 +0,0 @@
#!/bin/sh
dnx gen controller -async -udl -outDir Controllers -dc ApplicationDbContext -m "$1" -name "$2Controller"
# dnx gen controller -outDir Controllers -dc ApplicationDbContext -udl -m {model} -name {name}Controller
# dnx gen controller -outDir Controllers -dc ApplicationDbContext -udl -m Yavsc.Models.Booking.MusicianSettings -name InstrumentationController -async -scripts

View file

@ -1,12 +0,0 @@
#!/bin/bash
# Dnx command for this web app
NAME=[myWebAppName]
# root path to the server assets
ROOT=[/srv/www/[myRootDir]]
# relative path to the project source tree,
# from the above root path
PROJECT=[approot/src/[projectName]]

View file

@ -1,5 +1,5 @@
[Unit] [Unit]
Description=Yavsc Description=yavsc-$APP_NAME
After=syslog.target After=syslog.target
After=network.target After=network.target
@ -11,17 +11,17 @@ RestartSec=5s
Type=simple Type=simple
User=www-data User=www-data
Group=www-data Group=www-data
WorkingDirectory=/srv/www/yavsc/ WorkingDirectory=$DESTDIR
ExecStart=/srv/www/yavsc/Yavsc ExecStart=$DESTDIR/$APP_NAME
Restart=always Restart=always
Environment="HOME=/srv/www/yavsc" Environment="HOME=$DESTDIR"
Environment="ASPNETCORE_ENVIRONMENT=Production" Environment="ASPNETCORE_ENVIRONMENT=Production"
Environment="ASPNETCORE_ConnectionStrings__DefaultConnection=YOUR Postgresql CONNECTION STRING" Environment="ASPNETCORE_ConnectionStrings__YavscConnection=Server=$YAVSC_CONNECTION_HOST;Port=$YAVSC_CONNECTION_PORT;Database=$YAVSC_CONNECTION_DATABASE;Username=$YAVSC_CONNECTION_USERNAME;Password=$YAVSC_CONNECTION_PASSWORD;"
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE
StandardOutput=syslog StandardOutput=syslog
StandardError=syslog StandardError=syslog
SyslogIdentifier=yavsc SyslogIdentifier=$APP_NAME
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View file

@ -1,111 +0,0 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: yavsc
# Required-Start: $local_fs $network $named $time $syslog $postgresql
# Required-Stop: $local_fs $network $named $time $syslog $postgresql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Script to run yavsc
### END INIT INFO
# Author: Ivan Derevianko aka druss <drussilla7@gmail.com>
# Modified by: Paul Schneider <redienhcs.luap@gmail.com>
. /lib/init/vars.sh
. /lib/lsb/init-functions
NAME=yavsc
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
TMP_SAVE_runlevel_VAR=$runlevel
unset runlevel
running() {
if [ -f $PIDFILE ]
then
PID=$(cat $PIDFILE)
if kill -0 $PID 2>/dev/null
then
return 0
fi
fi
return 1
}
export WWW_USER=www-data
export ROOT=/srv/www/${NAME}
export DESC="$NAME"
export PIDFILE=/var/run/kestrel-${NAME}.pid
export LOGDIR=/var/log
export DOTNET_CLI_HOME=$ROOT
export ASPDOTNETCORE_ENVIRONMENT=Production
export ASPDOTNETCORE_LOGLEVEL=Information
status() {
if running;
then
echo "Service running $DESC ($NAME; pid: $PID)"
else
echo "Service stopped $DESC ($NAME)"
fi
echo WWW_USER: $WWW_USER ROOT:$ROOT DESC: $DESC NAME: $NAME PIDFILE: $PIDFILE LOGDIR=$LOGDIR
}
start() {
if running; then
echo "Service already running $DESC" "$NAME"
log_end_msg 0
else
cd $ROOT
sleep 4
log_daemon_msg "Starting service $NAME for user $WWW_USER"
if ! start-stop-daemon -SbmCv -u $WWW_USER -p $PIDFILE -d $ROOT -g www-data -x yavsc > "${LOGDIR}/kestrel-${NAME}.log"
then
log_daemon_msg "Could not start $NAME : $?, see ${LOGDIR}/kestrel-${NAME}.log"
log_end_msg 2
else
log_daemon_msg "Service $DESC started ($NAME), logs: ${LOGDIR}/kestrel-${NAME}.log"
log_end_msg 0
fi
fi
}
stop() {
if running
then
log_daemon_msg "Stopping service $NAME"
start-stop-daemon -K -p "$PIDFILE"
log_daemon_msg "$DESC stopped"
log_end_msg 0
else
log_daemon_msg "$DESC Service not running"
log_end_msg 1
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo "Usage: $0 {start|stop|restart}"
esac
export runlevel=$TMP_SAVE_runlevel_VAR

View file

@ -1,11 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.Blog; using Yavsc.Models.Blog;
using Yavsc.Server.Helpers; using Yavsc.Server.Helpers;

View file

@ -61,7 +61,8 @@ namespace Yavsc.ApiControllers
} catch (InvalidPathException ex) { } catch (InvalidPathException ex) {
pathex = ex; pathex = ex;
} }
if (pathex!=null) { if (pathex!=null)
{
_logger.LogError($"invalid sub path: '{subdir}'."); _logger.LogError($"invalid sub path: '{subdir}'.");
return BadRequest(pathex); return BadRequest(pathex);
} }

View file

@ -282,9 +282,6 @@ public static class HostingExtensions
.AddClientStore<ClientStore>() .AddClientStore<ClientStore>()
.AddCorsPolicyService<CorsPolicyService>() .AddCorsPolicyService<CorsPolicyService>()
.AddResourceStore<ResourceStore>() .AddResourceStore<ResourceStore>()
//.AddInMemoryIdentityResources(Config.IdentityResources)
//.AddInMemoryClients(Config.TestingClients)
//.AddInMemoryApiScopes(Config.TestingApiScopes)
.AddConfigurationStore(options => .AddConfigurationStore(options =>
{ {
options.ConfigureDbContext = b => b.UseNpgsql(connectionString, options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
@ -402,13 +399,20 @@ public static class HostingExtensions
{ {
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope()) using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{ {
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
try try
{ {
context.Database.Migrate(); foreach (Type contextType in new Type[]
{
typeof(PersistedGrantDbContext),
typeof(ConfigurationDbContext),
typeof(ApplicationDbContext)
})
{
((DbContext)serviceScope.ServiceProvider
.GetRequiredService(contextType))
.Database.Migrate();
}
} }
catch (InvalidOperationException ex) catch (InvalidOperationException ex)
{ {

View file

@ -1,30 +1,8 @@
DESTDIR=/srv/www/yavsc
CONFIGURATION=Release
USER_AND_GROUP=www-data:www-data
SERVICE_PROD=yavsc
DOTNET_FRAMEWORK=net9.0
all: css js all: css js
dotnet build dotnet build
showConfig:
@echo CONFIGURATION: $(CONFIGURATION)
@echo DESTDIR: $(DESTDIR)
@echo SERVICE_PROD: $(SERVICE_PROD)
publish:
ASPNETCORE_ENV=$(CONFIGURATION) dotnet publish
install_service:
sudo cp ../../contrib/yavsc.service /etc/systemd/system
sudo systemctl enable yavsc
pushInProd: publish
sudo systemctl stop $(SERVICE_PROD)
sudo cp -a bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish/* $(DESTDIR)
sudo chown -R $(USER_AND_GROUP) $(DESTDIR)
sudo sync
sudo systemctl start $(SERVICE_PROD)
%.css: %.scss %.css: %.scss
scss $^ > $@ scss $^ > $@

View file

@ -7,32 +7,25 @@
<asciidoc> <asciidoc>
== L'objectif == L'objectif
Cette application est construite pour mettre en relation des artistes Cette application est construite pour mettre en relation des artistes du domaine musical avec leur public.
du domaine musical avec leur public.
== Le fonctionnement == Le fonctionnement
Les utilisateurs du site sont soit artiste, soit client, soit administrateur. ils ont tous droit à leur blog. Les utilisateurs du site sont soit artiste, soit client, soit administrateur. ils ont tous droit à leur blog.
Pour les artistes, c'est un moyen de promouvoir leur activité. Pour les artistes, c'est un moyen de promouvoir leur activité.
Ils peuvent y publier des articles, truffés de vidéos et photos. Ils peuvent y publier des articles, truffés de vidéos et photos.
Pour les clients, c'est un moyen de casser la glace avec leurs idoles, Pour les clients, c'est un moyen de casser la glace avec leurs idoles, par la description détaillées de leur centres d'intérêts.
par la description détaillées de leur centres d'intérêts.
L'application propulse aussi une messagerie instantanée, disponible depuis L'application propulse aussi une messagerie instantanée, disponible depuis un navigateur Web ou depuis l'appplication mobile,
un navigateur Web ou depuis l'appplication mobile, pouvant garantir la preservation du secret sur toute information personnelle, du client comme du prestataire.
pouvant garantir la preservation du secret sur toute information personnelle,
du client comme du prestataire.
Puis viennent (ou pas) une prise commande, un payement du client, Puis viennent (ou pas) une prise commande, un payement du client,
la prestation, une collecte du retour du client, et un paiement du prestataire de services. la prestation, une collecte du retour du client, et un paiement du prestataire de services.
Ni le client ni le prestataire ne sont anonymes pour l'applications, Ni le client ni le prestataire ne sont anonymes pour l'applications, il sont même formellement authentifies par l'acquitement d'une première
il sont même formellement authentifies par l'acquitement d'une première
facturation en ligne, ou à l'occasion de la saisie de leur profil proféssionnel. facturation en ligne, ou à l'occasion de la saisie de leur profil proféssionnel.
Durant la phase de construction d'un contrat de prestation, Durant la phase de construction d'un contrat de prestation, le client et l'artiste peuvent profiter d'un canal de communication privé et anonyme, qui est fermé à la validation définitive du dit contrat.
le client et l'artiste peuvent profiter d'un canal de communication privé et anonyme,
qui est fermé à la validation définitive du dit contrat.
Valider un contrat, c'est: Valider un contrat, c'est:
@ -41,50 +34,37 @@ Valider un contrat, c'est:
* Le faire signer des deux parties * Le faire signer des deux parties
* Mettre en œuvre d'éventuels paiement d'arrhes * Mettre en œuvre d'éventuels paiement d'arrhes
Une fois validé, le contrat est publié à destination des deux parties. la facture est publiée à destination du client, Une fois validé, le contrat est publié à destination des deux parties. la facture est publiée à destination du client, qui peut l'honorer auprès du système, auquel cas ce client est marqué solvable, et le contrat est marqué approvisionné.
qui peut l'honorer auprès du système, auquel cas ce client est marqué solvable, et le contrat est marqué approvisionné.
En cas de défaut d'approvisionnement, le système prendra soin de marquer le contrat comme provisoire, et de prévenir l'artiste En cas de défaut d'approvisionnement, le système prendra soin de marquer le contrat comme provisoire, et de prévenir l'artiste d'effectuer toute prestation en relation tant le paiement associé laisse à douter.
d'effectuer toute prestation en relation tant le paiement associé laisse à douter.
Une fois sa prestation associée exécutée, les paiements relatifs sont effectués auprès de l'artiste. Une fois sa prestation associée exécutée, les paiements relatifs sont effectués auprès de l'artiste.
Pour un contrat exécuté et non honoré par le client, le processus de poursuite en recouvrement est engagé, sinon, le contrat est archivé, Pour un contrat exécuté et non honoré par le client, le processus de poursuite en recouvrement est engagé, sinon, le contrat est archivé, des attestations de paiement sont disponibles pour l'artiste et la facture est marquée payée, puis repostée au client.
des attestations de paiement sont disponibles pour l'artiste et la facture est marquée payée, puis repostée au client.
=== Pour l'artiste === Pour l'artiste
L'artiste choisit plusieurs paramètres qui vont faire son profil : L'artiste choisit plusieurs paramètres qui vont faire son profil :
* Le type d'activités qu'il veut promouvoir, le type de prestations qu'il fournit (est-ce un DJ, * Le type d'activités qu'il veut promouvoir, le type de prestations qu'il fournit (est-ce un DJ, un chanteur solo, un musicien solo, un ensemble musical classique, un groupe)
un chanteur solo, un musicien solo, un ensemble musical classique, un groupe) * La tarification de sa mise en contact avec un nouveau client (combien je reçois par demande client traitée sans lourdeur de plus d'une journée)
* La tarification de sa mise en contact avec un nouveau client
(combien je reçois par demande client traitée sans lourdeur de plus d'une journée)
* Le lieu où il exerce et, le cas échéant, sur combien de distance il pourrait se déplacer. * Le lieu où il exerce et, le cas échéant, sur combien de distance il pourrait se déplacer.
* un agenda Google optionnel, à consulter pour établir sa disponibilité * Un agenda Google optionnel, à consulter pour établir sa disponibilité
* Des paramètres supplémentaires en fonctions de son type d'activité par exemple, pour * Des paramètres supplémentaires en fonctions de son type d'activité par exemple, pour les ensembles, leur taille, le cas échéant, leur répertoire ou des indications sur le style de leur musique)
les ensembles, leur taille, le cas échéant, leur répertoire ou des indications sur le style de leur musique)
=== Pour le client === Pour le client
Il choisit un lieu et une date pour déclarer un événement avenir Il choisit un lieu et une date pour déclarer un événement avenir (il peut bien-sûr en programmer autant qu'il le veut).
(il peut bien-sûr en programmer autant qu'il le veut).
Il peut, parcourir les publications des artistes, et entamer, Il peut, parcourir les publications des artistes, et entamer, sur la base d'un de ses projets événementiel, la négociation d'un contrat de prestation.
sur la base d'un de ses projets événementiel, la négociation d'un contrat de prestation.
Il a accès à la connaissance des journées connues comme libres des artistes par le système. Il a accès à la connaissance des journées connues comme libres des artistes par le système.
== La confidentialité == La confidentialité
À aucun moment, aucune adresse postale, aucune adresse e-mail ni aucun numéro de téléphone À aucun moment, aucune adresse postale, aucune adresse e-mail ni aucun numéro de téléphone ne sont transmis ni aux clients, ni aux artistes. Seul le système a accès à ces informations.
ne sont transmis ni aux clients, ni aux artistes. Seul le système a accès à ces informations.
De plus, le droit de retrait est permanent et sa mise en oeuvre immédiate. De plus, le droit de retrait est permanent et sa mise en oeuvre immédiate.
Les artistes comme les clients peuvent demander leur désinscription, Les artistes comme les clients peuvent demander leur désinscription, qui désactive immédiatement les publications associées à leurs informations, et programme la suppression complète de ces dites informations dans les quinze jours à compter de la demande, sauf demande contradictoire.
qui désactive immédiatement les publications associées à leurs informations,
et programme la suppression complète de ces dites informations dans les quinze jours
à compter de la demande, sauf demande contradictoire.
L'opération est annulable, jusqu'à deux semaines après sa programmation. L'opération est annulable, jusqu'à deux semaines après sa programmation.
</asciidoc> </asciidoc>
<p>@Model</p>

View file

@ -34,7 +34,7 @@
@using IdentityServer8.EntityFramework.Entities; @using IdentityServer8.EntityFramework.Entities;
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Yavsc @addTagHelper *, Org
@inject IAuthorizationService AuthorizationService @inject IAuthorizationService AuthorizationService