diff options
author | Marvin Borner | 2018-06-08 20:03:25 +0200 |
---|---|---|
committer | Marvin Borner | 2018-06-08 20:03:25 +0200 |
commit | 92b7dd3335a6572debeacfb5faa82c63a5e67888 (patch) | |
tree | 7ebbca22595d542ec5e2912a24a0400ac8f6b113 /main/app/sprinkles/account | |
parent | 22a1bb27f94ea33042b0bdd35bef1a5cfa96cc0d (diff) |
Some minor fixes
Diffstat (limited to 'main/app/sprinkles/account')
100 files changed, 9376 insertions, 9376 deletions
diff --git a/main/app/sprinkles/account/asset-bundles.json b/main/app/sprinkles/account/asset-bundles.json index 7fc9430..157df0c 100644 --- a/main/app/sprinkles/account/asset-bundles.json +++ b/main/app/sprinkles/account/asset-bundles.json @@ -1,81 +1,81 @@ -{ - "bundle": { - "js/pages/account-settings": { - "scripts": [ - "userfrosting/js/pages/account-settings.js" - ], - "options": { - "result": { - "type": { - "scripts": "plain" - } - } - } - }, - "js/pages/forgot-password": { - "scripts": [ - "userfrosting/js/pages/forgot-password.js" - ], - "options": { - "result": { - "type": { - "scripts": "plain" - } - } - } - }, - "js/pages/resend-verification": { - "scripts": [ - "userfrosting/js/pages/resend-verification.js" - ], - "options": { - "result": { - "type": { - "scripts": "plain" - } - } - } - }, - "js/pages/set-or-reset-password": { - "scripts": [ - "userfrosting/js/pages/set-or-reset-password.js" - ], - "options": { - "result": { - "type": { - "scripts": "plain" - } - } - } - }, - "js/pages/register": { - "scripts": [ - "vendor/speakingurl/speakingurl.min.js", - "userfrosting/js/uf-captcha.js", - "SiteAssets/js/encryption.js", - "userfrosting/js/pages/register.js" - ], - "options": { - "result": { - "type": { - "scripts": "plain" - } - } - } - }, - "js/pages/sign-in": { - "scripts": [ - "vendor/urijs/src/URI.js", - "SiteAssets/js/encryption.js", - "userfrosting/js/pages/sign-in.js" - ], - "options": { - "result": { - "type": { - "scripts": "plain" - } - } - } - } - } +{
+ "bundle": {
+ "js/pages/account-settings": {
+ "scripts": [
+ "userfrosting/js/pages/account-settings.js"
+ ],
+ "options": {
+ "result": {
+ "type": {
+ "scripts": "plain"
+ }
+ }
+ }
+ },
+ "js/pages/forgot-password": {
+ "scripts": [
+ "userfrosting/js/pages/forgot-password.js"
+ ],
+ "options": {
+ "result": {
+ "type": {
+ "scripts": "plain"
+ }
+ }
+ }
+ },
+ "js/pages/resend-verification": {
+ "scripts": [
+ "userfrosting/js/pages/resend-verification.js"
+ ],
+ "options": {
+ "result": {
+ "type": {
+ "scripts": "plain"
+ }
+ }
+ }
+ },
+ "js/pages/set-or-reset-password": {
+ "scripts": [
+ "userfrosting/js/pages/set-or-reset-password.js"
+ ],
+ "options": {
+ "result": {
+ "type": {
+ "scripts": "plain"
+ }
+ }
+ }
+ },
+ "js/pages/register": {
+ "scripts": [
+ "vendor/speakingurl/speakingurl.min.js",
+ "userfrosting/js/uf-captcha.js",
+ "SiteAssets/js/encryption.js",
+ "userfrosting/js/pages/register.js"
+ ],
+ "options": {
+ "result": {
+ "type": {
+ "scripts": "plain"
+ }
+ }
+ }
+ },
+ "js/pages/sign-in": {
+ "scripts": [
+ "vendor/urijs/src/URI.js",
+ "SiteAssets/js/encryption.js",
+ "userfrosting/js/pages/sign-in.js"
+ ],
+ "options": {
+ "result": {
+ "type": {
+ "scripts": "plain"
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file diff --git a/main/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js b/main/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js index ed75c7b..f1e9845 100644 --- a/main/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js +++ b/main/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js @@ -1,29 +1,29 @@ -/** - * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. - * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} - * - * This script depends on validation rules specified in pages/partials/page.js.twig. - * - * Target page: account/settings - */ -$(document).ready(function () { - - // Apply select2 to locale field - $('.js-select2').select2(); - - $("#account-settings").ufForm({ - validators: page.validators.account_settings, - msgTarget: $("#alerts-page") - }).on("submitSuccess.ufForm", function () { - // Reload the page on success - window.location.reload(); - }); - - $("#profile-settings").ufForm({ - validators: page.validators.profile_settings, - msgTarget: $("#alerts-page") - }).on("submitSuccess.ufForm", function () { - // Reload the page on success - window.location.reload(); - }); -}); +/**
+ * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template.
+ * example: {{ assets.js('js/pages/sign-in-or-register') | raw }}
+ *
+ * This script depends on validation rules specified in pages/partials/page.js.twig.
+ *
+ * Target page: account/settings
+ */
+$(document).ready(function () {
+
+ // Apply select2 to locale field
+ $('.js-select2').select2();
+
+ $("#account-settings").ufForm({
+ validators: page.validators.account_settings,
+ msgTarget: $("#alerts-page")
+ }).on("submitSuccess.ufForm", function () {
+ // Reload the page on success
+ window.location.reload();
+ });
+
+ $("#profile-settings").ufForm({
+ validators: page.validators.profile_settings,
+ msgTarget: $("#alerts-page")
+ }).on("submitSuccess.ufForm", function () {
+ // Reload the page on success
+ window.location.reload();
+ });
+});
diff --git a/main/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js b/main/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js index 95247fc..6eaa401 100644 --- a/main/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js +++ b/main/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js @@ -1,18 +1,18 @@ -/** - * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. - * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} - * - * This script depends on validation rules specified in pages/partials/page.js.twig. - * - * Target page: account/forgot-password - */ -$(document).ready(function () { - - $("#request-password-reset").ufForm({ - validators: page.validators.forgot_password, - msgTarget: $("#alerts-page") - }).on("submitSuccess.ufForm", function () { - // Forward to login page on success - window.location.replace(site.uri.public + "/account/sign-in"); - }); -}); +/**
+ * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template.
+ * example: {{ assets.js('js/pages/sign-in-or-register') | raw }}
+ *
+ * This script depends on validation rules specified in pages/partials/page.js.twig.
+ *
+ * Target page: account/forgot-password
+ */
+$(document).ready(function () {
+
+ $("#request-password-reset").ufForm({
+ validators: page.validators.forgot_password,
+ msgTarget: $("#alerts-page")
+ }).on("submitSuccess.ufForm", function () {
+ // Forward to login page on success
+ window.location.replace(site.uri.public + "/account/sign-in");
+ });
+});
diff --git a/main/app/sprinkles/account/assets/userfrosting/js/pages/register.js b/main/app/sprinkles/account/assets/userfrosting/js/pages/register.js index a311305..4539d9b 100644 --- a/main/app/sprinkles/account/assets/userfrosting/js/pages/register.js +++ b/main/app/sprinkles/account/assets/userfrosting/js/pages/register.js @@ -1,93 +1,93 @@ -/** - * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. - * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} - * - * This script depends on validation rules specified in pages/partials/page.js.twig. - * - * Target page: account/register - */ -$(document).ready(function () { - // TOS modal - $(this).find('.js-show-tos').click(function () { - $("body").ufModal({ - sourceUrl: site.uri.public + "/modals/account/tos", - msgTarget: $("#alerts-page") - }); - }); - - // Auto-generate username when name is filled in - var autoGenerate = true; - $("#register").find('input[name=first_name], input[name=last_name]').on('input change', function () { - if (!autoGenerate) { - return; - } - - var form = $("#register"); - - var firstName = form.find('input[name=first_name]').val().trim(); - var lastName = form.find('input[name=last_name]').val().trim(); - - if (!firstName && !lastName) { - return; - } - - var userName = getSlug(firstName + ' ' + lastName, { - separator: '.' - }); - // Set slug - form.find('input[name=user_name]').val(userName); - }); - - // Autovalidate username field on a delay - var timer; - $("#register").find('input[name=first_name], input[name=last_name], input[name=user_name]').on('input change', function () { - clearTimeout(timer); // Clear the timer so we don't end up with dupes. - timer = setTimeout(function () { // assign timer a new timeout - $("#register").find('input[name=user_name]').valid(); - }, 50); - }); - - // Enable/disable username suggestions in registration page - $("#register").find('#form-register-username-suggest').on('click', function (e) { - e.preventDefault(); - var form = $("#register"); - $.getJSON(site.uri.public + '/account/suggest-username') - .done(function (data) { - // Set suggestion - form.find('input[name=user_name]').val(data.user_name); - }); - }); - - // Turn off autogenerate when someone enters stuff manually in user_name - $("#register").find('input[name=user_name]').on('input', function () { - autoGenerate = false; - }); - - // Add remote rule for checking usernames on the fly - var registrationValidators = $.extend( - true, // deep extend - page.validators.register, - { - rules: { - user_name: { - remote: { - url: site.uri.public + '/account/check-username', - dataType: 'text' - } - } - } - } - ); - - // Handles form submission - $("#register").ufForm({ - validators: registrationValidators, - msgTarget: $("#alerts-page"), - keyupDelay: 500 - }).on("submitSuccess.ufForm", function () { - window.location.reload(); - }).on("submitError.ufForm", function () { - // Reload captcha - $("#captcha").captcha(); - }); -}); +/**
+ * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template.
+ * example: {{ assets.js('js/pages/sign-in-or-register') | raw }}
+ *
+ * This script depends on validation rules specified in pages/partials/page.js.twig.
+ *
+ * Target page: account/register
+ */
+$(document).ready(function () {
+ // TOS modal
+ $(this).find('.js-show-tos').click(function () {
+ $("body").ufModal({
+ sourceUrl: site.uri.public + "/modals/account/tos",
+ msgTarget: $("#alerts-page")
+ });
+ });
+
+ // Auto-generate username when name is filled in
+ var autoGenerate = true;
+ $("#register").find('input[name=first_name], input[name=last_name]').on('input change', function () {
+ if (!autoGenerate) {
+ return;
+ }
+
+ var form = $("#register");
+
+ var firstName = form.find('input[name=first_name]').val().trim();
+ var lastName = form.find('input[name=last_name]').val().trim();
+
+ if (!firstName && !lastName) {
+ return;
+ }
+
+ var userName = getSlug(firstName + ' ' + lastName, {
+ separator: '.'
+ });
+ // Set slug
+ form.find('input[name=user_name]').val(userName);
+ });
+
+ // Autovalidate username field on a delay
+ var timer;
+ $("#register").find('input[name=first_name], input[name=last_name], input[name=user_name]').on('input change', function () {
+ clearTimeout(timer); // Clear the timer so we don't end up with dupes.
+ timer = setTimeout(function () { // assign timer a new timeout
+ $("#register").find('input[name=user_name]').valid();
+ }, 50);
+ });
+
+ // Enable/disable username suggestions in registration page
+ $("#register").find('#form-register-username-suggest').on('click', function (e) {
+ e.preventDefault();
+ var form = $("#register");
+ $.getJSON(site.uri.public + '/account/suggest-username')
+ .done(function (data) {
+ // Set suggestion
+ form.find('input[name=user_name]').val(data.user_name);
+ });
+ });
+
+ // Turn off autogenerate when someone enters stuff manually in user_name
+ $("#register").find('input[name=user_name]').on('input', function () {
+ autoGenerate = false;
+ });
+
+ // Add remote rule for checking usernames on the fly
+ var registrationValidators = $.extend(
+ true, // deep extend
+ page.validators.register,
+ {
+ rules: {
+ user_name: {
+ remote: {
+ url: site.uri.public + '/account/check-username',
+ dataType: 'text'
+ }
+ }
+ }
+ }
+ );
+
+ // Handles form submission
+ $("#register").ufForm({
+ validators: registrationValidators,
+ msgTarget: $("#alerts-page"),
+ keyupDelay: 500
+ }).on("submitSuccess.ufForm", function () {
+ window.location.reload();
+ }).on("submitError.ufForm", function () {
+ // Reload captcha
+ $("#captcha").captcha();
+ });
+});
diff --git a/main/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js b/main/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js index 7da85fa..a6db823 100644 --- a/main/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js +++ b/main/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js @@ -1,18 +1,18 @@ -/** - * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. - * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} - * - * This script depends on validation rules specified in pages/partials/page.js.twig. - * - * Target page: account/resend-verification - */ -$(document).ready(function () { - - $("#request-verification-email").ufForm({ - validators: page.validators.resend_verification, - msgTarget: $("#alerts-page") - }).on("submitSuccess.ufForm", function () { - // Forward to login page on success - window.location.replace(site.uri.public + "/account/sign-in"); - }); -}); +/**
+ * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template.
+ * example: {{ assets.js('js/pages/sign-in-or-register') | raw }}
+ *
+ * This script depends on validation rules specified in pages/partials/page.js.twig.
+ *
+ * Target page: account/resend-verification
+ */
+$(document).ready(function () {
+
+ $("#request-verification-email").ufForm({
+ validators: page.validators.resend_verification,
+ msgTarget: $("#alerts-page")
+ }).on("submitSuccess.ufForm", function () {
+ // Forward to login page on success
+ window.location.replace(site.uri.public + "/account/sign-in");
+ });
+});
diff --git a/main/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js b/main/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js index 62fbf4b..f5e2227 100644 --- a/main/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js +++ b/main/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js @@ -1,18 +1,18 @@ -/** - * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. - * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} - * - * This script depends on validation rules specified in pages/partials/page.js.twig. - * - * Target pages: account/set-password, account/reset-password - */ -$(document).ready(function () { - - $("#set-or-reset-password").ufForm({ - validators: page.validators.set_password, - msgTarget: $("#alerts-page") - }).on("submitSuccess.ufForm", function () { - // Forward to home page on success - window.location.replace(site.uri.public + "/account/sign-in"); - }); -}); +/**
+ * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template.
+ * example: {{ assets.js('js/pages/sign-in-or-register') | raw }}
+ *
+ * This script depends on validation rules specified in pages/partials/page.js.twig.
+ *
+ * Target pages: account/set-password, account/reset-password
+ */
+$(document).ready(function () {
+
+ $("#set-or-reset-password").ufForm({
+ validators: page.validators.set_password,
+ msgTarget: $("#alerts-page")
+ }).on("submitSuccess.ufForm", function () {
+ // Forward to home page on success
+ window.location.replace(site.uri.public + "/account/sign-in");
+ });
+});
diff --git a/main/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js b/main/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js index 769a1b3..7362d6d 100644 --- a/main/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js +++ b/main/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js @@ -1,73 +1,73 @@ -/** - * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. - * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} - * - * This script depends on validation rules specified in pages/partials/page.js.twig. - * - * Target page: account/sign-in - */ -$(document).ready(function () { - /** - * If there is a redirect parameter in the query string, redirect to that page. - * Otherwise, if there is a UF-Redirect header, redirect to that page. - * Otherwise, redirect to the home page. - */ - function redirectOnLogin(jqXHR) { - var components = URI.parse(window.location.href); - var query = URI.parseQuery(components['query']); - - if (query && query['redirect']) { - // Strip leading slashes from redirect strings - var redirectString = site.uri.public + '/' + query['redirect'].replace(/^\/+/, ""); - // Strip excess trailing slashes for clean URLs. e.g. if redirect=%2F - redirectString = redirectString.replace(/\/+$/, "/"); - // Redirect - window.location.replace(redirectString); - } else if (jqXHR.getResponseHeader('UF-Redirect')) { - window.location.replace(jqXHR.getResponseHeader('UF-Redirect')); - } else { - window.location.replace(site.uri.public); - } - } - - $("#sign-in").ufForm({ - validators: page.validators.login, - msgTarget: $("#alerts-page") - }).on("submitSuccess.ufForm", function (event, data, textStatus, jqXHR) { - if (localStorage.getItem("PrivateKey") === null && localStorage.getItem("🔒") === null) { - // GENERATE KEYS - var openpgp = window.openpgp; - var options; - var randomString = Math.random().toString(36).substr(2, 11); // PRIVKEY ENCRYPTION KEY - openpgp.initWorker({path: '/assets-raw/core/assets/SiteAssets/js/openpgp.worker.js'}); - options = { - userIds: [{name: $("input[name=user_name]").val()}], - curve: "curve25519", - passphrase: randomString - }; - openpgp.generateKey(options).then(function (key) { - localStorage.setItem("PrivateKey", key.privateKeyArmored); - localStorage.setItem("🔒", randomString); - - console.log(key.publicKeyArmored); - console.log(key.privateKeyArmored); - // SAVE PUBLIC KEY TO DATABASE - var data = { - csrf_name: site.csrf.name, - csrf_value: site.csrf.value, - PublicKey: key.publicKeyArmored - }; - $.ajax({ - type: 'POST', - dataType: "json", - url: site.uri.public + '/api/users/u/' + $("input[name=user_name]").val() + '/publickey', - data: data, - async: false - }); - redirectOnLogin(jqXHR); - }); - } else { - redirectOnLogin(jqXHR); - } - }); -}); +/**
+ * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template.
+ * example: {{ assets.js('js/pages/sign-in-or-register') | raw }}
+ *
+ * This script depends on validation rules specified in pages/partials/page.js.twig.
+ *
+ * Target page: account/sign-in
+ */
+$(document).ready(function () {
+ /**
+ * If there is a redirect parameter in the query string, redirect to that page.
+ * Otherwise, if there is a UF-Redirect header, redirect to that page.
+ * Otherwise, redirect to the home page.
+ */
+ function redirectOnLogin(jqXHR) {
+ var components = URI.parse(window.location.href);
+ var query = URI.parseQuery(components['query']);
+
+ if (query && query['redirect']) {
+ // Strip leading slashes from redirect strings
+ var redirectString = site.uri.public + '/' + query['redirect'].replace(/^\/+/, "");
+ // Strip excess trailing slashes for clean URLs. e.g. if redirect=%2F
+ redirectString = redirectString.replace(/\/+$/, "/");
+ // Redirect
+ window.location.replace(redirectString);
+ } else if (jqXHR.getResponseHeader('UF-Redirect')) {
+ window.location.replace(jqXHR.getResponseHeader('UF-Redirect'));
+ } else {
+ window.location.replace(site.uri.public);
+ }
+ }
+
+ $("#sign-in").ufForm({
+ validators: page.validators.login,
+ msgTarget: $("#alerts-page")
+ }).on("submitSuccess.ufForm", function (event, data, textStatus, jqXHR) {
+ if (localStorage.getItem("PrivateKey") === null && localStorage.getItem("🔒") === null) {
+ // GENERATE KEYS
+ var openpgp = window.openpgp;
+ var options;
+ var randomString = Math.random().toString(36).substr(2, 11); // PRIVKEY ENCRYPTION KEY
+ openpgp.initWorker({path: '/assets-raw/core/assets/SiteAssets/js/openpgp.worker.js'});
+ options = {
+ userIds: [{name: $("input[name=user_name]").val()}],
+ curve: "curve25519",
+ passphrase: randomString
+ };
+ openpgp.generateKey(options).then(function (key) {
+ localStorage.setItem("PrivateKey", key.privateKeyArmored);
+ localStorage.setItem("🔒", randomString);
+
+ console.log(key.publicKeyArmored);
+ console.log(key.privateKeyArmored);
+ // SAVE PUBLIC KEY TO DATABASE
+ var data = {
+ csrf_name: site.csrf.name,
+ csrf_value: site.csrf.value,
+ PublicKey: key.publicKeyArmored
+ };
+ $.ajax({
+ type: 'POST',
+ dataType: "json",
+ url: site.uri.public + '/api/users/u/' + $("input[name=user_name]").val() + '/publickey',
+ data: data,
+ async: false
+ });
+ redirectOnLogin(jqXHR);
+ });
+ } else {
+ redirectOnLogin(jqXHR);
+ }
+ });
+});
diff --git a/main/app/sprinkles/account/bower.json b/main/app/sprinkles/account/bower.json index d82e9d6..53fb54b 100644 --- a/main/app/sprinkles/account/bower.json +++ b/main/app/sprinkles/account/bower.json @@ -1,28 +1,28 @@ -{ - "name": "userfrosting-sprinkle-account", - "description": "Authentication and account management module for UserFrosting.", - "homepage": "https://github.com/userfrosting", - "license": "MIT", - "authors": [ - { - "name": "Alexander Weissman", - "homepage": "https://alexanderweissman.com" - }, - "ssnukala" - ], - "dependencies": {}, - "moduleType": [ - "node" - ], - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "assets/vendor", - "examples", - "demo-resources", - "demo", - "test", - "tests" - ] -} +{
+ "name": "userfrosting-sprinkle-account",
+ "description": "Authentication and account management module for UserFrosting.",
+ "homepage": "https://github.com/userfrosting",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Alexander Weissman",
+ "homepage": "https://alexanderweissman.com"
+ },
+ "ssnukala"
+ ],
+ "dependencies": {},
+ "moduleType": [
+ "node"
+ ],
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "assets/vendor",
+ "examples",
+ "demo-resources",
+ "demo",
+ "test",
+ "tests"
+ ]
+}
diff --git a/main/app/sprinkles/account/composer.json b/main/app/sprinkles/account/composer.json index 7307337..2a0b26d 100644 --- a/main/app/sprinkles/account/composer.json +++ b/main/app/sprinkles/account/composer.json @@ -1,28 +1,28 @@ -{ - "name": "userfrosting/sprinkle-account", - "type": "userfrosting-sprinkle", - "description": "Authentication and account management module for UserFrosting.", - "keywords": [ - "php user management", - "usercake", - "bootstrap" - ], - "homepage": "https://github.com/userfrosting/UserFrosting", - "license": "MIT", - "authors": [ - { - "name": "Alexander Weissman", - "homepage": "https://alexanderweissman.com" - } - ], - "require": { - "birke/rememberme": "^2.0", - "nikic/php-parser": "^1", - "php": ">=5.6" - }, - "autoload": { - "psr-4": { - "UserFrosting\\Sprinkle\\Account\\": "src/" - } - } -} +{
+ "name": "userfrosting/sprinkle-account",
+ "type": "userfrosting-sprinkle",
+ "description": "Authentication and account management module for UserFrosting.",
+ "keywords": [
+ "php user management",
+ "usercake",
+ "bootstrap"
+ ],
+ "homepage": "https://github.com/userfrosting/UserFrosting",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Alexander Weissman",
+ "homepage": "https://alexanderweissman.com"
+ }
+ ],
+ "require": {
+ "birke/rememberme": "^2.0",
+ "nikic/php-parser": "^1",
+ "php": ">=5.6"
+ },
+ "autoload": {
+ "psr-4": {
+ "UserFrosting\\Sprinkle\\Account\\": "src/"
+ }
+ }
+}
diff --git a/main/app/sprinkles/account/config/default.php b/main/app/sprinkles/account/config/default.php index b018bcd..4f145ba 100644 --- a/main/app/sprinkles/account/config/default.php +++ b/main/app/sprinkles/account/config/default.php @@ -1,79 +1,79 @@ -<?php - -/** - * Account configuration file for UserFrosting. - * - */ - -return [ - 'debug' => [ - 'auth' => FALSE - ], - // configuration for the 'password reset' feature - 'password_reset' => [ - 'algorithm' => 'sha512', - 'timeouts' => [ - 'create' => 86400, - 'reset' => 10800 - ] - ], - // See https://github.com/gbirke/rememberme for an explanation of these settings - 'remember_me' => [ - 'cookie' => [ - 'name' => 'rememberme' - ], - 'expire_time' => 604800, - 'session' => [ - 'path' => '/' - ], - 'table' => [ - 'tableName' => 'persistences', - 'credentialColumn' => 'user_id', - 'tokenColumn' => 'token', - 'persistentTokenColumn' => 'persistent_token', - 'expiresColumn' => 'expires_at' - ] - ], - 'reserved_user_ids' => [ - 'guest' => -1, - 'master' => 1 - ], - 'session' => [ - // The keys used in the session to store info about authenticated users - 'keys' => [ - 'current_user_id' => 'account.current_user_id', // the key to use for storing the authenticated user's id - 'captcha' => 'account.captcha' // Key used to store a captcha hash during captcha verification - ] - ], - // "Site" settings that are automatically passed to Twig - 'site' => [ - 'login' => [ - 'enable_email' => TRUE - ], - 'registration' => [ - 'enabled' => FALSE, // TODO: Datenschutzerklärung before enabling registration - 'captcha' => TRUE, - 'require_email_verification' => TRUE, - 'user_defaults' => [ - 'locale' => 'en_US', - 'group' => 'terran', - // Default roles for newly registered users - 'roles' => [ - 'user' => TRUE - ] - ] - ] - ], - 'throttles' => [ - 'check_username_request' => NULL, - 'password_reset_request' => NULL, - 'registration_attempt' => NULL, - 'sign_in_attempt' => NULL, - 'verification_request' => NULL - ], - // configuration for the 'email verification' feature - 'verification' => [ - 'algorithm' => 'sha512', - 'timeout' => 10800 - ] -]; +<?php
+
+/**
+ * Account configuration file for UserFrosting.
+ *
+ */
+
+return [
+ 'debug' => [
+ 'auth' => FALSE
+ ],
+ // configuration for the 'password reset' feature
+ 'password_reset' => [
+ 'algorithm' => 'sha512',
+ 'timeouts' => [
+ 'create' => 86400,
+ 'reset' => 10800
+ ]
+ ],
+ // See https://github.com/gbirke/rememberme for an explanation of these settings
+ 'remember_me' => [
+ 'cookie' => [
+ 'name' => 'rememberme'
+ ],
+ 'expire_time' => 604800,
+ 'session' => [
+ 'path' => '/'
+ ],
+ 'table' => [
+ 'tableName' => 'persistences',
+ 'credentialColumn' => 'user_id',
+ 'tokenColumn' => 'token',
+ 'persistentTokenColumn' => 'persistent_token',
+ 'expiresColumn' => 'expires_at'
+ ]
+ ],
+ 'reserved_user_ids' => [
+ 'guest' => -1,
+ 'master' => 1
+ ],
+ 'session' => [
+ // The keys used in the session to store info about authenticated users
+ 'keys' => [
+ 'current_user_id' => 'account.current_user_id', // the key to use for storing the authenticated user's id
+ 'captcha' => 'account.captcha' // Key used to store a captcha hash during captcha verification
+ ]
+ ],
+ // "Site" settings that are automatically passed to Twig
+ 'site' => [
+ 'login' => [
+ 'enable_email' => TRUE
+ ],
+ 'registration' => [
+ 'enabled' => FALSE, // TODO: Datenschutzerklärung before enabling registration
+ 'captcha' => TRUE,
+ 'require_email_verification' => TRUE,
+ 'user_defaults' => [
+ 'locale' => 'en_US',
+ 'group' => 'terran',
+ // Default roles for newly registered users
+ 'roles' => [
+ 'user' => TRUE
+ ]
+ ]
+ ]
+ ],
+ 'throttles' => [
+ 'check_username_request' => NULL,
+ 'password_reset_request' => NULL,
+ 'registration_attempt' => NULL,
+ 'sign_in_attempt' => NULL,
+ 'verification_request' => NULL
+ ],
+ // configuration for the 'email verification' feature
+ 'verification' => [
+ 'algorithm' => 'sha512',
+ 'timeout' => 10800
+ ]
+];
diff --git a/main/app/sprinkles/account/config/production.php b/main/app/sprinkles/account/config/production.php index 42b8ada..3ce9866 100644 --- a/main/app/sprinkles/account/config/production.php +++ b/main/app/sprinkles/account/config/production.php @@ -1,67 +1,67 @@ -<?php - -/** - * Account production config file for UserFrosting. You may override/extend this in your site's configuration file to customize deploy settings. - * - */ - -return [ - // See http://security.stackexchange.com/a/59550/74909 for the inspiration for our throttling system - 'throttles' => [ - 'check_username_request' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 40 => 1000 - ] - ], - 'password_reset_request' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 2 => 5, - 3 => 10, - 4 => 20, - 5 => 40, - 6 => 80, - 7 => 600 - ] - ], - 'registration_attempt' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 2 => 5, - 3 => 10, - 4 => 20, - 5 => 40, - 6 => 80, - 7 => 600 - ] - ], - 'sign_in_attempt' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 4 => 5, - 5 => 10, - 6 => 20, - 7 => 40, - 8 => 80, - 9 => 600 - ] - ], - 'verification_request' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 2 => 5, - 3 => 10, - 4 => 20, - 5 => 40, - 6 => 80, - 7 => 600 - ] - ] - ] -]; +<?php
+
+/**
+ * Account production config file for UserFrosting. You may override/extend this in your site's configuration file to customize deploy settings.
+ *
+ */
+
+return [
+ // See http://security.stackexchange.com/a/59550/74909 for the inspiration for our throttling system
+ 'throttles' => [
+ 'check_username_request' => [
+ 'method' => 'ip',
+ 'interval' => 3600,
+ 'delays' => [
+ 40 => 1000
+ ]
+ ],
+ 'password_reset_request' => [
+ 'method' => 'ip',
+ 'interval' => 3600,
+ 'delays' => [
+ 2 => 5,
+ 3 => 10,
+ 4 => 20,
+ 5 => 40,
+ 6 => 80,
+ 7 => 600
+ ]
+ ],
+ 'registration_attempt' => [
+ 'method' => 'ip',
+ 'interval' => 3600,
+ 'delays' => [
+ 2 => 5,
+ 3 => 10,
+ 4 => 20,
+ 5 => 40,
+ 6 => 80,
+ 7 => 600
+ ]
+ ],
+ 'sign_in_attempt' => [
+ 'method' => 'ip',
+ 'interval' => 3600,
+ 'delays' => [
+ 4 => 5,
+ 5 => 10,
+ 6 => 20,
+ 7 => 40,
+ 8 => 80,
+ 9 => 600
+ ]
+ ],
+ 'verification_request' => [
+ 'method' => 'ip',
+ 'interval' => 3600,
+ 'delays' => [
+ 2 => 5,
+ 3 => 10,
+ 4 => 20,
+ 5 => 40,
+ 6 => 80,
+ 7 => 600
+ ]
+ ]
+ ]
+];
diff --git a/main/app/sprinkles/account/factories/Users.php b/main/app/sprinkles/account/factories/Users.php index 2b5a3ca..eb49f42 100644 --- a/main/app/sprinkles/account/factories/Users.php +++ b/main/app/sprinkles/account/factories/Users.php @@ -1,23 +1,23 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -use League\FactoryMuffin\Faker\Facade as Faker; - -/** - * General factory for the User Model - */ -$fm->define('UserFrosting\Sprinkle\Account\Database\Models\User')->setDefinitions([ - 'user_name' => Faker::unique()->firstNameMale(), - 'first_name' => Faker::firstNameMale(), - 'last_name' => Faker::firstNameMale(), - 'email' => Faker::unique()->email(), - 'locale' => 'en_US', - 'flag_verified' => 1, - 'flag_enabled' => 1, - 'password' => Faker::password() -]); +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+use League\FactoryMuffin\Faker\Facade as Faker;
+
+/**
+ * General factory for the User Model
+ */
+$fm->define('UserFrosting\Sprinkle\Account\Database\Models\User')->setDefinitions([
+ 'user_name' => Faker::unique()->firstNameMale(),
+ 'first_name' => Faker::firstNameMale(),
+ 'last_name' => Faker::firstNameMale(),
+ 'email' => Faker::unique()->email(),
+ 'locale' => 'en_US',
+ 'flag_verified' => 1,
+ 'flag_enabled' => 1,
+ 'password' => Faker::password()
+]);
diff --git a/main/app/sprinkles/account/locale/ar/messages.php b/main/app/sprinkles/account/locale/ar/messages.php index 7f4506d..8f5485f 100644 --- a/main/app/sprinkles/account/locale/ar/messages.php +++ b/main/app/sprinkles/account/locale/ar/messages.php @@ -1,176 +1,176 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Modern Standard Arabic message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\ar - * @author Alexander Weissman and Abdullah Seba - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "الحساب", - - "ACCESS_DENIED" => "يبدو أنك لا تملك صلاحية للقيام بذلك", - - "DISABLED" => "هذا الحساب معطل يمكنك الاتصال بنا للحصول على مزيد من المعلومات", - - "EMAIL_UPDATED" => "تم تجديد البريد الإلكتروني بالحساب", - - "INVALID" => "هذا الحساب غير موجود قد تم حذفه يمكنك الاتصا بنا للحصول على مزيد من المعلومات", - - "MASTER_NOT_EXISTS" => "لا يمكنك تسجيل حساب جديد حتى تم إنشاء الحساب الرئيسي", - "MY" => "حسابي", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "تم اختراق جلسنك يجب عليك الخروج على كافة الأجهزة، ثم تسجيل الدخول مرة أخرى والتأكد من أن المعلومات الخاصة بك لم يعبث بها", - "TITLE" => "من الممكن أن حسابك قد اخترق", - "TEXT" => "ربما استخدم شخص معلومات التسجيل الدخول للدخول إلى هذه الصفحة. لسلامتك، تم انتهاء جميع الجلسات يرجا <a href=\"{{url}}\">التسجيل مرة اخرى</a> وتحقق من حسابك بسبب النشاط الغريب قد ترغب في تغيير كلمة المرور" - ], - - "SESSION_EXPIRED" => "انتهت جلستك تستطيع تسجيل الدخول مرة أخرى", - - "SETTINGS" => [ - "@TRANSLATION" => "إعدادات الحساب", - "DESCRIPTION" => "غير إعدادات حسابك، بما في ذلك البريد الإلكتروني، واسم وكلمة المرور -", - "UPDATED" => "تم تجديد إعدادات الحساب" - ], - - "TOOLS" => "أدوات الحساب", - - "UNVERIFIED" => "لم يتم التحقق من حسابك بعد افحص في رسائل البريد الإلكتروني و ملف البريد المزعج للحصول على تعليمات تفعيل الحساب", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "لقد أرسلنا رابط جديدا لتحقق عبر البريد الإلكتروني إلى {{email}} افحص في رسائل البريد الإلكتروني و ملف البريد المزعج", - "RESEND" => "إعادة ارسال بريد التحقق", - "COMPLETE" => "لقد تم التحقق من حسابك بنجاح يمكنك الآن تسجيل الدخول", - "EMAIL" => "ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل، و سوف نرسل البريد الإلكتروني لتحقق مرة أخرى", - "PAGE" => "إعادة إرسال البريد الإلكتروني التحقق من حسابك الجديد", - "SEND" => "ارسل رابط للتحقق عبر البريد الالكتروني", - "TOKEN_NOT_FOUND" => "رمز التحقق غير موجود أو تم تحقق الحساب من قبل", - ] - ], - - "EMAIL" => [ - "INVALID" => "لا يوجد حساب ل <strong>{{email}}</strong>", - "IN_USE" => "البريد الإلكتروني <strong>{{email}}</strong> قيد الاستخدام" - ], - - "FIRST_NAME" => "الاسم الاول", - - "HEADER_MESSAGE_ROOT" => "تسجيل الدخول باسم المستخدم ROOT", - - "LAST_NAME" => "اسم العائلة", - - "LOCALEACCOUNT" => "اللغة التي تستخدم لحسابك", - - "LOGIN" => [ - "@TRANSLATION" => "تسجيل الدخول", - - "ALREADY_COMPLETE" => "انت بالفعل داخل", - "SOCIAL" => "أو الدخول مع", - "REQUIRED" => "عذرا، يجب عليك تسجيل الدخول للوصول إلى هذا المكان" - ], - - "LOGOUT" => "تسجيل الخروج", - - "NAME" => "اسم", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "سجل الدخول إلى حسابك في {{site_name}} أو سجيل للحصول على حساب جديد", - "SUBTITLE" => "التسجيل مجانا أو قم بتسجيل الدخول باستخدام حساب موجود", - "TITLE" => "هيا نبدأ", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "كلمه المرور", - - "BETWEEN" => "ما بين {{min}}-{{max}} حروف", - - "CONFIRM" => "تأكيد كلمة المرور", - "CONFIRM_CURRENT" => "تأكيد كلمه المرور الحالي", - "CONFIRM_NEW" => "تأكيد كلمة المرور الجديدة", - "CONFIRM_NEW_EXPLAIN" => "إعادة إدخال كلمة المرور الجديدة", - "CONFIRM_NEW_HELP" => "لازم إذا كان المطلوب اختيار كلمة مرور جديدة", - "CURRENT" => "كلمة المرور الحالية", - "CURRENT_EXPLAIN" => "يجب عليك تأكيد كلمة المرور الحالية لإجراء التغييرات", - - "FORGOTTEN" => "كلمه المرور منسية", - "FORGET" => [ - "@TRANSLATION" => "لقد نسيت كلمة المرور", - - "COULD_NOT_UPDATE" => "لا يمكن تحديث كلمة المرور", - "EMAIL" => "ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل وسوف نرسل تعليمات لإعادة تعيين كلمة المرور", - "EMAIL_SEND" => "أرسل رابط تعيين كلمة المرور عبر البريد الالكتروني", - "INVALID" => "لم يتم العثور على إعادة تعيين كلمة المرور، أو انتهت صلاحية رابط حاول <a href=\"{{url}}\">إعادة تقديم طلبك<a>", - "PAGE" => "الحصول على رابط لإعادة تعيين كلمة المرور", - "REQUEST_CANNED" => "إلغاء طلب كلمة المرور", - "REQUEST_SENT" => "إذا تطابق البريد الإلكتروني <strong>{{email}}</strong> حسابا في نظامنا، فسيتم إرسال رابط إعادة تعيين كلمة المرور إلى <strong>{{email}}</strong>." - ], - - "RESET" => [ - "@TRANSLATION" => "إعادة تعيين كلمة المرور", - "CHOOSE" => "اختيار كلمة مرور جديدة للتواصل", - "PAGE" => "اختيار كلمة مرور جديدة لحسابك", - "SEND" => "تعيين كلمة المرور الجديدة وتسجيل الدخول" - ], - - "HASH_FAILED" => "فشلت التجزئة كلمة المرور يرجى الاتصال بمسؤول الموقع", - "INVALID" => "كلمة مرور الحالية لا تتطابق مع ما لدينا", - "NEW" => "كلمة مرور الجديدة", - "NOTHING_TO_UPDATE" => "لا يمكنك تحديث مع نفس كلمة مرور", - "UPDATED" => "جدد كلمة مرور", - - "CREATE" => [ - "@TRANSLATION" => "إنشاء كلمة مرور", - "PAGE" => "اختر كلمة مرور لحسابك الجديد", - "SET" => "تعيين كلمة المرور وتسجيل الدخول" - ] - ], - - "REGISTER" => "تسجيل", - "REGISTER_ME" => "سجلني", - "SIGN_IN_HERE" => "هل لديك حساب؟ <a href=\"{{url}}\">تسجيل الدخول هنا</a>", - - "REGISTRATION" => [ - "BROKEN" => "نحن آسفون، هناك مشكلة مع عملية تسجيل الحساب يرجى الاتصال بنا مباشرة للحصول على المساعدة", - "COMPLETE_TYPE1" => "لقد سجلت بنجاح يمكنك الآن تسجيل الدخول", - "COMPLETE_TYPE2" => "لقد سجلت بنجاح سوف تتلقى قريبا رسالة التحقق تحتوي على رابط لتفعيل حسابك لن تكون قادرا على تسجيل الدخول حتى الانتهاء من هذه الخطوة", - "DISABLED" => "عذرا، لقد تم تعطيل تسجيل اي حساب", - "LOGOUT" => "لا يمكنك التسجيل للحصول على حساب أثناء تسجيل الدخول", - "WELCOME" => "التسجيل سريع وبسيط" - ], - - "RATE_LIMIT_EXCEEDED" => "تم تجاوز الحد عددا لهذا الإجراء يجب الانتظار {{delay}} ثواني قبل القيام بمحاولة أخرى", - "REMEMBER_ME" => "تذكرنى", - "REMEMBER_ME_ON_COMPUTER" => "تذكرني على هذا الحاسوب (غير مستحسن للحواسب العامة)", - - "SIGNIN" => "تسجيل الدخول", - "SIGNIN_OR_REGISTER" => "تسجيل الدخول أو التسجيل", - "SIGNUP" => "تسجيل", - - "TOS" => "الأحكام والشروط", - "TOS_AGREEMENT" => "من خلال تسجيل حساب جديد في {{site_title}}, انت تقبل <a {{link_attributes | raw}}>الأحكام والشروط</a>", - "TOS_FOR" => "الأحكام والشروط ل {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "اسم المستخدم", - - "CHOOSE" => "اختيار اسم مستخدم فريد", - "INVALID" => "اسم المستخدم غير صالح", - "IN_USE" => "اسم المستخدم <strong>{{user_name}}</strong> قيد الاستخدام" - ], - - "USER_ID_INVALID" => "عدم وجود هوية المستخدم المطلوب", - "USER_OR_EMAIL_INVALID" => "اسم المستخدم أو عنوان البريد الإلكتروني غير صالح", - "USER_OR_PASS_INVALID" => "اسم المستخدم أو كلمة المرور غير صالحة", - - "WELCOME" => "مرحبا بعودتك, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Modern Standard Arabic message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\ar
+ * @author Alexander Weissman and Abdullah Seba
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "الحساب",
+
+ "ACCESS_DENIED" => "يبدو أنك لا تملك صلاحية للقيام بذلك",
+
+ "DISABLED" => "هذا الحساب معطل يمكنك الاتصال بنا للحصول على مزيد من المعلومات",
+
+ "EMAIL_UPDATED" => "تم تجديد البريد الإلكتروني بالحساب",
+
+ "INVALID" => "هذا الحساب غير موجود قد تم حذفه يمكنك الاتصا بنا للحصول على مزيد من المعلومات",
+
+ "MASTER_NOT_EXISTS" => "لا يمكنك تسجيل حساب جديد حتى تم إنشاء الحساب الرئيسي",
+ "MY" => "حسابي",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "تم اختراق جلسنك يجب عليك الخروج على كافة الأجهزة، ثم تسجيل الدخول مرة أخرى والتأكد من أن المعلومات الخاصة بك لم يعبث بها",
+ "TITLE" => "من الممكن أن حسابك قد اخترق",
+ "TEXT" => "ربما استخدم شخص معلومات التسجيل الدخول للدخول إلى هذه الصفحة. لسلامتك، تم انتهاء جميع الجلسات يرجا <a href=\"{{url}}\">التسجيل مرة اخرى</a> وتحقق من حسابك بسبب النشاط الغريب قد ترغب في تغيير كلمة المرور"
+ ],
+
+ "SESSION_EXPIRED" => "انتهت جلستك تستطيع تسجيل الدخول مرة أخرى",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "إعدادات الحساب",
+ "DESCRIPTION" => "غير إعدادات حسابك، بما في ذلك البريد الإلكتروني، واسم وكلمة المرور
+",
+ "UPDATED" => "تم تجديد إعدادات الحساب"
+ ],
+
+ "TOOLS" => "أدوات الحساب",
+
+ "UNVERIFIED" => "لم يتم التحقق من حسابك بعد افحص في رسائل البريد الإلكتروني و ملف البريد المزعج للحصول على تعليمات تفعيل الحساب",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "لقد أرسلنا رابط جديدا لتحقق عبر البريد الإلكتروني إلى {{email}} افحص في رسائل البريد الإلكتروني و ملف البريد المزعج",
+ "RESEND" => "إعادة ارسال بريد التحقق",
+ "COMPLETE" => "لقد تم التحقق من حسابك بنجاح يمكنك الآن تسجيل الدخول",
+ "EMAIL" => "ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل، و سوف نرسل البريد الإلكتروني لتحقق مرة أخرى",
+ "PAGE" => "إعادة إرسال البريد الإلكتروني التحقق من حسابك الجديد",
+ "SEND" => "ارسل رابط للتحقق عبر البريد الالكتروني",
+ "TOKEN_NOT_FOUND" => "رمز التحقق غير موجود أو تم تحقق الحساب من قبل",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "لا يوجد حساب ل <strong>{{email}}</strong>",
+ "IN_USE" => "البريد الإلكتروني <strong>{{email}}</strong> قيد الاستخدام"
+ ],
+
+ "FIRST_NAME" => "الاسم الاول",
+
+ "HEADER_MESSAGE_ROOT" => "تسجيل الدخول باسم المستخدم ROOT",
+
+ "LAST_NAME" => "اسم العائلة",
+
+ "LOCALEACCOUNT" => "اللغة التي تستخدم لحسابك",
+
+ "LOGIN" => [
+ "@TRANSLATION" => "تسجيل الدخول",
+
+ "ALREADY_COMPLETE" => "انت بالفعل داخل",
+ "SOCIAL" => "أو الدخول مع",
+ "REQUIRED" => "عذرا، يجب عليك تسجيل الدخول للوصول إلى هذا المكان"
+ ],
+
+ "LOGOUT" => "تسجيل الخروج",
+
+ "NAME" => "اسم",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "سجل الدخول إلى حسابك في {{site_name}} أو سجيل للحصول على حساب جديد",
+ "SUBTITLE" => "التسجيل مجانا أو قم بتسجيل الدخول باستخدام حساب موجود",
+ "TITLE" => "هيا نبدأ",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "كلمه المرور",
+
+ "BETWEEN" => "ما بين {{min}}-{{max}} حروف",
+
+ "CONFIRM" => "تأكيد كلمة المرور",
+ "CONFIRM_CURRENT" => "تأكيد كلمه المرور الحالي",
+ "CONFIRM_NEW" => "تأكيد كلمة المرور الجديدة",
+ "CONFIRM_NEW_EXPLAIN" => "إعادة إدخال كلمة المرور الجديدة",
+ "CONFIRM_NEW_HELP" => "لازم إذا كان المطلوب اختيار كلمة مرور جديدة",
+ "CURRENT" => "كلمة المرور الحالية",
+ "CURRENT_EXPLAIN" => "يجب عليك تأكيد كلمة المرور الحالية لإجراء التغييرات",
+
+ "FORGOTTEN" => "كلمه المرور منسية",
+ "FORGET" => [
+ "@TRANSLATION" => "لقد نسيت كلمة المرور",
+
+ "COULD_NOT_UPDATE" => "لا يمكن تحديث كلمة المرور",
+ "EMAIL" => "ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل وسوف نرسل تعليمات لإعادة تعيين كلمة المرور",
+ "EMAIL_SEND" => "أرسل رابط تعيين كلمة المرور عبر البريد الالكتروني",
+ "INVALID" => "لم يتم العثور على إعادة تعيين كلمة المرور، أو انتهت صلاحية رابط حاول <a href=\"{{url}}\">إعادة تقديم طلبك<a>",
+ "PAGE" => "الحصول على رابط لإعادة تعيين كلمة المرور",
+ "REQUEST_CANNED" => "إلغاء طلب كلمة المرور",
+ "REQUEST_SENT" => "إذا تطابق البريد الإلكتروني <strong>{{email}}</strong> حسابا في نظامنا، فسيتم إرسال رابط إعادة تعيين كلمة المرور إلى <strong>{{email}}</strong>."
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "إعادة تعيين كلمة المرور",
+ "CHOOSE" => "اختيار كلمة مرور جديدة للتواصل",
+ "PAGE" => "اختيار كلمة مرور جديدة لحسابك",
+ "SEND" => "تعيين كلمة المرور الجديدة وتسجيل الدخول"
+ ],
+
+ "HASH_FAILED" => "فشلت التجزئة كلمة المرور يرجى الاتصال بمسؤول الموقع",
+ "INVALID" => "كلمة مرور الحالية لا تتطابق مع ما لدينا",
+ "NEW" => "كلمة مرور الجديدة",
+ "NOTHING_TO_UPDATE" => "لا يمكنك تحديث مع نفس كلمة مرور",
+ "UPDATED" => "جدد كلمة مرور",
+
+ "CREATE" => [
+ "@TRANSLATION" => "إنشاء كلمة مرور",
+ "PAGE" => "اختر كلمة مرور لحسابك الجديد",
+ "SET" => "تعيين كلمة المرور وتسجيل الدخول"
+ ]
+ ],
+
+ "REGISTER" => "تسجيل",
+ "REGISTER_ME" => "سجلني",
+ "SIGN_IN_HERE" => "هل لديك حساب؟ <a href=\"{{url}}\">تسجيل الدخول هنا</a>",
+
+ "REGISTRATION" => [
+ "BROKEN" => "نحن آسفون، هناك مشكلة مع عملية تسجيل الحساب يرجى الاتصال بنا مباشرة للحصول على المساعدة",
+ "COMPLETE_TYPE1" => "لقد سجلت بنجاح يمكنك الآن تسجيل الدخول",
+ "COMPLETE_TYPE2" => "لقد سجلت بنجاح سوف تتلقى قريبا رسالة التحقق تحتوي على رابط لتفعيل حسابك لن تكون قادرا على تسجيل الدخول حتى الانتهاء من هذه الخطوة",
+ "DISABLED" => "عذرا، لقد تم تعطيل تسجيل اي حساب",
+ "LOGOUT" => "لا يمكنك التسجيل للحصول على حساب أثناء تسجيل الدخول",
+ "WELCOME" => "التسجيل سريع وبسيط"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "تم تجاوز الحد عددا لهذا الإجراء يجب الانتظار {{delay}} ثواني قبل القيام بمحاولة أخرى",
+ "REMEMBER_ME" => "تذكرنى",
+ "REMEMBER_ME_ON_COMPUTER" => "تذكرني على هذا الحاسوب (غير مستحسن للحواسب العامة)",
+
+ "SIGNIN" => "تسجيل الدخول",
+ "SIGNIN_OR_REGISTER" => "تسجيل الدخول أو التسجيل",
+ "SIGNUP" => "تسجيل",
+
+ "TOS" => "الأحكام والشروط",
+ "TOS_AGREEMENT" => "من خلال تسجيل حساب جديد في {{site_title}}, انت تقبل <a {{link_attributes | raw}}>الأحكام والشروط</a>",
+ "TOS_FOR" => "الأحكام والشروط ل {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "اسم المستخدم",
+
+ "CHOOSE" => "اختيار اسم مستخدم فريد",
+ "INVALID" => "اسم المستخدم غير صالح",
+ "IN_USE" => "اسم المستخدم <strong>{{user_name}}</strong> قيد الاستخدام"
+ ],
+
+ "USER_ID_INVALID" => "عدم وجود هوية المستخدم المطلوب",
+ "USER_OR_EMAIL_INVALID" => "اسم المستخدم أو عنوان البريد الإلكتروني غير صالح",
+ "USER_OR_PASS_INVALID" => "اسم المستخدم أو كلمة المرور غير صالحة",
+
+ "WELCOME" => "مرحبا بعودتك, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/ar/validate.php b/main/app/sprinkles/account/locale/ar/validate.php index 10543d0..0d6ff04 100644 --- a/main/app/sprinkles/account/locale/ar/validate.php +++ b/main/app/sprinkles/account/locale/ar/validate.php @@ -1,18 +1,18 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Modern Standard Arabic message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\ar - * @author Alexander Weissman and Abdullah Seba - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "يجب أن تكون كلمة المرور وكلمة المرور التأكيدية نفس" - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Modern Standard Arabic message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\ar
+ * @author Alexander Weissman and Abdullah Seba
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "يجب أن تكون كلمة المرور وكلمة المرور التأكيدية نفس"
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/de_DE/messages.php b/main/app/sprinkles/account/locale/de_DE/messages.php index ef3e47e..a9d1264 100644 --- a/main/app/sprinkles/account/locale/de_DE/messages.php +++ b/main/app/sprinkles/account/locale/de_DE/messages.php @@ -1,188 +1,188 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * German message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\de - * @author X-Anonymous-Y - * @author kevinrombach - * @author splitt3r - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Konto", - - "ACCESS_DENIED" => "Hmm, sieht aus als hätten Sie keine Berechtigung, um dies zu tun.", - - "DISABLED" => "Dieses Konto wurde deaktiviert. Bitte Kontaktieren Sie uns für weitere Informationen.", - - "EMAIL_UPDATED" => "E-Mail-Adresse aktualisiert.", - - "INVALID" => "Dieses Konto existiert nicht. Es wurde möglicherweise gelöscht. Bitte kontaktieren Sie uns für weitere Informationen.", - - "MASTER_NOT_EXISTS" => "Sie können kein neues Konto anlegen solange kein Root-Konto angelegt wurde!", - "MY" => "Mein Konto", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Ihre Sitzung wurde beeinträchtigt. Sie sollten sich auf allen Geräten abmelden, sich dann wieder anmelden und sicherstellen, dass Ihre Daten nicht manipuliert wurden.", - "TITLE" => "Ihr Konto wurde möglicherweise beeinträchtigt", - "TEXT" => "Möglicherweise ist es jemandem gelungen, Ihren Zugang zu dieser Seite zu übernehmen. Aus Sicherheitsgründen wurden Sie überall abgemeldet. Bitte <a href=\"{{url}}\">melden Sie sich neu an</a> und untersuchen Sie das Konto nach verdächtigen Aktivitäten. Außerdem sollten Sie Ihr Passwort ändern." - ], - "SESSION_EXPIRED" => "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.", - - "SETTINGS" => [ - "@TRANSLATION" => "Kontoeinstellungen", - "DESCRIPTION" => "Aktualisieren Sie Ihre Kontoeinstellungen, einschließlich E-Mail, Name und Passwort.", - "UPDATED" => "Kontoeinstellungen aktualisiert" - ], - - "TOOLS" => "Konto-Werkzeuge", - - "UNVERIFIED" => "Ihr Konto wurde noch nicht bestätigt. Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Konto-Aktivierungsanleitung.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Wir haben einen neuen Bestätigungslink an {{email}} gesendet. Überprüfen Sie Ihr E-Mail/Spam-Ordner oder versuchen Sie es später noch einmal.", - "RESEND" => "Bestätigungsmail erneut senden", - "COMPLETE" => "Sie haben Ihr Konto erfolgreich Verifiziert. Sie können sich jetzt anmelden.", - "EMAIL" => "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben, Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Bestätigungs-E-Mail.", - "PAGE" => "Senden Sie die Bestätigungs-E-Mail erneut für Ihr neues Konto.", - "SEND" => "Bestätigungslink erneut per E-Mail zusenden", - "TOKEN_NOT_FOUND" => "Verifizierungstoken existiert nicht / Konto wurde bereits verifiziert" - ] - ], - - "EMAIL" => [ - "INVALID" => "Es gibt kein Konto für <strong>{{email}}</strong>.", - "IN_USE" => "Die E-Mail Adresse <strong>{{email}}</strong> wird bereits verwendet.", - "VERIFICATION_REQUIRED" => "E-Mail (Bestätigung benötigt - Benutzen Sie eine echte E-Mail Adresse!)" - ], - - "EMAIL_OR_USERNAME" => "Benutzername oder E-mail Adresse", - - "FIRST_NAME" => "Vorname", - - "HEADER_MESSAGE_ROOT" => "Sie sind als Root-Benutzer angemeldet.", - - "LAST_NAME" => "Nachname", - - "LOCALE" => [ - "ACCOUNT" => "Die Sprache und das Gebietsschema für Ihr Konto", - "INVALID" => "<strong>{{locale}}</strong> ist kein gültiges Gebietsschema." - ], - - "LOGIN" => [ - "@TRANSLATION" => "Anmelden", - "ALREADY_COMPLETE" => "Sie sind bereits eingeloggt!", - "SOCIAL" => "Oder loggen Sie sich ein mit", - "REQUIRED" => "Sorry, Sie müssen angemeldet sein. Um auf diese Ressource zugreifen zu können." - ], - - "LOGOUT" => "Ausloggen", - - "NAME" => "Name", - - "NAME_AND_EMAIL" => "Name und E-Mail", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Melden Sie sich in Ihr {{site_name}} Konto an oder registrieren Sie sich für ein neues Konto.", - "SUBTITLE" => "Registrieren Sie sich kostenlos oder melden Sie sich mit einem bestehenden Konto an.", - "TITLE" => "Lass uns anfangen!" - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Passwort", - - "BETWEEN" => "Zwischen {{min}}-{{max}} Zeichen", - - "CONFIRM" => "Bestätige das Passwort", - "CONFIRM_CURRENT" => "Bitte bestätige dein jetziges Passwort", - "CONFIRM_NEW" => "Neues Passwort bestätigen", - "CONFIRM_NEW_EXPLAIN" => "Geben Sie Ihr neues Passwort erneut ein", - "CONFIRM_NEW_HELP" => "Erforderlich, wenn Sie ein neues Passwort wählen", - "CREATE" => [ - "@TRANSLATION" => "Passwort setzen", - "PAGE" => "Setzen Sie ein Passwort für den Account.", - "SET" => "Passwort setzen und anmelden" - ], - "CURRENT" => "Aktuelles Passwort", - "CURRENT_EXPLAIN" => "Sie müssen Ihr aktuelles Passwort bestätigen, um Änderungen vorzunehmen", - - "FORGOTTEN" => "Passwort vergessen", - "FORGET" => [ - "@TRANSLATION" => "Ich habe mein Passwort vergessen", - - "COULD_NOT_UPDATE" => "Das Passwort konnte nicht aktualisiert werden.", - "EMAIL" => "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben. Ein Link mit der Anweisungen zum Zurücksetzen Ihres Passworts wird Ihnen per E-Mail zugeschickt.", - "EMAIL_SEND" => "Neue Passwort zurücksetzen E-Mail senden", - "INVALID" => "Diese Anforderung zum Zurücksetzen des Passworts wurde nicht gefunden oder ist abgelaufen.Bitte versuchen Sie <a href=\'{{url}}\'>Ihre Anfrage erneut einzureichen<a>.", - "PAGE" => "Holen Sie sich einen Link, um Ihr Passwort zurückzusetzen.", - "REQUEST_CANNED" => "Verlorene Passwortanforderung abgebrochen.", - "REQUEST_SENT" => "Wenn die E-Mail <strong>{{email}}</strong> mit einem Account in unserem System übereinstimmt, wird ein Passwort-Reset-Link an <strong>{{email}}</strong> gesendet." - ], - - "HASH_FAILED" => "Passwort Hashing fehlgeschlagen. Bitte kontaktieren Sie einen Administrator.", - "INVALID" => "Das aktuelle Passwort stimmt nicht mit dem Datensatz überein", - "NEW" => "Neues Passwort", - "NOTHING_TO_UPDATE" => "Sie können nicht das gleiche Passwort zum Aktualisieren verwenden", - - "RESET" => [ - "@TRANSLATION" => "Passwort zurücksetzen", - "CHOOSE" => "Bitte wählen Sie ein neues Passwort, um fortzufahren.", - "PAGE" => "Wählen Sie ein neues Passwort für Ihr Konto.", - "SEND" => "Neues Passwort festlegen und anmelden" - ], - - "UPDATED" => "Konto Passwort aktualisiert" - ], - - "PROFILE" => [ - "SETTINGS" => "Profileinstellungen", - "UPDATED" => "Profileinstellungen aktualisiert" - ], - - "RATE_LIMIT_EXCEEDED" => "Die grenze für diese Maßnahme wurde überschritten. Sie müssen weitere {{delay}} Sekunden warten, bevor Sie einen weiteren Versuch machen dürfen.", - - "REGISTER" => "Registrieren", - "REGISTER_ME" => "Melden Sie mich an", - "REGISTRATION" => [ - "BROKEN" => "Es tut uns leid, es gibt ein Problem mit unserer Registrierung. Bitte kontaktieren Sie uns direkt für Hilfe.", - "COMPLETE_TYPE1" => "Sie haben sich erfolgreich registriert. Sie können sich jetzt anmelden.", - "COMPLETE_TYPE2" => "Sie haben sich erfolgreich registriert. Sie erhalten in Kürze eine Bestätigungs-E-Mail mit einem Link zur Aktivierung Ihres Kontos. Sie können sich nicht anmelden, bis Sie diesen Schritt abgeschlossen haben.", - "DISABLED" => "Es tut uns leid, Die Registrierung des Kontos ist deaktiviert.", - "LOGOUT" => "Es tut uns leid, Sie können kein neues Konto registrieren, während Sie angemeldet sind. Bitte melden Sie sich zuerst ab.", - "WELCOME" => "Die Registrierung ist schnell und einfach." - ], - "REMEMBER_ME" => "Erinnere dich an mich!", - "REMEMBER_ME_ON_COMPUTER" => "Erinnere dich an mich auf diesem Computer (nicht für öffentliche Computer empfohlen)", - - "SIGN_IN_HERE" => "Sie haben bereits einen Account? <a href=\"{{url}}\">Melden Sie sich hier an.</a>", - "SIGNIN" => "Anmelden", - "SIGNIN_OR_REGISTER" => "Anmelden oder registrieren", - "SIGNUP" => "Anmelden", - - "TOS" => "Geschäftsbedingungen", - "TOS_AGREEMENT" => "Durch die Registrierung eines Kontos auf {{site_title}} akzeptieren Sie die <a {{link_attributes | raw}}> Bedingungen </a>.", - "TOS_FOR" => "Allgemeine Geschäftsbedingungen für {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Benutzername", - - "CHOOSE" => "Wählen Sie einen eindeutigen Benutzernamen", - "INVALID" => "Ungültiger Benutzername", - "IN_USE" => "Benutzername <strong>{{user_name}}</strong> wird bereits verwendet.", - "NOT_AVAILABLE" => "Benutzername <strong>{{user_name}}</strong> ist nicht verfügbar. Wähle einen anderen Namen, der klicken Sie auf 'vorschlagen'." - ], - - "USER_ID_INVALID" => "Die angeforderte Benutzer-ID existiert nicht.", - "USER_OR_EMAIL_INVALID" => "Benutzername oder E-Mail-Adresse ist ungültig.", - "USER_OR_PASS_INVALID" => "Benutzername oder Passwort ist ungültig.", - - "WELCOME" => "Willkommen zurück, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * German message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\de
+ * @author X-Anonymous-Y
+ * @author kevinrombach
+ * @author splitt3r
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Konto",
+
+ "ACCESS_DENIED" => "Hmm, sieht aus als hätten Sie keine Berechtigung, um dies zu tun.",
+
+ "DISABLED" => "Dieses Konto wurde deaktiviert. Bitte Kontaktieren Sie uns für weitere Informationen.",
+
+ "EMAIL_UPDATED" => "E-Mail-Adresse aktualisiert.",
+
+ "INVALID" => "Dieses Konto existiert nicht. Es wurde möglicherweise gelöscht. Bitte kontaktieren Sie uns für weitere Informationen.",
+
+ "MASTER_NOT_EXISTS" => "Sie können kein neues Konto anlegen solange kein Root-Konto angelegt wurde!",
+ "MY" => "Mein Konto",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "Ihre Sitzung wurde beeinträchtigt. Sie sollten sich auf allen Geräten abmelden, sich dann wieder anmelden und sicherstellen, dass Ihre Daten nicht manipuliert wurden.",
+ "TITLE" => "Ihr Konto wurde möglicherweise beeinträchtigt",
+ "TEXT" => "Möglicherweise ist es jemandem gelungen, Ihren Zugang zu dieser Seite zu übernehmen. Aus Sicherheitsgründen wurden Sie überall abgemeldet. Bitte <a href=\"{{url}}\">melden Sie sich neu an</a> und untersuchen Sie das Konto nach verdächtigen Aktivitäten. Außerdem sollten Sie Ihr Passwort ändern."
+ ],
+ "SESSION_EXPIRED" => "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Kontoeinstellungen",
+ "DESCRIPTION" => "Aktualisieren Sie Ihre Kontoeinstellungen, einschließlich E-Mail, Name und Passwort.",
+ "UPDATED" => "Kontoeinstellungen aktualisiert"
+ ],
+
+ "TOOLS" => "Konto-Werkzeuge",
+
+ "UNVERIFIED" => "Ihr Konto wurde noch nicht bestätigt. Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Konto-Aktivierungsanleitung.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "Wir haben einen neuen Bestätigungslink an {{email}} gesendet. Überprüfen Sie Ihr E-Mail/Spam-Ordner oder versuchen Sie es später noch einmal.",
+ "RESEND" => "Bestätigungsmail erneut senden",
+ "COMPLETE" => "Sie haben Ihr Konto erfolgreich Verifiziert. Sie können sich jetzt anmelden.",
+ "EMAIL" => "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben, Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Bestätigungs-E-Mail.",
+ "PAGE" => "Senden Sie die Bestätigungs-E-Mail erneut für Ihr neues Konto.",
+ "SEND" => "Bestätigungslink erneut per E-Mail zusenden",
+ "TOKEN_NOT_FOUND" => "Verifizierungstoken existiert nicht / Konto wurde bereits verifiziert"
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "Es gibt kein Konto für <strong>{{email}}</strong>.",
+ "IN_USE" => "Die E-Mail Adresse <strong>{{email}}</strong> wird bereits verwendet.",
+ "VERIFICATION_REQUIRED" => "E-Mail (Bestätigung benötigt - Benutzen Sie eine echte E-Mail Adresse!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Benutzername oder E-mail Adresse",
+
+ "FIRST_NAME" => "Vorname",
+
+ "HEADER_MESSAGE_ROOT" => "Sie sind als Root-Benutzer angemeldet.",
+
+ "LAST_NAME" => "Nachname",
+
+ "LOCALE" => [
+ "ACCOUNT" => "Die Sprache und das Gebietsschema für Ihr Konto",
+ "INVALID" => "<strong>{{locale}}</strong> ist kein gültiges Gebietsschema."
+ ],
+
+ "LOGIN" => [
+ "@TRANSLATION" => "Anmelden",
+ "ALREADY_COMPLETE" => "Sie sind bereits eingeloggt!",
+ "SOCIAL" => "Oder loggen Sie sich ein mit",
+ "REQUIRED" => "Sorry, Sie müssen angemeldet sein. Um auf diese Ressource zugreifen zu können."
+ ],
+
+ "LOGOUT" => "Ausloggen",
+
+ "NAME" => "Name",
+
+ "NAME_AND_EMAIL" => "Name und E-Mail",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Melden Sie sich in Ihr {{site_name}} Konto an oder registrieren Sie sich für ein neues Konto.",
+ "SUBTITLE" => "Registrieren Sie sich kostenlos oder melden Sie sich mit einem bestehenden Konto an.",
+ "TITLE" => "Lass uns anfangen!"
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Passwort",
+
+ "BETWEEN" => "Zwischen {{min}}-{{max}} Zeichen",
+
+ "CONFIRM" => "Bestätige das Passwort",
+ "CONFIRM_CURRENT" => "Bitte bestätige dein jetziges Passwort",
+ "CONFIRM_NEW" => "Neues Passwort bestätigen",
+ "CONFIRM_NEW_EXPLAIN" => "Geben Sie Ihr neues Passwort erneut ein",
+ "CONFIRM_NEW_HELP" => "Erforderlich, wenn Sie ein neues Passwort wählen",
+ "CREATE" => [
+ "@TRANSLATION" => "Passwort setzen",
+ "PAGE" => "Setzen Sie ein Passwort für den Account.",
+ "SET" => "Passwort setzen und anmelden"
+ ],
+ "CURRENT" => "Aktuelles Passwort",
+ "CURRENT_EXPLAIN" => "Sie müssen Ihr aktuelles Passwort bestätigen, um Änderungen vorzunehmen",
+
+ "FORGOTTEN" => "Passwort vergessen",
+ "FORGET" => [
+ "@TRANSLATION" => "Ich habe mein Passwort vergessen",
+
+ "COULD_NOT_UPDATE" => "Das Passwort konnte nicht aktualisiert werden.",
+ "EMAIL" => "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben. Ein Link mit der Anweisungen zum Zurücksetzen Ihres Passworts wird Ihnen per E-Mail zugeschickt.",
+ "EMAIL_SEND" => "Neue Passwort zurücksetzen E-Mail senden",
+ "INVALID" => "Diese Anforderung zum Zurücksetzen des Passworts wurde nicht gefunden oder ist abgelaufen.Bitte versuchen Sie <a href=\'{{url}}\'>Ihre Anfrage erneut einzureichen<a>.",
+ "PAGE" => "Holen Sie sich einen Link, um Ihr Passwort zurückzusetzen.",
+ "REQUEST_CANNED" => "Verlorene Passwortanforderung abgebrochen.",
+ "REQUEST_SENT" => "Wenn die E-Mail <strong>{{email}}</strong> mit einem Account in unserem System übereinstimmt, wird ein Passwort-Reset-Link an <strong>{{email}}</strong> gesendet."
+ ],
+
+ "HASH_FAILED" => "Passwort Hashing fehlgeschlagen. Bitte kontaktieren Sie einen Administrator.",
+ "INVALID" => "Das aktuelle Passwort stimmt nicht mit dem Datensatz überein",
+ "NEW" => "Neues Passwort",
+ "NOTHING_TO_UPDATE" => "Sie können nicht das gleiche Passwort zum Aktualisieren verwenden",
+
+ "RESET" => [
+ "@TRANSLATION" => "Passwort zurücksetzen",
+ "CHOOSE" => "Bitte wählen Sie ein neues Passwort, um fortzufahren.",
+ "PAGE" => "Wählen Sie ein neues Passwort für Ihr Konto.",
+ "SEND" => "Neues Passwort festlegen und anmelden"
+ ],
+
+ "UPDATED" => "Konto Passwort aktualisiert"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Profileinstellungen",
+ "UPDATED" => "Profileinstellungen aktualisiert"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "Die grenze für diese Maßnahme wurde überschritten. Sie müssen weitere {{delay}} Sekunden warten, bevor Sie einen weiteren Versuch machen dürfen.",
+
+ "REGISTER" => "Registrieren",
+ "REGISTER_ME" => "Melden Sie mich an",
+ "REGISTRATION" => [
+ "BROKEN" => "Es tut uns leid, es gibt ein Problem mit unserer Registrierung. Bitte kontaktieren Sie uns direkt für Hilfe.",
+ "COMPLETE_TYPE1" => "Sie haben sich erfolgreich registriert. Sie können sich jetzt anmelden.",
+ "COMPLETE_TYPE2" => "Sie haben sich erfolgreich registriert. Sie erhalten in Kürze eine Bestätigungs-E-Mail mit einem Link zur Aktivierung Ihres Kontos. Sie können sich nicht anmelden, bis Sie diesen Schritt abgeschlossen haben.",
+ "DISABLED" => "Es tut uns leid, Die Registrierung des Kontos ist deaktiviert.",
+ "LOGOUT" => "Es tut uns leid, Sie können kein neues Konto registrieren, während Sie angemeldet sind. Bitte melden Sie sich zuerst ab.",
+ "WELCOME" => "Die Registrierung ist schnell und einfach."
+ ],
+ "REMEMBER_ME" => "Erinnere dich an mich!",
+ "REMEMBER_ME_ON_COMPUTER" => "Erinnere dich an mich auf diesem Computer (nicht für öffentliche Computer empfohlen)",
+
+ "SIGN_IN_HERE" => "Sie haben bereits einen Account? <a href=\"{{url}}\">Melden Sie sich hier an.</a>",
+ "SIGNIN" => "Anmelden",
+ "SIGNIN_OR_REGISTER" => "Anmelden oder registrieren",
+ "SIGNUP" => "Anmelden",
+
+ "TOS" => "Geschäftsbedingungen",
+ "TOS_AGREEMENT" => "Durch die Registrierung eines Kontos auf {{site_title}} akzeptieren Sie die <a {{link_attributes | raw}}> Bedingungen </a>.",
+ "TOS_FOR" => "Allgemeine Geschäftsbedingungen für {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Benutzername",
+
+ "CHOOSE" => "Wählen Sie einen eindeutigen Benutzernamen",
+ "INVALID" => "Ungültiger Benutzername",
+ "IN_USE" => "Benutzername <strong>{{user_name}}</strong> wird bereits verwendet.",
+ "NOT_AVAILABLE" => "Benutzername <strong>{{user_name}}</strong> ist nicht verfügbar. Wähle einen anderen Namen, der klicken Sie auf 'vorschlagen'."
+ ],
+
+ "USER_ID_INVALID" => "Die angeforderte Benutzer-ID existiert nicht.",
+ "USER_OR_EMAIL_INVALID" => "Benutzername oder E-Mail-Adresse ist ungültig.",
+ "USER_OR_PASS_INVALID" => "Benutzername oder Passwort ist ungültig.",
+
+ "WELCOME" => "Willkommen zurück, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/de_DE/validate.php b/main/app/sprinkles/account/locale/de_DE/validate.php index ea99fc0..33fa254 100644 --- a/main/app/sprinkles/account/locale/de_DE/validate.php +++ b/main/app/sprinkles/account/locale/de_DE/validate.php @@ -1,21 +1,21 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * German message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\de - * @author X-Anonymous-Y - * @author kevinrombach - * @author splitt3r - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Ihr Passwort und das Bestätigungspasswort müssen übereinstimmen.", - "USERNAME" => "Benutzernamen dürfen nur aus Kleinbuchstaben, Zahlen, '.', '-' und '_' bestehen." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * German message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\de
+ * @author X-Anonymous-Y
+ * @author kevinrombach
+ * @author splitt3r
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "Ihr Passwort und das Bestätigungspasswort müssen übereinstimmen.",
+ "USERNAME" => "Benutzernamen dürfen nur aus Kleinbuchstaben, Zahlen, '.', '-' und '_' bestehen."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/en_US/messages.php b/main/app/sprinkles/account/locale/en_US/messages.php index c57ba62..53306e4 100644 --- a/main/app/sprinkles/account/locale/en_US/messages.php +++ b/main/app/sprinkles/account/locale/en_US/messages.php @@ -1,183 +1,183 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * US English message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\en_US - * @author Alexander Weissman - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Account", - - "ACCESS_DENIED" => "Hmm, looks like you don't have permission to do that.", - - "DISABLED" => "This account has been disabled. Please contact us for more information.", - - "EMAIL_UPDATED" => "Account email updated", - - "INVALID" => "This account does not exist. It may have been deleted. Please contact us for more information.", - - "MASTER_NOT_EXISTS" => "You cannot register an account until the master account has been created!", - "MY" => "My Account", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Your session has been compromised. You should log out on all devices, then log back in and make sure that your data has not been tampered with.", - "TITLE" => "Your account may have been compromised", - "TEXT" => "Someone may have used your login information to acccess this page. For your safety, all sessions were logged out. Please <a href=\"{{url}}\">log in</a> and check your account for suspicious activity. You may also wish to change your password." - ], - "SESSION_EXPIRED" => "Your session has expired. Please sign in again.", - - "SETTINGS" => [ - "@TRANSLATION" => "Account settings", - "DESCRIPTION" => "Update your account settings, including email, name, and password.", - "UPDATED" => "Account settings updated" - ], - - "TOOLS" => "Account tools", - - "UNVERIFIED" => "Your account has not yet been verified. Check your emails / spam folder for account activation instructions.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "We have emailed a new verification link to {{email}}. Please check your inbox and spam folders for this email.", - "RESEND" => "Resend verification email", - "COMPLETE" => "You have successfully verified your account. You can now login.", - "EMAIL" => "Please enter the email address you used to sign up, and your verification email will be resent.", - "PAGE" => "Resend the verification email for your new account.", - "SEND" => "Email the verification link for my account", - "TOKEN_NOT_FOUND" => "Verification token does not exist / Account is already verified", - ] - ], - - "EMAIL" => [ - "INVALID" => "There is no account for <strong>{{email}}</strong>.", - "IN_USE" => "Email <strong>{{email}}</strong> is already in use.", - "VERIFICATION_REQUIRED" => "Email (verification required - use a real address!)" - ], - - "EMAIL_OR_USERNAME" => "Username or email address", - - "FIRST_NAME" => "First name", - - "HEADER_MESSAGE_ROOT" => "YOU ARE SIGNED IN AS THE ROOT USER", - - "LAST_NAME" => "Last name", - "LOCALE" => [ - "ACCOUNT" => "The language and locale to use for your account", - "INVALID" => "<strong>{{locale}}</strong> is not a valid locale." - ], - "LOGIN" => [ - "@TRANSLATION" => "Login", - "ALREADY_COMPLETE" => "You are already logged in!", - "SOCIAL" => "Or login with", - "REQUIRED" => "Sorry, you must be logged in to access this resource." - ], - "LOGOUT" => "Logout", - - "NAME" => "Name", - - "NAME_AND_EMAIL" => "Name and email", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Sign in to your {{site_name}} account, or register for a new account.", - "SUBTITLE" => "Register for free, or sign in with an existing account.", - "TITLE" => "Let's get started!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Password", - - "BETWEEN" => "Between {{min}}-{{max}} characters", - - "CONFIRM" => "Confirm password", - "CONFIRM_CURRENT" => "Please confirm your current password", - "CONFIRM_NEW" => "Confirm New Password", - "CONFIRM_NEW_EXPLAIN" => "Re-enter your new password", - "CONFIRM_NEW_HELP" => "Required only if selecting a new password", - "CREATE" => [ - "@TRANSLATION" => "Create Password", - "PAGE" => "Choose a password for your new account.", - "SET" => "Set Password and Sign In" - ], - "CURRENT" => "Current Password", - "CURRENT_EXPLAIN" => "You must confirm your current password to make changes", - - "FORGOTTEN" => "Forgotten Password", - "FORGET" => [ - "@TRANSLATION" => "I forgot my password", - - "COULD_NOT_UPDATE" => "Couldn't update password.", - "EMAIL" => "Please enter the email address you used to sign up. A link with instructions to reset your password will be emailed to you.", - "EMAIL_SEND" => "Email Password Reset Link", - "INVALID" => "This password reset request could not be found, or has expired. Please try <a href=\"{{url}}\">resubmitting your request<a>.", - "PAGE" => "Get a link to reset your password.", - "REQUEST_CANNED" => "Lost password request cancelled.", - "REQUEST_SENT" => "If the email <strong>{{email}}</strong> matches an account in our system, a password reset link will be sent to <strong>{{email}}</strong>." - ], - - "HASH_FAILED" => "Password hashing failed. Please contact a site administrator.", - "INVALID" => "Current password doesn't match the one we have on record", - "NEW" => "New Password", - "NOTHING_TO_UPDATE" => "You cannot update with the same password", - - "RESET" => [ - "@TRANSLATION" => "Reset Password", - "CHOOSE" => "Please choose a new password to continue.", - "PAGE" => "Choose a new password for your account.", - "SEND" => "Set New Password and Sign In" - ], - - "UPDATED" => "Account password updated" - ], - - "PROFILE" => [ - "SETTINGS" => "Profile settings", - "UPDATED" => "Profile settings updated" - ], - - "RATE_LIMIT_EXCEEDED" => "The rate limit for this action has been exceeded. You must wait another {{delay}} seconds before you will be allowed to make another attempt.", - - "REGISTER" => "Register", - "REGISTER_ME" => "Sign me up", - "REGISTRATION" => [ - "BROKEN" => "We're sorry, there is a problem with our account registration process. Please contact us directly for assistance.", - "COMPLETE_TYPE1" => "You have successfully registered. You can now sign in.", - "COMPLETE_TYPE2" => "You have successfully registered. A link to activate your account has been sent to <strong>{{email}}</strong>. You will not be able to sign in until you complete this step.", - "DISABLED" => "We're sorry, account registration has been disabled.", - "LOGOUT" => "I'm sorry, you cannot register for an account while logged in. Please log out first.", - "WELCOME" => "Registration is fast and simple." - ], - "REMEMBER_ME" => "Keep me signed in", - "REMEMBER_ME_ON_COMPUTER" => "Remember me on this computer (not recommended for public computers)", - - "SIGN_IN_HERE" => "Already have an account? <a href=\"{{url}}\">Sign in here.</a>", - "SIGNIN" => "Sign in", - "SIGNIN_OR_REGISTER" => "Sign in or register", - "SIGNUP" => "Sign Up", - - "TOS" => "Terms and Conditions", - "TOS_AGREEMENT" => "By registering an account with {{site_title}}, you accept the <a {{link_attributes | raw}}>terms and conditions</a>.", - "TOS_FOR" => "Terms and Conditions for {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Username", - - "CHOOSE" => "Choose a unique username", - "INVALID" => "Invalid username", - "IN_USE" => "Username <strong>{{user_name}}</strong> is already in use.", - "NOT_AVAILABLE" => "Username <strong>{{user_name}}</strong> is not available. Choose a different name, or click 'suggest'." - ], - - "USER_ID_INVALID" => "The requested user id does not exist.", - "USER_OR_EMAIL_INVALID" => "Username or email address is invalid.", - "USER_OR_PASS_INVALID" => "User not found or password is invalid.", - - "WELCOME" => "Welcome back, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * US English message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\en_US
+ * @author Alexander Weissman
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Account",
+
+ "ACCESS_DENIED" => "Hmm, looks like you don't have permission to do that.",
+
+ "DISABLED" => "This account has been disabled. Please contact us for more information.",
+
+ "EMAIL_UPDATED" => "Account email updated",
+
+ "INVALID" => "This account does not exist. It may have been deleted. Please contact us for more information.",
+
+ "MASTER_NOT_EXISTS" => "You cannot register an account until the master account has been created!",
+ "MY" => "My Account",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "Your session has been compromised. You should log out on all devices, then log back in and make sure that your data has not been tampered with.",
+ "TITLE" => "Your account may have been compromised",
+ "TEXT" => "Someone may have used your login information to acccess this page. For your safety, all sessions were logged out. Please <a href=\"{{url}}\">log in</a> and check your account for suspicious activity. You may also wish to change your password."
+ ],
+ "SESSION_EXPIRED" => "Your session has expired. Please sign in again.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Account settings",
+ "DESCRIPTION" => "Update your account settings, including email, name, and password.",
+ "UPDATED" => "Account settings updated"
+ ],
+
+ "TOOLS" => "Account tools",
+
+ "UNVERIFIED" => "Your account has not yet been verified. Check your emails / spam folder for account activation instructions.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "We have emailed a new verification link to {{email}}. Please check your inbox and spam folders for this email.",
+ "RESEND" => "Resend verification email",
+ "COMPLETE" => "You have successfully verified your account. You can now login.",
+ "EMAIL" => "Please enter the email address you used to sign up, and your verification email will be resent.",
+ "PAGE" => "Resend the verification email for your new account.",
+ "SEND" => "Email the verification link for my account",
+ "TOKEN_NOT_FOUND" => "Verification token does not exist / Account is already verified",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "There is no account for <strong>{{email}}</strong>.",
+ "IN_USE" => "Email <strong>{{email}}</strong> is already in use.",
+ "VERIFICATION_REQUIRED" => "Email (verification required - use a real address!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Username or email address",
+
+ "FIRST_NAME" => "First name",
+
+ "HEADER_MESSAGE_ROOT" => "YOU ARE SIGNED IN AS THE ROOT USER",
+
+ "LAST_NAME" => "Last name",
+ "LOCALE" => [
+ "ACCOUNT" => "The language and locale to use for your account",
+ "INVALID" => "<strong>{{locale}}</strong> is not a valid locale."
+ ],
+ "LOGIN" => [
+ "@TRANSLATION" => "Login",
+ "ALREADY_COMPLETE" => "You are already logged in!",
+ "SOCIAL" => "Or login with",
+ "REQUIRED" => "Sorry, you must be logged in to access this resource."
+ ],
+ "LOGOUT" => "Logout",
+
+ "NAME" => "Name",
+
+ "NAME_AND_EMAIL" => "Name and email",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Sign in to your {{site_name}} account, or register for a new account.",
+ "SUBTITLE" => "Register for free, or sign in with an existing account.",
+ "TITLE" => "Let's get started!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Password",
+
+ "BETWEEN" => "Between {{min}}-{{max}} characters",
+
+ "CONFIRM" => "Confirm password",
+ "CONFIRM_CURRENT" => "Please confirm your current password",
+ "CONFIRM_NEW" => "Confirm New Password",
+ "CONFIRM_NEW_EXPLAIN" => "Re-enter your new password",
+ "CONFIRM_NEW_HELP" => "Required only if selecting a new password",
+ "CREATE" => [
+ "@TRANSLATION" => "Create Password",
+ "PAGE" => "Choose a password for your new account.",
+ "SET" => "Set Password and Sign In"
+ ],
+ "CURRENT" => "Current Password",
+ "CURRENT_EXPLAIN" => "You must confirm your current password to make changes",
+
+ "FORGOTTEN" => "Forgotten Password",
+ "FORGET" => [
+ "@TRANSLATION" => "I forgot my password",
+
+ "COULD_NOT_UPDATE" => "Couldn't update password.",
+ "EMAIL" => "Please enter the email address you used to sign up. A link with instructions to reset your password will be emailed to you.",
+ "EMAIL_SEND" => "Email Password Reset Link",
+ "INVALID" => "This password reset request could not be found, or has expired. Please try <a href=\"{{url}}\">resubmitting your request<a>.",
+ "PAGE" => "Get a link to reset your password.",
+ "REQUEST_CANNED" => "Lost password request cancelled.",
+ "REQUEST_SENT" => "If the email <strong>{{email}}</strong> matches an account in our system, a password reset link will be sent to <strong>{{email}}</strong>."
+ ],
+
+ "HASH_FAILED" => "Password hashing failed. Please contact a site administrator.",
+ "INVALID" => "Current password doesn't match the one we have on record",
+ "NEW" => "New Password",
+ "NOTHING_TO_UPDATE" => "You cannot update with the same password",
+
+ "RESET" => [
+ "@TRANSLATION" => "Reset Password",
+ "CHOOSE" => "Please choose a new password to continue.",
+ "PAGE" => "Choose a new password for your account.",
+ "SEND" => "Set New Password and Sign In"
+ ],
+
+ "UPDATED" => "Account password updated"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Profile settings",
+ "UPDATED" => "Profile settings updated"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "The rate limit for this action has been exceeded. You must wait another {{delay}} seconds before you will be allowed to make another attempt.",
+
+ "REGISTER" => "Register",
+ "REGISTER_ME" => "Sign me up",
+ "REGISTRATION" => [
+ "BROKEN" => "We're sorry, there is a problem with our account registration process. Please contact us directly for assistance.",
+ "COMPLETE_TYPE1" => "You have successfully registered. You can now sign in.",
+ "COMPLETE_TYPE2" => "You have successfully registered. A link to activate your account has been sent to <strong>{{email}}</strong>. You will not be able to sign in until you complete this step.",
+ "DISABLED" => "We're sorry, account registration has been disabled.",
+ "LOGOUT" => "I'm sorry, you cannot register for an account while logged in. Please log out first.",
+ "WELCOME" => "Registration is fast and simple."
+ ],
+ "REMEMBER_ME" => "Keep me signed in",
+ "REMEMBER_ME_ON_COMPUTER" => "Remember me on this computer (not recommended for public computers)",
+
+ "SIGN_IN_HERE" => "Already have an account? <a href=\"{{url}}\">Sign in here.</a>",
+ "SIGNIN" => "Sign in",
+ "SIGNIN_OR_REGISTER" => "Sign in or register",
+ "SIGNUP" => "Sign Up",
+
+ "TOS" => "Terms and Conditions",
+ "TOS_AGREEMENT" => "By registering an account with {{site_title}}, you accept the <a {{link_attributes | raw}}>terms and conditions</a>.",
+ "TOS_FOR" => "Terms and Conditions for {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Username",
+
+ "CHOOSE" => "Choose a unique username",
+ "INVALID" => "Invalid username",
+ "IN_USE" => "Username <strong>{{user_name}}</strong> is already in use.",
+ "NOT_AVAILABLE" => "Username <strong>{{user_name}}</strong> is not available. Choose a different name, or click 'suggest'."
+ ],
+
+ "USER_ID_INVALID" => "The requested user id does not exist.",
+ "USER_OR_EMAIL_INVALID" => "Username or email address is invalid.",
+ "USER_OR_PASS_INVALID" => "User not found or password is invalid.",
+
+ "WELCOME" => "Welcome back, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/en_US/validate.php b/main/app/sprinkles/account/locale/en_US/validate.php index f91ecfe..6b33584 100644 --- a/main/app/sprinkles/account/locale/en_US/validate.php +++ b/main/app/sprinkles/account/locale/en_US/validate.php @@ -1,19 +1,19 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * US English message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\en_US - * @author Alexander Weissman - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Your password and confirmation password must match.", - "USERNAME" => "Username may consist only of lowercase letters, numbers, '.', '-', and '_'." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * US English message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\en_US
+ * @author Alexander Weissman
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "Your password and confirmation password must match.",
+ "USERNAME" => "Username may consist only of lowercase letters, numbers, '.', '-', and '_'."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/es_ES/messages.php b/main/app/sprinkles/account/locale/es_ES/messages.php index f469119..e084235 100644 --- a/main/app/sprinkles/account/locale/es_ES/messages.php +++ b/main/app/sprinkles/account/locale/es_ES/messages.php @@ -1,189 +1,189 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Spanish message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\es_ES - * @author rafa31gz - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Perfil", - - "ACCESS_DENIED" => "Hmm, parece que no tienes permiso para hacer eso.", - - "DISABLED" => "Esta cuenta se ha inhabilitado. Por favor contáctenos para más información.", - - "EMAIL_UPDATED" => "Correo electrónico de la cuenta actualizado", - - "INVALID" => "Esta cuenta no existe. Puede haber sido eliminado. Por favor contáctenos para más información.", - - "MASTER_NOT_EXISTS" => "No puede registrar una cuenta hasta que se haya creado la cuenta principal.", - "MY" => "Mi Perfil", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Su sesión ha sido comprometida. Debe desconectarse de todos los dispositivos y, a continuación, volver a iniciar sesión y asegurarse de que sus datos no han sido manipulados.", - "TITLE" => "Es posible que su cuenta se haya visto comprometida.", - "TEXT" => "Alguien puede haber utilizado su información de acceso para acceder a esta página. Para su seguridad, todas las sesiones se cerraron. <a href=\"{{url}}\"> ingrese </a> y compruebe si su actividad es sospechosa en su cuenta. También puede cambiar su contraseña." - ], - "SESSION_EXPIRED" => "Su sesión ha caducado. Inicie sesión nuevamente.", - - "SETTINGS" => [ - "@TRANSLATION" => "Configuraciones de la cuenta", - "DESCRIPTION" => "Actualice la configuración de su cuenta, incluido el correo electrónico, el nombre y la contraseña.", - "UPDATED" => "Configuración de la cuenta actualizada" - ], - - "TOOLS" => "Herramientas de la cuenta", - - "UNVERIFIED" => "Tu cuenta aún no se ha verificado. Revise sus correos electrónicos / carpeta de spam para obtener instrucciones sobre la activación de la cuenta.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Hemos enviado por correo electrónico un nuevo enlace de verificación a {{email}}. Comprueba tu bandeja de entrada y las carpetas de spam para este correo electrónico.", - "RESEND" => "Reenviar correo electrónico de verificación", - "COMPLETE" => "Ha verificado correctamente su cuenta. Ahora puede iniciar sesión.", - "EMAIL" => "Ingrese la dirección de correo electrónico que utilizó para registrarse y su correo electrónico de verificación será enviado de nuevo.", - "PAGE" => "Vuelva a enviar el correo electrónico de verificación de su nueva cuenta.", - "SEND" => "Reenviar correo de verificación", - "TOKEN_NOT_FOUND" => "El token de verificación no existe / La cuenta ya está verificada", - ] - ], - - "EMAIL" => [ - "INVALID" => "No hay cuenta para <strong> {{email}} </strong>.", - "IN_USE" => "El correo electrónico <strong> {{email}} </strong> ya está en uso.", - "VERIFICATION_REQUIRED" => "Correo electrónico (se requiere verificación - ¡use una dirección real!)" - ], - - "EMAIL_OR_USERNAME" => "Nombre de usuario o dirección de correo electrónico", - - "FIRST_NAME" => "Nombre", - - "HEADER_MESSAGE_ROOT" => "USTED HA INGRESADO COMO USUARIO ROOT", - - "LAST_NAME" => "Apellidos", - - "LOCALE" => [ - "ACCOUNT" => "El idioma y la configuración regional para utilizar en su cuenta", - "INVALID" => "<strong>{{locale}}</strong> no es un idioma válido." - ], - - "LOGIN" => [ - "@TRANSLATION" => "Acceder", - "ALREADY_COMPLETE" => "¡Ya se ha autentificado!", - "SOCIAL" => "O ingrese con", - "REQUIRED" => "Lo sentimos, debes iniciar sesión para acceder a este recurso." - ], - - "LOGOUT" => "Cerrar sesión", - - "NAME" => "Nombre", - - "NAME_AND_EMAIL" => "Nombre y correo electrónico", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Inicie sesión en su cuenta de {{site_name}} o regístrese para obtener una nueva cuenta.", - "SUBTITLE" => "Regístrese gratis o inicie sesión con una cuenta existente.", - "TITLE" => "¡Empecemos!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Contraseña", - - "BETWEEN" => "Entre {{min}} - {{max}} (recomendado 12)", - - "CONFIRM" => "Confirmar contraseña", - "CONFIRM_CURRENT" => "Por favor, confirma tu contraseña actual", - "CONFIRM_NEW" => "Confirmar nueva contraseña", - "CONFIRM_NEW_EXPLAIN" => "Vuelve a ingresar tu nueva contraseña", - "CONFIRM_NEW_HELP" => "Sólo se requiere si se selecciona una nueva contraseña", - "CREATE" => [ - "@TRANSLATION" => "Crear contraseña", - "PAGE" => "Elija una contraseña para su nueva cuenta.", - "SET" => "Establecer contraseña e iniciar sesión" - ], - "CURRENT" => "Contraseña actual", - "CURRENT_EXPLAIN" => "Debe confirmar su contraseña actual para realizar cambios", - - "FORGOTTEN" => "Contraseña olvidada", - "FORGET" => [ - "@TRANSLATION" => "Olvidé mi contraseña", - - "COULD_NOT_UPDATE" => "No se pudo actualizar la contraseña.", - "EMAIL" => "Introduce la dirección de correo electrónico que utilizaste para registrarte. Se le enviará por correo electrónico un enlace con las instrucciones para restablecer su contraseña.", - "EMAIL_SEND" => "Contraseña de correo electrónico Restablecer enlace", - "INVALID" => "No se pudo encontrar esta solicitud de restablecimiento de contraseña o ha caducado. Intenta <a href=\"{{url}}\"> volver a enviar tu solicitud <a>.", - "PAGE" => "Obtenga un enlace para restablecer su contraseña.", - "REQUEST_CANNED" => "Se ha cancelado la solicitud de contraseña perdida.", - "REQUEST_SENT" => "Se ha enviado un enlace de restablecimiento de contraseña a <strong> {{email}} </strong>." - ], - - "RESET" => [ - "@TRANSLATION" => "Restablecer la contraseña", - "CHOOSE" => "Por favor, elija una nueva contraseña para continuar.", - "PAGE" => "Elige una nueva contraseña para tu cuenta.", - "SEND" => "Establecer nueva contraseña e iniciar sesión" - ], - - "HASH_FAILED" => "El hash de la contraseña ha fallado. Póngase en contacto con un administrador del sitio.", - "INVALID" => "La contraseña actual no coincide con la que tenemos registrada", - "NEW" => "Nueva contraseña", - "NOTHING_TO_UPDATE" => "No se puede actualizar con la misma contraseña", - "UPDATED" => "Contraseña de la cuenta actualizada" - ], - - "PROFILE" => [ - "SETTINGS" => "Configuración de perfil", - "UPDATED" => "Configuración del perfil actualizada" - ], - - "RATE_LIMIT_EXCEEDED" => "Se ha superado el límite de velocidad para esta acción. Debe esperar otro {{delay}} segundos antes de que se le permita hacer otro intento.", - - "REGISTER" => "Registro", - "REGISTER_ME" => "Inscríbeme", - "REGISTRATION" => [ - "BROKEN" => "Lo sentimos, hay un problema con nuestro proceso de registro de cuenta. Póngase en contacto con nosotros directamente para obtener ayuda.", - "COMPLETE_TYPE1" => "Se ha registrado exitosamente. Ahora puede iniciar sesión.", - "COMPLETE_TYPE2" => "Se ha registrado exitosamente. Se ha enviado un enlace para activar tu cuenta a <strong> {{email}} </strong>. No podrá iniciar sesión hasta que complete este paso.", - "DISABLED" => "Lo sentimos, el registro de cuenta se ha deshabilitado.", - "LOGOUT" => "Lo siento, no puede registrarse para una cuenta mientras está conectado. Por favor, cierra la sesión primero.", - "WELCOME" => "El registro es rápido y sencillo." - ], - - "REMEMBER_ME" => "¡Recuérdame!", - "REMEMBER_ME_ON_COMPUTER" => "Recuérdeme en este ordenador (no se recomienda para ordenadores públicos)", - - "SIGNIN" => "Iniciar sesión", - "SIGNIN_OR_REGISTER" => "Ingresa o Registro", - "SIGNUP" => "Regístrate", - "SUGGEST" => "Sugerencia", - "HAVE_ACCOUNT" => "¿Ya tienes una cuenta?", - "SIGN_IN_HERE" => "¿Ya tienes una cuenta? <a href=\"{{url}}\"> Acceda aquí. </a>", - - - "TOS" => "Términos y Condiciones", - "TOS_AGREEMENT" => "Al registrar una cuenta con {{site_title}}, acepta los <a {{link_attributes | raw}}> términos y condiciones </a>.", - "TOS_FOR" => "Términos y condiciones para {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Nombre de usuario", - - "CHOOSE" => "Elige un nombre de usuario único", - "INVALID" => "Nombre de usuario no válido", - "IN_USE" => "El nombre de usuario <strong> {{user_name}} </strong> ya está en uso.", - "NOT_AVAILABLE" => "El nombre de usuario <strong> {{user_name}} </strong> no está disponible. Elija otro nombre o haga clic en \"sugerir\"." - ], - - "USER_ID_INVALID" => "El ID de usuario solicitado no existe.", - "USER_OR_EMAIL_INVALID" => "El nombre de usuario o la dirección de correo electrónico no son válidos.", - "USER_OR_PASS_INVALID" => "Usuario no encontrado o la contraseña no es válida.", - - "WELCOME" => "Bienvenido de nuevo, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Spanish message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\es_ES
+ * @author rafa31gz
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Perfil",
+
+ "ACCESS_DENIED" => "Hmm, parece que no tienes permiso para hacer eso.",
+
+ "DISABLED" => "Esta cuenta se ha inhabilitado. Por favor contáctenos para más información.",
+
+ "EMAIL_UPDATED" => "Correo electrónico de la cuenta actualizado",
+
+ "INVALID" => "Esta cuenta no existe. Puede haber sido eliminado. Por favor contáctenos para más información.",
+
+ "MASTER_NOT_EXISTS" => "No puede registrar una cuenta hasta que se haya creado la cuenta principal.",
+ "MY" => "Mi Perfil",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "Su sesión ha sido comprometida. Debe desconectarse de todos los dispositivos y, a continuación, volver a iniciar sesión y asegurarse de que sus datos no han sido manipulados.",
+ "TITLE" => "Es posible que su cuenta se haya visto comprometida.",
+ "TEXT" => "Alguien puede haber utilizado su información de acceso para acceder a esta página. Para su seguridad, todas las sesiones se cerraron. <a href=\"{{url}}\"> ingrese </a> y compruebe si su actividad es sospechosa en su cuenta. También puede cambiar su contraseña."
+ ],
+ "SESSION_EXPIRED" => "Su sesión ha caducado. Inicie sesión nuevamente.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Configuraciones de la cuenta",
+ "DESCRIPTION" => "Actualice la configuración de su cuenta, incluido el correo electrónico, el nombre y la contraseña.",
+ "UPDATED" => "Configuración de la cuenta actualizada"
+ ],
+
+ "TOOLS" => "Herramientas de la cuenta",
+
+ "UNVERIFIED" => "Tu cuenta aún no se ha verificado. Revise sus correos electrónicos / carpeta de spam para obtener instrucciones sobre la activación de la cuenta.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "Hemos enviado por correo electrónico un nuevo enlace de verificación a {{email}}. Comprueba tu bandeja de entrada y las carpetas de spam para este correo electrónico.",
+ "RESEND" => "Reenviar correo electrónico de verificación",
+ "COMPLETE" => "Ha verificado correctamente su cuenta. Ahora puede iniciar sesión.",
+ "EMAIL" => "Ingrese la dirección de correo electrónico que utilizó para registrarse y su correo electrónico de verificación será enviado de nuevo.",
+ "PAGE" => "Vuelva a enviar el correo electrónico de verificación de su nueva cuenta.",
+ "SEND" => "Reenviar correo de verificación",
+ "TOKEN_NOT_FOUND" => "El token de verificación no existe / La cuenta ya está verificada",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "No hay cuenta para <strong> {{email}} </strong>.",
+ "IN_USE" => "El correo electrónico <strong> {{email}} </strong> ya está en uso.",
+ "VERIFICATION_REQUIRED" => "Correo electrónico (se requiere verificación - ¡use una dirección real!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Nombre de usuario o dirección de correo electrónico",
+
+ "FIRST_NAME" => "Nombre",
+
+ "HEADER_MESSAGE_ROOT" => "USTED HA INGRESADO COMO USUARIO ROOT",
+
+ "LAST_NAME" => "Apellidos",
+
+ "LOCALE" => [
+ "ACCOUNT" => "El idioma y la configuración regional para utilizar en su cuenta",
+ "INVALID" => "<strong>{{locale}}</strong> no es un idioma válido."
+ ],
+
+ "LOGIN" => [
+ "@TRANSLATION" => "Acceder",
+ "ALREADY_COMPLETE" => "¡Ya se ha autentificado!",
+ "SOCIAL" => "O ingrese con",
+ "REQUIRED" => "Lo sentimos, debes iniciar sesión para acceder a este recurso."
+ ],
+
+ "LOGOUT" => "Cerrar sesión",
+
+ "NAME" => "Nombre",
+
+ "NAME_AND_EMAIL" => "Nombre y correo electrónico",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Inicie sesión en su cuenta de {{site_name}} o regístrese para obtener una nueva cuenta.",
+ "SUBTITLE" => "Regístrese gratis o inicie sesión con una cuenta existente.",
+ "TITLE" => "¡Empecemos!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Contraseña",
+
+ "BETWEEN" => "Entre {{min}} - {{max}} (recomendado 12)",
+
+ "CONFIRM" => "Confirmar contraseña",
+ "CONFIRM_CURRENT" => "Por favor, confirma tu contraseña actual",
+ "CONFIRM_NEW" => "Confirmar nueva contraseña",
+ "CONFIRM_NEW_EXPLAIN" => "Vuelve a ingresar tu nueva contraseña",
+ "CONFIRM_NEW_HELP" => "Sólo se requiere si se selecciona una nueva contraseña",
+ "CREATE" => [
+ "@TRANSLATION" => "Crear contraseña",
+ "PAGE" => "Elija una contraseña para su nueva cuenta.",
+ "SET" => "Establecer contraseña e iniciar sesión"
+ ],
+ "CURRENT" => "Contraseña actual",
+ "CURRENT_EXPLAIN" => "Debe confirmar su contraseña actual para realizar cambios",
+
+ "FORGOTTEN" => "Contraseña olvidada",
+ "FORGET" => [
+ "@TRANSLATION" => "Olvidé mi contraseña",
+
+ "COULD_NOT_UPDATE" => "No se pudo actualizar la contraseña.",
+ "EMAIL" => "Introduce la dirección de correo electrónico que utilizaste para registrarte. Se le enviará por correo electrónico un enlace con las instrucciones para restablecer su contraseña.",
+ "EMAIL_SEND" => "Contraseña de correo electrónico Restablecer enlace",
+ "INVALID" => "No se pudo encontrar esta solicitud de restablecimiento de contraseña o ha caducado. Intenta <a href=\"{{url}}\"> volver a enviar tu solicitud <a>.",
+ "PAGE" => "Obtenga un enlace para restablecer su contraseña.",
+ "REQUEST_CANNED" => "Se ha cancelado la solicitud de contraseña perdida.",
+ "REQUEST_SENT" => "Se ha enviado un enlace de restablecimiento de contraseña a <strong> {{email}} </strong>."
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "Restablecer la contraseña",
+ "CHOOSE" => "Por favor, elija una nueva contraseña para continuar.",
+ "PAGE" => "Elige una nueva contraseña para tu cuenta.",
+ "SEND" => "Establecer nueva contraseña e iniciar sesión"
+ ],
+
+ "HASH_FAILED" => "El hash de la contraseña ha fallado. Póngase en contacto con un administrador del sitio.",
+ "INVALID" => "La contraseña actual no coincide con la que tenemos registrada",
+ "NEW" => "Nueva contraseña",
+ "NOTHING_TO_UPDATE" => "No se puede actualizar con la misma contraseña",
+ "UPDATED" => "Contraseña de la cuenta actualizada"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Configuración de perfil",
+ "UPDATED" => "Configuración del perfil actualizada"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "Se ha superado el límite de velocidad para esta acción. Debe esperar otro {{delay}} segundos antes de que se le permita hacer otro intento.",
+
+ "REGISTER" => "Registro",
+ "REGISTER_ME" => "Inscríbeme",
+ "REGISTRATION" => [
+ "BROKEN" => "Lo sentimos, hay un problema con nuestro proceso de registro de cuenta. Póngase en contacto con nosotros directamente para obtener ayuda.",
+ "COMPLETE_TYPE1" => "Se ha registrado exitosamente. Ahora puede iniciar sesión.",
+ "COMPLETE_TYPE2" => "Se ha registrado exitosamente. Se ha enviado un enlace para activar tu cuenta a <strong> {{email}} </strong>. No podrá iniciar sesión hasta que complete este paso.",
+ "DISABLED" => "Lo sentimos, el registro de cuenta se ha deshabilitado.",
+ "LOGOUT" => "Lo siento, no puede registrarse para una cuenta mientras está conectado. Por favor, cierra la sesión primero.",
+ "WELCOME" => "El registro es rápido y sencillo."
+ ],
+
+ "REMEMBER_ME" => "¡Recuérdame!",
+ "REMEMBER_ME_ON_COMPUTER" => "Recuérdeme en este ordenador (no se recomienda para ordenadores públicos)",
+
+ "SIGNIN" => "Iniciar sesión",
+ "SIGNIN_OR_REGISTER" => "Ingresa o Registro",
+ "SIGNUP" => "Regístrate",
+ "SUGGEST" => "Sugerencia",
+ "HAVE_ACCOUNT" => "¿Ya tienes una cuenta?",
+ "SIGN_IN_HERE" => "¿Ya tienes una cuenta? <a href=\"{{url}}\"> Acceda aquí. </a>",
+
+
+ "TOS" => "Términos y Condiciones",
+ "TOS_AGREEMENT" => "Al registrar una cuenta con {{site_title}}, acepta los <a {{link_attributes | raw}}> términos y condiciones </a>.",
+ "TOS_FOR" => "Términos y condiciones para {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Nombre de usuario",
+
+ "CHOOSE" => "Elige un nombre de usuario único",
+ "INVALID" => "Nombre de usuario no válido",
+ "IN_USE" => "El nombre de usuario <strong> {{user_name}} </strong> ya está en uso.",
+ "NOT_AVAILABLE" => "El nombre de usuario <strong> {{user_name}} </strong> no está disponible. Elija otro nombre o haga clic en \"sugerir\"."
+ ],
+
+ "USER_ID_INVALID" => "El ID de usuario solicitado no existe.",
+ "USER_OR_EMAIL_INVALID" => "El nombre de usuario o la dirección de correo electrónico no son válidos.",
+ "USER_OR_PASS_INVALID" => "Usuario no encontrado o la contraseña no es válida.",
+
+ "WELCOME" => "Bienvenido de nuevo, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/es_ES/validate.php b/main/app/sprinkles/account/locale/es_ES/validate.php index ecc1b6a..342ca14 100644 --- a/main/app/sprinkles/account/locale/es_ES/validate.php +++ b/main/app/sprinkles/account/locale/es_ES/validate.php @@ -1,19 +1,19 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Spanish message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\es_ES - * @author rafa31gz - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Su contraseña y contraseña de confirmación deben coincidir.", - "USERNAME" => "El nombre de usuario puede consistir sólo en letras minúsculas, números, '.', '-' y '_'." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Spanish message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\es_ES
+ * @author rafa31gz
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "Su contraseña y contraseña de confirmación deben coincidir.",
+ "USERNAME" => "El nombre de usuario puede consistir sólo en letras minúsculas, números, '.', '-' y '_'."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/fa/messages.php b/main/app/sprinkles/account/locale/fa/messages.php index f66727f..00fba60 100644 --- a/main/app/sprinkles/account/locale/fa/messages.php +++ b/main/app/sprinkles/account/locale/fa/messages.php @@ -1,178 +1,178 @@ -<?php - -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Standard Farsi/Persian message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\fa - * @author aminakbari - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "حساب", - - "ACCESS_DENIED" => "به نظر می آید که شما اجازه انجام این کار را ندارید", - - "DISABLED" => "این حساب کاربری غیر فعال شده است. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.", - - "EMAIL_UPDATED" => "آدرس پست الکترونیکی حساب، به روز رسانی شد", - - "INVALID" => "این اکانت موجود نیست. ممکن است که حذف شده باشد. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.", - - "MASTER_NOT_EXISTS" => "تا زمانی که حساب اصلی ساخته نشده است نمیتوانید حساب کاربری جدیدی بسازید.", - "MY" => "حساب من", - - "SESSION_COMPROMISED" => "ممکن است سژن شما مورد حمله واقع شده باشد. بهتر است با همه دستگاه های خود از وب سایت خارج شوید و دوباره وارد شوید. همچنین توجه بفرمایید که اطلاعات حسابتان، مورد حمله واقع نشده باشد. ", - "SESSION_COMPROMISED_TITLE" => "ممکن است که اکانت شما مورد حمله واقع شده باشد", - "SESSION_EXPIRED" => "سژن شما به پایان رسیده است. لطفا دوباره وارد شوید.", - - "SETTINGS" => [ - "@TRANSLATION" => "تنظیمات حساب", - "DESCRIPTION" => "اطلاعات حسابتان یعنی پست الکترونیکی،نام و گذرواژه خود را به روز رسانی کنید", - "UPDATED" => "تنظیمات حساب به روز رسانی شد" - ], - - "TOOLS" => "ابزار حساب", - - "UNVERIFIED" => "شما هنوز آدرس پست الکترونیکی خود را فعال نکرده اید. برای فعال سازی لطفا ایمیل خود را چک کنید.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "لینک فعال سازی برای ایمیل {{email}} ارسال شد. لطفا ایمیل خود را چک کنید.", - "RESEND" => "ارسال دوباره ایمیل فعال سازی", - "COMPLETE" => "شما پست الکترونیکی خود را با موفقیت فعال سازی کردید. حالا می توانید وارد شوید.", - "EMAIL" => "لطفا آدرس پست الکترونیکی که با آن ثبت نام کردید وارد کنید تا ایمیل فعال سازی دوباره برایتان ارسال شود.", - "PAGE" => "ارسال دوباره ایمیل فعال سازی برای حساب جدید شما", - "SEND" => "ارسال ایمیل فعال سازی برای حساب کاربری", - "TOKEN_NOT_FOUND" => "این حساب کاربری یا قبلا فعال شده است و یا کد فعال سازی موجود نیست.", - ] - ], - - "EMAIL" => [ - "INVALID" => "حساب کاربری با <strong>{{email}}</strong> ثبت نشده است.", - "IN_USE" => "ایمیل <strong>{{email}}</strong> قبلا استفاده شده است", - "VERIFICATION_REQUIRED" => "آدرس پست الکترونیکی را بصورت صحیح وارد کنید" - ], - - "EMAIL_OR_USERNAME" => "نام کاربری یا آدرس پست الکترونیکی", - - "FIRST_NAME" => "نام", - - "HEADER_MESSAGE_ROOT" => "شما بعنوان کاربر اصلی وارد شده اید", - - "LAST_NAME" => "نام خانوادگی", - - "LOCALE" => [ - "ACCOUNT" => "زبان انتخابی برای حساب شما", - "INVALID" => "<strong>{{locale}}</strong> زبان صحیحی نیست" - ], - - "LOGIN" => [ - "@TRANSLATION" => "ورود", - "ALREADY_COMPLETE" => "شما قبلا وارد شده اید.", - "SOCIAL" => "یا با روش های زیر وارد شوید", - "REQUIRED" => "برای دیدن این صفحه لازم است که وارد شوید" - ], - - "LOGOUT" => "خروج", - - "NAME" => "نام", - - "NAME_AND_EMAIL" => "نام و پست الکترونیکی", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "به حساب کاربری خود در {{site_name}} وارد شوید و یا حساب کاربری جدیدی بسازید", - "SUBTITLE" => "ثبت نام کنید و یا با حساب کاربری خود وارد شوید", - "TITLE" => "بیایید شروع کنیم!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "گذرواژه", - - "BETWEEN" => "بین {{min}}-{{max}} حرف", - - "CONFIRM" => "رمز عبور را وارد کنید", - "CONFIRM_CURRENT" => "لطفا رمز عبور فعلی را تایید کنید", - "CONFIRM_NEW" => "رمز عبور جدید را وارد کنید", - "CONFIRM_NEW_EXPLAIN" => "رمز عبور جدید را تکرار کنید", - "CONFIRM_NEW_HELP" => "فقط زمانی لازم است که می خواهید گذرواژه جدیدی انتخاب کنید", - "CURRENT" => "گذرواژه فعلی", - "CURRENT_EXPLAIN" => "شما باید گذرواژه فعلی خود را وارد کنید تا بتوانید اطلاعات را به روز رسانی کنید", - - "FORGOTTEN" => "فراموشی گذرواژه", - "FORGET" => [ - "@TRANSLATION" => "گذرواژه خود را فراموش کرده ام", - - "COULD_NOT_UPDATE" => "گذرواژه به روز رسانی نشد", - "EMAIL" => "لطفا آدرس پست الکترونیکی که در زمان ثبت نام استفاده کردید، وارد کنید. لینک بازیابی گذرواژه برای شما ایمیل خواهد شد.", - "EMAIL_SEND" => "لینک بازیابی گذرواژه ایمیل شود", - "INVALID" => "درخواست بازیابی کذرواژه پیدا نشد و یا منقضی شده است. لطفا درخواست را <a href=\"{{url}}\">دوباره ارسال کنید<a>", - "PAGE" => "دریافت لینک بازیابی گذرواژه", - "REQUEST_CANNED" => "درخواست فراموشی گذرواژه، حذف شد.", - "REQUEST_SENT" => "ایمیل بازیابی گذرواژه به <strong>{{email}}</strong> ارسال شد." - ], - - "RESET" => [ - "@TRANSLATION" => "تغییر گذرواژه", - "CHOOSE" => "لطفا گذرواژه جدید را انتخاب کنید", - "PAGE" => "برای حساب خود، گذرواژه جدیدی انتخاب کنید.", - "SEND" => "گذرواژه جدید را انتخاب کرده و وارد شوید" - ], - - "HASH_FAILED" => "هشینگ گذرواژه با مشکل روبرو شد. لطفا با مسولین وب سایت تماس برقرار کنید", - "INVALID" => "گذرواژه فعلی درست وارد نشده است", - "NEW" => "گذرواژه جدید", - "NOTHING_TO_UPDATE" => "شما نمیتوانید همان گذرواژه را دوباره وارد کنید", - "UPDATED" => "گذرواژه به روز رسانی شد" - ], - - "PROFILE" => [ - "SETTINGS" => "تنظیمات شخصی حساب", - "UPDATED" => "تنظیمات شخصی حساب به روز رسانی شد" - ], - - "REGISTER" => "ثبت نام", - "REGISTER_ME" => "ثبت نام کن", - - "REGISTRATION" => [ - "BROKEN" => "متاسفانه پروسه ثبت نام با مشکلی روبرو شد. برای دریافت کمک لطفا با ما تماس بگیرید.", - "COMPLETE_TYPE1" => "شما با موفقیت ثبت نام کردید. حالا میتوانید وارد شوید.", - "COMPLETE_TYPE2" => "شما با موفقیت ثبت نام کردید. لینک فعال سازی حساب به آدرس پست الکترونیکیتان <strong>{{email}}</strong> ارسال شد. بدون فعال سازی نمیتوانید وارد شوید.", - "DISABLED" => "با عرض تاسف، امکان ثبت در وب سایت، غیر فعال شده است.", - "LOGOUT" => "شما همزمان این که وارد شده اید نمیتوانید حساب کاربری جدیدی بسازید. لطفا ابتدا خارج شوید.", - "WELCOME" => "سریع و ساده ثبت نام کنید" - ], - - "RATE_LIMIT_EXCEEDED" => "شما محدودیت تعداد انجام این کار را پشت سر گذاشتید. لطفا {{delay}} ثانیه دیگر صبر کرده و دوباره تلاش کنید.", - "REMEMBER_ME" => "من را به خاطر بسپار!", - "REMEMBER_ME_ON_COMPUTER" => "من را در این دستگاه به خاطر بسپار (برای دستگاه های عمومی پیشنهاد نمی شود)", - - "SIGNIN" => "ورود", - "SIGNIN_OR_REGISTER" => "ثبت نام کنید و یا وارد شوید", - "SIGNUP" => "ثبت نام", - - "TOS" => "شرایط و مقررات", - "TOS_AGREEMENT" => "با ثبت نام در {{site_title}} موافقت خود با <a {{link_attributes | raw}}>شرایط و مقررات</a> را نشان میدهید.", - "TOS_FOR" => "شرایط و مقررات {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "نام کاربری", - - "CHOOSE" => "یک نام کاربری منحصر به فرد انتخاب کنید", - "INVALID" => "نام کاربری معتبر نیست", - "IN_USE" => "نام کاربری <strong>{{user_name}}</strong> قبلا استفاده شده است", - "NOT_AVAILABLE" => "نام کاربری <strong>{{user_name}}</strong> موجود نیست. لطفا نام کاربری دیگری انتخاب کنید" - ], - - "USER_ID_INVALID" => "آی دی کاربری مد نظر شما موجود نیست", - "USER_OR_EMAIL_INVALID" => "نام کاربری و یا آدرس پست الکترونیکی معتبر نیست", - "USER_OR_PASS_INVALID" => "کاربری یافت نشد و یا گذرواژه صحیح نیست", - - "WELCOME" => "خوش آمدید {{first_name}}" -]; +<?php
+
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Standard Farsi/Persian message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\fa
+ * @author aminakbari
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "حساب",
+
+ "ACCESS_DENIED" => "به نظر می آید که شما اجازه انجام این کار را ندارید",
+
+ "DISABLED" => "این حساب کاربری غیر فعال شده است. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.",
+
+ "EMAIL_UPDATED" => "آدرس پست الکترونیکی حساب، به روز رسانی شد",
+
+ "INVALID" => "این اکانت موجود نیست. ممکن است که حذف شده باشد. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.",
+
+ "MASTER_NOT_EXISTS" => "تا زمانی که حساب اصلی ساخته نشده است نمیتوانید حساب کاربری جدیدی بسازید.",
+ "MY" => "حساب من",
+
+ "SESSION_COMPROMISED" => "ممکن است سژن شما مورد حمله واقع شده باشد. بهتر است با همه دستگاه های خود از وب سایت خارج شوید و دوباره وارد شوید. همچنین توجه بفرمایید که اطلاعات حسابتان، مورد حمله واقع نشده باشد. ",
+ "SESSION_COMPROMISED_TITLE" => "ممکن است که اکانت شما مورد حمله واقع شده باشد",
+ "SESSION_EXPIRED" => "سژن شما به پایان رسیده است. لطفا دوباره وارد شوید.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "تنظیمات حساب",
+ "DESCRIPTION" => "اطلاعات حسابتان یعنی پست الکترونیکی،نام و گذرواژه خود را به روز رسانی کنید",
+ "UPDATED" => "تنظیمات حساب به روز رسانی شد"
+ ],
+
+ "TOOLS" => "ابزار حساب",
+
+ "UNVERIFIED" => "شما هنوز آدرس پست الکترونیکی خود را فعال نکرده اید. برای فعال سازی لطفا ایمیل خود را چک کنید.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "لینک فعال سازی برای ایمیل {{email}} ارسال شد. لطفا ایمیل خود را چک کنید.",
+ "RESEND" => "ارسال دوباره ایمیل فعال سازی",
+ "COMPLETE" => "شما پست الکترونیکی خود را با موفقیت فعال سازی کردید. حالا می توانید وارد شوید.",
+ "EMAIL" => "لطفا آدرس پست الکترونیکی که با آن ثبت نام کردید وارد کنید تا ایمیل فعال سازی دوباره برایتان ارسال شود.",
+ "PAGE" => "ارسال دوباره ایمیل فعال سازی برای حساب جدید شما",
+ "SEND" => "ارسال ایمیل فعال سازی برای حساب کاربری",
+ "TOKEN_NOT_FOUND" => "این حساب کاربری یا قبلا فعال شده است و یا کد فعال سازی موجود نیست.",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "حساب کاربری با <strong>{{email}}</strong> ثبت نشده است.",
+ "IN_USE" => "ایمیل <strong>{{email}}</strong> قبلا استفاده شده است",
+ "VERIFICATION_REQUIRED" => "آدرس پست الکترونیکی را بصورت صحیح وارد کنید"
+ ],
+
+ "EMAIL_OR_USERNAME" => "نام کاربری یا آدرس پست الکترونیکی",
+
+ "FIRST_NAME" => "نام",
+
+ "HEADER_MESSAGE_ROOT" => "شما بعنوان کاربر اصلی وارد شده اید",
+
+ "LAST_NAME" => "نام خانوادگی",
+
+ "LOCALE" => [
+ "ACCOUNT" => "زبان انتخابی برای حساب شما",
+ "INVALID" => "<strong>{{locale}}</strong> زبان صحیحی نیست"
+ ],
+
+ "LOGIN" => [
+ "@TRANSLATION" => "ورود",
+ "ALREADY_COMPLETE" => "شما قبلا وارد شده اید.",
+ "SOCIAL" => "یا با روش های زیر وارد شوید",
+ "REQUIRED" => "برای دیدن این صفحه لازم است که وارد شوید"
+ ],
+
+ "LOGOUT" => "خروج",
+
+ "NAME" => "نام",
+
+ "NAME_AND_EMAIL" => "نام و پست الکترونیکی",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "به حساب کاربری خود در {{site_name}} وارد شوید و یا حساب کاربری جدیدی بسازید",
+ "SUBTITLE" => "ثبت نام کنید و یا با حساب کاربری خود وارد شوید",
+ "TITLE" => "بیایید شروع کنیم!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "گذرواژه",
+
+ "BETWEEN" => "بین {{min}}-{{max}} حرف",
+
+ "CONFIRM" => "رمز عبور را وارد کنید",
+ "CONFIRM_CURRENT" => "لطفا رمز عبور فعلی را تایید کنید",
+ "CONFIRM_NEW" => "رمز عبور جدید را وارد کنید",
+ "CONFIRM_NEW_EXPLAIN" => "رمز عبور جدید را تکرار کنید",
+ "CONFIRM_NEW_HELP" => "فقط زمانی لازم است که می خواهید گذرواژه جدیدی انتخاب کنید",
+ "CURRENT" => "گذرواژه فعلی",
+ "CURRENT_EXPLAIN" => "شما باید گذرواژه فعلی خود را وارد کنید تا بتوانید اطلاعات را به روز رسانی کنید",
+
+ "FORGOTTEN" => "فراموشی گذرواژه",
+ "FORGET" => [
+ "@TRANSLATION" => "گذرواژه خود را فراموش کرده ام",
+
+ "COULD_NOT_UPDATE" => "گذرواژه به روز رسانی نشد",
+ "EMAIL" => "لطفا آدرس پست الکترونیکی که در زمان ثبت نام استفاده کردید، وارد کنید. لینک بازیابی گذرواژه برای شما ایمیل خواهد شد.",
+ "EMAIL_SEND" => "لینک بازیابی گذرواژه ایمیل شود",
+ "INVALID" => "درخواست بازیابی کذرواژه پیدا نشد و یا منقضی شده است. لطفا درخواست را <a href=\"{{url}}\">دوباره ارسال کنید<a>",
+ "PAGE" => "دریافت لینک بازیابی گذرواژه",
+ "REQUEST_CANNED" => "درخواست فراموشی گذرواژه، حذف شد.",
+ "REQUEST_SENT" => "ایمیل بازیابی گذرواژه به <strong>{{email}}</strong> ارسال شد."
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "تغییر گذرواژه",
+ "CHOOSE" => "لطفا گذرواژه جدید را انتخاب کنید",
+ "PAGE" => "برای حساب خود، گذرواژه جدیدی انتخاب کنید.",
+ "SEND" => "گذرواژه جدید را انتخاب کرده و وارد شوید"
+ ],
+
+ "HASH_FAILED" => "هشینگ گذرواژه با مشکل روبرو شد. لطفا با مسولین وب سایت تماس برقرار کنید",
+ "INVALID" => "گذرواژه فعلی درست وارد نشده است",
+ "NEW" => "گذرواژه جدید",
+ "NOTHING_TO_UPDATE" => "شما نمیتوانید همان گذرواژه را دوباره وارد کنید",
+ "UPDATED" => "گذرواژه به روز رسانی شد"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "تنظیمات شخصی حساب",
+ "UPDATED" => "تنظیمات شخصی حساب به روز رسانی شد"
+ ],
+
+ "REGISTER" => "ثبت نام",
+ "REGISTER_ME" => "ثبت نام کن",
+
+ "REGISTRATION" => [
+ "BROKEN" => "متاسفانه پروسه ثبت نام با مشکلی روبرو شد. برای دریافت کمک لطفا با ما تماس بگیرید.",
+ "COMPLETE_TYPE1" => "شما با موفقیت ثبت نام کردید. حالا میتوانید وارد شوید.",
+ "COMPLETE_TYPE2" => "شما با موفقیت ثبت نام کردید. لینک فعال سازی حساب به آدرس پست الکترونیکیتان <strong>{{email}}</strong> ارسال شد. بدون فعال سازی نمیتوانید وارد شوید.",
+ "DISABLED" => "با عرض تاسف، امکان ثبت در وب سایت، غیر فعال شده است.",
+ "LOGOUT" => "شما همزمان این که وارد شده اید نمیتوانید حساب کاربری جدیدی بسازید. لطفا ابتدا خارج شوید.",
+ "WELCOME" => "سریع و ساده ثبت نام کنید"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "شما محدودیت تعداد انجام این کار را پشت سر گذاشتید. لطفا {{delay}} ثانیه دیگر صبر کرده و دوباره تلاش کنید.",
+ "REMEMBER_ME" => "من را به خاطر بسپار!",
+ "REMEMBER_ME_ON_COMPUTER" => "من را در این دستگاه به خاطر بسپار (برای دستگاه های عمومی پیشنهاد نمی شود)",
+
+ "SIGNIN" => "ورود",
+ "SIGNIN_OR_REGISTER" => "ثبت نام کنید و یا وارد شوید",
+ "SIGNUP" => "ثبت نام",
+
+ "TOS" => "شرایط و مقررات",
+ "TOS_AGREEMENT" => "با ثبت نام در {{site_title}} موافقت خود با <a {{link_attributes | raw}}>شرایط و مقررات</a> را نشان میدهید.",
+ "TOS_FOR" => "شرایط و مقررات {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "نام کاربری",
+
+ "CHOOSE" => "یک نام کاربری منحصر به فرد انتخاب کنید",
+ "INVALID" => "نام کاربری معتبر نیست",
+ "IN_USE" => "نام کاربری <strong>{{user_name}}</strong> قبلا استفاده شده است",
+ "NOT_AVAILABLE" => "نام کاربری <strong>{{user_name}}</strong> موجود نیست. لطفا نام کاربری دیگری انتخاب کنید"
+ ],
+
+ "USER_ID_INVALID" => "آی دی کاربری مد نظر شما موجود نیست",
+ "USER_OR_EMAIL_INVALID" => "نام کاربری و یا آدرس پست الکترونیکی معتبر نیست",
+ "USER_OR_PASS_INVALID" => "کاربری یافت نشد و یا گذرواژه صحیح نیست",
+
+ "WELCOME" => "خوش آمدید {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/fa/validate.php b/main/app/sprinkles/account/locale/fa/validate.php index 4e8dc74..cb6739d 100644 --- a/main/app/sprinkles/account/locale/fa/validate.php +++ b/main/app/sprinkles/account/locale/fa/validate.php @@ -1,20 +1,20 @@ -<?php - -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Standard Farsi/Persian message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\fa - * @author aminakbari - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "گذرواژه و تکرار آن باید با یکدیگر تطبیق پیدا کنند", - "USERNAME" => "نام کاربری فقط میتواند از حروف کوچک، اعداد، '.'، '-' و '_' متشکل شوند." - ] -]; +<?php
+
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Standard Farsi/Persian message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\fa
+ * @author aminakbari
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "گذرواژه و تکرار آن باید با یکدیگر تطبیق پیدا کنند",
+ "USERNAME" => "نام کاربری فقط میتواند از حروف کوچک، اعداد، '.'، '-' و '_' متشکل شوند."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/fr_FR/messages.php b/main/app/sprinkles/account/locale/fr_FR/messages.php index 9de347f..6132dcb 100644 --- a/main/app/sprinkles/account/locale/fr_FR/messages.php +++ b/main/app/sprinkles/account/locale/fr_FR/messages.php @@ -1,179 +1,179 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * French message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\fr - * @author Louis Charette - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Compte d'utilisateur", - - "ACCESS_DENIED" => "Hmm, on dirait que vous n'avez pas la permission de faire ceci.", - - "DISABLED" => "Ce compte a été désactivé. Veuillez nous contacter pour plus d'informations.", - - "EMAIL_UPDATED" => "Adresse email mise à jour", - - "INVALID" => "Ce compte n'existe pas. Il a peut-être été supprimé. Veuillez nous contacter pour plus d'informations.", - - "MASTER_NOT_EXISTS" => "Vous ne pouvez pas enregistrer un compte tant que le compte principal n'a pas été créé!", - "MY" => "Mon compte", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Votre session a été compromise. Vous devez vous déconnecter de tous les périphériques, puis vous reconnecter et vous assurer que vos données n'ont pas été altérées.", - "TITLE" => "Votre compte peut avoir été compromis" - ], - "SESSION_EXPIRED" => "Votre session a expiré. Veuillez vous connecter à nouveau.", - - "SETTINGS" => [ - "@TRANSLATION" => "Paramètres du compte", - "DESCRIPTION" => "Mettez à jour les paramètres de votre compte, y compris votre adresse e-mail, votre nom et votre mot de passe.", - "UPDATED" => "Paramètres du compte mis à jour" - ], - - "TOOLS" => "Outils du compte", - - "UNVERIFIED" => "Votre compte n'a pas encore été vérifié. Vérifiez vos emails / dossier spam pour les instructions d'activation du compte.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Nous avons envoyé un nouveau lien de vérification à {{email}}. Veuillez vérifier vos dossiers de boîte de réception et de spam pour ce courriel.", - "RESEND" => "Renvoyer le courriel de validation", - "COMPLETE" => "Votre compte a été validé. Vous pouvez maintenant vous connecter.", - "EMAIL" => "Veuillez saisir l'adresse email que vous avez utilisée pour vous inscrire et votre courriel de vérification sera renvoyé.", - "PAGE" => "Renvoyer l'email de validation de votre nouveau compte.", - "SEND" => "Envoyer le lien de validation de mon compte", - "TOKEN_NOT_FOUND" => "Le jeton de vérification n'existe pas / Le compte est déjà vérifié", - ] - ], - - "EMAIL" => [ - "INVALID" => "Il n'y a aucun compte pour <strong>{{email}}</strong>.", - "IN_USE" => "Le email <strong>{{email}}</strong> est déjà utilisé.", - "VERIFICATION_REQUIRED" => "Email (vérification requise - utiliser une adresse réelle!)" - ], - - "EMAIL_OR_USERNAME" => "Nom d'utilisateur ou adresse email", - - "FIRST_NAME" => "Prénom", - - "HEADER_MESSAGE_ROOT" => "VOUS ÊTES CONNECTÉ EN TANT QUE L'UTILISATEUR ROOT", - - "LAST_NAME" => "Nom de famille", - - "LOCALE" => [ - "ACCOUNT" => "La langue utilisé pour votre compte d'utilisateur", - "INVALID" => "<strong>{{locale}}</strong> n'est pas une langue valide." - ], - - "LOGIN" => [ - "@TRANSLATION" => "Connexion", - "ALREADY_COMPLETE" => "Vous êtes déjà connecté!", - "SOCIAL" => "Ou se connecter avec", - "REQUIRED" => "Désolé, vous devez être connecté pour accéder à cette ressource." - ], - - "LOGOUT" => "Déconnexion", - - "NAME" => "Nom", - - "NAME_AND_EMAIL" => "Nom et email", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Connectez-vous à votre compte {{site_name}} ou enregistrez-vous pour un nouveau compte.", - "SUBTITLE" => "Inscrivez-vous gratuitement ou connectez-vous avec un compte existant.", - "TITLE" => "Commençons!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Mot de passe", - - "BETWEEN" => "Entre {{min}} et {{max}} charactères", - - "CONFIRM" => "Confirmer le mot de passe", - "CONFIRM_CURRENT" => "Veuillez confirmer votre mot de passe actuel", - "CONFIRM_NEW" => "Confirmer le nouveau mot de passe", - "CONFIRM_NEW_EXPLAIN" => "Confirmer le mot de passe", - "CONFIRM_NEW_HELP" => "Obligatoire uniquement si vous sélectionnez un nouveau mot de passe", - "CURRENT" => "Mot de passe actuel", - "CURRENT_EXPLAIN" => "Vous devez confirmer votre mot de passe actuel pour apporter des modifications", - - "FORGOTTEN" => "Mot de passe oublié", - "FORGET" => [ - "@TRANSLATION" => "J'ai oublié mon mot de passe", - - "COULD_NOT_UPDATE" => "Impossible de mettre à jour le mot de passe.", - "EMAIL" => "Veuillez saisir l'adresse e-mail que vous avez utilisée pour vous inscrire. Un lien avec les instructions pour réinitialiser votre mot de passe vous sera envoyé par email.", - "EMAIL_SEND" => "Envoyer le lien de réinitialisation", - "INVALID" => "Cette requête de réinitialisation de mot de passe n'a pas pu être trouvée ou a expiré. Veuillez réessayer <a href=\"{{url}}\"> de soumettre votre demande <a>.", - "PAGE" => "Obtenir un lien pour réinitialiser votre mot de passe.", - "REQUEST_CANNED" => "Demande de mot de passe perdu annulée.", - "REQUEST_SENT" => "Si l'adresse e-mail <strong>{{email}}</strong> correspond à un compte dans notre système, un lien de réinitialisation de mot de passe sera envoyé à <strong>{{email}}</strong>." - ], - - "RESET" => [ - "@TRANSLATION" => "Réinitialiser le mot de passe", - "CHOOSE" => "Veuillez choisir un nouveau mot de passe pour continuer.", - "PAGE" => "Choisissez un nouveau mot de passe pour votre compte.", - "SEND" => "Définir un nouveau mot de passe" - ], - - "HASH_FAILED" => "Le hachage du mot de passe a échoué. Veuillez contacter un administrateur de site.", - "INVALID" => "Le mot de passe actuel ne correspond pas à celui que nous avons au dossier", - "NEW" => "Nouveau mot de passe", - "NOTHING_TO_UPDATE" => "Vous ne pouvez pas mettre à jour avec le même mot de passe", - "UPDATED" => "Mot de passe du compte mis à jour" - ], - - "PROFILE" => [ - "SETTINGS" => "Paramètres du profil", - "UPDATED" => "Paramètres du profil mis à jour" - ], - - "REGISTER" => "S'inscrire", - "REGISTER_ME" => "S'inscrire", - - "REGISTRATION" => [ - "BROKEN" => "Nous sommes désolés, il ya un problème avec notre processus d'enregistrement de compte. Veuillez nous contacter directement pour obtenir de l'aide.", - "COMPLETE_TYPE1" => "Vous êtes inscrit avec succès. Vous pouvez maintenant vous connecter.", - "COMPLETE_TYPE2" => "Vous êtes inscrit avec succès. Vous recevrez bientôt un e-mail de validation contenant un lien pour activer votre compte. Vous ne pourrez pas vous connecter avant d'avoir terminé cette étape.", - "DISABLED" => "Désolé, l'enregistrement de compte a été désactivé.", - "LOGOUT" => "Désolé, vous ne pouvez pas vous inscrire tout en étant connecté. Veuillez vous déconnecter en premier.", - "WELCOME" => "L'inscription est rapide et simple." - ], - - "RATE_LIMIT_EXCEEDED" => "La limite de tentatives pour cette action a été dépassée. Vous devez attendre {{delay}} secondes avant de pouvoir effectuer une autre tentative.", - "REMEMBER_ME" => "Se souvenir de moi!", - "REMEMBER_ME_ON_COMPUTER" => "Se souvenir de moi sur cet ordinateur (non recommandé pour les ordinateurs publics)", - - "SIGNIN" => "Se connecter", - "SIGNIN_OR_REGISTER" => "Se connecter ou s'inscrire", - "SIGNUP" => "S'inscrire", - - "TOS" => "Termes et conditions", - "TOS_AGREEMENT" => "En créant un compte avec {{site_title}}, vous acceptez les <a {{link_attributes | raw}}>termes et conditions</a>.", - "TOS_FOR" => "Termes et conditions pour {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Nom d'utilisateur", - - "CHOOSE" => "Choisissez un nom d'utilisateur unique", - "INVALID" => "Nom d'utilisateur invalide", - "IN_USE" => "Le nom d'utilisateur '{{username}}' est déjà utilisé.", - "NOT_AVAILABLE" => "Le nom d'utilisateur <strong>{{user_name}}</strong> n'est pas disponible. Choisissez un autre nom, ou cliquez sur « suggérer »." - ], - - "USER_ID_INVALID" => "L'identifiant d'utilisateur demandé n'existe pas.", - "USER_OR_EMAIL_INVALID" => "Nom d'utilisateur ou adresse e-mail non valide.", - "USER_OR_PASS_INVALID" => "Nom d'utilisateur ou mot de passe incorrect.", - - "WELCOME" => "Bienvenue {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * French message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\fr
+ * @author Louis Charette
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Compte d'utilisateur",
+
+ "ACCESS_DENIED" => "Hmm, on dirait que vous n'avez pas la permission de faire ceci.",
+
+ "DISABLED" => "Ce compte a été désactivé. Veuillez nous contacter pour plus d'informations.",
+
+ "EMAIL_UPDATED" => "Adresse email mise à jour",
+
+ "INVALID" => "Ce compte n'existe pas. Il a peut-être été supprimé. Veuillez nous contacter pour plus d'informations.",
+
+ "MASTER_NOT_EXISTS" => "Vous ne pouvez pas enregistrer un compte tant que le compte principal n'a pas été créé!",
+ "MY" => "Mon compte",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "Votre session a été compromise. Vous devez vous déconnecter de tous les périphériques, puis vous reconnecter et vous assurer que vos données n'ont pas été altérées.",
+ "TITLE" => "Votre compte peut avoir été compromis"
+ ],
+ "SESSION_EXPIRED" => "Votre session a expiré. Veuillez vous connecter à nouveau.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Paramètres du compte",
+ "DESCRIPTION" => "Mettez à jour les paramètres de votre compte, y compris votre adresse e-mail, votre nom et votre mot de passe.",
+ "UPDATED" => "Paramètres du compte mis à jour"
+ ],
+
+ "TOOLS" => "Outils du compte",
+
+ "UNVERIFIED" => "Votre compte n'a pas encore été vérifié. Vérifiez vos emails / dossier spam pour les instructions d'activation du compte.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "Nous avons envoyé un nouveau lien de vérification à {{email}}. Veuillez vérifier vos dossiers de boîte de réception et de spam pour ce courriel.",
+ "RESEND" => "Renvoyer le courriel de validation",
+ "COMPLETE" => "Votre compte a été validé. Vous pouvez maintenant vous connecter.",
+ "EMAIL" => "Veuillez saisir l'adresse email que vous avez utilisée pour vous inscrire et votre courriel de vérification sera renvoyé.",
+ "PAGE" => "Renvoyer l'email de validation de votre nouveau compte.",
+ "SEND" => "Envoyer le lien de validation de mon compte",
+ "TOKEN_NOT_FOUND" => "Le jeton de vérification n'existe pas / Le compte est déjà vérifié",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "Il n'y a aucun compte pour <strong>{{email}}</strong>.",
+ "IN_USE" => "Le email <strong>{{email}}</strong> est déjà utilisé.",
+ "VERIFICATION_REQUIRED" => "Email (vérification requise - utiliser une adresse réelle!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Nom d'utilisateur ou adresse email",
+
+ "FIRST_NAME" => "Prénom",
+
+ "HEADER_MESSAGE_ROOT" => "VOUS ÊTES CONNECTÉ EN TANT QUE L'UTILISATEUR ROOT",
+
+ "LAST_NAME" => "Nom de famille",
+
+ "LOCALE" => [
+ "ACCOUNT" => "La langue utilisé pour votre compte d'utilisateur",
+ "INVALID" => "<strong>{{locale}}</strong> n'est pas une langue valide."
+ ],
+
+ "LOGIN" => [
+ "@TRANSLATION" => "Connexion",
+ "ALREADY_COMPLETE" => "Vous êtes déjà connecté!",
+ "SOCIAL" => "Ou se connecter avec",
+ "REQUIRED" => "Désolé, vous devez être connecté pour accéder à cette ressource."
+ ],
+
+ "LOGOUT" => "Déconnexion",
+
+ "NAME" => "Nom",
+
+ "NAME_AND_EMAIL" => "Nom et email",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Connectez-vous à votre compte {{site_name}} ou enregistrez-vous pour un nouveau compte.",
+ "SUBTITLE" => "Inscrivez-vous gratuitement ou connectez-vous avec un compte existant.",
+ "TITLE" => "Commençons!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Mot de passe",
+
+ "BETWEEN" => "Entre {{min}} et {{max}} charactères",
+
+ "CONFIRM" => "Confirmer le mot de passe",
+ "CONFIRM_CURRENT" => "Veuillez confirmer votre mot de passe actuel",
+ "CONFIRM_NEW" => "Confirmer le nouveau mot de passe",
+ "CONFIRM_NEW_EXPLAIN" => "Confirmer le mot de passe",
+ "CONFIRM_NEW_HELP" => "Obligatoire uniquement si vous sélectionnez un nouveau mot de passe",
+ "CURRENT" => "Mot de passe actuel",
+ "CURRENT_EXPLAIN" => "Vous devez confirmer votre mot de passe actuel pour apporter des modifications",
+
+ "FORGOTTEN" => "Mot de passe oublié",
+ "FORGET" => [
+ "@TRANSLATION" => "J'ai oublié mon mot de passe",
+
+ "COULD_NOT_UPDATE" => "Impossible de mettre à jour le mot de passe.",
+ "EMAIL" => "Veuillez saisir l'adresse e-mail que vous avez utilisée pour vous inscrire. Un lien avec les instructions pour réinitialiser votre mot de passe vous sera envoyé par email.",
+ "EMAIL_SEND" => "Envoyer le lien de réinitialisation",
+ "INVALID" => "Cette requête de réinitialisation de mot de passe n'a pas pu être trouvée ou a expiré. Veuillez réessayer <a href=\"{{url}}\"> de soumettre votre demande <a>.",
+ "PAGE" => "Obtenir un lien pour réinitialiser votre mot de passe.",
+ "REQUEST_CANNED" => "Demande de mot de passe perdu annulée.",
+ "REQUEST_SENT" => "Si l'adresse e-mail <strong>{{email}}</strong> correspond à un compte dans notre système, un lien de réinitialisation de mot de passe sera envoyé à <strong>{{email}}</strong>."
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "Réinitialiser le mot de passe",
+ "CHOOSE" => "Veuillez choisir un nouveau mot de passe pour continuer.",
+ "PAGE" => "Choisissez un nouveau mot de passe pour votre compte.",
+ "SEND" => "Définir un nouveau mot de passe"
+ ],
+
+ "HASH_FAILED" => "Le hachage du mot de passe a échoué. Veuillez contacter un administrateur de site.",
+ "INVALID" => "Le mot de passe actuel ne correspond pas à celui que nous avons au dossier",
+ "NEW" => "Nouveau mot de passe",
+ "NOTHING_TO_UPDATE" => "Vous ne pouvez pas mettre à jour avec le même mot de passe",
+ "UPDATED" => "Mot de passe du compte mis à jour"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Paramètres du profil",
+ "UPDATED" => "Paramètres du profil mis à jour"
+ ],
+
+ "REGISTER" => "S'inscrire",
+ "REGISTER_ME" => "S'inscrire",
+
+ "REGISTRATION" => [
+ "BROKEN" => "Nous sommes désolés, il ya un problème avec notre processus d'enregistrement de compte. Veuillez nous contacter directement pour obtenir de l'aide.",
+ "COMPLETE_TYPE1" => "Vous êtes inscrit avec succès. Vous pouvez maintenant vous connecter.",
+ "COMPLETE_TYPE2" => "Vous êtes inscrit avec succès. Vous recevrez bientôt un e-mail de validation contenant un lien pour activer votre compte. Vous ne pourrez pas vous connecter avant d'avoir terminé cette étape.",
+ "DISABLED" => "Désolé, l'enregistrement de compte a été désactivé.",
+ "LOGOUT" => "Désolé, vous ne pouvez pas vous inscrire tout en étant connecté. Veuillez vous déconnecter en premier.",
+ "WELCOME" => "L'inscription est rapide et simple."
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "La limite de tentatives pour cette action a été dépassée. Vous devez attendre {{delay}} secondes avant de pouvoir effectuer une autre tentative.",
+ "REMEMBER_ME" => "Se souvenir de moi!",
+ "REMEMBER_ME_ON_COMPUTER" => "Se souvenir de moi sur cet ordinateur (non recommandé pour les ordinateurs publics)",
+
+ "SIGNIN" => "Se connecter",
+ "SIGNIN_OR_REGISTER" => "Se connecter ou s'inscrire",
+ "SIGNUP" => "S'inscrire",
+
+ "TOS" => "Termes et conditions",
+ "TOS_AGREEMENT" => "En créant un compte avec {{site_title}}, vous acceptez les <a {{link_attributes | raw}}>termes et conditions</a>.",
+ "TOS_FOR" => "Termes et conditions pour {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Nom d'utilisateur",
+
+ "CHOOSE" => "Choisissez un nom d'utilisateur unique",
+ "INVALID" => "Nom d'utilisateur invalide",
+ "IN_USE" => "Le nom d'utilisateur '{{username}}' est déjà utilisé.",
+ "NOT_AVAILABLE" => "Le nom d'utilisateur <strong>{{user_name}}</strong> n'est pas disponible. Choisissez un autre nom, ou cliquez sur « suggérer »."
+ ],
+
+ "USER_ID_INVALID" => "L'identifiant d'utilisateur demandé n'existe pas.",
+ "USER_OR_EMAIL_INVALID" => "Nom d'utilisateur ou adresse e-mail non valide.",
+ "USER_OR_PASS_INVALID" => "Nom d'utilisateur ou mot de passe incorrect.",
+
+ "WELCOME" => "Bienvenue {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/fr_FR/validate.php b/main/app/sprinkles/account/locale/fr_FR/validate.php index 2d4d65f..6e146ea 100644 --- a/main/app/sprinkles/account/locale/fr_FR/validate.php +++ b/main/app/sprinkles/account/locale/fr_FR/validate.php @@ -1,18 +1,18 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * French message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\fr - * @author Louis Charette - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Votre mot de passe et votre mot de passe de confirmation doivent correspondre." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * French message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\fr
+ * @author Louis Charette
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "Votre mot de passe et votre mot de passe de confirmation doivent correspondre."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/it_IT/messages.php b/main/app/sprinkles/account/locale/it_IT/messages.php index 3c765b5..ea4da36 100644 --- a/main/app/sprinkles/account/locale/it_IT/messages.php +++ b/main/app/sprinkles/account/locale/it_IT/messages.php @@ -1,186 +1,186 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Italian message token translations for the 'account' sprinkle. - * This translation was generated with Google translate. Please contribute if you are a native speaker. - * - * @package userfrosting\i18n\it - * @author Alexander Weissman - * @author Pietro Marangon (@Pe46dro) - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Account", - - "ACCESS_DENIED" => "Sembra tu non abbiamo il permesso di fare questo.", - - "DISABLED" => "Questo account è stato disattivato, contattaci per maggiori informazioni", - - "EMAIL_UPDATED" => "Email aggiornata", - - "INVALID" => "Questo account non esiste. Può essere stato cancellato. Vi preghiamo di contattarci per ulteriori informazioni.", - - "MASTER_NOT_EXISTS" => "Non puoi registrare un account finche l'account primario non sarà creato!", - "MY" => "Il mio account", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "La tua sessione è stata compromessa. Devi eseguire il logout su tutti i dispositivi, quindi riaccenderti e assicurati che i tuoi dati non siano stati manomessi.", - "TITLE" => "Il tuo account potrebbe essere stato compromesso", - "TEXT" => "Qualcuno potrebbe aver utilizzato le tue informazioni di accesso per accedere a questa pagina. Per la tua sicurezza tutte le sessioni sono state disconnesse. <a href=\"{{url}}\">Accedi</a> e controlla l'account per attività sospette. Potresti anche desiderare di cambiare la tua password." - ], - "SESSION_EXPIRED" => "La tua sessione è scaduta. Accedi nuovamente.", - - "SETTINGS" => [ - "@TRANSLATION" => "Impostazioni dell 'account", - "DESCRIPTION" => "Aggiorna le impostazioni del tuo account, tra cui email, nome e password.", - "UPDATED" => "Impostazioni account aggiornate" - ], - - "TOOLS" => "Account tools", - - "UNVERIFIED" => "Il tuo account non è stato attivato. Controlla nella tua mail ( anche nella cartella dello spam ) per riceve le instruzioni per attivare il tuo account", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Ti è stato inviato un nuovo codice di attivazione, controlla la tua email ({{email}}).", - "RESEND" => "Invia nuovamente email di verifica.", - "COMPLETE" => "Hai verificato con successo il tuo account. È ora possibile accedere.", - "EMAIL" => "Inserisci l'indirizzo email che hai utilizzato per registrarti e la tua email di verifica sarà resentata.", - "PAGE" => "Ripeti l'email di verifica per il tuo nuovo account.", - "SEND" => "Inviilo il collegamento di verifica per il mio account", - "TOKEN_NOT_FOUND" => "Il token non esiste / l'account è già stato attivato" - ] - ], - - "EMAIL" => [ - "INVALID" => "Non esiste alcun account per <strong>{{email}}</strong>.", - "IN_USE" => "L'email '{{email}}' è già in uso", - "VERIFICATION_REQUIRED" => "Email (verifica richiesta - utilizzare un indirizzo reale!)" - ], - - "EMAIL_OR_USERNAME" => "Username o Indirizzo Email", - - "FIRST_NAME" => "Nome", - - "HEADER_MESSAGE_ROOT" => "LOGGATO COME ROOT", - - "LAST_NAME" => "Cognome", - "LOCALE" => [ - "ACCOUNT" => "La lingua e la località da utilizzare per il tuo account", - "INVALID" => "<strong>{{locale}}</strong> non è una località valida.", - - - ], - "LOGIN" => [ - "@TRANSLATION" => "Accesso", - "ALREADY_COMPLETE" => "Sei già loggato!", - "SOCIAL" => "O accedi con", - "REQUIRED" => "Devi essere loggato per accedere a questa risorsa" - ], - "LOGOUT" => "Logout", - - "NAME" => "Nome", - - "NAME_AND_EMAIL" => "Nome e email", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Accedi al tuo account {{site_name}} o registrati per un nuovo account.", - "SUBTITLE" => "Registrati gratuitamente o accedi con un account esistente.", - "TITLE" => "Iniziamo!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Password", - - "BETWEEN" => "La password deve essere tra {{min}} e i {{max}} caratteri", - - "CONFIRM" => "Conferma la password", - "CONFIRM_CURRENT" => "Conferma la password attuale", - "CONFIRM_NEW" => "Conferma la tua nuova password", - "CONFIRM_NEW_EXPLAIN" => "Inserisci nuovamente la nuova password", - "CONFIRM_NEW_HELP" => "Richiesto solo se si seleziona una nuova password", - "CREATE" => [ - "@TRANSLATION" => "Crea password", - "PAGE" => "Scegli una password per il tuo nuovo account.", - "SET" => "Imposta password e accedi" - ], - "CURRENT" => "Password attuale", - "CURRENT_EXPLAIN" => "Devi confermare la tua password corrente per apportare modifiche", - - "FORGOTTEN" => "Password dimenticata", - "FORGET" => [ - "@TRANSLATION" => "Ho dimenticato la mia password", - - "COULD_NOT_UPDATE" => "Password non aggiornata", - "EMAIL" => "Inserisci l'indirizzo email che hai utilizzato per iscriverti. Un collegamento con le istruzioni per reimpostare la tua password verrà inviata via email.", - "EMAIL_SEND" => "Email link di resetta password", - "INVALID" => "Questa richiesta di ripristino della password non è stata trovata o è scaduta. Prova a <a href=\"{{url}}\">riprovare</a> la tua richiesta.", - "PAGE" => "Ottieni un collegamento per reimpostare la tua password.", - "REQUEST_CANNED" => "Richiesta di recupero password cancellata.", - "REQUEST_SENT" => "Se l'email <strong>{{email}}</strong> corrisponde a un account nel nostro sistema, verrà inviato un collegamento per la reimpostazione della password a <strong>{{email}}</strong>." - ], - - "HASH_FAILED" => "Hash della password fallito. Contatta l'amministratore di sistema.", - "INVALID" => "La password corrente non corrisponde con quella in memoria", - "NEW" => "Nuova Password", - "NOTHING_TO_UPDATE" => "Non puoi aggiornare con la stessa password", - - "RESET" => [ - "@TRANSLATION" => "Resetta la Password", - "CHOOSE" => "Inserisci la tua nuova password", - "PAGE" => "Scegli una nuova password per il tuo account.", - "SEND" => "Impostare nuova password e accedere" - ], - - "UPDATED" => "Password aggiornata" - ], - - "PROFILE" => [ - "SETTINGS" => "Impostazioni del profilo", - "UPDATED" => "Le impostazioni del profilo sono aggiornate" - ], - - "RATE_LIMIT_EXCEEDED" => "Il limite di velocità per questa azione è stato superato. Devi aspettare un altro {{delay}} secondi prima che ti sia permesso di fare un altro tentativo.", - "REGISTER" => "Registrare", - "REGISTER_ME" => "Iscrivimi", - "REGISTRATION" => [ - "BROKEN" => "Ci dispiace, c'è un problema con il nostro processo di registrazione dell'account. Vi preghiamo di contattarci direttamente per assistenza.", - "COMPLETE_TYPE1" => "Sei stato registrato con successo ora puoi eseguire il login", - "COMPLETE_TYPE2" => "Sei stato registrato con successo. Riceverai presto una mail a <strong>{{email}}</strong> per l'attivazione. Devi attivare il tuo account prima di eseguire il login.", - "DISABLED" => "La registrazione di nuovi account è stata bloccata", - "LOGOUT" => "Non è possibile registrare un account mentre si è loggati", - "WELCOME" => "La registrazione è semplice e veloce" - ], - "REMEMBER_ME" => "Ricordami!", - "REMEMBER_ME_ON_COMPUTER" => "Ricordami su questo computer (non consigliato per i computer pubblici)", - - "SIGN_IN_HERE" => "Hai già un account? <a href=\"{{url}}\">Accedi qui</a>", - "SIGNIN" => "Accedi", - "SIGNIN_OR_REGISTER" => "Accedi o registri", - "SIGNUP" => "Registrazione", - - "TOS" => "Termini e condizioni", - "TOS_AGREEMENT" => "Registrando un account con {{site_title}}, accetti il <a {{link_attributes | raw}}>termini e condizioni</a>.", - "TOS_FOR" => "Termini e condizioni per {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Username", - - "CHOOSE" => "Inserisci il tuo username", - "INVALID" => "Username non valido", - "IN_USE" => "Il nome utente '{{user_name}}' è già in uso", - "NOT_AVAILABLE" => "Il nome utente <strong>{{user_name}}</strong> non è disponibile. Scegli un nome diverso, oppure fai clic su \"suggerisci\"." - ], - - "USER_ID_INVALID" => "User ID richiesto non è valido", - "USER_OR_EMAIL_INVALID" => "L'indirizzo mail o il nome utente non sono validi", - "USER_OR_PASS_INVALID" => "Il nome utente o la password non sono validi", - - "WELCOME" => "Bentornato, {{display_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Italian message token translations for the 'account' sprinkle.
+ * This translation was generated with Google translate. Please contribute if you are a native speaker.
+ *
+ * @package userfrosting\i18n\it
+ * @author Alexander Weissman
+ * @author Pietro Marangon (@Pe46dro)
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Account",
+
+ "ACCESS_DENIED" => "Sembra tu non abbiamo il permesso di fare questo.",
+
+ "DISABLED" => "Questo account è stato disattivato, contattaci per maggiori informazioni",
+
+ "EMAIL_UPDATED" => "Email aggiornata",
+
+ "INVALID" => "Questo account non esiste. Può essere stato cancellato. Vi preghiamo di contattarci per ulteriori informazioni.",
+
+ "MASTER_NOT_EXISTS" => "Non puoi registrare un account finche l'account primario non sarà creato!",
+ "MY" => "Il mio account",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "La tua sessione è stata compromessa. Devi eseguire il logout su tutti i dispositivi, quindi riaccenderti e assicurati che i tuoi dati non siano stati manomessi.",
+ "TITLE" => "Il tuo account potrebbe essere stato compromesso",
+ "TEXT" => "Qualcuno potrebbe aver utilizzato le tue informazioni di accesso per accedere a questa pagina. Per la tua sicurezza tutte le sessioni sono state disconnesse. <a href=\"{{url}}\">Accedi</a> e controlla l'account per attività sospette. Potresti anche desiderare di cambiare la tua password."
+ ],
+ "SESSION_EXPIRED" => "La tua sessione è scaduta. Accedi nuovamente.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Impostazioni dell 'account",
+ "DESCRIPTION" => "Aggiorna le impostazioni del tuo account, tra cui email, nome e password.",
+ "UPDATED" => "Impostazioni account aggiornate"
+ ],
+
+ "TOOLS" => "Account tools",
+
+ "UNVERIFIED" => "Il tuo account non è stato attivato. Controlla nella tua mail ( anche nella cartella dello spam ) per riceve le instruzioni per attivare il tuo account",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "Ti è stato inviato un nuovo codice di attivazione, controlla la tua email ({{email}}).",
+ "RESEND" => "Invia nuovamente email di verifica.",
+ "COMPLETE" => "Hai verificato con successo il tuo account. È ora possibile accedere.",
+ "EMAIL" => "Inserisci l'indirizzo email che hai utilizzato per registrarti e la tua email di verifica sarà resentata.",
+ "PAGE" => "Ripeti l'email di verifica per il tuo nuovo account.",
+ "SEND" => "Inviilo il collegamento di verifica per il mio account",
+ "TOKEN_NOT_FOUND" => "Il token non esiste / l'account è già stato attivato"
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "Non esiste alcun account per <strong>{{email}}</strong>.",
+ "IN_USE" => "L'email '{{email}}' è già in uso",
+ "VERIFICATION_REQUIRED" => "Email (verifica richiesta - utilizzare un indirizzo reale!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Username o Indirizzo Email",
+
+ "FIRST_NAME" => "Nome",
+
+ "HEADER_MESSAGE_ROOT" => "LOGGATO COME ROOT",
+
+ "LAST_NAME" => "Cognome",
+ "LOCALE" => [
+ "ACCOUNT" => "La lingua e la località da utilizzare per il tuo account",
+ "INVALID" => "<strong>{{locale}}</strong> non è una località valida.",
+
+
+ ],
+ "LOGIN" => [
+ "@TRANSLATION" => "Accesso",
+ "ALREADY_COMPLETE" => "Sei già loggato!",
+ "SOCIAL" => "O accedi con",
+ "REQUIRED" => "Devi essere loggato per accedere a questa risorsa"
+ ],
+ "LOGOUT" => "Logout",
+
+ "NAME" => "Nome",
+
+ "NAME_AND_EMAIL" => "Nome e email",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Accedi al tuo account {{site_name}} o registrati per un nuovo account.",
+ "SUBTITLE" => "Registrati gratuitamente o accedi con un account esistente.",
+ "TITLE" => "Iniziamo!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Password",
+
+ "BETWEEN" => "La password deve essere tra {{min}} e i {{max}} caratteri",
+
+ "CONFIRM" => "Conferma la password",
+ "CONFIRM_CURRENT" => "Conferma la password attuale",
+ "CONFIRM_NEW" => "Conferma la tua nuova password",
+ "CONFIRM_NEW_EXPLAIN" => "Inserisci nuovamente la nuova password",
+ "CONFIRM_NEW_HELP" => "Richiesto solo se si seleziona una nuova password",
+ "CREATE" => [
+ "@TRANSLATION" => "Crea password",
+ "PAGE" => "Scegli una password per il tuo nuovo account.",
+ "SET" => "Imposta password e accedi"
+ ],
+ "CURRENT" => "Password attuale",
+ "CURRENT_EXPLAIN" => "Devi confermare la tua password corrente per apportare modifiche",
+
+ "FORGOTTEN" => "Password dimenticata",
+ "FORGET" => [
+ "@TRANSLATION" => "Ho dimenticato la mia password",
+
+ "COULD_NOT_UPDATE" => "Password non aggiornata",
+ "EMAIL" => "Inserisci l'indirizzo email che hai utilizzato per iscriverti. Un collegamento con le istruzioni per reimpostare la tua password verrà inviata via email.",
+ "EMAIL_SEND" => "Email link di resetta password",
+ "INVALID" => "Questa richiesta di ripristino della password non è stata trovata o è scaduta. Prova a <a href=\"{{url}}\">riprovare</a> la tua richiesta.",
+ "PAGE" => "Ottieni un collegamento per reimpostare la tua password.",
+ "REQUEST_CANNED" => "Richiesta di recupero password cancellata.",
+ "REQUEST_SENT" => "Se l'email <strong>{{email}}</strong> corrisponde a un account nel nostro sistema, verrà inviato un collegamento per la reimpostazione della password a <strong>{{email}}</strong>."
+ ],
+
+ "HASH_FAILED" => "Hash della password fallito. Contatta l'amministratore di sistema.",
+ "INVALID" => "La password corrente non corrisponde con quella in memoria",
+ "NEW" => "Nuova Password",
+ "NOTHING_TO_UPDATE" => "Non puoi aggiornare con la stessa password",
+
+ "RESET" => [
+ "@TRANSLATION" => "Resetta la Password",
+ "CHOOSE" => "Inserisci la tua nuova password",
+ "PAGE" => "Scegli una nuova password per il tuo account.",
+ "SEND" => "Impostare nuova password e accedere"
+ ],
+
+ "UPDATED" => "Password aggiornata"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Impostazioni del profilo",
+ "UPDATED" => "Le impostazioni del profilo sono aggiornate"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "Il limite di velocità per questa azione è stato superato. Devi aspettare un altro {{delay}} secondi prima che ti sia permesso di fare un altro tentativo.",
+ "REGISTER" => "Registrare",
+ "REGISTER_ME" => "Iscrivimi",
+ "REGISTRATION" => [
+ "BROKEN" => "Ci dispiace, c'è un problema con il nostro processo di registrazione dell'account. Vi preghiamo di contattarci direttamente per assistenza.",
+ "COMPLETE_TYPE1" => "Sei stato registrato con successo ora puoi eseguire il login",
+ "COMPLETE_TYPE2" => "Sei stato registrato con successo. Riceverai presto una mail a <strong>{{email}}</strong> per l'attivazione. Devi attivare il tuo account prima di eseguire il login.",
+ "DISABLED" => "La registrazione di nuovi account è stata bloccata",
+ "LOGOUT" => "Non è possibile registrare un account mentre si è loggati",
+ "WELCOME" => "La registrazione è semplice e veloce"
+ ],
+ "REMEMBER_ME" => "Ricordami!",
+ "REMEMBER_ME_ON_COMPUTER" => "Ricordami su questo computer (non consigliato per i computer pubblici)",
+
+ "SIGN_IN_HERE" => "Hai già un account? <a href=\"{{url}}\">Accedi qui</a>",
+ "SIGNIN" => "Accedi",
+ "SIGNIN_OR_REGISTER" => "Accedi o registri",
+ "SIGNUP" => "Registrazione",
+
+ "TOS" => "Termini e condizioni",
+ "TOS_AGREEMENT" => "Registrando un account con {{site_title}}, accetti il <a {{link_attributes | raw}}>termini e condizioni</a>.",
+ "TOS_FOR" => "Termini e condizioni per {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Username",
+
+ "CHOOSE" => "Inserisci il tuo username",
+ "INVALID" => "Username non valido",
+ "IN_USE" => "Il nome utente '{{user_name}}' è già in uso",
+ "NOT_AVAILABLE" => "Il nome utente <strong>{{user_name}}</strong> non è disponibile. Scegli un nome diverso, oppure fai clic su \"suggerisci\"."
+ ],
+
+ "USER_ID_INVALID" => "User ID richiesto non è valido",
+ "USER_OR_EMAIL_INVALID" => "L'indirizzo mail o il nome utente non sono validi",
+ "USER_OR_PASS_INVALID" => "Il nome utente o la password non sono validi",
+
+ "WELCOME" => "Bentornato, {{display_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/it_IT/validate.php b/main/app/sprinkles/account/locale/it_IT/validate.php index 9fc7884..511ea61 100644 --- a/main/app/sprinkles/account/locale/it_IT/validate.php +++ b/main/app/sprinkles/account/locale/it_IT/validate.php @@ -1,21 +1,21 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Italian message token translations for the 'account' sprinkle. - * This translation was generated with Google translate. Please contribute if you are a native speaker. - * - * @package userfrosting\i18n\it - * @author Alexander Weissman - * @author Pietro Marangon (@Pe46dro) - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "I due campi devono combaciare", - "USERNAME" => "L'username può essere composto da caratteri alfanumerici, '.', '-', e '_'." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Italian message token translations for the 'account' sprinkle.
+ * This translation was generated with Google translate. Please contribute if you are a native speaker.
+ *
+ * @package userfrosting\i18n\it
+ * @author Alexander Weissman
+ * @author Pietro Marangon (@Pe46dro)
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "I due campi devono combaciare",
+ "USERNAME" => "L'username può essere composto da caratteri alfanumerici, '.', '-', e '_'."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/pt_PT/messages.php b/main/app/sprinkles/account/locale/pt_PT/messages.php index 0e8f3e1..4b0c2e4 100644 --- a/main/app/sprinkles/account/locale/pt_PT/messages.php +++ b/main/app/sprinkles/account/locale/pt_PT/messages.php @@ -1,166 +1,166 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Portuguese message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\pt - * @author Bruno Silva (brunomnsilva@gmail.com) - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Conta", - - "ACCESS_DENIED" => "Hmm, parece que não tem permissões para fazer isso.", - - "DISABLED" => "Esta conta foi desativada. Por favor contacte-nos para mais informações.", - - "EMAIL_UPDATED" => "Email da conta atualizado", - - "INVALID" => "Esta conta não existe. Pode ter sido removida. Por favor contacte-nos para mais informações.", - - "MASTER_NOT_EXISTS" => "Não pode registrar uma conta enquanto a conta principal não for criada!", - "MY" => "A minha conta", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "A sua sessão foi comprometida. Deverá fechar todas as sessões, voltar a iniciar sessão e verificar que os seus dados não foram alterados por alheios.", - "TITLE" => "A sua sessão pode ter sido comprometida" - ], - "SESSION_EXPIRED" => "A sua sessão expirou. Por favor inicie nova sessão.", - - "SETTINGS" => [ - "@TRANSLATION" => "Definições de conta", - "DESCRIPTION" => "Atualize as suas definições, incluindo email, nome e password.", - "UPDATED" => "Definições de conta atualizadas" - ], - - "TOOLS" => "Ferramentas de conta", - - "UNVERIFIED" => "A sua conta ainda não foi verificada. Consulte o seu email (incluindo a pasta de spam) para instruções de ativação.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Enviámos um link de verificação para o endereço {{email}}. Por favor consulte o seu email (incluindo a pasta de spam).", - "RESEND" => "Enviar novamente email de verificação", - "COMPLETE" => "Verificou com sucesso a sua conta. Pode iniciar sessão.", - "EMAIL" => "Por favor introduza o endereço de email que utilizou no registro e um email de verificação será enviado.", - "PAGE" => "Reenviar email de verificação para a sua nova conta.", - "SEND" => "Enviar email com link de verificação", - "TOKEN_NOT_FOUND" => "Token de verificação inexistente / Conta já verificada", - ] - ], - - "EMAIL" => [ - "INVALID" => "Não existe nenhuma conta para <strong>{{email}}</strong>.", - "IN_USE" => "O email <strong>{{email}}</strong> já se encontra em uso." - ], - - "FIRST_NAME" => "Primeiro nome", - - "HEADER_MESSAGE_ROOT" => "INICIOU SESSÃO COM A CONTA ROOT", - - "LAST_NAME" => "Último nome", - - "LOCALE.ACCOUNT" => "Linguagem e localização a utilizar na sua conta", - - "LOGIN" => [ - "@TRANSLATION" => "Entrar", - - "ALREADY_COMPLETE" => "Sessão já iniciada!", - "SOCIAL" => "Ou inicie sessão com", - "REQUIRED" => "Lamentamos, tem de iniciar sessão para aceder a este recurso." - ], - - "LOGOUT" => "Sair", - - "NAME" => "Nome", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Inicie sessão na sua conta {{site_name}}, ou registre-se para uma nova conta.", - "SUBTITLE" => "Registre-se gratuitamente, ou inicie sessão com uma conta existente.", - "TITLE" => "Vamos começar!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Password", - - "BETWEEN" => "Entre {{min}}-{{max}} carateres", - - "CONFIRM" => "Confirme a password", - "CONFIRM_CURRENT" => "Por favor confirme a sua password atual", - "CONFIRM_NEW" => "Confirmar Nova Password", - "CONFIRM_NEW_EXPLAIN" => "Re-introduza a sua nova password", - "CONFIRM_NEW_HELP" => "Apenas necessário se escolher uma nova password", - "CURRENT" => "Password Atual", - "CURRENT_EXPLAIN" => "Tem de confirmar a sua password atual para efetuar alterações", - - "FORGOTTEN" => "Password Esquecida", - "FORGET" => [ - "@TRANSLATION" => "Esqueci a minha password", - - "COULD_NOT_UPDATE" => "Não foi possível atualizar a password.", - "EMAIL" => "Por favor introduza o endereço de email que utilizou no registro. Enviaremos um email com instruções para efetuar o reset à sua password.", - "EMAIL_SEND" => "Enviar email com link de reset da password", - "INVALID" => "This password reset request could not be found, or has expired. Please try <a href=\"{{url}}\">resubmitting your request<a>.", - "PAGE" => "Obtenha um link para fazer reset à sua password.", - "REQUEST_CANNED" => "Pedido de password esquecida foi cancelado.", - "REQUEST_SENT" => "Se o email <strong>{{email}}</strong> corresponder a uma conta em nosso sistema, um link de redefinição de senha será enviado para <strong>{{email}}</strong>." - ], - - "RESET" => [ - "@TRANSLATION" => "Reset Password", - "CHOOSE" => "Por favor escolha uma nova password para continuar.", - "PAGE" => "Escolha uma nova password para a sua conta.", - "SEND" => "Definir nova password e registrar" - ], - - "HASH_FAILED" => "Falhou o hashing da password. Por favor contacte um administrador do site.", - "INVALID" => "A password atual não coincide com a que temos em sistema", - "NEW" => "Nova Password", - "NOTHING_TO_UPDATE" => "Não pode atualizar para a mesma password", - "UPDATED" => "Password da conta foi atualizada" - ], - - "REGISTER" => "Registrar", - "REGISTER_ME" => "Registrar-me", - - "REGISTRATION" => [ - "BROKEN" => "Lamentamos, existe um problema com o nosso processo de registro. Contacte-nos diretamente para assistência.", - "COMPLETE_TYPE1" => "Registrou-se com sucesso. Pode iniciar sessão.", - "COMPLETE_TYPE2" => "Registrou-se com sucesso. Receberá em breve um email de verificação contendo um link para verificar a sua conta. Não será possível iniciar sessão até completar este passo.", - "DISABLED" => "Lamentamos, o registro de novas contas foi desativado.", - "LOGOUT" => "Não pode registrar uma nova conta enquanto tiver sessão iniciada. Por favor feche a sua sessão primeiro.", - "WELCOME" => "O registro é rápido e simples." - ], - - "RATE_LIMIT_EXCEEDED" => "Excedeu o número de tentativas para esta ação. Tem de aguardar {{delay}} segundos até lhe ser permitida nova tentativa.", - "REMEMBER_ME" => "Lembrar de mim!", - "REMEMBER_ME_ON_COMPUTER" => "Lembrar de mim neste computador (não recomendado em computadores públicos)", - - "SIGNIN" => "Iniciar Sessão", - "SIGNIN_OR_REGISTER" => "Iniciar sessão ou registrar", - "SIGNUP" => "Registrar", - - "TOS" => "Termos e Condições", - "TOS_AGREEMENT" => "Ao registrar uma conta em {{site_title}}, está a aceitar os <a {{link_attributes | raw}}>termos e condições</a>.", - "TOS_FOR" => "Termos e Condições para {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Nome de utilizador", - - "CHOOSE" => "Escolha um nome de utilizador único", - "INVALID" => "Nome de utilizador inválido", - "IN_USE" => "O nome de utilizador <strong>{{user_name}}</strong> já se encontra em uso." - ], - - "USER_ID_INVALID" => "O id de utilizador solicitado não existe.", - "USER_OR_EMAIL_INVALID" => "Nome de utilizador ou endereço de email inválidos.", - "USER_OR_PASS_INVALID" => "Nome de utilizador ou password inválidos.", - - "WELCOME" => "Bem-vindo, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Portuguese message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\pt
+ * @author Bruno Silva (brunomnsilva@gmail.com)
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Conta",
+
+ "ACCESS_DENIED" => "Hmm, parece que não tem permissões para fazer isso.",
+
+ "DISABLED" => "Esta conta foi desativada. Por favor contacte-nos para mais informações.",
+
+ "EMAIL_UPDATED" => "Email da conta atualizado",
+
+ "INVALID" => "Esta conta não existe. Pode ter sido removida. Por favor contacte-nos para mais informações.",
+
+ "MASTER_NOT_EXISTS" => "Não pode registrar uma conta enquanto a conta principal não for criada!",
+ "MY" => "A minha conta",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "A sua sessão foi comprometida. Deverá fechar todas as sessões, voltar a iniciar sessão e verificar que os seus dados não foram alterados por alheios.",
+ "TITLE" => "A sua sessão pode ter sido comprometida"
+ ],
+ "SESSION_EXPIRED" => "A sua sessão expirou. Por favor inicie nova sessão.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Definições de conta",
+ "DESCRIPTION" => "Atualize as suas definições, incluindo email, nome e password.",
+ "UPDATED" => "Definições de conta atualizadas"
+ ],
+
+ "TOOLS" => "Ferramentas de conta",
+
+ "UNVERIFIED" => "A sua conta ainda não foi verificada. Consulte o seu email (incluindo a pasta de spam) para instruções de ativação.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "Enviámos um link de verificação para o endereço {{email}}. Por favor consulte o seu email (incluindo a pasta de spam).",
+ "RESEND" => "Enviar novamente email de verificação",
+ "COMPLETE" => "Verificou com sucesso a sua conta. Pode iniciar sessão.",
+ "EMAIL" => "Por favor introduza o endereço de email que utilizou no registro e um email de verificação será enviado.",
+ "PAGE" => "Reenviar email de verificação para a sua nova conta.",
+ "SEND" => "Enviar email com link de verificação",
+ "TOKEN_NOT_FOUND" => "Token de verificação inexistente / Conta já verificada",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "Não existe nenhuma conta para <strong>{{email}}</strong>.",
+ "IN_USE" => "O email <strong>{{email}}</strong> já se encontra em uso."
+ ],
+
+ "FIRST_NAME" => "Primeiro nome",
+
+ "HEADER_MESSAGE_ROOT" => "INICIOU SESSÃO COM A CONTA ROOT",
+
+ "LAST_NAME" => "Último nome",
+
+ "LOCALE.ACCOUNT" => "Linguagem e localização a utilizar na sua conta",
+
+ "LOGIN" => [
+ "@TRANSLATION" => "Entrar",
+
+ "ALREADY_COMPLETE" => "Sessão já iniciada!",
+ "SOCIAL" => "Ou inicie sessão com",
+ "REQUIRED" => "Lamentamos, tem de iniciar sessão para aceder a este recurso."
+ ],
+
+ "LOGOUT" => "Sair",
+
+ "NAME" => "Nome",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Inicie sessão na sua conta {{site_name}}, ou registre-se para uma nova conta.",
+ "SUBTITLE" => "Registre-se gratuitamente, ou inicie sessão com uma conta existente.",
+ "TITLE" => "Vamos começar!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Password",
+
+ "BETWEEN" => "Entre {{min}}-{{max}} carateres",
+
+ "CONFIRM" => "Confirme a password",
+ "CONFIRM_CURRENT" => "Por favor confirme a sua password atual",
+ "CONFIRM_NEW" => "Confirmar Nova Password",
+ "CONFIRM_NEW_EXPLAIN" => "Re-introduza a sua nova password",
+ "CONFIRM_NEW_HELP" => "Apenas necessário se escolher uma nova password",
+ "CURRENT" => "Password Atual",
+ "CURRENT_EXPLAIN" => "Tem de confirmar a sua password atual para efetuar alterações",
+
+ "FORGOTTEN" => "Password Esquecida",
+ "FORGET" => [
+ "@TRANSLATION" => "Esqueci a minha password",
+
+ "COULD_NOT_UPDATE" => "Não foi possível atualizar a password.",
+ "EMAIL" => "Por favor introduza o endereço de email que utilizou no registro. Enviaremos um email com instruções para efetuar o reset à sua password.",
+ "EMAIL_SEND" => "Enviar email com link de reset da password",
+ "INVALID" => "This password reset request could not be found, or has expired. Please try <a href=\"{{url}}\">resubmitting your request<a>.",
+ "PAGE" => "Obtenha um link para fazer reset à sua password.",
+ "REQUEST_CANNED" => "Pedido de password esquecida foi cancelado.",
+ "REQUEST_SENT" => "Se o email <strong>{{email}}</strong> corresponder a uma conta em nosso sistema, um link de redefinição de senha será enviado para <strong>{{email}}</strong>."
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "Reset Password",
+ "CHOOSE" => "Por favor escolha uma nova password para continuar.",
+ "PAGE" => "Escolha uma nova password para a sua conta.",
+ "SEND" => "Definir nova password e registrar"
+ ],
+
+ "HASH_FAILED" => "Falhou o hashing da password. Por favor contacte um administrador do site.",
+ "INVALID" => "A password atual não coincide com a que temos em sistema",
+ "NEW" => "Nova Password",
+ "NOTHING_TO_UPDATE" => "Não pode atualizar para a mesma password",
+ "UPDATED" => "Password da conta foi atualizada"
+ ],
+
+ "REGISTER" => "Registrar",
+ "REGISTER_ME" => "Registrar-me",
+
+ "REGISTRATION" => [
+ "BROKEN" => "Lamentamos, existe um problema com o nosso processo de registro. Contacte-nos diretamente para assistência.",
+ "COMPLETE_TYPE1" => "Registrou-se com sucesso. Pode iniciar sessão.",
+ "COMPLETE_TYPE2" => "Registrou-se com sucesso. Receberá em breve um email de verificação contendo um link para verificar a sua conta. Não será possível iniciar sessão até completar este passo.",
+ "DISABLED" => "Lamentamos, o registro de novas contas foi desativado.",
+ "LOGOUT" => "Não pode registrar uma nova conta enquanto tiver sessão iniciada. Por favor feche a sua sessão primeiro.",
+ "WELCOME" => "O registro é rápido e simples."
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "Excedeu o número de tentativas para esta ação. Tem de aguardar {{delay}} segundos até lhe ser permitida nova tentativa.",
+ "REMEMBER_ME" => "Lembrar de mim!",
+ "REMEMBER_ME_ON_COMPUTER" => "Lembrar de mim neste computador (não recomendado em computadores públicos)",
+
+ "SIGNIN" => "Iniciar Sessão",
+ "SIGNIN_OR_REGISTER" => "Iniciar sessão ou registrar",
+ "SIGNUP" => "Registrar",
+
+ "TOS" => "Termos e Condições",
+ "TOS_AGREEMENT" => "Ao registrar uma conta em {{site_title}}, está a aceitar os <a {{link_attributes | raw}}>termos e condições</a>.",
+ "TOS_FOR" => "Termos e Condições para {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Nome de utilizador",
+
+ "CHOOSE" => "Escolha um nome de utilizador único",
+ "INVALID" => "Nome de utilizador inválido",
+ "IN_USE" => "O nome de utilizador <strong>{{user_name}}</strong> já se encontra em uso."
+ ],
+
+ "USER_ID_INVALID" => "O id de utilizador solicitado não existe.",
+ "USER_OR_EMAIL_INVALID" => "Nome de utilizador ou endereço de email inválidos.",
+ "USER_OR_PASS_INVALID" => "Nome de utilizador ou password inválidos.",
+
+ "WELCOME" => "Bem-vindo, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/pt_PT/validate.php b/main/app/sprinkles/account/locale/pt_PT/validate.php index 4acc93e..dca0111 100644 --- a/main/app/sprinkles/account/locale/pt_PT/validate.php +++ b/main/app/sprinkles/account/locale/pt_PT/validate.php @@ -1,18 +1,18 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Portuguese message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\pt - * @author Bruno Silva (brunomnsilva@gmail.com) - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "A password e respetiva confirmação têm de coincidir." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Portuguese message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\pt
+ * @author Bruno Silva (brunomnsilva@gmail.com)
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "A password e respetiva confirmação têm de coincidir."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/ru_RU/messages.php b/main/app/sprinkles/account/locale/ru_RU/messages.php index ed7c123..9149d04 100644 --- a/main/app/sprinkles/account/locale/ru_RU/messages.php +++ b/main/app/sprinkles/account/locale/ru_RU/messages.php @@ -1,183 +1,183 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Russian message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\ru_RU - * @author @rendername - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Аккаунт", - - "ACCESS_DENIED" => "Для получения доступа у вас недостаточно прав.", - - "DISABLED" => "Аккаунт отключен. Пожалуйста, свяжитесь с нами для получения дополнительной информации.", - - "EMAIL_UPDATED" => "Email аккаунта обновлён", - - "INVALID" => "Этот аккаунт не существует. Возможно, он удалён. Пожалуйста, свяжитесь с нами для получения дополнительной информации.", - - "MASTER_NOT_EXISTS" => "Вы не можете зарегистрировать аккаунт до тех пор, пока основная учётная запись не будет создана!", - "MY" => "Мой профиль", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Ваша сессия была скомпрометирована. Вы должны выйти на всех устройствах, а затем снова войти и убедиться, что ваши данные не были изменены.", - "TITLE" => "Возможно, ваш аккаунт был скомпрометированн", - "TEXT" => "Возможно, кто-то использовал ваши данные для входа на эту страницу. В целях безопасности все сеансы были завершены. Пожалуйста, повторно <a href=\"{{url}}\"> войдите </a> и проверьте свой аккаунт на подозрительную активность. Рекомендуем сменить пароль." - ], - "SESSION_EXPIRED" => "Срок вашей сессии истек. Пожалуйста войдите еще раз.", - - "SETTINGS" => [ - "@TRANSLATION" => "Настройки аккаунта", - "DESCRIPTION" => "Обновите настройки своего аккаунта, включая адрес электронной почты, имя и пароль.", - "UPDATED" => "Данные аккаунта обновлены" - ], - - "TOOLS" => "Инструменты аккаунта", - - "UNVERIFIED" => "Ваш аккаунт ещё не подтверждён. Проверьте вашу email почту, в том числе папку спам и следуйте инструкциям.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Мы отправили на ваш email новую ссылку для активации {{email}}. Пожалуйста, проверьте папку \"Входящие\" и \"Спам\".", - "RESEND" => "Повторно отправить письмо с подтверждением", - "COMPLETE" => "Вы успешно подтвердили свой аккаунт. Теперь вы можете войти.", - "EMAIL" => "Введите email, который вы использовали для регистрации, вам будет повторно отправлено письмо с подтверждением.", - "PAGE" => "Повторно оправить письмо подтверждения на email для нового аккаунта.", - "SEND" => "Проверка по электронной почте для аккаунта", - "TOKEN_NOT_FOUND" => "Код подтверждения не действителен либо аккаунт уже подтверждён", - ] - ], - - "EMAIL" => [ - "INVALID" => "Нет не одного аккаунта с <strong> {{email}} </strong>.", - "IN_USE" => "Email <strong>{{email}}</strong> уже используется.", - "VERIFICATION_REQUIRED" => "Email (указывайте верный - необходим для активации!)" - ], - - "EMAIL_OR_USERNAME" => "Имя пользователя или Email", - - "FIRST_NAME" => "Имя", - - "HEADER_MESSAGE_ROOT" => "ВЫ АВТОРИЗОВАНЫ С СУПЕР-ПРАВАМИ", - - "LAST_NAME" => "Фамилия", - "LOCALE" => [ - "ACCOUNT" => "Основной язык для вашего аккаунта", - "INVALID" => "<strong>{{locale}}</strong> язык недопустим." - ], - "LOGIN" => [ - "@TRANSLATION" => "Вход", - "ALREADY_COMPLETE" => "Вы уже выполнили вход!", - "SOCIAL" => "Или войти через", - "REQUIRED" => "Извините, Вы должны авторизоваться для доступа к этому ресурсу." - ], - "LOGOUT" => "Выход", - - "NAME" => "Имя", - - "NAME_AND_EMAIL" => "Имя и email", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Войдите в свой аккаунт {{site_name}}, или Зарегистрируйтесь.", - "SUBTITLE" => "Зарегистрироваться или войти в существующий аккаунт.", - "TITLE" => "Приступим!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Пароль", - - "BETWEEN" => "Кол-во {{min}}-{{max}} символов", - - "CONFIRM" => "Подтверждение пароля", - "CONFIRM_CURRENT" => "Пожалуйста, введите ваш текущий пароль", - "CONFIRM_NEW" => "Подтвердите новый пароль", - "CONFIRM_NEW_EXPLAIN" => "Повторно введите Ваш новый пароль", - "CONFIRM_NEW_HELP" => "Требуется только при выборе нового пароля", - "CREATE" => [ - "@TRANSLATION" => "Создать пароль", - "PAGE" => "Выберите пароль для вашего аккаунта.", - "SET" => "Установить пароль и войти" - ], - "CURRENT" => "Текущий пароль", - "CURRENT_EXPLAIN" => "Для продолжения вы должны ввести текущий пароль", - - "FORGOTTEN" => "Забытый пароль?", - "FORGET" => [ - "@TRANSLATION" => "Я забыл свой пароль", - - "COULD_NOT_UPDATE" => "Не удалось обновить пароль.", - "EMAIL" => "Пожалуйста, введите адрес электронной почты, который Вы использовали при регистрации. Ссылка с инструкцией по сбросу пароля будет отправлена вам по электронной почте.", - "EMAIL_SEND" => "Ссылка сброса пароля по Email", - "INVALID" => "Этот запрос сброса пароля не может быть найден, или истек. Пожалуйста, попробуйте <a href=\"{{url}}\"> повторно сбросить пароль<a>.", - "PAGE" => "Получите ссылку для сброса пароля.", - "REQUEST_CANNED" => "Запрос на сброс пароля отменен.", - "REQUEST_SENT" => "Если email <strong>{{email}}</strong> существует в нашей системе у какого-либо аккаунта, ссылка на сброс пароля будет направлена на <strong>{{email}}</strong>." - ], - - "HASH_FAILED" => "Хэширование пароля не удалось. Пожалуйста, попробуйте другой пароль, либо свяжитесь с администратором сайта.", - "INVALID" => "Текущий пароль не соответствует тому, который задан в системе.", - "NEW" => "Новый пароль", - "NOTHING_TO_UPDATE" => "Невозможно обновить с тем же паролем", - - "RESET" => [ - "@TRANSLATION" => "Сбросить пароль", - "CHOOSE" => "Пожалуйста, выберите новый пароль, чтобы продолжить.", - "PAGE" => "Выберите новый пароль для вашего аккаунта.", - "SEND" => "Задать новый пароль и войти" - ], - - "UPDATED" => "Пароль аккаунта обновлён" - ], - - "PROFILE" => [ - "SETTINGS" => "Настройки профиля", - "UPDATED" => "Настройки профиля обновлены" - ], - - "RATE_LIMIT_EXCEEDED" => "Превышен лимит попыток для этого действия. Вы должны подождать еще {{delay}} секунд, прежде чем вам вам будет разрешено сделать ещё попытку.", - - "REGISTER" => "Регистрация", - "REGISTER_ME" => "Зарегистрируйте меня", - "REGISTRATION" => [ - "BROKEN" => "К сожалению, есть проблема с регистрации аккаунта. Свяжитесь с нами напрямую для получения помощи.", - "COMPLETE_TYPE1" => "Вы успешно зарегистрировались. Теперь вы можете войти.", - "COMPLETE_TYPE2" => "Вы успешно зарегистрировались. Ссылка для активации вашего аккаунта была отправлена на <strong>{{email}}</strong>. Вы сможете войти в систему только после активации аккаунта.", - "DISABLED" => "Извините, регистрация аккаунта была отключена.", - "LOGOUT" => "Извините, вы не можете зарегистрироваться когда уже авторизовались в системе. Сначала выйдите из системы.", - "WELCOME" => "Быстрая и простая регистрация." - ], - "REMEMBER_ME" => "Запомнить", - "REMEMBER_ME_ON_COMPUTER" => "Запомнить меня на этом компьютере (не рекомендуется для общедоступных компьютеров)", - - "SIGN_IN_HERE" => "Уже есть аккаунт? <a href=\"{{url}}\"> войти.</a>", - "SIGNIN" => "Вход", - "SIGNIN_OR_REGISTER" => "Регистрация или вход", - "SIGNUP" => "Вход", - - "TOS" => "Пользовательское соглашение", - "TOS_AGREEMENT" => "Регистрируя аккаунт на {{site_title}}, вы принимаете <a {{link_attributes | raw}}> условия и положения</a>.", - "TOS_FOR" => "Правила и условия для {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "Пользователь", - - "CHOOSE" => "Выберите имя пользователя", - "INVALID" => "Недопустимое имя пользователя", - "IN_USE" => "<strong>{{user_name}}</strong> имя пользователя уже используется.", - "NOT_AVAILABLE" => "Имя пользователя <strong>{{user_name}}</strong> не доступно. Выберите другое имя или нажмите кнопку «предложить»." - ], - - "USER_ID_INVALID" => "ID запрашиваемого пользователя не существует.", - "USER_OR_EMAIL_INVALID" => "Имя пользователя или email не верный.", - "USER_OR_PASS_INVALID" => "Пользователь не найден или пароль является недействительным.", - - "WELCOME" => "Добро пожаловать, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Russian message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\ru_RU
+ * @author @rendername
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Аккаунт",
+
+ "ACCESS_DENIED" => "Для получения доступа у вас недостаточно прав.",
+
+ "DISABLED" => "Аккаунт отключен. Пожалуйста, свяжитесь с нами для получения дополнительной информации.",
+
+ "EMAIL_UPDATED" => "Email аккаунта обновлён",
+
+ "INVALID" => "Этот аккаунт не существует. Возможно, он удалён. Пожалуйста, свяжитесь с нами для получения дополнительной информации.",
+
+ "MASTER_NOT_EXISTS" => "Вы не можете зарегистрировать аккаунт до тех пор, пока основная учётная запись не будет создана!",
+ "MY" => "Мой профиль",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "Ваша сессия была скомпрометирована. Вы должны выйти на всех устройствах, а затем снова войти и убедиться, что ваши данные не были изменены.",
+ "TITLE" => "Возможно, ваш аккаунт был скомпрометированн",
+ "TEXT" => "Возможно, кто-то использовал ваши данные для входа на эту страницу. В целях безопасности все сеансы были завершены. Пожалуйста, повторно <a href=\"{{url}}\"> войдите </a> и проверьте свой аккаунт на подозрительную активность. Рекомендуем сменить пароль."
+ ],
+ "SESSION_EXPIRED" => "Срок вашей сессии истек. Пожалуйста войдите еще раз.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Настройки аккаунта",
+ "DESCRIPTION" => "Обновите настройки своего аккаунта, включая адрес электронной почты, имя и пароль.",
+ "UPDATED" => "Данные аккаунта обновлены"
+ ],
+
+ "TOOLS" => "Инструменты аккаунта",
+
+ "UNVERIFIED" => "Ваш аккаунт ещё не подтверждён. Проверьте вашу email почту, в том числе папку спам и следуйте инструкциям.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "Мы отправили на ваш email новую ссылку для активации {{email}}. Пожалуйста, проверьте папку \"Входящие\" и \"Спам\".",
+ "RESEND" => "Повторно отправить письмо с подтверждением",
+ "COMPLETE" => "Вы успешно подтвердили свой аккаунт. Теперь вы можете войти.",
+ "EMAIL" => "Введите email, который вы использовали для регистрации, вам будет повторно отправлено письмо с подтверждением.",
+ "PAGE" => "Повторно оправить письмо подтверждения на email для нового аккаунта.",
+ "SEND" => "Проверка по электронной почте для аккаунта",
+ "TOKEN_NOT_FOUND" => "Код подтверждения не действителен либо аккаунт уже подтверждён",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "Нет не одного аккаунта с <strong> {{email}} </strong>.",
+ "IN_USE" => "Email <strong>{{email}}</strong> уже используется.",
+ "VERIFICATION_REQUIRED" => "Email (указывайте верный - необходим для активации!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Имя пользователя или Email",
+
+ "FIRST_NAME" => "Имя",
+
+ "HEADER_MESSAGE_ROOT" => "ВЫ АВТОРИЗОВАНЫ С СУПЕР-ПРАВАМИ",
+
+ "LAST_NAME" => "Фамилия",
+ "LOCALE" => [
+ "ACCOUNT" => "Основной язык для вашего аккаунта",
+ "INVALID" => "<strong>{{locale}}</strong> язык недопустим."
+ ],
+ "LOGIN" => [
+ "@TRANSLATION" => "Вход",
+ "ALREADY_COMPLETE" => "Вы уже выполнили вход!",
+ "SOCIAL" => "Или войти через",
+ "REQUIRED" => "Извините, Вы должны авторизоваться для доступа к этому ресурсу."
+ ],
+ "LOGOUT" => "Выход",
+
+ "NAME" => "Имя",
+
+ "NAME_AND_EMAIL" => "Имя и email",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "Войдите в свой аккаунт {{site_name}}, или Зарегистрируйтесь.",
+ "SUBTITLE" => "Зарегистрироваться или войти в существующий аккаунт.",
+ "TITLE" => "Приступим!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Пароль",
+
+ "BETWEEN" => "Кол-во {{min}}-{{max}} символов",
+
+ "CONFIRM" => "Подтверждение пароля",
+ "CONFIRM_CURRENT" => "Пожалуйста, введите ваш текущий пароль",
+ "CONFIRM_NEW" => "Подтвердите новый пароль",
+ "CONFIRM_NEW_EXPLAIN" => "Повторно введите Ваш новый пароль",
+ "CONFIRM_NEW_HELP" => "Требуется только при выборе нового пароля",
+ "CREATE" => [
+ "@TRANSLATION" => "Создать пароль",
+ "PAGE" => "Выберите пароль для вашего аккаунта.",
+ "SET" => "Установить пароль и войти"
+ ],
+ "CURRENT" => "Текущий пароль",
+ "CURRENT_EXPLAIN" => "Для продолжения вы должны ввести текущий пароль",
+
+ "FORGOTTEN" => "Забытый пароль?",
+ "FORGET" => [
+ "@TRANSLATION" => "Я забыл свой пароль",
+
+ "COULD_NOT_UPDATE" => "Не удалось обновить пароль.",
+ "EMAIL" => "Пожалуйста, введите адрес электронной почты, который Вы использовали при регистрации. Ссылка с инструкцией по сбросу пароля будет отправлена вам по электронной почте.",
+ "EMAIL_SEND" => "Ссылка сброса пароля по Email",
+ "INVALID" => "Этот запрос сброса пароля не может быть найден, или истек. Пожалуйста, попробуйте <a href=\"{{url}}\"> повторно сбросить пароль<a>.",
+ "PAGE" => "Получите ссылку для сброса пароля.",
+ "REQUEST_CANNED" => "Запрос на сброс пароля отменен.",
+ "REQUEST_SENT" => "Если email <strong>{{email}}</strong> существует в нашей системе у какого-либо аккаунта, ссылка на сброс пароля будет направлена на <strong>{{email}}</strong>."
+ ],
+
+ "HASH_FAILED" => "Хэширование пароля не удалось. Пожалуйста, попробуйте другой пароль, либо свяжитесь с администратором сайта.",
+ "INVALID" => "Текущий пароль не соответствует тому, который задан в системе.",
+ "NEW" => "Новый пароль",
+ "NOTHING_TO_UPDATE" => "Невозможно обновить с тем же паролем",
+
+ "RESET" => [
+ "@TRANSLATION" => "Сбросить пароль",
+ "CHOOSE" => "Пожалуйста, выберите новый пароль, чтобы продолжить.",
+ "PAGE" => "Выберите новый пароль для вашего аккаунта.",
+ "SEND" => "Задать новый пароль и войти"
+ ],
+
+ "UPDATED" => "Пароль аккаунта обновлён"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Настройки профиля",
+ "UPDATED" => "Настройки профиля обновлены"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "Превышен лимит попыток для этого действия. Вы должны подождать еще {{delay}} секунд, прежде чем вам вам будет разрешено сделать ещё попытку.",
+
+ "REGISTER" => "Регистрация",
+ "REGISTER_ME" => "Зарегистрируйте меня",
+ "REGISTRATION" => [
+ "BROKEN" => "К сожалению, есть проблема с регистрации аккаунта. Свяжитесь с нами напрямую для получения помощи.",
+ "COMPLETE_TYPE1" => "Вы успешно зарегистрировались. Теперь вы можете войти.",
+ "COMPLETE_TYPE2" => "Вы успешно зарегистрировались. Ссылка для активации вашего аккаунта была отправлена на <strong>{{email}}</strong>. Вы сможете войти в систему только после активации аккаунта.",
+ "DISABLED" => "Извините, регистрация аккаунта была отключена.",
+ "LOGOUT" => "Извините, вы не можете зарегистрироваться когда уже авторизовались в системе. Сначала выйдите из системы.",
+ "WELCOME" => "Быстрая и простая регистрация."
+ ],
+ "REMEMBER_ME" => "Запомнить",
+ "REMEMBER_ME_ON_COMPUTER" => "Запомнить меня на этом компьютере (не рекомендуется для общедоступных компьютеров)",
+
+ "SIGN_IN_HERE" => "Уже есть аккаунт? <a href=\"{{url}}\"> войти.</a>",
+ "SIGNIN" => "Вход",
+ "SIGNIN_OR_REGISTER" => "Регистрация или вход",
+ "SIGNUP" => "Вход",
+
+ "TOS" => "Пользовательское соглашение",
+ "TOS_AGREEMENT" => "Регистрируя аккаунт на {{site_title}}, вы принимаете <a {{link_attributes | raw}}> условия и положения</a>.",
+ "TOS_FOR" => "Правила и условия для {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Пользователь",
+
+ "CHOOSE" => "Выберите имя пользователя",
+ "INVALID" => "Недопустимое имя пользователя",
+ "IN_USE" => "<strong>{{user_name}}</strong> имя пользователя уже используется.",
+ "NOT_AVAILABLE" => "Имя пользователя <strong>{{user_name}}</strong> не доступно. Выберите другое имя или нажмите кнопку «предложить»."
+ ],
+
+ "USER_ID_INVALID" => "ID запрашиваемого пользователя не существует.",
+ "USER_OR_EMAIL_INVALID" => "Имя пользователя или email не верный.",
+ "USER_OR_PASS_INVALID" => "Пользователь не найден или пароль является недействительным.",
+
+ "WELCOME" => "Добро пожаловать, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/ru_RU/validate.php b/main/app/sprinkles/account/locale/ru_RU/validate.php index 4d39bbe..44ff0ae 100644 --- a/main/app/sprinkles/account/locale/ru_RU/validate.php +++ b/main/app/sprinkles/account/locale/ru_RU/validate.php @@ -1,19 +1,19 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Russian message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\ru_RU - * @author @rendername - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Пароли не совпадают.", - "USERNAME" => "Имя может состоять только из строчных букв, цифр, '.', '-' и «_»." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Russian message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\ru_RU
+ * @author @rendername
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "Пароли не совпадают.",
+ "USERNAME" => "Имя может состоять только из строчных букв, цифр, '.', '-' и «_»."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/th_TH/messages.php b/main/app/sprinkles/account/locale/th_TH/messages.php index d937de1..0aaf1de 100644 --- a/main/app/sprinkles/account/locale/th_TH/messages.php +++ b/main/app/sprinkles/account/locale/th_TH/messages.php @@ -1,164 +1,164 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Thai message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\th - * @author Karuhut Komol - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "บัญชี", - - "ACCESS_DENIED" => "หืมม ดูเหมือนว่าคุณไม่ได้รับอนุญาตให้ทำเช่นนั้น", - - "DISABLED" => "บัญชีนี้ถูกปิดการใช้งานไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", - - "EMAIL_UPDATED" => "ปรับปรุงบัญชีอีเมลแล้ว", - - "INVALID" => "ไม่พบบัญชีนี้ มันอาจถูกลบไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", - - "MASTER_NOT_EXISTS" => "คุณไม่สามารถสมัครสมาชิกได้จนกว่าจะสร้างบัญชีหลัก!", - "MY" => "บัญชีของฉัน", - - "SESSION_COMPROMISED" => "เซสชันของคุณถูกลักลอบใช้ คุณควรจะออกจากระบบบนอุปกรณ์ทั้งหมดแล้วกลับเข้าสู่ระบบและตรวจสอบให้แน่ใจว่าไม่มีการแก้ไขข้อมูลของคุณ", - "SESSION_COMPROMISED_TITLE" => "บัญชีของคุณอาจถูกบุกรุก", - "SESSION_EXPIRED" => "เซสชันของคุณหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง", - - "SETTINGS" => [ - "@TRANSLATION" => "การตั้งค่าบัญชี", - "DESCRIPTION" => "ปรับปรุงการตั้งค่าบัญชีของคุณ รวมไปถึงอีเมล ชื่อ และรหัสผ่าน", - "UPDATED" => "ปรับปรุงการตั้งค่าบัญชีของคุณแล้ว" - ], - - "TOOLS" => "เครื่องมือบัญชี", - - "UNVERIFIED" => "บัญชีของคุณยังไม่ได้รับการยืนยัน กรุณาตรวจสอบกล่องอีเมลและจดหมายขยะของคุณสำหรับขั้นตอนการเปิดใช้งานบัญชี", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "เราได้ส่งลิงก์สำหรับการยืนยันใหม่ไปยังอีเมล {{email}} กรุณาตรวจสอบอีเมลนี้ในกล่องอีเมลและจดหมายขยะของคุณ", - "RESEND" => "ส่งอีเมลยืนยันอีกครั้ง", - "COMPLETE" => "คุณได้ยืนยันอีเมลของคุณเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", - "EMAIL" => "กรุณากรอกอีเมลที่คุณได้ใช้สมัครไว้แล้วอีเมลยืนยันจะถูกส่งไปให้ใหม่", - "PAGE" => "ส่งอีเมลยืนยันสำหรับบัญชีของฉันใหม่", - "SEND" => "ส่งอีเมลยืนยันให้บัญชีของฉัน", - "TOKEN_NOT_FOUND" => "ไม่พบโทเคนยืนยันอีเมล / บัญชีนี้ได้ยืนยันแล้ว", - ] - ], - - "EMAIL" => [ - "INVALID" => "อีเมล <strong>{{email}}</strong> ไม่มีอยู่จริง", - "IN_USE" => "อีเมล <strong>{{email}}</strong> ได้ถูกใช้งานแล้ว" - ], - - "FIRST_NAME" => "ชื่อจริง", - - "HEADER_MESSAGE_ROOT" => "คุณได้เข้าสู่ระบบเป็นผู้ดูแลสูงสุด", - - "LAST_NAME" => "นามสกุล", - - "LOCALE.ACCOUNT" => "ภาษาและสถานที่ที่จะใช้สำหรับบัญชีของคุณ", - - "LOGIN" => [ - "@TRANSLATION" => "เข้าสู่ะระบบ", - - "ALREADY_COMPLETE" => "คุณได้เข้าสู่ระบบอยู่แล้ว!", - "SOCIAL" => "หรือเข้าสู่ระบบด้วย", - "REQUIRED" => "ขออภัย คุณจะต้องเข้าสู่ระบบเพื่อเข้าถึงส่วนนี้" - ], - - "LOGOUT" => "ออกจากระบบ", - - "NAME" => "ชื่อ", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "เข้าสู่ระบบไปยังบัญชี {{site_name}} หรือสมัครสมาชิกสำหรับบัญชีใหม่", - "SUBTITLE" => "สมัครสมาชิกฟรี หรือเข้าสู่ระบบด้วยบัญชีที่มีอยู่", - "TITLE" => "มาเริ่มกันเลย!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "รหัสผ่าน", - - "BETWEEN" => "ระหว่าง {{min}}-{{max}} ตัวอักษร", - - "CONFIRM" => "ยืนยันรหัสผ่าน", - "CONFIRM_CURRENT" => "กรุณายืนยันรหัสผ่านปัจจุบันของคุณ", - "CONFIRM_NEW" => "ยืนยันรหัสผ่านใหม่", - "CONFIRM_NEW_EXPLAIN" => "กรอกรหัสผ่านใหม่ของคุณอีกครั้ง", - "CONFIRM_NEW_HELP" => "กรอกเฉพาะเมื่อคุณต้องการตั้งรหัสผ่านใหม่", - "CURRENT" => "รหัสผ่านปัจจุบัน", - "CURRENT_EXPLAIN" => "คุณจะต้องยืนยันรหัสผ่านปัจจุบันเพื่อแก้ไขข้อมูล", - - "FORGOTTEN" => "ลืมรหัสผ่าน", - "FORGET" => [ - "@TRANSLATION" => "ฉันลืมรหัสผ่านของฉัน", - - "COULD_NOT_UPDATE" => "ไม่สามารถปรับปรุงรหัสผ่าน", - "EMAIL" => "กรุณากรอกที่อยู่อีเมลที่คุณเคยใช้เข้าสู่ระบบ ลิงก์ขั้นตอนการรีเซ็ตรหัสผ่านของคุณจะถูกส่งไปให้คุณ", - "EMAIL_SEND" => "ลิงก์รีเซ็ตรหัสผ่านจากอีเมล", - "INVALID" => "ขอรีเซ็ตรหัสผ่านนี้ไม่มีอยู่ หรือหมดอายุไปแล้ว กรุณาลอง <a href=\"{{url}}\">ส่งคำขอของคุณอีกครั้ง<a>", - "PAGE" => "รับลิงก์สำหรับการรีเซ็ตรหัสผ่านของคุณ", - "REQUEST_CANNED" => "คำขอลืมรหัสผ่านได้ถูกยกเลิก", - "REQUEST_SENT" => "หากอีเมล <strong>{{email}}</strong> ตรงกับบัญชีในระบบของเราลิงก์การรีเซ็ตรหัสผ่านจะถูกส่งไปที่ <strong>{{email}}</strong>" - ], - - "RESET" => [ - "@TRANSLATION" => "รีเซ็ตรหัสผ่าน", - "CHOOSE" => "กรุณาเลือกรหัสผ่านใหม่เพื่อดำเนินการต่อ", - "PAGE" => "เลือกรหัสผ่านใหม่สำหรับบัญชีของคุณ", - "SEND" => "ตั้งรหัสผ่านใหม่และเข้าสู่ระบบ" - ], - - "HASH_FAILED" => "เข้ารหัสรหัสผ่านล้มเหลว กรุณาติดต่อผู้ดูแลระบบของเว็บไซต์", - "INVALID" => "รหัสผ่านปัจจุบันไม่ตรงกับรหัสผ่านที่เราบันทึกไว้", - "NEW" => "รหัสผ่านใหม่", - "NOTHING_TO_UPDATE" => "คุณไม่สามารถปรังปรุงด้วยรหัสผ่านเดียวกัน", - "UPDATED" => "ปรังปรุงรหัสผ่านของบัญชีแล้ว" - ], - - "REGISTER" => "สมัครสมาชิก", - "REGISTER_ME" => "ให้ฉันสมัครสมาชิกด้วย", - - "REGISTRATION" => [ - "BROKEN" => "เราขออภัย มันมีปัญหาในการดำเนินการสมัครสมาชิกของเรา กรุณาติดต่อเราโดยตรงเพื่อขอความช่วยเหลือ", - "COMPLETE_TYPE1" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", - "COMPLETE_TYPE2" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณจะได้รับอีเมลยืนยันที่มีลิงก์สำหรับเปิดใช้งานบัญชีของคุณอยู่ คุณจะไม่สามารถเข้าสู่ระบบจนกว่าคุณจะยืนยันอีเมลแล้ว", - "DISABLED" => "เราขออภัย ระบบสมัครสมาชิกได้ถูกปิดไว้", - "LOGOUT" => "เราขออภัย คุณไม่สามารถสมัครสมาชิกขณะที่เข้าสู่ระบบอยู่ กรุณาออกจากระบบก่อน", - "WELCOME" => "การสมัครสมาชิกนั้นรวดเร็ว และง่ายดาย" - ], - - "RATE_LIMIT_EXCEEDED" => "ถึงขีดจำกัดสำหรับการกระทำนี้แล้ว คุณจะต้องรออีก {{delay}} วินาที ก่อนที่คุณจะได้รับอนุญาตให้ลองใหม่อีกครั้ง", - "REMEMBER_ME" => "จำฉันไว้ในระบบ!", - "REMEMBER_ME_ON_COMPUTER" => "จำฉันไว้ในระบบบนคอมพิวเตอร์นี้ (ไม่แนะนำสำหรับคอมพิวเตอร์สาธารณะ)", - - "SIGNIN" => "เข้าสู่ะระบบ", - "SIGNIN_OR_REGISTER" => "เข้าสู่ระบบหรือสมัครสมาชิก", - "SIGNUP" => "สมัครสมาชิก", - - "TOS" => "ข้อตกลงและเงื่อนไข", - "TOS_AGREEMENT" => "ในการสมัครสมาชิกกับ {{site_title}} หมายถึงคุณยอมรับ <a {{link_attributes}}>ข้อตกลงและเงื่อนไข</a> แล้ว", - "TOS_FOR" => "ข้อตกลงและเงื่อนไขสำหรับ {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "ชื่อผู้ใช้", - - "CHOOSE" => "เลือกชื่อผู้ใช้ที่เป็นเป็นเอกลักษณ์", - "INVALID" => "ชื่อผู้ใช้ไม่ถูกต้อง", - "IN_USE" => "ชื่อผู้ใช้ <strong>{{user_name}}</strong> ถูกใช้งานแล้ว" - ], - - "USER_ID_INVALID" => "ไม่พบหมายเลขผู้ใช้ที่ร้องขอมา", - "USER_OR_EMAIL_INVALID" => "ชื่อผู้ใช้หรือที่อยู่อีเมลไม่ถูกต้อง", - "USER_OR_PASS_INVALID" => "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง", - - "WELCOME" => "ยินดีต้อนรับ {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Thai message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\th
+ * @author Karuhut Komol
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "บัญชี",
+
+ "ACCESS_DENIED" => "หืมม ดูเหมือนว่าคุณไม่ได้รับอนุญาตให้ทำเช่นนั้น",
+
+ "DISABLED" => "บัญชีนี้ถูกปิดการใช้งานไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม",
+
+ "EMAIL_UPDATED" => "ปรับปรุงบัญชีอีเมลแล้ว",
+
+ "INVALID" => "ไม่พบบัญชีนี้ มันอาจถูกลบไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม",
+
+ "MASTER_NOT_EXISTS" => "คุณไม่สามารถสมัครสมาชิกได้จนกว่าจะสร้างบัญชีหลัก!",
+ "MY" => "บัญชีของฉัน",
+
+ "SESSION_COMPROMISED" => "เซสชันของคุณถูกลักลอบใช้ คุณควรจะออกจากระบบบนอุปกรณ์ทั้งหมดแล้วกลับเข้าสู่ระบบและตรวจสอบให้แน่ใจว่าไม่มีการแก้ไขข้อมูลของคุณ",
+ "SESSION_COMPROMISED_TITLE" => "บัญชีของคุณอาจถูกบุกรุก",
+ "SESSION_EXPIRED" => "เซสชันของคุณหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "การตั้งค่าบัญชี",
+ "DESCRIPTION" => "ปรับปรุงการตั้งค่าบัญชีของคุณ รวมไปถึงอีเมล ชื่อ และรหัสผ่าน",
+ "UPDATED" => "ปรับปรุงการตั้งค่าบัญชีของคุณแล้ว"
+ ],
+
+ "TOOLS" => "เครื่องมือบัญชี",
+
+ "UNVERIFIED" => "บัญชีของคุณยังไม่ได้รับการยืนยัน กรุณาตรวจสอบกล่องอีเมลและจดหมายขยะของคุณสำหรับขั้นตอนการเปิดใช้งานบัญชี",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "เราได้ส่งลิงก์สำหรับการยืนยันใหม่ไปยังอีเมล {{email}} กรุณาตรวจสอบอีเมลนี้ในกล่องอีเมลและจดหมายขยะของคุณ",
+ "RESEND" => "ส่งอีเมลยืนยันอีกครั้ง",
+ "COMPLETE" => "คุณได้ยืนยันอีเมลของคุณเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที",
+ "EMAIL" => "กรุณากรอกอีเมลที่คุณได้ใช้สมัครไว้แล้วอีเมลยืนยันจะถูกส่งไปให้ใหม่",
+ "PAGE" => "ส่งอีเมลยืนยันสำหรับบัญชีของฉันใหม่",
+ "SEND" => "ส่งอีเมลยืนยันให้บัญชีของฉัน",
+ "TOKEN_NOT_FOUND" => "ไม่พบโทเคนยืนยันอีเมล / บัญชีนี้ได้ยืนยันแล้ว",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "อีเมล <strong>{{email}}</strong> ไม่มีอยู่จริง",
+ "IN_USE" => "อีเมล <strong>{{email}}</strong> ได้ถูกใช้งานแล้ว"
+ ],
+
+ "FIRST_NAME" => "ชื่อจริง",
+
+ "HEADER_MESSAGE_ROOT" => "คุณได้เข้าสู่ระบบเป็นผู้ดูแลสูงสุด",
+
+ "LAST_NAME" => "นามสกุล",
+
+ "LOCALE.ACCOUNT" => "ภาษาและสถานที่ที่จะใช้สำหรับบัญชีของคุณ",
+
+ "LOGIN" => [
+ "@TRANSLATION" => "เข้าสู่ะระบบ",
+
+ "ALREADY_COMPLETE" => "คุณได้เข้าสู่ระบบอยู่แล้ว!",
+ "SOCIAL" => "หรือเข้าสู่ระบบด้วย",
+ "REQUIRED" => "ขออภัย คุณจะต้องเข้าสู่ระบบเพื่อเข้าถึงส่วนนี้"
+ ],
+
+ "LOGOUT" => "ออกจากระบบ",
+
+ "NAME" => "ชื่อ",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "เข้าสู่ระบบไปยังบัญชี {{site_name}} หรือสมัครสมาชิกสำหรับบัญชีใหม่",
+ "SUBTITLE" => "สมัครสมาชิกฟรี หรือเข้าสู่ระบบด้วยบัญชีที่มีอยู่",
+ "TITLE" => "มาเริ่มกันเลย!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "รหัสผ่าน",
+
+ "BETWEEN" => "ระหว่าง {{min}}-{{max}} ตัวอักษร",
+
+ "CONFIRM" => "ยืนยันรหัสผ่าน",
+ "CONFIRM_CURRENT" => "กรุณายืนยันรหัสผ่านปัจจุบันของคุณ",
+ "CONFIRM_NEW" => "ยืนยันรหัสผ่านใหม่",
+ "CONFIRM_NEW_EXPLAIN" => "กรอกรหัสผ่านใหม่ของคุณอีกครั้ง",
+ "CONFIRM_NEW_HELP" => "กรอกเฉพาะเมื่อคุณต้องการตั้งรหัสผ่านใหม่",
+ "CURRENT" => "รหัสผ่านปัจจุบัน",
+ "CURRENT_EXPLAIN" => "คุณจะต้องยืนยันรหัสผ่านปัจจุบันเพื่อแก้ไขข้อมูล",
+
+ "FORGOTTEN" => "ลืมรหัสผ่าน",
+ "FORGET" => [
+ "@TRANSLATION" => "ฉันลืมรหัสผ่านของฉัน",
+
+ "COULD_NOT_UPDATE" => "ไม่สามารถปรับปรุงรหัสผ่าน",
+ "EMAIL" => "กรุณากรอกที่อยู่อีเมลที่คุณเคยใช้เข้าสู่ระบบ ลิงก์ขั้นตอนการรีเซ็ตรหัสผ่านของคุณจะถูกส่งไปให้คุณ",
+ "EMAIL_SEND" => "ลิงก์รีเซ็ตรหัสผ่านจากอีเมล",
+ "INVALID" => "ขอรีเซ็ตรหัสผ่านนี้ไม่มีอยู่ หรือหมดอายุไปแล้ว กรุณาลอง <a href=\"{{url}}\">ส่งคำขอของคุณอีกครั้ง<a>",
+ "PAGE" => "รับลิงก์สำหรับการรีเซ็ตรหัสผ่านของคุณ",
+ "REQUEST_CANNED" => "คำขอลืมรหัสผ่านได้ถูกยกเลิก",
+ "REQUEST_SENT" => "หากอีเมล <strong>{{email}}</strong> ตรงกับบัญชีในระบบของเราลิงก์การรีเซ็ตรหัสผ่านจะถูกส่งไปที่ <strong>{{email}}</strong>"
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "รีเซ็ตรหัสผ่าน",
+ "CHOOSE" => "กรุณาเลือกรหัสผ่านใหม่เพื่อดำเนินการต่อ",
+ "PAGE" => "เลือกรหัสผ่านใหม่สำหรับบัญชีของคุณ",
+ "SEND" => "ตั้งรหัสผ่านใหม่และเข้าสู่ระบบ"
+ ],
+
+ "HASH_FAILED" => "เข้ารหัสรหัสผ่านล้มเหลว กรุณาติดต่อผู้ดูแลระบบของเว็บไซต์",
+ "INVALID" => "รหัสผ่านปัจจุบันไม่ตรงกับรหัสผ่านที่เราบันทึกไว้",
+ "NEW" => "รหัสผ่านใหม่",
+ "NOTHING_TO_UPDATE" => "คุณไม่สามารถปรังปรุงด้วยรหัสผ่านเดียวกัน",
+ "UPDATED" => "ปรังปรุงรหัสผ่านของบัญชีแล้ว"
+ ],
+
+ "REGISTER" => "สมัครสมาชิก",
+ "REGISTER_ME" => "ให้ฉันสมัครสมาชิกด้วย",
+
+ "REGISTRATION" => [
+ "BROKEN" => "เราขออภัย มันมีปัญหาในการดำเนินการสมัครสมาชิกของเรา กรุณาติดต่อเราโดยตรงเพื่อขอความช่วยเหลือ",
+ "COMPLETE_TYPE1" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที",
+ "COMPLETE_TYPE2" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณจะได้รับอีเมลยืนยันที่มีลิงก์สำหรับเปิดใช้งานบัญชีของคุณอยู่ คุณจะไม่สามารถเข้าสู่ระบบจนกว่าคุณจะยืนยันอีเมลแล้ว",
+ "DISABLED" => "เราขออภัย ระบบสมัครสมาชิกได้ถูกปิดไว้",
+ "LOGOUT" => "เราขออภัย คุณไม่สามารถสมัครสมาชิกขณะที่เข้าสู่ระบบอยู่ กรุณาออกจากระบบก่อน",
+ "WELCOME" => "การสมัครสมาชิกนั้นรวดเร็ว และง่ายดาย"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "ถึงขีดจำกัดสำหรับการกระทำนี้แล้ว คุณจะต้องรออีก {{delay}} วินาที ก่อนที่คุณจะได้รับอนุญาตให้ลองใหม่อีกครั้ง",
+ "REMEMBER_ME" => "จำฉันไว้ในระบบ!",
+ "REMEMBER_ME_ON_COMPUTER" => "จำฉันไว้ในระบบบนคอมพิวเตอร์นี้ (ไม่แนะนำสำหรับคอมพิวเตอร์สาธารณะ)",
+
+ "SIGNIN" => "เข้าสู่ะระบบ",
+ "SIGNIN_OR_REGISTER" => "เข้าสู่ระบบหรือสมัครสมาชิก",
+ "SIGNUP" => "สมัครสมาชิก",
+
+ "TOS" => "ข้อตกลงและเงื่อนไข",
+ "TOS_AGREEMENT" => "ในการสมัครสมาชิกกับ {{site_title}} หมายถึงคุณยอมรับ <a {{link_attributes}}>ข้อตกลงและเงื่อนไข</a> แล้ว",
+ "TOS_FOR" => "ข้อตกลงและเงื่อนไขสำหรับ {{title}}",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "ชื่อผู้ใช้",
+
+ "CHOOSE" => "เลือกชื่อผู้ใช้ที่เป็นเป็นเอกลักษณ์",
+ "INVALID" => "ชื่อผู้ใช้ไม่ถูกต้อง",
+ "IN_USE" => "ชื่อผู้ใช้ <strong>{{user_name}}</strong> ถูกใช้งานแล้ว"
+ ],
+
+ "USER_ID_INVALID" => "ไม่พบหมายเลขผู้ใช้ที่ร้องขอมา",
+ "USER_OR_EMAIL_INVALID" => "ชื่อผู้ใช้หรือที่อยู่อีเมลไม่ถูกต้อง",
+ "USER_OR_PASS_INVALID" => "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง",
+
+ "WELCOME" => "ยินดีต้อนรับ {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/th_TH/validate.php b/main/app/sprinkles/account/locale/th_TH/validate.php index 14a7adb..7e2945b 100644 --- a/main/app/sprinkles/account/locale/th_TH/validate.php +++ b/main/app/sprinkles/account/locale/th_TH/validate.php @@ -1,18 +1,18 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Thai message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\th - * @author Karuhut Komol - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "รหัสผ่านและรหัสผ่านยืนยันของคุณจะต้องตรงกัน" - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Thai message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\th
+ * @author Karuhut Komol
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "รหัสผ่านและรหัสผ่านยืนยันของคุณจะต้องตรงกัน"
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/tr/messages.php b/main/app/sprinkles/account/locale/tr/messages.php index a18bf99..2698676 100644 --- a/main/app/sprinkles/account/locale/tr/messages.php +++ b/main/app/sprinkles/account/locale/tr/messages.php @@ -1,183 +1,183 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Turkish message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\tr - * @author Dumblledore - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Hesap", - - "ACCESS_DENIED" => "Hmm. görünüşe göre böyle bir şey için izne sahip değilsiniz.", - - "DISABLED" => "Bu hesap durduruldu. Daha çok bilgi için bizimle iletişime geçin.", - - "EMAIL_UPDATED" => "Hesap maili güncellendi", - - "INVALID" => "Bu hesap bulunamadı. Silinmiş olabilir. Daha çok bilgi için bizimle iletişime geçin.", - - "MASTER_NOT_EXISTS" => "Ana hesap oluşturuluncaya kadar bir hesap oluşturamazsın!", - "MY" => "Hesabım", - - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Oturumunuz tehlikeye atıldı. Tüm cihazlardan çıkmanız, daha sonra giriş yapmanız ve bilgilerinizin değiştirilmediğini kontrol etmeniz gerekir.", - "TITLE" => "Hesabınız tehlikeye atılmış olabilir", - "TEXT" => "Birisi bu sayfayı ele geçirmek için giriş verilerinizi kullanmış olabilir. Güvenliğiniz için tüm oturumlar günlüğe kaydedildi. Lütfen <a href=\"{{url}}\">giriş yapın</a>ve şüpheli hareketler için hesabınızı kontrol edin. Ayrıca şifrenizi değiştirmek isteyebilirsiniz." - ], - "SESSION_EXPIRED" => "Oturumunuz sona erdi. Lütfen tekrar oturum açın.", - - "SETTINGS" => [ - "@TRANSLATION" => "Hesap ayarları", - "DESCRIPTION" => "E-posta, isim ve parolanız da dahil olmak üzere hesap ayarlarınızı güncelleyin.", - "UPDATED" => "Hesap ayarları güncellendi" - ], - - "TOOLS" => "Hesap araçları", - - "UNVERIFIED" => "Hesap henüz onaylanmadı. Hesap etkinleştirme talimatları için e-postalarınızı ve spam klasörünüzü kontrol edin.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "{{email}} için yeni bir doğrulama bağlantısı e-posta ile gönderildi. Lütfen bu e-postanın gelen kutusunu ve spam klasörlerini kontrol edin.", - "RESEND" => "Doğrulama e-postasını tekrar gönder", - "COMPLETE" => "Hesabınızı başarıyla doğruladınız. Şimdi giriş yapabilirsiniz.", - "EMAIL" => "Kaydolmak için kullandığınız e-posta adresinizi giriniz, ve doğrulama e-postanızı tekrar gönderin.", - "PAGE" => "Yeni hesabınız için doğrulama e-postasını tekrar gönder.", - "SEND" => "Hesabım için doğrulama bağlantısını e-posta ile gönder", - "TOKEN_NOT_FOUND" => "Doğrulama belirteci bulunumadı / Hesap zaten doğrulandı", - ] - ], - - "EMAIL" => [ - "INVALID" => "<strong>{{email}}</strong> için hesap yoktur.", - "IN_USE" => "E-posta <strong>{{email}}</strong> zaten kullanılıyor.", - "VERIFICATION_REQUIRED" => "E-posta (doğrulama gerekli - gerçek bir adres kullanın!)" - ], - - "EMAIL_OR_USERNAME" => "Kullanıcı adı veya e-posta adresi", - - "FIRST_NAME" => "Adınız", - - "HEADER_MESSAGE_ROOT" => "Kök kullanıcı olarak giriş yaptın", - - "LAST_NAME" => "Soyadı", - "LOCALE" => [ - "ACCOUNT" => "Hesabınız için kullanılacak dil ve yerel ayar", - "INVALID" => "<strong>{{locale}}</strong> geçersiz bir yerel." - ], - "LOGIN" => [ - "@TRANSLATION" => "Oturum Aç", - "ALREADY_COMPLETE" => "Zaten oturum açtınız!", - "SOCIAL" => "Veya şununla oturum aç", - "REQUIRED" => "Üzgünüm, bu sayfaya ulaşmak için oturum açmalısın." - ], - "LOGOUT" => "Oturumu kapat", - - "NAME" => "Ad", - - "NAME_AND_EMAIL" => "Ad ve e-posta", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "{{site_name}} hesabınız ile giriş yapın ya da yeni bir hesap oluşturun.", - "SUBTITLE" => "Ücretsiz üye ol veya mevcut bir hesap ile giriş yapın.", - "TITLE" => "Hadi başlayalım!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "Parola", - - "BETWEEN" => "{{min}}-{{max}} karakterler arasında", - - "CONFIRM" => "Şifreyi onayla", - "CONFIRM_CURRENT" => "Lütfen şuanki parolanızı giriniz", - "CONFIRM_NEW" => "Yeni parolayı onayla", - "CONFIRM_NEW_EXPLAIN" => "Yeni parolayı tekrar gir", - "CONFIRM_NEW_HELP" => "Sadece yeni bir şifre seçerseniz gerekli", - "CREATE" => [ - "@TRANSLATION" => "Parola Oluştur", - "PAGE" => "Yeni hesabınız için bir şifre belirleyin.", - "SET" => "Parolayı Ayarla ve Giriş Yap" - ], - "CURRENT" => "Şimdiki Parola", - "CURRENT_EXPLAIN" => "Değişiklikler için şimdiki parolanız ile onaylamalısınız", - - "FORGOTTEN" => "Unutulan Şifre", - "FORGET" => [ - "@TRANSLATION" => "Şifremi unuttum", - - "COULD_NOT_UPDATE" => "Şifre güncellenemedi.", - "EMAIL" => "Lütfen kaydolmak için kullandığınız e-posta adresini giriniz. Şifrenizi sıfırlama talimatlarıyla bir bir bağlantı e-postanıza gönderilecektir.", - "EMAIL_SEND" => "E-posta şifre sıfırlama bağlantısı", - "INVALID" => "Bu şifre sıfırlama isteği bulunamadı ya da süresi bitmiş. Lütfen <a href=\"{{url}}\">isteğinizi yeniden göndermeyi<a>deneyin.", - "PAGE" => "Şifrenizi sıfırlamak için bir bağlantı oluşturun.", - "REQUEST_CANNED" => "Kayıp parola isteği iptal edildi.", - "REQUEST_SENT" => "Eğer e-posta<strong>{{email}}</strong> sistemdeki bir hesap ile eşleşirse, bir şifre yenileme bağlantısı<strong>{{email}}</strong> gönderilir." - ], - - "HASH_FAILED" => "Parola karma başarısız oldu. Lütfen bir site yöneticisiyle iletişime geçin.", - "INVALID" => "Şimdiki şifre kayıt edilen şifre ile eşleşmiyor", - "NEW" => "Yeni Şifre", - "NOTHING_TO_UPDATE" => "Aynı şifre ile güncelleyemezsiniz", - - "RESET" => [ - "@TRANSLATION" => "Şifre sıfırlama", - "CHOOSE" => "Lütfen devam etmek için yeni bir şifre belirleyiniz.", - "PAGE" => "Hesabınız için yeni bir şifre belirleyiniz.", - "SEND" => "Yeni şifre ayarla ve giriş yap" - ], - - "UPDATED" => "Hesap şifresi güncellendi" - ], - - "PROFILE" => [ - "SETTINGS" => "Profil ayarları", - "UPDATED" => "Profil ayarları güncellendi" - ], - - "RATE_LIMIT_EXCEEDED" => "Bu işlem için belirlenen son oran aşıldı. Başka bir deneme yapmanıza izin verilene kadar {{delay}} bir süre beklemelisiniz.", - - "REGISTER" => "Kaydol", - "REGISTER_ME" => "Beni kaydet", - "REGISTRATION" => [ - "BROKEN" => "Üzgünüz, hesap kayıt işlemimizde bir sorun var. Lütfen destek almak için doğrudan bizimle iletişime geçin.", - "COMPLETE_TYPE1" => "Kaydınız başarıyla tamamlandı. Şimdi giriş yapabilirsiniz.", - "COMPLETE_TYPE2" => "Kaydınız başarıyla tamamlandı. Hesabınızı aktifleştirmek için bir bağlantı gönderildi<strong>{{email}}</strong>. Bu adımı tamamlayana kadar oturum açamazsınız.", - "DISABLED" => "Üzgünüz, hesap kaydı devre dışı bırakıldı.", - "LOGOUT" => "Üzgünüm, oturumunuz açıkken yeni bir hesap oluşturamazsınız. Lütfen önce oturumunuzdan çıkış yapınız.", - "WELCOME" => "Kaydolmak hızlı ve basittir." - ], - "REMEMBER_ME" => "Beni hatırla!", - "REMEMBER_ME_ON_COMPUTER" => "Bu bilgisayarda beni hatırla ( genel bilgisayarlar için önerilmez)", - - "SIGN_IN_HERE" => "Zaten bir hesaba sahip misiniz?<a href=\"{{url}}\">burada giriş yap</a>", - "SIGNIN" => "Giriş yap", - "SIGNIN_OR_REGISTER" => "Giriş yap veya kayıt ol", - "SIGNUP" => "Üye ol", - - "TOS" => "Şartlar ve Koşullar", - "TOS_AGREEMENT" => "Bir hesap ile kaydolarak {{site_title}} sen kabul edersin <a {{link_attributes | raw}}>şartlar ve koşulları</a>.", - "TOS_FOR" => "{{title}} için şartlar ve koşullar", - - "USERNAME" => [ - "@TRANSLATION" => "Kullanıcı Adı", - - "CHOOSE" => "Benzersiz bir kullanıcı adı seç", - "INVALID" => "Geçersiz kullanıcı adı", - "IN_USE" => "<strong>{{user_name}}</strong> kullanıcı adı zaten mevcut.", - "NOT_AVAILABLE" => "<strong>{{user_name}}</strong> kullanıcı adı kullanılamaz. Farklı bir isim veya 'öneriye' tıklayın." - ], - - "USER_ID_INVALID" => "İstenen kullanıcı adı mevcut değil.", - "USER_OR_EMAIL_INVALID" => "Kullanıcı adı veya e-posta adresi hatalı.", - "USER_OR_PASS_INVALID" => "Kullanıcı bulunamadı ya da şifre hatalı.", - - "WELCOME" => "Tekrar Hoşgeldiniz.{{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Turkish message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\tr
+ * @author Dumblledore
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "Hesap",
+
+ "ACCESS_DENIED" => "Hmm. görünüşe göre böyle bir şey için izne sahip değilsiniz.",
+
+ "DISABLED" => "Bu hesap durduruldu. Daha çok bilgi için bizimle iletişime geçin.",
+
+ "EMAIL_UPDATED" => "Hesap maili güncellendi",
+
+ "INVALID" => "Bu hesap bulunamadı. Silinmiş olabilir. Daha çok bilgi için bizimle iletişime geçin.",
+
+ "MASTER_NOT_EXISTS" => "Ana hesap oluşturuluncaya kadar bir hesap oluşturamazsın!",
+ "MY" => "Hesabım",
+
+ "SESSION_COMPROMISED" => [
+ "@TRANSLATION" => "Oturumunuz tehlikeye atıldı. Tüm cihazlardan çıkmanız, daha sonra giriş yapmanız ve bilgilerinizin değiştirilmediğini kontrol etmeniz gerekir.",
+ "TITLE" => "Hesabınız tehlikeye atılmış olabilir",
+ "TEXT" => "Birisi bu sayfayı ele geçirmek için giriş verilerinizi kullanmış olabilir. Güvenliğiniz için tüm oturumlar günlüğe kaydedildi. Lütfen <a href=\"{{url}}\">giriş yapın</a>ve şüpheli hareketler için hesabınızı kontrol edin. Ayrıca şifrenizi değiştirmek isteyebilirsiniz."
+ ],
+ "SESSION_EXPIRED" => "Oturumunuz sona erdi. Lütfen tekrar oturum açın.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "Hesap ayarları",
+ "DESCRIPTION" => "E-posta, isim ve parolanız da dahil olmak üzere hesap ayarlarınızı güncelleyin.",
+ "UPDATED" => "Hesap ayarları güncellendi"
+ ],
+
+ "TOOLS" => "Hesap araçları",
+
+ "UNVERIFIED" => "Hesap henüz onaylanmadı. Hesap etkinleştirme talimatları için e-postalarınızı ve spam klasörünüzü kontrol edin.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "{{email}} için yeni bir doğrulama bağlantısı e-posta ile gönderildi. Lütfen bu e-postanın gelen kutusunu ve spam klasörlerini kontrol edin.",
+ "RESEND" => "Doğrulama e-postasını tekrar gönder",
+ "COMPLETE" => "Hesabınızı başarıyla doğruladınız. Şimdi giriş yapabilirsiniz.",
+ "EMAIL" => "Kaydolmak için kullandığınız e-posta adresinizi giriniz, ve doğrulama e-postanızı tekrar gönderin.",
+ "PAGE" => "Yeni hesabınız için doğrulama e-postasını tekrar gönder.",
+ "SEND" => "Hesabım için doğrulama bağlantısını e-posta ile gönder",
+ "TOKEN_NOT_FOUND" => "Doğrulama belirteci bulunumadı / Hesap zaten doğrulandı",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "<strong>{{email}}</strong> için hesap yoktur.",
+ "IN_USE" => "E-posta <strong>{{email}}</strong> zaten kullanılıyor.",
+ "VERIFICATION_REQUIRED" => "E-posta (doğrulama gerekli - gerçek bir adres kullanın!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "Kullanıcı adı veya e-posta adresi",
+
+ "FIRST_NAME" => "Adınız",
+
+ "HEADER_MESSAGE_ROOT" => "Kök kullanıcı olarak giriş yaptın",
+
+ "LAST_NAME" => "Soyadı",
+ "LOCALE" => [
+ "ACCOUNT" => "Hesabınız için kullanılacak dil ve yerel ayar",
+ "INVALID" => "<strong>{{locale}}</strong> geçersiz bir yerel."
+ ],
+ "LOGIN" => [
+ "@TRANSLATION" => "Oturum Aç",
+ "ALREADY_COMPLETE" => "Zaten oturum açtınız!",
+ "SOCIAL" => "Veya şununla oturum aç",
+ "REQUIRED" => "Üzgünüm, bu sayfaya ulaşmak için oturum açmalısın."
+ ],
+ "LOGOUT" => "Oturumu kapat",
+
+ "NAME" => "Ad",
+
+ "NAME_AND_EMAIL" => "Ad ve e-posta",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "{{site_name}} hesabınız ile giriş yapın ya da yeni bir hesap oluşturun.",
+ "SUBTITLE" => "Ücretsiz üye ol veya mevcut bir hesap ile giriş yapın.",
+ "TITLE" => "Hadi başlayalım!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "Parola",
+
+ "BETWEEN" => "{{min}}-{{max}} karakterler arasında",
+
+ "CONFIRM" => "Şifreyi onayla",
+ "CONFIRM_CURRENT" => "Lütfen şuanki parolanızı giriniz",
+ "CONFIRM_NEW" => "Yeni parolayı onayla",
+ "CONFIRM_NEW_EXPLAIN" => "Yeni parolayı tekrar gir",
+ "CONFIRM_NEW_HELP" => "Sadece yeni bir şifre seçerseniz gerekli",
+ "CREATE" => [
+ "@TRANSLATION" => "Parola Oluştur",
+ "PAGE" => "Yeni hesabınız için bir şifre belirleyin.",
+ "SET" => "Parolayı Ayarla ve Giriş Yap"
+ ],
+ "CURRENT" => "Şimdiki Parola",
+ "CURRENT_EXPLAIN" => "Değişiklikler için şimdiki parolanız ile onaylamalısınız",
+
+ "FORGOTTEN" => "Unutulan Şifre",
+ "FORGET" => [
+ "@TRANSLATION" => "Şifremi unuttum",
+
+ "COULD_NOT_UPDATE" => "Şifre güncellenemedi.",
+ "EMAIL" => "Lütfen kaydolmak için kullandığınız e-posta adresini giriniz. Şifrenizi sıfırlama talimatlarıyla bir bir bağlantı e-postanıza gönderilecektir.",
+ "EMAIL_SEND" => "E-posta şifre sıfırlama bağlantısı",
+ "INVALID" => "Bu şifre sıfırlama isteği bulunamadı ya da süresi bitmiş. Lütfen <a href=\"{{url}}\">isteğinizi yeniden göndermeyi<a>deneyin.",
+ "PAGE" => "Şifrenizi sıfırlamak için bir bağlantı oluşturun.",
+ "REQUEST_CANNED" => "Kayıp parola isteği iptal edildi.",
+ "REQUEST_SENT" => "Eğer e-posta<strong>{{email}}</strong> sistemdeki bir hesap ile eşleşirse, bir şifre yenileme bağlantısı<strong>{{email}}</strong> gönderilir."
+ ],
+
+ "HASH_FAILED" => "Parola karma başarısız oldu. Lütfen bir site yöneticisiyle iletişime geçin.",
+ "INVALID" => "Şimdiki şifre kayıt edilen şifre ile eşleşmiyor",
+ "NEW" => "Yeni Şifre",
+ "NOTHING_TO_UPDATE" => "Aynı şifre ile güncelleyemezsiniz",
+
+ "RESET" => [
+ "@TRANSLATION" => "Şifre sıfırlama",
+ "CHOOSE" => "Lütfen devam etmek için yeni bir şifre belirleyiniz.",
+ "PAGE" => "Hesabınız için yeni bir şifre belirleyiniz.",
+ "SEND" => "Yeni şifre ayarla ve giriş yap"
+ ],
+
+ "UPDATED" => "Hesap şifresi güncellendi"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "Profil ayarları",
+ "UPDATED" => "Profil ayarları güncellendi"
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "Bu işlem için belirlenen son oran aşıldı. Başka bir deneme yapmanıza izin verilene kadar {{delay}} bir süre beklemelisiniz.",
+
+ "REGISTER" => "Kaydol",
+ "REGISTER_ME" => "Beni kaydet",
+ "REGISTRATION" => [
+ "BROKEN" => "Üzgünüz, hesap kayıt işlemimizde bir sorun var. Lütfen destek almak için doğrudan bizimle iletişime geçin.",
+ "COMPLETE_TYPE1" => "Kaydınız başarıyla tamamlandı. Şimdi giriş yapabilirsiniz.",
+ "COMPLETE_TYPE2" => "Kaydınız başarıyla tamamlandı. Hesabınızı aktifleştirmek için bir bağlantı gönderildi<strong>{{email}}</strong>. Bu adımı tamamlayana kadar oturum açamazsınız.",
+ "DISABLED" => "Üzgünüz, hesap kaydı devre dışı bırakıldı.",
+ "LOGOUT" => "Üzgünüm, oturumunuz açıkken yeni bir hesap oluşturamazsınız. Lütfen önce oturumunuzdan çıkış yapınız.",
+ "WELCOME" => "Kaydolmak hızlı ve basittir."
+ ],
+ "REMEMBER_ME" => "Beni hatırla!",
+ "REMEMBER_ME_ON_COMPUTER" => "Bu bilgisayarda beni hatırla ( genel bilgisayarlar için önerilmez)",
+
+ "SIGN_IN_HERE" => "Zaten bir hesaba sahip misiniz?<a href=\"{{url}}\">burada giriş yap</a>",
+ "SIGNIN" => "Giriş yap",
+ "SIGNIN_OR_REGISTER" => "Giriş yap veya kayıt ol",
+ "SIGNUP" => "Üye ol",
+
+ "TOS" => "Şartlar ve Koşullar",
+ "TOS_AGREEMENT" => "Bir hesap ile kaydolarak {{site_title}} sen kabul edersin <a {{link_attributes | raw}}>şartlar ve koşulları</a>.",
+ "TOS_FOR" => "{{title}} için şartlar ve koşullar",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "Kullanıcı Adı",
+
+ "CHOOSE" => "Benzersiz bir kullanıcı adı seç",
+ "INVALID" => "Geçersiz kullanıcı adı",
+ "IN_USE" => "<strong>{{user_name}}</strong> kullanıcı adı zaten mevcut.",
+ "NOT_AVAILABLE" => "<strong>{{user_name}}</strong> kullanıcı adı kullanılamaz. Farklı bir isim veya 'öneriye' tıklayın."
+ ],
+
+ "USER_ID_INVALID" => "İstenen kullanıcı adı mevcut değil.",
+ "USER_OR_EMAIL_INVALID" => "Kullanıcı adı veya e-posta adresi hatalı.",
+ "USER_OR_PASS_INVALID" => "Kullanıcı bulunamadı ya da şifre hatalı.",
+
+ "WELCOME" => "Tekrar Hoşgeldiniz.{{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/tr/validate.php b/main/app/sprinkles/account/locale/tr/validate.php index cd4380b..e392979 100644 --- a/main/app/sprinkles/account/locale/tr/validate.php +++ b/main/app/sprinkles/account/locale/tr/validate.php @@ -1,19 +1,19 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Turkish message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\tr - * @author Dumblledore - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Şifreniz ve onaylama şifreniz eşleşmiyor.", - "USERNAME" => "Kullanıcı adınız sadece küçük harfler, sayılar, '.', '-', ve '_' içerebilir." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Turkish message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\tr
+ * @author Dumblledore
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "Şifreniz ve onaylama şifreniz eşleşmiyor.",
+ "USERNAME" => "Kullanıcı adınız sadece küçük harfler, sayılar, '.', '-', ve '_' içerebilir."
+ ]
+];
diff --git a/main/app/sprinkles/account/locale/zh_CN/messages.php b/main/app/sprinkles/account/locale/zh_CN/messages.php index 41c4439..61a89df 100644 --- a/main/app/sprinkles/account/locale/zh_CN/messages.php +++ b/main/app/sprinkles/account/locale/zh_CN/messages.php @@ -1,177 +1,177 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Chinese message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\zh_CN - * @author @BruceGui (https://github.com/BruceGui) - */ - -return [ - "ACCOUNT" => [ - "@TRANSLATION" => "账户", - - "ACCESS_DENIED" => "噢, 你好像没有权限这么做.", - - "DISABLED" => "这个账户已被禁用. 请联系我们获取更多信息.", - - "EMAIL_UPDATED" => "账户邮箱更新成功", - - "INVALID" => "此账户不存在. 可能已被删除. 请联系我们获取更多信息.", - - "MASTER_NOT_EXISTS" => "在创建超级账户之前你不能注册", - "MY" => "我的账户", - - "SESSION_COMPROMISED" => "你的会话已泄露. 你应该在所有的设备上注销, 然后再登陆确保你的数据没被修改.", - "SESSION_COMPROMISED_TITLE" => "你的账户可能被盗用", - "SESSION_EXPIRED" => "会话已过期. 请重新登陆.", - - "SETTINGS" => [ - "@TRANSLATION" => "账户设置", - "DESCRIPTION" => "更新你的账户, 包括邮箱、姓名和密码.", - "UPDATED" => "账户更新成功" - ], - - "TOOLS" => "账户工具", - - "UNVERIFIED" => "你的账户还没有验证. 检查你的(垃圾)邮箱文件夹进行验证.", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "我们发送了新的验证链接 {{email}}. 请检查你的收件箱或垃圾邮件进行验证.", - "RESEND" => "重新发送验证邮件", - "COMPLETE" => "你已成功验证. 现在可以登陆了.", - "EMAIL" => "请输入你登陆时的邮箱, 然后将会发送验证邮件.", - "PAGE" => "重新发送验证邮件给你的新账户.", - "SEND" => "为我的账户发送验证邮件", - "TOKEN_NOT_FOUND" => "验证令牌不存在 / 账户已经验证", - ] - ], - - "EMAIL" => [ - "INVALID" => "<strong>{{email}}</strong> 没有账户注册.", - "IN_USE" => "邮箱 <strong>{{email}}</strong> 已被使用.", - "VERIFICATION_REQUIRED" => "邮箱 (需要进行验证 - 请使用一个有效的!)" - ], - - "EMAIL_OR_USERNAME" => "用户名或邮箱地址", - - "FIRST_NAME" => "名字", - - "HEADER_MESSAGE_ROOT" => "你现在以超级用户登陆", - - "LAST_NAME" => "姓氏", - - "LOCALE" => [ - "ACCOUNT" => "设置你账户的地区和语言", - "INVALID" => "<strong>{{locale}}</strong> 不是一个有效的地区." - ], - - "LOGIN" => [ - "@TRANSLATION" => "登陆", - "ALREADY_COMPLETE" => "你已经登陆!", - "SOCIAL" => "用其他方式登陆", - "REQUIRED" => "对不起, 你需要登陆才能获取资源." - ], - - "LOGOUT" => "注销", - - "NAME" => "名字", - - "NAME_AND_EMAIL" => "名字和邮箱", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "用 {{site_name}} 账户登陆, 或者创建新账户.", - "SUBTITLE" => "免费注册, 或用已有账户登陆.", - "TITLE" => "让我们开始吧!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "密码", - - "BETWEEN" => "字符长度 {{min}}-{{max}} ", - - "CONFIRM" => "确认密码", - "CONFIRM_CURRENT" => "请确认当前密码", - "CONFIRM_NEW" => "确认新密码", - "CONFIRM_NEW_EXPLAIN" => "重新输入新密码", - "CONFIRM_NEW_HELP" => "选择了新密码时才需要", - "CURRENT" => "密码正确", - "CURRENT_EXPLAIN" => "你必须要确认密码再进行修改", - - "FORGOTTEN" => "忘记密码", - "FORGET" => [ - "@TRANSLATION" => "我忘记了密码", - - "COULD_NOT_UPDATE" => "无法更新密码.", - "EMAIL" => "请输入你登陆时的邮箱. 重置密码的链接将会发送给你.", - "EMAIL_SEND" => "发送重置密码链接", - "INVALID" => "这个重置密码请求无法使用, 或已过期. 请 <a href=\"{{url}}\">重新发送请求<a>.", - "PAGE" => "获取重置密码的链接.", - "REQUEST_CANNED" => "取消重置请求.", - "REQUEST_SENT" => "重置密码的链接已经发送 <strong>{{email}}</strong>." - ], - - "RESET" => [ - "@TRANSLATION" => "重置密码", - "CHOOSE" => "请输入新密码.", - "PAGE" => "为账户设置新密码.", - "SEND" => "设置密码并登陆" - ], - - "HASH_FAILED" => "密码验证失败. 请联系网站管理.", - "INVALID" => "当前密码无法与记录匹配", - "NEW" => "新密码", - "NOTHING_TO_UPDATE" => "新密码不能与旧密码相同", - "UPDATED" => "账户密码更新成功" - ], - - "PROFILE" => [ - "SETTINGS" => "简介设置", - "UPDATED" => "简介设置成功" - ], - - "REGISTER" => "注册", - "REGISTER_ME" => "注册", - - "REGISTRATION" => [ - "BROKEN" => "抱歉, 账户注册过程发送错误. 请联系我们寻求帮助.", - "COMPLETE_TYPE1" => "你已注册成功. 现在可以登陆了.", - "COMPLETE_TYPE2" => "成功注册. 激活链接已经发送给 <strong>{{email}}</strong>. 激活之前无法登陆.", - "DISABLED" => "抱歉, 账户注册以禁用.", - "LOGOUT" => "抱歉, 登陆时不能注册. 请先注销.", - "WELCOME" => "注册简单快速." - ], - - "RATE_LIMIT_EXCEEDED" => "行动速度过快. 请等 {{delay}} 秒后再尝试新的操作.", - "REMEMBER_ME" => "记住我!", - "REMEMBER_ME_ON_COMPUTER" => "在此电脑上记住我 (不推荐在公共电脑上)", - - "SIGNIN" => "登陆", - "SIGNIN_OR_REGISTER" => "登陆或注册", - "SIGNUP" => "注销", - - "TOS" => "条款和说明", - "TOS_AGREEMENT" => "在 {{site_title}} 注册, 你需要接收 <a {{link_attributes | raw}}>条款和说明</a>.", - "TOS_FOR" => "{{title}}的条款和说明", - - "USERNAME" => [ - "@TRANSLATION" => "用户名", - - "CHOOSE" => "取一个唯一的用户名", - "INVALID" => "无效的用户名", - "IN_USE" => "用户名 <strong>{{user_name}}</strong> 已存在.", - "NOT_AVAILABLE" => "用户名 <strong>{{user_name}}</strong> 不可用. 重新选择用户名, 或者点击 '建议'." - ], - - "USER_ID_INVALID" => "请求的用户不存在.", - "USER_OR_EMAIL_INVALID" => "用户名或邮箱无效.", - "USER_OR_PASS_INVALID" => "没有发现用户或密码错误.", - - "WELCOME" => "欢迎回来, {{first_name}}" -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Chinese message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\zh_CN
+ * @author @BruceGui (https://github.com/BruceGui)
+ */
+
+return [
+ "ACCOUNT" => [
+ "@TRANSLATION" => "账户",
+
+ "ACCESS_DENIED" => "噢, 你好像没有权限这么做.",
+
+ "DISABLED" => "这个账户已被禁用. 请联系我们获取更多信息.",
+
+ "EMAIL_UPDATED" => "账户邮箱更新成功",
+
+ "INVALID" => "此账户不存在. 可能已被删除. 请联系我们获取更多信息.",
+
+ "MASTER_NOT_EXISTS" => "在创建超级账户之前你不能注册",
+ "MY" => "我的账户",
+
+ "SESSION_COMPROMISED" => "你的会话已泄露. 你应该在所有的设备上注销, 然后再登陆确保你的数据没被修改.",
+ "SESSION_COMPROMISED_TITLE" => "你的账户可能被盗用",
+ "SESSION_EXPIRED" => "会话已过期. 请重新登陆.",
+
+ "SETTINGS" => [
+ "@TRANSLATION" => "账户设置",
+ "DESCRIPTION" => "更新你的账户, 包括邮箱、姓名和密码.",
+ "UPDATED" => "账户更新成功"
+ ],
+
+ "TOOLS" => "账户工具",
+
+ "UNVERIFIED" => "你的账户还没有验证. 检查你的(垃圾)邮箱文件夹进行验证.",
+
+ "VERIFICATION" => [
+ "NEW_LINK_SENT" => "我们发送了新的验证链接 {{email}}. 请检查你的收件箱或垃圾邮件进行验证.",
+ "RESEND" => "重新发送验证邮件",
+ "COMPLETE" => "你已成功验证. 现在可以登陆了.",
+ "EMAIL" => "请输入你登陆时的邮箱, 然后将会发送验证邮件.",
+ "PAGE" => "重新发送验证邮件给你的新账户.",
+ "SEND" => "为我的账户发送验证邮件",
+ "TOKEN_NOT_FOUND" => "验证令牌不存在 / 账户已经验证",
+ ]
+ ],
+
+ "EMAIL" => [
+ "INVALID" => "<strong>{{email}}</strong> 没有账户注册.",
+ "IN_USE" => "邮箱 <strong>{{email}}</strong> 已被使用.",
+ "VERIFICATION_REQUIRED" => "邮箱 (需要进行验证 - 请使用一个有效的!)"
+ ],
+
+ "EMAIL_OR_USERNAME" => "用户名或邮箱地址",
+
+ "FIRST_NAME" => "名字",
+
+ "HEADER_MESSAGE_ROOT" => "你现在以超级用户登陆",
+
+ "LAST_NAME" => "姓氏",
+
+ "LOCALE" => [
+ "ACCOUNT" => "设置你账户的地区和语言",
+ "INVALID" => "<strong>{{locale}}</strong> 不是一个有效的地区."
+ ],
+
+ "LOGIN" => [
+ "@TRANSLATION" => "登陆",
+ "ALREADY_COMPLETE" => "你已经登陆!",
+ "SOCIAL" => "用其他方式登陆",
+ "REQUIRED" => "对不起, 你需要登陆才能获取资源."
+ ],
+
+ "LOGOUT" => "注销",
+
+ "NAME" => "名字",
+
+ "NAME_AND_EMAIL" => "名字和邮箱",
+
+ "PAGE" => [
+ "LOGIN" => [
+ "DESCRIPTION" => "用 {{site_name}} 账户登陆, 或者创建新账户.",
+ "SUBTITLE" => "免费注册, 或用已有账户登陆.",
+ "TITLE" => "让我们开始吧!",
+ ]
+ ],
+
+ "PASSWORD" => [
+ "@TRANSLATION" => "密码",
+
+ "BETWEEN" => "字符长度 {{min}}-{{max}} ",
+
+ "CONFIRM" => "确认密码",
+ "CONFIRM_CURRENT" => "请确认当前密码",
+ "CONFIRM_NEW" => "确认新密码",
+ "CONFIRM_NEW_EXPLAIN" => "重新输入新密码",
+ "CONFIRM_NEW_HELP" => "选择了新密码时才需要",
+ "CURRENT" => "密码正确",
+ "CURRENT_EXPLAIN" => "你必须要确认密码再进行修改",
+
+ "FORGOTTEN" => "忘记密码",
+ "FORGET" => [
+ "@TRANSLATION" => "我忘记了密码",
+
+ "COULD_NOT_UPDATE" => "无法更新密码.",
+ "EMAIL" => "请输入你登陆时的邮箱. 重置密码的链接将会发送给你.",
+ "EMAIL_SEND" => "发送重置密码链接",
+ "INVALID" => "这个重置密码请求无法使用, 或已过期. 请 <a href=\"{{url}}\">重新发送请求<a>.",
+ "PAGE" => "获取重置密码的链接.",
+ "REQUEST_CANNED" => "取消重置请求.",
+ "REQUEST_SENT" => "重置密码的链接已经发送 <strong>{{email}}</strong>."
+ ],
+
+ "RESET" => [
+ "@TRANSLATION" => "重置密码",
+ "CHOOSE" => "请输入新密码.",
+ "PAGE" => "为账户设置新密码.",
+ "SEND" => "设置密码并登陆"
+ ],
+
+ "HASH_FAILED" => "密码验证失败. 请联系网站管理.",
+ "INVALID" => "当前密码无法与记录匹配",
+ "NEW" => "新密码",
+ "NOTHING_TO_UPDATE" => "新密码不能与旧密码相同",
+ "UPDATED" => "账户密码更新成功"
+ ],
+
+ "PROFILE" => [
+ "SETTINGS" => "简介设置",
+ "UPDATED" => "简介设置成功"
+ ],
+
+ "REGISTER" => "注册",
+ "REGISTER_ME" => "注册",
+
+ "REGISTRATION" => [
+ "BROKEN" => "抱歉, 账户注册过程发送错误. 请联系我们寻求帮助.",
+ "COMPLETE_TYPE1" => "你已注册成功. 现在可以登陆了.",
+ "COMPLETE_TYPE2" => "成功注册. 激活链接已经发送给 <strong>{{email}}</strong>. 激活之前无法登陆.",
+ "DISABLED" => "抱歉, 账户注册以禁用.",
+ "LOGOUT" => "抱歉, 登陆时不能注册. 请先注销.",
+ "WELCOME" => "注册简单快速."
+ ],
+
+ "RATE_LIMIT_EXCEEDED" => "行动速度过快. 请等 {{delay}} 秒后再尝试新的操作.",
+ "REMEMBER_ME" => "记住我!",
+ "REMEMBER_ME_ON_COMPUTER" => "在此电脑上记住我 (不推荐在公共电脑上)",
+
+ "SIGNIN" => "登陆",
+ "SIGNIN_OR_REGISTER" => "登陆或注册",
+ "SIGNUP" => "注销",
+
+ "TOS" => "条款和说明",
+ "TOS_AGREEMENT" => "在 {{site_title}} 注册, 你需要接收 <a {{link_attributes | raw}}>条款和说明</a>.",
+ "TOS_FOR" => "{{title}}的条款和说明",
+
+ "USERNAME" => [
+ "@TRANSLATION" => "用户名",
+
+ "CHOOSE" => "取一个唯一的用户名",
+ "INVALID" => "无效的用户名",
+ "IN_USE" => "用户名 <strong>{{user_name}}</strong> 已存在.",
+ "NOT_AVAILABLE" => "用户名 <strong>{{user_name}}</strong> 不可用. 重新选择用户名, 或者点击 '建议'."
+ ],
+
+ "USER_ID_INVALID" => "请求的用户不存在.",
+ "USER_OR_EMAIL_INVALID" => "用户名或邮箱无效.",
+ "USER_OR_PASS_INVALID" => "没有发现用户或密码错误.",
+
+ "WELCOME" => "欢迎回来, {{first_name}}"
+];
diff --git a/main/app/sprinkles/account/locale/zh_CN/validate.php b/main/app/sprinkles/account/locale/zh_CN/validate.php index db58c06..b0ecff3 100644 --- a/main/app/sprinkles/account/locale/zh_CN/validate.php +++ b/main/app/sprinkles/account/locale/zh_CN/validate.php @@ -1,19 +1,19 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * - * Chinese message token translations for the 'account' sprinkle. - * - * @package userfrosting\i18n\zh_CN - * @author @BruceGui (https://github.com/BruceGui) - */ - -return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "密码不一致.", - "USERNAME" => "用户名必须以小写字母, 数字, '.', '-', 和 '_'组成." - ] -]; +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ *
+ * Chinese message token translations for the 'account' sprinkle.
+ *
+ * @package userfrosting\i18n\zh_CN
+ * @author @BruceGui (https://github.com/BruceGui)
+ */
+
+return [
+ "VALIDATE" => [
+ "PASSWORD_MISMATCH" => "密码不一致.",
+ "USERNAME" => "用户名必须以小写字母, 数字, '.', '-', 和 '_'组成."
+ ]
+];
diff --git a/main/app/sprinkles/account/src/Account.php b/main/app/sprinkles/account/src/Account.php index 9f43166..1faccf4 100644 --- a/main/app/sprinkles/account/src/Account.php +++ b/main/app/sprinkles/account/src/Account.php @@ -1,21 +1,21 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account; - -use UserFrosting\System\Sprinkle\Sprinkle; - -/** - * Bootstrapper class for the 'account' sprinkle. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class Account extends Sprinkle -{ - -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account;
+
+use UserFrosting\System\Sprinkle\Sprinkle;
+
+/**
+ * Bootstrapper class for the 'account' sprinkle.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Account extends Sprinkle
+{
+
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/AuthGuard.php b/main/app/sprinkles/account/src/Authenticate/AuthGuard.php index ce64bd7..9603a87 100644 --- a/main/app/sprinkles/account/src/Authenticate/AuthGuard.php +++ b/main/app/sprinkles/account/src/Authenticate/AuthGuard.php @@ -1,55 +1,55 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate; - -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Slim\Http\Body; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException; - -/** - * Middleware to catch requests that fail because they require user authentication. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AuthGuard -{ - /** - * @var Authenticator - */ - protected $authenticator; - - /** - * Constructor. - * - * @param $authenticator Authenticator The current authentication object. - */ - public function __construct($authenticator) { - $this->authenticator = $authenticator; - } - - /** - * Invoke the AuthGuard middleware, throwing an exception if there is no authenticated user in the session. - * - * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request - * @param \Psr\Http\Message\ResponseInterface $response PSR7 response - * @param callable $next Next middleware - * - * @return \Psr\Http\Message\ResponseInterface - */ - public function __invoke($request, $response, $next) { - if (!$this->authenticator->check()) { - throw new AuthExpiredException(); - } else { - return $next($request, $response); - } - - return $response; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Slim\Http\Body;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException;
+
+/**
+ * Middleware to catch requests that fail because they require user authentication.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AuthGuard
+{
+ /**
+ * @var Authenticator
+ */
+ protected $authenticator;
+
+ /**
+ * Constructor.
+ *
+ * @param $authenticator Authenticator The current authentication object.
+ */
+ public function __construct($authenticator) {
+ $this->authenticator = $authenticator;
+ }
+
+ /**
+ * Invoke the AuthGuard middleware, throwing an exception if there is no authenticated user in the session.
+ *
+ * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
+ * @param \Psr\Http\Message\ResponseInterface $response PSR7 response
+ * @param callable $next Next middleware
+ *
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ public function __invoke($request, $response, $next) {
+ if (!$this->authenticator->check()) {
+ throw new AuthExpiredException();
+ } else {
+ return $next($request, $response);
+ }
+
+ return $response;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Authenticator.php b/main/app/sprinkles/account/src/Authenticate/Authenticator.php index 735a688..a4586e4 100644 --- a/main/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/main/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -1,407 +1,407 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate; - -use Birke\Rememberme\Authenticator as RememberMe; -use Birke\Rememberme\Storage\PDOStorage as RememberMePDO; -use Birke\Rememberme\Triplet as RememberMeTriplet; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Session\Session; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountDisabledException; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountInvalidException; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountNotVerifiedException; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException; -use UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException; -use UserFrosting\Sprinkle\Account\Database\Models\User; -use UserFrosting\Sprinkle\Account\Facades\Password; -use UserFrosting\Sprinkle\Core\Util\ClassMapper; - -/** - * Handles authentication tasks. - * - * @author Alex Weissman (https://alexanderweissman.com) - * Partially inspired by Laravel's Authentication component: https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/SessionGuard.php - */ -class Authenticator -{ - /** - * @var ClassMapper - */ - protected $classMapper; - - /** - * @var Session - */ - protected $session; - - /** - * @var Config - */ - protected $config; - - /** - * @var Cache - */ - protected $cache; - - /** - * @var bool - */ - protected $loggedOut = FALSE; - - /** - * @var RememberMePDO - */ - protected $rememberMeStorage; - - /** - * @var RememberMe - */ - protected $rememberMe; - - /** - * @var User - */ - protected $user; - - /** - * Indicates if the user was authenticated via a rememberMe cookie. - * - * @var bool - */ - protected $viaRemember = FALSE; - - /** - * Create a new Authenticator object. - * - * @param ClassMapper $classMapper Maps generic class identifiers to specific class names. - * @param Session $session The session wrapper object that will store the user's id. - * @param Config $config Config object that contains authentication settings. - * @param mixed $cache Cache service instance - */ - public function __construct(ClassMapper $classMapper, Session $session, $config, $cache) { - $this->classMapper = $classMapper; - $this->session = $session; - $this->config = $config; - $this->cache = $cache; - - // Initialize RememberMe storage - $this->rememberMeStorage = new RememberMePDO($this->config['remember_me.table']); - - // Get the actual PDO instance from Eloquent - $pdo = Capsule::connection()->getPdo(); - - $this->rememberMeStorage->setConnection($pdo); - - // Set up RememberMe - $this->rememberMe = new RememberMe($this->rememberMeStorage); - // Set cookie name - $cookieName = $this->config['session.name'] . '-' . $this->config['remember_me.cookie.name']; - $this->rememberMe->getCookie()->setName($cookieName); - - // Change cookie path - $this->rememberMe->getCookie()->setPath($this->config['remember_me.session.path']); - - // Set expire time, if specified - if ($this->config->has('remember_me.expire_time') && ($this->config->has('remember_me.expire_time') != NULL)) { - $this->rememberMe->getCookie()->setExpireTime($this->config['remember_me.expire_time']); - } - - $this->user = NULL; - - $this->viaRemember = FALSE; - } - - /** - * Attempts to authenticate a user based on a supplied identity and password. - * - * If successful, the user's id is stored in session. - */ - public function attempt($identityColumn, $identityValue, $password, $rememberMe = FALSE) { - // Try to load the user, using the specified conditions - $user = $this->classMapper->staticMethod('user', 'where', $identityColumn, $identityValue)->first(); - - if (!$user) { - throw new InvalidCredentialsException(); - } - - // Check that the user has a password set (so, rule out newly created accounts without a password) - if (!$user->password) { - throw new InvalidCredentialsException(); - } - - // Check that the user's account is enabled - if ($user->flag_enabled == 0) { - throw new AccountDisabledException(); - } - - // Check that the user's account is verified (if verification is required) - if ($this->config['site.registration.require_email_verification'] && $user->flag_verified == 0) { - throw new AccountNotVerifiedException(); - } - - // Here is my password. May I please assume the identify of this user now? - if (Password::verify($password, $user->password)) { - $this->login($user, $rememberMe); - return $user; - } else { - // We know the password is at fault here (as opposed to the identity), but lets not give away the combination in case of someone bruteforcing - throw new InvalidCredentialsException(); - } - } - - /** - * Determine if the current user is authenticated. - * - * @return bool - */ - public function check() { - return !is_null($this->user()); - } - - /** - * Determine if the current user is a guest (unauthenticated). - * - * @return bool - */ - public function guest() { - return !$this->check(); - } - - /** - * Process an account login request. - * - * This method logs in the specified user, allowing the client to assume the user's identity for the duration of the session. - * @param User $user The user to log in. - * @param bool $rememberMe Set to true to make this a "persistent session", i.e. one that will re-login even after the session expires. - * @odo Figure out a way to update the currentUser service to reflect the logged-in user *immediately* in the service provider. - * As it stands, the currentUser service will still reflect a "guest user" for the remainder of the request. - */ - public function login($user, $rememberMe = FALSE) { - $oldId = session_id(); - $this->session->regenerateId(TRUE); - - // Since regenerateId deletes the old session, we'll do the same in cache - $this->flushSessionCache($oldId); - - // If the user wants to be remembered, create Rememberme cookie - if ($rememberMe) { - $this->rememberMe->createCookie($user->id); - } else { - $this->rememberMe->clearCookie(); - } - - // Assume identity - $key = $this->config['session.keys.current_user_id']; - $this->session[$key] = $user->id; - - // Set auth mode - $this->viaRemember = FALSE; - - // User login actions - $user->onLogin(); - } - - /** - * Processes an account logout request. - * - * Logs the currently authenticated user out, destroying the PHP session and clearing the persistent session. - * This can optionally remove persistent sessions across all browsers/devices, since there can be a "RememberMe" cookie - * and corresponding database entries in multiple browsers/devices. See http://jaspan.com/improved_persistent_login_cookie_best_practice. - * - * @param bool $complete If set to true, will ensure that the user is logged out from *all* browsers on all devices. - */ - public function logout($complete = FALSE) { - $currentUserId = $this->session->get($this->config['session.keys.current_user_id']); - - // This removes all of the user's persistent logins from the database - if ($complete) { - $this->storage->cleanAllTriplets($currentUserId); - } - - // Clear the rememberMe cookie - $this->rememberMe->clearCookie(); - - // User logout actions - if ($currentUserId) { - $currentUser = $this->classMapper->staticMethod('user', 'find', $currentUserId); - if ($currentUser) { - $currentUser->onLogout(); - } - } - - $this->user = NULL; - $this->loggedOut = TRUE; - - $oldId = session_id(); - - // Completely destroy the session - $this->session->destroy(); - - // Since regenerateId deletes the old session, we'll do the same in cache - $this->flushSessionCache($oldId); - - // Restart the session service - $this->session->start(); - } - - /** - * Try to get the currently authenticated user, returning a guest user if none was found. - * - * Tries to re-establish a session for "remember-me" users who have been logged out due to an expired session. - * @return User|null - * @throws AuthExpiredException - * @throws AuthCompromisedException - * @throws AccountInvalidException - * @throws AccountDisabledException - */ - public function user() { - $user = NULL; - - if (!$this->loggedOut) { - - // Return any cached user - if (!is_null($this->user)) { - return $this->user; - } - - // If this throws a PDOException we catch it and return null than allowing the exception to propagate. - // This is because the error handler relies on Twig, which relies on a Twig Extension, which relies on the global current_user variable. - // So, we really don't want this method to throw any database exceptions. - try { - // Now, check to see if we have a user in session - $user = $this->loginSessionUser(); - - // If no user was found in the session, try to login via RememberMe cookie - if (!$user) { - $user = $this->loginRememberedUser(); - } - } catch (\PDOException $e) { - $user = NULL; - } - } - - return $this->user = $user; - } - - /** - * Determine whether the current user was authenticated using a remember me cookie. - * - * This function is useful when users are performing sensitive operations, and you may want to force them to re-authenticate. - * @return bool - */ - public function viaRemember() { - return $this->viaRemember; - } - - /** - * Attempt to log in the client from their rememberMe token (in their cookie). - * - * @return User|bool If successful, the User object of the remembered user. Otherwise, return false. - * @throws AuthCompromisedException The client attempted to log in with an invalid rememberMe token. - */ - protected function loginRememberedUser() { - /** @var \Birke\Rememberme\LoginResult $loginResult */ - $loginResult = $this->rememberMe->login(); - - if ($loginResult->isSuccess()) { - // Update in session - $this->session[$this->config['session.keys.current_user_id']] = $loginResult->getCredential(); - // There is a chance that an attacker has stolen the login token, - // so we store the fact that the user was logged in via RememberMe (instead of login form) - $this->viaRemember = TRUE; - } else { - // If $rememberMe->login() was not successful, check if the token was invalid as well. This means the cookie was stolen. - if ($loginResult->hasPossibleManipulation()) { - throw new AuthCompromisedException(); - } - } - - return $this->validateUserAccount($loginResult->getCredential()); - } - - /** - * Attempt to log in the client from the session. - * - * @return User|null If successful, the User object of the user in session. Otherwise, return null. - * @throws AuthExpiredException The client attempted to use an expired rememberMe token. - */ - protected function loginSessionUser() { - $userId = $this->session->get($this->config['session.keys.current_user_id']); - - // If a user_id was found in the session, check any rememberMe cookie that was submitted. - // If they submitted an expired rememberMe cookie, then we need to log them out. - if ($userId) { - if (!$this->validateRememberMeCookie()) { - $this->logout(); - throw new AuthExpiredException(); - } - } - - return $this->validateUserAccount($userId); - } - - /** - * Determine if the cookie contains a valid rememberMe token. - * - * @return bool - */ - protected function validateRememberMeCookie() { - $cookieValue = $this->rememberMe->getCookie()->getValue(); - if (!$cookieValue) { - return TRUE; - } - $triplet = RememberMeTriplet::fromString($cookieValue); - if (!$triplet->isValid()) { - return FALSE; - } - - return TRUE; - } - - /** - * Tries to load the specified user by id from the database. - * - * Checks that the account is valid and enabled, throwing an exception if not. - * @param int $userId - * @return User|null - * @throws AccountInvalidException - * @throws AccountDisabledException - */ - protected function validateUserAccount($userId) { - if ($userId) { - $user = $this->classMapper->staticMethod('user', 'find', $userId); - - // If the user doesn't exist any more, throw an exception. - if (!$user) { - throw new AccountInvalidException(); - } - - // If the user has been disabled since their last request, throw an exception. - if (!$user->flag_enabled) { - throw new AccountDisabledException(); - } - - return $user; - } else { - return NULL; - } - } - - /** - * Flush the cache associated with a session id - * - * @param string $id The session id - * @return bool - */ - public function flushSessionCache($id) { - return $this->cache->tags('_s' . $id)->flush(); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate;
+
+use Birke\Rememberme\Authenticator as RememberMe;
+use Birke\Rememberme\Storage\PDOStorage as RememberMePDO;
+use Birke\Rememberme\Triplet as RememberMeTriplet;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Session\Session;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountDisabledException;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountInvalidException;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountNotVerifiedException;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException;
+use UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Account\Facades\Password;
+use UserFrosting\Sprinkle\Core\Util\ClassMapper;
+
+/**
+ * Handles authentication tasks.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * Partially inspired by Laravel's Authentication component: https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/SessionGuard.php
+ */
+class Authenticator
+{
+ /**
+ * @var ClassMapper
+ */
+ protected $classMapper;
+
+ /**
+ * @var Session
+ */
+ protected $session;
+
+ /**
+ * @var Config
+ */
+ protected $config;
+
+ /**
+ * @var Cache
+ */
+ protected $cache;
+
+ /**
+ * @var bool
+ */
+ protected $loggedOut = FALSE;
+
+ /**
+ * @var RememberMePDO
+ */
+ protected $rememberMeStorage;
+
+ /**
+ * @var RememberMe
+ */
+ protected $rememberMe;
+
+ /**
+ * @var User
+ */
+ protected $user;
+
+ /**
+ * Indicates if the user was authenticated via a rememberMe cookie.
+ *
+ * @var bool
+ */
+ protected $viaRemember = FALSE;
+
+ /**
+ * Create a new Authenticator object.
+ *
+ * @param ClassMapper $classMapper Maps generic class identifiers to specific class names.
+ * @param Session $session The session wrapper object that will store the user's id.
+ * @param Config $config Config object that contains authentication settings.
+ * @param mixed $cache Cache service instance
+ */
+ public function __construct(ClassMapper $classMapper, Session $session, $config, $cache) {
+ $this->classMapper = $classMapper;
+ $this->session = $session;
+ $this->config = $config;
+ $this->cache = $cache;
+
+ // Initialize RememberMe storage
+ $this->rememberMeStorage = new RememberMePDO($this->config['remember_me.table']);
+
+ // Get the actual PDO instance from Eloquent
+ $pdo = Capsule::connection()->getPdo();
+
+ $this->rememberMeStorage->setConnection($pdo);
+
+ // Set up RememberMe
+ $this->rememberMe = new RememberMe($this->rememberMeStorage);
+ // Set cookie name
+ $cookieName = $this->config['session.name'] . '-' . $this->config['remember_me.cookie.name'];
+ $this->rememberMe->getCookie()->setName($cookieName);
+
+ // Change cookie path
+ $this->rememberMe->getCookie()->setPath($this->config['remember_me.session.path']);
+
+ // Set expire time, if specified
+ if ($this->config->has('remember_me.expire_time') && ($this->config->has('remember_me.expire_time') != NULL)) {
+ $this->rememberMe->getCookie()->setExpireTime($this->config['remember_me.expire_time']);
+ }
+
+ $this->user = NULL;
+
+ $this->viaRemember = FALSE;
+ }
+
+ /**
+ * Attempts to authenticate a user based on a supplied identity and password.
+ *
+ * If successful, the user's id is stored in session.
+ */
+ public function attempt($identityColumn, $identityValue, $password, $rememberMe = FALSE) {
+ // Try to load the user, using the specified conditions
+ $user = $this->classMapper->staticMethod('user', 'where', $identityColumn, $identityValue)->first();
+
+ if (!$user) {
+ throw new InvalidCredentialsException();
+ }
+
+ // Check that the user has a password set (so, rule out newly created accounts without a password)
+ if (!$user->password) {
+ throw new InvalidCredentialsException();
+ }
+
+ // Check that the user's account is enabled
+ if ($user->flag_enabled == 0) {
+ throw new AccountDisabledException();
+ }
+
+ // Check that the user's account is verified (if verification is required)
+ if ($this->config['site.registration.require_email_verification'] && $user->flag_verified == 0) {
+ throw new AccountNotVerifiedException();
+ }
+
+ // Here is my password. May I please assume the identify of this user now?
+ if (Password::verify($password, $user->password)) {
+ $this->login($user, $rememberMe);
+ return $user;
+ } else {
+ // We know the password is at fault here (as opposed to the identity), but lets not give away the combination in case of someone bruteforcing
+ throw new InvalidCredentialsException();
+ }
+ }
+
+ /**
+ * Determine if the current user is authenticated.
+ *
+ * @return bool
+ */
+ public function check() {
+ return !is_null($this->user());
+ }
+
+ /**
+ * Determine if the current user is a guest (unauthenticated).
+ *
+ * @return bool
+ */
+ public function guest() {
+ return !$this->check();
+ }
+
+ /**
+ * Process an account login request.
+ *
+ * This method logs in the specified user, allowing the client to assume the user's identity for the duration of the session.
+ * @param User $user The user to log in.
+ * @param bool $rememberMe Set to true to make this a "persistent session", i.e. one that will re-login even after the session expires.
+ * @odo Figure out a way to update the currentUser service to reflect the logged-in user *immediately* in the service provider.
+ * As it stands, the currentUser service will still reflect a "guest user" for the remainder of the request.
+ */
+ public function login($user, $rememberMe = FALSE) {
+ $oldId = session_id();
+ $this->session->regenerateId(TRUE);
+
+ // Since regenerateId deletes the old session, we'll do the same in cache
+ $this->flushSessionCache($oldId);
+
+ // If the user wants to be remembered, create Rememberme cookie
+ if ($rememberMe) {
+ $this->rememberMe->createCookie($user->id);
+ } else {
+ $this->rememberMe->clearCookie();
+ }
+
+ // Assume identity
+ $key = $this->config['session.keys.current_user_id'];
+ $this->session[$key] = $user->id;
+
+ // Set auth mode
+ $this->viaRemember = FALSE;
+
+ // User login actions
+ $user->onLogin();
+ }
+
+ /**
+ * Processes an account logout request.
+ *
+ * Logs the currently authenticated user out, destroying the PHP session and clearing the persistent session.
+ * This can optionally remove persistent sessions across all browsers/devices, since there can be a "RememberMe" cookie
+ * and corresponding database entries in multiple browsers/devices. See http://jaspan.com/improved_persistent_login_cookie_best_practice.
+ *
+ * @param bool $complete If set to true, will ensure that the user is logged out from *all* browsers on all devices.
+ */
+ public function logout($complete = FALSE) {
+ $currentUserId = $this->session->get($this->config['session.keys.current_user_id']);
+
+ // This removes all of the user's persistent logins from the database
+ if ($complete) {
+ $this->storage->cleanAllTriplets($currentUserId);
+ }
+
+ // Clear the rememberMe cookie
+ $this->rememberMe->clearCookie();
+
+ // User logout actions
+ if ($currentUserId) {
+ $currentUser = $this->classMapper->staticMethod('user', 'find', $currentUserId);
+ if ($currentUser) {
+ $currentUser->onLogout();
+ }
+ }
+
+ $this->user = NULL;
+ $this->loggedOut = TRUE;
+
+ $oldId = session_id();
+
+ // Completely destroy the session
+ $this->session->destroy();
+
+ // Since regenerateId deletes the old session, we'll do the same in cache
+ $this->flushSessionCache($oldId);
+
+ // Restart the session service
+ $this->session->start();
+ }
+
+ /**
+ * Try to get the currently authenticated user, returning a guest user if none was found.
+ *
+ * Tries to re-establish a session for "remember-me" users who have been logged out due to an expired session.
+ * @return User|null
+ * @throws AuthExpiredException
+ * @throws AuthCompromisedException
+ * @throws AccountInvalidException
+ * @throws AccountDisabledException
+ */
+ public function user() {
+ $user = NULL;
+
+ if (!$this->loggedOut) {
+
+ // Return any cached user
+ if (!is_null($this->user)) {
+ return $this->user;
+ }
+
+ // If this throws a PDOException we catch it and return null than allowing the exception to propagate.
+ // This is because the error handler relies on Twig, which relies on a Twig Extension, which relies on the global current_user variable.
+ // So, we really don't want this method to throw any database exceptions.
+ try {
+ // Now, check to see if we have a user in session
+ $user = $this->loginSessionUser();
+
+ // If no user was found in the session, try to login via RememberMe cookie
+ if (!$user) {
+ $user = $this->loginRememberedUser();
+ }
+ } catch (\PDOException $e) {
+ $user = NULL;
+ }
+ }
+
+ return $this->user = $user;
+ }
+
+ /**
+ * Determine whether the current user was authenticated using a remember me cookie.
+ *
+ * This function is useful when users are performing sensitive operations, and you may want to force them to re-authenticate.
+ * @return bool
+ */
+ public function viaRemember() {
+ return $this->viaRemember;
+ }
+
+ /**
+ * Attempt to log in the client from their rememberMe token (in their cookie).
+ *
+ * @return User|bool If successful, the User object of the remembered user. Otherwise, return false.
+ * @throws AuthCompromisedException The client attempted to log in with an invalid rememberMe token.
+ */
+ protected function loginRememberedUser() {
+ /** @var \Birke\Rememberme\LoginResult $loginResult */
+ $loginResult = $this->rememberMe->login();
+
+ if ($loginResult->isSuccess()) {
+ // Update in session
+ $this->session[$this->config['session.keys.current_user_id']] = $loginResult->getCredential();
+ // There is a chance that an attacker has stolen the login token,
+ // so we store the fact that the user was logged in via RememberMe (instead of login form)
+ $this->viaRemember = TRUE;
+ } else {
+ // If $rememberMe->login() was not successful, check if the token was invalid as well. This means the cookie was stolen.
+ if ($loginResult->hasPossibleManipulation()) {
+ throw new AuthCompromisedException();
+ }
+ }
+
+ return $this->validateUserAccount($loginResult->getCredential());
+ }
+
+ /**
+ * Attempt to log in the client from the session.
+ *
+ * @return User|null If successful, the User object of the user in session. Otherwise, return null.
+ * @throws AuthExpiredException The client attempted to use an expired rememberMe token.
+ */
+ protected function loginSessionUser() {
+ $userId = $this->session->get($this->config['session.keys.current_user_id']);
+
+ // If a user_id was found in the session, check any rememberMe cookie that was submitted.
+ // If they submitted an expired rememberMe cookie, then we need to log them out.
+ if ($userId) {
+ if (!$this->validateRememberMeCookie()) {
+ $this->logout();
+ throw new AuthExpiredException();
+ }
+ }
+
+ return $this->validateUserAccount($userId);
+ }
+
+ /**
+ * Determine if the cookie contains a valid rememberMe token.
+ *
+ * @return bool
+ */
+ protected function validateRememberMeCookie() {
+ $cookieValue = $this->rememberMe->getCookie()->getValue();
+ if (!$cookieValue) {
+ return TRUE;
+ }
+ $triplet = RememberMeTriplet::fromString($cookieValue);
+ if (!$triplet->isValid()) {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Tries to load the specified user by id from the database.
+ *
+ * Checks that the account is valid and enabled, throwing an exception if not.
+ * @param int $userId
+ * @return User|null
+ * @throws AccountInvalidException
+ * @throws AccountDisabledException
+ */
+ protected function validateUserAccount($userId) {
+ if ($userId) {
+ $user = $this->classMapper->staticMethod('user', 'find', $userId);
+
+ // If the user doesn't exist any more, throw an exception.
+ if (!$user) {
+ throw new AccountInvalidException();
+ }
+
+ // If the user has been disabled since their last request, throw an exception.
+ if (!$user->flag_enabled) {
+ throw new AccountDisabledException();
+ }
+
+ return $user;
+ } else {
+ return NULL;
+ }
+ }
+
+ /**
+ * Flush the cache associated with a session id
+ *
+ * @param string $id The session id
+ * @return bool
+ */
+ public function flushSessionCache($id) {
+ return $this->cache->tags('_s' . $id)->flush();
+ }
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php index 3ad4c59..314fcc3 100644 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php +++ b/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php @@ -1,22 +1,22 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Disabled account exception. Used when an account has been disabled. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AccountDisabledException extends HttpException -{ - protected $defaultMessage = 'ACCOUNT.DISABLED'; - protected $httpErrorCode = 403; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Disabled account exception. Used when an account has been disabled.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AccountDisabledException extends HttpException
+{
+ protected $defaultMessage = 'ACCOUNT.DISABLED';
+ protected $httpErrorCode = 403;
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php index fb06fae..bc42b62 100644 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php +++ b/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php @@ -1,22 +1,22 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Invalid account exception. Used when an account has been removed during an active session. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AccountInvalidException extends HttpException -{ - protected $defaultMessage = 'ACCOUNT.INVALID'; - protected $httpErrorCode = 403; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Invalid account exception. Used when an account has been removed during an active session.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AccountInvalidException extends HttpException
+{
+ protected $defaultMessage = 'ACCOUNT.INVALID';
+ protected $httpErrorCode = 403;
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php index 2a721bb..1548201 100644 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php +++ b/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php @@ -1,22 +1,22 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Unverified account exception. Used when an account is required to complete email verification, but hasn't done so yet. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AccountNotVerifiedException extends HttpException -{ - protected $defaultMessage = 'ACCOUNT.UNVERIFIED'; - protected $httpErrorCode = 403; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Unverified account exception. Used when an account is required to complete email verification, but hasn't done so yet.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AccountNotVerifiedException extends HttpException
+{
+ protected $defaultMessage = 'ACCOUNT.UNVERIFIED';
+ protected $httpErrorCode = 403;
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php index 52fd528..dd169bd 100644 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php +++ b/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php @@ -1,21 +1,21 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; - -use UserFrosting\Support\Exception\ForbiddenException; - -/** - * Compromised authentication exception. Used when we suspect theft of the rememberMe cookie. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AuthCompromisedException extends ForbiddenException -{ - protected $defaultMessage = 'ACCOUNT.SESSION_COMPROMISED'; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
+
+use UserFrosting\Support\Exception\ForbiddenException;
+
+/**
+ * Compromised authentication exception. Used when we suspect theft of the rememberMe cookie.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AuthCompromisedException extends ForbiddenException
+{
+ protected $defaultMessage = 'ACCOUNT.SESSION_COMPROMISED';
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php index ab7cbdb..2345118 100644 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php +++ b/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php @@ -1,22 +1,22 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Expired authentication exception. Used when the user needs to authenticate/reauthenticate. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AuthExpiredException extends HttpException -{ - protected $defaultMessage = 'ACCOUNT.SESSION_EXPIRED'; - protected $httpErrorCode = 401; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Expired authentication exception. Used when the user needs to authenticate/reauthenticate.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AuthExpiredException extends HttpException
+{
+ protected $defaultMessage = 'ACCOUNT.SESSION_EXPIRED';
+ protected $httpErrorCode = 401;
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php b/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php index 78ea3de..8f73403 100644 --- a/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php +++ b/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php @@ -1,22 +1,22 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Invalid credentials exception. Used when an account fails authentication for some reason. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class InvalidCredentialsException extends HttpException -{ - protected $defaultMessage = 'USER_OR_PASS_INVALID'; - protected $httpErrorCode = 403; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Invalid credentials exception. Used when an account fails authentication for some reason.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class InvalidCredentialsException extends HttpException
+{
+ protected $defaultMessage = 'USER_OR_PASS_INVALID';
+ protected $httpErrorCode = 403;
+}
diff --git a/main/app/sprinkles/account/src/Authenticate/Hasher.php b/main/app/sprinkles/account/src/Authenticate/Hasher.php index 5de939f..7ec832e 100644 --- a/main/app/sprinkles/account/src/Authenticate/Hasher.php +++ b/main/app/sprinkles/account/src/Authenticate/Hasher.php @@ -1,105 +1,105 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authenticate; - -/** - * Password hashing and validation class - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class Hasher -{ - /** - * Default crypt cost factor. - * - * @var int - */ - protected $defaultRounds = 10; - - /** - * Returns the hashing type for a specified password hash. - * - * Automatically detects the hash type: "sha1" (for UserCake legacy accounts), "legacy" (for 0.1.x accounts), and "modern" (used for new accounts). - * @param string $password the hashed password. - * @return string "sha1"|"legacy"|"modern". - */ - public function getHashType($password) { - // If the password in the db is 65 characters long, we have an sha1-hashed password. - if (strlen($password) == 65) { - return 'sha1'; - } else if (strlen($password) == 82) { - return 'legacy'; - } - - return 'modern'; - } - - /** - * Hashes a plaintext password using bcrypt. - * - * @param string $password the plaintext password. - * @param array $options - * @return string the hashed password. - * @throws HashFailedException - */ - public function hash($password, array $options = []) { - $hash = password_hash($password, PASSWORD_BCRYPT, [ - 'cost' => $this->cost($options), - ]); - - if (!$hash) { - throw new HashFailedException(); - } - - return $hash; - } - - /** - * Verify a plaintext password against the user's hashed password. - * - * @param string $password The plaintext password to verify. - * @param string $hash The hash to compare against. - * @param array $options - * @return boolean True if the password matches, false otherwise. - */ - public function verify($password, $hash, array $options = []) { - $hashType = $this->getHashType($hash); - - if ($hashType == 'sha1') { - // Legacy UserCake passwords - $salt = substr($hash, 0, 25); // Extract the salt from the hash - $inputHash = $salt . sha1($salt . $password); - - return (hash_equals($inputHash, $hash) === TRUE); - - } else if ($hashType == 'legacy') { - // Homegrown implementation (assuming that current install has been using a cost parameter of 12) - // Used for manual implementation of bcrypt. - // Note that this legacy hashing put the salt at the _end_ for some reason. - $salt = substr($hash, 60); - $inputHash = crypt($password, '$2y$12$' . $salt); - $correctHash = substr($hash, 0, 60); - - return (hash_equals($inputHash, $correctHash) === TRUE); - } - - // Modern implementation - return password_verify($password, $hash); - } - - /** - * Extract the cost value from the options array. - * - * @param array $options - * @return int - */ - protected function cost(array $options = []) { - return isset($options['rounds']) ? $options['rounds'] : $this->defaultRounds; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authenticate;
+
+/**
+ * Password hashing and validation class
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Hasher
+{
+ /**
+ * Default crypt cost factor.
+ *
+ * @var int
+ */
+ protected $defaultRounds = 10;
+
+ /**
+ * Returns the hashing type for a specified password hash.
+ *
+ * Automatically detects the hash type: "sha1" (for UserCake legacy accounts), "legacy" (for 0.1.x accounts), and "modern" (used for new accounts).
+ * @param string $password the hashed password.
+ * @return string "sha1"|"legacy"|"modern".
+ */
+ public function getHashType($password) {
+ // If the password in the db is 65 characters long, we have an sha1-hashed password.
+ if (strlen($password) == 65) {
+ return 'sha1';
+ } else if (strlen($password) == 82) {
+ return 'legacy';
+ }
+
+ return 'modern';
+ }
+
+ /**
+ * Hashes a plaintext password using bcrypt.
+ *
+ * @param string $password the plaintext password.
+ * @param array $options
+ * @return string the hashed password.
+ * @throws HashFailedException
+ */
+ public function hash($password, array $options = []) {
+ $hash = password_hash($password, PASSWORD_BCRYPT, [
+ 'cost' => $this->cost($options),
+ ]);
+
+ if (!$hash) {
+ throw new HashFailedException();
+ }
+
+ return $hash;
+ }
+
+ /**
+ * Verify a plaintext password against the user's hashed password.
+ *
+ * @param string $password The plaintext password to verify.
+ * @param string $hash The hash to compare against.
+ * @param array $options
+ * @return boolean True if the password matches, false otherwise.
+ */
+ public function verify($password, $hash, array $options = []) {
+ $hashType = $this->getHashType($hash);
+
+ if ($hashType == 'sha1') {
+ // Legacy UserCake passwords
+ $salt = substr($hash, 0, 25); // Extract the salt from the hash
+ $inputHash = $salt . sha1($salt . $password);
+
+ return (hash_equals($inputHash, $hash) === TRUE);
+
+ } else if ($hashType == 'legacy') {
+ // Homegrown implementation (assuming that current install has been using a cost parameter of 12)
+ // Used for manual implementation of bcrypt.
+ // Note that this legacy hashing put the salt at the _end_ for some reason.
+ $salt = substr($hash, 60);
+ $inputHash = crypt($password, '$2y$12$' . $salt);
+ $correctHash = substr($hash, 0, 60);
+
+ return (hash_equals($inputHash, $correctHash) === TRUE);
+ }
+
+ // Modern implementation
+ return password_verify($password, $hash);
+ }
+
+ /**
+ * Extract the cost value from the options array.
+ *
+ * @param array $options
+ * @return int
+ */
+ protected function cost(array $options = []) {
+ return isset($options['rounds']) ? $options['rounds'] : $this->defaultRounds;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php index e36f4f4..8a8225e 100644 --- a/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ b/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php @@ -1,138 +1,138 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authorize; - -use Monolog\Logger; -use PhpParser\Lexer\Emulative as EmulativeLexer; -use PhpParser\Node; -use PhpParser\NodeTraverser; -use PhpParser\Parser as Parser; -use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter; -use PhpParser\Error as PhpParserException; -use Psr\Http\Message\ServerRequestInterface as Request; -use UserFrosting\Sprinkle\Account\Database\Models\User; - -/** - * AccessConditionExpression class - * - * This class models the evaluation of an authorization condition expression, as associated with permissions. - * A condition is built as a boolean expression composed of AccessCondition method calls. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AccessConditionExpression -{ - /** - * @var User A user object, which for convenience can be referenced as 'self' in access conditions. - */ - protected $user; - - /** - * @var ParserNodeFunctionEvaluator The node visitor, which evaluates access condition callbacks used in a permission condition. - */ - protected $nodeVisitor; - - /** - * @var \PhpParser\Parser The PhpParser object to use (initialized in the ctor) - */ - protected $parser; - - /** - * @var NodeTraverser The NodeTraverser object to use (initialized in the ctor) - */ - protected $traverser; - - /** - * @var StandardPrettyPrinter The PrettyPrinter object to use (initialized in the ctor) - */ - protected $prettyPrinter; - - /** - * @var Logger - */ - protected $logger; - - /** - * @var bool Set to true if you want debugging information printed to the auth log. - */ - protected $debug; - - /** - * Create a new AccessConditionExpression object. - * - * @param User $user A user object, which for convenience can be referenced as 'self' in access conditions. - * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. - * @param bool $debug Set to true if you want debugging information printed to the auth log. - */ - public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, User $user, Logger $logger, $debug = FALSE) { - $this->nodeVisitor = $nodeVisitor; - $this->user = $user; - $this->parser = new Parser(new EmulativeLexer); - $this->traverser = new NodeTraverser; - $this->traverser->addVisitor($nodeVisitor); - $this->prettyPrinter = new StandardPrettyPrinter; - $this->logger = $logger; - $this->debug = $debug; - } - - /** - * Evaluates a condition expression, based on the given parameters. - * - * The special parameter `self` is an array of the current user's data. - * This get included automatically, and so does not need to be passed in. - * @param string $condition a boolean expression composed of calls to AccessCondition functions. - * @param array[mixed] $params the parameters to be used when evaluating the expression. - * @return bool true if the condition is passed for the given parameters, otherwise returns false. - */ - public function evaluateCondition($condition, $params) { - // Set the reserved `self` parameters. - // This replaces any values of `self` specified in the arguments, thus preventing them from being overridden in malicious user input. - // (For example, from an unfiltered request body). - $params['self'] = $this->user->export(); - - $this->nodeVisitor->setParams($params); - - $code = "<?php $condition;"; - - if ($this->debug) { - $this->logger->debug("Evaluating access condition '$condition' with parameters:", $params); - } - - // Traverse the parse tree, and execute any callbacks found using the supplied parameters. - // Replace the function node with the return value of the callback. - try { - // parse - $stmts = $this->parser->parse($code); - - // traverse - $stmts = $this->traverser->traverse($stmts); - - // Evaluate boolean statement. It is safe to use eval() here, because our expression has been reduced entirely to a boolean expression. - $expr = $this->prettyPrinter->prettyPrintExpr($stmts[0]); - $expr_eval = "return " . $expr . ";\n"; - $result = eval($expr_eval); - - if ($this->debug) { - $this->logger->debug("Expression '$expr' evaluates to " . ($result == TRUE ? "true" : "false")); - } - - return $result; - } catch (PhpParserException $e) { - if ($this->debug) { - $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage()); - } - return FALSE; // Access fails if the access condition can't be parsed. - } catch (AuthorizationException $e) { - if ($this->debug) { - $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage()); - } - return FALSE; - } - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authorize;
+
+use Monolog\Logger;
+use PhpParser\Lexer\Emulative as EmulativeLexer;
+use PhpParser\Node;
+use PhpParser\NodeTraverser;
+use PhpParser\Parser as Parser;
+use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter;
+use PhpParser\Error as PhpParserException;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+
+/**
+ * AccessConditionExpression class
+ *
+ * This class models the evaluation of an authorization condition expression, as associated with permissions.
+ * A condition is built as a boolean expression composed of AccessCondition method calls.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AccessConditionExpression
+{
+ /**
+ * @var User A user object, which for convenience can be referenced as 'self' in access conditions.
+ */
+ protected $user;
+
+ /**
+ * @var ParserNodeFunctionEvaluator The node visitor, which evaluates access condition callbacks used in a permission condition.
+ */
+ protected $nodeVisitor;
+
+ /**
+ * @var \PhpParser\Parser The PhpParser object to use (initialized in the ctor)
+ */
+ protected $parser;
+
+ /**
+ * @var NodeTraverser The NodeTraverser object to use (initialized in the ctor)
+ */
+ protected $traverser;
+
+ /**
+ * @var StandardPrettyPrinter The PrettyPrinter object to use (initialized in the ctor)
+ */
+ protected $prettyPrinter;
+
+ /**
+ * @var Logger
+ */
+ protected $logger;
+
+ /**
+ * @var bool Set to true if you want debugging information printed to the auth log.
+ */
+ protected $debug;
+
+ /**
+ * Create a new AccessConditionExpression object.
+ *
+ * @param User $user A user object, which for convenience can be referenced as 'self' in access conditions.
+ * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations.
+ * @param bool $debug Set to true if you want debugging information printed to the auth log.
+ */
+ public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, User $user, Logger $logger, $debug = FALSE) {
+ $this->nodeVisitor = $nodeVisitor;
+ $this->user = $user;
+ $this->parser = new Parser(new EmulativeLexer);
+ $this->traverser = new NodeTraverser;
+ $this->traverser->addVisitor($nodeVisitor);
+ $this->prettyPrinter = new StandardPrettyPrinter;
+ $this->logger = $logger;
+ $this->debug = $debug;
+ }
+
+ /**
+ * Evaluates a condition expression, based on the given parameters.
+ *
+ * The special parameter `self` is an array of the current user's data.
+ * This get included automatically, and so does not need to be passed in.
+ * @param string $condition a boolean expression composed of calls to AccessCondition functions.
+ * @param array[mixed] $params the parameters to be used when evaluating the expression.
+ * @return bool true if the condition is passed for the given parameters, otherwise returns false.
+ */
+ public function evaluateCondition($condition, $params) {
+ // Set the reserved `self` parameters.
+ // This replaces any values of `self` specified in the arguments, thus preventing them from being overridden in malicious user input.
+ // (For example, from an unfiltered request body).
+ $params['self'] = $this->user->export();
+
+ $this->nodeVisitor->setParams($params);
+
+ $code = "<?php $condition;";
+
+ if ($this->debug) {
+ $this->logger->debug("Evaluating access condition '$condition' with parameters:", $params);
+ }
+
+ // Traverse the parse tree, and execute any callbacks found using the supplied parameters.
+ // Replace the function node with the return value of the callback.
+ try {
+ // parse
+ $stmts = $this->parser->parse($code);
+
+ // traverse
+ $stmts = $this->traverser->traverse($stmts);
+
+ // Evaluate boolean statement. It is safe to use eval() here, because our expression has been reduced entirely to a boolean expression.
+ $expr = $this->prettyPrinter->prettyPrintExpr($stmts[0]);
+ $expr_eval = "return " . $expr . ";\n";
+ $result = eval($expr_eval);
+
+ if ($this->debug) {
+ $this->logger->debug("Expression '$expr' evaluates to " . ($result == TRUE ? "true" : "false"));
+ }
+
+ return $result;
+ } catch (PhpParserException $e) {
+ if ($this->debug) {
+ $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage());
+ }
+ return FALSE; // Access fails if the access condition can't be parsed.
+ } catch (AuthorizationException $e) {
+ if ($this->debug) {
+ $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage());
+ }
+ return FALSE;
+ }
+ }
+}
diff --git a/main/app/sprinkles/account/src/Authorize/AuthorizationException.php b/main/app/sprinkles/account/src/Authorize/AuthorizationException.php index 33f3d35..f93e847 100644 --- a/main/app/sprinkles/account/src/Authorize/AuthorizationException.php +++ b/main/app/sprinkles/account/src/Authorize/AuthorizationException.php @@ -1,24 +1,24 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authorize; - -use UserFrosting\Support\Exception\ForbiddenException; - -/** - * AuthorizationException class - * - * Exception for AccessConditionExpression. - * - * @author Alex Weissman (https://alexanderweissman.com) - * @see http://www.userfrosting.com/components/#authorization - */ -class AuthorizationException extends ForbiddenException -{ - -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authorize;
+
+use UserFrosting\Support\Exception\ForbiddenException;
+
+/**
+ * AuthorizationException class
+ *
+ * Exception for AccessConditionExpression.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see http://www.userfrosting.com/components/#authorization
+ */
+class AuthorizationException extends ForbiddenException
+{
+
+}
diff --git a/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php index f9fb196..487881f 100644 --- a/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -1,153 +1,153 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authorize; - -use Interop\Container\ContainerInterface; -use UserFrosting\Sprinkle\Account\Database\Models\User; - -/** - * AuthorizationManager class. - * - * Manages a collection of access condition callbacks, and uses them to perform access control checks on user objects. - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AuthorizationManager -{ - /** - * @var ContainerInterface The global container object, which holds all your services. - */ - protected $ci; - - /** - * @var array[callable] An array of callbacks that accept some parameters and evaluate to true or false. - */ - protected $callbacks = []; - - /** - * Create a new AuthorizationManager object. - * - * @param ContainerInterface $ci The global container object, which holds all your services. - */ - public function __construct(ContainerInterface $ci, array $callbacks = []) { - $this->ci = $ci; - $this->callbacks = $callbacks; - } - - /** - * Register an authorization callback, which can then be used in permission conditions. - * - * To add additional callbacks, simply extend the `authorizer` service in your Sprinkle's service provider. - * @param string $name - * @param callable $callback - */ - public function addCallback($name, $callback) { - $this->callbacks[$name] = $callback; - return $this; - } - - /** - * Get all authorization callbacks. - * - * @return callable[] - */ - public function getCallbacks() { - return $this->callbacks; - } - - /** - * Checks whether or not a user has access on a particular permission slug. - * - * Determine if this user has access to the given $slug under the given $params. - * - * @param UserFrosting\Sprinkle\Account\Database\Models\User $user - * @param string $slug The permission slug to check for access. - * @param array $params [optional] An array of field names => values, specifying any additional data to provide the authorization module - * when determining whether or not this user has access. - * @return boolean True if the user has access, false otherwise. - */ - public function checkAccess(User $user, $slug, array $params = []) { - $debug = $this->ci->config['debug.auth']; - - if ($debug) { - $trace = array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), 1); - $this->ci->authLogger->debug("Authorization check requested at: ", $trace); - $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'..."); - } - - if ($this->ci->authenticator->guest()) { - if ($debug) { - $this->ci->authLogger->debug("User is not logged in. Access denied."); - } - return FALSE; - } - - // The master (root) account has access to everything. - // Need to use loose comparison for now, because some DBs return `id` as a string. - - if ($user->id == $this->ci->config['reserved_user_ids.master']) { - if ($debug) { - $this->ci->authLogger->debug("User is the master (root) user. Access granted."); - } - return TRUE; - } - - // Find all permissions that apply to this user (via roles), and check if any evaluate to true. - $permissions = $user->getCachedPermissions(); - - if (empty($permissions) || !isset($permissions[$slug])) { - if ($debug) { - $this->ci->authLogger->debug("No matching permissions found. Access denied."); - } - return FALSE; - } - - $permissions = $permissions[$slug]; - - if ($debug) { - $this->ci->authLogger->debug("Found matching permissions: \n" . print_r($this->getPermissionsArrayDebugInfo($permissions), TRUE)); - } - - $nodeVisitor = new ParserNodeFunctionEvaluator($this->callbacks, $this->ci->authLogger, $debug); - $ace = new AccessConditionExpression($nodeVisitor, $user, $this->ci->authLogger, $debug); - - foreach ($permissions as $permission) { - $pass = $ace->evaluateCondition($permission->conditions, $params); - if ($pass) { - if ($debug) { - $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}' . Access granted."); - } - return TRUE; - } - } - - if ($debug) { - $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied."); - } - - return FALSE; - } - - /** - * Remove extraneous information from the permission to reduce verbosity. - * - * @param array - * @return array - */ - protected function getPermissionsArrayDebugInfo($permissions) { - $permissionsInfo = []; - foreach ($permissions as $permission) { - $permissionData = array_only($permission->toArray(), ['id', 'slug', 'name', 'conditions', 'description']); - // Remove this until we can find an efficient way to only load these once during debugging - //$permissionData['roles_via'] = $permission->roles_via->pluck('id')->all(); - $permissionsInfo[] = $permissionData; - } - - return $permissionsInfo; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authorize;
+
+use Interop\Container\ContainerInterface;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+
+/**
+ * AuthorizationManager class.
+ *
+ * Manages a collection of access condition callbacks, and uses them to perform access control checks on user objects.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AuthorizationManager
+{
+ /**
+ * @var ContainerInterface The global container object, which holds all your services.
+ */
+ protected $ci;
+
+ /**
+ * @var array[callable] An array of callbacks that accept some parameters and evaluate to true or false.
+ */
+ protected $callbacks = [];
+
+ /**
+ * Create a new AuthorizationManager object.
+ *
+ * @param ContainerInterface $ci The global container object, which holds all your services.
+ */
+ public function __construct(ContainerInterface $ci, array $callbacks = []) {
+ $this->ci = $ci;
+ $this->callbacks = $callbacks;
+ }
+
+ /**
+ * Register an authorization callback, which can then be used in permission conditions.
+ *
+ * To add additional callbacks, simply extend the `authorizer` service in your Sprinkle's service provider.
+ * @param string $name
+ * @param callable $callback
+ */
+ public function addCallback($name, $callback) {
+ $this->callbacks[$name] = $callback;
+ return $this;
+ }
+
+ /**
+ * Get all authorization callbacks.
+ *
+ * @return callable[]
+ */
+ public function getCallbacks() {
+ return $this->callbacks;
+ }
+
+ /**
+ * Checks whether or not a user has access on a particular permission slug.
+ *
+ * Determine if this user has access to the given $slug under the given $params.
+ *
+ * @param UserFrosting\Sprinkle\Account\Database\Models\User $user
+ * @param string $slug The permission slug to check for access.
+ * @param array $params [optional] An array of field names => values, specifying any additional data to provide the authorization module
+ * when determining whether or not this user has access.
+ * @return boolean True if the user has access, false otherwise.
+ */
+ public function checkAccess(User $user, $slug, array $params = []) {
+ $debug = $this->ci->config['debug.auth'];
+
+ if ($debug) {
+ $trace = array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), 1);
+ $this->ci->authLogger->debug("Authorization check requested at: ", $trace);
+ $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'...");
+ }
+
+ if ($this->ci->authenticator->guest()) {
+ if ($debug) {
+ $this->ci->authLogger->debug("User is not logged in. Access denied.");
+ }
+ return FALSE;
+ }
+
+ // The master (root) account has access to everything.
+ // Need to use loose comparison for now, because some DBs return `id` as a string.
+
+ if ($user->id == $this->ci->config['reserved_user_ids.master']) {
+ if ($debug) {
+ $this->ci->authLogger->debug("User is the master (root) user. Access granted.");
+ }
+ return TRUE;
+ }
+
+ // Find all permissions that apply to this user (via roles), and check if any evaluate to true.
+ $permissions = $user->getCachedPermissions();
+
+ if (empty($permissions) || !isset($permissions[$slug])) {
+ if ($debug) {
+ $this->ci->authLogger->debug("No matching permissions found. Access denied.");
+ }
+ return FALSE;
+ }
+
+ $permissions = $permissions[$slug];
+
+ if ($debug) {
+ $this->ci->authLogger->debug("Found matching permissions: \n" . print_r($this->getPermissionsArrayDebugInfo($permissions), TRUE));
+ }
+
+ $nodeVisitor = new ParserNodeFunctionEvaluator($this->callbacks, $this->ci->authLogger, $debug);
+ $ace = new AccessConditionExpression($nodeVisitor, $user, $this->ci->authLogger, $debug);
+
+ foreach ($permissions as $permission) {
+ $pass = $ace->evaluateCondition($permission->conditions, $params);
+ if ($pass) {
+ if ($debug) {
+ $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}' . Access granted.");
+ }
+ return TRUE;
+ }
+ }
+
+ if ($debug) {
+ $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied.");
+ }
+
+ return FALSE;
+ }
+
+ /**
+ * Remove extraneous information from the permission to reduce verbosity.
+ *
+ * @param array
+ * @return array
+ */
+ protected function getPermissionsArrayDebugInfo($permissions) {
+ $permissionsInfo = [];
+ foreach ($permissions as $permission) {
+ $permissionData = array_only($permission->toArray(), ['id', 'slug', 'name', 'conditions', 'description']);
+ // Remove this until we can find an efficient way to only load these once during debugging
+ //$permissionData['roles_via'] = $permission->roles_via->pluck('id')->all();
+ $permissionsInfo[] = $permissionData;
+ }
+
+ return $permissionsInfo;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php b/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php index e0db07d..af26d9a 100644 --- a/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php +++ b/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php @@ -1,189 +1,189 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Authorize; - -use Monolog\Logger; -use PhpParser\Node; -use PhpParser\NodeVisitorAbstract; -use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter; - -/** - * ParserNodeFunctionEvaluator class - * - * This class parses access control condition expressions. - * - * @author Alex Weissman (https://alexanderweissman.com) - * @see http://www.userfrosting.com/components/#authorization - */ -class ParserNodeFunctionEvaluator extends NodeVisitorAbstract -{ - - /** - * @var array[callable] An array of callback functions to be used when evaluating a condition expression. - */ - protected $callbacks; - /** - * @var \PhpParser\PrettyPrinter\Standard The PrettyPrinter object to use (initialized in the ctor) - */ - protected $prettyPrinter; - /** - * @var array The parameters to be used when evaluating the methods in the condition expression, as an array. - */ - protected $params = []; - - /** - * @var Logger - */ - protected $logger; - - /** - * @var bool Set to true if you want debugging information printed to the auth log. - */ - protected $debug; - - /** - * Create a new ParserNodeFunctionEvaluator object. - * - * @param array $params The parameters to be used when evaluating the methods in the condition expression, as an array. - * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. - * @param bool $debug Set to true if you want debugging information printed to the auth log. - */ - public function __construct($callbacks, $logger, $debug = FALSE) { - $this->callbacks = $callbacks; - $this->prettyPrinter = new StandardPrettyPrinter; - $this->logger = $logger; - $this->debug = $debug; - $this->params = []; - } - - public function leaveNode(Node $node) { - // Look for function calls - if ($node instanceof \PhpParser\Node\Expr\FuncCall) { - $eval = new \PhpParser\Node\Scalar\LNumber; - - // Get the method name - $callbackName = $node->name->toString(); - // Get the method arguments - $argNodes = $node->args; - - $args = []; - $argsInfo = []; - foreach ($argNodes as $arg) { - $argString = $this->prettyPrinter->prettyPrintExpr($arg->value); - - // Debugger info - $currentArgInfo = [ - 'expression' => $argString - ]; - // Resolve parameter placeholders ('variable' names (either single-word or array-dot identifiers)) - if (($arg->value instanceof \PhpParser\Node\Expr\BinaryOp\Concat) || ($arg->value instanceof \PhpParser\Node\Expr\ConstFetch)) { - $value = $this->resolveParamPath($argString); - $currentArgInfo['type'] = "parameter"; - $currentArgInfo['resolved_value'] = $value; - // Resolve arrays - } else if ($arg->value instanceof \PhpParser\Node\Expr\Array_) { - $value = $this->resolveArray($arg); - $currentArgInfo['type'] = "array"; - $currentArgInfo['resolved_value'] = print_r($value, TRUE); - // Resolve strings - } else if ($arg->value instanceof \PhpParser\Node\Scalar\String_) { - $value = $arg->value->value; - $currentArgInfo['type'] = "string"; - $currentArgInfo['resolved_value'] = $value; - // Resolve numbers - } else if ($arg->value instanceof \PhpParser\Node\Scalar\DNumber) { - $value = $arg->value->value; - $currentArgInfo['type'] = "float"; - $currentArgInfo['resolved_value'] = $value; - } else if ($arg->value instanceof \PhpParser\Node\Scalar\LNumber) { - $value = $arg->value->value; - $currentArgInfo['type'] = "integer"; - $currentArgInfo['resolved_value'] = $value; - // Anything else is simply interpreted as its literal string value - } else { - $value = $argString; - $currentArgInfo['type'] = "unknown"; - $currentArgInfo['resolved_value'] = $value; - } - - $args[] = $value; - $argsInfo[] = $currentArgInfo; - } - - if ($this->debug) { - if (count($args)) { - $this->logger->debug("Evaluating callback '$callbackName' on: ", $argsInfo); - } else { - $this->logger->debug("Evaluating callback '$callbackName'..."); - } - } - - // Call the specified access condition callback with the specified arguments. - if (isset($this->callbacks[$callbackName]) && is_callable($this->callbacks[$callbackName])) { - $result = call_user_func_array($this->callbacks[$callbackName], $args); - } else { - throw new AuthorizationException("Authorization failed: Access condition method '$callbackName' does not exist."); - } - - if ($this->debug) { - $this->logger->debug("Result: " . ($result ? "1" : "0")); - } - - return new \PhpParser\Node\Scalar\LNumber($result ? "1" : "0"); - } - } - - public function setParams($params) { - $this->params = $params; - } - - /** - * Resolve an array expression in a condition expression into an actual array. - * - * @param string $arg the array, represented as a string. - * @return array[mixed] the array, as a plain ol' PHP array. - */ - private function resolveArray($arg) { - $arr = []; - $items = (array)$arg->value->items; - foreach ($items as $item) { - if ($item->key) { - $arr[$item->key] = $item->value->value; - } else { - $arr[] = $item->value->value; - } - } - return $arr; - } - - /** - * Resolve a parameter path (e.g. "user.id", "post", etc) into its value. - * - * @param string $path the name of the parameter to resolve, based on the parameters set in this object. - * @throws Exception the path could not be resolved. Path is malformed or key does not exist. - * @return mixed the value of the specified parameter. - */ - private function resolveParamPath($path) { - $pathTokens = explode(".", $path); - $value = $this->params; - foreach ($pathTokens as $token) { - $token = trim($token); - if (is_array($value) && isset($value[$token])) { - $value = $value[$token]; - continue; - } else if (is_object($value) && isset($value->$token)) { - $value = $value->$token; - continue; - } else { - throw new AuthorizationException("Cannot resolve the path \"$path\". Error at token \"$token\"."); - } - } - return $value; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Authorize;
+
+use Monolog\Logger;
+use PhpParser\Node;
+use PhpParser\NodeVisitorAbstract;
+use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter;
+
+/**
+ * ParserNodeFunctionEvaluator class
+ *
+ * This class parses access control condition expressions.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see http://www.userfrosting.com/components/#authorization
+ */
+class ParserNodeFunctionEvaluator extends NodeVisitorAbstract
+{
+
+ /**
+ * @var array[callable] An array of callback functions to be used when evaluating a condition expression.
+ */
+ protected $callbacks;
+ /**
+ * @var \PhpParser\PrettyPrinter\Standard The PrettyPrinter object to use (initialized in the ctor)
+ */
+ protected $prettyPrinter;
+ /**
+ * @var array The parameters to be used when evaluating the methods in the condition expression, as an array.
+ */
+ protected $params = [];
+
+ /**
+ * @var Logger
+ */
+ protected $logger;
+
+ /**
+ * @var bool Set to true if you want debugging information printed to the auth log.
+ */
+ protected $debug;
+
+ /**
+ * Create a new ParserNodeFunctionEvaluator object.
+ *
+ * @param array $params The parameters to be used when evaluating the methods in the condition expression, as an array.
+ * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations.
+ * @param bool $debug Set to true if you want debugging information printed to the auth log.
+ */
+ public function __construct($callbacks, $logger, $debug = FALSE) {
+ $this->callbacks = $callbacks;
+ $this->prettyPrinter = new StandardPrettyPrinter;
+ $this->logger = $logger;
+ $this->debug = $debug;
+ $this->params = [];
+ }
+
+ public function leaveNode(Node $node) {
+ // Look for function calls
+ if ($node instanceof \PhpParser\Node\Expr\FuncCall) {
+ $eval = new \PhpParser\Node\Scalar\LNumber;
+
+ // Get the method name
+ $callbackName = $node->name->toString();
+ // Get the method arguments
+ $argNodes = $node->args;
+
+ $args = [];
+ $argsInfo = [];
+ foreach ($argNodes as $arg) {
+ $argString = $this->prettyPrinter->prettyPrintExpr($arg->value);
+
+ // Debugger info
+ $currentArgInfo = [
+ 'expression' => $argString
+ ];
+ // Resolve parameter placeholders ('variable' names (either single-word or array-dot identifiers))
+ if (($arg->value instanceof \PhpParser\Node\Expr\BinaryOp\Concat) || ($arg->value instanceof \PhpParser\Node\Expr\ConstFetch)) {
+ $value = $this->resolveParamPath($argString);
+ $currentArgInfo['type'] = "parameter";
+ $currentArgInfo['resolved_value'] = $value;
+ // Resolve arrays
+ } else if ($arg->value instanceof \PhpParser\Node\Expr\Array_) {
+ $value = $this->resolveArray($arg);
+ $currentArgInfo['type'] = "array";
+ $currentArgInfo['resolved_value'] = print_r($value, TRUE);
+ // Resolve strings
+ } else if ($arg->value instanceof \PhpParser\Node\Scalar\String_) {
+ $value = $arg->value->value;
+ $currentArgInfo['type'] = "string";
+ $currentArgInfo['resolved_value'] = $value;
+ // Resolve numbers
+ } else if ($arg->value instanceof \PhpParser\Node\Scalar\DNumber) {
+ $value = $arg->value->value;
+ $currentArgInfo['type'] = "float";
+ $currentArgInfo['resolved_value'] = $value;
+ } else if ($arg->value instanceof \PhpParser\Node\Scalar\LNumber) {
+ $value = $arg->value->value;
+ $currentArgInfo['type'] = "integer";
+ $currentArgInfo['resolved_value'] = $value;
+ // Anything else is simply interpreted as its literal string value
+ } else {
+ $value = $argString;
+ $currentArgInfo['type'] = "unknown";
+ $currentArgInfo['resolved_value'] = $value;
+ }
+
+ $args[] = $value;
+ $argsInfo[] = $currentArgInfo;
+ }
+
+ if ($this->debug) {
+ if (count($args)) {
+ $this->logger->debug("Evaluating callback '$callbackName' on: ", $argsInfo);
+ } else {
+ $this->logger->debug("Evaluating callback '$callbackName'...");
+ }
+ }
+
+ // Call the specified access condition callback with the specified arguments.
+ if (isset($this->callbacks[$callbackName]) && is_callable($this->callbacks[$callbackName])) {
+ $result = call_user_func_array($this->callbacks[$callbackName], $args);
+ } else {
+ throw new AuthorizationException("Authorization failed: Access condition method '$callbackName' does not exist.");
+ }
+
+ if ($this->debug) {
+ $this->logger->debug("Result: " . ($result ? "1" : "0"));
+ }
+
+ return new \PhpParser\Node\Scalar\LNumber($result ? "1" : "0");
+ }
+ }
+
+ public function setParams($params) {
+ $this->params = $params;
+ }
+
+ /**
+ * Resolve an array expression in a condition expression into an actual array.
+ *
+ * @param string $arg the array, represented as a string.
+ * @return array[mixed] the array, as a plain ol' PHP array.
+ */
+ private function resolveArray($arg) {
+ $arr = [];
+ $items = (array)$arg->value->items;
+ foreach ($items as $item) {
+ if ($item->key) {
+ $arr[$item->key] = $item->value->value;
+ } else {
+ $arr[] = $item->value->value;
+ }
+ }
+ return $arr;
+ }
+
+ /**
+ * Resolve a parameter path (e.g. "user.id", "post", etc) into its value.
+ *
+ * @param string $path the name of the parameter to resolve, based on the parameters set in this object.
+ * @throws Exception the path could not be resolved. Path is malformed or key does not exist.
+ * @return mixed the value of the specified parameter.
+ */
+ private function resolveParamPath($path) {
+ $pathTokens = explode(".", $path);
+ $value = $this->params;
+ foreach ($pathTokens as $token) {
+ $token = trim($token);
+ if (is_array($value) && isset($value[$token])) {
+ $value = $value[$token];
+ continue;
+ } else if (is_object($value) && isset($value->$token)) {
+ $value = $value->$token;
+ continue;
+ } else {
+ throw new AuthorizationException("Cannot resolve the path \"$path\". Error at token \"$token\".");
+ }
+ }
+ return $value;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php index f928a2c..178c2b3 100644 --- a/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -1,321 +1,321 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Bakery; - -use Illuminate\Database\Capsule\Manager as Capsule; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use UserFrosting\System\Bakery\BaseCommand; -use UserFrosting\System\Bakery\DatabaseTest; -use UserFrosting\System\Database\Model\Migrations; -use UserFrosting\Sprinkle\Account\Database\Models\User; -use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\Sprinkle\Account\Facades\Password; - -/** - * Create root user CLI command. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class CreateAdminUser extends BaseCommand -{ - use DatabaseTest; - - /** - * @var string[] Migration dependencies for this command to work - */ - protected $dependencies = [ - '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\UsersTable', - '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable', - '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RoleUsersTable' - ]; - - /** - * {@inheritDoc} - */ - protected function configure() { - $this->setName("create-admin") - ->setDescription("Create the initial admin (root) user account"); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Root account setup"); - - // Need the database - try { - $this->io->writeln("<info>Testing database connection</info>", OutputInterface::VERBOSITY_VERBOSE); - $this->testDB(); - $this->io->writeln("Ok", OutputInterface::VERBOSITY_VERBOSE); - } catch (\Exception $e) { - $this->io->error($e->getMessage()); - exit(1); - } - - // Need migration table - if (!Capsule::schema()->hasColumn('migrations', 'id')) { - $this->io->error("Migrations doesn't appear to have been run! Make sure the database is properly migrated by using the `php bakery migrate` command."); - exit(1); - } - - // Make sure the required mirgations have been run - foreach ($this->dependencies as $migration) { - if (!Migrations::where('migration', $migration)->exists()) { - $this->io->error("Migration `$migration` doesn't appear to have been run! Make sure all migrations are up to date by using the `php bakery migrate` command."); - exit(1); - } - } - - // Make sure that there are no users currently in the user table - // We setup the root account here so it can be done independent of the version check - if (User::count() > 0) { - - $this->io->note("Table 'users' is not empty. Skipping root account setup. To set up the root account again, please truncate or drop the table and try again."); - - } else { - - $this->io->writeln("Please answer the following questions to create the root account:\n"); - - // Get the account details - $userName = $this->askUsername(); - $email = $this->askEmail(); - $firstName = $this->askFirstName(); - $lastName = $this->askLastName(); - $password = $this->askPassword(); - - // Ok, now we've got the info and we can create the new user. - $this->io->write("\n<info>Saving the root user details...</info>"); - $rootUser = new User([ - "user_name" => $userName, - "email" => $email, - "first_name" => $firstName, - "last_name" => $lastName, - "password" => Password::hash($password) - ]); - - $rootUser->save(); - - $defaultRoles = [ - 'user' => Role::where('slug', 'user')->first(), - 'group-admin' => Role::where('slug', 'group-admin')->first(), - 'site-admin' => Role::where('slug', 'site-admin')->first() - ]; - - foreach ($defaultRoles as $slug => $role) { - if ($role) { - $rootUser->roles()->attach($role->id); - } - } - - $this->io->success("Root user creation successful!"); - } - } - - /** - * Ask for the username - * - * @access protected - * @return void - */ - protected function askUsername() { - while (!isset($userName) || !$this->validateUsername($userName)) { - $userName = $this->io->ask("Choose a root username (1-50 characters, no leading or trailing whitespace)"); - } - return $userName; - } - - /** - * Validate the username. - * - * @access protected - * @param mixed $userName - * @return void - */ - protected function validateUsername($userName) { - // Validate length - if (strlen($userName) < 1 || strlen($userName) > 50) { - $this->io->error("Username must be between 1-50 characters"); - return FALSE; - } - - // Validate format - $options = [ - 'options' => [ - 'regexp' => "/^\S((.*\S)|)$/" - ] - ]; - $validate = filter_var($userName, FILTER_VALIDATE_REGEXP, $options); - if (!$validate) { - $this->io->error("Username can't have any leading or trailing whitespace"); - return FALSE; - } - - return TRUE; - } - - /** - * Ask for the email - * - * @access protected - * @return void - */ - protected function askEmail() { - while (!isset($email) || !$this->validateEmail($email)) { - $email = $this->io->ask("Enter a valid email address (1-254 characters, must be compatible with FILTER_VALIDATE_EMAIL)"); - } - return $email; - } - - /** - * Validate the email. - * - * @access protected - * @param mixed $email - * @return void - */ - protected function validateEmail($email) { - // Validate length - if (strlen($email) < 1 || strlen($email) > 254) { - $this->io->error("Email must be between 1-254 characters"); - return FALSE; - } - - // Validate format - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - $this->io->error("Email must be compatible with FILTER_VALIDATE_EMAIL"); - return FALSE; - } - - return TRUE; - } - - /** - * Ask for the first name - * - * @access protected - * @return void - */ - protected function askFirstName() { - while (!isset($firstName) || !$this->validateFirstName($firstName)) { - $firstName = $this->io->ask("Enter the user first name (1-20 characters)"); - } - return $firstName; - } - - /** - * validateFirstName function. - * - * @access protected - * @param mixed $name - * @return void - */ - protected function validateFirstName($firstName) { - // Validate length - if (strlen($firstName) < 1 || strlen($firstName) > 20) { - $this->io->error("First name must be between 1-20 characters"); - return FALSE; - } - - return TRUE; - } - - /** - * Ask for the last name - * - * @access protected - * @return void - */ - protected function askLastName() { - while (!isset($lastName) || !$this->validateLastName($lastName)) { - $lastName = $this->io->ask("Enter the user last name (1-30 characters)"); - } - return $lastName; - } - - /** - * validateLastName function. - * - * @access protected - * @param mixed $lastName - * @return void - */ - protected function validateLastName($lastName) { - // Validate length - if (strlen($lastName) < 1 || strlen($lastName) > 30) { - $this->io->error("Last name must be between 1-30 characters"); - return FALSE; - } - - return TRUE; - } - - /** - * Ask for the password - * - * @access protected - * @return void - */ - protected function askPassword() { - while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password)) { - $password = $this->io->askHidden("Enter password (12-255 characters)"); - } - return $password; - } - - /** - * validatePassword function. - * - * @access protected - * @param mixed $password - * @return void - */ - protected function validatePassword($password) { - if (strlen($password) < 12 || strlen($password) > 255) { - $this->io->error("Password must be between 12-255 characters"); - return FALSE; - } - - return TRUE; - } - - /** - * confirmPassword function. - * - * @access protected - * @param mixed $passwordToConfirm - * @return void - */ - protected function confirmPassword($passwordToConfirm) { - while (!isset($password)) { - $password = $this->io->askHidden("Please re-enter the chosen password"); - } - return $this->validatePasswordConfirmation($password, $passwordToConfirm); - } - - /** - * validatePasswordConfirmation function. - * - * @access protected - * @param mixed $password - * @param mixed $passwordToConfirm - * @return void - */ - protected function validatePasswordConfirmation($password, $passwordToConfirm) { - if ($password != $passwordToConfirm) { - $this->io->error("Passwords do not match, please try again."); - return FALSE; - } - - return TRUE; - } +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Bakery;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use UserFrosting\System\Bakery\BaseCommand;
+use UserFrosting\System\Bakery\DatabaseTest;
+use UserFrosting\System\Database\Model\Migrations;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Account\Database\Models\Role;
+use UserFrosting\Sprinkle\Account\Facades\Password;
+
+/**
+ * Create root user CLI command.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class CreateAdminUser extends BaseCommand
+{
+ use DatabaseTest;
+
+ /**
+ * @var string[] Migration dependencies for this command to work
+ */
+ protected $dependencies = [
+ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\UsersTable',
+ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable',
+ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RoleUsersTable'
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function configure() {
+ $this->setName("create-admin")
+ ->setDescription("Create the initial admin (root) user account");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ $this->io->title("Root account setup");
+
+ // Need the database
+ try {
+ $this->io->writeln("<info>Testing database connection</info>", OutputInterface::VERBOSITY_VERBOSE);
+ $this->testDB();
+ $this->io->writeln("Ok", OutputInterface::VERBOSITY_VERBOSE);
+ } catch (\Exception $e) {
+ $this->io->error($e->getMessage());
+ exit(1);
+ }
+
+ // Need migration table
+ if (!Capsule::schema()->hasColumn('migrations', 'id')) {
+ $this->io->error("Migrations doesn't appear to have been run! Make sure the database is properly migrated by using the `php bakery migrate` command.");
+ exit(1);
+ }
+
+ // Make sure the required mirgations have been run
+ foreach ($this->dependencies as $migration) {
+ if (!Migrations::where('migration', $migration)->exists()) {
+ $this->io->error("Migration `$migration` doesn't appear to have been run! Make sure all migrations are up to date by using the `php bakery migrate` command.");
+ exit(1);
+ }
+ }
+
+ // Make sure that there are no users currently in the user table
+ // We setup the root account here so it can be done independent of the version check
+ if (User::count() > 0) {
+
+ $this->io->note("Table 'users' is not empty. Skipping root account setup. To set up the root account again, please truncate or drop the table and try again.");
+
+ } else {
+
+ $this->io->writeln("Please answer the following questions to create the root account:\n");
+
+ // Get the account details
+ $userName = $this->askUsername();
+ $email = $this->askEmail();
+ $firstName = $this->askFirstName();
+ $lastName = $this->askLastName();
+ $password = $this->askPassword();
+
+ // Ok, now we've got the info and we can create the new user.
+ $this->io->write("\n<info>Saving the root user details...</info>");
+ $rootUser = new User([
+ "user_name" => $userName,
+ "email" => $email,
+ "first_name" => $firstName,
+ "last_name" => $lastName,
+ "password" => Password::hash($password)
+ ]);
+
+ $rootUser->save();
+
+ $defaultRoles = [
+ 'user' => Role::where('slug', 'user')->first(),
+ 'group-admin' => Role::where('slug', 'group-admin')->first(),
+ 'site-admin' => Role::where('slug', 'site-admin')->first()
+ ];
+
+ foreach ($defaultRoles as $slug => $role) {
+ if ($role) {
+ $rootUser->roles()->attach($role->id);
+ }
+ }
+
+ $this->io->success("Root user creation successful!");
+ }
+ }
+
+ /**
+ * Ask for the username
+ *
+ * @access protected
+ * @return void
+ */
+ protected function askUsername() {
+ while (!isset($userName) || !$this->validateUsername($userName)) {
+ $userName = $this->io->ask("Choose a root username (1-50 characters, no leading or trailing whitespace)");
+ }
+ return $userName;
+ }
+
+ /**
+ * Validate the username.
+ *
+ * @access protected
+ * @param mixed $userName
+ * @return void
+ */
+ protected function validateUsername($userName) {
+ // Validate length
+ if (strlen($userName) < 1 || strlen($userName) > 50) {
+ $this->io->error("Username must be between 1-50 characters");
+ return FALSE;
+ }
+
+ // Validate format
+ $options = [
+ 'options' => [
+ 'regexp' => "/^\S((.*\S)|)$/"
+ ]
+ ];
+ $validate = filter_var($userName, FILTER_VALIDATE_REGEXP, $options);
+ if (!$validate) {
+ $this->io->error("Username can't have any leading or trailing whitespace");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Ask for the email
+ *
+ * @access protected
+ * @return void
+ */
+ protected function askEmail() {
+ while (!isset($email) || !$this->validateEmail($email)) {
+ $email = $this->io->ask("Enter a valid email address (1-254 characters, must be compatible with FILTER_VALIDATE_EMAIL)");
+ }
+ return $email;
+ }
+
+ /**
+ * Validate the email.
+ *
+ * @access protected
+ * @param mixed $email
+ * @return void
+ */
+ protected function validateEmail($email) {
+ // Validate length
+ if (strlen($email) < 1 || strlen($email) > 254) {
+ $this->io->error("Email must be between 1-254 characters");
+ return FALSE;
+ }
+
+ // Validate format
+ if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ $this->io->error("Email must be compatible with FILTER_VALIDATE_EMAIL");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Ask for the first name
+ *
+ * @access protected
+ * @return void
+ */
+ protected function askFirstName() {
+ while (!isset($firstName) || !$this->validateFirstName($firstName)) {
+ $firstName = $this->io->ask("Enter the user first name (1-20 characters)");
+ }
+ return $firstName;
+ }
+
+ /**
+ * validateFirstName function.
+ *
+ * @access protected
+ * @param mixed $name
+ * @return void
+ */
+ protected function validateFirstName($firstName) {
+ // Validate length
+ if (strlen($firstName) < 1 || strlen($firstName) > 20) {
+ $this->io->error("First name must be between 1-20 characters");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Ask for the last name
+ *
+ * @access protected
+ * @return void
+ */
+ protected function askLastName() {
+ while (!isset($lastName) || !$this->validateLastName($lastName)) {
+ $lastName = $this->io->ask("Enter the user last name (1-30 characters)");
+ }
+ return $lastName;
+ }
+
+ /**
+ * validateLastName function.
+ *
+ * @access protected
+ * @param mixed $lastName
+ * @return void
+ */
+ protected function validateLastName($lastName) {
+ // Validate length
+ if (strlen($lastName) < 1 || strlen($lastName) > 30) {
+ $this->io->error("Last name must be between 1-30 characters");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Ask for the password
+ *
+ * @access protected
+ * @return void
+ */
+ protected function askPassword() {
+ while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password)) {
+ $password = $this->io->askHidden("Enter password (12-255 characters)");
+ }
+ return $password;
+ }
+
+ /**
+ * validatePassword function.
+ *
+ * @access protected
+ * @param mixed $password
+ * @return void
+ */
+ protected function validatePassword($password) {
+ if (strlen($password) < 12 || strlen($password) > 255) {
+ $this->io->error("Password must be between 12-255 characters");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * confirmPassword function.
+ *
+ * @access protected
+ * @param mixed $passwordToConfirm
+ * @return void
+ */
+ protected function confirmPassword($passwordToConfirm) {
+ while (!isset($password)) {
+ $password = $this->io->askHidden("Please re-enter the chosen password");
+ }
+ return $this->validatePasswordConfirmation($password, $passwordToConfirm);
+ }
+
+ /**
+ * validatePasswordConfirmation function.
+ *
+ * @access protected
+ * @param mixed $password
+ * @param mixed $passwordToConfirm
+ * @return void
+ */
+ protected function validatePasswordConfirmation($password, $passwordToConfirm) {
+ if ($password != $passwordToConfirm) {
+ $this->io->error("Passwords do not match, please try again.");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
}
\ No newline at end of file diff --git a/main/app/sprinkles/account/src/Controller/AccountController.php b/main/app/sprinkles/account/src/Controller/AccountController.php index 7373923..c4201a7 100644 --- a/main/app/sprinkles/account/src/Controller/AccountController.php +++ b/main/app/sprinkles/account/src/Controller/AccountController.php @@ -1,1271 +1,1271 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Controller; - -use Carbon\Carbon; -use Illuminate\Database\Capsule\Manager as Capsule; -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException as NotFoundException; -use UserFrosting\Fortress\RequestDataTransformer; -use UserFrosting\Fortress\RequestSchema; -use UserFrosting\Fortress\ServerSideValidator; -use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; -use UserFrosting\Sprinkle\Account\Controller\Exception\SpammyRequestException; -use UserFrosting\Sprinkle\Account\Facades\Password; -use UserFrosting\Sprinkle\Account\Util\Util as AccountUtil; -use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Mail\EmailRecipient; -use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage; -use UserFrosting\Sprinkle\Core\Util\Captcha; -use UserFrosting\Support\Exception\BadRequestException; -use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; - -/** - * Controller class for /account/* URLs. Handles account-related activities, including login, registration, password recovery, and account settings. - * - * @author Alex Weissman (https://alexanderweissman.com) - * @see http://www.userfrosting.com/navigating/#structure - */ -class AccountController extends SimpleController -{ - /** - * Check a username for availability. - * - * This route is throttled by default, to discourage abusing it for account enumeration. - * This route is "public access". - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function checkUsername(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - // GET parameters - $params = $request->getQueryParams(); - - // Load request schema - $schema = new RequestSchema('schema://requests/check-username.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - // O: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException - $e = new BadRequestException('Missing or malformed request data!'); - foreach ($validator->errors() as $idx => $field) { - foreach ($field as $eidx => $error) { - $e->addUserMessage($error); - } - } - throw $e; - } - - /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - $delay = $throttler->getDelay('check_username_request'); - - // Throttle requests - if ($delay > 0) { - return $response->withStatus(429); - } - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\I18n\MessageTranslator $translator */ - $translator = $this->ci->translator; - - // Log throttleable event - $throttler->logEvent('check_username_request'); - - if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { - $message = $translator->translate('USERNAME.NOT_AVAILABLE', $data); - return $response->write($message)->withStatus(200); - } else { - return $response->write('true')->withStatus(200); - } - } - - /** - * Processes a request to cancel a password reset request. - * - * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. - * Processes the request from the password reset link, checking that: - * 1. The provided token is associated with an existing user account, who has a pending password reset request. - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function denyResetPassword(Request $request, Response $response, $args) { - // GET parameters - $params = $request->getQueryParams(); - - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - $loginPage = $this->ci->router->pathFor('login'); - - // Load validation rules - $schema = new RequestSchema('schema://requests/deny-password.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Since this is a GET request, we need to redirect on failure - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel - return $response->withRedirect($loginPage, 400); - } - - $passwordReset = $this->ci->repoPasswordReset->cancel($data['token']); - - if (!$passwordReset) { - $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID'); - return $response->withRedirect($loginPage, 400); - } - - $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED'); - return $response->withRedirect($loginPage); - } - - /** - * Processes a request to email a forgotten password reset link to the user. - * - * Processes the request from the form on the "forgot password" page, checking that: - * 1. The rate limit for this type of request is being observed. - * 2. The provided email address belongs to a registered account; - * 3. The submitted data is valid. - * Note that we have removed the requirement that a password reset request not already be in progress. - * This is because we need to allow users to re-request a reset, even if they lose the first reset email. - * This route is "public access". - * Request type: POST - * @odo require additional user information - * @odo prevent password reset requests for root account? - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function forgotPassword(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/forgot-password.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - // Throttle requests - - /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - - $throttleData = [ - 'email' => $data['email'] - ]; - $delay = $throttler->getDelay('password_reset_request', $throttleData); - - if ($delay > 0) { - $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); - return $response->withStatus(429); - } - - // All checks passed! log events/activities, update user, and send email - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) { - - // Log throttleable event - $throttler->logEvent('password_reset_request', $throttleData); - - // Load the user, by email address - $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first(); - - // Check that the email exists. - // If there is no user with that email address, we should still pretend like we succeeded, to prevent account enumeration - if ($user) { - // Try to generate a new password reset request. - // Use timeout for "reset password" - $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']); - - // Create and send email - $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig'); - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $passwordReset->getToken(), - 'request_date' => Carbon::now()->format('Y-m-d H:i:s') - ]); - - $this->ci->mailer->send($message); - } - }); - - $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]); - return $response->withStatus(200); - } - - /** - * Returns a modal containing account terms of service. - * - * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function getModalAccountTos(Request $request, Response $response, $args) { - return $this->ci->view->render($response, 'modals/tos.html.twig'); - } - - /** - * Generate a random captcha, store it to the session, and return the captcha image. - * - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function imageCaptcha(Request $request, Response $response, $args) { - $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); - $captcha->generateRandomCode(); - - return $response->withStatus(200) - ->withHeader('Content-Type', 'image/png;base64') - ->write($captcha->getImage()); - } - - /** - * Processes an account login request. - * - * Processes the request from the form on the login page, checking that: - * 1. The user is not already logged in. - * 2. The rate limit for this type of request is being observed. - * 3. Email login is enabled, if an email address was used. - * 4. The user account exists. - * 5. The user account is enabled and verified. - * 6. The user entered a valid username/email and password. - * This route, by definition, is "public access". - * Request type: POST - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function login(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Return 200 success if user is already logged in - if ($authenticator->check()) { - $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE'); - return $response->withStatus(200); - } - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/login.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - // Determine whether we are trying to log in with an email address or a username - $isEmail = filter_var($data['user_name'], FILTER_VALIDATE_EMAIL); - - // Throttle requests - - /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - - $userIdentifier = $data['user_name']; - - $throttleData = [ - 'user_identifier' => $userIdentifier - ]; - - $delay = $throttler->getDelay('sign_in_attempt', $throttleData); - if ($delay > 0) { - $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [ - 'delay' => $delay - ]); - return $response->withStatus(429); - } - - // Log throttleable event - $throttler->logEvent('sign_in_attempt', $throttleData); - - // If credential is an email address, but email login is not enabled, raise an error. - // Note that we do this after logging throttle event, so this error counts towards throttling limit. - if ($isEmail && !$config['site.login.enable_email']) { - $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID'); - return $response->withStatus(403); - } - - // Try to authenticate the user. Authenticator will throw an exception on failure. - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - $currentUser = $authenticator->attempt(($isEmail ? 'email' : 'user_name'), $userIdentifier, $data['password'], $data['rememberme']); - - $ms->addMessageTranslated('success', 'WELCOME', $currentUser->export()); - - // Set redirect, if relevant - $redirectOnLogin = $this->ci->get('redirect.onLogin'); - - return $redirectOnLogin($request, $response, $args); - } - - /** - * Log the user out completely, including destroying any "remember me" token. - * - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function logout(Request $request, Response $response, $args) { - // Destroy the session - $this->ci->authenticator->logout(); - - // Return to home page - $config = $this->ci->config; - return $response->withStatus(302)->withHeader('Location', $config['site.uri.public']); - } - - /** - * Render the "forgot password" page. - * - * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them. - * By default, this is a "public page" (does not require authentication). - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageForgotPassword(Request $request, Response $response, $args) { - // Load validation rules - $schema = new RequestSchema('schema://requests/forgot-password.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/forgot-password.html.twig', [ - 'page' => [ - 'validators' => [ - 'forgot_password' => $validator->rules('json', FALSE) - ] - ] - ]); - } - - - /** - * Render the account registration page for UserFrosting. - * - * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled). - * By definition, this is a "public page" (does not require authentication). - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageRegister(Request $request, Response $response, $args) { - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - if (!$config['site.registration.enabled']) { - throw new NotFoundException($request, $response); - } - - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Redirect if user is already logged in - if ($authenticator->check()) { - $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); - - return $redirect($request, $response, $args); - } - - // Load validation rules - $schema = new RequestSchema('schema://requests/register.yaml'); - $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/register.html.twig', [ - 'page' => [ - 'validators' => [ - 'register' => $validatorRegister->rules('json', FALSE) - ] - ] - ]); - } - - /** - * Render the "resend verification email" page. - * - * This is a form that allows users who lost their account verification link to have the link resent to their email address. - * By default, this is a "public page" (does not require authentication). - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageResendVerification(Request $request, Response $response, $args) { - // Load validation rules - $schema = new RequestSchema('schema://requests/resend-verification.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/resend-verification.html.twig', [ - 'page' => [ - 'validators' => [ - 'resend_verification' => $validator->rules('json', FALSE) - ] - ] - ]); - } - - /** - * Reset password page. - * - * Renders the new password page for password reset requests. - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageResetPassword(Request $request, Response $response, $args) { - // Insert the user's secret token from the link into the password reset form - $params = $request->getQueryParams(); - - // Load validation rules - note this uses the same schema as "set password" - $schema = new RequestSchema('schema://requests/set-password.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/reset-password.html.twig', [ - 'page' => [ - 'validators' => [ - 'set_password' => $validator->rules('json', FALSE) - ] - ], - 'token' => isset($params['token']) ? $params['token'] : '', - ]); - } - - /** - * Render the "set password" page. - * - * Renders the page where new users who have had accounts created for them by another user, can set their password. - * By default, this is a "public page" (does not require authentication). - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageSetPassword(Request $request, Response $response, $args) { - // Insert the user's secret token from the link into the password set form - $params = $request->getQueryParams(); - - // Load validation rules - $schema = new RequestSchema('schema://requests/set-password.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/set-password.html.twig', [ - 'page' => [ - 'validators' => [ - 'set_password' => $validator->rules('json', FALSE) - ] - ], - 'token' => isset($params['token']) ? $params['token'] : '', - ]); - } - - /** - * Account settings page. - * - * Provides a form for users to modify various properties of their account, such as name, email, locale, etc. - * Any fields that the user does not have permission to modify will be automatically disabled. - * This page requires authentication. - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageSettings(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $this->ci->authorizer; - - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - // Access-controlled page - if (!$authorizer->checkAccess($currentUser, 'uri_account_settings')) { - throw new ForbiddenException(); - } - - // Load validation rules - $schema = new RequestSchema('schema://requests/account-settings.yaml'); - $validatorAccountSettings = new JqueryValidationAdapter($schema, $this->ci->translator); - - $schema = new RequestSchema('schema://requests/profile-settings.yaml'); - $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator); - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // Get a list of all locales - $locales = $config->getDefined('site.locales.available'); - - return $this->ci->view->render($response, 'pages/account-settings.html.twig', [ - 'locales' => $locales, - 'page' => [ - 'validators' => [ - 'account_settings' => $validatorAccountSettings->rules('json', FALSE), - 'profile_settings' => $validatorProfileSettings->rules('json', FALSE) - ], - 'visibility' => ($authorizer->checkAccess($currentUser, 'update_account_settings') ? '' : 'disabled') - ] - ]); - } - - /** - * Render the account sign-in page for UserFrosting. - * - * This allows existing users to sign in. - * By definition, this is a "public page" (does not require authentication). - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function pageSignIn(Request $request, Response $response, $args) { - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Redirect if user is already logged in - if ($authenticator->check()) { - $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); - - return $redirect($request, $response, $args); - } - - // Load validation rules - $schema = new RequestSchema('schema://requests/login.yaml'); - $validatorLogin = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/sign-in.html.twig', [ - 'page' => [ - 'validators' => [ - 'login' => $validatorLogin->rules('json', FALSE) - ] - ] - ]); - } - - /** - * Processes a request to update a user's profile information. - * - * Processes the request from the user profile settings form, checking that: - * 1. They have the necessary permissions to update the posted field(s); - * 2. The submitted data is valid. - * This route requires authentication. - * Request type: POST - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function profile(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $this->ci->authorizer; - - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - // Access control for entire resource - check that the current user has permission to modify themselves - // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. - if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { - $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); - return $response->withStatus(403); - } - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/profile-settings.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - $error = FALSE; - - // Validate, and halt on validation errors. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - $error = TRUE; - } - - // Check that locale is valid - $locales = $config->getDefined('site.locales.available'); - if (!array_key_exists($data['locale'], $locales)) { - $ms->addMessageTranslated('danger', 'LOCALE.INVALID', $data); - $error = TRUE; - } - - if ($error) { - return $response->withStatus(400); - } - - // Looks good, let's update with new values! - // Note that only fields listed in `profile-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB - $currentUser->fill($data); - - $currentUser->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their profile settings.", [ - 'type' => 'update_profile_settings' - ]); - - $ms->addMessageTranslated('success', 'PROFILE.UPDATED'); - return $response->withStatus(200); - } - - /** - * Processes an new account registration request. - * - * This is throttled to prevent account enumeration, since it needs to divulge when a username/email has been used. - * Processes the request from the form on the registration page, checking that: - * 1. The honeypot was not modified; - * 2. The master account has already been created (during installation); - * 3. Account registration is enabled; - * 4. The user is not already logged in; - * 5. Valid information was entered; - * 6. The captcha, if enabled, is correct; - * 7. The username and email are not already taken. - * Automatically sends an activation link upon success, if account activation is enabled. - * This route is "public access". - * Request type: POST - * Returns the User Object for the user record that was created. - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function register(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // Get POST parameters: user_name, first_name, last_name, email, password, passwordc, captcha, spiderbro, csrf_token - $params = $request->getParsedBody(); - - // Check the honeypot. 'spiderbro' is not a real field, it is hidden on the main page and must be submitted with its default value for this to be processed. - if (!isset($params['spiderbro']) || $params['spiderbro'] != 'http://') { - throw new SpammyRequestException('Possible spam received:' . print_r($params, TRUE)); - } - - // Security measure: do not allow registering new users until the master account has been created. - if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) { - $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS'); - return $response->withStatus(403); - } - - // Check if registration is currently enabled - if (!$config['site.registration.enabled']) { - $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED'); - return $response->withStatus(403); - } - - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Prevent the user from registering if he/she is already logged in - if ($authenticator->check()) { - $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT'); - return $response->withStatus(403); - } - - // Load the request schema - $schema = new RequestSchema('schema://requests/register.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - $error = FALSE; - - // Validate request data - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - $error = TRUE; - } - - /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - $delay = $throttler->getDelay('registration_attempt'); - - // Throttle requests - if ($delay > 0) { - return $response->withStatus(429); - } - - // Check if username or email already exists - if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { - $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data); - $error = TRUE; - } - - if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { - $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); - $error = TRUE; - } - - // Check captcha, if required - if ($config['site.registration.captcha']) { - $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); - if (!$data['captcha'] || !$captcha->verifyCode($data['captcha'])) { - $ms->addMessageTranslated('danger', 'CAPTCHA.FAIL'); - $error = TRUE; - } - } - - if ($error) { - return $response->withStatus(400); - } - - // Remove captcha, password confirmation from object data after validation - unset($data['captcha']); - unset($data['passwordc']); - - if ($config['site.registration.require_email_verification']) { - $data['flag_verified'] = FALSE; - } else { - $data['flag_verified'] = TRUE; - } - - // Load default group - $groupSlug = $config['site.registration.user_defaults.group']; - $defaultGroup = $classMapper->staticMethod('group', 'where', 'slug', $groupSlug)->first(); - - if (!$defaultGroup) { - $e = new HttpException("Account registration is not working because the default group '$groupSlug' does not exist."); - $e->addUserMessage('REGISTRATION.BROKEN'); - throw $e; - } - - // Set default group - $data['group_id'] = $defaultGroup->id; - - // Set default locale - $data['locale'] = $config['site.registration.user_defaults.locale']; - - // Hash password - $data['password'] = Password::hash($data['password']); - - // All checks passed! log events/activities, create user, and send verification email (if required) - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $throttler) { - // Log throttleable event - $throttler->logEvent('registration_attempt'); - - // Create the user - $user = $classMapper->createInstance('user', $data); - - // Store new user to database - $user->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [ - 'type' => 'sign_up', - 'user_id' => $user->id - ]); - - // Load default roles - $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs'); - $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get(); - $defaultRoleIds = $defaultRoles->pluck('id')->all(); - - // Attach default roles - $user->roles()->attach($defaultRoleIds); - - // Verification email - if ($config['site.registration.require_email_verification']) { - // Try to generate a new verification request - $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); - - // Create and send verification email - $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig'); - - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $verification->getToken() - ]); - - $this->ci->mailer->send($message); - - $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray()); - } else { - // No verification required - $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1'); - } - }); - - return $response->withStatus(200); - } - - /** - * Processes a request to resend the verification email for a new user account. - * - * Processes the request from the resend verification email form, checking that: - * 1. The rate limit on this type of request is observed; - * 2. The provided email is associated with an existing user account; - * 3. The user account is not already verified; - * 4. The submitted data is valid. - * This route is "public access". - * Request type: POST - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function resendVerification(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/resend-verification.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - // Throttle requests - - /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - - $throttleData = [ - 'email' => $data['email'] - ]; - $delay = $throttler->getDelay('verification_request', $throttleData); - - if ($delay > 0) { - $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); - return $response->withStatus(429); - } - - // All checks passed! log events/activities, create user, and send verification email (if required) - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) { - // Log throttleable event - $throttler->logEvent('verification_request', $throttleData); - - // Load the user, by email address - $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first(); - - // Check that the user exists and is not already verified. - // If there is no user with that email address, or the user exists and is already verified, - // we pretend like we succeeded to prevent account enumeration - if ($user && $user->flag_verified != '1') { - // We're good to go - record user activity and send the email - $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); - - // Create and send verification email - $message = new TwigMailMessage($this->ci->view, 'mail/resend-verification.html.twig'); - - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $verification->getToken() - ]); - - $this->ci->mailer->send($message); - } - }); - - $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]); - return $response->withStatus(200); - } - - /** - * Processes a request to set the password for a new or current user. - * - * Processes the request from the password create/reset form, which should have the secret token embedded in it, checking that: - * 1. The provided secret token is associated with an existing user account; - * 2. The user has a password set/reset request in progress; - * 3. The token has not expired; - * 4. The submitted data (new password) is valid. - * This route is "public access". - * Request type: POST - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function setPassword(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/set-password.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - $forgotPasswordPage = $this->ci->router->pathFor('forgot-password'); - - // Ok, try to complete the request with the specified token and new password - $passwordReset = $this->ci->repoPasswordReset->complete($data['token'], [ - 'password' => $data['password'] - ]); - - if (!$passwordReset) { - $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]); - return $response->withStatus(400); - } - - $ms->addMessageTranslated('success', 'PASSWORD.UPDATED'); - - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Log out any existing user, and create a new session - if ($authenticator->check()) { - $authenticator->logout(); - } - - // Auto-login the user (without "remember me") - $user = $passwordReset->user; - $authenticator->login($user); - - $ms->addMessageTranslated('success', 'WELCOME', $user->export()); - return $response->withStatus(200); - } - - /** - * Processes a request to update a user's account information. - * - * Processes the request from the user account settings form, checking that: - * 1. The user correctly input their current password; - * 2. They have the necessary permissions to update the posted field(s); - * 3. The submitted data is valid. - * This route requires authentication. - * Request type: POST - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function settings(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $this->ci->authorizer; - - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - // Access control for entire resource - check that the current user has permission to modify themselves - // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. - if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { - $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); - return $response->withStatus(403); - } - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - // POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/account-settings.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - $error = FALSE; - - // Validate, and halt on validation errors. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - $error = TRUE; - } - - // Confirm current password - if (!isset($data['passwordcheck']) || !Password::verify($data['passwordcheck'], $currentUser->password)) { - $ms->addMessageTranslated('danger', 'PASSWORD.INVALID'); - $error = TRUE; - } - - // Remove password check, password confirmation from object data after validation - unset($data['passwordcheck']); - unset($data['passwordc']); - - // If new email was submitted, check that the email address is not in use - if (isset($data['email']) && $data['email'] != $currentUser->email && $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { - $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); - $error = TRUE; - } - - if ($error) { - return $response->withStatus(400); - } - - // Hash new password, if specified - if (isset($data['password']) && !empty($data['password'])) { - $data['password'] = Password::hash($data['password']); - } else { - // Do not pass to model if no password is specified - unset($data['password']); - } - - // Looks good, let's update with new values! - // Note that only fields listed in `account-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB - $currentUser->fill($data); - - $currentUser->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their account settings.", [ - 'type' => 'update_account_settings' - ]); - - $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED'); - return $response->withStatus(200); - } - - /** - * Suggest an available username for a specified first/last name. - * - * This route is "public access". - * Request type: GET - * @odo Can this route be abused for account enumeration? If so we should throttle it as well. - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function suggestUsername(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - $suggestion = AccountUtil::randomUniqueUsername($classMapper, 50, 10); - - // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content. - // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating). - return $response->withJson([ - 'user_name' => $suggestion - ], 200, JSON_PRETTY_PRINT); - } - - /** - * Processes an new email verification request. - * - * Processes the request from the email verification link that was emailed to the user, checking that: - * 1. The token provided matches a user in the database; - * 2. The user account is not already verified; - * This route is "public access". - * Request type: GET - * - * @param Request $request - * @param Response $response - * @param array $args - * @return void - */ - public function verify(Request $request, Response $response, $args) { - /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ - $ms = $this->ci->alerts; - - /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - - $loginPage = $this->ci->router->pathFor('login'); - - // GET parameters - $params = $request->getQueryParams(); - - // Load request schema - $schema = new RequestSchema('schema://requests/account-verify.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. This is a GET request, so we redirect on validation error. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel - return $response->withRedirect($loginPage, 400); - } - - $verification = $this->ci->repoVerification->complete($data['token']); - - if (!$verification) { - $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND'); - return $response->withRedirect($loginPage, 400); - } - - $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.COMPLETE'); - - // Forward to login page - return $response->withRedirect($loginPage); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Controller;
+
+use Carbon\Carbon;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use Slim\Exception\NotFoundException as NotFoundException;
+use UserFrosting\Fortress\RequestDataTransformer;
+use UserFrosting\Fortress\RequestSchema;
+use UserFrosting\Fortress\ServerSideValidator;
+use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
+use UserFrosting\Sprinkle\Account\Controller\Exception\SpammyRequestException;
+use UserFrosting\Sprinkle\Account\Facades\Password;
+use UserFrosting\Sprinkle\Account\Util\Util as AccountUtil;
+use UserFrosting\Sprinkle\Core\Controller\SimpleController;
+use UserFrosting\Sprinkle\Core\Mail\EmailRecipient;
+use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage;
+use UserFrosting\Sprinkle\Core\Util\Captcha;
+use UserFrosting\Support\Exception\BadRequestException;
+use UserFrosting\Support\Exception\ForbiddenException;
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Controller class for /account/* URLs. Handles account-related activities, including login, registration, password recovery, and account settings.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see http://www.userfrosting.com/navigating/#structure
+ */
+class AccountController extends SimpleController
+{
+ /**
+ * Check a username for availability.
+ *
+ * This route is throttled by default, to discourage abusing it for account enumeration.
+ * This route is "public access".
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function checkUsername(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ // Load request schema
+ $schema = new RequestSchema('schema://requests/check-username.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ // O: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException
+ $e = new BadRequestException('Missing or malformed request data!');
+ foreach ($validator->errors() as $idx => $field) {
+ foreach ($field as $eidx => $error) {
+ $e->addUserMessage($error);
+ }
+ }
+ throw $e;
+ }
+
+ /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
+ $throttler = $this->ci->throttler;
+ $delay = $throttler->getDelay('check_username_request');
+
+ // Throttle requests
+ if ($delay > 0) {
+ return $response->withStatus(429);
+ }
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\I18n\MessageTranslator $translator */
+ $translator = $this->ci->translator;
+
+ // Log throttleable event
+ $throttler->logEvent('check_username_request');
+
+ if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) {
+ $message = $translator->translate('USERNAME.NOT_AVAILABLE', $data);
+ return $response->write($message)->withStatus(200);
+ } else {
+ return $response->write('true')->withStatus(200);
+ }
+ }
+
+ /**
+ * Processes a request to cancel a password reset request.
+ *
+ * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves.
+ * Processes the request from the password reset link, checking that:
+ * 1. The provided token is associated with an existing user account, who has a pending password reset request.
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function denyResetPassword(Request $request, Response $response, $args) {
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $loginPage = $this->ci->router->pathFor('login');
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/deny-password.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors. Since this is a GET request, we need to redirect on failure
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel
+ return $response->withRedirect($loginPage, 400);
+ }
+
+ $passwordReset = $this->ci->repoPasswordReset->cancel($data['token']);
+
+ if (!$passwordReset) {
+ $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID');
+ return $response->withRedirect($loginPage, 400);
+ }
+
+ $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED');
+ return $response->withRedirect($loginPage);
+ }
+
+ /**
+ * Processes a request to email a forgotten password reset link to the user.
+ *
+ * Processes the request from the form on the "forgot password" page, checking that:
+ * 1. The rate limit for this type of request is being observed.
+ * 2. The provided email address belongs to a registered account;
+ * 3. The submitted data is valid.
+ * Note that we have removed the requirement that a password reset request not already be in progress.
+ * This is because we need to allow users to re-request a reset, even if they lose the first reset email.
+ * This route is "public access".
+ * Request type: POST
+ * @odo require additional user information
+ * @odo prevent password reset requests for root account?
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function forgotPassword(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // Get POST parameters
+ $params = $request->getParsedBody();
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/forgot-password.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ return $response->withStatus(400);
+ }
+
+ // Throttle requests
+
+ /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
+ $throttler = $this->ci->throttler;
+
+ $throttleData = [
+ 'email' => $data['email']
+ ];
+ $delay = $throttler->getDelay('password_reset_request', $throttleData);
+
+ if ($delay > 0) {
+ $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]);
+ return $response->withStatus(429);
+ }
+
+ // All checks passed! log events/activities, update user, and send email
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) {
+
+ // Log throttleable event
+ $throttler->logEvent('password_reset_request', $throttleData);
+
+ // Load the user, by email address
+ $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first();
+
+ // Check that the email exists.
+ // If there is no user with that email address, we should still pretend like we succeeded, to prevent account enumeration
+ if ($user) {
+ // Try to generate a new password reset request.
+ // Use timeout for "reset password"
+ $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']);
+
+ // Create and send email
+ $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig');
+ $message->from($config['address_book.admin'])
+ ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
+ ->addParams([
+ 'user' => $user,
+ 'token' => $passwordReset->getToken(),
+ 'request_date' => Carbon::now()->format('Y-m-d H:i:s')
+ ]);
+
+ $this->ci->mailer->send($message);
+ }
+ });
+
+ $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]);
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Returns a modal containing account terms of service.
+ *
+ * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function getModalAccountTos(Request $request, Response $response, $args) {
+ return $this->ci->view->render($response, 'modals/tos.html.twig');
+ }
+
+ /**
+ * Generate a random captcha, store it to the session, and return the captcha image.
+ *
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function imageCaptcha(Request $request, Response $response, $args) {
+ $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']);
+ $captcha->generateRandomCode();
+
+ return $response->withStatus(200)
+ ->withHeader('Content-Type', 'image/png;base64')
+ ->write($captcha->getImage());
+ }
+
+ /**
+ * Processes an account login request.
+ *
+ * Processes the request from the form on the login page, checking that:
+ * 1. The user is not already logged in.
+ * 2. The rate limit for this type of request is being observed.
+ * 3. Email login is enabled, if an email address was used.
+ * 4. The user account exists.
+ * 5. The user account is enabled and verified.
+ * 6. The user entered a valid username/email and password.
+ * This route, by definition, is "public access".
+ * Request type: POST
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function login(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $this->ci->authenticator;
+
+ // Return 200 success if user is already logged in
+ if ($authenticator->check()) {
+ $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE');
+ return $response->withStatus(200);
+ }
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // Get POST parameters
+ $params = $request->getParsedBody();
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/login.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ return $response->withStatus(400);
+ }
+
+ // Determine whether we are trying to log in with an email address or a username
+ $isEmail = filter_var($data['user_name'], FILTER_VALIDATE_EMAIL);
+
+ // Throttle requests
+
+ /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
+ $throttler = $this->ci->throttler;
+
+ $userIdentifier = $data['user_name'];
+
+ $throttleData = [
+ 'user_identifier' => $userIdentifier
+ ];
+
+ $delay = $throttler->getDelay('sign_in_attempt', $throttleData);
+ if ($delay > 0) {
+ $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [
+ 'delay' => $delay
+ ]);
+ return $response->withStatus(429);
+ }
+
+ // Log throttleable event
+ $throttler->logEvent('sign_in_attempt', $throttleData);
+
+ // If credential is an email address, but email login is not enabled, raise an error.
+ // Note that we do this after logging throttle event, so this error counts towards throttling limit.
+ if ($isEmail && !$config['site.login.enable_email']) {
+ $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID');
+ return $response->withStatus(403);
+ }
+
+ // Try to authenticate the user. Authenticator will throw an exception on failure.
+ /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $this->ci->authenticator;
+
+ $currentUser = $authenticator->attempt(($isEmail ? 'email' : 'user_name'), $userIdentifier, $data['password'], $data['rememberme']);
+
+ $ms->addMessageTranslated('success', 'WELCOME', $currentUser->export());
+
+ // Set redirect, if relevant
+ $redirectOnLogin = $this->ci->get('redirect.onLogin');
+
+ return $redirectOnLogin($request, $response, $args);
+ }
+
+ /**
+ * Log the user out completely, including destroying any "remember me" token.
+ *
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function logout(Request $request, Response $response, $args) {
+ // Destroy the session
+ $this->ci->authenticator->logout();
+
+ // Return to home page
+ $config = $this->ci->config;
+ return $response->withStatus(302)->withHeader('Location', $config['site.uri.public']);
+ }
+
+ /**
+ * Render the "forgot password" page.
+ *
+ * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them.
+ * By default, this is a "public page" (does not require authentication).
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageForgotPassword(Request $request, Response $response, $args) {
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/forgot-password.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'pages/forgot-password.html.twig', [
+ 'page' => [
+ 'validators' => [
+ 'forgot_password' => $validator->rules('json', FALSE)
+ ]
+ ]
+ ]);
+ }
+
+
+ /**
+ * Render the account registration page for UserFrosting.
+ *
+ * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled).
+ * By definition, this is a "public page" (does not require authentication).
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageRegister(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ if (!$config['site.registration.enabled']) {
+ throw new NotFoundException($request, $response);
+ }
+
+ /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $this->ci->authenticator;
+
+ // Redirect if user is already logged in
+ if ($authenticator->check()) {
+ $redirect = $this->ci->get('redirect.onAlreadyLoggedIn');
+
+ return $redirect($request, $response, $args);
+ }
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/register.yaml');
+ $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'pages/register.html.twig', [
+ 'page' => [
+ 'validators' => [
+ 'register' => $validatorRegister->rules('json', FALSE)
+ ]
+ ]
+ ]);
+ }
+
+ /**
+ * Render the "resend verification email" page.
+ *
+ * This is a form that allows users who lost their account verification link to have the link resent to their email address.
+ * By default, this is a "public page" (does not require authentication).
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageResendVerification(Request $request, Response $response, $args) {
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/resend-verification.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'pages/resend-verification.html.twig', [
+ 'page' => [
+ 'validators' => [
+ 'resend_verification' => $validator->rules('json', FALSE)
+ ]
+ ]
+ ]);
+ }
+
+ /**
+ * Reset password page.
+ *
+ * Renders the new password page for password reset requests.
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageResetPassword(Request $request, Response $response, $args) {
+ // Insert the user's secret token from the link into the password reset form
+ $params = $request->getQueryParams();
+
+ // Load validation rules - note this uses the same schema as "set password"
+ $schema = new RequestSchema('schema://requests/set-password.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'pages/reset-password.html.twig', [
+ 'page' => [
+ 'validators' => [
+ 'set_password' => $validator->rules('json', FALSE)
+ ]
+ ],
+ 'token' => isset($params['token']) ? $params['token'] : '',
+ ]);
+ }
+
+ /**
+ * Render the "set password" page.
+ *
+ * Renders the page where new users who have had accounts created for them by another user, can set their password.
+ * By default, this is a "public page" (does not require authentication).
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageSetPassword(Request $request, Response $response, $args) {
+ // Insert the user's secret token from the link into the password set form
+ $params = $request->getQueryParams();
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/set-password.yaml');
+ $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'pages/set-password.html.twig', [
+ 'page' => [
+ 'validators' => [
+ 'set_password' => $validator->rules('json', FALSE)
+ ]
+ ],
+ 'token' => isset($params['token']) ? $params['token'] : '',
+ ]);
+ }
+
+ /**
+ * Account settings page.
+ *
+ * Provides a form for users to modify various properties of their account, such as name, email, locale, etc.
+ * Any fields that the user does not have permission to modify will be automatically disabled.
+ * This page requires authentication.
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageSettings(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_account_settings')) {
+ throw new ForbiddenException();
+ }
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/account-settings.yaml');
+ $validatorAccountSettings = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ $schema = new RequestSchema('schema://requests/profile-settings.yaml');
+ $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // Get a list of all locales
+ $locales = $config->getDefined('site.locales.available');
+
+ return $this->ci->view->render($response, 'pages/account-settings.html.twig', [
+ 'locales' => $locales,
+ 'page' => [
+ 'validators' => [
+ 'account_settings' => $validatorAccountSettings->rules('json', FALSE),
+ 'profile_settings' => $validatorProfileSettings->rules('json', FALSE)
+ ],
+ 'visibility' => ($authorizer->checkAccess($currentUser, 'update_account_settings') ? '' : 'disabled')
+ ]
+ ]);
+ }
+
+ /**
+ * Render the account sign-in page for UserFrosting.
+ *
+ * This allows existing users to sign in.
+ * By definition, this is a "public page" (does not require authentication).
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function pageSignIn(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $this->ci->authenticator;
+
+ // Redirect if user is already logged in
+ if ($authenticator->check()) {
+ $redirect = $this->ci->get('redirect.onAlreadyLoggedIn');
+
+ return $redirect($request, $response, $args);
+ }
+
+ // Load validation rules
+ $schema = new RequestSchema('schema://requests/login.yaml');
+ $validatorLogin = new JqueryValidationAdapter($schema, $this->ci->translator);
+
+ return $this->ci->view->render($response, 'pages/sign-in.html.twig', [
+ 'page' => [
+ 'validators' => [
+ 'login' => $validatorLogin->rules('json', FALSE)
+ ]
+ ]
+ ]);
+ }
+
+ /**
+ * Processes a request to update a user's profile information.
+ *
+ * Processes the request from the user profile settings form, checking that:
+ * 1. They have the necessary permissions to update the posted field(s);
+ * 2. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: POST
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function profile(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access control for entire resource - check that the current user has permission to modify themselves
+ // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify.
+ if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) {
+ $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED');
+ return $response->withStatus(403);
+ }
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // POST parameters
+ $params = $request->getParsedBody();
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/profile-settings.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate, and halt on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ // Check that locale is valid
+ $locales = $config->getDefined('site.locales.available');
+ if (!array_key_exists($data['locale'], $locales)) {
+ $ms->addMessageTranslated('danger', 'LOCALE.INVALID', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ // Looks good, let's update with new values!
+ // Note that only fields listed in `profile-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB
+ $currentUser->fill($data);
+
+ $currentUser->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their profile settings.", [
+ 'type' => 'update_profile_settings'
+ ]);
+
+ $ms->addMessageTranslated('success', 'PROFILE.UPDATED');
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes an new account registration request.
+ *
+ * This is throttled to prevent account enumeration, since it needs to divulge when a username/email has been used.
+ * Processes the request from the form on the registration page, checking that:
+ * 1. The honeypot was not modified;
+ * 2. The master account has already been created (during installation);
+ * 3. Account registration is enabled;
+ * 4. The user is not already logged in;
+ * 5. Valid information was entered;
+ * 6. The captcha, if enabled, is correct;
+ * 7. The username and email are not already taken.
+ * Automatically sends an activation link upon success, if account activation is enabled.
+ * This route is "public access".
+ * Request type: POST
+ * Returns the User Object for the user record that was created.
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function register(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // Get POST parameters: user_name, first_name, last_name, email, password, passwordc, captcha, spiderbro, csrf_token
+ $params = $request->getParsedBody();
+
+ // Check the honeypot. 'spiderbro' is not a real field, it is hidden on the main page and must be submitted with its default value for this to be processed.
+ if (!isset($params['spiderbro']) || $params['spiderbro'] != 'http://') {
+ throw new SpammyRequestException('Possible spam received:' . print_r($params, TRUE));
+ }
+
+ // Security measure: do not allow registering new users until the master account has been created.
+ if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) {
+ $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS');
+ return $response->withStatus(403);
+ }
+
+ // Check if registration is currently enabled
+ if (!$config['site.registration.enabled']) {
+ $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED');
+ return $response->withStatus(403);
+ }
+
+ /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $this->ci->authenticator;
+
+ // Prevent the user from registering if he/she is already logged in
+ if ($authenticator->check()) {
+ $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT');
+ return $response->withStatus(403);
+ }
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/register.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate request data
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
+ $throttler = $this->ci->throttler;
+ $delay = $throttler->getDelay('registration_attempt');
+
+ // Throttle requests
+ if ($delay > 0) {
+ return $response->withStatus(429);
+ }
+
+ // Check if username or email already exists
+ if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) {
+ $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) {
+ $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ // Check captcha, if required
+ if ($config['site.registration.captcha']) {
+ $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']);
+ if (!$data['captcha'] || !$captcha->verifyCode($data['captcha'])) {
+ $ms->addMessageTranslated('danger', 'CAPTCHA.FAIL');
+ $error = TRUE;
+ }
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ // Remove captcha, password confirmation from object data after validation
+ unset($data['captcha']);
+ unset($data['passwordc']);
+
+ if ($config['site.registration.require_email_verification']) {
+ $data['flag_verified'] = FALSE;
+ } else {
+ $data['flag_verified'] = TRUE;
+ }
+
+ // Load default group
+ $groupSlug = $config['site.registration.user_defaults.group'];
+ $defaultGroup = $classMapper->staticMethod('group', 'where', 'slug', $groupSlug)->first();
+
+ if (!$defaultGroup) {
+ $e = new HttpException("Account registration is not working because the default group '$groupSlug' does not exist.");
+ $e->addUserMessage('REGISTRATION.BROKEN');
+ throw $e;
+ }
+
+ // Set default group
+ $data['group_id'] = $defaultGroup->id;
+
+ // Set default locale
+ $data['locale'] = $config['site.registration.user_defaults.locale'];
+
+ // Hash password
+ $data['password'] = Password::hash($data['password']);
+
+ // All checks passed! log events/activities, create user, and send verification email (if required)
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $throttler) {
+ // Log throttleable event
+ $throttler->logEvent('registration_attempt');
+
+ // Create the user
+ $user = $classMapper->createInstance('user', $data);
+
+ // Store new user to database
+ $user->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [
+ 'type' => 'sign_up',
+ 'user_id' => $user->id
+ ]);
+
+ // Load default roles
+ $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
+ $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get();
+ $defaultRoleIds = $defaultRoles->pluck('id')->all();
+
+ // Attach default roles
+ $user->roles()->attach($defaultRoleIds);
+
+ // Verification email
+ if ($config['site.registration.require_email_verification']) {
+ // Try to generate a new verification request
+ $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']);
+
+ // Create and send verification email
+ $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig');
+
+ $message->from($config['address_book.admin'])
+ ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
+ ->addParams([
+ 'user' => $user,
+ 'token' => $verification->getToken()
+ ]);
+
+ $this->ci->mailer->send($message);
+
+ $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray());
+ } else {
+ // No verification required
+ $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1');
+ }
+ });
+
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes a request to resend the verification email for a new user account.
+ *
+ * Processes the request from the resend verification email form, checking that:
+ * 1. The rate limit on this type of request is observed;
+ * 2. The provided email is associated with an existing user account;
+ * 3. The user account is not already verified;
+ * 4. The submitted data is valid.
+ * This route is "public access".
+ * Request type: POST
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function resendVerification(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // Get POST parameters
+ $params = $request->getParsedBody();
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/resend-verification.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ return $response->withStatus(400);
+ }
+
+ // Throttle requests
+
+ /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
+ $throttler = $this->ci->throttler;
+
+ $throttleData = [
+ 'email' => $data['email']
+ ];
+ $delay = $throttler->getDelay('verification_request', $throttleData);
+
+ if ($delay > 0) {
+ $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]);
+ return $response->withStatus(429);
+ }
+
+ // All checks passed! log events/activities, create user, and send verification email (if required)
+ // Begin transaction - DB will be rolled back if an exception occurs
+ Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) {
+ // Log throttleable event
+ $throttler->logEvent('verification_request', $throttleData);
+
+ // Load the user, by email address
+ $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first();
+
+ // Check that the user exists and is not already verified.
+ // If there is no user with that email address, or the user exists and is already verified,
+ // we pretend like we succeeded to prevent account enumeration
+ if ($user && $user->flag_verified != '1') {
+ // We're good to go - record user activity and send the email
+ $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']);
+
+ // Create and send verification email
+ $message = new TwigMailMessage($this->ci->view, 'mail/resend-verification.html.twig');
+
+ $message->from($config['address_book.admin'])
+ ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
+ ->addParams([
+ 'user' => $user,
+ 'token' => $verification->getToken()
+ ]);
+
+ $this->ci->mailer->send($message);
+ }
+ });
+
+ $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]);
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes a request to set the password for a new or current user.
+ *
+ * Processes the request from the password create/reset form, which should have the secret token embedded in it, checking that:
+ * 1. The provided secret token is associated with an existing user account;
+ * 2. The user has a password set/reset request in progress;
+ * 3. The token has not expired;
+ * 4. The submitted data (new password) is valid.
+ * This route is "public access".
+ * Request type: POST
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function setPassword(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // Get POST parameters
+ $params = $request->getParsedBody();
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/set-password.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ return $response->withStatus(400);
+ }
+
+ $forgotPasswordPage = $this->ci->router->pathFor('forgot-password');
+
+ // Ok, try to complete the request with the specified token and new password
+ $passwordReset = $this->ci->repoPasswordReset->complete($data['token'], [
+ 'password' => $data['password']
+ ]);
+
+ if (!$passwordReset) {
+ $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]);
+ return $response->withStatus(400);
+ }
+
+ $ms->addMessageTranslated('success', 'PASSWORD.UPDATED');
+
+ /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $this->ci->authenticator;
+
+ // Log out any existing user, and create a new session
+ if ($authenticator->check()) {
+ $authenticator->logout();
+ }
+
+ // Auto-login the user (without "remember me")
+ $user = $passwordReset->user;
+ $authenticator->login($user);
+
+ $ms->addMessageTranslated('success', 'WELCOME', $user->export());
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Processes a request to update a user's account information.
+ *
+ * Processes the request from the user account settings form, checking that:
+ * 1. The user correctly input their current password;
+ * 2. They have the necessary permissions to update the posted field(s);
+ * 3. The submitted data is valid.
+ * This route requires authentication.
+ * Request type: POST
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function settings(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access control for entire resource - check that the current user has permission to modify themselves
+ // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify.
+ if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) {
+ $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED');
+ return $response->withStatus(403);
+ }
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ // POST parameters
+ $params = $request->getParsedBody();
+
+ // Load the request schema
+ $schema = new RequestSchema('schema://requests/account-settings.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ $error = FALSE;
+
+ // Validate, and halt on validation errors.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ $error = TRUE;
+ }
+
+ // Confirm current password
+ if (!isset($data['passwordcheck']) || !Password::verify($data['passwordcheck'], $currentUser->password)) {
+ $ms->addMessageTranslated('danger', 'PASSWORD.INVALID');
+ $error = TRUE;
+ }
+
+ // Remove password check, password confirmation from object data after validation
+ unset($data['passwordcheck']);
+ unset($data['passwordc']);
+
+ // If new email was submitted, check that the email address is not in use
+ if (isset($data['email']) && $data['email'] != $currentUser->email && $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) {
+ $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
+ $error = TRUE;
+ }
+
+ if ($error) {
+ return $response->withStatus(400);
+ }
+
+ // Hash new password, if specified
+ if (isset($data['password']) && !empty($data['password'])) {
+ $data['password'] = Password::hash($data['password']);
+ } else {
+ // Do not pass to model if no password is specified
+ unset($data['password']);
+ }
+
+ // Looks good, let's update with new values!
+ // Note that only fields listed in `account-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB
+ $currentUser->fill($data);
+
+ $currentUser->save();
+
+ // Create activity record
+ $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their account settings.", [
+ 'type' => 'update_account_settings'
+ ]);
+
+ $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED');
+ return $response->withStatus(200);
+ }
+
+ /**
+ * Suggest an available username for a specified first/last name.
+ *
+ * This route is "public access".
+ * Request type: GET
+ * @odo Can this route be abused for account enumeration? If so we should throttle it as well.
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function suggestUsername(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ $suggestion = AccountUtil::randomUniqueUsername($classMapper, 50, 10);
+
+ // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
+ // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
+ return $response->withJson([
+ 'user_name' => $suggestion
+ ], 200, JSON_PRETTY_PRINT);
+ }
+
+ /**
+ * Processes an new email verification request.
+ *
+ * Processes the request from the email verification link that was emailed to the user, checking that:
+ * 1. The token provided matches a user in the database;
+ * 2. The user account is not already verified;
+ * This route is "public access".
+ * Request type: GET
+ *
+ * @param Request $request
+ * @param Response $response
+ * @param array $args
+ * @return void
+ */
+ public function verify(Request $request, Response $response, $args) {
+ /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
+ $ms = $this->ci->alerts;
+
+ /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = $this->ci->classMapper;
+
+ /** @var \UserFrosting\Support\Repository\Repository $config */
+ $config = $this->ci->config;
+
+ $loginPage = $this->ci->router->pathFor('login');
+
+ // GET parameters
+ $params = $request->getQueryParams();
+
+ // Load request schema
+ $schema = new RequestSchema('schema://requests/account-verify.yaml');
+
+ // Whitelist and set parameter defaults
+ $transformer = new RequestDataTransformer($schema);
+ $data = $transformer->transform($params);
+
+ // Validate, and halt on validation errors. This is a GET request, so we redirect on validation error.
+ $validator = new ServerSideValidator($schema, $this->ci->translator);
+ if (!$validator->validate($data)) {
+ $ms->addValidationErrors($validator);
+ // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel
+ return $response->withRedirect($loginPage, 400);
+ }
+
+ $verification = $this->ci->repoVerification->complete($data['token']);
+
+ if (!$verification) {
+ $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND');
+ return $response->withRedirect($loginPage, 400);
+ }
+
+ $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.COMPLETE');
+
+ // Forward to login page
+ return $response->withRedirect($loginPage);
+ }
+}
diff --git a/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php b/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php index d66a16c..1f0cf4a 100644 --- a/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php +++ b/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php @@ -1,21 +1,21 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Controller\Exception; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Spammy request exception. Used when a bot has attempted to spam a public form, and fallen into our honeypot. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class SpammyRequestException extends HttpException -{ - -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Controller\Exception;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Spammy request exception. Used when a bot has attempted to spam a public form, and fallen into our honeypot.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class SpammyRequestException extends HttpException
+{
+
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php index db02ec2..6fcb8aa 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php @@ -1,53 +1,53 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use UserFrosting\System\Bakery\Migration; -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; - -/** - * Sessions table migration - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class ActivitiesTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('activities')) { - $this->schema->create('activities', function (Blueprint $table) { - $table->increments('id'); - $table->string('ip_address', 45)->nullable(); - $table->integer('user_id')->unsigned(); - $table->string('type', 255)->comment('An identifier used to track the type of activity.'); - $table->timestamp('occurred_at')->nullable(); - $table->text('description')->nullable(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - //$table->foreign('user_id')->references('id')->on('users'); - $table->index('user_id'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('activities'); - } +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use UserFrosting\System\Bakery\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+
+/**
+ * Sessions table migration
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ActivitiesTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('activities')) {
+ $this->schema->create('activities', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('ip_address', 45)->nullable();
+ $table->integer('user_id')->unsigned();
+ $table->string('type', 255)->comment('An identifier used to track the type of activity.');
+ $table->timestamp('occurred_at')->nullable();
+ $table->text('description')->nullable();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ //$table->foreign('user_id')->references('id')->on('users');
+ $table->index('user_id');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('activities');
+ }
}
\ No newline at end of file diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index 07583af..d8498f4 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -1,81 +1,81 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\Sprinkle\Account\Database\Models\Group; -use UserFrosting\System\Bakery\Migration; - -/** - * Groups table migration - * "Group" now replaces the notion of "primary group" in earlier versions of UF. A user can belong to exactly one group. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class GroupsTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('groups')) { - $this->schema->create('groups', function (Blueprint $table) { - $table->increments('id'); - $table->string('slug'); - $table->string('name'); - $table->text('description')->nullable(); - $table->string('icon', 100)->nullable(FALSE)->default('fa fa-user')->comment('The icon representing users in this group.'); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - $table->unique('slug'); - $table->index('slug'); - }); - - // Add default groups - $groups = [ - 'terran' => new Group([ - 'slug' => 'terran', - 'name' => 'Terran', - 'description' => 'The terrans are a young species with psionic potential. The terrans of the Koprulu sector descend from the survivors of a disastrous 23rd century colonization mission from Earth.', - 'icon' => 'sc sc-terran' - ]), - 'zerg' => new Group([ - 'slug' => 'zerg', - 'name' => 'Zerg', - 'description' => 'Dedicated to the pursuit of genetic perfection, the zerg relentlessly hunt down and assimilate advanced species across the galaxy, incorporating useful genetic code into their own.', - 'icon' => 'sc sc-zerg' - ]), - 'protoss' => new Group([ - 'slug' => 'protoss', - 'name' => 'Protoss', - 'description' => 'The protoss, a.k.a. the Firstborn, are a sapient humanoid race native to Aiur. Their advanced technology complements and enhances their psionic mastery.', - 'icon' => 'sc sc-protoss' - ]) - ]; - - foreach ($groups as $slug => $group) { - $group->save(); - } - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('groups'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\Sprinkle\Account\Database\Models\Group;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Groups table migration
+ * "Group" now replaces the notion of "primary group" in earlier versions of UF. A user can belong to exactly one group.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class GroupsTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('groups')) {
+ $this->schema->create('groups', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('slug');
+ $table->string('name');
+ $table->text('description')->nullable();
+ $table->string('icon', 100)->nullable(FALSE)->default('fa fa-user')->comment('The icon representing users in this group.');
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ $table->unique('slug');
+ $table->index('slug');
+ });
+
+ // Add default groups
+ $groups = [
+ 'terran' => new Group([
+ 'slug' => 'terran',
+ 'name' => 'Terran',
+ 'description' => 'The terrans are a young species with psionic potential. The terrans of the Koprulu sector descend from the survivors of a disastrous 23rd century colonization mission from Earth.',
+ 'icon' => 'sc sc-terran'
+ ]),
+ 'zerg' => new Group([
+ 'slug' => 'zerg',
+ 'name' => 'Zerg',
+ 'description' => 'Dedicated to the pursuit of genetic perfection, the zerg relentlessly hunt down and assimilate advanced species across the galaxy, incorporating useful genetic code into their own.',
+ 'icon' => 'sc sc-zerg'
+ ]),
+ 'protoss' => new Group([
+ 'slug' => 'protoss',
+ 'name' => 'Protoss',
+ 'description' => 'The protoss, a.k.a. the Firstborn, are a sapient humanoid race native to Aiur. Their advanced technology complements and enhances their psionic mastery.',
+ 'icon' => 'sc sc-protoss'
+ ])
+ ];
+
+ foreach ($groups as $slug => $group) {
+ $group->save();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('groups');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php index 47eb00d..932ab47 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php @@ -1,56 +1,56 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; - -/** - * password_resets table migration - * Manages requests for password resets. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class passwordResetsTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('password_resets')) { - $this->schema->create('password_resets', function (Blueprint $table) { - $table->increments('id'); - $table->integer('user_id')->unsigned(); - $table->string('hash'); - $table->boolean('completed')->default(0); - $table->timestamp('expires_at')->nullable(); - $table->timestamp('completed_at')->nullable(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - //$table->foreign('user_id')->references('id')->on('users'); - $table->index('user_id'); - $table->index('hash'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('password_resets'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * password_resets table migration
+ * Manages requests for password resets.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class passwordResetsTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('password_resets')) {
+ $this->schema->create('password_resets', function (Blueprint $table) {
+ $table->increments('id');
+ $table->integer('user_id')->unsigned();
+ $table->string('hash');
+ $table->boolean('completed')->default(0);
+ $table->timestamp('expires_at')->nullable();
+ $table->timestamp('completed_at')->nullable();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ //$table->foreign('user_id')->references('id')->on('users');
+ $table->index('user_id');
+ $table->index('hash');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('password_resets');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php index 8e06cd6..dca6639 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php @@ -1,54 +1,54 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; - -/** - * Permission_roles table migration - * Many-to-many mapping between permissions and roles. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class PermissionRolesTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('permission_roles')) { - $this->schema->create('permission_roles', function (Blueprint $table) { - $table->integer('permission_id')->unsigned(); - $table->integer('role_id')->unsigned(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - $table->primary(['permission_id', 'role_id']); - //$table->foreign('permission_id')->references('id')->on('permissions'); - //$table->foreign('role_id')->references('id')->on('roles'); - $table->index('permission_id'); - $table->index('role_id'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('permission_roles'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Permission_roles table migration
+ * Many-to-many mapping between permissions and roles.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PermissionRolesTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('permission_roles')) {
+ $this->schema->create('permission_roles', function (Blueprint $table) {
+ $table->integer('permission_id')->unsigned();
+ $table->integer('role_id')->unsigned();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ $table->primary(['permission_id', 'role_id']);
+ //$table->foreign('permission_id')->references('id')->on('permissions');
+ //$table->foreign('role_id')->references('id')->on('roles');
+ $table->index('permission_id');
+ $table->index('role_id');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('permission_roles');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index bef8cdd..efc014b 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -1,260 +1,260 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\Sprinkle\Account\Database\Models\Permission; -use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\System\Bakery\Migration; - -/** - * Permissions table migration - * Permissions now replace the 'authorize_group' and 'authorize_user' tables. - * Also, they now map many-to-many to roles. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class PermissionsTable extends Migration -{ - /** - * {@inheritDoc} - */ - public $dependencies = [ - '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable', - '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\PermissionRolesTable' - ]; - - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('permissions')) { - $this->schema->create('permissions', function (Blueprint $table) { - $table->increments('id'); - $table->string('slug')->comment('A code that references a specific action or URI that an assignee of this permission has access to.'); - $table->string('name'); - $table->text('conditions')->comment('The conditions under which members of this group have access to this hook.'); - $table->text('description')->nullable(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('permissions'); - } - - /** - * {@inheritDoc} - */ - public function seed() { - // Skip this if table is not empty - if (Permission::count() == 0) { - - $defaultRoleIds = [ - 'user' => Role::where('slug', 'user')->first()->id, - 'group-admin' => Role::where('slug', 'group-admin')->first()->id, - 'site-admin' => Role::where('slug', 'site-admin')->first()->id - ]; - - // Add default permissions - $permissions = [ - 'create_group' => new Permission([ - 'slug' => 'create_group', - 'name' => 'Create group', - 'conditions' => 'always()', - 'description' => 'Create a new group.' - ]), - 'create_user' => new Permission([ - 'slug' => 'create_user', - 'name' => 'Create user', - 'conditions' => 'always()', - 'description' => 'Create a new user in your own group and assign default roles.' - ]), - 'create_user_field' => new Permission([ - 'slug' => 'create_user_field', - 'name' => 'Set new user group', - 'conditions' => "subset(fields,['group'])", - 'description' => 'Set the group when creating a new user.' - ]), - 'delete_group' => new Permission([ - 'slug' => 'delete_group', - 'name' => 'Delete group', - 'conditions' => "always()", - 'description' => 'Delete a group.' - ]), - 'delete_user' => new Permission([ - 'slug' => 'delete_user', - 'name' => 'Delete user', - 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)", - 'description' => 'Delete users who are not Site Administrators.' - ]), - 'update_account_settings' => new Permission([ - 'slug' => 'update_account_settings', - 'name' => 'Edit user', - 'conditions' => 'always()', - 'description' => 'Edit your own account settings.' - ]), - 'update_group_field' => new Permission([ - 'slug' => 'update_group_field', - 'name' => 'Edit group', - 'conditions' => 'always()', - 'description' => 'Edit basic properties of any group.' - ]), - 'update_user_field' => new Permission([ - 'slug' => 'update_user_field', - 'name' => 'Edit user', - 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])", - 'description' => 'Edit users who are not Site Administrators.' - ]), - 'update_user_field_group' => new Permission([ - 'slug' => 'update_user_field', - 'name' => 'Edit group user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])", - 'description' => 'Edit users in your own group who are not Site or Group Administrators, except yourself.' - ]), - 'uri_account_settings' => new Permission([ - 'slug' => 'uri_account_settings', - 'name' => 'Account settings page', - 'conditions' => 'always()', - 'description' => 'View the account settings page.' - ]), - 'uri_activities' => new Permission([ - 'slug' => 'uri_activities', - 'name' => 'Activity monitor', - 'conditions' => 'always()', - 'description' => 'View a list of all activities for all users.' - ]), - 'uri_dashboard' => new Permission([ - 'slug' => 'uri_dashboard', - 'name' => 'Admin dashboard', - 'conditions' => 'always()', - 'description' => 'View the administrative dashboard.' - ]), - 'uri_group' => new Permission([ - 'slug' => 'uri_group', - 'name' => 'View group', - 'conditions' => 'always()', - 'description' => 'View the group page of any group.' - ]), - 'uri_group_own' => new Permission([ - 'slug' => 'uri_group', - 'name' => 'View own group', - 'conditions' => 'equals_num(self.group_id,group.id)', - 'description' => 'View the group page of your own group.' - ]), - 'uri_groups' => new Permission([ - 'slug' => 'uri_groups', - 'name' => 'Group management page', - 'conditions' => 'always()', - 'description' => 'View a page containing a list of groups.' - ]), - 'uri_user' => new Permission([ - 'slug' => 'uri_user', - 'name' => 'View user', - 'conditions' => 'always()', - 'description' => 'View the user page of any user.' - ]), - 'uri_user_in_group' => new Permission([ - 'slug' => 'uri_user', - 'name' => 'View user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))", - 'description' => 'View the user page of any user in your group, except the master user and Site and Group Administrators (except yourself).' - ]), - 'uri_users' => new Permission([ - 'slug' => 'uri_users', - 'name' => 'User management page', - 'conditions' => 'always()', - 'description' => 'View a page containing a table of users.' - ]), - 'view_group_field' => new Permission([ - 'slug' => 'view_group_field', - 'name' => 'View group', - 'conditions' => "in(property,['name','icon','slug','description','users'])", - 'description' => 'View certain properties of any group.' - ]), - 'view_group_field_own' => new Permission([ - 'slug' => 'view_group_field', - 'name' => 'View group', - 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])", - 'description' => 'View certain properties of your own group.' - ]), - 'view_user_field' => new Permission([ - 'slug' => 'view_user_field', - 'name' => 'View user', - 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])", - 'description' => 'View certain properties of any user.' - ]), - 'view_user_field_group' => new Permission([ - 'slug' => 'view_user_field', - 'name' => 'View user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])", - 'description' => 'View certain properties of any user in your own group, except the master user and Site and Group Administrators (except yourself).' - ]) - ]; - - foreach ($permissions as $slug => $permission) { - $permission->save(); - } - - // Add default mappings to permissions - $roleUser = Role::where('slug', 'user')->first(); - if ($roleUser) { - $roleUser->permissions()->sync([ - $permissions['update_account_settings']->id, - $permissions['uri_account_settings']->id, - $permissions['uri_dashboard']->id - ]); - } - - $roleSiteAdmin = Role::where('slug', 'site-admin')->first(); - if ($roleSiteAdmin) { - $roleSiteAdmin->permissions()->sync([ - $permissions['create_group']->id, - $permissions['create_user']->id, - $permissions['create_user_field']->id, - $permissions['delete_group']->id, - $permissions['delete_user']->id, - $permissions['update_user_field']->id, - $permissions['update_group_field']->id, - $permissions['uri_activities']->id, - $permissions['uri_group']->id, - $permissions['uri_groups']->id, - $permissions['uri_user']->id, - $permissions['uri_users']->id, - $permissions['view_group_field']->id, - $permissions['view_user_field']->id - ]); - } - - $roleGroupAdmin = Role::where('slug', 'group-admin')->first(); - if ($roleGroupAdmin) { - $roleGroupAdmin->permissions()->sync([ - $permissions['create_user']->id, - $permissions['update_user_field_group']->id, - $permissions['uri_group_own']->id, - $permissions['uri_user_in_group']->id, - $permissions['view_group_field_own']->id, - $permissions['view_user_field_group']->id - ]); - } - } - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\Sprinkle\Account\Database\Models\Permission;
+use UserFrosting\Sprinkle\Account\Database\Models\Role;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Permissions table migration
+ * Permissions now replace the 'authorize_group' and 'authorize_user' tables.
+ * Also, they now map many-to-many to roles.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PermissionsTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public $dependencies = [
+ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable',
+ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\PermissionRolesTable'
+ ];
+
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('permissions')) {
+ $this->schema->create('permissions', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('slug')->comment('A code that references a specific action or URI that an assignee of this permission has access to.');
+ $table->string('name');
+ $table->text('conditions')->comment('The conditions under which members of this group have access to this hook.');
+ $table->text('description')->nullable();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('permissions');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function seed() {
+ // Skip this if table is not empty
+ if (Permission::count() == 0) {
+
+ $defaultRoleIds = [
+ 'user' => Role::where('slug', 'user')->first()->id,
+ 'group-admin' => Role::where('slug', 'group-admin')->first()->id,
+ 'site-admin' => Role::where('slug', 'site-admin')->first()->id
+ ];
+
+ // Add default permissions
+ $permissions = [
+ 'create_group' => new Permission([
+ 'slug' => 'create_group',
+ 'name' => 'Create group',
+ 'conditions' => 'always()',
+ 'description' => 'Create a new group.'
+ ]),
+ 'create_user' => new Permission([
+ 'slug' => 'create_user',
+ 'name' => 'Create user',
+ 'conditions' => 'always()',
+ 'description' => 'Create a new user in your own group and assign default roles.'
+ ]),
+ 'create_user_field' => new Permission([
+ 'slug' => 'create_user_field',
+ 'name' => 'Set new user group',
+ 'conditions' => "subset(fields,['group'])",
+ 'description' => 'Set the group when creating a new user.'
+ ]),
+ 'delete_group' => new Permission([
+ 'slug' => 'delete_group',
+ 'name' => 'Delete group',
+ 'conditions' => "always()",
+ 'description' => 'Delete a group.'
+ ]),
+ 'delete_user' => new Permission([
+ 'slug' => 'delete_user',
+ 'name' => 'Delete user',
+ 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)",
+ 'description' => 'Delete users who are not Site Administrators.'
+ ]),
+ 'update_account_settings' => new Permission([
+ 'slug' => 'update_account_settings',
+ 'name' => 'Edit user',
+ 'conditions' => 'always()',
+ 'description' => 'Edit your own account settings.'
+ ]),
+ 'update_group_field' => new Permission([
+ 'slug' => 'update_group_field',
+ 'name' => 'Edit group',
+ 'conditions' => 'always()',
+ 'description' => 'Edit basic properties of any group.'
+ ]),
+ 'update_user_field' => new Permission([
+ 'slug' => 'update_user_field',
+ 'name' => 'Edit user',
+ 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])",
+ 'description' => 'Edit users who are not Site Administrators.'
+ ]),
+ 'update_user_field_group' => new Permission([
+ 'slug' => 'update_user_field',
+ 'name' => 'Edit group user',
+ 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])",
+ 'description' => 'Edit users in your own group who are not Site or Group Administrators, except yourself.'
+ ]),
+ 'uri_account_settings' => new Permission([
+ 'slug' => 'uri_account_settings',
+ 'name' => 'Account settings page',
+ 'conditions' => 'always()',
+ 'description' => 'View the account settings page.'
+ ]),
+ 'uri_activities' => new Permission([
+ 'slug' => 'uri_activities',
+ 'name' => 'Activity monitor',
+ 'conditions' => 'always()',
+ 'description' => 'View a list of all activities for all users.'
+ ]),
+ 'uri_dashboard' => new Permission([
+ 'slug' => 'uri_dashboard',
+ 'name' => 'Admin dashboard',
+ 'conditions' => 'always()',
+ 'description' => 'View the administrative dashboard.'
+ ]),
+ 'uri_group' => new Permission([
+ 'slug' => 'uri_group',
+ 'name' => 'View group',
+ 'conditions' => 'always()',
+ 'description' => 'View the group page of any group.'
+ ]),
+ 'uri_group_own' => new Permission([
+ 'slug' => 'uri_group',
+ 'name' => 'View own group',
+ 'conditions' => 'equals_num(self.group_id,group.id)',
+ 'description' => 'View the group page of your own group.'
+ ]),
+ 'uri_groups' => new Permission([
+ 'slug' => 'uri_groups',
+ 'name' => 'Group management page',
+ 'conditions' => 'always()',
+ 'description' => 'View a page containing a list of groups.'
+ ]),
+ 'uri_user' => new Permission([
+ 'slug' => 'uri_user',
+ 'name' => 'View user',
+ 'conditions' => 'always()',
+ 'description' => 'View the user page of any user.'
+ ]),
+ 'uri_user_in_group' => new Permission([
+ 'slug' => 'uri_user',
+ 'name' => 'View user',
+ 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))",
+ 'description' => 'View the user page of any user in your group, except the master user and Site and Group Administrators (except yourself).'
+ ]),
+ 'uri_users' => new Permission([
+ 'slug' => 'uri_users',
+ 'name' => 'User management page',
+ 'conditions' => 'always()',
+ 'description' => 'View a page containing a table of users.'
+ ]),
+ 'view_group_field' => new Permission([
+ 'slug' => 'view_group_field',
+ 'name' => 'View group',
+ 'conditions' => "in(property,['name','icon','slug','description','users'])",
+ 'description' => 'View certain properties of any group.'
+ ]),
+ 'view_group_field_own' => new Permission([
+ 'slug' => 'view_group_field',
+ 'name' => 'View group',
+ 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])",
+ 'description' => 'View certain properties of your own group.'
+ ]),
+ 'view_user_field' => new Permission([
+ 'slug' => 'view_user_field',
+ 'name' => 'View user',
+ 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])",
+ 'description' => 'View certain properties of any user.'
+ ]),
+ 'view_user_field_group' => new Permission([
+ 'slug' => 'view_user_field',
+ 'name' => 'View user',
+ 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])",
+ 'description' => 'View certain properties of any user in your own group, except the master user and Site and Group Administrators (except yourself).'
+ ])
+ ];
+
+ foreach ($permissions as $slug => $permission) {
+ $permission->save();
+ }
+
+ // Add default mappings to permissions
+ $roleUser = Role::where('slug', 'user')->first();
+ if ($roleUser) {
+ $roleUser->permissions()->sync([
+ $permissions['update_account_settings']->id,
+ $permissions['uri_account_settings']->id,
+ $permissions['uri_dashboard']->id
+ ]);
+ }
+
+ $roleSiteAdmin = Role::where('slug', 'site-admin')->first();
+ if ($roleSiteAdmin) {
+ $roleSiteAdmin->permissions()->sync([
+ $permissions['create_group']->id,
+ $permissions['create_user']->id,
+ $permissions['create_user_field']->id,
+ $permissions['delete_group']->id,
+ $permissions['delete_user']->id,
+ $permissions['update_user_field']->id,
+ $permissions['update_group_field']->id,
+ $permissions['uri_activities']->id,
+ $permissions['uri_group']->id,
+ $permissions['uri_groups']->id,
+ $permissions['uri_user']->id,
+ $permissions['uri_users']->id,
+ $permissions['view_group_field']->id,
+ $permissions['view_user_field']->id
+ ]);
+ }
+
+ $roleGroupAdmin = Role::where('slug', 'group-admin')->first();
+ if ($roleGroupAdmin) {
+ $roleGroupAdmin->permissions()->sync([
+ $permissions['create_user']->id,
+ $permissions['update_user_field_group']->id,
+ $permissions['uri_group_own']->id,
+ $permissions['uri_user_in_group']->id,
+ $permissions['view_group_field_own']->id,
+ $permissions['view_user_field_group']->id
+ ]);
+ }
+ }
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php index 41378d3..c51461a 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php @@ -1,56 +1,56 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; - -/** - * Persistences table migration - * Many-to-many mapping between roles and users. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class PersistencesTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('persistences')) { - $this->schema->create('persistences', function (Blueprint $table) { - $table->increments('id'); - $table->integer('user_id')->unsigned(); - $table->string('token', 40); - $table->string('persistent_token', 40); - $table->timestamp('expires_at')->nullable(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - //$table->foreign('user_id')->references('id')->on('users'); - $table->index('user_id'); - $table->index('token'); - $table->index('persistent_token'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('persistences'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Persistences table migration
+ * Many-to-many mapping between roles and users.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class PersistencesTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('persistences')) {
+ $this->schema->create('persistences', function (Blueprint $table) {
+ $table->increments('id');
+ $table->integer('user_id')->unsigned();
+ $table->string('token', 40);
+ $table->string('persistent_token', 40);
+ $table->timestamp('expires_at')->nullable();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ //$table->foreign('user_id')->references('id')->on('users');
+ $table->index('user_id');
+ $table->index('token');
+ $table->index('persistent_token');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('persistences');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php index 4c7ca06..0820a02 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php @@ -1,54 +1,54 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; - -/** - * Role_users table migration - * Many-to-many mapping between roles and users. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class RoleUsersTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('role_users')) { - $this->schema->create('role_users', function (Blueprint $table) { - $table->integer('user_id')->unsigned(); - $table->integer('role_id')->unsigned(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - $table->primary(['user_id', 'role_id']); - //$table->foreign('user_id')->references('id')->on('users'); - //$table->foreign('role_id')->references('id')->on('roles'); - $table->index('user_id'); - $table->index('role_id'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('role_users'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Role_users table migration
+ * Many-to-many mapping between roles and users.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class RoleUsersTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('role_users')) {
+ $this->schema->create('role_users', function (Blueprint $table) {
+ $table->integer('user_id')->unsigned();
+ $table->integer('role_id')->unsigned();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ $table->primary(['user_id', 'role_id']);
+ //$table->foreign('user_id')->references('id')->on('users');
+ //$table->foreign('role_id')->references('id')->on('roles');
+ $table->index('user_id');
+ $table->index('role_id');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('role_users');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php index 20fe699..3a524e2 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php @@ -1,77 +1,77 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\System\Bakery\Migration; - -/** - * Roles table migration - * Roles replace "groups" in UF 0.3.x. Users acquire permissions through roles. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class RolesTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('roles')) { - $this->schema->create('roles', function (Blueprint $table) { - $table->increments('id'); - $table->string('slug'); - $table->string('name'); - $table->text('description')->nullable(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - $table->unique('slug'); - $table->index('slug'); - }); - - // Add default roles - $roles = [ - 'user' => new Role([ - 'slug' => 'user', - 'name' => 'User', - 'description' => 'This role provides basic user functionality.' - ]), - 'site-admin' => new Role([ - 'slug' => 'site-admin', - 'name' => 'Site Administrator', - 'description' => 'This role is meant for "site administrators", who can basically do anything except create, edit, or delete other administrators.' - ]), - 'group-admin' => new Role([ - 'slug' => 'group-admin', - 'name' => 'Group Administrator', - 'description' => 'This role is meant for "group administrators", who can basically do anything with users in their own group, except other administrators of that group.' - ]) - ]; - - foreach ($roles as $slug => $role) { - $role->save(); - } - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('roles'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\Sprinkle\Account\Database\Models\Role;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Roles table migration
+ * Roles replace "groups" in UF 0.3.x. Users acquire permissions through roles.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class RolesTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('roles')) {
+ $this->schema->create('roles', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('slug');
+ $table->string('name');
+ $table->text('description')->nullable();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ $table->unique('slug');
+ $table->index('slug');
+ });
+
+ // Add default roles
+ $roles = [
+ 'user' => new Role([
+ 'slug' => 'user',
+ 'name' => 'User',
+ 'description' => 'This role provides basic user functionality.'
+ ]),
+ 'site-admin' => new Role([
+ 'slug' => 'site-admin',
+ 'name' => 'Site Administrator',
+ 'description' => 'This role is meant for "site administrators", who can basically do anything except create, edit, or delete other administrators.'
+ ]),
+ 'group-admin' => new Role([
+ 'slug' => 'group-admin',
+ 'name' => 'Group Administrator',
+ 'description' => 'This role is meant for "group administrators", who can basically do anything with users in their own group, except other administrators of that group.'
+ ])
+ ];
+
+ foreach ($roles as $slug => $role) {
+ $role->save();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('roles');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php index 9c634e8..694da5b 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php @@ -1,68 +1,68 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; - -/** - * Users table migration - * Removed the 'display_name', 'title', 'secret_token', and 'flag_password_reset' fields, and added first and last name and 'last_activity_id'. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class UsersTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('users')) { - $this->schema->create('users', function (Blueprint $table) { - $table->increments('id'); - $table->string('user_name', 50); - $table->string('email', 254); - $table->string('first_name', 20); - $table->string('last_name', 30); - $table->string('locale', 10)->default('en_US')->comment('The language and locale to use for this user.'); - $table->string('theme', 100)->nullable()->comment("The user theme."); - $table->integer('group_id')->unsigned()->default(1)->comment("The id of the user group."); - $table->boolean('flag_verified')->default(1)->comment("Set to 1 if the user has verified their account via email, 0 otherwise."); - $table->boolean('flag_enabled')->default(1)->comment("Set to 1 if the user account is currently enabled, 0 otherwise. Disabled accounts cannot be logged in to, but they retain all of their data and settings."); - $table->integer('last_activity_id')->unsigned()->nullable()->comment("The id of the last activity performed by this user."); - $table->string('password', 255); - $table->softDeletes(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - //$table->foreign('group_id')->references('id')->on('groups'); - //$table->foreign('last_activity_id')->references('id')->on('activities'); - $table->unique('user_name'); - $table->index('user_name'); - $table->unique('email'); - $table->index('email'); - $table->index('group_id'); - $table->index('last_activity_id'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('users'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Users table migration
+ * Removed the 'display_name', 'title', 'secret_token', and 'flag_password_reset' fields, and added first and last name and 'last_activity_id'.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class UsersTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('users')) {
+ $this->schema->create('users', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('user_name', 50);
+ $table->string('email', 254);
+ $table->string('first_name', 20);
+ $table->string('last_name', 30);
+ $table->string('locale', 10)->default('en_US')->comment('The language and locale to use for this user.');
+ $table->string('theme', 100)->nullable()->comment("The user theme.");
+ $table->integer('group_id')->unsigned()->default(1)->comment("The id of the user group.");
+ $table->boolean('flag_verified')->default(1)->comment("Set to 1 if the user has verified their account via email, 0 otherwise.");
+ $table->boolean('flag_enabled')->default(1)->comment("Set to 1 if the user account is currently enabled, 0 otherwise. Disabled accounts cannot be logged in to, but they retain all of their data and settings.");
+ $table->integer('last_activity_id')->unsigned()->nullable()->comment("The id of the last activity performed by this user.");
+ $table->string('password', 255);
+ $table->softDeletes();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ //$table->foreign('group_id')->references('id')->on('groups');
+ //$table->foreign('last_activity_id')->references('id')->on('activities');
+ $table->unique('user_name');
+ $table->index('user_name');
+ $table->unique('email');
+ $table->index('email');
+ $table->index('group_id');
+ $table->index('last_activity_id');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('users');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php index e42114c..2c4d28f 100644 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php +++ b/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php @@ -1,56 +1,56 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; - -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; - -/** - * Verifications table migration - * Manages requests for email account verification. - * Version 4.0.0 - * - * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration - * @author Alex Weissman (https://alexanderweissman.com) - */ -class VerificationsTable extends Migration -{ - /** - * {@inheritDoc} - */ - public function up() { - if (!$this->schema->hasTable('verifications')) { - $this->schema->create('verifications', function (Blueprint $table) { - $table->increments('id'); - $table->integer('user_id')->unsigned(); - $table->string('hash'); - $table->boolean('completed')->default(0); - $table->timestamp('expires_at')->nullable(); - $table->timestamp('completed_at')->nullable(); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - //$table->foreign('user_id')->references('id')->on('users'); - $table->index('user_id'); - $table->index('hash'); - }); - } - } - - /** - * {@inheritDoc} - */ - public function down() { - $this->schema->drop('verifications'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+use UserFrosting\System\Bakery\Migration;
+
+/**
+ * Verifications table migration
+ * Manages requests for email account verification.
+ * Version 4.0.0
+ *
+ * See https://laravel.com/docs/5.4/migrations#tables
+ * @extends Migration
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class VerificationsTable extends Migration
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function up() {
+ if (!$this->schema->hasTable('verifications')) {
+ $this->schema->create('verifications', function (Blueprint $table) {
+ $table->increments('id');
+ $table->integer('user_id')->unsigned();
+ $table->string('hash');
+ $table->boolean('completed')->default(0);
+ $table->timestamp('expires_at')->nullable();
+ $table->timestamp('completed_at')->nullable();
+ $table->timestamps();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ //$table->foreign('user_id')->references('id')->on('users');
+ $table->index('user_id');
+ $table->index('hash');
+ });
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function down() {
+ $this->schema->drop('verifications');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/Activity.php b/main/app/sprinkles/account/src/Database/Models/Activity.php index 4e5b609..8f6cd18 100644 --- a/main/app/sprinkles/account/src/Database/Models/Activity.php +++ b/main/app/sprinkles/account/src/Database/Models/Activity.php @@ -1,83 +1,83 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -/** - * Activity Class - * - * Represents a single user activity at a specified point in time. - * @author Alex Weissman (https://alexanderweissman.com) - * @property string ip_address - * @property int user_id - * @property string type - * @property datetime occurred_at - * @property string description - */ -class Activity extends Model -{ - /** - * @var string The name of the table for the current model. - */ - protected $table = "activities"; - - protected $fillable = [ - "ip_address", - "user_id", - "type", - "occurred_at", - "description" - ]; - - /** - * Joins the activity's user, so we can do things like sort, search, paginate, etc. - */ - public function scopeJoinUser($query) { - $query = $query->select('activities.*'); - - $query = $query->leftJoin('users', 'activities.user_id', '=', 'users.id'); - - return $query; - } - - /** - * Add clauses to select the most recent event of each type for each user, to the query. - * - * @return \Illuminate\Database\Query\Builder - */ - public function scopeMostRecentEvents($query) { - return $query->select('user_id', 'event_type', Capsule::raw('MAX(occurred_at) as occurred_at')) - ->groupBy('user_id') - ->groupBy('type'); - } - - /** - * Add clauses to select the most recent event of a given type for each user, to the query. - * - * @param string $type The type of event, matching the `event_type` field in the user_event table. - * @return \Illuminate\Database\Query\Builder - */ - public function scopeMostRecentEventsByType($query, $type) { - return $query->select('user_id', Capsule::raw('MAX(occurred_at) as occurred_at')) - ->where('type', $type) - ->groupBy('user_id'); - } - - /** - * Get the user associated with this activity. - */ - public function user() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+/**
+ * Activity Class
+ *
+ * Represents a single user activity at a specified point in time.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @property string ip_address
+ * @property int user_id
+ * @property string type
+ * @property datetime occurred_at
+ * @property string description
+ */
+class Activity extends Model
+{
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = "activities";
+
+ protected $fillable = [
+ "ip_address",
+ "user_id",
+ "type",
+ "occurred_at",
+ "description"
+ ];
+
+ /**
+ * Joins the activity's user, so we can do things like sort, search, paginate, etc.
+ */
+ public function scopeJoinUser($query) {
+ $query = $query->select('activities.*');
+
+ $query = $query->leftJoin('users', 'activities.user_id', '=', 'users.id');
+
+ return $query;
+ }
+
+ /**
+ * Add clauses to select the most recent event of each type for each user, to the query.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeMostRecentEvents($query) {
+ return $query->select('user_id', 'event_type', Capsule::raw('MAX(occurred_at) as occurred_at'))
+ ->groupBy('user_id')
+ ->groupBy('type');
+ }
+
+ /**
+ * Add clauses to select the most recent event of a given type for each user, to the query.
+ *
+ * @param string $type The type of event, matching the `event_type` field in the user_event table.
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeMostRecentEventsByType($query, $type) {
+ return $query->select('user_id', Capsule::raw('MAX(occurred_at) as occurred_at'))
+ ->where('type', $type)
+ ->groupBy('user_id');
+ }
+
+ /**
+ * Get the user associated with this activity.
+ */
+ public function user() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/Group.php b/main/app/sprinkles/account/src/Database/Models/Group.php index f0a1e1f..abb0e36 100644 --- a/main/app/sprinkles/account/src/Database/Models/Group.php +++ b/main/app/sprinkles/account/src/Database/Models/Group.php @@ -1,68 +1,68 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -/** - * Group Class - * - * Represents a group object as stored in the database. - * - * @package UserFrosting - * @author Alex Weissman - * @see http://www.userfrosting.com/tutorials/lesson-3-data-model/ - * - * @property string slug - * @property string name - * @property string description - * @property string icon - */ -class Group extends Model -{ - /** - * @var string The name of the table for the current model. - */ - protected $table = "groups"; - - protected $fillable = [ - "slug", - "name", - "description", - "icon" - ]; - - /** - * @var bool Enable timestamps for this class. - */ - public $timestamps = TRUE; - - /** - * Delete this group from the database, along with any user associations - * - * @odo What do we do with users when their group is deleted? Reassign them? Or, can a user be "groupless"? - */ - public function delete() { - // Delete the group - $result = parent::delete(); - - return $result; - } - - /** - * Lazily load a collection of Users which belong to this group. - */ - public function users() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->hasMany($classMapper->getClassMapping('user'), 'group_id'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+/**
+ * Group Class
+ *
+ * Represents a group object as stored in the database.
+ *
+ * @package UserFrosting
+ * @author Alex Weissman
+ * @see http://www.userfrosting.com/tutorials/lesson-3-data-model/
+ *
+ * @property string slug
+ * @property string name
+ * @property string description
+ * @property string icon
+ */
+class Group extends Model
+{
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = "groups";
+
+ protected $fillable = [
+ "slug",
+ "name",
+ "description",
+ "icon"
+ ];
+
+ /**
+ * @var bool Enable timestamps for this class.
+ */
+ public $timestamps = TRUE;
+
+ /**
+ * Delete this group from the database, along with any user associations
+ *
+ * @odo What do we do with users when their group is deleted? Reassign them? Or, can a user be "groupless"?
+ */
+ public function delete() {
+ // Delete the group
+ $result = parent::delete();
+
+ return $result;
+ }
+
+ /**
+ * Lazily load a collection of Users which belong to this group.
+ */
+ public function users() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->hasMany($classMapper->getClassMapping('user'), 'group_id');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/PasswordReset.php b/main/app/sprinkles/account/src/Database/Models/PasswordReset.php index 3fc4e3c..99b1920 100644 --- a/main/app/sprinkles/account/src/Database/Models/PasswordReset.php +++ b/main/app/sprinkles/account/src/Database/Models/PasswordReset.php @@ -1,74 +1,74 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -/** - * Password Reset Class - * - * Represents a password reset request for a specific user. - * @author Alex Weissman (https://alexanderweissman.com) - * @property int user_id - * @property hash token - * @property bool completed - * @property datetime expires_at - * @property datetime completed_at - */ -class PasswordReset extends Model -{ - /** - * @var string The name of the table for the current model. - */ - protected $table = "password_resets"; - - protected $fillable = [ - "user_id", - "hash", - "completed", - "expires_at", - "completed_at" - ]; - - /** - * @var bool Enable timestamps for PasswordResets. - */ - public $timestamps = TRUE; - - /** - * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted. - */ - protected $token; - - /** - * @return string - */ - public function getToken() { - return $this->token; - } - - /** - * @param string $value - */ - public function setToken($value) { - $this->token = $value; - return $this; - } - - /** - * Get the user associated with this reset request. - */ - public function user() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+/**
+ * Password Reset Class
+ *
+ * Represents a password reset request for a specific user.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @property int user_id
+ * @property hash token
+ * @property bool completed
+ * @property datetime expires_at
+ * @property datetime completed_at
+ */
+class PasswordReset extends Model
+{
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = "password_resets";
+
+ protected $fillable = [
+ "user_id",
+ "hash",
+ "completed",
+ "expires_at",
+ "completed_at"
+ ];
+
+ /**
+ * @var bool Enable timestamps for PasswordResets.
+ */
+ public $timestamps = TRUE;
+
+ /**
+ * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted.
+ */
+ protected $token;
+
+ /**
+ * @return string
+ */
+ public function getToken() {
+ return $this->token;
+ }
+
+ /**
+ * @param string $value
+ */
+ public function setToken($value) {
+ $this->token = $value;
+ return $this;
+ }
+
+ /**
+ * Get the user associated with this reset request.
+ */
+ public function user() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/Permission.php b/main/app/sprinkles/account/src/Database/Models/Permission.php index 3035e56..da4391f 100644 --- a/main/app/sprinkles/account/src/Database/Models/Permission.php +++ b/main/app/sprinkles/account/src/Database/Models/Permission.php @@ -1,117 +1,117 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -/** - * Permission Class. - * - * Represents a permission for a role or user. - * @author Alex Weissman (https://alexanderweissman.com) - * @property string slug - * @property string name - * @property string conditions - * @property string description - */ -class Permission extends Model -{ - /** - * @var string The name of the table for the current model. - */ - protected $table = "permissions"; - - protected $fillable = [ - "slug", - "name", - "conditions", - "description" - ]; - - /** - * @var bool Enable timestamps for this class. - */ - public $timestamps = TRUE; - - /** - * Delete this permission from the database, removing associations with roles. - * - */ - public function delete() { - // Remove all role associations - $this->roles()->detach(); - - // Delete the permission - $result = parent::delete(); - - return $result; - } - - /** - * Get a list of roles to which this permission is assigned. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany - */ - public function roles() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsToMany($classMapper->getClassMapping('role'), 'permission_roles', 'permission_id', 'role_id')->withTimestamps(); - } - - /** - * Query scope to get all permissions assigned to a specific role. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param int $roleId - * @return \Illuminate\Database\Eloquent\Builder - */ - public function scopeForRole($query, $roleId) { - return $query->join('permission_roles', function ($join) use ($roleId) { - $join->on('permission_roles.permission_id', 'permissions.id') - ->where('role_id', $roleId); - }); - } - - /** - * Query scope to get all permissions NOT associated with a specific role. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param int $roleId - * @return \Illuminate\Database\Eloquent\Builder - */ - public function scopeNotForRole($query, $roleId) { - return $query->join('permission_roles', function ($join) use ($roleId) { - $join->on('permission_roles.permission_id', 'permissions.id') - ->where('role_id', '!=', $roleId); - }); - } - - /** - * Get a list of users who have this permission, along with a list of roles through which each user has the permission. - * - * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough - */ - public function users() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsToManyThrough( - $classMapper->getClassMapping('user'), - $classMapper->getClassMapping('role'), - 'permission_roles', - 'permission_id', - 'role_id', - 'role_users', - 'role_id', - 'user_id' - ); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+/**
+ * Permission Class.
+ *
+ * Represents a permission for a role or user.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @property string slug
+ * @property string name
+ * @property string conditions
+ * @property string description
+ */
+class Permission extends Model
+{
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = "permissions";
+
+ protected $fillable = [
+ "slug",
+ "name",
+ "conditions",
+ "description"
+ ];
+
+ /**
+ * @var bool Enable timestamps for this class.
+ */
+ public $timestamps = TRUE;
+
+ /**
+ * Delete this permission from the database, removing associations with roles.
+ *
+ */
+ public function delete() {
+ // Remove all role associations
+ $this->roles()->detach();
+
+ // Delete the permission
+ $result = parent::delete();
+
+ return $result;
+ }
+
+ /**
+ * Get a list of roles to which this permission is assigned.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
+ */
+ public function roles() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsToMany($classMapper->getClassMapping('role'), 'permission_roles', 'permission_id', 'role_id')->withTimestamps();
+ }
+
+ /**
+ * Query scope to get all permissions assigned to a specific role.
+ *
+ * @param \Illuminate\Database\Eloquent\Builder $query
+ * @param int $roleId
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function scopeForRole($query, $roleId) {
+ return $query->join('permission_roles', function ($join) use ($roleId) {
+ $join->on('permission_roles.permission_id', 'permissions.id')
+ ->where('role_id', $roleId);
+ });
+ }
+
+ /**
+ * Query scope to get all permissions NOT associated with a specific role.
+ *
+ * @param \Illuminate\Database\Eloquent\Builder $query
+ * @param int $roleId
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function scopeNotForRole($query, $roleId) {
+ return $query->join('permission_roles', function ($join) use ($roleId) {
+ $join->on('permission_roles.permission_id', 'permissions.id')
+ ->where('role_id', '!=', $roleId);
+ });
+ }
+
+ /**
+ * Get a list of users who have this permission, along with a list of roles through which each user has the permission.
+ *
+ * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough
+ */
+ public function users() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsToManyThrough(
+ $classMapper->getClassMapping('user'),
+ $classMapper->getClassMapping('role'),
+ 'permission_roles',
+ 'permission_id',
+ 'role_id',
+ 'role_users',
+ 'role_id',
+ 'user_id'
+ );
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/Role.php b/main/app/sprinkles/account/src/Database/Models/Role.php index 4a58df0..f8e40b3 100644 --- a/main/app/sprinkles/account/src/Database/Models/Role.php +++ b/main/app/sprinkles/account/src/Database/Models/Role.php @@ -1,101 +1,101 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -/** - * Role Class - * - * Represents a role, which aggregates permissions and to which a user can be assigned. - * @author Alex Weissman (https://alexanderweissman.com) - * @property string slug - * @property string name - * @property string description - */ -class Role extends Model -{ - /** - * @var string The name of the table for the current model. - */ - protected $table = "roles"; - - protected $fillable = [ - "slug", - "name", - "description" - ]; - - /** - * @var bool Enable timestamps for this class. - */ - public $timestamps = TRUE; - - /** - * Delete this role from the database, removing associations with permissions and users. - * - */ - public function delete() { - // Remove all permission associations - $this->permissions()->detach(); - - // Remove all user associations - $this->users()->detach(); - - // Delete the role - $result = parent::delete(); - - return $result; - } - - /** - * Get a list of default roles. - */ - public static function getDefaultSlugs() { - /** @var UserFrosting\Config $config */ - $config = static::$ci->config; - - return array_map('trim', array_keys($config['site.registration.user_defaults.roles'], TRUE)); - } - - /** - * Get a list of permissions assigned to this role. - */ - public function permissions() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsToMany($classMapper->getClassMapping('permission'), 'permission_roles', 'role_id', 'permission_id')->withTimestamps(); - } - - /** - * Query scope to get all roles assigned to a specific user. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param int $userId - * @return \Illuminate\Database\Eloquent\Builder - */ - public function scopeForUser($query, $userId) { - return $query->join('role_users', function ($join) use ($userId) { - $join->on('role_users.role_id', 'roles.id') - ->where('user_id', $userId); - }); - } - - /** - * Get a list of users who have this role. - */ - public function users() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsToMany($classMapper->getClassMapping('user'), 'role_users', 'role_id', 'user_id'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+/**
+ * Role Class
+ *
+ * Represents a role, which aggregates permissions and to which a user can be assigned.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @property string slug
+ * @property string name
+ * @property string description
+ */
+class Role extends Model
+{
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = "roles";
+
+ protected $fillable = [
+ "slug",
+ "name",
+ "description"
+ ];
+
+ /**
+ * @var bool Enable timestamps for this class.
+ */
+ public $timestamps = TRUE;
+
+ /**
+ * Delete this role from the database, removing associations with permissions and users.
+ *
+ */
+ public function delete() {
+ // Remove all permission associations
+ $this->permissions()->detach();
+
+ // Remove all user associations
+ $this->users()->detach();
+
+ // Delete the role
+ $result = parent::delete();
+
+ return $result;
+ }
+
+ /**
+ * Get a list of default roles.
+ */
+ public static function getDefaultSlugs() {
+ /** @var UserFrosting\Config $config */
+ $config = static::$ci->config;
+
+ return array_map('trim', array_keys($config['site.registration.user_defaults.roles'], TRUE));
+ }
+
+ /**
+ * Get a list of permissions assigned to this role.
+ */
+ public function permissions() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsToMany($classMapper->getClassMapping('permission'), 'permission_roles', 'role_id', 'permission_id')->withTimestamps();
+ }
+
+ /**
+ * Query scope to get all roles assigned to a specific user.
+ *
+ * @param \Illuminate\Database\Eloquent\Builder $query
+ * @param int $userId
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function scopeForUser($query, $userId) {
+ return $query->join('role_users', function ($join) use ($userId) {
+ $join->on('role_users.role_id', 'roles.id')
+ ->where('user_id', $userId);
+ });
+ }
+
+ /**
+ * Get a list of users who have this role.
+ */
+ public function users() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsToMany($classMapper->getClassMapping('user'), 'role_users', 'role_id', 'user_id');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/User.php b/main/app/sprinkles/account/src/Database/Models/User.php index b401db2..cccd307 100644 --- a/main/app/sprinkles/account/src/Database/Models/User.php +++ b/main/app/sprinkles/account/src/Database/Models/User.php @@ -1,469 +1,469 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Carbon\Carbon; -use Illuminate\Database\Capsule\Manager as Capsule; -use Illuminate\Database\Eloquent\SoftDeletes; -use UserFrosting\Sprinkle\Account\Facades\Password; -use UserFrosting\Sprinkle\Core\Database\Models\Model; -use UserFrosting\Sprinkle\Core\Facades\Debug; - -/** - * User Class - * - * Represents a User object as stored in the database. - * - * @author Alex Weissman (https://alexanderweissman.com) - * @property int id - * @property string user_name - * @property string first_name - * @property string last_name - * @property string email - * @property string locale - * @property string theme - * @property int group_id - * @property bool flag_verified - * @property bool flag_enabled - * @property int last_activity_id - * @property timestamp created_at - * @property timestamp updated_at - * @property string password - * @property timestamp deleted_at - */ -class User extends Model -{ - use SoftDeletes; - - /** - * The name of the table for the current model. - * - * @var string - */ - protected $table = 'users'; - - /** - * Fields that should be mass-assignable when creating a new User. - * - * @var string[] - */ - protected $fillable = [ - 'user_name', - 'first_name', - 'last_name', - 'email', - 'locale', - 'theme', - 'group_id', - 'flag_verified', - 'flag_enabled', - 'last_activity_id', - 'password', - 'deleted_at' - ]; - - /** - * A list of attributes to hide by default when using toArray() and toJson(). - * - * @link https://laravel.com/docs/5.4/eloquent-serialization#hiding-attributes-from-json - * @var string[] - */ - protected $hidden = [ - 'password' - ]; - - /** - * The attributes that should be mutated to dates. - * - * @var string[] - */ - protected $dates = [ - 'deleted_at' - ]; - - protected $appends = [ - 'full_name' - ]; - - /** - * Cached dictionary of permissions for the user. - * - * @var array - */ - protected $cachedPermissions; - - /** - * Enable timestamps for Users. - * - * @var bool - */ - public $timestamps = TRUE; - - /** - * Determine if the property for this object exists. - * - * We add relations here so that Twig will be able to find them. - * See http://stackoverflow.com/questions/29514081/cannot-access-eloquent-attributes-on-twig/35908957#35908957 - * Every property in __get must also be implemented here for Twig to recognize it. - * @param string $name the name of the property to check. - * @return bool true if the property is defined, false otherwise. - */ - public function __isset($name) { - if (in_array($name, [ - 'group', - 'last_sign_in_time', - 'avatar' - ])) { - return TRUE; - } else { - return parent::__isset($name); - } - } - - /** - * Get a property for this object. - * - * @param string $name the name of the property to retrieve. - * @throws Exception the property does not exist for this object. - * @return string the associated property. - */ - public function __get($name) { - if ($name == 'last_sign_in_time') { - return $this->lastActivityTime('sign_in'); - } else if ($name == 'avatar') { - // Use Gravatar as the user avatar - $hash = md5(strtolower(trim($this->email))); - return 'https://www.gravatar.com/avatar/' . $hash . '?d=mm'; - } else { - return parent::__get($name); - } - } - - /** - * Get all activities for this user. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany - */ - public function activities() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->hasMany($classMapper->getClassMapping('activity'), 'user_id'); - } - - /** - * Delete this user from the database, along with any linked roles and activities. - * - * @param bool $hardDelete Set to true to completely remove the user and all associated objects. - * @return bool true if the deletion was successful, false otherwise. - */ - public function delete($hardDelete = FALSE) { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - if ($hardDelete) { - // Remove all role associations - $this->roles()->detach(); - - // Remove all user activities - $classMapper->staticMethod('activity', 'where', 'user_id', $this->id)->delete(); - - // Remove all user tokens - $classMapper->staticMethod('password_reset', 'where', 'user_id', $this->id)->delete(); - $classMapper->staticMethod('verification', 'where', 'user_id', $this->id)->delete(); - - // Delete the user - $result = parent::forceDelete(); - } else { - // Soft delete the user, leaving all associated records alone - $result = parent::delete(); - } - - return $result; - } - - /** - * Determines whether a user exists, including checking soft-deleted records - * - * @deprecated since 4.1.7 This method conflicts with and overrides the Builder::exists() method. Use Model::findUnique instead. - * @param mixed $value - * @param string $identifier - * @param bool $checkDeleted set to true to include soft-deleted records - * @return User|null - */ - public static function exists($value, $identifier = 'user_name', $checkDeleted = TRUE) { - return static::findUnique($value, $identifier, $checkDeleted); - } - - /** - * Return a cache instance specific to that user - * - * @return \Illuminate\Contracts\Cache\Store - */ - public function getCache() { - return static::$ci->cache->tags('_u' . $this->id); - } - - /** - * Allows you to get the full name of the user using `$user->full_name` - * - * @return string - */ - public function getFullNameAttribute() { - return $this->first_name . ' ' . $this->last_name; - } - - /** - * Retrieve the cached permissions dictionary for this user. - * - * @return array - */ - public function getCachedPermissions() { - if (!isset($this->cachedPermissions)) { - $this->reloadCachedPermissions(); - } - - return $this->cachedPermissions; - } - - /** - * Retrieve the cached permissions dictionary for this user. - * - * @return User - */ - public function reloadCachedPermissions() { - $this->cachedPermissions = $this->buildPermissionsDictionary(); - - return $this; - } - - /** - * Get the amount of time, in seconds, that has elapsed since the last activity of a certain time for this user. - * - * @param string $type The type of activity to search for. - * @return int - */ - public function getSecondsSinceLastActivity($type) { - $time = $this->lastActivityTime($type); - $time = $time ? $time : '0000-00-00 00:00:00'; - $time = new Carbon($time); - - return $time->diffInSeconds(); - } - - /** - * Return this user's group. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function group() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsTo($classMapper->getClassMapping('group'), 'group_id'); - } - - /** - * Returns whether or not this user is the master user. - * - * @return bool - */ - public function isMaster() { - $masterId = static::$ci->config['reserved_user_ids.master']; - - // Need to use loose comparison for now, because some DBs return `id` as a string - return ($this->id == $masterId); - } - - /** - * Get the most recent activity for this user, based on the user's last_activity_id. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function lastActivity() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsTo($classMapper->getClassMapping('activity'), 'last_activity_id'); - } - - /** - * Find the most recent activity for this user of a particular type. - * - * @param string $type - * @return \Illuminate\Database\Eloquent\Builder - */ - public function lastActivityOfType($type = NULL) { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - $query = $this->hasOne($classMapper->getClassMapping('activity'), 'user_id'); - - if ($type) { - $query = $query->where('type', $type); - } - - return $query->latest('occurred_at'); - } - - /** - * Get the most recent time for a specified activity type for this user. - * - * @param string $type - * @return string|null The last activity time, as a SQL formatted time (YYYY-MM-DD HH:MM:SS), or null if an activity of this type doesn't exist. - */ - public function lastActivityTime($type) { - $result = $this->activities() - ->where('type', $type) - ->max('occurred_at'); - return $result ? $result : NULL; - } - - /** - * Performs tasks to be done after this user has been successfully authenticated. - * - * By default, adds a new sign-in activity and updates any legacy hash. - * @param mixed[] $params Optional array of parameters used for this event handler. - * @odo Transition to Laravel Event dispatcher to handle this - */ - public function onLogin($params = []) { - // Add a sign in activity (time is automatically set by database) - static::$ci->userActivityLogger->info("User {$this->user_name} signed in.", [ - 'type' => 'sign_in' - ]); - - // Update password if we had encountered an outdated hash - $passwordType = Password::getHashType($this->password); - - if ($passwordType != 'modern') { - if (!isset($params['password'])) { - Debug::debug('Notice: Unhashed password must be supplied to update to modern password hashing.'); - } else { - // Hash the user's password and update - $passwordHash = Password::hash($params['password']); - if ($passwordHash === NULL) { - Debug::debug('Notice: outdated password hash could not be updated because the new hashing algorithm is not supported. Are you running PHP >= 5.3.7?'); - } else { - $this->password = $passwordHash; - Debug::debug('Notice: outdated password hash has been automatically updated to modern hashing.'); - } - } - } - - // Save changes - $this->save(); - - return $this; - } - - /** - * Performs tasks to be done after this user has been logged out. - * - * By default, adds a new sign-out activity. - * @param mixed[] $params Optional array of parameters used for this event handler. - * @do Transition to Laravel Event dispatcher to handle this - */ - public function onLogout($params = []) { - static::$ci->userActivityLogger->info("User {$this->user_name} signed out.", [ - 'type' => 'sign_out' - ]); - - return $this; - } - - /** - * Get all password reset requests for this user. - * - * @return \Illuminate\Database\Eloquent\Relations\HasMany - */ - public function passwordResets() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->hasMany($classMapper->getClassMapping('password_reset'), 'user_id'); - } - - /** - * Get all of the permissions this user has, via its roles. - * - * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough - */ - public function permissions() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsToManyThrough( - $classMapper->getClassMapping('permission'), - $classMapper->getClassMapping('role'), - 'role_users', - 'user_id', - 'role_id', - 'permission_roles', - 'role_id', - 'permission_id' - ); - } - - /** - * Get all roles to which this user belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany - */ - public function roles() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsToMany($classMapper->getClassMapping('role'), 'role_users', 'user_id', 'role_id')->withTimestamps(); - } - - /** - * Query scope to get all users who have a specific role. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param int $roleId - * @return \Illuminate\Database\Eloquent\Builder - */ - public function scopeForRole($query, $roleId) { - return $query->join('role_users', function ($join) use ($roleId) { - $join->on('role_users.user_id', 'users.id') - ->where('role_id', $roleId); - }); - } - - /** - * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc. - * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder - */ - public function scopeJoinLastActivity($query) { - $query = $query->select('users.*'); - - $query = $query->leftJoin('activities', 'activities.id', '=', 'users.last_activity_id'); - - return $query; - } - - /** - * Loads permissions for this user into a cached dictionary of slugs -> arrays of permissions, - * so we don't need to keep requerying the DB for every call of checkAccess. - * - * @return array - */ - protected function buildPermissionsDictionary() { - $permissions = $this->permissions()->get(); - $cachedPermissions = []; - - foreach ($permissions as $permission) { - $cachedPermissions[$permission->slug][] = $permission; - } - - return $cachedPermissions; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Carbon\Carbon;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use UserFrosting\Sprinkle\Account\Facades\Password;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+
+/**
+ * User Class
+ *
+ * Represents a User object as stored in the database.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @property int id
+ * @property string user_name
+ * @property string first_name
+ * @property string last_name
+ * @property string email
+ * @property string locale
+ * @property string theme
+ * @property int group_id
+ * @property bool flag_verified
+ * @property bool flag_enabled
+ * @property int last_activity_id
+ * @property timestamp created_at
+ * @property timestamp updated_at
+ * @property string password
+ * @property timestamp deleted_at
+ */
+class User extends Model
+{
+ use SoftDeletes;
+
+ /**
+ * The name of the table for the current model.
+ *
+ * @var string
+ */
+ protected $table = 'users';
+
+ /**
+ * Fields that should be mass-assignable when creating a new User.
+ *
+ * @var string[]
+ */
+ protected $fillable = [
+ 'user_name',
+ 'first_name',
+ 'last_name',
+ 'email',
+ 'locale',
+ 'theme',
+ 'group_id',
+ 'flag_verified',
+ 'flag_enabled',
+ 'last_activity_id',
+ 'password',
+ 'deleted_at'
+ ];
+
+ /**
+ * A list of attributes to hide by default when using toArray() and toJson().
+ *
+ * @link https://laravel.com/docs/5.4/eloquent-serialization#hiding-attributes-from-json
+ * @var string[]
+ */
+ protected $hidden = [
+ 'password'
+ ];
+
+ /**
+ * The attributes that should be mutated to dates.
+ *
+ * @var string[]
+ */
+ protected $dates = [
+ 'deleted_at'
+ ];
+
+ protected $appends = [
+ 'full_name'
+ ];
+
+ /**
+ * Cached dictionary of permissions for the user.
+ *
+ * @var array
+ */
+ protected $cachedPermissions;
+
+ /**
+ * Enable timestamps for Users.
+ *
+ * @var bool
+ */
+ public $timestamps = TRUE;
+
+ /**
+ * Determine if the property for this object exists.
+ *
+ * We add relations here so that Twig will be able to find them.
+ * See http://stackoverflow.com/questions/29514081/cannot-access-eloquent-attributes-on-twig/35908957#35908957
+ * Every property in __get must also be implemented here for Twig to recognize it.
+ * @param string $name the name of the property to check.
+ * @return bool true if the property is defined, false otherwise.
+ */
+ public function __isset($name) {
+ if (in_array($name, [
+ 'group',
+ 'last_sign_in_time',
+ 'avatar'
+ ])) {
+ return TRUE;
+ } else {
+ return parent::__isset($name);
+ }
+ }
+
+ /**
+ * Get a property for this object.
+ *
+ * @param string $name the name of the property to retrieve.
+ * @throws Exception the property does not exist for this object.
+ * @return string the associated property.
+ */
+ public function __get($name) {
+ if ($name == 'last_sign_in_time') {
+ return $this->lastActivityTime('sign_in');
+ } else if ($name == 'avatar') {
+ // Use Gravatar as the user avatar
+ $hash = md5(strtolower(trim($this->email)));
+ return 'https://www.gravatar.com/avatar/' . $hash . '?d=mm';
+ } else {
+ return parent::__get($name);
+ }
+ }
+
+ /**
+ * Get all activities for this user.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function activities() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->hasMany($classMapper->getClassMapping('activity'), 'user_id');
+ }
+
+ /**
+ * Delete this user from the database, along with any linked roles and activities.
+ *
+ * @param bool $hardDelete Set to true to completely remove the user and all associated objects.
+ * @return bool true if the deletion was successful, false otherwise.
+ */
+ public function delete($hardDelete = FALSE) {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ if ($hardDelete) {
+ // Remove all role associations
+ $this->roles()->detach();
+
+ // Remove all user activities
+ $classMapper->staticMethod('activity', 'where', 'user_id', $this->id)->delete();
+
+ // Remove all user tokens
+ $classMapper->staticMethod('password_reset', 'where', 'user_id', $this->id)->delete();
+ $classMapper->staticMethod('verification', 'where', 'user_id', $this->id)->delete();
+
+ // Delete the user
+ $result = parent::forceDelete();
+ } else {
+ // Soft delete the user, leaving all associated records alone
+ $result = parent::delete();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Determines whether a user exists, including checking soft-deleted records
+ *
+ * @deprecated since 4.1.7 This method conflicts with and overrides the Builder::exists() method. Use Model::findUnique instead.
+ * @param mixed $value
+ * @param string $identifier
+ * @param bool $checkDeleted set to true to include soft-deleted records
+ * @return User|null
+ */
+ public static function exists($value, $identifier = 'user_name', $checkDeleted = TRUE) {
+ return static::findUnique($value, $identifier, $checkDeleted);
+ }
+
+ /**
+ * Return a cache instance specific to that user
+ *
+ * @return \Illuminate\Contracts\Cache\Store
+ */
+ public function getCache() {
+ return static::$ci->cache->tags('_u' . $this->id);
+ }
+
+ /**
+ * Allows you to get the full name of the user using `$user->full_name`
+ *
+ * @return string
+ */
+ public function getFullNameAttribute() {
+ return $this->first_name . ' ' . $this->last_name;
+ }
+
+ /**
+ * Retrieve the cached permissions dictionary for this user.
+ *
+ * @return array
+ */
+ public function getCachedPermissions() {
+ if (!isset($this->cachedPermissions)) {
+ $this->reloadCachedPermissions();
+ }
+
+ return $this->cachedPermissions;
+ }
+
+ /**
+ * Retrieve the cached permissions dictionary for this user.
+ *
+ * @return User
+ */
+ public function reloadCachedPermissions() {
+ $this->cachedPermissions = $this->buildPermissionsDictionary();
+
+ return $this;
+ }
+
+ /**
+ * Get the amount of time, in seconds, that has elapsed since the last activity of a certain time for this user.
+ *
+ * @param string $type The type of activity to search for.
+ * @return int
+ */
+ public function getSecondsSinceLastActivity($type) {
+ $time = $this->lastActivityTime($type);
+ $time = $time ? $time : '0000-00-00 00:00:00';
+ $time = new Carbon($time);
+
+ return $time->diffInSeconds();
+ }
+
+ /**
+ * Return this user's group.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function group() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsTo($classMapper->getClassMapping('group'), 'group_id');
+ }
+
+ /**
+ * Returns whether or not this user is the master user.
+ *
+ * @return bool
+ */
+ public function isMaster() {
+ $masterId = static::$ci->config['reserved_user_ids.master'];
+
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ return ($this->id == $masterId);
+ }
+
+ /**
+ * Get the most recent activity for this user, based on the user's last_activity_id.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function lastActivity() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsTo($classMapper->getClassMapping('activity'), 'last_activity_id');
+ }
+
+ /**
+ * Find the most recent activity for this user of a particular type.
+ *
+ * @param string $type
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function lastActivityOfType($type = NULL) {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ $query = $this->hasOne($classMapper->getClassMapping('activity'), 'user_id');
+
+ if ($type) {
+ $query = $query->where('type', $type);
+ }
+
+ return $query->latest('occurred_at');
+ }
+
+ /**
+ * Get the most recent time for a specified activity type for this user.
+ *
+ * @param string $type
+ * @return string|null The last activity time, as a SQL formatted time (YYYY-MM-DD HH:MM:SS), or null if an activity of this type doesn't exist.
+ */
+ public function lastActivityTime($type) {
+ $result = $this->activities()
+ ->where('type', $type)
+ ->max('occurred_at');
+ return $result ? $result : NULL;
+ }
+
+ /**
+ * Performs tasks to be done after this user has been successfully authenticated.
+ *
+ * By default, adds a new sign-in activity and updates any legacy hash.
+ * @param mixed[] $params Optional array of parameters used for this event handler.
+ * @odo Transition to Laravel Event dispatcher to handle this
+ */
+ public function onLogin($params = []) {
+ // Add a sign in activity (time is automatically set by database)
+ static::$ci->userActivityLogger->info("User {$this->user_name} signed in.", [
+ 'type' => 'sign_in'
+ ]);
+
+ // Update password if we had encountered an outdated hash
+ $passwordType = Password::getHashType($this->password);
+
+ if ($passwordType != 'modern') {
+ if (!isset($params['password'])) {
+ Debug::debug('Notice: Unhashed password must be supplied to update to modern password hashing.');
+ } else {
+ // Hash the user's password and update
+ $passwordHash = Password::hash($params['password']);
+ if ($passwordHash === NULL) {
+ Debug::debug('Notice: outdated password hash could not be updated because the new hashing algorithm is not supported. Are you running PHP >= 5.3.7?');
+ } else {
+ $this->password = $passwordHash;
+ Debug::debug('Notice: outdated password hash has been automatically updated to modern hashing.');
+ }
+ }
+ }
+
+ // Save changes
+ $this->save();
+
+ return $this;
+ }
+
+ /**
+ * Performs tasks to be done after this user has been logged out.
+ *
+ * By default, adds a new sign-out activity.
+ * @param mixed[] $params Optional array of parameters used for this event handler.
+ * @do Transition to Laravel Event dispatcher to handle this
+ */
+ public function onLogout($params = []) {
+ static::$ci->userActivityLogger->info("User {$this->user_name} signed out.", [
+ 'type' => 'sign_out'
+ ]);
+
+ return $this;
+ }
+
+ /**
+ * Get all password reset requests for this user.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function passwordResets() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->hasMany($classMapper->getClassMapping('password_reset'), 'user_id');
+ }
+
+ /**
+ * Get all of the permissions this user has, via its roles.
+ *
+ * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough
+ */
+ public function permissions() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsToManyThrough(
+ $classMapper->getClassMapping('permission'),
+ $classMapper->getClassMapping('role'),
+ 'role_users',
+ 'user_id',
+ 'role_id',
+ 'permission_roles',
+ 'role_id',
+ 'permission_id'
+ );
+ }
+
+ /**
+ * Get all roles to which this user belongs.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
+ */
+ public function roles() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsToMany($classMapper->getClassMapping('role'), 'role_users', 'user_id', 'role_id')->withTimestamps();
+ }
+
+ /**
+ * Query scope to get all users who have a specific role.
+ *
+ * @param \Illuminate\Database\Eloquent\Builder $query
+ * @param int $roleId
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function scopeForRole($query, $roleId) {
+ return $query->join('role_users', function ($join) use ($roleId) {
+ $join->on('role_users.user_id', 'users.id')
+ ->where('role_id', $roleId);
+ });
+ }
+
+ /**
+ * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc.
+ *
+ * @param \Illuminate\Database\Eloquent\Builder $query
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function scopeJoinLastActivity($query) {
+ $query = $query->select('users.*');
+
+ $query = $query->leftJoin('activities', 'activities.id', '=', 'users.last_activity_id');
+
+ return $query;
+ }
+
+ /**
+ * Loads permissions for this user into a cached dictionary of slugs -> arrays of permissions,
+ * so we don't need to keep requerying the DB for every call of checkAccess.
+ *
+ * @return array
+ */
+ protected function buildPermissionsDictionary() {
+ $permissions = $this->permissions()->get();
+ $cachedPermissions = [];
+
+ foreach ($permissions as $permission) {
+ $cachedPermissions[$permission->slug][] = $permission;
+ }
+
+ return $cachedPermissions;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Database/Models/Verification.php b/main/app/sprinkles/account/src/Database/Models/Verification.php index f6697b6..f642d77 100644 --- a/main/app/sprinkles/account/src/Database/Models/Verification.php +++ b/main/app/sprinkles/account/src/Database/Models/Verification.php @@ -1,68 +1,68 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Database\Models; - -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -/** - * Verification Class - * - * Represents a pending email verification for a new user account. - * @author Alex Weissman (https://alexanderweissman.com) - * @property int user_id - * @property hash token - * @property bool completed - * @property datetime expires_at - * @property datetime completed_at - */ -class Verification extends Model -{ - /** - * @var string The name of the table for the current model. - */ - protected $table = "verifications"; - - protected $fillable = [ - "user_id", - "hash", - "completed", - "expires_at", - "completed_at" - ]; - - /** - * @var bool Enable timestamps for Verifications. - */ - public $timestamps = TRUE; - - /** - * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted. - */ - protected $token; - - public function getToken() { - return $this->token; - } - - public function setToken($value) { - $this->token = $value; - return $this; - } - - /** - * Get the user associated with this verification request. - */ - public function user() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = static::$ci->classMapper; - - return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id'); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Database\Models;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+/**
+ * Verification Class
+ *
+ * Represents a pending email verification for a new user account.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @property int user_id
+ * @property hash token
+ * @property bool completed
+ * @property datetime expires_at
+ * @property datetime completed_at
+ */
+class Verification extends Model
+{
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = "verifications";
+
+ protected $fillable = [
+ "user_id",
+ "hash",
+ "completed",
+ "expires_at",
+ "completed_at"
+ ];
+
+ /**
+ * @var bool Enable timestamps for Verifications.
+ */
+ public $timestamps = TRUE;
+
+ /**
+ * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted.
+ */
+ protected $token;
+
+ public function getToken() {
+ return $this->token;
+ }
+
+ public function setToken($value) {
+ $this->token = $value;
+ return $this;
+ }
+
+ /**
+ * Get the user associated with this verification request.
+ */
+ public function user() {
+ /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
+ $classMapper = static::$ci->classMapper;
+
+ return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id');
+ }
+}
diff --git a/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php b/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php index 4c3b100..ccefe72 100644 --- a/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php +++ b/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php @@ -1,34 +1,34 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Error\Handler; - -use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; - -/** - * Handler for AuthCompromisedExceptions. - * - * Warns the user that their account may have been compromised due to a stolen "remember me" cookie. - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AuthCompromisedExceptionHandler extends HttpExceptionHandler -{ - /** - * Render a generic, user-friendly response without sensitive debugging information. - * - * @return ResponseInterface - */ - public function renderGenericResponse() { - $template = $this->ci->view->getEnvironment()->loadTemplate('pages/error/compromised.html.twig'); - - return $this->response - ->withStatus($this->statusCode) - ->withHeader('Content-type', $this->contentType) - ->write($template->render()); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Error\Handler;
+
+use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler;
+
+/**
+ * Handler for AuthCompromisedExceptions.
+ *
+ * Warns the user that their account may have been compromised due to a stolen "remember me" cookie.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AuthCompromisedExceptionHandler extends HttpExceptionHandler
+{
+ /**
+ * Render a generic, user-friendly response without sensitive debugging information.
+ *
+ * @return ResponseInterface
+ */
+ public function renderGenericResponse() {
+ $template = $this->ci->view->getEnvironment()->loadTemplate('pages/error/compromised.html.twig');
+
+ return $this->response
+ ->withStatus($this->statusCode)
+ ->withHeader('Content-type', $this->contentType)
+ ->write($template->render());
+ }
+}
diff --git a/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php b/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php index fd3ca1f..fb04bd1 100644 --- a/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php +++ b/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php @@ -1,50 +1,50 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Error\Handler; - -use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; - -/** - * Handler for AuthExpiredExceptions. - * - * Forwards the user to the login page when their session has expired. - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AuthExpiredExceptionHandler extends HttpExceptionHandler -{ - /** - * Custom handling for requests that did not pass authentication. - */ - public function handle() { - // For auth expired exceptions, we always add messages to the alert stream. - $this->writeAlerts(); - - $response = $this->response; - - // For non-AJAX requests, we forward the user to the login page. - if (!$this->request->isXhr()) { - $uri = $this->request->getUri(); - $path = $uri->getPath(); - $query = $uri->getQuery(); - $fragment = $uri->getFragment(); - - $path = $path - . ($query ? '?' . $query : '') - . ($fragment ? '#' . $fragment : ''); - - $loginPage = $this->ci->router->pathFor('login', [], [ - 'redirect' => $path - ]); - - $response = $response->withRedirect($loginPage); - } - - return $response; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Error\Handler;
+
+use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler;
+
+/**
+ * Handler for AuthExpiredExceptions.
+ *
+ * Forwards the user to the login page when their session has expired.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AuthExpiredExceptionHandler extends HttpExceptionHandler
+{
+ /**
+ * Custom handling for requests that did not pass authentication.
+ */
+ public function handle() {
+ // For auth expired exceptions, we always add messages to the alert stream.
+ $this->writeAlerts();
+
+ $response = $this->response;
+
+ // For non-AJAX requests, we forward the user to the login page.
+ if (!$this->request->isXhr()) {
+ $uri = $this->request->getUri();
+ $path = $uri->getPath();
+ $query = $uri->getQuery();
+ $fragment = $uri->getFragment();
+
+ $path = $path
+ . ($query ? '?' . $query : '')
+ . ($fragment ? '#' . $fragment : '');
+
+ $loginPage = $this->ci->router->pathFor('login', [], [
+ 'redirect' => $path
+ ]);
+
+ $response = $response->withRedirect($loginPage);
+ }
+
+ return $response;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php b/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php index b418dde..0166d2a 100644 --- a/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php +++ b/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php @@ -1,31 +1,31 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Error\Handler; - -use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; -use UserFrosting\Support\Message\UserMessage; - -/** - * Handler for ForbiddenExceptions. Only really needed to override the default error message. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class ForbiddenExceptionHandler extends HttpExceptionHandler -{ - /** - * Resolve a list of error messages to present to the end user. - * - * @return array - */ - protected function determineUserMessages() { - return [ - new UserMessage("ACCOUNT.ACCESS_DENIED") - ]; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Error\Handler;
+
+use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler;
+use UserFrosting\Support\Message\UserMessage;
+
+/**
+ * Handler for ForbiddenExceptions. Only really needed to override the default error message.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ForbiddenExceptionHandler extends HttpExceptionHandler
+{
+ /**
+ * Resolve a list of error messages to present to the end user.
+ *
+ * @return array
+ */
+ protected function determineUserMessages() {
+ return [
+ new UserMessage("ACCOUNT.ACCESS_DENIED")
+ ];
+ }
+}
diff --git a/main/app/sprinkles/account/src/Facades/Password.php b/main/app/sprinkles/account/src/Facades/Password.php index 0664b7a..ec300d3 100644 --- a/main/app/sprinkles/account/src/Facades/Password.php +++ b/main/app/sprinkles/account/src/Facades/Password.php @@ -1,28 +1,28 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Facades; - -use UserFrosting\System\Facade; - -/** - * Implements facade for the "password" service - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class Password extends Facade -{ - /** - * Get the registered name of the component. - * - * @return string - */ - protected static function getFacadeAccessor() { - return 'passwordHasher'; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Facades;
+
+use UserFrosting\System\Facade;
+
+/**
+ * Implements facade for the "password" service
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Password extends Facade
+{
+ /**
+ * Get the registered name of the component.
+ *
+ * @return string
+ */
+ protected static function getFacadeAccessor() {
+ return 'passwordHasher';
+ }
+}
diff --git a/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php b/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php index a1cd14f..eb57f43 100644 --- a/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php +++ b/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php @@ -1,33 +1,33 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Log; - -use UserFrosting\Sprinkle\Core\Log\DatabaseHandler; - -/** - * Monolog handler for storing user activities to the database. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class UserActivityDatabaseHandler extends DatabaseHandler -{ - /** - * {@inheritDoc} - */ - protected function write(array $record) { - $log = $this->classMapper->createInstance($this->modelName, $record['extra']); - $log->save(); - - if (isset($record['extra']['user_id'])) { - $user = $this->classMapper->staticMethod('user', 'find', $record['extra']['user_id']); - $user->last_activity_id = $log->id; - $user->save(); - } - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Log;
+
+use UserFrosting\Sprinkle\Core\Log\DatabaseHandler;
+
+/**
+ * Monolog handler for storing user activities to the database.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class UserActivityDatabaseHandler extends DatabaseHandler
+{
+ /**
+ * {@inheritDoc}
+ */
+ protected function write(array $record) {
+ $log = $this->classMapper->createInstance($this->modelName, $record['extra']);
+ $log->save();
+
+ if (isset($record['extra']['user_id'])) {
+ $user = $this->classMapper->staticMethod('user', 'find', $record['extra']['user_id']);
+ $user->last_activity_id = $log->id;
+ $user->save();
+ }
+ }
+}
diff --git a/main/app/sprinkles/account/src/Log/UserActivityProcessor.php b/main/app/sprinkles/account/src/Log/UserActivityProcessor.php index f1aa8c7..a5c0d98 100644 --- a/main/app/sprinkles/account/src/Log/UserActivityProcessor.php +++ b/main/app/sprinkles/account/src/Log/UserActivityProcessor.php @@ -1,44 +1,44 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Log; - -use Monolog\Logger; - -/** - * Monolog processor for constructing the user activity message. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class UserActivityProcessor -{ - /** - * @var int - */ - protected $userId; - - /** - * @param int $userId The id of the user for whom we will be logging activities. - */ - public function __construct($userId) { - $this->userId = $userId; - } - - public function __invoke(array $record) { - $additionalFields = [ - 'ip_address' => $_SERVER['REMOTE_ADDR'], - 'user_id' => $this->userId, - 'occurred_at' => $record['datetime'], - 'description' => $record['message'] - ]; - - $record['extra'] = array_replace_recursive($record['extra'], $additionalFields, $record['context']); - - return $record; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Log;
+
+use Monolog\Logger;
+
+/**
+ * Monolog processor for constructing the user activity message.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class UserActivityProcessor
+{
+ /**
+ * @var int
+ */
+ protected $userId;
+
+ /**
+ * @param int $userId The id of the user for whom we will be logging activities.
+ */
+ public function __construct($userId) {
+ $this->userId = $userId;
+ }
+
+ public function __invoke(array $record) {
+ $additionalFields = [
+ 'ip_address' => $_SERVER['REMOTE_ADDR'],
+ 'user_id' => $this->userId,
+ 'occurred_at' => $record['datetime'],
+ 'description' => $record['message']
+ ];
+
+ $record['extra'] = array_replace_recursive($record['extra'], $additionalFields, $record['context']);
+
+ return $record;
+ }
+}
diff --git a/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php b/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php index 21ff548..06a37a8 100644 --- a/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php +++ b/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php @@ -1,34 +1,34 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Repository; - -use UserFrosting\Sprinkle\Account\Facades\Password; - -/** - * Token repository class for password reset requests. - * - * @author Alex Weissman (https://alexanderweissman.com) - * @see https://learn.userfrosting.com/users/user-accounts - */ -class PasswordResetRepository extends TokenRepository -{ - /** - * {@inheritDoc} - */ - protected $modelIdentifier = 'password_reset'; - - /** - * {@inheritDoc} - */ - protected function updateUser($user, $args) { - $user->password = Password::hash($args['password']); - // DO: generate user activity? or do this in controller? - $user->save(); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Repository;
+
+use UserFrosting\Sprinkle\Account\Facades\Password;
+
+/**
+ * Token repository class for password reset requests.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see https://learn.userfrosting.com/users/user-accounts
+ */
+class PasswordResetRepository extends TokenRepository
+{
+ /**
+ * {@inheritDoc}
+ */
+ protected $modelIdentifier = 'password_reset';
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function updateUser($user, $args) {
+ $user->password = Password::hash($args['password']);
+ // DO: generate user activity? or do this in controller?
+ $user->save();
+ }
+}
diff --git a/main/app/sprinkles/account/src/Repository/TokenRepository.php b/main/app/sprinkles/account/src/Repository/TokenRepository.php index 5c2e34a..6b289bf 100644 --- a/main/app/sprinkles/account/src/Repository/TokenRepository.php +++ b/main/app/sprinkles/account/src/Repository/TokenRepository.php @@ -1,223 +1,223 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Repository; - -use Carbon\Carbon; -use UserFrosting\Sprinkle\Account\Database\Models\User; -use UserFrosting\Sprinkle\Core\Database\Models\Model; -use UserFrosting\Sprinkle\Core\Util\ClassMapper; - -/** - * An abstract class for interacting with a repository of time-sensitive user tokens. - * - * User tokens are used, for example, to perform password resets and new account email verifications. - * @author Alex Weissman (https://alexanderweissman.com) - * @see https://learn.userfrosting.com/users/user-accounts - */ -abstract class TokenRepository -{ - - /** - * @var ClassMapper - */ - protected $classMapper; - - /** - * @var string - */ - protected $algorithm; - - /** - * @var string - */ - protected $modelIdentifier; - - /** - * Create a new TokenRepository object. - * - * @param ClassMapper $classMapper Maps generic class identifiers to specific class names. - * @param string $algorithm The hashing algorithm to use when storing generated tokens. - */ - public function __construct(ClassMapper $classMapper, $algorithm = 'sha512') { - $this->classMapper = $classMapper; - $this->algorithm = $algorithm; - } - - /** - * Cancels a specified token by removing it from the database. - * - * @param int $token The token to remove. - * @return Model|false - */ - public function cancel($token) { - // Hash the password reset token for the stored version - $hash = hash($this->algorithm, $token); - - // Find an incomplete reset request for the specified hash - $model = $this->classMapper - ->staticMethod($this->modelIdentifier, 'where', 'hash', $hash) - ->where('completed', FALSE) - ->first(); - - if ($model === NULL) { - return FALSE; - } - - $model->delete(); - - return $model; - } - - /** - * Completes a token-based process, invoking updateUser() in the child object to do the actual action. - * - * @param int $token The token to complete. - * @param mixed[] $userParams An optional list of parameters to pass to updateUser(). - * @return Model|false - */ - public function complete($token, $userParams = []) { - // Hash the token for the stored version - $hash = hash($this->algorithm, $token); - - // Find an unexpired, incomplete token for the specified hash - $model = $this->classMapper - ->staticMethod($this->modelIdentifier, 'where', 'hash', $hash) - ->where('completed', FALSE) - ->where('expires_at', '>', Carbon::now()) - ->first(); - - if ($model === NULL) { - return FALSE; - } - - // Fetch user for this token - $user = $this->classMapper->staticMethod('user', 'find', $model->user_id); - - if (is_null($user)) { - return FALSE; - } - - $this->updateUser($user, $userParams); - - $model->fill([ - 'completed' => TRUE, - 'completed_at' => Carbon::now() - ]); - - $model->save(); - - return $model; - } - - /** - * Create a new token for a specified user. - * - * @param User $user The user object to associate with this token. - * @param int $timeout The time, in seconds, after which this token should expire. - * @return Model The model (PasswordReset, Verification, etc) object that stores the token. - */ - public function create(User $user, $timeout) { - // Remove any previous tokens for this user - $this->removeExisting($user); - - // Compute expiration time - $expiresAt = Carbon::now()->addSeconds($timeout); - - $model = $this->classMapper->createInstance($this->modelIdentifier); - - // Generate a random token - $model->setToken($this->generateRandomToken()); - - // Hash the password reset token for the stored version - $hash = hash($this->algorithm, $model->getToken()); - - $model->fill([ - 'hash' => $hash, - 'completed' => FALSE, - 'expires_at' => $expiresAt - ]); - - $model->user_id = $user->id; - - $model->save(); - - return $model; - } - - /** - * Determine if a specified user has an incomplete and unexpired token. - * - * @param User $user The user object to look up. - * @param int $token Optionally, try to match a specific token. - * @return Model|false - */ - public function exists(User $user, $token = NULL) { - $model = $this->classMapper - ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id) - ->where('completed', FALSE) - ->where('expires_at', '>', Carbon::now()); - - if ($token) { - // get token hash - $hash = hash($this->algorithm, $token); - $model->where('hash', $hash); - } - - return $model->first() ?: FALSE; - } - - /** - * Delete all existing tokens from the database for a particular user. - * - * @param User $user - * @return int - */ - protected function removeExisting(User $user) { - return $this->classMapper - ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id) - ->delete(); - } - - /** - * Remove all expired tokens from the database. - * - * @return bool|null - */ - public function removeExpired() { - return $this->classMapper - ->staticMethod($this->modelIdentifier, 'where', 'completed', FALSE) - ->where('expires_at', '<', Carbon::now()) - ->delete(); - } - - /** - * Generate a new random token for this user. - * - * This generates a token to use for verifying a new account, resetting a lost password, etc. - * @param string $gen specify an existing token that, if we happen to generate the same value, we should regenerate on. - * @return string - */ - protected function generateRandomToken($gen = NULL) { - do { - $gen = md5(uniqid(mt_rand(), FALSE)); - } while ($this->classMapper - ->staticMethod($this->modelIdentifier, 'where', 'hash', hash($this->algorithm, $gen)) - ->first()); - return $gen; - } - - /** - * Modify the user during the token completion process. - * - * This method is called during complete(), and is a way for concrete implementations to modify the user. - * @param User $user the user object to modify. - * @return mixed[] $args the list of parameters that were supplied to the call to `complete()` - */ - abstract protected function updateUser($user, $args); -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Repository;
+
+use Carbon\Carbon;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+use UserFrosting\Sprinkle\Core\Util\ClassMapper;
+
+/**
+ * An abstract class for interacting with a repository of time-sensitive user tokens.
+ *
+ * User tokens are used, for example, to perform password resets and new account email verifications.
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see https://learn.userfrosting.com/users/user-accounts
+ */
+abstract class TokenRepository
+{
+
+ /**
+ * @var ClassMapper
+ */
+ protected $classMapper;
+
+ /**
+ * @var string
+ */
+ protected $algorithm;
+
+ /**
+ * @var string
+ */
+ protected $modelIdentifier;
+
+ /**
+ * Create a new TokenRepository object.
+ *
+ * @param ClassMapper $classMapper Maps generic class identifiers to specific class names.
+ * @param string $algorithm The hashing algorithm to use when storing generated tokens.
+ */
+ public function __construct(ClassMapper $classMapper, $algorithm = 'sha512') {
+ $this->classMapper = $classMapper;
+ $this->algorithm = $algorithm;
+ }
+
+ /**
+ * Cancels a specified token by removing it from the database.
+ *
+ * @param int $token The token to remove.
+ * @return Model|false
+ */
+ public function cancel($token) {
+ // Hash the password reset token for the stored version
+ $hash = hash($this->algorithm, $token);
+
+ // Find an incomplete reset request for the specified hash
+ $model = $this->classMapper
+ ->staticMethod($this->modelIdentifier, 'where', 'hash', $hash)
+ ->where('completed', FALSE)
+ ->first();
+
+ if ($model === NULL) {
+ return FALSE;
+ }
+
+ $model->delete();
+
+ return $model;
+ }
+
+ /**
+ * Completes a token-based process, invoking updateUser() in the child object to do the actual action.
+ *
+ * @param int $token The token to complete.
+ * @param mixed[] $userParams An optional list of parameters to pass to updateUser().
+ * @return Model|false
+ */
+ public function complete($token, $userParams = []) {
+ // Hash the token for the stored version
+ $hash = hash($this->algorithm, $token);
+
+ // Find an unexpired, incomplete token for the specified hash
+ $model = $this->classMapper
+ ->staticMethod($this->modelIdentifier, 'where', 'hash', $hash)
+ ->where('completed', FALSE)
+ ->where('expires_at', '>', Carbon::now())
+ ->first();
+
+ if ($model === NULL) {
+ return FALSE;
+ }
+
+ // Fetch user for this token
+ $user = $this->classMapper->staticMethod('user', 'find', $model->user_id);
+
+ if (is_null($user)) {
+ return FALSE;
+ }
+
+ $this->updateUser($user, $userParams);
+
+ $model->fill([
+ 'completed' => TRUE,
+ 'completed_at' => Carbon::now()
+ ]);
+
+ $model->save();
+
+ return $model;
+ }
+
+ /**
+ * Create a new token for a specified user.
+ *
+ * @param User $user The user object to associate with this token.
+ * @param int $timeout The time, in seconds, after which this token should expire.
+ * @return Model The model (PasswordReset, Verification, etc) object that stores the token.
+ */
+ public function create(User $user, $timeout) {
+ // Remove any previous tokens for this user
+ $this->removeExisting($user);
+
+ // Compute expiration time
+ $expiresAt = Carbon::now()->addSeconds($timeout);
+
+ $model = $this->classMapper->createInstance($this->modelIdentifier);
+
+ // Generate a random token
+ $model->setToken($this->generateRandomToken());
+
+ // Hash the password reset token for the stored version
+ $hash = hash($this->algorithm, $model->getToken());
+
+ $model->fill([
+ 'hash' => $hash,
+ 'completed' => FALSE,
+ 'expires_at' => $expiresAt
+ ]);
+
+ $model->user_id = $user->id;
+
+ $model->save();
+
+ return $model;
+ }
+
+ /**
+ * Determine if a specified user has an incomplete and unexpired token.
+ *
+ * @param User $user The user object to look up.
+ * @param int $token Optionally, try to match a specific token.
+ * @return Model|false
+ */
+ public function exists(User $user, $token = NULL) {
+ $model = $this->classMapper
+ ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id)
+ ->where('completed', FALSE)
+ ->where('expires_at', '>', Carbon::now());
+
+ if ($token) {
+ // get token hash
+ $hash = hash($this->algorithm, $token);
+ $model->where('hash', $hash);
+ }
+
+ return $model->first() ?: FALSE;
+ }
+
+ /**
+ * Delete all existing tokens from the database for a particular user.
+ *
+ * @param User $user
+ * @return int
+ */
+ protected function removeExisting(User $user) {
+ return $this->classMapper
+ ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id)
+ ->delete();
+ }
+
+ /**
+ * Remove all expired tokens from the database.
+ *
+ * @return bool|null
+ */
+ public function removeExpired() {
+ return $this->classMapper
+ ->staticMethod($this->modelIdentifier, 'where', 'completed', FALSE)
+ ->where('expires_at', '<', Carbon::now())
+ ->delete();
+ }
+
+ /**
+ * Generate a new random token for this user.
+ *
+ * This generates a token to use for verifying a new account, resetting a lost password, etc.
+ * @param string $gen specify an existing token that, if we happen to generate the same value, we should regenerate on.
+ * @return string
+ */
+ protected function generateRandomToken($gen = NULL) {
+ do {
+ $gen = md5(uniqid(mt_rand(), FALSE));
+ } while ($this->classMapper
+ ->staticMethod($this->modelIdentifier, 'where', 'hash', hash($this->algorithm, $gen))
+ ->first());
+ return $gen;
+ }
+
+ /**
+ * Modify the user during the token completion process.
+ *
+ * This method is called during complete(), and is a way for concrete implementations to modify the user.
+ * @param User $user the user object to modify.
+ * @return mixed[] $args the list of parameters that were supplied to the call to `complete()`
+ */
+ abstract protected function updateUser($user, $args);
+}
diff --git a/main/app/sprinkles/account/src/Repository/VerificationRepository.php b/main/app/sprinkles/account/src/Repository/VerificationRepository.php index d714dce..f7ee3e7 100644 --- a/main/app/sprinkles/account/src/Repository/VerificationRepository.php +++ b/main/app/sprinkles/account/src/Repository/VerificationRepository.php @@ -1,31 +1,31 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Repository; - -/** - * Token repository class for new account verifications. - * - * @author Alex Weissman (https://alexanderweissman.com) - * @see https://learn.userfrosting.com/users/user-accounts - */ -class VerificationRepository extends TokenRepository -{ - /** - * {@inheritDoc} - */ - protected $modelIdentifier = 'verification'; - - /** - * {@inheritDoc} - */ - protected function updateUser($user, $args) { - $user->flag_verified = 1; - $user->save(); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Repository;
+
+/**
+ * Token repository class for new account verifications.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ * @see https://learn.userfrosting.com/users/user-accounts
+ */
+class VerificationRepository extends TokenRepository
+{
+ /**
+ * {@inheritDoc}
+ */
+ protected $modelIdentifier = 'verification';
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function updateUser($user, $args) {
+ $user->flag_verified = 1;
+ $user->save();
+ }
+}
diff --git a/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 38d81d5..1615d2e 100644 --- a/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -1,444 +1,444 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\ServicesProvider; - -use Birke\Rememberme\Authenticator as RememberMe; -use Illuminate\Database\Capsule\Manager as Capsule; -use Monolog\Formatter\LineFormatter; -use Monolog\Handler\ErrorLogHandler; -use Monolog\Handler\StreamHandler; -use Monolog\Logger; -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface as Request; -use UserFrosting\Sprinkle\Account\Authenticate\Authenticator; -use UserFrosting\Sprinkle\Account\Authenticate\AuthGuard; -use UserFrosting\Sprinkle\Account\Authenticate\Hasher; -use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager; -use UserFrosting\Sprinkle\Account\Database\Models\User; -use UserFrosting\Sprinkle\Account\Log\UserActivityDatabaseHandler; -use UserFrosting\Sprinkle\Account\Log\UserActivityProcessor; -use UserFrosting\Sprinkle\Account\Repository\PasswordResetRepository; -use UserFrosting\Sprinkle\Account\Repository\VerificationRepository; -use UserFrosting\Sprinkle\Account\Twig\AccountExtension; -use UserFrosting\Sprinkle\Core\Facades\Debug; -use UserFrosting\Sprinkle\Core\Log\MixedFormatter; - -/** - * Registers services for the account sprinkle, such as currentUser, etc. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class ServicesProvider -{ - /** - * Register UserFrosting's account services. - * - * @param Container $container A DI container implementing ArrayAccess and container-interop. - */ - public function register($container) { - /** - * Extend the asset manager service to see assets for the current user's theme. - */ - $container->extend('assets', function ($assets, $c) { - - // Register paths for user theme, if a user is logged in - // We catch any authorization-related exceptions, so that error pages can be rendered. - try { - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $c->authenticator; - $currentUser = $c->currentUser; - } catch (\Exception $e) { - return $assets; - } - - if ($authenticator->check()) { - $c->sprinkleManager->addResource('assets', $currentUser->theme); - } - - return $assets; - }); - - /** - * Extend the 'classMapper' service to register model classes. - * - * Mappings added: User, Group, Role, Permission, Activity, PasswordReset, Verification - */ - $container->extend('classMapper', function ($classMapper, $c) { - $classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\Account\Database\Models\User'); - $classMapper->setClassMapping('group', 'UserFrosting\Sprinkle\Account\Database\Models\Group'); - $classMapper->setClassMapping('role', 'UserFrosting\Sprinkle\Account\Database\Models\Role'); - $classMapper->setClassMapping('permission', 'UserFrosting\Sprinkle\Account\Database\Models\Permission'); - $classMapper->setClassMapping('activity', 'UserFrosting\Sprinkle\Account\Database\Models\Activity'); - $classMapper->setClassMapping('password_reset', 'UserFrosting\Sprinkle\Account\Database\Models\PasswordReset'); - $classMapper->setClassMapping('verification', 'UserFrosting\Sprinkle\Account\Database\Models\Verification'); - return $classMapper; - }); - - /** - * Extends the 'errorHandler' service with custom exception handlers. - * - * Custom handlers added: ForbiddenExceptionHandler - */ - $container->extend('errorHandler', function ($handler, $c) { - // Register the ForbiddenExceptionHandler. - $handler->registerHandler('\UserFrosting\Support\Exception\ForbiddenException', '\UserFrosting\Sprinkle\Account\Error\Handler\ForbiddenExceptionHandler'); - // Register the AuthExpiredExceptionHandler - $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthExpiredExceptionHandler'); - // Register the AuthCompromisedExceptionHandler. - $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthCompromisedExceptionHandler'); - return $handler; - }); - - /** - * Extends the 'localePathBuilder' service, adding any locale files from the user theme. - * - */ - $container->extend('localePathBuilder', function ($pathBuilder, $c) { - // Add paths for user theme, if a user is logged in - // We catch any authorization-related exceptions, so that error pages can be rendered. - try { - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $c->authenticator; - $currentUser = $c->currentUser; - } catch (\Exception $e) { - return $pathBuilder; - } - - if ($authenticator->check()) { - // Add paths to locale files for user theme - $themePath = $c->sprinkleManager->addResource('locale', $currentUser->theme); - - // Add user locale - $pathBuilder->addLocales($currentUser->locale); - } - - return $pathBuilder; - }); - - /** - * Extends the 'view' service with the AccountExtension for Twig. - * - * Adds account-specific functions, globals, filters, etc to Twig, and the path to templates for the user theme. - */ - $container->extend('view', function ($view, $c) { - $twig = $view->getEnvironment(); - $extension = new AccountExtension($c); - $twig->addExtension($extension); - - // Add paths for user theme, if a user is logged in - // We catch any authorization-related exceptions, so that error pages can be rendered. - try { - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $c->authenticator; - $currentUser = $c->currentUser; - } catch (\Exception $e) { - return $view; - } - - if ($authenticator->check()) { - $theme = $currentUser->theme; - $themePath = $c->sprinkleManager->addResource('templates', $theme); - if ($themePath) { - $loader = $twig->getLoader(); - $loader->prependPath($themePath); - // Add namespaced path as well - $loader->addPath($themePath, $theme); - } - } - - return $view; - }); - - /** - * Authentication service. - * - * Supports logging in users, remembering their sessions, etc. - */ - $container['authenticator'] = function ($c) { - $classMapper = $c->classMapper; - $config = $c->config; - $session = $c->session; - $cache = $c->cache; - - // Force database connection to boot up - $c->db; - - // Fix RememberMe table name - $config['remember_me.table.tableName'] = Capsule::connection()->getTablePrefix() . $config['remember_me.table.tableName']; - - $authenticator = new Authenticator($classMapper, $session, $config, $cache); - return $authenticator; - }; - - /** - * Sets up the AuthGuard middleware, used to limit access to authenticated users for certain routes. - */ - $container['authGuard'] = function ($c) { - $authenticator = $c->authenticator; - return new AuthGuard($authenticator); - }; - - /** - * Authorization check logging with Monolog. - * - * Extend this service to push additional handlers onto the 'auth' log stack. - */ - $container['authLogger'] = function ($c) { - $logger = new Logger('auth'); - - $logFile = $c->get('locator')->findResource('log://userfrosting.log', TRUE, TRUE); - - $handler = new StreamHandler($logFile); - - $formatter = new MixedFormatter(NULL, NULL, TRUE); - - $handler->setFormatter($formatter); - $logger->pushHandler($handler); - - return $logger; - }; - - /** - * Authorization service. - * - * Determines permissions for user actions. Extend this service to add additional access condition callbacks. - */ - $container['authorizer'] = function ($c) { - $config = $c->config; - - // Default access condition callbacks. Add more in your sprinkle by using $container->extend(...) - $callbacks = [ - /** - * Unconditionally grant permission - use carefully! - * @return bool returns true no matter what. - */ - 'always' => function () { - return TRUE; - }, - - /** - * Check if the specified values are identical to one another (strict comparison). - * @param mixed $val1 the first value to compare. - * @param mixed $val2 the second value to compare. - * @return bool true if the values are strictly equal, false otherwise. - */ - 'equals' => function ($val1, $val2) { - return ($val1 === $val2); - }, - - /** - * Check if the specified values are numeric, and if so, if they are equal to each other. - * @param mixed $val1 the first value to compare. - * @param mixed $val2 the second value to compare. - * @return bool true if the values are numeric and equal, false otherwise. - */ - 'equals_num' => function ($val1, $val2) { - if (!is_numeric($val1)) { - return FALSE; - } - if (!is_numeric($val2)) { - return FALSE; - } - - return ($val1 == $val2); - }, - - /** - * Check if the specified user (by user_id) has a particular role. - * - * @param int $user_id the id of the user. - * @param int $role_id the id of the role. - * @return bool true if the user has the role, false otherwise. - */ - 'has_role' => function ($user_id, $role_id) { - return Capsule::table('role_users') - ->where('user_id', $user_id) - ->where('role_id', $role_id) - ->count() > 0; - }, - - /** - * Check if the specified value $needle is in the values of $haystack. - * - * @param mixed $needle the value to look for in $haystack - * @param array[mixed] $haystack the array of values to search. - * @return bool true if $needle is present in the values of $haystack, false otherwise. - */ - 'in' => function ($needle, $haystack) { - return in_array($needle, $haystack); - }, - - /** - * Check if the specified user (by user_id) is in a particular group. - * - * @param int $user_id the id of the user. - * @param int $group_id the id of the group. - * @return bool true if the user is in the group, false otherwise. - */ - 'in_group' => function ($user_id, $group_id) { - $user = User::find($user_id); - return ($user->group_id == $group_id); - }, - - /** - * Check if the specified user (by user_id) is the master user. - * - * @param int $user_id the id of the user. - * @return bool true if the user id is equal to the id of the master account, false otherwise. - */ - 'is_master' => function ($user_id) use ($config) { - // Need to use loose comparison for now, because some DBs return `id` as a string - return ($user_id == $config['reserved_user_ids.master']); - }, - - /** - * Check if all values in the array $needle are present in the values of $haystack. - * - * @param array[mixed] $needle the array whose values we should look for in $haystack - * @param array[mixed] $haystack the array of values to search. - * @return bool true if every value in $needle is present in the values of $haystack, false otherwise. - */ - 'subset' => function ($needle, $haystack) { - return count($needle) == count(array_intersect($needle, $haystack)); - }, - - /** - * Check if all keys of the array $needle are present in the values of $haystack. - * - * This function is useful for whitelisting an array of key-value parameters. - * @param array[mixed] $needle the array whose keys we should look for in $haystack - * @param array[mixed] $haystack the array of values to search. - * @return bool true if every key in $needle is present in the values of $haystack, false otherwise. - */ - 'subset_keys' => function ($needle, $haystack) { - return count($needle) == count(array_intersect(array_keys($needle), $haystack)); - } - ]; - - $authorizer = new AuthorizationManager($c, $callbacks); - return $authorizer; - }; - - /** - * Loads the User object for the currently logged-in user. - */ - $container['currentUser'] = function ($c) { - $authenticator = $c->authenticator; - - return $authenticator->user(); - }; - - $container['passwordHasher'] = function ($c) { - $hasher = new Hasher(); - return $hasher; - }; - - /** - * Returns a callback that forwards to dashboard if user is already logged in. - */ - $container['redirect.onAlreadyLoggedIn'] = function ($c) { - /** - * This method is invoked when a user attempts to perform certain public actions when they are already logged in. - * - * Forward to user's landing page or last visited page - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response - * @param array $args - * @return \Psr\Http\Message\ResponseInterface - */ - return function (Request $request, Response $response, array $args) use ($c) { - $redirect = $c->router->pathFor('dashboard'); - - return $response->withRedirect($redirect, 302); - }; - }; - - /** - * Returns a callback that handles setting the `UF-Redirect` header after a successful login. - */ - $container['redirect.onLogin'] = function ($c) { - /** - * This method is invoked when a user completes the login process. - * - * Returns a callback that handles setting the `UF-Redirect` header after a successful login. - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response - * @param array $args - * @return \Psr\Http\Message\ResponseInterface - */ - return function (Request $request, Response $response, array $args) use ($c) { - // Backwards compatibility for the deprecated determineRedirectOnLogin service - if ($c->has('determineRedirectOnLogin')) { - $determineRedirectOnLogin = $c->determineRedirectOnLogin; - - return $determineRedirectOnLogin($response)->withStatus(200); - } - - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $c->authorizer; - - $currentUser = $c->authenticator->user(); - - if ($authorizer->checkAccess($currentUser, 'uri_account_settings')) { - return $response->withHeader('UF-Redirect', $c->router->pathFor('settings')); - } else { - return $response->withHeader('UF-Redirect', $c->router->pathFor('index')); - } - }; - }; - - /** - * Repository for password reset requests. - */ - $container['repoPasswordReset'] = function ($c) { - $classMapper = $c->classMapper; - $config = $c->config; - - $repo = new PasswordResetRepository($classMapper, $config['password_reset.algorithm']); - return $repo; - }; - - /** - * Repository for verification requests. - */ - $container['repoVerification'] = function ($c) { - $classMapper = $c->classMapper; - $config = $c->config; - - $repo = new VerificationRepository($classMapper, $config['verification.algorithm']); - return $repo; - }; - - /** - * Logger for logging the current user's activities to the database. - * - * Extend this service to push additional handlers onto the 'userActivity' log stack. - */ - $container['userActivityLogger'] = function ($c) { - $classMapper = $c->classMapper; - $config = $c->config; - $session = $c->session; - - $logger = new Logger('userActivity'); - - $handler = new UserActivityDatabaseHandler($classMapper, 'activity'); - - // Note that we get the user id from the session, not the currentUser service. - // This is because the currentUser service may not reflect the actual user during login/logout requests. - $currentUserIdKey = $config['session.keys.current_user_id']; - $userId = isset($session[$currentUserIdKey]) ? $session[$currentUserIdKey] : $config['reserved_user_ids.guest']; - $processor = new UserActivityProcessor($userId); - - $logger->pushProcessor($processor); - $logger->pushHandler($handler); - - return $logger; - }; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\ServicesProvider;
+
+use Birke\Rememberme\Authenticator as RememberMe;
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Monolog\Formatter\LineFormatter;
+use Monolog\Handler\ErrorLogHandler;
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
+use UserFrosting\Sprinkle\Account\Authenticate\AuthGuard;
+use UserFrosting\Sprinkle\Account\Authenticate\Hasher;
+use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager;
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\Account\Log\UserActivityDatabaseHandler;
+use UserFrosting\Sprinkle\Account\Log\UserActivityProcessor;
+use UserFrosting\Sprinkle\Account\Repository\PasswordResetRepository;
+use UserFrosting\Sprinkle\Account\Repository\VerificationRepository;
+use UserFrosting\Sprinkle\Account\Twig\AccountExtension;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Sprinkle\Core\Log\MixedFormatter;
+
+/**
+ * Registers services for the account sprinkle, such as currentUser, etc.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class ServicesProvider
+{
+ /**
+ * Register UserFrosting's account services.
+ *
+ * @param Container $container A DI container implementing ArrayAccess and container-interop.
+ */
+ public function register($container) {
+ /**
+ * Extend the asset manager service to see assets for the current user's theme.
+ */
+ $container->extend('assets', function ($assets, $c) {
+
+ // Register paths for user theme, if a user is logged in
+ // We catch any authorization-related exceptions, so that error pages can be rendered.
+ try {
+ /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $c->authenticator;
+ $currentUser = $c->currentUser;
+ } catch (\Exception $e) {
+ return $assets;
+ }
+
+ if ($authenticator->check()) {
+ $c->sprinkleManager->addResource('assets', $currentUser->theme);
+ }
+
+ return $assets;
+ });
+
+ /**
+ * Extend the 'classMapper' service to register model classes.
+ *
+ * Mappings added: User, Group, Role, Permission, Activity, PasswordReset, Verification
+ */
+ $container->extend('classMapper', function ($classMapper, $c) {
+ $classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\Account\Database\Models\User');
+ $classMapper->setClassMapping('group', 'UserFrosting\Sprinkle\Account\Database\Models\Group');
+ $classMapper->setClassMapping('role', 'UserFrosting\Sprinkle\Account\Database\Models\Role');
+ $classMapper->setClassMapping('permission', 'UserFrosting\Sprinkle\Account\Database\Models\Permission');
+ $classMapper->setClassMapping('activity', 'UserFrosting\Sprinkle\Account\Database\Models\Activity');
+ $classMapper->setClassMapping('password_reset', 'UserFrosting\Sprinkle\Account\Database\Models\PasswordReset');
+ $classMapper->setClassMapping('verification', 'UserFrosting\Sprinkle\Account\Database\Models\Verification');
+ return $classMapper;
+ });
+
+ /**
+ * Extends the 'errorHandler' service with custom exception handlers.
+ *
+ * Custom handlers added: ForbiddenExceptionHandler
+ */
+ $container->extend('errorHandler', function ($handler, $c) {
+ // Register the ForbiddenExceptionHandler.
+ $handler->registerHandler('\UserFrosting\Support\Exception\ForbiddenException', '\UserFrosting\Sprinkle\Account\Error\Handler\ForbiddenExceptionHandler');
+ // Register the AuthExpiredExceptionHandler
+ $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthExpiredExceptionHandler');
+ // Register the AuthCompromisedExceptionHandler.
+ $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthCompromisedExceptionHandler');
+ return $handler;
+ });
+
+ /**
+ * Extends the 'localePathBuilder' service, adding any locale files from the user theme.
+ *
+ */
+ $container->extend('localePathBuilder', function ($pathBuilder, $c) {
+ // Add paths for user theme, if a user is logged in
+ // We catch any authorization-related exceptions, so that error pages can be rendered.
+ try {
+ /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $c->authenticator;
+ $currentUser = $c->currentUser;
+ } catch (\Exception $e) {
+ return $pathBuilder;
+ }
+
+ if ($authenticator->check()) {
+ // Add paths to locale files for user theme
+ $themePath = $c->sprinkleManager->addResource('locale', $currentUser->theme);
+
+ // Add user locale
+ $pathBuilder->addLocales($currentUser->locale);
+ }
+
+ return $pathBuilder;
+ });
+
+ /**
+ * Extends the 'view' service with the AccountExtension for Twig.
+ *
+ * Adds account-specific functions, globals, filters, etc to Twig, and the path to templates for the user theme.
+ */
+ $container->extend('view', function ($view, $c) {
+ $twig = $view->getEnvironment();
+ $extension = new AccountExtension($c);
+ $twig->addExtension($extension);
+
+ // Add paths for user theme, if a user is logged in
+ // We catch any authorization-related exceptions, so that error pages can be rendered.
+ try {
+ /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
+ $authenticator = $c->authenticator;
+ $currentUser = $c->currentUser;
+ } catch (\Exception $e) {
+ return $view;
+ }
+
+ if ($authenticator->check()) {
+ $theme = $currentUser->theme;
+ $themePath = $c->sprinkleManager->addResource('templates', $theme);
+ if ($themePath) {
+ $loader = $twig->getLoader();
+ $loader->prependPath($themePath);
+ // Add namespaced path as well
+ $loader->addPath($themePath, $theme);
+ }
+ }
+
+ return $view;
+ });
+
+ /**
+ * Authentication service.
+ *
+ * Supports logging in users, remembering their sessions, etc.
+ */
+ $container['authenticator'] = function ($c) {
+ $classMapper = $c->classMapper;
+ $config = $c->config;
+ $session = $c->session;
+ $cache = $c->cache;
+
+ // Force database connection to boot up
+ $c->db;
+
+ // Fix RememberMe table name
+ $config['remember_me.table.tableName'] = Capsule::connection()->getTablePrefix() . $config['remember_me.table.tableName'];
+
+ $authenticator = new Authenticator($classMapper, $session, $config, $cache);
+ return $authenticator;
+ };
+
+ /**
+ * Sets up the AuthGuard middleware, used to limit access to authenticated users for certain routes.
+ */
+ $container['authGuard'] = function ($c) {
+ $authenticator = $c->authenticator;
+ return new AuthGuard($authenticator);
+ };
+
+ /**
+ * Authorization check logging with Monolog.
+ *
+ * Extend this service to push additional handlers onto the 'auth' log stack.
+ */
+ $container['authLogger'] = function ($c) {
+ $logger = new Logger('auth');
+
+ $logFile = $c->get('locator')->findResource('log://userfrosting.log', TRUE, TRUE);
+
+ $handler = new StreamHandler($logFile);
+
+ $formatter = new MixedFormatter(NULL, NULL, TRUE);
+
+ $handler->setFormatter($formatter);
+ $logger->pushHandler($handler);
+
+ return $logger;
+ };
+
+ /**
+ * Authorization service.
+ *
+ * Determines permissions for user actions. Extend this service to add additional access condition callbacks.
+ */
+ $container['authorizer'] = function ($c) {
+ $config = $c->config;
+
+ // Default access condition callbacks. Add more in your sprinkle by using $container->extend(...)
+ $callbacks = [
+ /**
+ * Unconditionally grant permission - use carefully!
+ * @return bool returns true no matter what.
+ */
+ 'always' => function () {
+ return TRUE;
+ },
+
+ /**
+ * Check if the specified values are identical to one another (strict comparison).
+ * @param mixed $val1 the first value to compare.
+ * @param mixed $val2 the second value to compare.
+ * @return bool true if the values are strictly equal, false otherwise.
+ */
+ 'equals' => function ($val1, $val2) {
+ return ($val1 === $val2);
+ },
+
+ /**
+ * Check if the specified values are numeric, and if so, if they are equal to each other.
+ * @param mixed $val1 the first value to compare.
+ * @param mixed $val2 the second value to compare.
+ * @return bool true if the values are numeric and equal, false otherwise.
+ */
+ 'equals_num' => function ($val1, $val2) {
+ if (!is_numeric($val1)) {
+ return FALSE;
+ }
+ if (!is_numeric($val2)) {
+ return FALSE;
+ }
+
+ return ($val1 == $val2);
+ },
+
+ /**
+ * Check if the specified user (by user_id) has a particular role.
+ *
+ * @param int $user_id the id of the user.
+ * @param int $role_id the id of the role.
+ * @return bool true if the user has the role, false otherwise.
+ */
+ 'has_role' => function ($user_id, $role_id) {
+ return Capsule::table('role_users')
+ ->where('user_id', $user_id)
+ ->where('role_id', $role_id)
+ ->count() > 0;
+ },
+
+ /**
+ * Check if the specified value $needle is in the values of $haystack.
+ *
+ * @param mixed $needle the value to look for in $haystack
+ * @param array[mixed] $haystack the array of values to search.
+ * @return bool true if $needle is present in the values of $haystack, false otherwise.
+ */
+ 'in' => function ($needle, $haystack) {
+ return in_array($needle, $haystack);
+ },
+
+ /**
+ * Check if the specified user (by user_id) is in a particular group.
+ *
+ * @param int $user_id the id of the user.
+ * @param int $group_id the id of the group.
+ * @return bool true if the user is in the group, false otherwise.
+ */
+ 'in_group' => function ($user_id, $group_id) {
+ $user = User::find($user_id);
+ return ($user->group_id == $group_id);
+ },
+
+ /**
+ * Check if the specified user (by user_id) is the master user.
+ *
+ * @param int $user_id the id of the user.
+ * @return bool true if the user id is equal to the id of the master account, false otherwise.
+ */
+ 'is_master' => function ($user_id) use ($config) {
+ // Need to use loose comparison for now, because some DBs return `id` as a string
+ return ($user_id == $config['reserved_user_ids.master']);
+ },
+
+ /**
+ * Check if all values in the array $needle are present in the values of $haystack.
+ *
+ * @param array[mixed] $needle the array whose values we should look for in $haystack
+ * @param array[mixed] $haystack the array of values to search.
+ * @return bool true if every value in $needle is present in the values of $haystack, false otherwise.
+ */
+ 'subset' => function ($needle, $haystack) {
+ return count($needle) == count(array_intersect($needle, $haystack));
+ },
+
+ /**
+ * Check if all keys of the array $needle are present in the values of $haystack.
+ *
+ * This function is useful for whitelisting an array of key-value parameters.
+ * @param array[mixed] $needle the array whose keys we should look for in $haystack
+ * @param array[mixed] $haystack the array of values to search.
+ * @return bool true if every key in $needle is present in the values of $haystack, false otherwise.
+ */
+ 'subset_keys' => function ($needle, $haystack) {
+ return count($needle) == count(array_intersect(array_keys($needle), $haystack));
+ }
+ ];
+
+ $authorizer = new AuthorizationManager($c, $callbacks);
+ return $authorizer;
+ };
+
+ /**
+ * Loads the User object for the currently logged-in user.
+ */
+ $container['currentUser'] = function ($c) {
+ $authenticator = $c->authenticator;
+
+ return $authenticator->user();
+ };
+
+ $container['passwordHasher'] = function ($c) {
+ $hasher = new Hasher();
+ return $hasher;
+ };
+
+ /**
+ * Returns a callback that forwards to dashboard if user is already logged in.
+ */
+ $container['redirect.onAlreadyLoggedIn'] = function ($c) {
+ /**
+ * This method is invoked when a user attempts to perform certain public actions when they are already logged in.
+ *
+ * Forward to user's landing page or last visited page
+ * @param \Psr\Http\Message\ServerRequestInterface $request
+ * @param \Psr\Http\Message\ResponseInterface $response
+ * @param array $args
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ return function (Request $request, Response $response, array $args) use ($c) {
+ $redirect = $c->router->pathFor('dashboard');
+
+ return $response->withRedirect($redirect, 302);
+ };
+ };
+
+ /**
+ * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
+ */
+ $container['redirect.onLogin'] = function ($c) {
+ /**
+ * This method is invoked when a user completes the login process.
+ *
+ * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
+ * @param \Psr\Http\Message\ServerRequestInterface $request
+ * @param \Psr\Http\Message\ResponseInterface $response
+ * @param array $args
+ * @return \Psr\Http\Message\ResponseInterface
+ */
+ return function (Request $request, Response $response, array $args) use ($c) {
+ // Backwards compatibility for the deprecated determineRedirectOnLogin service
+ if ($c->has('determineRedirectOnLogin')) {
+ $determineRedirectOnLogin = $c->determineRedirectOnLogin;
+
+ return $determineRedirectOnLogin($response)->withStatus(200);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
+ $authorizer = $c->authorizer;
+
+ $currentUser = $c->authenticator->user();
+
+ if ($authorizer->checkAccess($currentUser, 'uri_account_settings')) {
+ return $response->withHeader('UF-Redirect', $c->router->pathFor('settings'));
+ } else {
+ return $response->withHeader('UF-Redirect', $c->router->pathFor('index'));
+ }
+ };
+ };
+
+ /**
+ * Repository for password reset requests.
+ */
+ $container['repoPasswordReset'] = function ($c) {
+ $classMapper = $c->classMapper;
+ $config = $c->config;
+
+ $repo = new PasswordResetRepository($classMapper, $config['password_reset.algorithm']);
+ return $repo;
+ };
+
+ /**
+ * Repository for verification requests.
+ */
+ $container['repoVerification'] = function ($c) {
+ $classMapper = $c->classMapper;
+ $config = $c->config;
+
+ $repo = new VerificationRepository($classMapper, $config['verification.algorithm']);
+ return $repo;
+ };
+
+ /**
+ * Logger for logging the current user's activities to the database.
+ *
+ * Extend this service to push additional handlers onto the 'userActivity' log stack.
+ */
+ $container['userActivityLogger'] = function ($c) {
+ $classMapper = $c->classMapper;
+ $config = $c->config;
+ $session = $c->session;
+
+ $logger = new Logger('userActivity');
+
+ $handler = new UserActivityDatabaseHandler($classMapper, 'activity');
+
+ // Note that we get the user id from the session, not the currentUser service.
+ // This is because the currentUser service may not reflect the actual user during login/logout requests.
+ $currentUserIdKey = $config['session.keys.current_user_id'];
+ $userId = isset($session[$currentUserIdKey]) ? $session[$currentUserIdKey] : $config['reserved_user_ids.guest'];
+ $processor = new UserActivityProcessor($userId);
+
+ $logger->pushProcessor($processor);
+ $logger->pushHandler($handler);
+
+ return $logger;
+ };
+ }
+}
diff --git a/main/app/sprinkles/account/src/Twig/AccountExtension.php b/main/app/sprinkles/account/src/Twig/AccountExtension.php index 287f879..fc94a1a 100644 --- a/main/app/sprinkles/account/src/Twig/AccountExtension.php +++ b/main/app/sprinkles/account/src/Twig/AccountExtension.php @@ -1,62 +1,62 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Twig; - -use Interop\Container\ContainerInterface; -use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; -use Slim\Http\Uri; - -/** - * Extends Twig functionality for the Account sprinkle. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class AccountExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface -{ - - protected $services; - protected $config; - - public function __construct(ContainerInterface $services) { - $this->services = $services; - $this->config = $services->config; - } - - public function getName() { - return 'userfrosting/account'; - } - - public function getFunctions() { - return array( - // Add Twig function for checking permissions during dynamic menu rendering - new \Twig_SimpleFunction('checkAccess', function ($slug, $params = []) { - $authorizer = $this->services->authorizer; - $currentUser = $this->services->currentUser; - - return $authorizer->checkAccess($currentUser, $slug, $params); - }), - new \Twig_SimpleFunction('checkAuthenticated', function () { - $authenticator = $this->services->authenticator; - return $authenticator->check(); - }) - ); - } - - public function getGlobals() { - try { - $currentUser = $this->services->currentUser; - } catch (\Exception $e) { - $currentUser = NULL; - } - - return [ - 'current_user' => $currentUser - ]; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Twig;
+
+use Interop\Container\ContainerInterface;
+use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
+use Slim\Http\Uri;
+
+/**
+ * Extends Twig functionality for the Account sprinkle.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class AccountExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface
+{
+
+ protected $services;
+ protected $config;
+
+ public function __construct(ContainerInterface $services) {
+ $this->services = $services;
+ $this->config = $services->config;
+ }
+
+ public function getName() {
+ return 'userfrosting/account';
+ }
+
+ public function getFunctions() {
+ return array(
+ // Add Twig function for checking permissions during dynamic menu rendering
+ new \Twig_SimpleFunction('checkAccess', function ($slug, $params = []) {
+ $authorizer = $this->services->authorizer;
+ $currentUser = $this->services->currentUser;
+
+ return $authorizer->checkAccess($currentUser, $slug, $params);
+ }),
+ new \Twig_SimpleFunction('checkAuthenticated', function () {
+ $authenticator = $this->services->authenticator;
+ return $authenticator->check();
+ })
+ );
+ }
+
+ public function getGlobals() {
+ try {
+ $currentUser = $this->services->currentUser;
+ } catch (\Exception $e) {
+ $currentUser = NULL;
+ }
+
+ return [
+ 'current_user' => $currentUser
+ ];
+ }
+}
diff --git a/main/app/sprinkles/account/src/Util/HashFailedException.php b/main/app/sprinkles/account/src/Util/HashFailedException.php index 765096b..580bed1 100644 --- a/main/app/sprinkles/account/src/Util/HashFailedException.php +++ b/main/app/sprinkles/account/src/Util/HashFailedException.php @@ -1,22 +1,22 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Util; - -use UserFrosting\Support\Exception\HttpException; - -/** - * Password hash failure exception. Used when the supplied password could not be hashed for some reason. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class HashFailedException extends HttpException -{ - protected $defaultMessage = 'PASSWORD.HASH_FAILED'; - protected $httpErrorCode = 500; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Util;
+
+use UserFrosting\Support\Exception\HttpException;
+
+/**
+ * Password hash failure exception. Used when the supplied password could not be hashed for some reason.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class HashFailedException extends HttpException
+{
+ protected $defaultMessage = 'PASSWORD.HASH_FAILED';
+ protected $httpErrorCode = 500;
+}
diff --git a/main/app/sprinkles/account/src/Util/Util.php b/main/app/sprinkles/account/src/Util/Util.php index f8a0444..f3a08a2 100644 --- a/main/app/sprinkles/account/src/Util/Util.php +++ b/main/app/sprinkles/account/src/Util/Util.php @@ -1,39 +1,39 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Sprinkle\Account\Util; - -use UserFrosting\Sprinkle\Core\Util\Util as CoreUtil; - -/** - * Util Class - * - * Static utility functions for the account Sprinkle. - * - * @author Alex Weissman (https://alexanderweissman.com) - */ -class Util -{ - /** - * Generate a random, unique username from a list of adjectives and nouns. - */ - static public function randomUniqueUsername($classMapper, $maxLength, $maxTries = 10) { - for ($n = 1; $n <= 3; $n++) { - for ($m = 0; $m < 10; $m++) { - // Generate a random phrase with $n adjectives - $suggestion = CoreUtil::randomPhrase($n, $maxLength, $maxTries, '.'); - if (!$classMapper->staticMethod('user', 'where', 'user_name', $suggestion)->first()) { - return $suggestion; - } - } - } - - return ''; - } - -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Sprinkle\Account\Util;
+
+use UserFrosting\Sprinkle\Core\Util\Util as CoreUtil;
+
+/**
+ * Util Class
+ *
+ * Static utility functions for the account Sprinkle.
+ *
+ * @author Alex Weissman (https://alexanderweissman.com)
+ */
+class Util
+{
+ /**
+ * Generate a random, unique username from a list of adjectives and nouns.
+ */
+ static public function randomUniqueUsername($classMapper, $maxLength, $maxTries = 10) {
+ for ($n = 1; $n <= 3; $n++) {
+ for ($m = 0; $m < 10; $m++) {
+ // Generate a random phrase with $n adjectives
+ $suggestion = CoreUtil::randomPhrase($n, $maxLength, $maxTries, '.');
+ if (!$classMapper->staticMethod('user', 'where', 'user_name', $suggestion)->first()) {
+ return $suggestion;
+ }
+ }
+ }
+
+ return '';
+ }
+
+}
diff --git a/main/app/sprinkles/account/templates/forms/settings-account.html.twig b/main/app/sprinkles/account/templates/forms/settings-account.html.twig index 19281d5..7594f28 100644 --- a/main/app/sprinkles/account/templates/forms/settings-account.html.twig +++ b/main/app/sprinkles/account/templates/forms/settings-account.html.twig @@ -1,41 +1,41 @@ -<form id="account-settings" role="form" action="{{ site.uri.public }}/account/settings" method="post"> - <div class="box-header"> - <h3 class="box-title"><i class="fa fa-gear fa-fw"></i> {{ translate("ACCOUNT.SETTINGS") }}</h3> - </div> - <div class="box-body"> - {% include "forms/csrf.html.twig" %} - <!-- Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 --> - <input type="text" style="display:none"> - <input type="password" style="display:none"> - - {% block settings_account %} - <div class="form-group"> - <label for="input-email" class="ccontrol-label">{{ translate("EMAIL") }}</label> - <input type="text" id="input-email" class="form-control" name="email" value="{{ current_user.email }}" - autocomplete="off" placeholder="{{ translate("EMAIL.YOUR") }}" {{ page.visibility }}> - </div> - {% if page.visibility != "disabled" %} - <div class="form-group"> - <label for="input-password" class="control-label">{{ translate("PASSWORD.NEW") }}</label> - <input type="password" id="input-password" class="form-control" name="password" - placeholder="{{ translate("PASSWORD.BETWEEN", {min: 12, max: 100}) }} ({{ translate("OPTIONAL") }})"> - </div> - <div class="form-group"> - <label for="input-passwordc" class="control-label">{{ translate("PASSWORD.CONFIRM_NEW") }}</label> - <input type="password" id="input-passwordc" class="form-control" name="passwordc" - placeholder="{{ translate("PASSWORD.CONFIRM_NEW_HELP") }}"> - </div> - <hr> - <div class="form-group"> - <label for="input-passwordcheck" class="control-label">{{ translate("PASSWORD.CURRENT") }}</label> - <input type="password" id="input-passwordcheck" class="form-control" name="passwordcheck" - placeholder="{{ translate("PASSWORD.CURRENT_EXPLAIN") }}"> - </div> - {% endif %} - {% endblock %} - </div> - <div class="box-footer text-center"> - <button type="reset" class="btn btn-default">{{ translate('RESET') }}</button> - <button type="submit" class="btn btn-primary js-submit">{{ translate('SAVE') }}</button> - </div> +<form id="account-settings" role="form" action="{{ site.uri.public }}/account/settings" method="post">
+ <div class="box-header">
+ <h3 class="box-title"><i class="fa fa-gear fa-fw"></i> {{ translate("ACCOUNT.SETTINGS") }}</h3>
+ </div>
+ <div class="box-body">
+ {% include "forms/csrf.html.twig" %}
+ <!-- Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 -->
+ <input type="text" style="display:none">
+ <input type="password" style="display:none">
+
+ {% block settings_account %}
+ <div class="form-group">
+ <label for="input-email" class="ccontrol-label">{{ translate("EMAIL") }}</label>
+ <input type="text" id="input-email" class="form-control" name="email" value="{{ current_user.email }}"
+ autocomplete="off" placeholder="{{ translate("EMAIL.YOUR") }}" {{ page.visibility }}>
+ </div>
+ {% if page.visibility != "disabled" %}
+ <div class="form-group">
+ <label for="input-password" class="control-label">{{ translate("PASSWORD.NEW") }}</label>
+ <input type="password" id="input-password" class="form-control" name="password"
+ placeholder="{{ translate("PASSWORD.BETWEEN", {min: 12, max: 100}) }} ({{ translate("OPTIONAL") }})">
+ </div>
+ <div class="form-group">
+ <label for="input-passwordc" class="control-label">{{ translate("PASSWORD.CONFIRM_NEW") }}</label>
+ <input type="password" id="input-passwordc" class="form-control" name="passwordc"
+ placeholder="{{ translate("PASSWORD.CONFIRM_NEW_HELP") }}">
+ </div>
+ <hr>
+ <div class="form-group">
+ <label for="input-passwordcheck" class="control-label">{{ translate("PASSWORD.CURRENT") }}</label>
+ <input type="password" id="input-passwordcheck" class="form-control" name="passwordcheck"
+ placeholder="{{ translate("PASSWORD.CURRENT_EXPLAIN") }}">
+ </div>
+ {% endif %}
+ {% endblock %}
+ </div>
+ <div class="box-footer text-center">
+ <button type="reset" class="btn btn-default">{{ translate('RESET') }}</button>
+ <button type="submit" class="btn btn-primary js-submit">{{ translate('SAVE') }}</button>
+ </div>
</form>
\ No newline at end of file diff --git a/main/app/sprinkles/account/templates/forms/settings-profile.html.twig b/main/app/sprinkles/account/templates/forms/settings-profile.html.twig index 09f4e40..a0f1194 100644 --- a/main/app/sprinkles/account/templates/forms/settings-profile.html.twig +++ b/main/app/sprinkles/account/templates/forms/settings-profile.html.twig @@ -1,45 +1,45 @@ -<form id="profile-settings" role="form" action="{{ site.uri.public }}/account/settings/profile" method="post"> - <div class="box-header"> - <h3 class="box-title"><i class="fa fa-user fa-fw"></i> {{ translate("PROFILE.SETTINGS") }}</h3> - </div> - <div class="box-body"> - {% include "forms/csrf.html.twig" %} - - {% block settings_profile %} - <label for="input-first-name" class="control-label">{{ translate("NAME") }}</label> - <div class="row"> - <div class="col-sm-6"> - <div class="form-group"> - <input type="text" id="input-first-name" class="form-control" name="first_name" - value="{{ current_user.first_name }}" - placeholder="{{ translate("FIRST_NAME") }}" {{ page.visibility }}> - </div> - </div> - <div class="col-sm-6"> - <div class="form-group"> - <input type="text" id="input-last-name" class="form-control" name="last_name" - value="{{ current_user.last_name }}" - placeholder="{{ translate("LAST_NAME") }}" {{ page.visibility }}> - </div> - </div> - </div> - - <div class="form-group"> - <label for="input-locale" class="control-label">{{ translate("LOCALE") }}</label> - <select id="input-locale" class="form-control js-select2" name="locale" {{ page.visibility }}> - {% for option, label in locales %} - {% if label is not empty %} - <option value="{{ option }}" - {% if (option == current_user.locale) %}selected{% endif %}>{{ label }}</option> - {% endif %} - {% endfor %} - </select> - <p class="help-block">{{ translate("LOCALE.ACCOUNT") }}.</p> - </div> - {% endblock %} - </div> - <div class="box-footer text-center"> - <button type="reset" class="btn btn-default">{{ translate('RESET') }}</button> - <button type="submit" class="btn btn-primary js-submit">{{ translate('SAVE') }}</button> - </div> -</form> +<form id="profile-settings" role="form" action="{{ site.uri.public }}/account/settings/profile" method="post">
+ <div class="box-header">
+ <h3 class="box-title"><i class="fa fa-user fa-fw"></i> {{ translate("PROFILE.SETTINGS") }}</h3>
+ </div>
+ <div class="box-body">
+ {% include "forms/csrf.html.twig" %}
+
+ {% block settings_profile %}
+ <label for="input-first-name" class="control-label">{{ translate("NAME") }}</label>
+ <div class="row">
+ <div class="col-sm-6">
+ <div class="form-group">
+ <input type="text" id="input-first-name" class="form-control" name="first_name"
+ value="{{ current_user.first_name }}"
+ placeholder="{{ translate("FIRST_NAME") }}" {{ page.visibility }}>
+ </div>
+ </div>
+ <div class="col-sm-6">
+ <div class="form-group">
+ <input type="text" id="input-last-name" class="form-control" name="last_name"
+ value="{{ current_user.last_name }}"
+ placeholder="{{ translate("LAST_NAME") }}" {{ page.visibility }}>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="input-locale" class="control-label">{{ translate("LOCALE") }}</label>
+ <select id="input-locale" class="form-control js-select2" name="locale" {{ page.visibility }}>
+ {% for option, label in locales %}
+ {% if label is not empty %}
+ <option value="{{ option }}"
+ {% if (option == current_user.locale) %}selected{% endif %}>{{ label }}</option>
+ {% endif %}
+ {% endfor %}
+ </select>
+ <p class="help-block">{{ translate("LOCALE.ACCOUNT") }}.</p>
+ </div>
+ {% endblock %}
+ </div>
+ <div class="box-footer text-center">
+ <button type="reset" class="btn btn-default">{{ translate('RESET') }}</button>
+ <button type="submit" class="btn btn-primary js-submit">{{ translate('SAVE') }}</button>
+ </div>
+</form>
diff --git a/main/app/sprinkles/account/templates/mail/password-reset.html.twig b/main/app/sprinkles/account/templates/mail/password-reset.html.twig index 087703d..a1293ce 100644 --- a/main/app/sprinkles/account/templates/mail/password-reset.html.twig +++ b/main/app/sprinkles/account/templates/mail/password-reset.html.twig @@ -1,28 +1,28 @@ -{% block subject %} - {{ site.title }} - your password reset request -{% endblock %} - -{% block body %} - <p>Dear {{ user.first_name }}, - </p> - <p> - A lost password request has been submitted for your account with {{ site.title }} ({{ site.uri.public }}) - on {{ request_date | date('m/d/Y g:i A') }}. - </p> - <p> - If you or someone you trust sent this request, and you wish to set a new password, please click this link: <a - href="{{ site.uri.public }}/account/set-password/confirm?token={{ token }}">{{ site.uri.public }} - /account/set-password/confirm?token={{ token }}</a> - </p> - - <p> - If you did <b>not</b> expect this email, you may click this link to cancel the request: <a - href="{{ site.uri.public }}/account/set-password/deny?token={{ token }}">{{ site.uri.public }} - /account/set-password/deny?token={{ token }}</a>, or simply do nothing and the request will expire on its - own. - </p> - <p> - With regards,<br> - The {{ site.title }} Team - </p> +{% block subject %}
+ {{ site.title }} - your password reset request
+{% endblock %}
+
+{% block body %}
+ <p>Dear {{ user.first_name }},
+ </p>
+ <p>
+ A lost password request has been submitted for your account with {{ site.title }} ({{ site.uri.public }})
+ on {{ request_date | date('m/d/Y g:i A') }}.
+ </p>
+ <p>
+ If you or someone you trust sent this request, and you wish to set a new password, please click this link: <a
+ href="{{ site.uri.public }}/account/set-password/confirm?token={{ token }}">{{ site.uri.public }}
+ /account/set-password/confirm?token={{ token }}</a>
+ </p>
+
+ <p>
+ If you did <b>not</b> expect this email, you may click this link to cancel the request: <a
+ href="{{ site.uri.public }}/account/set-password/deny?token={{ token }}">{{ site.uri.public }}
+ /account/set-password/deny?token={{ token }}</a>, or simply do nothing and the request will expire on its
+ own.
+ </p>
+ <p>
+ With regards,<br>
+ The {{ site.title }} Team
+ </p>
{% endblock %}
\ No newline at end of file diff --git a/main/app/sprinkles/account/templates/mail/resend-verification.html.twig b/main/app/sprinkles/account/templates/mail/resend-verification.html.twig index 56efa21..69e5adb 100644 --- a/main/app/sprinkles/account/templates/mail/resend-verification.html.twig +++ b/main/app/sprinkles/account/templates/mail/resend-verification.html.twig @@ -1,20 +1,20 @@ -{% block subject %} - {{ site.title }} - verify your account -{% endblock %} - -{% block body %} - <p>Dear {{ user.first_name }}, - </p> - <p> - We have received a new verification request for your account with {{ site.title }} ({{ site.uri.public }}). - Please follow the link below to verify your account. If your account is already active, please disregard this - message. - </p> - <a href="{{ site.uri.public }}/account/verify?token={{ token }}">{{ site.uri.public }} - /account/verify?token={{ token }}</a> - </p> - <p> - With regards,<br> - The {{ site.title }} Team - </p> -{% endblock %} +{% block subject %}
+ {{ site.title }} - verify your account
+{% endblock %}
+
+{% block body %}
+ <p>Dear {{ user.first_name }},
+ </p>
+ <p>
+ We have received a new verification request for your account with {{ site.title }} ({{ site.uri.public }}).
+ Please follow the link below to verify your account. If your account is already active, please disregard this
+ message.
+ </p>
+ <a href="{{ site.uri.public }}/account/verify?token={{ token }}">{{ site.uri.public }}
+ /account/verify?token={{ token }}</a>
+ </p>
+ <p>
+ With regards,<br>
+ The {{ site.title }} Team
+ </p>
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/mail/verify-account.html.twig b/main/app/sprinkles/account/templates/mail/verify-account.html.twig index 7a20525..9c003c9 100644 --- a/main/app/sprinkles/account/templates/mail/verify-account.html.twig +++ b/main/app/sprinkles/account/templates/mail/verify-account.html.twig @@ -1,22 +1,22 @@ -{% block subject %} - Welcome to {{ site.title }} - please verify your account -{% endblock %} - -{% block body %} - <p>Dear {{ user.first_name }}, - </p> - <p> - You are receiving this email because you registered with {{ site.title }} ({{ site.uri.public }}). - </p> - <p> - You will need to verify your account before you can login. Please follow the link below to verify your account. - </p> - <p> - <a href="{{ site.uri.public }}/account/verify?token={{ token }}">{{ site.uri.public }} - /account/verify?token={{ token }}</a> - </p> - <p> - With regards,<br> - The {{ site.title }} Team - </p> -{% endblock %} +{% block subject %}
+ Welcome to {{ site.title }} - please verify your account
+{% endblock %}
+
+{% block body %}
+ <p>Dear {{ user.first_name }},
+ </p>
+ <p>
+ You are receiving this email because you registered with {{ site.title }} ({{ site.uri.public }}).
+ </p>
+ <p>
+ You will need to verify your account before you can login. Please follow the link below to verify your account.
+ </p>
+ <p>
+ <a href="{{ site.uri.public }}/account/verify?token={{ token }}">{{ site.uri.public }}
+ /account/verify?token={{ token }}</a>
+ </p>
+ <p>
+ With regards,<br>
+ The {{ site.title }} Team
+ </p>
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/modals/tos.html.twig b/main/app/sprinkles/account/templates/modals/tos.html.twig index 6ef17da..aa67377 100644 --- a/main/app/sprinkles/account/templates/modals/tos.html.twig +++ b/main/app/sprinkles/account/templates/modals/tos.html.twig @@ -1,16 +1,16 @@ -{% extends 'modals/modal.html.twig' %} - -{% block modal_title %} - {{ translate("TOS_FOR", {title: site.title}) }} -{% endblock %} - -{% block modal_body %} - <div class="text-left"> - {% include 'pages/partials/legal.html.twig' %} - {% include 'pages/partials/privacy.html.twig' %} - </div> -{% endblock %} - -{% block modal_footer %} - <button type="button" data-dismiss="modal" class="btn btn-primary btn-block">Got it!</button> -{% endblock %} +{% extends 'modals/modal.html.twig' %}
+
+{% block modal_title %}
+ {{ translate("TOS_FOR", {title: site.title}) }}
+{% endblock %}
+
+{% block modal_body %}
+ <div class="text-left">
+ {% include 'pages/partials/legal.html.twig' %}
+ {% include 'pages/partials/privacy.html.twig' %}
+ </div>
+{% endblock %}
+
+{% block modal_footer %}
+ <button type="button" data-dismiss="modal" class="btn btn-primary btn-block">Got it!</button>
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/navigation/main-nav.html.twig b/main/app/sprinkles/account/templates/navigation/main-nav.html.twig index dfe2fc8..ce18b3a 100644 --- a/main/app/sprinkles/account/templates/navigation/main-nav.html.twig +++ b/main/app/sprinkles/account/templates/navigation/main-nav.html.twig @@ -1,13 +1,13 @@ -{# This extend the same file from core to add a sign-up/sign-in or "my account" link to the "home page" nav menu. #} -{% extends "@core/navigation/main-nav.html.twig" %} - -{% block secondary_nav %} - {{ parent() }} - {% if not checkAuthenticated() %} - <li> - <a href="{{ site.uri.public }}/account/sign-in" class="nav-highlight">{{ translate("SIGNIN") }}</a> - </li> - {% else %} - {% include "navigation/user-card.html.twig" %} - {% endif %} -{% endblock %} +{# This extend the same file from core to add a sign-up/sign-in or "my account" link to the "home page" nav menu. #}
+{% extends "@core/navigation/main-nav.html.twig" %}
+
+{% block secondary_nav %}
+ {{ parent() }}
+ {% if not checkAuthenticated() %}
+ <li>
+ <a href="{{ site.uri.public }}/account/sign-in" class="nav-highlight">{{ translate("SIGNIN") }}</a>
+ </li>
+ {% else %}
+ {% include "navigation/user-card.html.twig" %}
+ {% endif %}
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/navigation/user-card.html.twig b/main/app/sprinkles/account/templates/navigation/user-card.html.twig index 3c1fc3c..6978d7e 100644 --- a/main/app/sprinkles/account/templates/navigation/user-card.html.twig +++ b/main/app/sprinkles/account/templates/navigation/user-card.html.twig @@ -1,35 +1,35 @@ -{% block userCard %} - <li class="dropdown user user-menu"> - {% block userCard_nav %} - <a href="#" class="dropdown-toggle" data-toggle="dropdown"> - <img src="{{ current_user.avatar }}" class="user-image" alt="User Image"> - <span class="hidden-xs">{{ current_user.first_name }} {{ current_user.last_name }}</span> - <i class="fa fa-chevron-down"></i> - </a> - {% endblock %} - <ul class="dropdown-menu"> - {% block userCard_userInfo %} - <!-- User image --> - <li class="user-header"> - <img src="{{ current_user.avatar }}" class="img-circle" alt="User Image"> - <p> - {{ current_user.first_name }} {{ current_user.last_name }} - <small>({{ current_user.user_name }})</small> - </p> - </li> - {% endblock %} - - <!-- Menu Footer--> - <li class="user-footer"> - {% block userCard_menu %} - {% if checkAccess('uri_account_settings') %} - <a href="{{ site.uri.public }}/account/settings" - class="btn btn-default btn-flat btn-block">{{ translate("ACCOUNT.MY") }}</a> - {% endif %} - <a href="{{ site.uri.public }}/account/logout" - class="btn btn-default btn-flat btn-block">{{ translate("LOGOUT") }}</a> - {% endblock %} - </li> - </ul> - </li> -{% endblock %} +{% block userCard %}
+ <li class="dropdown user user-menu">
+ {% block userCard_nav %}
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+ <img src="{{ current_user.avatar }}" class="user-image" alt="User Image">
+ <span class="hidden-xs">{{ current_user.first_name }} {{ current_user.last_name }}</span>
+ <i class="fa fa-chevron-down"></i>
+ </a>
+ {% endblock %}
+ <ul class="dropdown-menu">
+ {% block userCard_userInfo %}
+ <!-- User image -->
+ <li class="user-header">
+ <img src="{{ current_user.avatar }}" class="img-circle" alt="User Image">
+ <p>
+ {{ current_user.first_name }} {{ current_user.last_name }}
+ <small>({{ current_user.user_name }})</small>
+ </p>
+ </li>
+ {% endblock %}
+
+ <!-- Menu Footer-->
+ <li class="user-footer">
+ {% block userCard_menu %}
+ {% if checkAccess('uri_account_settings') %}
+ <a href="{{ site.uri.public }}/account/settings"
+ class="btn btn-default btn-flat btn-block">{{ translate("ACCOUNT.MY") }}</a>
+ {% endif %}
+ <a href="{{ site.uri.public }}/account/logout"
+ class="btn btn-default btn-flat btn-block">{{ translate("LOGOUT") }}</a>
+ {% endblock %}
+ </li>
+ </ul>
+ </li>
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/pages/account-settings.html.twig b/main/app/sprinkles/account/templates/pages/account-settings.html.twig index cfe82c1..4d8bf7a 100644 --- a/main/app/sprinkles/account/templates/pages/account-settings.html.twig +++ b/main/app/sprinkles/account/templates/pages/account-settings.html.twig @@ -1,45 +1,45 @@ -{% extends forcedLayout ? forcedLayout : "pages/abstract/default.html.twig" %} - -{% set page_active = "account-settings" %} - -{% block stylesheets_page %} - <!-- Page-specific CSS asset bundle --> - {{ assets.css('css/form-widgets') | raw }} -{% endblock %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{ translate("ACCOUNT.SETTINGS") }}{% endblock %} - -{% block page_description %}{{ translate("ACCOUNT.SETTINGS.DESCRIPTION") }}{% endblock %} - -{% block body_matter %} - - <div class="row"> - <div class="col-lg-6"> - {% block settings_profile_box %} - <div class="box box-primary"> - {% include "forms/settings-profile.html.twig" %} - </div> - {% endblock %} - </div> - <div class="col-lg-6"> - {% block settings_account_box %} - <div class="box box-primary"> - {% include "forms/settings-account.html.twig" %} - </div> - {% endblock %} - </div> - </div> -{% endblock %} -{% block scripts_page %} - <!-- Include validation rules --> - <script> - {% include "pages/partials/page.js.twig" %} - </script> - - <!-- Include form widgets JS --> - {{ assets.js('js/form-widgets') | raw }} - - <!-- Include page-specific JS --> - {{ assets.js('js/pages/account-settings') | raw }} +{% extends forcedLayout ? forcedLayout : "pages/abstract/default.html.twig" %}
+
+{% set page_active = "account-settings" %}
+
+{% block stylesheets_page %}
+ <!-- Page-specific CSS asset bundle -->
+ {{ assets.css('css/form-widgets') | raw }}
+{% endblock %}
+
+{# Overrides blocks in head of base template #}
+{% block page_title %}{{ translate("ACCOUNT.SETTINGS") }}{% endblock %}
+
+{% block page_description %}{{ translate("ACCOUNT.SETTINGS.DESCRIPTION") }}{% endblock %}
+
+{% block body_matter %}
+
+ <div class="row">
+ <div class="col-lg-6">
+ {% block settings_profile_box %}
+ <div class="box box-primary">
+ {% include "forms/settings-profile.html.twig" %}
+ </div>
+ {% endblock %}
+ </div>
+ <div class="col-lg-6">
+ {% block settings_account_box %}
+ <div class="box box-primary">
+ {% include "forms/settings-account.html.twig" %}
+ </div>
+ {% endblock %}
+ </div>
+ </div>
+{% endblock %}
+{% block scripts_page %}
+ <!-- Include validation rules -->
+ <script>
+ {% include "pages/partials/page.js.twig" %}
+ </script>
+
+ <!-- Include form widgets JS -->
+ {{ assets.js('js/form-widgets') | raw }}
+
+ <!-- Include page-specific JS -->
+ {{ assets.js('js/pages/account-settings') | raw }}
{% endblock %}
\ No newline at end of file diff --git a/main/app/sprinkles/account/templates/pages/error/compromised.html.twig b/main/app/sprinkles/account/templates/pages/error/compromised.html.twig index c12aa7d..caea258 100644 --- a/main/app/sprinkles/account/templates/pages/error/compromised.html.twig +++ b/main/app/sprinkles/account/templates/pages/error/compromised.html.twig @@ -1,11 +1,11 @@ -{% extends "pages/abstract/error.html.twig" %} - -{% block page_title %}{{ translate('ACCOUNT.SESSION_COMPROMISED.TITLE') }}{% endblock %} - -{% block page_description %}{{ translate('ACCOUNT.SESSION_COMPROMISED.TITLE') }}{% endblock %} - -{% block heading %} - <i class="fa fa-warning text-yellow"></i> {{ translate('ACCOUNT.SESSION_COMPROMISED.TEXT', { - 'url' : site.uri.public ~ '/account/sign-in' -}) | raw }} -{% endblock %} +{% extends "pages/abstract/error.html.twig" %}
+
+{% block page_title %}{{ translate('ACCOUNT.SESSION_COMPROMISED.TITLE') }}{% endblock %}
+
+{% block page_description %}{{ translate('ACCOUNT.SESSION_COMPROMISED.TITLE') }}{% endblock %}
+
+{% block heading %}
+ <i class="fa fa-warning text-yellow"></i> {{ translate('ACCOUNT.SESSION_COMPROMISED.TEXT', {
+ 'url' : site.uri.public ~ '/account/sign-in'
+}) | raw }}
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/pages/forgot-password.html.twig b/main/app/sprinkles/account/templates/pages/forgot-password.html.twig index 2c890a1..a709f7c 100644 --- a/main/app/sprinkles/account/templates/pages/forgot-password.html.twig +++ b/main/app/sprinkles/account/templates/pages/forgot-password.html.twig @@ -1,49 +1,49 @@ -{% extends "pages/abstract/base.html.twig" %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{ translate("PASSWORD.FORGOTTEN") }}{% endblock %} - -{% block page_description %}{{ translate("PASSWORD.FORGET.PAGE") }}{% endblock %} - -{% block body_attributes %} - class="hold-transition login-page" -{% endblock %} - -{% block content %} -<div class="login-box"> - <div class="login-logo"> - <a href="{{ site.uri.public }}">{{ site.title }}</a> - </div> - <!-- /.login-logo --> - - <div class="login-box-body login-form"> - <p class="login-box-msg"><strong>{{ translate("PASSWORD.FORGOTTEN") }}</strong></p> - <p class="login-box-msg">{{ translate("PASSWORD.FORGET.EMAIL") }}</p> - - <div class="form-alerts" id="alerts-page"></div> - - <form id="request-password-reset" role="form" action="{{ site.uri.public }}/account/forgot-password" - method="post" class="r-form"> - {% include "forms/csrf.html.twig" %} - <div class="form-group"> - <label class="sr-only" for="reset-form-email">{{ translate("EMAIL") }}</label> - <input type="text" name="email" placeholder="{{ translate("EMAIL") }}" class="form-control" - id="reset-form-email"> - </div> - <button type="submit" - class="btn btn-block btn-primary">{{ translate("PASSWORD.FORGET.EMAIL_SEND") }}</button> - </form> - </div> - <!-- /.login-box-body --> - {% endblock %} - - {% block scripts_page %} - <!-- Include validation rules --> - <script> - {% include "pages/partials/page.js.twig" %} - </script> - - <!-- Include page-specific JS bundle --> - {{ assets.js('js/pages/forgot-password') | raw }} - - {% endblock %} +{% extends "pages/abstract/base.html.twig" %}
+
+{# Overrides blocks in head of base template #}
+{% block page_title %}{{ translate("PASSWORD.FORGOTTEN") }}{% endblock %}
+
+{% block page_description %}{{ translate("PASSWORD.FORGET.PAGE") }}{% endblock %}
+
+{% block body_attributes %}
+ class="hold-transition login-page"
+{% endblock %}
+
+{% block content %}
+<div class="login-box">
+ <div class="login-logo">
+ <a href="{{ site.uri.public }}">{{ site.title }}</a>
+ </div>
+ <!-- /.login-logo -->
+
+ <div class="login-box-body login-form">
+ <p class="login-box-msg"><strong>{{ translate("PASSWORD.FORGOTTEN") }}</strong></p>
+ <p class="login-box-msg">{{ translate("PASSWORD.FORGET.EMAIL") }}</p>
+
+ <div class="form-alerts" id="alerts-page"></div>
+
+ <form id="request-password-reset" role="form" action="{{ site.uri.public }}/account/forgot-password"
+ method="post" class="r-form">
+ {% include "forms/csrf.html.twig" %}
+ <div class="form-group">
+ <label class="sr-only" for="reset-form-email">{{ translate("EMAIL") }}</label>
+ <input type="text" name="email" placeholder="{{ translate("EMAIL") }}" class="form-control"
+ id="reset-form-email">
+ </div>
+ <button type="submit"
+ class="btn btn-block btn-primary">{{ translate("PASSWORD.FORGET.EMAIL_SEND") }}</button>
+ </form>
+ </div>
+ <!-- /.login-box-body -->
+ {% endblock %}
+
+ {% block scripts_page %}
+ <!-- Include validation rules -->
+ <script>
+ {% include "pages/partials/page.js.twig" %}
+ </script>
+
+ <!-- Include page-specific JS bundle -->
+ {{ assets.js('js/pages/forgot-password') | raw }}
+
+ {% endblock %}
diff --git a/main/app/sprinkles/account/templates/pages/register.html.twig b/main/app/sprinkles/account/templates/pages/register.html.twig index bcfc253..7f0b878 100644 --- a/main/app/sprinkles/account/templates/pages/register.html.twig +++ b/main/app/sprinkles/account/templates/pages/register.html.twig @@ -1,117 +1,117 @@ -{% extends "pages/abstract/base.html.twig" %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{ translate('REGISTER') }}{% endblock %} - -{% block page_description %}{{ translate('PAGE.LOGIN.DESCRIPTION', {'site_name': site.title }) }}{% endblock %} - -{% block body_attributes %} - class="hold-transition login-page" -{% endblock %} - -{% block content %} - <div class="login-box"> - <div class="login-logo"> - <a href="{{ site.uri.public }}">{{ site.title }}</a> - </div> - <!-- /.login-logo --> - - <div class="login-box-body register-form"> - <p class="login-box-msg"><strong>{{ translate('REGISTER') }}</strong></p> - <div class="form-alerts" id="alerts-page"></div> - - <form id="register" role="form" action="{{ site.uri.public }}/account/register" method="post" - class="r-form"> - {% include "forms/csrf.html.twig" %} - <label for="r-form-first-name">{{ translate('NAME_AND_EMAIL') }}</label> - <div class="row"> - <div class="col-md-6"> - <div class="form-group"> - <label class="sr-only" for="r-form-first-name">{{ translate('FIRST_NAME') }}</label> - <input type="text" name="first_name" placeholder="{{ translate('FIRST_NAME') }}" - class="form-control" id="r-form-first-name" autocomplete="off"> - </div> - </div> - <div class="col-md-6"> - <div class="form-group"> - <label class="sr-only" for="r-form-last-name">{{ translate('LAST_NAME') }}</label> - <input type="text" name="last_name" placeholder="{{ translate('LAST_NAME') }}" - class="form-control" id="r-form-last-name" autocomplete="off"> - </div> - </div> - </div> - <div class="form-group"> - <input type="text" name="email" - placeholder="{% if site.registration.require_email_verification %}{{ translate('EMAIL.VERIFICATION_REQUIRED') }}{% else %}{{ translate('EMAIL.YOUR') }}{% endif %}" - class="form-control" id="r-form-email"> - </div> - <div class="form-group"> - <label for="r-form-username">{{ translate('USERNAME') }}</label> - <span class="pull-right"><a href="#" id="form-register-username-suggest">[{{ translate('SUGGEST') }} - ]</a></span> - <input type="text" name="user_name" placeholder="{{ translate('USERNAME.CHOOSE') }}" - class="form-control" id="r-form-username" autocomplete="off"> - </div> - <div class="form-group"> - <label for="r-form-password">{{ translate('PASSWORD') }}</label> - <input type="password" name="password" - placeholder="{{ translate('PASSWORD.BETWEEN', {min: 12, max: 100}) }}" class="form-control" - id="r-form-password"> - </div> - <div class="form-group"> - <label class="sr-only" for="r-form-passwordc">{{ translate('PASSWORD.CONFIRM') }}</label> - <input type="password" name="passwordc" placeholder="{{ translate('PASSWORD.CONFIRM') }}" - class="form-control" id="r-form-passwordc"> - </div> - {% if site.registration.captcha %} - <div class="form-group"> - <label class="sr-only" for="r-form-passwordc">{{ translate('CAPTCHA.VERIFY') }}</label> - <div class="row"> - <div class="col-md-6"> - <input type="text" name="captcha" placeholder="{{ translate('CAPTCHA.SPECIFY') }}" - class="form-control" id="r-form-captcha"> - </div> - <div class="col-md-6 form-col-captcha"> - <img src="{{ site.uri.public }}/account/captcha" id="captcha" - data-target="#r-form-captcha"> - </div> - </div> - </div> - {% endif %} - <div class="collapse"> - <label>Spiderbro: Don't change me bro, I'm tryin'a catch some flies!</label> - <input name="spiderbro" id="spiderbro" value="http://" /> - </div> - <div class="text-left"> - <p> - {{ translate('TOS_AGREEMENT', { - 'site_title' : site.title, - 'link_attributes' : 'class="js-show-tos" href="#" data-toggle="modal"' - }) | raw }} - </p> - </div> - <div> - <button type="submit" class="btn btn-block btn-primary">{{ translate('REGISTER_ME') }}</button> - </div> - <div style="padding-top: 10px;"> - {{ translate('SIGN_IN_HERE', { - 'url' : site.uri.public ~'/account/sign-in' - }) | raw }} - </div> - </form> - </div> - <!-- /.login-box-body --> - - </div> - <!-- /.login-box --> -{% endblock %} - -{% block scripts_page %} - <!-- Include validation rules --> - <script> - {% include "pages/partials/page.js.twig" %} - </script> - - <!-- Include page-specific JS --> - {{ assets.js('js/pages/register') | raw }} -{% endblock %} +{% extends "pages/abstract/base.html.twig" %}
+
+{# Overrides blocks in head of base template #}
+{% block page_title %}{{ translate('REGISTER') }}{% endblock %}
+
+{% block page_description %}{{ translate('PAGE.LOGIN.DESCRIPTION', {'site_name': site.title }) }}{% endblock %}
+
+{% block body_attributes %}
+ class="hold-transition login-page"
+{% endblock %}
+
+{% block content %}
+ <div class="login-box">
+ <div class="login-logo">
+ <a href="{{ site.uri.public }}">{{ site.title }}</a>
+ </div>
+ <!-- /.login-logo -->
+
+ <div class="login-box-body register-form">
+ <p class="login-box-msg"><strong>{{ translate('REGISTER') }}</strong></p>
+ <div class="form-alerts" id="alerts-page"></div>
+
+ <form id="register" role="form" action="{{ site.uri.public }}/account/register" method="post"
+ class="r-form">
+ {% include "forms/csrf.html.twig" %}
+ <label for="r-form-first-name">{{ translate('NAME_AND_EMAIL') }}</label>
+ <div class="row">
+ <div class="col-md-6">
+ <div class="form-group">
+ <label class="sr-only" for="r-form-first-name">{{ translate('FIRST_NAME') }}</label>
+ <input type="text" name="first_name" placeholder="{{ translate('FIRST_NAME') }}"
+ class="form-control" id="r-form-first-name" autocomplete="off">
+ </div>
+ </div>
+ <div class="col-md-6">
+ <div class="form-group">
+ <label class="sr-only" for="r-form-last-name">{{ translate('LAST_NAME') }}</label>
+ <input type="text" name="last_name" placeholder="{{ translate('LAST_NAME') }}"
+ class="form-control" id="r-form-last-name" autocomplete="off">
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <input type="text" name="email"
+ placeholder="{% if site.registration.require_email_verification %}{{ translate('EMAIL.VERIFICATION_REQUIRED') }}{% else %}{{ translate('EMAIL.YOUR') }}{% endif %}"
+ class="form-control" id="r-form-email">
+ </div>
+ <div class="form-group">
+ <label for="r-form-username">{{ translate('USERNAME') }}</label>
+ <span class="pull-right"><a href="#" id="form-register-username-suggest">[{{ translate('SUGGEST') }}
+ ]</a></span>
+ <input type="text" name="user_name" placeholder="{{ translate('USERNAME.CHOOSE') }}"
+ class="form-control" id="r-form-username" autocomplete="off">
+ </div>
+ <div class="form-group">
+ <label for="r-form-password">{{ translate('PASSWORD') }}</label>
+ <input type="password" name="password"
+ placeholder="{{ translate('PASSWORD.BETWEEN', {min: 12, max: 100}) }}" class="form-control"
+ id="r-form-password">
+ </div>
+ <div class="form-group">
+ <label class="sr-only" for="r-form-passwordc">{{ translate('PASSWORD.CONFIRM') }}</label>
+ <input type="password" name="passwordc" placeholder="{{ translate('PASSWORD.CONFIRM') }}"
+ class="form-control" id="r-form-passwordc">
+ </div>
+ {% if site.registration.captcha %}
+ <div class="form-group">
+ <label class="sr-only" for="r-form-passwordc">{{ translate('CAPTCHA.VERIFY') }}</label>
+ <div class="row">
+ <div class="col-md-6">
+ <input type="text" name="captcha" placeholder="{{ translate('CAPTCHA.SPECIFY') }}"
+ class="form-control" id="r-form-captcha">
+ </div>
+ <div class="col-md-6 form-col-captcha">
+ <img src="{{ site.uri.public }}/account/captcha" id="captcha"
+ data-target="#r-form-captcha">
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ <div class="collapse">
+ <label>Spiderbro: Don't change me bro, I'm tryin'a catch some flies!</label>
+ <input name="spiderbro" id="spiderbro" value="http://" />
+ </div>
+ <div class="text-left">
+ <p>
+ {{ translate('TOS_AGREEMENT', {
+ 'site_title' : site.title,
+ 'link_attributes' : 'class="js-show-tos" href="#" data-toggle="modal"'
+ }) | raw }}
+ </p>
+ </div>
+ <div>
+ <button type="submit" class="btn btn-block btn-primary">{{ translate('REGISTER_ME') }}</button>
+ </div>
+ <div style="padding-top: 10px;">
+ {{ translate('SIGN_IN_HERE', {
+ 'url' : site.uri.public ~'/account/sign-in'
+ }) | raw }}
+ </div>
+ </form>
+ </div>
+ <!-- /.login-box-body -->
+
+ </div>
+ <!-- /.login-box -->
+{% endblock %}
+
+{% block scripts_page %}
+ <!-- Include validation rules -->
+ <script>
+ {% include "pages/partials/page.js.twig" %}
+ </script>
+
+ <!-- Include page-specific JS -->
+ {{ assets.js('js/pages/register') | raw }}
+{% endblock %}
diff --git a/main/app/sprinkles/account/templates/pages/resend-verification.html.twig b/main/app/sprinkles/account/templates/pages/resend-verification.html.twig index 4bf611c..9b5c55a 100644 --- a/main/app/sprinkles/account/templates/pages/resend-verification.html.twig +++ b/main/app/sprinkles/account/templates/pages/resend-verification.html.twig @@ -1,49 +1,49 @@ -{% extends "pages/abstract/base.html.twig" %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{ translate("ACCOUNT.VERIFICATION.RESEND") }}{% endblock %} - -{% block page_description %}{{ translate("ACCOUNT.VERIFICATION.PAGE") }}{% endblock %} - -{% block body_attributes %} - class="hold-transition login-page" -{% endblock %} - -{% block content %} -<div class="login-box"> - <div class="login-logo"> - <a href="{{ site.uri.public }}">{{ site.title }}</a> - </div> - <!-- /.login-logo --> - - <div class="login-box-body login-form"> - <p class="login-box-msg"><strong>{{ translate("ACCOUNT.VERIFICATION.RESEND") }}</strong></p> - <p class="login-box-msg">{{ translate("ACCOUNT.VERIFICATION.EMAIL") }}</p> - - <div class="form-alerts" id="alerts-page"></div> - - <form id="request-verification-email" role="form" action="{{ site.uri.public }}/account/resend-verification" - method="post" class="r-form"> - {% include "forms/csrf.html.twig" %} - <div class="form-group"> - <label class="sr-only" for="verification-form-email">{{ translate("EMAIL") }}</label> - <input type="text" name="email" placeholder="{{ translate("EMAIL") }}" class="form-control" - id="verification-form-email"> - </div> - <button type="submit" - class="btn btn-block btn-primary">{{ translate("ACCOUNT.VERIFICATION.SEND") }}</button> - </form> - </div> - <!-- /.login-box-body --> - {% endblock %} - - {% block scripts_page %} - <!-- Include validation rules --> - <script> - {% include "pages/partials/page.js.twig" %} - </script> - - <!-- Include page-specific JS --> - {{ assets.js('js/pages/resend-verification') | raw }} - - {% endblock %} +{% extends "pages/abstract/base.html.twig" %}
+
+{# Overrides blocks in head of base template #}
+{% block page_title %}{{ translate("ACCOUNT.VERIFICATION.RESEND") }}{% endblock %}
+
+{% block page_description %}{{ translate("ACCOUNT.VERIFICATION.PAGE") }}{% endblock %}
+
+{% block body_attributes %}
+ class="hold-transition login-page"
+{% endblock %}
+
+{% block content %}
+<div class="login-box">
+ <div class="login-logo">
+ <a href="{{ site.uri.public }}">{{ site.title }}</a>
+ </div>
+ <!-- /.login-logo -->
+
+ <div class="login-box-body login-form">
+ <p class="login-box-msg"><strong>{{ translate("ACCOUNT.VERIFICATION.RESEND") }}</strong></p>
+ <p class="login-box-msg">{{ translate("ACCOUNT.VERIFICATION.EMAIL") }}</p>
+
+ <div class="form-alerts" id="alerts-page"></div>
+
+ <form id="request-verification-email" role="form" action="{{ site.uri.public }}/account/resend-verification"
+ method="post" class="r-form">
+ {% include "forms/csrf.html.twig" %}
+ <div class="form-group">
+ <label class="sr-only" for="verification-form-email">{{ translate("EMAIL") }}</label>
+ <input type="text" name="email" placeholder="{{ translate("EMAIL") }}" class="form-control"
+ id="verification-form-email">
+ </div>
+ <button type="submit"
+ class="btn btn-block btn-primary">{{ translate("ACCOUNT.VERIFICATION.SEND") }}</button>
+ </form>
+ </div>
+ <!-- /.login-box-body -->
+ {% endblock %}
+
+ {% block scripts_page %}
+ <!-- Include validation rules -->
+ <script>
+ {% include "pages/partials/page.js.twig" %}
+ </script>
+
+ <!-- Include page-specific JS -->
+ {{ assets.js('js/pages/resend-verification') | raw }}
+
+ {% endblock %}
diff --git a/main/app/sprinkles/account/templates/pages/reset-password.html.twig b/main/app/sprinkles/account/templates/pages/reset-password.html.twig index 71f6f02..c1cda61 100644 --- a/main/app/sprinkles/account/templates/pages/reset-password.html.twig +++ b/main/app/sprinkles/account/templates/pages/reset-password.html.twig @@ -1,60 +1,60 @@ -{% extends "pages/abstract/base.html.twig" %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{ translate("PASSWORD.RESET") }}{% endblock %} - -{% block page_description %}{{ translate("PASSWORD.RESET.PAGE") }}{% endblock %} - -{% block body_attributes %} - class="hold-transition login-page" -{% endblock %} - -{% block content %} -<div class="login-box"> - <div class="login-logo"> - <a href="{{ site.uri.public }}">{{ site.title }}</a> - </div> - <!-- /.login-logo --> - - <div class="login-box-body login-form"> - <p class="login-box-msg"><strong>{{ translate("PASSWORD.RESET") }}</strong></p> - <p class="login-box-msg">{{ translate("PASSWORD.RESET.CHOOSE") }}</p> - - <div class="form-alerts" id="alerts-page"></div> - - <form id="set-or-reset-password" role="form" action="{{ site.uri.public }}/account/set-password" method="post" - class="r-form"> - {% include "forms/csrf.html.twig" %} - {# Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 #} - <input type="text" style="display:none"> - <input type="password" style="display:none"> - - <div class="form-group"> - <label class="sr-only" for="form-password">{{ translate("PASSWORD.NEW") }}</label> - <input type="password" name="password" - placeholder="{{ translate("PASSWORD.BETWEEN", {min: 12, max: 100}) }}" class="form-control" - id="form-password"> - </div> - - <div class="form-group"> - <label class="sr-only" for="form-passwordc">{{ translate("PASSWORD.CONFIRM_NEW") }}</label> - <input type="password" name="passwordc" placeholder="{{ translate("PASSWORD.CONFIRM_NEW_EXPLAIN") }}" - class="form-control" id="form-passwordc"> - </div> - <input type="hidden" name="token" value="{{ token }}"> - <button type="submit" class="btn btn-block btn-primary">{{ translate("PASSWORD.RESET.SEND") }}</button> - </form> - </div> - <!-- /.login-box-body --> - {% endblock %} - - {% block scripts_page %} - <!-- Include validation rules --> - <script> - {% include "pages/partials/page.js.twig" %} - </script> - - <!-- Include page-specific JS bundle --> - {{ assets.js('js/pages/set-or-reset-password') | raw }} - - {% endblock %} +{% extends "pages/abstract/base.html.twig" %}
+
+{# Overrides blocks in head of base template #}
+{% block page_title %}{{ translate("PASSWORD.RESET") }}{% endblock %}
+
+{% block page_description %}{{ translate("PASSWORD.RESET.PAGE") }}{% endblock %}
+
+{% block body_attributes %}
+ class="hold-transition login-page"
+{% endblock %}
+
+{% block content %}
+<div class="login-box">
+ <div class="login-logo">
+ <a href="{{ site.uri.public }}">{{ site.title }}</a>
+ </div>
+ <!-- /.login-logo -->
+
+ <div class="login-box-body login-form">
+ <p class="login-box-msg"><strong>{{ translate("PASSWORD.RESET") }}</strong></p>
+ <p class="login-box-msg">{{ translate("PASSWORD.RESET.CHOOSE") }}</p>
+
+ <div class="form-alerts" id="alerts-page"></div>
+
+ <form id="set-or-reset-password" role="form" action="{{ site.uri.public }}/account/set-password" method="post"
+ class="r-form">
+ {% include "forms/csrf.html.twig" %}
+ {# Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 #}
+ <input type="text" style="display:none">
+ <input type="password" style="display:none">
+
+ <div class="form-group">
+ <label class="sr-only" for="form-password">{{ translate("PASSWORD.NEW") }}</label>
+ <input type="password" name="password"
+ placeholder="{{ translate("PASSWORD.BETWEEN", {min: 12, max: 100}) }}" class="form-control"
+ id="form-password">
+ </div>
+
+ <div class="form-group">
+ <label class="sr-only" for="form-passwordc">{{ translate("PASSWORD.CONFIRM_NEW") }}</label>
+ <input type="password" name="passwordc" placeholder="{{ translate("PASSWORD.CONFIRM_NEW_EXPLAIN") }}"
+ class="form-control" id="form-passwordc">
+ </div>
+ <input type="hidden" name="token" value="{{ token }}">
+ <button type="submit" class="btn btn-block btn-primary">{{ translate("PASSWORD.RESET.SEND") }}</button>
+ </form>
+ </div>
+ <!-- /.login-box-body -->
+ {% endblock %}
+
+ {% block scripts_page %}
+ <!-- Include validation rules -->
+ <script>
+ {% include "pages/partials/page.js.twig" %}
+ </script>
+
+ <!-- Include page-specific JS bundle -->
+ {{ assets.js('js/pages/set-or-reset-password') | raw }}
+
+ {% endblock %}
diff --git a/main/app/sprinkles/account/templates/pages/sign-in.html.twig b/main/app/sprinkles/account/templates/pages/sign-in.html.twig index 4e2e21c..60743cb 100644 --- a/main/app/sprinkles/account/templates/pages/sign-in.html.twig +++ b/main/app/sprinkles/account/templates/pages/sign-in.html.twig @@ -1,90 +1,90 @@ -{% extends "pages/abstract/base.html.twig" %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{ translate('SIGNIN') }}{% endblock %} - -{% block page_description %}{{ translate('PAGE.LOGIN.DESCRIPTION', {'site_name': site.title }) }}{% endblock %} - -{% block body_attributes %} - class="hold-transition login-page" -{% endblock %} - -{% block content %} - <div class="login-box"> - <div class="login-logo"> - <a href="{{ site.uri.public }}">{{ site.title }}</a> - </div> - <!-- /.login-logo --> - - <div class="login-box-body login-form"> - <p class="login-box-msg"><strong>{{ translate('SIGNIN') }}</strong></p> - - <div class="form-alerts" id="alerts-page"></div> - - <form action="{{ site.uri.public }}/account/login" id="sign-in" method="post"> - {% include "forms/csrf.html.twig" %} - <div class="form-group has-feedback"> - <input type="text" class="form-control" - placeholder="{% if site.login.enable_email %}{{ translate('EMAIL_OR_USERNAME') }}{% else %}{{ translate('USERNAME') }}{% endif %}" - name="user_name"> - <i class="glyphicon glyphicon-user form-control-icon" aria-hidden="true"></i> - </div> - <div class="form-group has-feedback"> - <input type="password" class="form-control" placeholder="{{ translate('PASSWORD') }}" - name="password"> - <i class="glyphicon glyphicon-lock form-control-icon" aria-hidden="true"></i> - </div> - <div class="row"> - <div class="col-xs-8"> - <div class="checkbox icheck"> - <label> - <input type="checkbox" class="js-icheck" - name="rememberme"> {{ translate('REMEMBER_ME') }} - </label> - </div> - </div> - <!-- /.col --> - <div class="col-xs-4"> - <button type="submit" - class="btn btn-primary btn-block btn-flat">{{ translate('LOGIN') }}</button> - </div> - <!-- /.col --> - </div> - </form> - - <a href="{{ site.uri.public }}/account/forgot-password">{{ translate('PASSWORD.FORGET') }}</a><br> - {% if site.registration.require_email_verification %} - <a href="{{ site.uri.public }}/account/resend-verification">{{ translate('ACCOUNT.VERIFICATION.RESEND') }}</a> - <br> - {% endif %} - {% if site.registration.enabled %} - <a href="{{ site.uri.public }}/account/register">{{ translate('REGISTER') }}</a> - {% endif %} - - </div> - <!-- /.login-box-body --> - </div> - <!-- /.login-box --> -{% endblock %} - -{% block scripts_page %} - <!-- Include validation rules --> - <script> - {% include "pages/partials/page.js.twig" %} - </script> - - <script> - site = $.extend( - true, // deep extend - { - "registration": { - "enabled": "{{ site.registration.enabled }}" - } - }, - site - ); - </script> - - <!-- Include page-specific JS --> - {{ assets.js('js/pages/sign-in') | raw }} -{% endblock %} +{% extends "pages/abstract/base.html.twig" %}
+
+{# Overrides blocks in head of base template #}
+{% block page_title %}{{ translate('SIGNIN') }}{% endblock %}
+
+{% block page_description %}{{ translate('PAGE.LOGIN.DESCRIPTION', {'site_name': site.title }) }}{% endblock %}
+
+{% block body_attributes %}
+ class="hold-transition login-page"
+{% endblock %}
+
+{% block content %}
+ <div class="login-box">
+ <div class="login-logo">
+ <a href="{{ site.uri.public }}">{{ site.title }}</a>
+ </div>
+ <!-- /.login-logo -->
+
+ <div class="login-box-body login-form">
+ <p class="login-box-msg"><strong>{{ translate('SIGNIN') }}</strong></p>
+
+ <div class="form-alerts" id="alerts-page"></div>
+
+ <form action="{{ site.uri.public }}/account/login" id="sign-in" method="post">
+ {% include "forms/csrf.html.twig" %}
+ <div class="form-group has-feedback">
+ <input type="text" class="form-control"
+ placeholder="{% if site.login.enable_email %}{{ translate('EMAIL_OR_USERNAME') }}{% else %}{{ translate('USERNAME') }}{% endif %}"
+ name="user_name">
+ <i class="glyphicon glyphicon-user form-control-icon" aria-hidden="true"></i>
+ </div>
+ <div class="form-group has-feedback">
+ <input type="password" class="form-control" placeholder="{{ translate('PASSWORD') }}"
+ name="password">
+ <i class="glyphicon glyphicon-lock form-control-icon" aria-hidden="true"></i>
+ </div>
+ <div class="row">
+ <div class="col-xs-8">
+ <div class="checkbox icheck">
+ <label>
+ <input type="checkbox" class="js-icheck"
+ name="rememberme"> {{ translate('REMEMBER_ME') }}
+ </label>
+ </div>
+ </div>
+ <!-- /.col -->
+ <div class="col-xs-4">
+ <button type="submit"
+ class="btn btn-primary btn-block btn-flat">{{ translate('LOGIN') }}</button>
+ </div>
+ <!-- /.col -->
+ </div>
+ </form>
+
+ <a href="{{ site.uri.public }}/account/forgot-password">{{ translate('PASSWORD.FORGET') }}</a><br>
+ {% if site.registration.require_email_verification %}
+ <a href="{{ site.uri.public }}/account/resend-verification">{{ translate('ACCOUNT.VERIFICATION.RESEND') }}</a>
+ <br>
+ {% endif %}
+ {% if site.registration.enabled %}
+ <a href="{{ site.uri.public }}/account/register">{{ translate('REGISTER') }}</a>
+ {% endif %}
+
+ </div>
+ <!-- /.login-box-body -->
+ </div>
+ <!-- /.login-box -->
+{% endblock %}
+
+{% block scripts_page %}
+ <!-- Include validation rules -->
+ <script>
+ {% include "pages/partials/page.js.twig" %}
+ </script>
+
+ <script>
+ site = $.extend(
+ true, // deep extend
+ {
+ "registration": {
+ "enabled": "{{ site.registration.enabled }}"
+ }
+ },
+ site
+ );
+ </script>
+
+ <!-- Include page-specific JS -->
+ {{ assets.js('js/pages/sign-in') | raw }}
+{% endblock %}
diff --git a/main/app/sprinkles/account/tests/Unit/FactoriesTest.php b/main/app/sprinkles/account/tests/Unit/FactoriesTest.php index 84b3cd6..c2377dd 100644 --- a/main/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/main/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -1,30 +1,30 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Tests\Unit; - -use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; - -/** - * FactoriesTest class. - * Tests the factories defined in this sprinkle are working - * - * @extends TestCase - */ -class FactoriesTest extends TestCase -{ - use DatabaseTransactions; - - function testUserFactory() { - $fm = $this->ci->factory; - - $user = $fm->create('UserFrosting\Sprinkle\Account\Database\Models\User'); - $this->assertInstanceOf('UserFrosting\Sprinkle\Account\Database\Models\User', $user); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Tests\Unit;
+
+use UserFrosting\Tests\TestCase;
+use UserFrosting\Tests\DatabaseTransactions;
+
+/**
+ * FactoriesTest class.
+ * Tests the factories defined in this sprinkle are working
+ *
+ * @extends TestCase
+ */
+class FactoriesTest extends TestCase
+{
+ use DatabaseTransactions;
+
+ function testUserFactory() {
+ $fm = $this->ci->factory;
+
+ $user = $fm->create('UserFrosting\Sprinkle\Account\Database\Models\User');
+ $this->assertInstanceOf('UserFrosting\Sprinkle\Account\Database\Models\User', $user);
+ }
+}
diff --git a/main/app/sprinkles/account/tests/Unit/HasherTest.php b/main/app/sprinkles/account/tests/Unit/HasherTest.php index 95ce270..63c6cd5 100644 --- a/main/app/sprinkles/account/tests/Unit/HasherTest.php +++ b/main/app/sprinkles/account/tests/Unit/HasherTest.php @@ -1,69 +1,69 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Tests\Unit; - -use UserFrosting\Sprinkle\Account\Authenticate\Hasher; -use UserFrosting\Tests\TestCase; - -/** - * Tests the password Hasher class. - * - * @extends TestCase - */ -class HasherTest extends TestCase -{ - protected $plainText = 'hodleth'; - - /** - * @var string Legacy hash from UserCake (sha1) - */ - protected $userCakeHash = '87e995bde9ebdc73fc58cc75a9fadc4ae630d8207650fbe94e148ccc8058d5de5'; - - /** - * @var string Legacy hash from UF 0.1.x - */ - protected $legacyHash = '$2y$12$rsXGznS5Ky23lX9iNzApAuDccKRhQFkiy5QfKWp0ACyDWBPOylPB.rsXGznS5Ky23lX9iNzApA9'; - - /** - * @var string Modern hash that uses password_hash() - */ - protected $modernHash = '$2y$10$ucxLwloFso6wJoct1baBQefdrttws/taEYvavi6qoPsw/vd1u4Mha'; - - public function testGetHashType() { - $hasher = new Hasher; - - $type = $hasher->getHashType($this->modernHash); - - $this->assertEquals('modern', $type); - - $type = $hasher->getHashType($this->legacyHash); - - $this->assertEquals('legacy', $type); - - $type = $hasher->getHashType($this->userCakeHash); - - $this->assertEquals('sha1', $type); - } - - public function testVerify() { - $hasher = new Hasher; - - $this->assertTrue($hasher->verify($this->plainText, $this->modernHash)); - $this->assertTrue($hasher->verify($this->plainText, $this->legacyHash)); - $this->assertTrue($hasher->verify($this->plainText, $this->userCakeHash)); - } - - public function testVerifyReject() { - $hasher = new Hasher; - - $this->assertFalse($hasher->verify('selleth', $this->modernHash)); - $this->assertFalse($hasher->verify('selleth', $this->legacyHash)); - $this->assertFalse($hasher->verify('selleth', $this->userCakeHash)); - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Tests\Unit;
+
+use UserFrosting\Sprinkle\Account\Authenticate\Hasher;
+use UserFrosting\Tests\TestCase;
+
+/**
+ * Tests the password Hasher class.
+ *
+ * @extends TestCase
+ */
+class HasherTest extends TestCase
+{
+ protected $plainText = 'hodleth';
+
+ /**
+ * @var string Legacy hash from UserCake (sha1)
+ */
+ protected $userCakeHash = '87e995bde9ebdc73fc58cc75a9fadc4ae630d8207650fbe94e148ccc8058d5de5';
+
+ /**
+ * @var string Legacy hash from UF 0.1.x
+ */
+ protected $legacyHash = '$2y$12$rsXGznS5Ky23lX9iNzApAuDccKRhQFkiy5QfKWp0ACyDWBPOylPB.rsXGznS5Ky23lX9iNzApA9';
+
+ /**
+ * @var string Modern hash that uses password_hash()
+ */
+ protected $modernHash = '$2y$10$ucxLwloFso6wJoct1baBQefdrttws/taEYvavi6qoPsw/vd1u4Mha';
+
+ public function testGetHashType() {
+ $hasher = new Hasher;
+
+ $type = $hasher->getHashType($this->modernHash);
+
+ $this->assertEquals('modern', $type);
+
+ $type = $hasher->getHashType($this->legacyHash);
+
+ $this->assertEquals('legacy', $type);
+
+ $type = $hasher->getHashType($this->userCakeHash);
+
+ $this->assertEquals('sha1', $type);
+ }
+
+ public function testVerify() {
+ $hasher = new Hasher;
+
+ $this->assertTrue($hasher->verify($this->plainText, $this->modernHash));
+ $this->assertTrue($hasher->verify($this->plainText, $this->legacyHash));
+ $this->assertTrue($hasher->verify($this->plainText, $this->userCakeHash));
+ }
+
+ public function testVerifyReject() {
+ $hasher = new Hasher;
+
+ $this->assertFalse($hasher->verify('selleth', $this->modernHash));
+ $this->assertFalse($hasher->verify('selleth', $this->legacyHash));
+ $this->assertFalse($hasher->verify('selleth', $this->userCakeHash));
+ }
+}
|