Merge branch 'feature/lost-password' into develop

feature/blog
Näser 3 years ago
commit 0e8121bc25

@ -1,16 +0,0 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{package.json,*.yml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

@ -1,28 +0,0 @@
HOST=0.0.0.0
PORT=1337
APP_KEYS=chUnDYzQYwe0TBtXVv4sPg==,fVrGPGw5Xd4UdPisWHOHxQ==,Qre2n8wneae2BrXOotmagw==,B3suExWQFpyJS9mhqNcOLg==
API_TOKEN_SALT=tyYia7Nui8Y0lM0IRTDjmg==
ADMIN_JWT_SECRET=q1dnfyvh3K7yhTYbYNS7jw==
JWT_SECRET=nc8prafomnDTfDdS00OqTQ==
PG_DATABASE_HOST=localhost
PG_DATABASE_PORT=5432
PG_DATABASE_NAME=gs_database
PG_DATABASE_USERNAME=gs_username
PG_DATABASE_ROOT_PASSWORD=gs_root_username
PG_DATABASE_PASSWORD=gs_password
PG_DATABASE_SCHEMA=public
MYSQL_DATABASE_HOST=localhost
MYSQL_DATABASE_PORT=3307
MYSQL_DATABASE_NAME=gs_database
MYSQL_DATABASE_USERNAME=gs_username
MYSQL_DATABASE_ROOT_PASSWORD=gs_root_username
MYSQL_DATABASE_PASSWORD=gs_password
SMTP_HOST=mail.infomaniak.com
SMTP_PORT=587
SMTP_USERNAME=synology@naser.fr
SMTP_PASSWORD=Em18071988!
SMTP_DEFAULT_FROM=no-reply@strapi.io
SMTP_DEFAULT_REPLY=synology@naser.fr

@ -1,28 +0,0 @@
HOST=0.0.0.0
PORT=1337
APP_KEYS=chUnDYzQYwe0TBtXVv4sPg==,fVrGPGw5Xd4UdPisWHOHxQ==,Qre2n8wneae2BrXOotmagw==,B3suExWQFpyJS9mhqNcOLg==
API_TOKEN_SALT=tyYia7Nui8Y0lM0IRTDjmg==
ADMIN_JWT_SECRET=q1dnfyvh3K7yhTYbYNS7jw==
JWT_SECRET=nc8prafomnDTfDdS00OqTQ==
PG_DATABASE_HOST=localhost
PG_DATABASE_PORT=5432
PG_DATABASE_NAME=gs_database
PG_DATABASE_USERNAME=gs_username
PG_DATABASE_ROOT_PASSWORD=gs_root_username
PG_DATABASE_PASSWORD=gs_password
PG_DATABASE_SCHEMA=public
MYSQL_DATABASE_HOST=localhost
MYSQL_DATABASE_PORT=3306
MYSQL_DATABASE_NAME=dpxtrufj_gs_database
MYSQL_DATABASE_USERNAME=dpxtrufj_gs_username
MYSQL_DATABASE_ROOT_PASSWORD=gs_root_username
MYSQL_DATABASE_PASSWORD=q7=@oa*F*s4?8*Hq4H
SMTP_HOST=node143-eu.n0c.com
SMTP_PORT=587
SMTP_USERNAME=no-reply@nasercloud.fr
SMTP_PASSWORD=GuitarSchool123!
SMTP_DEFAULT_FROM=no-reply@strapi.io
SMTP_DEFAULT_REPLY=synology@naser.fr

@ -1,28 +0,0 @@
HOST=0.0.0.0
PORT=1337
APP_KEYS=chUnDYzQYwe0TBtXVv4sPg==,fVrGPGw5Xd4UdPisWHOHxQ==,Qre2n8wneae2BrXOotmagw==,B3suExWQFpyJS9mhqNcOLg==
API_TOKEN_SALT=tyYia7Nui8Y0lM0IRTDjmg==
ADMIN_JWT_SECRET=q1dnfyvh3K7yhTYbYNS7jw==
JWT_SECRET=nc8prafomnDTfDdS00OqTQ==
PG_DATABASE_HOST=localhost
PG_DATABASE_PORT=5432
PG_DATABASE_NAME=gs_database
PG_DATABASE_USERNAME=gs_username
PG_DATABASE_ROOT_PASSWORD=gs_root_username
PG_DATABASE_PASSWORD=gs_password
PG_DATABASE_SCHEMA=public
MYSQL_DATABASE_HOST=localhost
MYSQL_DATABASE_PORT=3306
MYSQL_DATABASE_NAME=dpxtrufj_gs_database
MYSQL_DATABASE_USERNAME=dpxtrufj_gs_user
MYSQL_DATABASE_ROOT_PASSWORD=gs_root_username
MYSQL_DATABASE_PASSWORD=q7=@oa*F*s4?8*Hq4H
SMTP_HOST=node143-eu.n0c.com
SMTP_PORT=587
SMTP_USERNAME=no-reply@nasercloud.fr
SMTP_PASSWORD=GuitarSchool123!
SMTP_DEFAULT_FROM=no-reply@nasercloud.fr
SMTP_DEFAULT_REPLY=contact@nasercloud.fr

@ -1,115 +0,0 @@
############################
# OS X
############################
.DS_Store
.AppleDouble
.LSOverride
Icon
.Spotlight-V100
.Trashes
._*
############################
# Linux
############################
*~
############################
# Windows
############################
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp
############################
# Packages
############################
*.7z
*.csv
*.dat
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.com
*.class
*.dll
*.exe
*.o
*.seed
*.so
*.swo
*.swp
*.swn
*.swm
*.out
*.pid
############################
# Logs and databases
############################
.tmp
*.log
*.sql
*.sqlite
*.sqlite3
############################
# Misc.
############################
*#
ssl
.idea
nbproject
public/uploads/*
!public/uploads/.gitkeep
############################
# Node.js
############################
lib-cov
lcov.info
pids
logs
results
node_modules
.node_history
############################
# Tests
############################
testApp
coverage
############################
# Strapi
############################
.env
license.txt
exports
*.cache
dist
build
.strapi-updater.json

@ -1,57 +0,0 @@
# 🚀 Getting started with Strapi
Strapi comes with a full featured [Command Line Interface](https://docs.strapi.io/developer-docs/latest/developer-resources/cli/CLI.html) (CLI) which lets you scaffold and manage your project in seconds.
### `develop`
Start your Strapi application with autoReload enabled. [Learn more](https://docs.strapi.io/developer-docs/latest/developer-resources/cli/CLI.html#strapi-develop)
```
npm run develop
# or
yarn develop
```
### `start`
Start your Strapi application with autoReload disabled. [Learn more](https://docs.strapi.io/developer-docs/latest/developer-resources/cli/CLI.html#strapi-start)
```
npm run start
# or
yarn start
```
### `build`
Build your admin panel. [Learn more](https://docs.strapi.io/developer-docs/latest/developer-resources/cli/CLI.html#strapi-build)
```
npm run build
# or
yarn build
```
## ⚙️ Deployment
Strapi gives you many possible deployment options for your project. Find the one that suits you on the [deployment section of the documentation](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment.html).
## 📚 Learn more
- [Resource center](https://strapi.io/resource-center) - Strapi resource center.
- [Strapi documentation](https://docs.strapi.io) - Official Strapi documentation.
- [Strapi tutorials](https://strapi.io/tutorials) - List of tutorials made by the core team and the community.
- [Strapi blog](https://docs.strapi.io) - Official Strapi blog containing articles made by the Strapi team and the community.
- [Changelog](https://strapi.io/changelog) - Find out about the Strapi product updates, new features and general improvements.
Feel free to check out the [Strapi GitHub repository](https://github.com/strapi/strapi). Your feedback and contributions are welcome!
## ✨ Community
- [Discord](https://discord.strapi.io) - Come chat with the Strapi community including the core team.
- [Forum](https://forum.strapi.io/) - Place to discuss, ask questions and find answers, show your Strapi project and get feedback or just talk with other Community members.
- [Awesome Strapi](https://github.com/strapi/awesome-strapi) - A curated list of awesome things related to Strapi.
---
<sub>🤫 Psst! [Strapi is hiring](https://strapi.io/careers).</sub>

@ -1,8 +0,0 @@
export default ({ env }) => ({
auth: {
secret: env('ADMIN_JWT_SECRET'),
},
apiToken: {
salt: env('API_TOKEN_SALT'),
},
});

@ -1,10 +0,0 @@
export default {
responses: {
privateAttributes: ['_v', 'id', 'created_at'],
},
rest: {
defaultLimit: 100,
maxLimit: 250,
withCount: true,
},
};

@ -1,20 +0,0 @@
export default ({env}) => ({
connection: {
client: 'mysql',
connection: {
host: env('MYSQL_DATABASE_HOST', 'localhost'),
port: env.int('MYSQL_DATABASE_PORT', 3306),
database: env('MYSQL_DATABASE_NAME', 'bank'),
user: env('MYSQL_DATABASE_USERNAME', 'postgres'),
password: env('MYSQL_DATABASE_PASSWORD', '0000'),
},
debug: false,
},
// connection: {
// client: 'sqlite',
// connection: {
// filename: path.join(__dirname, '..', '..', env('DATABASE_FILENAME', '.tmp/data.db')),
// },
// useNullAsDefault: true,
// },
});

@ -1,12 +0,0 @@
export default [
'strapi::errors',
'strapi::security',
'strapi::cors',
'strapi::poweredBy',
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];

@ -1,25 +0,0 @@
module.exports = ({env}) => ({
// ...
email: {
config: {
provider: 'nodemailer',
providerOptions: {
host: env('SMTP_HOST', 'smtp.example.com'),
port: env('SMTP_PORT', 587),
auth: {
user: env('SMTP_USERNAME'),
pass: env('SMTP_PASSWORD'),
},
// ... any custom nodemailer options
},
settings: {
defaultFrom: env('SMTP_DEFAULT_FROM', 'no-reply@strapi.io'),
defaultReplyTo: env('SMTP_DEFAULT_REPLY', 'synology@naser.fr'),
},
},
},
'import-export-entries': {
enabled: true
}
// ...
});

@ -1,7 +0,0 @@
export default ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
app: {
keys: env.array('APP_KEYS'),
},
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 497 B

@ -1,20 +0,0 @@
services:
gs_mysql:
image: 'mariadb:10.3'
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE_NAME}
# So you don't have to use root, but you can if you like
MYSQL_USER: ${MYSQL_DATABASE_USERNAME}
# You can use whatever password you like
MYSQL_PASSWORD: ${MYSQL_DATABASE_PASSWORD}
# Password for root access
MYSQL_ROOT_PASSWORD: ${MYSQL_DATABASE_ROOT_PASSWORD}
ports:
# <Port exposed> : < MySQL Port running inside container>
- '${MYSQL_DATABASE_PORT}:3306'
expose:
# Opens port 3306 on the container
- '${MYSQL_DATABASE_PORT}'
# Where our data will be persisted
volumes:
- gs_mariadb-master:/var/lib/mysql

File diff suppressed because it is too large Load Diff

@ -1,40 +0,0 @@
{
"name": "backend",
"private": true,
"version": "0.1.0",
"description": "A Strapi application",
"scripts": {
"generate": "strapi generate",
"develop": "strapi develop",
"start": "strapi start",
"build": "strapi build",
"strapi": "strapi"
},
"overrides": {
"@strapi/strapi": "4.5.4"
},
"dependencies": {
"@strapi/plugin-i18n": "4.5.4",
"@strapi/plugin-users-permissions": "4.5.4",
"@strapi/provider-email-nodemailer": "4.5.6",
"@strapi/strapi": "4.5.4",
"@strapi/utils": "4.5.6",
"better-sqlite3": "7.4.6",
"mysql": "2.18.1",
"pg": "8.8.0",
"strapi-plugin-import-export-entries": "1.18.0",
"strapi-plugin-menus": "1.2.1",
"strapi-plugin-populate-deep": "1.1.2"
},
"author": {
"name": "A Strapi developer"
},
"strapi": {
"uuid": "d1de7a93-c68b-4597-80ee-b5b56ea4eb10"
},
"engines": {
"node": ">=14.19.1 <=18.x.x",
"npm": ">=6.0.0"
},
"license": "MIT"
}

@ -1,20 +0,0 @@
services:
gs_postgres:
image: postgres:14-alpine
container_name: gs_postgres
shm_size: '4gb'
environment:
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
TZ: Europe/Paris
healthcheck:
test: 'PGPASSWORD="${DATABASE_PASSWORD}" psql --host ${DATABASE_HOST} --username ${DATABASE_USERNAME} --dbname ${DATABASE_NAME} -c "select 1" ; [ "0" -eq "$$?" ]; echo $$?'
interval: 30s
timeout: 10s
retries: 3
volumes:
- gs_postgres-master:/var/lib/postgresql/data:z
- ./.db/init:/docker-entrypoint-initdb.d
ports:
- ${DATABASE_PORT}:5432 # DB

@ -1,3 +0,0 @@
# To prevent search engines from seeing the site altogether, uncomment the next two lines:
# User-Agent: *
# Disallow: /

@ -1,35 +0,0 @@
export default {
config: {
locales: [
// 'ar',
// 'fr',
// 'cs',
// 'de',
// 'dk',
// 'es',
// 'he',
// 'id',
// 'it',
// 'ja',
// 'ko',
// 'ms',
// 'nl',
// 'no',
// 'pl',
// 'pt-BR',
// 'pt',
// 'ru',
// 'sk',
// 'sv',
// 'th',
// 'tr',
// 'uk',
// 'vi',
// 'zh-Hans',
// 'zh',
],
},
bootstrap(app) {
console.log(app);
},
};

@ -1,13 +0,0 @@
{
"extends": "@strapi/typescript-utils/tsconfigs/admin",
"include": [
"../plugins/**/admin/src/**/*",
"./"
],
"exclude": [
"node_modules/",
"build/",
"dist/",
"**/*.test.ts"
]
}

