Merge branch 'dev' into 'master'

Migration de strapi v3 vers la v4

See merge request cedric-famibelle-pronzola/oki-api!1
This commit is contained in:
2022-05-19 22:37:41 +00:00
49 changed files with 35875 additions and 5331 deletions
+7
View File
@@ -33,3 +33,10 @@ TELEGRAM_API_TOKEN=
DEEPL_URL= DEEPL_URL=
DEEPL_KEY= DEEPL_KEY=
# V4 variables
API_TOKEN_SALT=
ADMIN_JWT_SECRET=
APP_KEYS=
-50
View File
@@ -1,50 +0,0 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/v3.x/concepts/models.html#lifecycle-hooks)
* to customize this model
*/
const slugify = require('slugify')
const jwennTeksEpiId = async data => {
const teks = await strapi.query('teks').find({id_in: data})
return teks
}
const jwennAwtisEpiId = async id => {
const awtis = await strapi.query('awtis').find({id})
return awtis
}
module.exports = {
lifecycles: {
beforeUpdate: async (params, data) => {
if (!data.slug) {
data.slug = slugify(data.alias, {lower: true, remove: /[*#+~.()'"!:@]/g})
}
},
beforeCreate: async data => {
data.slug = slugify(data.alias, {lower: true, remove: /[*#+~.()'"!:@]/g})
},
afterUpdate: async (params, data) => {
const {id} = data
const awtis = await jwennAwtisEpiId(id)
if (awtis.teks && awtis.teks.length >= 1) {
const teks = await jwennTeksEpiId(awtis.teks)
Promise.all(teks.map(async t => {
const {id, tit, slug, awtis} = t
const alias = awtis.map(a => a.alias).join('-')
const slugUpdated = slugify(`${alias}-${tit}`, {lower: true, remove: /[*#+~.()'"!:@]/g})
if (slug !== slugUpdated) {
await strapi.query('teks').update(
{id},
{slug: slugUpdated}
)
}
}))
}
}
}
}
-53
View File
@@ -1,53 +0,0 @@
{
"kind": "collectionType",
"collectionName": "awtis",
"info": {
"name": "awtis",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"attributes": {
"alias": {
"type": "string",
"unique": true,
"required": true
},
"prenon": {
"type": "string"
},
"non": {
"type": "string"
},
"biyografi": {
"type": "richtext"
},
"nesans": {
"type": "date"
},
"foto": {
"collection": "file",
"via": "related",
"allowedTypes": [
"images"
],
"plugin": "upload",
"required": false,
"pluginOptions": {}
},
"teks": {
"via": "awtis",
"collection": "teks"
},
"user": {
"plugin": "users-permissions",
"model": "user"
},
"slug": {
"type": "string"
}
}
}
-39
View File
@@ -1,39 +0,0 @@
'use strict';
const jwennTeksEpiId = async teksId => {
const teks = await strapi.query('teks').findOne({id: teksId})
return teks
}
const jwennUserEpiId = async userId => {
const user = await strapi.query('user', 'users-permissions').findOne({id: userId})
return user
}
module.exports = {
lifecycles: {
beforeCreate: async data => {
if (data.kontni && data.teks && data.user) {
const teks = await jwennTeksEpiId(data.teks)
const user = await jwennUserEpiId(data.user)
if(!teks || !user) {
throw strapi.errors.badRequest('Not found')
}
} else {
throw strapi.errors.badRequest('Missing fields')
}
},
afterCreate: async data => {
if (data.user) {
strapi.services.email.send(
process.env.SMTP_FROM,
process.env.SMTP_SEND_TO,
`Nouveau commentaire de ${data.user.username}`,
data.kontni
)
}
}
}
};
-35
View File
@@ -1,35 +0,0 @@
{
"kind": "collectionType",
"collectionName": "komante",
"info": {
"name": "komante",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true,
"privateAttributes": [
"createdAt",
"updatedAt"
]
},
"attributes": {
"kontni": {
"type": "richtext",
"required": true
},
"user": {
"plugin": "users-permissions",
"model": "user"
},
"teks": {
"via": "komante",
"model": "teks"
},
"sentAt": {
"type": "datetime",
"required": true
}
}
}
-130
View File
@@ -1,130 +0,0 @@
'use strict';
const slugify = require('slugify')
const axios = require('axios')
const TELEGRAM_API_URL = 'https://api.telegram.org'
const TELEGRAM_CHAN_ID = process.env.TELEGRAM_CHAN_ID || null
const TELEGRAM_API_TOKEN = process.env.TELEGRAM_API_TOKEN || null
const MESSAGE_URL = `${TELEGRAM_API_URL}/bot${TELEGRAM_API_TOKEN}/sendMessage?chat_id=${TELEGRAM_CHAN_ID}&parse_mode=html`
const jwennAwtisEpiId = async data => {
const awtis = await strapi.query('awtis').find({id: data})
return awtis.map(a => a.alias).join('-')
}
const jwennUserEpiId = async userId => {
if (!userId) {
return null
}
const user = await strapi.query('user', 'users-permissions').findOne({id: userId})
return user
}
const jwennUserAdminEpiId = async userAdminId => {
if (!userAdminId) {
return null
}
const user = await strapi.query('user', 'admin').findOne({id: userAdminId, 'roles.code_nin': 'strapi-super-admin'})
return user
}
const translateTeks = async teksFR => {
const english = await strapi.services.translator.translate('FR', 'EN', teksFR)
const espagnol = await strapi.services.translator.translate('FR', 'ES', teksFR)
const deutsch = await strapi.services.translator.translate('FR', 'DE', teksFR)
const italiano = await strapi.services.translator.translate('FR', 'IT', teksFR)
return {
francais: teksFR,
english: english + '\n\n (Translated by DeepL)',
espagnol: espagnol + '\n\n (Traducido por DeepL)',
deutsch: deutsch + '\n\n (Übersetzt von DeepL)',
italiano: italiano + '\n\n (Tradotto da DeepL)'
}
}
module.exports = {
lifecycles: {
beforeCreate: async data => {
const user = await jwennUserEpiId(data?.user?.id)
const userAdmin = await jwennUserAdminEpiId(data?.created_by)
if (userAdmin) {
data.userAdmin = userAdmin.username
}
if (data.tit && !data.forceSlug) {
const awtis = await jwennAwtisEpiId(data.awtis)
data.slug = slugify(`${awtis}-${data.tit}`, {lower: true, remove: /[*#+~.()'"!:@]/g})
}
if (user && user.canAutoTranslate && data.tradiksyonOtomatik && data.tradiksyon.francais && (!data.tradiksyon.english || !data.tradiksyon.espagnol || !data.tradiksyon.deutsch || !data.tradiksyon.italiano)) {
const traslate = await translateTeks(data.tradiksyon.francais)
data.tradiksyon = traslate
}
},
beforeUpdate: async (params, data) => {
if (data.tit && !data.forceSlug) {
const awtis = await jwennAwtisEpiId(data.awtis)
data.slug = slugify(`${awtis}-${data.tit}`, {lower: true, remove: /[*#+~.()'"!:@]/g})
}
if (data.published_at != null) {
const {id} = params
const previousData = await strapi.query('teks').findOne({id})
const previousPublishedAt = previousData.published_at
const currentPublished_at = data.published_at
if (currentPublished_at != previousPublishedAt) {
const message = `<b>Nouvelle publication</b> \xF0\x9F\x8E\xB6 \xF0\x9F\x94\xA5
\n${process.env.WEBSITE_URL}/paroles/${previousData.slug}`
if (previousData.user) {
strapi.services.email.send(
process.env.SMTP_FROM,
previousData.user.email,
`Publication de "${previousData.tit}"`,
`Le titre que vous avez soumis, "${previousData.tit}" a été publié sur le site. Vous pouvez le trouver à l'adresse ${process.env.WEBSITE_URL}/paroles/${previousData.slug}`
)
}
const user = await jwennUserAdminEpiId(previousData?.created_by?.id)
if (user) {
strapi.services.email.send(
process.env.SMTP_FROM,
user.email,
`Publication de "${previousData.tit}"`,
`Le titre que vous avez soumis, "${previousData.tit}" a été publié sur le site. Vous pouvez le trouver à l'adresse ${process.env.WEBSITE_URL}/paroles/${previousData.slug}`
)
}
await axios.post(`${MESSAGE_URL}&text=${message}`)
}
}
},
afterCreate: async data => {
if (data.user) {
strapi.services.email.send(
process.env.SMTP_FROM,
process.env.SMTP_SEND_TO,
`Nouveau texte de ${data.user.username} : "${data.tit}" (site)`,
`Le titre "${data.tit}" a été soumis depuis le site.`
)
}
const user = await jwennUserAdminEpiId(data?.created_by?.id)
if (user) {
strapi.services.email.send(
process.env.SMTP_FROM,
process.env.SMTP_SEND_TO,
`Nouveau texte de ${user.username} : "${data.tit}" (dashboard)`,
`Le titre "${data.tit}" a été soumis depuis le dashboard.`
)
}
}
}
}
-82
View File
@@ -1,82 +0,0 @@
{
"kind": "collectionType",
"collectionName": "teks",
"info": {
"name": "Teks",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"attributes": {
"tit": {
"type": "string",
"required": true
},
"transkripsyon": {
"type": "richtext",
"required": true
},
"tradiksyon": {
"type": "component",
"repeatable": false,
"component": "trad.traductions"
},
"lanne": {
"type": "integer"
},
"lyen": {
"type": "component",
"repeatable": true,
"component": "url.liens"
},
"awtis": {
"via": "teks",
"collection": "awtis",
"dominant": true
},
"kouteyAchtey": {
"type": "component",
"repeatable": true,
"component": "store.store"
},
"slug": {
"type": "string"
},
"kouveti": {
"model": "file",
"via": "related",
"allowedTypes": [
"images"
],
"plugin": "upload",
"required": false,
"pluginOptions": {}
},
"okiMizikID": {
"type": "integer"
},
"user": {
"plugin": "users-permissions",
"model": "user"
},
"eksplisit": {
"type": "boolean"
},
"komante": {
"via": "teks",
"collection": "komante"
},
"forceSlug": {
"type": "boolean"
},
"tradiksyonOtomatik": {
"type": "boolean"
},
"userAdmin": {
"type": "string"
}
}
}
+17
View File
@@ -0,0 +1,17 @@
const forgotPasswordTemplate = require('./email-templates/forgot-password');
module.exports = ({ env }) => ({
url: env('STRAPI_ADMIN_URL', '/admin'),
apiToken: {
salt: env('API_TOKEN_SALT', 'd9b0df66ff97a666027e665707b4e3e7'),
},
auth: {
secret: env('ADMIN_JWT_SECRET', '77b2c87dbab4e1697bec244226fbd1b3'),
},
forgotPassword: {
from: env('SMTP_FROM'),
replyTo: env('SMTP_REPLY_TO'),
emailTemplate: forgotPasswordTemplate,
},
});
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
rest: {
defaultLimit: 25,
maxLimit: 100,
withCount: true,
},
};
+9
View File
@@ -0,0 +1,9 @@
module.exports = {
myJob: {
task: ({ strapi }) => {console.log('TODO > save db')},
options: {
rule: '0 0 * * SUN',
tz: 'Indian/Reunion',
},
},
};
+8 -12
View File
@@ -1,15 +1,11 @@
const path = require('path');
module.exports = ({ env }) => ({ module.exports = ({ env }) => ({
defaultConnection: 'default', connection: {
connections: { client: 'sqlite',
default: { connection: {
connector: 'bookshelf', filename: path.join(__dirname, '..', env('DATABASE_FILENAME', '.tmp/data.db')),
settings: {
client: 'sqlite',
filename: '.tmp/data.db',
},
options: {
useNullAsDefault: true,
},
}, },
useNullAsDefault: true,
}, },
}) });
+1 -1
View File
@@ -3,7 +3,7 @@ const subject = `Réinitialiser le mot de passe`;
const html = `<p>Bèl bonjou <%= user.firstname %></p> const html = `<p>Bèl bonjou <%= user.firstname %></p>
<p>Nous avons appris que tu a perdu ton mot de passe. Nous en sommes désolés ! </p> <p>Nous avons appris que tu a perdu ton mot de passe. Nous en sommes désolés ! </p>
<p>Mais ne tinquiéte pas ! Tu peux utiliser le lien suivant pour le réinitialiser :</p> <p>Mais ne tinquiéte pas ! Tu peux utiliser le lien suivant pour le réinitialiser :</p>
<p><%= url %></p>`; <p><a href="<%= url %>"><%= url %></a></p>`;
const text = `Bèl bonjou <%= user.firstname %> const text = `Bèl bonjou <%= user.firstname %>
Nous avons appris que tu a perdu ton mot de passe. Nous en sommes désolés ! Nous avons appris que tu a perdu ton mot de passe. Nous en sommes désolés !
-13
View File
@@ -1,13 +0,0 @@
'use strict';
/**
* An asynchronous bootstrap function that runs before
* your application gets started.
*
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*
* See more details here: https://strapi.io/documentation/v3.x/concepts/configurations.html#bootstrap
*/
module.exports = () => {};
-21
View File
@@ -1,21 +0,0 @@
'use strict';
/**
* Cron config that gives you an opportunity
* to run scheduled jobs.
*
* The cron format consists of:
* [SECOND (optional)] [MINUTE] [HOUR] [DAY OF MONTH] [MONTH OF YEAR] [DAY OF WEEK]
*
* See more details here: https://strapi.io/documentation/v3.x/concepts/configurations.html#cron-tasks
*/
module.exports = {
/**
* Simple example.
* Every monday at 1am.
*/
// '0 1 * * 1': () => {
//
// }
};
-5
View File
@@ -1,5 +0,0 @@
'use strict';
module.exports = async (/* ctx */) => {
// return ctx.notFound('My custom message 404');
};
+17 -10
View File
@@ -1,11 +1,18 @@
module.exports = ({env}) => ({
settings: { module.exports = ({ env }) => [
cache: { 'strapi::errors',
enabled: true, 'strapi::security',
models: ['awtis', 'teks'], {
type: 'mem', name: 'strapi::cors',
maxAge: 3600000, config: {
enableEtagSupport: true origin: ['http://localhost', env('WEBSITE_URL')],
} }
} },
}) 'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
+9 -7
View File
@@ -1,12 +1,14 @@
module.exports = ({env}) => ({ module.exports = ({env}) => ({
email: { email: {
provider: 'nodemailer', config: {
providerOptions: { provider: 'nodemailer',
host: env('SMTP_HOST', 'smtp.example.com'), providerOptions: {
port: env('SMTP_PORT', 587), host: env('SMTP_HOST', 'smtp.example.com'),
auth: { port: env('SMTP_PORT', 587),
user: env('SMTP_USERNAME'), auth: {
pass: env('SMTP_PASSWORD'), user: env('SMTP_USERNAME'),
pass: env('SMTP_PASSWORD'),
}
} }
}, },
settings: { settings: {
+7 -12
View File
@@ -1,18 +1,13 @@
const forgotPasswordTemplate = require('./email-templates/forgot-password'); const cronTasks = require("./cron-task");
module.exports = ({ env }) => ({ module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'), host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337), port: env.int('PORT', 1337),
url: env('STRAPI_URL', null), app: {
admin: { keys: env.array('APP_KEYS'),
url: env('STRAPI_ADMIN_URL', '/admin'),
auth: {
secret: env('ADMIN_JWT_SECRET', '71b106d7b2a4853774b0b27424b77097'),
},
forgotPassword: {
from: env('SMTP_FROM'),
replyTo: env('SMTP_REPLY_TO'),
emailTemplate: forgotPasswordTemplate,
},
}, },
cron: {
enabled: true,
tasks: cronTasks,
}
}); });
+7 -18
View File
@@ -11,24 +11,13 @@
}, },
"devDependencies": {}, "devDependencies": {},
"dependencies": { "dependencies": {
"knex": "0.21.19", "@strapi/plugin-documentation": "^4.1.11",
"nodemailer": "^6.6.1", "@strapi/plugin-i18n": "4.1.11",
"qs": "^6.10.3", "@strapi/plugin-users-permissions": "4.1.11",
"slugify": "^1.4.6", "@strapi/provider-email-nodemailer": "^4.1.11",
"sqlite3": "5.0.2", "@strapi/strapi": "4.1.11",
"strapi": "3.6.9", "better-sqlite3": "7.4.6",
"strapi-admin": "3.6.9", "slugify": "^1.6.5"
"strapi-connector-bookshelf": "3.6.9",
"strapi-connector-mongoose": "^3.6.9",
"strapi-middleware-cache": "^2.1.7",
"strapi-plugin-content-manager": "3.6.9",
"strapi-plugin-content-type-builder": "3.6.9",
"strapi-plugin-documentation": "3.6.9",
"strapi-plugin-email": "3.6.9",
"strapi-plugin-upload": "3.6.9",
"strapi-plugin-users-permissions": "3.6.9",
"strapi-provider-email-nodemailer": "3.6.9",
"strapi-utils": "3.6.9"
}, },
"author": { "author": {
"name": "Ced" "name": "Ced"
@@ -0,0 +1,69 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/v3.x/concepts/models.html#lifecycle-hooks)
* to customize this model
*/
const { ValidationError } = require("@strapi/utils").errors
const slugify = require('slugify')
const jwennTeksEpiId = async data => {
const paroles = await strapi.db.query('api::parole.parole').find({id_in: data})
return paroles
}
const jwennAwtisEpiId = async id => {
const artiste = await strapi.db.query('api::artiste.artiste').findOne({id})
return artiste
}
const validateArtiste = alias => {
if (!alias || alias.trim().length === 0) {
throw new ValidationError('Champ obligatoire. Veuillez choisir un alias.');
}
}
module.exports = {
beforeUpdate: async event => {
let {data} = event.params
if(!data.publishedAt) {
validateArtiste(data.alias)
if (!data.slug || data.slug !== slugify(data.alias, {lower: true, remove: /[*#+~.()'"!:@]/g})) {
data.slug = slugify(data.alias, {lower: true, remove: /[*#+~.()'"!:@]/g})
}
}
},
beforeCreate: async event => {
let {data} = event.params
validateArtiste(data.alias)
data.slug = slugify(data.alias, {lower: true, remove: /[*#+~.()'"!:@]/g})
},
afterUpdate: async event => {
let {data} = event.params
const {id} = data
const artiste = await jwennAwtisEpiId(id)
if (artiste.paroles && artiste.paroles.length >= 1) {
const paroles = await jwennTeksEpiId(artiste.paroles)
Promise.all(paroles.map(async t => {
const {id, titre, slug, artiste} = t
const alias = artiste.map(a => a.alias).join('-')
const slugUpdated = slugify(`${alias}-${titre}`, {lower: true, remove: /[*#+~.()'"!:@]/g})
if (slug !== slugUpdated) {
await strapi.db.query('api::parole.parole').update({
where: {id},
data: {
slug: slugUpdated
}
})
}
}))
}
}
}
@@ -0,0 +1,59 @@
{
"kind": "collectionType",
"collectionName": "artistes",
"info": {
"singularName": "artiste",
"pluralName": "artistes",
"displayName": "Artistes",
"description": ""
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"alias": {
"type": "string",
"required": true
},
"prenom": {
"type": "string"
},
"nom": {
"type": "string"
},
"biographie": {
"type": "richtext"
},
"dateNaissance": {
"type": "date"
},
"slug": {
"type": "string"
},
"paroles": {
"type": "relation",
"relation": "manyToMany",
"target": "api::parole.parole",
"inversedBy": "artistes"
},
"userAdmin": {
"type": "relation",
"relation": "oneToOne",
"target": "admin::user"
},
"user": {
"type": "relation",
"relation": "oneToOne",
"target": "plugin::users-permissions.user"
},
"photo": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images"
]
}
}
}
+56
View File
@@ -0,0 +1,56 @@
'use strict';
const { createCoreController } = require('@strapi/strapi').factories;
const { ValidationError } = require("@strapi/utils").errors
const slugify = require('slugify')
const getSlug = text => {
return slugify(text, {lower: true, remove: /[*#+~.()'"!:@]/g})
}
module.exports = createCoreController('api::artiste.artiste', ({strapi}) => ({
async create(ctx) {
const {body} = ctx.request
let {data} = body
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
try {
const {id} = await strapi.plugins[
'users-permissions'
].services.jwt.getToken(ctx)
if (id !== data.user.id) {
throw new UnauthorizedError('Opération non autorisée')
}
} catch (err) {
throw new UnauthorizedError(ctx, err, 'Opération non autorisée')
}
}
const user = await strapi.entityService.findOne('plugin::users-permissions.user', body.data.user.id)
if (!user) {
throw new NotFoundError('Utilisateur introuvable.')
}
if (user.id !== data.user.id || user.username !== data.user.username || user.email !== data.user.email) {
throw new ValidationError('Informations non valides.')
}
const artiste = await strapi.db.query('api::artiste.artiste').findOne({
where: {slug: getSlug(data.alias)}
})
if (artiste) {
return artiste
} else {
const newArtiste = await strapi.entityService.create('api::artiste.artiste', {
data: {
...data
}
})
return newArtiste
}
}
}))
@@ -0,0 +1,486 @@
{
"/artistes": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ArtisteListResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Artiste"
],
"parameters": [
{
"name": "sort",
"in": "query",
"description": "Sort by attributes ascending (asc) or descending (desc)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "pagination[withCount]",
"in": "query",
"description": "Retun page/pageSize (default: true)",
"deprecated": false,
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "pagination[page]",
"in": "query",
"description": "Page number (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[pageSize]",
"in": "query",
"description": "Page size (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[start]",
"in": "query",
"description": "Offset value (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[limit]",
"in": "query",
"description": "Number of entities to return (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "fields",
"in": "query",
"description": "Fields to return (ex: title,author)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "populate",
"in": "query",
"description": "Relations to return",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
}
],
"operationId": "get/artistes"
},
"post": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ArtisteResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Artiste"
],
"parameters": [],
"operationId": "post/artistes",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ArtisteRequest"
}
}
}
}
}
},
"/artistes/{id}": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ArtisteResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Artiste"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "get/artistes/{id}"
},
"put": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ArtisteResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Artiste"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "put/artistes/{id}",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ArtisteRequest"
}
}
}
}
},
"delete": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "integer",
"format": "int64"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Artiste"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "delete/artistes/{id}"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
'use strict';
const { createCoreRouter } = require('@strapi/strapi').factories;
module.exports = createCoreRouter('api::artiste.artiste')
+5
View File
@@ -0,0 +1,5 @@
'use strict';
const { createCoreService } = require('@strapi/strapi').factories;
module.exports = createCoreService('api::artiste.artiste');
@@ -0,0 +1,66 @@
'use strict';
const { ValidationError, NotFoundError } = require("@strapi/utils").errors
const jwennUserEpiId = async userId => {
if (!userId) {
return null
}
const user = await strapi.db.query('plugin::users-permissions.user').findOne({
where: {id: userId}
})
return user
}
const jwennParoleEpiId = async paroleId => {
if (!paroleId) {
return null
}
const parole = await strapi.db.query('api::parole.parole').findOne({
where: {id: paroleId}
})
return parole
}
const validateCommentaire = data => {
if (!data.contenu && !data.datePublication) {
throw new ValidationError('Mauvaise requête, contenu et datePublication sont obligatoires')
}
if (!data.contenu || data.contenu.trim().length === 0) {
throw new ValidationError('Champ obligatoire. Veuillez renseigner le contenu du commentaire.')
}
if (data.contenu.trim().length > 500) {
throw new ValidationError('Le commentaire doit contenir 500 caractères maximum.')
}
}
module.exports = {
beforeCreate: async event => {
const {data} = event.params
validateCommentaire(data)
},
afterCreate: async event => {
const {data, result} = event.params
const user = await jwennUserEpiId(data.user)
const parole = await jwennParoleEpiId(data.parole)
if (!parole) {
throw new NotFoundError('Texte introuvable.')
}
if (user) {
strapi.plugins['email'].services.email.send({
from: process.env.SMTP_FROM,
to: process.env.SMTP_SEND_TO,
subject: `Commentaire de ${user.username} sur "${parole.titre}"`,
html: data.contenu
})
}
}
};
@@ -0,0 +1,34 @@
{
"kind": "collectionType",
"collectionName": "commentaires",
"info": {
"singularName": "commentaire",
"pluralName": "commentaires",
"displayName": "Commentaires",
"description": ""
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"contenu": {
"type": "richtext",
"required": true
},
"datePublication": {
"type": "datetime",
"required": true
},
"user": {
"type": "relation",
"relation": "oneToOne",
"target": "plugin::users-permissions.user"
},
"parole": {
"type": "relation",
"relation": "oneToOne",
"target": "api::parole.parole"
}
}
}
@@ -0,0 +1,58 @@
'use strict';
const { createCoreController } = require('@strapi/strapi').factories;
const { ValidationError, NotFoundError, UnauthorizedError } = require("@strapi/utils").errors
module.exports = createCoreController('api::commentaire.commentaire', ({strapi}) => ({
async create(ctx) {
const {body} = ctx.request
let {data} = body
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
try {
const {id} = await strapi.plugins[
'users-permissions'
].services.jwt.getToken(ctx)
if (id !== data.user.id) {
throw new UnauthorizedError('Opération non autorisée')
}
} catch (err) {
throw new UnauthorizedError(ctx, err, 'Opération non autorisée')
}
}
const user = await strapi.entityService.findOne('plugin::users-permissions.user', body.data.user.id)
if (!user) {
throw new NotFoundError('Utilisateur introuvable.')
}
if (user.id !== data.user.id || user.username !== data.user.username || user.email !== data.user.email) {
throw new ValidationError('Informations non valides.')
}
data.user = user.id
const parole = await strapi.entityService.findOne('api::parole.parole', data.parole, {
fields: ['id']
})
if (!parole) {
throw new NotFoundError('Texte introuvable.')
}
const newCommentaire = await strapi.entityService.create('api::commentaire.commentaire', {
data: {
...data
}
})
await strapi.entityService.update('api::parole.parole', parole.id, {
data: {
commentaires: [newCommentaire.id]
}
})
return newCommentaire;
}
}))
@@ -0,0 +1,486 @@
{
"/commentaires": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CommentaireListResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Commentaire"
],
"parameters": [
{
"name": "sort",
"in": "query",
"description": "Sort by attributes ascending (asc) or descending (desc)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "pagination[withCount]",
"in": "query",
"description": "Retun page/pageSize (default: true)",
"deprecated": false,
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "pagination[page]",
"in": "query",
"description": "Page number (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[pageSize]",
"in": "query",
"description": "Page size (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[start]",
"in": "query",
"description": "Offset value (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[limit]",
"in": "query",
"description": "Number of entities to return (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "fields",
"in": "query",
"description": "Fields to return (ex: title,author)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "populate",
"in": "query",
"description": "Relations to return",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
}
],
"operationId": "get/commentaires"
},
"post": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CommentaireResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Commentaire"
],
"parameters": [],
"operationId": "post/commentaires",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CommentaireRequest"
}
}
}
}
}
},
"/commentaires/{id}": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CommentaireResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Commentaire"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "get/commentaires/{id}"
},
"put": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CommentaireResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Commentaire"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "put/commentaires/{id}",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CommentaireRequest"
}
}
}
}
},
"delete": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "integer",
"format": "int64"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Commentaire"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "delete/commentaires/{id}"
}
}
}
@@ -0,0 +1,5 @@
'use strict';
const { createCoreRouter } = require('@strapi/strapi').factories;
module.exports = createCoreRouter('api::commentaire.commentaire')
@@ -0,0 +1,5 @@
'use strict';
const { createCoreService } = require('@strapi/strapi').factories;
module.exports = createCoreService('api::commentaire.commentaire');
@@ -0,0 +1,194 @@
'use strict';
const slugify = require('slugify')
const axios = require('axios')
const { ValidationError } = require("@strapi/utils").errors
const TELEGRAM_API_URL = 'https://api.telegram.org'
const TELEGRAM_CHAN_ID = process.env.TELEGRAM_CHAN_ID || null
const TELEGRAM_API_TOKEN = process.env.TELEGRAM_API_TOKEN || null
const MESSAGE_URL = `${TELEGRAM_API_URL}/bot${TELEGRAM_API_TOKEN}/sendMessage?chat_id=${TELEGRAM_CHAN_ID}&parse_mode=html`
const getSlug = (artiste, parole) => {
return slugify(`${artiste}-${parole}`, {lower: true, remove: /[*#+~.()'"!:@]/g})
}
const isSlugExists = async existingSlug => {
const slugs = await strapi.db.query('api::parole.parole').count({
where: {
slug: {
$eq: existingSlug
}
}
})
return Boolean(slugs)
}
const jwennAwtisEpiId = async id => {
if (!id) {
throw new ValidationError('Champ obligatoire. Veuillez choisir au moins un artiste.');
}
const artiste = await strapi.db.query('api::artiste.artiste').findMany({
select: ['alias'],
where: {
id: {
$in: id
}
}
})
return artiste.map(a => a.alias).join('-')
}
const jwennUserEpiId = async userId => {
if (!userId) {
return null
}
const user = await strapi.db.query('plugin::users-permissions.user').findOne({id: userId})
return user
}
const jwennUserAdminEpiId = async userAdminId => {
if (!userAdminId) {
return null
}
const userAdmin = await strapi.db.query('admin::user').findOne({
where: {
$and: [
{
id: userAdminId
},
{
$not: {
roles: {
code: 'strapi-super-admin'
}
}
}
]
}
})
return userAdmin
}
const validateParoles = (titre, transcription) => {
if (!titre || titre.trim().length === 0) {
throw new ValidationError('Champ obligatoire. Veuillez choisir un titre.');
}
if (!transcription || transcription.trim().length === 0) {
throw new ValidationError('Champ obligatoire. Veuillez renseigner la transcription.')
}
if (transcription.trim().length < 10) {
throw new ValidationError('La transcription doit contenir au moins 10 caractères.')
}
}
module.exports = {
beforeCreate: async event => {
let {data} = event.params
validateParoles(data.titre, data.transcription)
const userAdmin = await jwennUserAdminEpiId(data?.createdBy)
if (userAdmin) {
data.userAdmin = userAdmin
}
if (data.titre && !data.forceSlug) {
const artiste = await jwennAwtisEpiId(data.artistes)
data.slug = getSlug(artiste, data.titre)
}
const getSlugExistance = await isSlugExists(data.slug)
if (getSlugExistance) {
throw new ValidationError('Un morceau du même artiste existe déjà.')
}
},
beforeUpdate: async event => {
let {data} = event.params
const {where} = event.params
if(!data.publishedAt && data.titre && data.transcription) {
validateParoles(data.titre, data.transcription)
if (data.titre && !data.forceSlug) {
const artiste = await jwennAwtisEpiId(data.artistes)
data.slug = getSlug(artiste, data.titre)
}
}
if (data.publishedAt != null) {
const {id} = where
const previousData = await strapi.db.query('api::parole.parole').findOne({
where: {id},
populate: {userAdmin: true, user: true}
})
const previousPublishedAt = previousData.publishedAt
const currentPublished_at = data.publishedAt
if (currentPublished_at != previousPublishedAt) {
const message = `<b>Nouvelle publication</b> \xF0\x9F\x8E\xB6 \xF0\x9F\x94\xA5
\n${process.env.WEBSITE_URL}/paroles/${previousData.slug}`
if (previousData.user) {
strapi.plugins['email'].services.email.send({
from: process.env.SMTP_FROM,
to: previousData.user.email,
subject: `Publication de "${previousData.titre}" sur oki.re`,
text: `Le titre que vous avez soumis, "${previousData.titre}" a été publié sur le site.
Vous pouvez le trouver à l'adresse ${process.env.WEBSITE_URL}/paroles/${previousData.slug}
Merci pour votre contribution ❤️`,
html: `<p>Le titre que vous avez soumis, <strong>"${previousData.titre}"</strong> a été publié sur le site.</p>
<p>Vous pouvez le trouver à l'adresse <a href="${process.env.WEBSITE_URL}/paroles/${previousData.slug}">${process.env.WEBSITE_URL}/paroles/${previousData.slug}</a>.</p><p>Merci pour votre contribution ❤️</p>`
})
}
if (previousData.userAdmin) {
strapi.plugins['email'].services.email.send({
from: process.env.SMTP_FROM,
to: previousData.userAdmin.email,
subject: `Publication de "${previousData.titre}" sur oki.re`,
text: `Le titre que vous avez soumis, "${previousData.titre}" a été publié sur le site.
Vous pouvez le trouver à l'adresse ${process.env.WEBSITE_URL}/paroles/${previousData.slug}.
Merci pour votre contribution ❤️`,
html: `<p>Le titre que vous avez soumis, <strong>"${previousData.titre}"</strong> a été publié sur le site.</p>
<p>Vous pouvez le trouver à l'adresse <a href="${process.env.WEBSITE_URL}/paroles/${previousData.slug}">${process.env.WEBSITE_URL}/paroles/${previousData.slug}</a>.</p><p>Merci pour votre contribution ❤️</p>`
})
}
await axios.post(`${MESSAGE_URL}&text=${message}`)
}
}
},
afterCreate: async event => {
const {data} = event.params
const user = await jwennUserEpiId(data.user)
const userAdmin = await jwennUserAdminEpiId(data?.createdBy)
if (user) {
strapi.plugins['email'].services.email.send({
from: process.env.SMTP_FROM,
to: process.env.SMTP_SEND_TO,
subject: `Nouveau texte de ${user.username} : "${data.titre}" (site)`,
text: `Le titre "${data.titre}" a été soumis depuis le site.`,
html: `Le titre <strong>"${data.titre}"</strong> a été soumis depuis le site.`
})
}
if (userAdmin) {
strapi.plugins['email'].services.email.send({
from: process.env.SMTP_FROM,
to: process.env.SMTP_SEND_TO,
subject: `Nouveau texte de ${userAdmin.firstname} : "${data.titre}" (site)`,
text: `Le titre "${data.titre}" a été soumis depuis le site.`,
html: `Le titre <strong>"${data.titre}"</strong> a été soumis depuis le site.`
})
}
}
}
@@ -0,0 +1,87 @@
{
"kind": "collectionType",
"collectionName": "paroles",
"info": {
"singularName": "parole",
"pluralName": "paroles",
"displayName": "Paroles",
"description": ""
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"titre": {
"type": "string",
"required": true
},
"transcription": {
"type": "richtext",
"required": true
},
"annee": {
"type": "integer"
},
"slug": {
"type": "string",
"unique": true
},
"okiMizikID": {
"type": "integer"
},
"explicitLyrics": {
"type": "boolean"
},
"forceSlug": {
"type": "boolean"
},
"traductionAuto": {
"type": "boolean"
},
"artistes": {
"type": "relation",
"relation": "manyToMany",
"target": "api::artiste.artiste",
"mappedBy": "paroles"
},
"userAdmin": {
"type": "relation",
"relation": "oneToOne",
"target": "admin::user"
},
"user": {
"type": "relation",
"relation": "oneToOne",
"target": "plugin::users-permissions.user"
},
"couverture": {
"type": "media",
"multiple": false,
"required": false,
"allowedTypes": [
"images"
]
},
"traductions": {
"type": "component",
"repeatable": false,
"component": "trad.traductions"
},
"streamVideo": {
"type": "component",
"repeatable": true,
"component": "url.liens"
},
"streamAudio": {
"type": "component",
"repeatable": true,
"component": "store.album"
},
"commentaires": {
"type": "relation",
"relation": "oneToMany",
"target": "api::commentaire.commentaire"
}
}
}
+112
View File
@@ -0,0 +1,112 @@
'use strict';
const { createCoreController } = require('@strapi/strapi').factories;
module.exports = createCoreController('api::parole.parole', ({strapi}) => ({
async findOne(ctx) {
const {id} = ctx.params
const parole = await strapi.entityService.findOne('api::parole.parole', id, {
populate: ['artistes']
})
return parole
},
async update(ctx) {
const {body} = ctx.request
const {data} = body
const updatedParole = await strapi.entityService.update('api::parole.parole', data.id, {
data: {
...data
}
})
return updatedParole
},
async create(ctx) {
const translateLyrics = async parolesFR => {
const anglais = await strapi.service('api::parole.parole').translate('FR', 'EN', parolesFR)
const espagnol = await strapi.service('api::parole.parole').translate('FR', 'ES', parolesFR)
const allemand = await strapi.service('api::parole.parole').translate('FR', 'DE', parolesFR)
const italien = await strapi.service('api::parole.parole').translate('FR', 'IT', parolesFR)
return {
francais: parolesFR,
anglais: anglais + '\n\n (Translated by DeepL)',
espagnol: espagnol + '\n\n (Traducido por DeepL)',
allemand: allemand + '\n\n (Übersetzt von DeepL)',
italien: italien + '\n\n (Tradotto da DeepL)'
}
}
const {body} = ctx.request
const {data} = body
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
try {
const {id} = await strapi.plugins[
'users-permissions'
].services.jwt.getToken(ctx)
if (id !== data.user.id) {
throw new UnauthorizedError('Opération non autorisée')
}
} catch (err) {
throw new UnauthorizedError(ctx, err, 'Opération non autorisée')
}
}
const user = await strapi.entityService.findOne('plugin::users-permissions.user', body.data.user.id)
if (!user) {
throw new NotFoundError('Utilisateur introuvable.')
}
if (user.id !== data.user.id || user.username !== data.user.username || user.email !== data.user.email) {
throw new ValidationError('Informations non valides.')
}
const artiste = await strapi.entityService.findOne('api::artiste.artiste', data.artistes[0])
if (!artiste) {
throw new NotFoundError('Artiste introuvable.')
}
const currentUserParole = await strapi.entityService.findMany('api::parole.parole', {
fields: ['id'],
filters: {
user: {
id: {
$eq: user.id
}
},
publishedAt: {
$eq: null
}
}
})
if (user && user.canAutoTranslate && data.traductionAuto && data.traductions.francais && (!data.traductions.anglais || !data.traductions.espagnol || !data.traductions.allemand || !data.traductions.italien)) {
const translated = await translateLyrics(data.traductions.francais)
data.traductions = translated
}
console.log('data createCoreController', data)
const newParole = await strapi.entityService.create('api::parole.parole', {
data: {
...data
}
})
const parolesIds = currentUserParole.map(({id}) => id)
parolesIds.push(newParole.id)
await strapi.entityService.update('plugin::users-permissions.user', user.id, {
data: {
paroles: parolesIds
}
})
return newParole
}
}))
@@ -0,0 +1,486 @@
{
"/paroles": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ParoleListResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Parole"
],
"parameters": [
{
"name": "sort",
"in": "query",
"description": "Sort by attributes ascending (asc) or descending (desc)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "pagination[withCount]",
"in": "query",
"description": "Retun page/pageSize (default: true)",
"deprecated": false,
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "pagination[page]",
"in": "query",
"description": "Page number (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[pageSize]",
"in": "query",
"description": "Page size (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[start]",
"in": "query",
"description": "Offset value (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[limit]",
"in": "query",
"description": "Number of entities to return (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "fields",
"in": "query",
"description": "Fields to return (ex: title,author)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "populate",
"in": "query",
"description": "Relations to return",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
}
],
"operationId": "get/paroles"
},
"post": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ParoleResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Parole"
],
"parameters": [],
"operationId": "post/paroles",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ParoleRequest"
}
}
}
}
}
},
"/paroles/{id}": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ParoleResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Parole"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "get/paroles/{id}"
},
"put": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ParoleResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Parole"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "put/paroles/{id}",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ParoleRequest"
}
}
}
}
},
"delete": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "integer",
"format": "int64"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Parole"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "delete/paroles/{id}"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
'use strict';
const { createCoreRouter } = require('@strapi/strapi').factories;
module.exports = createCoreRouter('api::parole.parole')
+41
View File
@@ -0,0 +1,41 @@
'use strict';
const qs = require('qs')
const axios = require('axios')
const { createCoreService } = require('@strapi/strapi').factories;
class Translator {
constructor() {
this.deeplApi = process.env.DEEPL_URL || 'api-free.deepl.com'
this.deeplKey = process.env.DEEPL_KEY
this.urlRequest = `https://${this.deeplApi}/v2/translate`
}
async get(origin, target, text) {
try {
const data = {
auth_key: this.deeplKey,
source_lang: origin,
target_lang: target,
text
}
const result = await axios.post(this.urlRequest, qs.stringify(data), {
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
})
return result.data
} catch (error) {
console.log('error', error)
}
}
}
module.exports = createCoreService('api::parole.parole', ({strapi}) => ({
async translate(origin, target, text) {
const translator = new Translator()
const data = await translator.get(origin, target, text)
return data.translations[0].text
}
}));
+27
View File
@@ -0,0 +1,27 @@
{
"collectionName": "components_store_albums",
"info": {
"displayName": "Album",
"icon": "music",
"description": ""
},
"options": {},
"attributes": {
"url": {
"type": "string"
},
"plateforme": {
"type": "enumeration",
"enum": [
"Tidal",
"Spotify",
"Deezer",
"Qobuz",
"Youtubemusic",
"Applemusic",
"Amazon",
"Soundcloud"
]
}
}
}
+26
View File
@@ -0,0 +1,26 @@
{
"collectionName": "components_trad_traductions",
"info": {
"displayName": "Traductions",
"icon": "spell-check",
"description": ""
},
"options": {},
"attributes": {
"francais": {
"type": "richtext"
},
"anglais": {
"type": "richtext"
},
"espagnol": {
"type": "richtext"
},
"allemand": {
"type": "richtext"
},
"italien": {
"type": "richtext"
}
}
}
+26
View File
@@ -0,0 +1,26 @@
{
"collectionName": "components_url_liens",
"info": {
"displayName": "Vidéo",
"icon": "hand-pointer",
"description": ""
},
"options": {},
"attributes": {
"url": {
"type": "string"
},
"plateforme": {
"type": "enumeration",
"enum": [
"Youtube",
"Gadé",
"Dailymotion",
"Vimeo",
"File",
"Lbry",
"Rumble"
]
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,136 @@
<!DOCTYPE html><html><head>
<title>Login - Documentation</title>
<link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet">
<style>
html {
font-size: 62.5%;
height: 100%;
margin: 0;
padding: 0;
}
body {
height: 100%;
margin: 0;
background-color: #ffffff;
font-family: 'Lato';
font-size: 1.4rem;
font-weight: 400;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.login {
height: 100%;
background-color: #F6F9FC;
}
.login .login-form {
height: calc(100% - 70px);
padding: 68px 0 0;
text-align: center;
}
.login .login-form form {
position: relative;
max-width: 460px;
padding: 26px 30px;
margin: 55px auto 0;
background-color: #ffffff;
border-radius: 3px;
box-shadow: 0px 2px 4px rgba(91, 107, 174, .15);
text-align: center;
}
.login .login-form form:before {
position: absolute;
content: '';
top: 0px;
left: 0;
display: inline-block;
width: 100%;
height: 2px;
background-color: #2B66CC;
}
.login .login-form form .error {
display: block;
color: #FF4E00;
padding-bottom: 20px;
}
.login .login-form .sub-title {
margin-top: 35px;
font-size: 1.6rem;
font-weight: 400;
}
.login .login-form .logo{
max-height: 40px;
}
.login .login-form form label {
display: block;
margin-bottom: 18px;
width: 100%;
text-align: left;
font-weight: 600;
}
.login .login-form form input {
outline: none;
width: calc(100% - 30px);
height: 36px;
padding: 0 15px;
border: 1px solid #ECECEC;
border-radius: 2px;
margin-bottom: 20px;
line-height: 36px;
text-align: left;
}
.login .login-form form input[type=submit] {
cursor: pointer;
display: inline-block;
width: auto;
margin: 12px auto 0;
padding: 0 75px;
background: transparent;
border-radius: 36px;
border: 1px solid #2B66CC;
color: #2B66CC;
text-transform: uppercase;
font-size: 1.4rem;
font-weight: 700;
transition: all .2s ease-out;
}
.login .login-form form input[type=submit]:hover {
background: #2B66CC;
color: #ffffff;
}
</style>
</head>
<body>
<div class="login">
<section class="login-form">
<div class="container">
<div class="row">
<div class="col-lg-6 col-lg-offset-3 col-md-12">
<img alt="Strapi logo" class="logo" src="https://strapi.io/assets/images/logo_login.png">
<h2 class="sub-title">Enter the password to access the documentation.</h2>
<form method="post" action="/documentation/login">
<span class="error"></span>
<label>Password</label>
<input type="password" name="password" placeholder="•••••••••">
<input type="submit" value="Login">
</form>
</div>
</div>
</div>
</section>
</div>
</body></html>
@@ -0,0 +1 @@
{}
@@ -0,0 +1,388 @@
{
"/upload/files/count": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadFileResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Upload - File"
],
"parameters": [],
"operationId": "get/upload/files/count"
}
},
"/upload/files": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadFileListResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Upload - File"
],
"parameters": [
{
"name": "sort",
"in": "query",
"description": "Sort by attributes ascending (asc) or descending (desc)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "pagination[withCount]",
"in": "query",
"description": "Retun page/pageSize (default: true)",
"deprecated": false,
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "pagination[page]",
"in": "query",
"description": "Page number (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[pageSize]",
"in": "query",
"description": "Page size (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[start]",
"in": "query",
"description": "Offset value (default: 0)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "pagination[limit]",
"in": "query",
"description": "Number of entities to return (default: 25)",
"deprecated": false,
"required": false,
"schema": {
"type": "integer"
}
},
{
"name": "fields",
"in": "query",
"description": "Fields to return (ex: title,author)",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "populate",
"in": "query",
"description": "Relations to return",
"deprecated": false,
"required": false,
"schema": {
"type": "string"
}
}
],
"operationId": "get/upload/files"
}
},
"/upload/files/{id}": {
"get": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadFileResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Upload - File"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "get/upload/files/{id}"
},
"delete": {
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "integer",
"format": "int64"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
},
"tags": [
"Upload - File"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "",
"deprecated": false,
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "delete/upload/files/{id}"
}
}
}
@@ -0,0 +1,75 @@
{
"kind": "collectionType",
"collectionName": "up_users",
"info": {
"name": "user",
"description": "",
"singularName": "user",
"pluralName": "users",
"displayName": "User"
},
"options": {
"draftAndPublish": false,
"timestamps": true
},
"attributes": {
"username": {
"type": "string",
"minLength": 3,
"unique": true,
"configurable": false,
"required": true
},
"email": {
"type": "email",
"minLength": 6,
"configurable": false,
"required": true
},
"provider": {
"type": "string",
"configurable": false
},
"password": {
"type": "password",
"minLength": 6,
"configurable": false,
"private": true
},
"resetPasswordToken": {
"type": "string",
"configurable": false,
"private": true
},
"confirmationToken": {
"type": "string",
"configurable": false,
"private": true
},
"confirmed": {
"type": "boolean",
"default": false,
"configurable": false
},
"blocked": {
"type": "boolean",
"default": false,
"configurable": false
},
"role": {
"type": "relation",
"relation": "manyToOne",
"target": "plugin::users-permissions.role",
"inversedBy": "users",
"configurable": false
},
"canAutoTranslate": {
"type": "boolean"
},
"paroles": {
"type": "relation",
"relation": "oneToMany",
"target": "api::parole.parole"
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
module.exports = plugin => {
const sanitizeOutput = (user) => {
const {password, resetPasswordToken, confirmationToken, ...sanitizedUser} = user
return sanitizedUser;
};
plugin.controllers.user.me = async (ctx) => {
if (!ctx.state.user) {
return ctx.unauthorized();
}
const user = await strapi.entityService.findOne('plugin::users-permissions.user', ctx.state.user.id, {populate: {
paroles: {
filters: {
publishedAt: {
$eq: null
}
},
populate: {
artistes: true,
traductions: true
}
}
}})
ctx.body = sanitizeOutput(user)
}
return plugin
}
+4194 -4843
View File
File diff suppressed because it is too large Load Diff