<commit_before>const errors = require('@feathersjs/errors');
const userModel = require('./model');
const accountModel = require('../account/model');
const consentModel = require('../consent/model');
const { getAge } = require('../../utils');
const logger = require('../../logger');

const { CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS } = require('../../../config/globals');

const formatBirthdate1 = (datestamp) => {
	if (datestamp == undefined) return false;

	const d = datestamp.split('.');
	return `${d[1]}.${d[0]}.${d[2]}`;
};

const populateUser = (app, data) => {
	let oldUser;
	const user = {
		firstName: data.firstName,
		lastName: data.lastName,
		email: data.email,
		roles: ['student'],
		schoolId: data.schoolId,
	};

	const formatedBirthday = formatBirthdate1(data.birthDate);
	if (formatedBirthday) {
		user.birthday = new Date(formatedBirthday);
	}

	if (data.classId) user.classId = data.classId;

	if (data.importHash) {
		return app.service('users').find({ query: { importHash: data.importHash, _id: data.userId, $populate: ['roles'] } }).then((users) => {
			if (users.data.length <= 0 || users.data.length > 1) {
				throw new errors.BadRequest('Kein Nutzer für die eingegebenen Daten gefunden.');
			}
			oldUser = users.data[0];

			Object.keys(oldUser).forEach((key) => {
				if (oldUser[key] !== null && key !== 'firstName' && key !== 'lastName') {
					user[key] = oldUser[key];
				}
			});

			user.roles = user.roles.map((role) => (typeof role === 'object' ? role.name : role));

			delete user.importHash;
			return { user, oldUser };
		});
	}
	return Promise.resolve({ user, oldUser });
};

const insertUserToDB = async (app, data, user) => {
	if (user._id) {
		user.roles = [...new Set(await app.service('roles')
			.find({ query: { name: { $in: user.roles } } })
			.then((roles) => {
				const r = roles.data.map((role) => role._id);
				return r;
			}))];
		return app.service('users')
			.update(user._id, user)
			.catch((err) => {
				logger.warning(err);
				throw new errors.BadRequest('Fehler beim Updaten der Nutzerdaten.');
			});
	}
	return app.service('users').create(user, { _additional: { parentEmail: data.parent_email, asTask: 'student' } })
		.catch((err) => {
			logger.error(err);
			// fixme check error message is correct, check err
			let msg = 'Fehler beim Erstellen des Nutzers. '
				+ 'Eventuell ist die E-Mail-Adresse bereits im System registriert. '
				+ 'Wende dich an den Support. Damit wir dir schnell helfen können, '
				+ 'teile uns bitte alle angegebenen E-Mail-Adressen mit.';
			if (err && err.message) {
				if (err.message.includes('bereits')) {
					// account or user exists
					msg = `${err.message} `
					+ 'Wahrscheinlich kannst du dich damit bereits einloggen. '
					+ 'Nutze dazu den Login. Dort kannst du dir auch ein neues Passwort zusenden lassen.';
				}
			}
			throw new errors.BadRequest(msg);
		});
};