@ -1,12 +0,0 @@
'use strict';
const MonacoWebackPlugin = require('monaco-editor-webpack-plugin');
/* eslint-disable no-unused-vars */
module.exports = (config, webpack) => {
// Note: we provide webpack above so you should not `require` it
// Perform customizations to webpack config
// Important: return the modified config
config.plugins.push(new MonacoWebackPlugin())
return config;
};

@ -1,32 +0,0 @@
{
"kind": "collectionType",
"collectionName": "pages",
"info": {
"singularName": "page",
"pluralName": "pages",
"displayName": "Pages",
"description": ""
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"label": {
"type": "string"
},
"slug": {
"type": "uid",
"targetField": "label"
},
"seo": {
"type": "component",
"repeatable": false,
"component": "shared.seo"
},
"Login": {
"type": "dynamiczone",
"components": []
}
}
}

@ -1,7 +0,0 @@
/**
* page controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::page.page');

@ -1,7 +0,0 @@
/**
* page router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::page.page');

@ -1,7 +0,0 @@
/**
* page service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::page.page');

@ -1,17 +0,0 @@
/**
* A set of functions called "actions" for `username`
*/
export default {
findOne: async (ctx, next) => {
try {
const data = await strapi
.service("api::username.username")
.findUsername(ctx.params.username);
ctx.body = data;
} catch (err) {
ctx.badRequest("Post report controller error", {moreDetails: err});
}
}
};

@ -1,13 +0,0 @@
export default {
routes: [
{
method: 'GET',
path: '/username/:username',
handler: 'username.findOne',
config: {
policies: [],
middlewares: [],
},
},
],
};

@ -1,18 +0,0 @@
/**
* username service
*/
export default () => ({
findUsername: async (username) => {
try {
console.log(username);
let users = await strapi.entityService.findMany(
"plugin::users-permissions.user", {filters: {email: username}}
);
return users.length !== 0;
} catch (err) {
return err;
}
}
});

@ -1,16 +0,0 @@
{
"collectionName": "components_meta_metas",
"info": {
"displayName": "meta",
"icon": "network-wired"
},
"options": {},
"attributes": {
"property": {
"type": "string"
},
"content": {
"type": "string"
}
}
}

@ -1,36 +0,0 @@
{
"collectionName": "components_shared_seos",
"info": {
"displayName": "Seo",
"icon": "book",
"description": ""
},
"options": {},
"attributes": {
"metaTitle": {
"type": "string"
},
"metaDescription": {
"type": "text"
},
"SharedImage": {
"displayName": "SharedImage",
"type": "component",
"repeatable": false,
"component": "shared.shared-image"
},
"Meta": {
"displayName": "meta",
"type": "component",
"repeatable": true,
"component": "meta.meta"
},
"preventIndexing": {
"type": "boolean",
"default": false
},
"structuredData": {
"type": "json"
}
}
}