const registerUser = function register(data, params, app) {
	let parent = null; let user = null; let oldUser = null; let account = null; let consent = null; let
		consentPromise = null;

	return new Promise(((resolve) => {
		resolve();
	})).then(() => {
		let classPromise = null; let
			schoolPromise = null;
		// resolve class or school Id
		classPromise = app.service('classes').find({ query: { _id: data.classOrSchoolId } });
		schoolPromise = app.service('schools').find({ query: { _id: data.classOrSchoolId } });
		return Promise.all([classPromise, schoolPromise])
			.then(([classes, schools]) => {
				if (classes.total === 1) {
					data.classId = data.classOrSchoolId;
					data.schoolId = classes.data[0].schoolId;
					return Promise.resolve();
				}
				if (schools.total === 1) {
					data.schoolId = data.classOrSchoolId;
					return Promise.resolve();
				}
				return Promise.reject('Ungültiger Link');
			});
	}).then(() => populateUser(app, data)
		.then((response) => {
			user = response.user;
			oldUser = response.oldUser;
		})).then(() => {
		if ((user.roles || []).includes('student')) {
			// wrong birthday object?
			if (user.birthday instanceof Date && Number.isNaN(user.birthday)) {
				return Promise.reject(new errors.BadRequest(
					'Fehler bei der Erkennung des ausgewählten Geburtstages.'
						+ ' Bitte lade die Seite neu und starte erneut.',
				));
			}
			// wrong age?
			const age = getAge(user.birthday);
			if (data.parent_email && age >= CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS) {
				return Promise.reject(new errors.BadRequest(
					`Schüleralter: ${age} Im Elternregistrierungs-Prozess darf der Schüler`
						+ `nicht ${CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS} Jahre oder älter sein.`,
				));
			} if (!data.parent_email && age < CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS) {
				return Promise.reject(new errors.BadRequest(
					`Schüleralter: ${age} Im Schülerregistrierungs-Prozess darf der Schüler`
						+ ` nicht jünger als ${CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS} Jahre sein.`,
				));
			}
		}

		// identical emails?
		if (data.parent_email && data.parent_email === data.email) {
			return Promise.reject(new errors.BadRequest(
				'Bitte gib eine unterschiedliche E-Mail-Adresse für dein Kind an.',
			));
		}<commit_msg>SC-4045 Ignore missing parentEmail in registration if SKIP_CONDITIONS_CONSENT is set<commit_after>const { Configuration } = require('@schul-cloud/commons');
const errors = require('@feathersjs/errors');
const userModel = require('./model');
const accountModel = require('../account/model');
const consentModel = require('../consent/model');
const { getAge } = require('../../utils');
const logger = require('../../logger');

const { CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS } = require('../../../config/globals');

const formatBirthdate1 = (datestamp) => {
	if (datestamp == undefined) return false;

	const d = datestamp.split('.');
	return `${d[1]}.${d[0]}.${d[2]}`;
};

const populateUser = (app, data) => {
	let oldUser;
	const user = {
		firstName: data.firstName,
		lastName: data.lastName,
		email: data.email,
		roles: ['student'],
		schoolId: data.schoolId,
	};

	const formatedBirthday = formatBirthdate1(data.birthDate);
	if (formatedBirthday) {
		user.birthday = new Date(formatedBirthday);
	}

	if (data.classId) user.classId = data.classId;

	if (data.importHash) {
		return app.service('users').find({ query: { importHash: data.importHash, _id: data.userId, $populate: ['roles'] } }).then((users) => {
			if (users.data.length <= 0 || users.data.length > 1) {
				throw new errors.BadRequest('Kein Nutzer für die eingegebenen Daten gefunden.');
			}
			oldUser = users.data[0];

			Object.keys(oldUser).forEach((key) => {
				if (oldUser[key] !== null && key !== 'firstName' && key !== 'lastName') {
					user[key] = oldUser[key];
				}
			});

			user.roles = user.roles.map((role) => (typeof role === 'object' ? role.name : role));

			delete user.importHash;
			return { user, oldUser };
		});
	}
	return Promise.resolve({ user, oldUser });
};

const insertUserToDB = async (app, data, user) => {
	if (user._id) {
		user.roles = [...new Set(await app.service('roles')
			.find({ query: { name: { $in: user.roles } } })
			.then((roles) => {
				const r = roles.data.map((role) => role._id);
				return r;
			}))];
		return app.service('users')
			.update(user._id, user)
			.catch((err) => {
				logger.warning(err);
				throw new errors.BadRequest('Fehler beim Updaten der Nutzerdaten.');
			});
	}
	return app.service('users').create(user, { _additional: { parentEmail: data.parent_email, asTask: 'student' } })
		.catch((err) => {
			logger.error(err);
			// fixme check error message is correct, check err
			let msg = 'Fehler beim Erstellen des Nutzers. '
				+ 'Eventuell ist die E-Mail-Adresse bereits im System registriert. '
				+ 'Wende dich an den Support. Damit wir dir schnell helfen können, '
				+ 'teile uns bitte alle angegebenen E-Mail-Adressen mit.';
			if (err && err.message) {
				if (err.message.includes('bereits')) {
					// account or user exists
					msg = `${err.message} `
					+ 'Wahrscheinlich kannst du dich damit bereits einloggen. '
					+ 'Nutze dazu den Login. Dort kannst du dir auch ein neues Passwort zusenden lassen.';
				}
			}
			throw new errors.BadRequest(msg);
		});
};

const registerUser = function register(data, params, app) {
	let parent = null; let user = null; let oldUser = null; let account = null; let consent = null; let
		consentPromise = null;

	return new Promise(((resolve) => {
		resolve();
	})).then(() => {
		let classPromise = null; let
			schoolPromise = null;
		// resolve class or school Id
		classPromise = app.service('classes').find({ query: { _id: data.classOrSchoolId } });
		schoolPromise = app.service('schools').find({ query: { _id: data.classOrSchoolId } });
		return Promise.all([classPromise, schoolPromise])
			.then(([classes, schools]) => {
				if (classes.total === 1) {
					data.classId = data.classOrSchoolId;
					data.schoolId = classes.data[0].schoolId;
					return Promise.resolve();
				}
				if (schools.total === 1) {
					data.schoolId = data.classOrSchoolId;
					return Promise.resolve();
				}
				return Promise.reject('Ungültiger Link');
			});
	}).then(() => populateUser(app, data)
		.then((response) => {
			user = response.user;
			oldUser = response.oldUser;
		})).then(() => {
		const consentSkipCondition = Configuration.get('SKIP_CONDITIONS_CONSENT');
		if ((user.roles || []).includes('student')) {
			// wrong birthday object?
			if (user.birthday instanceof Date && Number.isNaN(user.birthday)) {
				return Promise.reject(new errors.BadRequest(
					'Fehler bei der Erkennung des ausgewählten Geburtstages.'
						+ ' Bitte lade die Seite neu und starte erneut.',
				));
			}
			// wrong age?
			const age = getAge(user.birthday);
			if (data.parent_email && age >= CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS) {
				return Promise.reject(new errors.BadRequest(
					`Schüleralter: ${age} Im Elternregistrierungs-Prozess darf der Schüler`
						+ `nicht ${CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS} Jahre oder älter sein.`,
				));
			} if (!data.parent_email && age < CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS && !consentSkipCondition.includes('student')) {
				return Promise.reject(new errors.BadRequest(
					`Schüleralter: ${age} Im Schülerregistrierungs-Prozess darf der Schüler`
						+ ` nicht jünger als ${CONSENT_WITHOUT_PARENTS_MIN_AGE_YEARS} Jahre sein.`,
				));
			}
		}

		// identical emails?
		if (data.parent_email && data.parent_email === data.email) {
			return Promise.reject(new errors.BadRequest(
				'Bitte gib eine unterschiedliche E-Mail-Adresse für dein Kind an.',
			));
		}
{'fraction_non_alphanumeric': 0.15986008697296275, 'fraction_numerical': 0.0024579315560597464, 'mean_word_length': 3.593573599652627, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '226962', 'n_tokens_mistral': 4103, 'n_tokens_neox': 3578, 'n_words': 846}