@ -1,24 +0,0 @@
{
"collectionName": "components_shared_shared_images",
"info": {
"displayName": "SharedImage",
"icon": "file-image",
"description": ""
},
"options": {},
"attributes": {
"alt": {
"type": "string"
},
"media": {
"allowedTypes": [
"images",
"files",
"videos",
"audios"
],
"type": "media",
"multiple": false
}
}
}

@ -1,79 +0,0 @@
{
"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
},
"avatar": {
"allowedTypes": [
"images"
],
"type": "media",
"configurable": false,
"multiple": false
},
"newsletter": {
"type": "boolean",
"default": false
}
}
}

@ -1,18 +0,0 @@
export default {
/**
* An asynchronous register function that runs before
* your application is initialized.
*
* This gives you an opportunity to extend code.
*/
register(/*{ strapi }*/) {},
/**
* 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.
*/
bootstrap(/*{ strapi }*/) {},
};

@ -1,23 +0,0 @@
{
"extends": "@strapi/typescript-utils/tsconfigs/server",
"compilerOptions": {
"outDir": "../../dist/apps/backend/dist",
"rootDir": "."
},
"include": [
"./",
"./**/*.ts",
"./**/*.js",
"src/**/*.json"
],
"exclude": [
"node_modules/",
"build/",
"dist/",
".cache/",
".tmp/",
"src/admin/",
"**/*.test.*",
"src/plugins/**"
]
}

@ -0,0 +1,2 @@
NX_STRAPI_URL_API=http://localhost:1337/api
NX_STRAPI_URL=http://localhost:1337

@ -2,6 +2,7 @@ import axios from "axios";
import * as _ from 'lodash';
import {environment} from "../environments/environment";
import {config} from "../config";
export type Inputs = {
email: string,
@ -12,6 +13,16 @@ export type Inputs = {
newsletter: boolean,
}
export type LostPasswordInputs = {
email: string;
}
export type ResetPasswordInputs = {
password: string,
passwordConfirmation: string,
code: string
}
export const hasAvatar = (user) => {
return !_.isNil(user.avatar);
}

@ -1,6 +1,9 @@
import axios from 'axios';
import {signIn} from "next-auth/react";
import * as _ from 'lodash';
import {config} from "../config";
import {environment} from "../environments/environment";
export async function createJwtToken(email, password) {
return await signIn('credentials', {
@ -11,15 +14,37 @@ export async function createJwtToken(email, password) {
}
export async function signInStrapi({email, password}) {
const res = await axios.post(`${(config.env as any).STRAPI_URL_API}/auth/local`, {
const res = await axios.post(`${environment.strapiApiUrl}/auth/local`, {
identifier: email,
password,
});
if (res && res.data) {
const user = await axios.get(`${(config.env as any).STRAPI_URL_API}/users/${res.data.user.id}?populate=deep`);
const user = await axios.get(`${environment.strapiApiUrl}/users/${res.data.user.id}?populate=deep`);
if (user && user.data) {
res.data.user = {...res.data.user, ...user.data};
}
}
return res.data;
}
export async function lostPasswordStrapi({email}) {
const res = await axios.post(`${environment.strapiApiUrl}/auth/forgot-password`, {email});
if (res && res.data) {
return res.data.ok;
} else {
return false;
}
}
export async function resetPasswordStrapi({password, passwordConfirmation, code}) {
const res = await axios.post(`${environment.strapiApiUrl}/auth/reset-password`, {
password,
passwordConfirmation,
code
});
if (res && res.data) {
return !_.isNil(res.data.jwt);
} else {
return false;
}
}

@ -3,8 +3,8 @@ import CredentialsProvider from 'next-auth/providers/credentials';
import {JWT} from "next-auth/jwt";
import {AdapterUser} from "next-auth/adapters";
import {signInStrapi} from '../../../libs/auth';
import {environment} from "../../../environments/environment";
import {signInStrapi} from '../../../libs/auth';
export default NextAuth({

@ -9,7 +9,6 @@ import {environment} from "../environments/environment";
const getPageMetadata = async (path) => {
try {
console.log((config.env as any));
return await axios.get(`${environment.strapiApiUrl}/pages?filters[slug]=${path === '/' ? 'home' : path.slice(1, path.length)}&populate=deep`);
} catch (e) {
console.error(e);
@ -19,7 +18,6 @@ const getPageMetadata = async (path) => {
export const getServerSideProps = async (context) => {
const path = context.resolvedUrl;
console.log((config.env as any));
const menuHeader = await axios.get(`${environment.strapiApiUrl}/menus/1?nested&populate=deep`);
const menuFooter = await axios.get(`${environment.strapiApiUrl}/menus/2?nested&populate=deep`);
const page = await getPageMetadata(path);

@ -1,14 +1,19 @@
import axios from "axios";
import delve from "dlv";
import {useState} from "react";
import {SubmitHandler, useForm} from "react-hook-form";
import SeoConfig from "../../components/seo-config/seo-config";
import Layout from "../../components/layout/layout";
import styles from "../sign-up/index.module.scss";
import {config} from "../../config";
import {environment} from "../../environments/environment";
import {LostPasswordInputs} from "../../libs/api";
import {lostPasswordStrapi} from "../../libs/auth";
import styles from "../sign-up/index.module.scss";
const getPageMetadata = async (path) => {
try {
return await axios.get(`${environment.strapiApiUrl}/pages?filters[slug]=${path === '/' ? 'home' : path.slice(1, path.length)}&populate=deep`);
return await axios.get(`${environment.strapiApiUrl}/pages?filters[slug]=${path === '/' ? 'home' : path.slice(1, path.length)}&populate=deep`);
} catch (e) {
console.error(e);
return Promise.resolve({})
@ -31,6 +36,26 @@ export const getServerSideProps = async (context) => {
}
export function LostPassword({menuHeaders, menuFooter, page, seo}) {
const {register, handleSubmit, formState: {errors}} = useForm({
defaultValues: {
email: ""
}
});
const [isSent, setIsSent] = useState(null);
const onSubmit: SubmitHandler<LostPasswordInputs> = async (data: LostPasswordInputs) => {
try {
const result = await lostPasswordStrapi({email: data.email});
setIsSent(result);
} catch (e) {
setIsSent(false);
}
}
const hasErrors = () => Object.keys(errors).length > 0;
const isBoolean = (val) => typeof val === "boolean";
return (
<>
<SeoConfig {...seo}/>
@ -40,10 +65,61 @@ export function LostPassword({menuHeaders, menuFooter, page, seo}) {
<div className="container px-6 py-4 md:py-12 h-full mx-auto">
<div className="flex justify-center items-center flex-wrap h-full g-6 text-gray-800">
<div className="md:w-8/12 lg:w-6/12">
<p>Form here</p>
<div
className="w-full max-w-[560px] p-4 bg-white border border-gray-200 rounded-lg shadow-md sm:p-6 md:p-8 dark:bg-gray-800 dark:border-gray-700">
<form className="space-y-6" onSubmit={handleSubmit(onSubmit)}>
<header className="text-left block">
<h3 className="text-3xl font-normal dark:text-white mb-6">Mot de passe oublié</h3>
<p className="mb-6 text-base font-normal text-gray-500 dark:text-gray-400">
Veuillez saisir votre addresse email ci-dessous et nous vous enverrons un courriel pour
changer votre mot de passe.
</p>
</header>
<main>
{isBoolean(isSent) && isSent ? (<div
className="p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400"
role="alert">
<span className="font-medium">Email envoyé !</span> Vérifiez votre boite de réception ou vos
courrier indésirables.
</div>) : ('')}
{isBoolean(isSent) && !isSent ? (<div
className="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400"
role="alert">
<span className="font-medium">Oups !</span> Une erreur est survenue durant l'envoi de l'email.
Rapprochez vous de nos équipes pour en savoir plus.
</div>) : ('')}
<section className="grid grid-cols-1 gap-4 mb-4">
<div>
<label htmlFor="email"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
E-mail
</label>
<div className="relative">
<input type="email"
name="email"
id="email"
{...register("email", {required: "L'email est requis"})}
className={errors.email ? 'bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-lg focus:ring-red-500 dark:bg-gray-700 focus:border-red-500 block w-full p-2.5 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500' : 'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pr-10 p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white'}
placeholder="name@company.com"/>
{errors.email && (
<p className="mt-2 text-sm text-red-600 dark:text-red-500">{errors.email.message}</p>)}
</div>
</div>
</section>
<section className="flex items-center pt-5">
<button type="submit"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 w-full disabled:bg-gray-500 focus:disabled:bg-gray-500 hover:disabled:bg-gray-500"
data-mdb-ripple="true"
data-mdb-ripple-color="light" disabled={hasErrors()}>
Envoyer le code par email
</button>
</section>
</main>
</form>
</div>
</div>
<div className="md:w-8/12 lg:w-6/12 mb-12 md:mb-0 hidden md:block">
<img src="https://mdbcdn.b-cdn.net/img/Photos/new-templates/bootstrap-login-form/draw2.png"
<img src="/images/page-lost-password.png"
className="w-full" alt="Phone image"/>
</div>
</div>

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,170 @@
import delve from "dlv";
import axios from "axios";
import {SubmitHandler, useForm} from "react-hook-form";
import SeoConfig from "../../components/seo-config/seo-config";
import Layout from "../../components/layout/layout";
import {environment} from "../../environments/environment";
import {ResetPasswordInputs} from "../../libs/api";
import styles from './index.module.scss';
import {useRouter} from "next/router";
import {useState} from "react";
import {resetPasswordStrapi} from "../../libs/auth";
const getPageMetadata = async (path) => {
try {
return await axios.get(`${environment.strapiApiUrl}/pages?filters[slug]=${path === '/' ? 'home' : path.slice(1, path.length)}&populate=deep`);
} catch (e) {
console.error(e);
return Promise.resolve({})
}
}
export const getServerSideProps = async (context) => {
const path = context.resolvedUrl;
const menuHeader = await axios.get(`${environment.strapiApiUrl}/menus/1?nested&populate=deep`);
const menuFooter = await axios.get(`${environment.strapiApiUrl}/menus/2?nested&populate=deep`);
const page = await getPageMetadata(path);
return {
props: {
menuHeaders: delve(menuHeader, 'data.data.attributes.items.data', []),
menuFooter: delve(menuFooter, 'data.data.attributes.items.data', []),
page: delve(page, "data.data.0.attributes", {}),
seo: delve(page, "data.data.0.attributes.seo", {})
}
}
}
export function ResetPassword({menuHeaders, menuFooter, page, seo}) {
const router = useRouter();
const [success, setSuccess] = useState(null);
const {register, handleSubmit, getValues, formState: {errors}} = useForm({
defaultValues: {
password: null,
passwordConfirmation: null,
code: router.query ? router.query.code : null
}
});
const onSubmit: SubmitHandler<ResetPasswordInputs> = async (data: ResetPasswordInputs) => {
try {
const result = await resetPasswordStrapi({
password: data.password,
passwordConfirmation: data.passwordConfirmation,
code: data.code
});
setSuccess(result);
setTimeout(() => router.push('/sign-in'), 5000);
} catch (e) {
setSuccess(false);
}
}
const hasErrors = () => Object.keys(errors).length > 0;
const isBoolean = (val) => typeof val === "boolean";
return (
<>
<SeoConfig {...seo}/>
<Layout menuHeader={menuHeaders} menuFooter={menuFooter}>
<div className={styles['page-sign-up']}>
<section className={styles['section']}>
<div className="container px-6 py-4 md:py-12 h-full mx-auto">
<div className="flex justify-center items-center flex-wrap h-full g-6 text-gray-800">
<div className="md:w-8/12 lg:w-6/12 mb-12 md:mb-0 hidden md:block">
<img src="/images/page-lost-password.png"
className="w-full" alt="Phone image"/>
</div>
<div className="md:w-8/12 lg:w-6/12 flex justify-end">
<div
className="w-full max-w-[560px] p-4 bg-white border border-gray-200 rounded-lg shadow-md sm:p-6 md:p-8 dark:bg-gray-800 dark:border-gray-700">
<form className="space-y-6" onSubmit={handleSubmit(onSubmit)}>
<header className="text-left block">
<h3 className="text-3xl font-normal dark:text-white mb-6">Changer votre mot de passe</h3>
<p className="mb-6 text-base font-normal text-gray-500 dark:text-gray-400">
Indiquez votre nouveau mot de passe
</p>
</header>
{isBoolean(success) && success ? (<div
className="p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400"
role="alert">
<span className="font-medium">Mot de passe changé !</span> vous allez être redirigé vers la page
de connexion.
</div>) : ('')}
{isBoolean(success) && !success ? (<div
className="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400"
role="alert">
<span className="font-medium">Oups !</span> Une erreur est survenue durant le changement du mot
de passe. Rapprochez vous de nos équipes pour en savoir plus.
</div>) : ('')}
<main>
<section className="grid grid-cols-1 gap-4 mb-4">
<div>
<label htmlFor="password"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Mot de passe
</label>
<div className="relative">
<input type="password"
name="password"
id="password"
{...register("password", {required: "Le mot de passe est requis", minLength: 8})}
className={errors.email ? 'bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-lg focus:ring-red-500 dark:bg-gray-700 focus:border-red-500 block w-full p-2.5 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500' : 'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pr-10 p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white'}/>
{errors.password && errors.password.type !== "minLength" && (
<p
className="mt-2 text-sm text-red-600 dark:text-red-500">{errors.password.message}</p>)}
{errors.password && errors.password.type === "minLength" && (
<p className="mt-2 text-sm text-red-600 dark:text-red-500">Le mot de passe doit avoir
une
longueur minimum de 8 charactères</p>)}
</div>
</div>
<div>
<label htmlFor="passwordConfirmation"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Confirmez votre mot de passe
</label>
<div className="relative">
<input type="password"
name="passwordConfirmation"
id="passwordConfirmation"
{...register("passwordConfirmation", {
required: "Veuillez confirmer le mot de passe", validate: {
matchesPreviousPassword: (value) => {
const {password} = getValues();
return password === value || "Les mots de passe ne correspondent pas";
}
}
})}
className={errors.password ? 'bg-red-50 border border-red-500 text-red-900 placeholder-red-700 text-sm rounded-lg focus:ring-red-500 dark:bg-gray-700 focus:border-red-500 block w-full p-2.5 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500' : 'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pr-10 p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white'}/>
{errors.passwordConfirmation && (
<p
className="mt-2 text-sm text-red-600 dark:text-red-500">{errors.passwordConfirmation.message}</p>)}
</div>
</div>
</section>
<section className="flex items-center pt-5">
<button type="submit"
className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 w-full disabled:bg-gray-500 focus:disabled:bg-gray-500 hover:disabled:bg-gray-500"
data-mdb-ripple="true"
data-mdb-ripple-color="light" disabled={hasErrors()}>
Changer votre mot de passe
</button>
</section>
</main>
</form>
</div>
</div>
</div>
</div>
</section>
</div>
</Layout>
</>
);
}
export default ResetPassword;

@ -4,12 +4,11 @@ import {useRouter} from "next/router";
import SeoConfig from "../../components/seo-config/seo-config";
import Layout from "../../components/layout/layout";
import styles from './index.module.scss';
import {createJwtToken} from "../../libs/auth";
import {config} from "../../config";
import {environment} from "../../environments/environment";
import styles from './index.module.scss';
const getPageMetadata = async (path) => {
try {
return await axios.get(`${environment.strapiApiUrl}/pages?filters[slug]=${path === '/' ? 'home' : path.slice(1, path.length)}&populate=deep`);

@ -190,7 +190,7 @@ export function SignUp({seo, menuHeaders, menuFooter}) {
longueur minimum de 8 charactères</p>)}
</div>
<div>
<label htmlFor="password2"
<label htmlFor="passwordConfirmation"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
Confirmez le mot de passe
</label>

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

@ -1,34 +0,0 @@
services:
# PostgreSQL (Database)
#gs_postgres:
# extends:
# file: apps/backend/postgres.yml
# service: gs_postgres
# MySQL (Database)
gs_mysql:
extends:
file: apps/backend/mysql.yml
service: gs_mysql
gs_redis:
image: "redis:alpine"
ports:
- "6379:6379"
gs_redis_commander:
image: rediscommander/redis-commander:latest
environment:
- REDIS_HOSTS=local:gs_redis:6379
ports:
- "8081:8081"
depends_on:
- gs_redis
volumes:
gs_postgres-master:
driver: local
gs_mariadb-master:
driver: local

File diff suppressed because one or more lines are too long

@ -3,47 +3,35 @@
"version": "0.0.0",
"license": "MIT",
"scripts": {
"start:docker": "env $(cat apps/backend/.env) docker-compose up -d --force-recreate",
"install:backend": "cd apps/backend && npm install",
"generate:backend": "cd apps/backend && npm run generate",
"build:backend": "cd apps/backend && npm run build",
"build:backend:staging": "cd apps/backend && npm run build",
"postbuild:backend:staging": "node scripts/strapi/build-staging.js",
"predevelop:backend": "npm run start:docker && npm run build:backend",
"develop:backend": "cd apps/backend && npm run develop",
"start:client": "nx serve client",
"build:client:development": "npm run build client -- --configuration development --verbose",
"build:client:staging": "npm run build client -- --configuration staging",
"build:client:production": "npm run build client -- --configuration production",
"start": "nx serve",
"build": "nx build",
"test": "nx test",
"start:website": "nx serve website",
"build:website:development": "nx build website --configuration development --verbose",
"build:website:staging": "nx build website --configuration staging",
"postbuild:website:staging": "node scripts/website/build-staging.js",
"build:website:production": "nx build website --configuration production",
"start": "nx serve",
"build": "nx build",
"test": "nx test"
"build:website:production": "nx build website --configuration production"
},
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@fortawesome/fontawesome-svg-core": "6.2.1",
"@fortawesome/free-solid-svg-icons": "6.2.1",
"@fortawesome/react-fontawesome": "0.2.0",
"@nrwl/next": "15.5.1",
"axios": "^1.2.2",
"dlv": "^1.1.3",
"flowbite": "^1.6.2",
"axios": "1.2.2",
"dlv": "1.1.3",
"flowbite": "1.6.2",
"next": "13.1.1",
"next-auth": "^4.18.8",
"next-auth": "4.18.8",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-helmet": "^6.0.0",
"react-hook-form": "^7.42.1",
"rxjs": "^7.8.0",
"tslib": "^2.3.0"
"react-helmet": "6.0.0",
"react-hook-form": "7.42.1",
"rxjs": "7.8.0",
"tslib": "2.3.0"
},
"devDependencies": {
"@babel/preset-react": "^7.14.5",
"@babel/preset-react": "7.14.5",
"@nrwl/cypress": "15.5.1",
"@nrwl/eslint-plugin-nx": "15.5.1",
"@nrwl/jest": "15.5.1",
@ -51,21 +39,20 @@
"@nrwl/react": "15.5.1",
"@nrwl/web": "15.5.1",
"@nrwl/workspace": "15.5.1",
"@nx-extend/strapi": "^3.2.0",
"@testing-library/react": "13.4.0",
"@types/jest": "28.1.1",
"@types/node": "18.11.9",
"@types/react": "18.0.25",
"@types/react-dom": "18.0.9",
"@typescript-eslint/eslint-plugin": "^5.36.1",
"@typescript-eslint/parser": "^5.36.1",
"@typescript-eslint/eslint-plugin": "5.36.1",
"@typescript-eslint/parser": "5.36.1",
"autoprefixer": "10.4.13",
"babel-jest": "28.1.1",
"cypress": "^12.2.0",
"eslint": "~8.15.0",
"cypress": "12.2.0",
"eslint": "8.15.0",
"eslint-config-next": "13.1.1",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-cypress": "^2.10.3",
"eslint-plugin-cypress": "2.10.3",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.31.11",
@ -74,12 +61,12 @@
"jest-environment-jsdom": "28.1.1",
"nx": "15.5.1",
"postcss": "8.4.19",
"prettier": "^2.6.2",
"prettier": "2.6.2",
"react-test-renderer": "18.2.0",
"sass": "1.55.0",
"tailwindcss": "3.2.4",
"ts-jest": "28.0.5",
"ts-node": "10.9.1",
"typescript": "~4.8.2"
"typescript": "4.8.2"
}
}

@ -1,9 +0,0 @@
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
fse.copySync(path.join(__dirname, '..', '..', 'apps/backend/public'), path.join(__dirname, '..', '..', 'dist', 'apps', 'backend/public'));
fs.copyFileSync(path.join(__dirname, '..', '..', 'apps/backend/.env.staging'), path.join(__dirname, '..', '..', 'dist', 'apps', 'backend/.env'));
fs.copyFileSync(path.join(__dirname, 'sources/server.js'), path.join(__dirname, '..', '..', 'dist', 'apps', 'backend/server.js'));
fs.copyFileSync(path.join(__dirname, 'sources/package.json'), path.join(__dirname, '..', '..', 'dist', 'apps', 'backend/package.json'));
fs.copyFileSync(path.join(__dirname, 'sources/.strapi-updater.json'), path.join(__dirname, '..', '..', 'dist', 'apps', 'backend/.strapi-updater.json'));

@ -1,4 +0,0 @@
{
"latest": "4.5.6",
"lastUpdateCheck": 1674315789881
}

@ -1,31 +0,0 @@
{
"name": "nx-guitar-school",
"version": "0.0.0",
"overrides": {
"@strapi/strapi": "4.5.4"
},
"dependencies": {
"@strapi/plugin-i18n": "4.5.4",
"@strapi/plugin-users-permissions": "4.5.4",
"@strapi/provider-email-nodemailer": "4.5.6",
"@strapi/strapi": "4.5.4",
"@strapi/utils": "4.5.6",
"better-sqlite3": "7.4.6",
"mysql": "2.18.1",
"pg": "8.8.0",
"strapi-plugin-import-export-entries": "1.18.0",
"strapi-plugin-menus": "1.2.1",
"strapi-plugin-populate-deep": "1.1.2"
},
"author": {
"name": "A Strapi developer"
},
"strapi": {
"uuid": "d1de7a93-c68b-4597-80ee-b5b56ea4eb10"
},
"engines": {
"node": ">=14.19.1 <=18.x.x",
"npm": ">=6.0.0"
},
"license": "MIT"
}

@ -1,3 +0,0 @@
const strapi = require('@strapi/strapi');
const app = strapi({distDir: './dist'});
app.start();
Loading…
Cancel
Save