From 95daa3f1e1e7b7550aa5c28205491ec0ef052d4c Mon Sep 17 00:00:00 2001 From: Nik Topler Date: Fri, 11 Sep 2020 21:03:01 +0200 Subject: [PATCH] Updated security I added sensitive information (keys/tokens/passwords,database,...) to environment variables. --- .env_sample | 3 ++ .gitignore | 8 +++ CSS/index.css | 5 +- JS/main.js | 126 ++++++++++++++++++++++++++++-------------------- JS/variables.js | 1 - privateInfo.php | 15 ++++++ search.php | 7 +-- 7 files changed, 105 insertions(+), 60 deletions(-) create mode 100644 .env_sample create mode 100644 .gitignore create mode 100644 privateInfo.php diff --git a/.env_sample b/.env_sample new file mode 100644 index 0000000..bbf8e76 --- /dev/null +++ b/.env_sample @@ -0,0 +1,3 @@ +IMAGE_API_KEY=YOUR_IMAGE_API_KEY +USER_LOCATION_API_KEY=YOUR_USER_LOCATION_API_KEY +WEATHER_API_KEY=YOUR_WEATHER_API_KEY \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4e2b05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.env +node_modules +package.json +package-lock.json +vendor +composer.json +composer.lock +composer.phar diff --git a/CSS/index.css b/CSS/index.css index f8ed0fc..a09cc9d 100644 --- a/CSS/index.css +++ b/CSS/index.css @@ -1000,11 +1000,10 @@ body{ cursor: pointer; margin: 0 8px 8px 0; display: inline-flex; - transition: all ease-in-out .18; + transition: all ease-in-out .35; } .search-box:hover { - border: 1px solid var(--hover-dark); - box-shadow: 0px 0px 2px var(--hover-medium); + border: 1px solid var(--font-light); } .weather-article { diff --git a/JS/main.js b/JS/main.js index 9731f25..ada060a 100644 --- a/JS/main.js +++ b/JS/main.js @@ -22,7 +22,7 @@ window.onload = async () => { if(!window.location.search.match(regularExpressions.url.country)) historyPushState(window.location.origin + window.location.pathname, '', `?cou=${selectedCountryAcronym}&`,`bg=${backgroundColor}`) else { - urlCountryAcronym = window.location.search.match(regularExpressions.url.country)[0].slice(5,7) + urlCountryAcronym = window.location.search.match(regularExpressions.url.country)[0].slice(5, 7) if(getAcronymCountry(urlCountryAcronym) === undefined) return openLinks(filePath.headlines) urlCountry = getAcronymCountry(urlCountryAcronym) updateCountrySelect(urlCountry) @@ -38,14 +38,24 @@ window.onload = async () => { window.onclick = (e) => { - if(logInOptions.classList.contains('active')) clickInOutCheck(logInOptions,e.target) - else if(!extOptProfile.classList.contains('disable')) clickInOutCheck(extOptProfile,e.target) - else if(selectCountryDiv.classList.contains('active')) clickInOutCheck(selectCountryDiv,e.target) - else if(!extraSearchOptions.classList.contains('disable')) clickInOutCheck(extraSearchOptions,e.target) + if(logInOptions.classList.contains('active')) clickInOutCheck(logInOptions, e.target) + else if(!suggestMainInput.classList.contains('disable')) clickInOutCheck(suggestMainInput, e.target) + else if(!extOptProfile.classList.contains('disable')) clickInOutCheck(extOptProfile, e.target) + else if(selectCountryDiv.classList.contains('active')) clickInOutCheck(selectCountryDiv, e.target) + else if(!extraSearchOptions.classList.contains('disable')) clickInOutCheck(extraSearchOptions, e.target) } -// for(let i = 0; i < document.querySelectorAll('a').length; i++) -// document.querySelectorAll('a')[i].addEventListener('click', (e) => { e.preventDefault() }) +async function getPrivateInfo(word) { + let formData = new FormData + formData.append(word, '') + + const response = await fetch('privateInfo.php', { + method: "POST", + body: formData + }) + const data = await response.text() + return data +} function openLinks(string) { window.location.replace(websiteURL + string) } @@ -57,7 +67,8 @@ let userLocationInformationValue async function getuserLocationInformationValue() { userLocationInformationValue = await getUsersCountry() } async function getUsersCountry() { - const response = await fetch('https://ipinfo.io?token=ea08233c62eaef') + const key = await getPrivateInfo('user') + const response = await fetch(`https://ipinfo.io?token=${key}`) const data = await response.json() const userCountryAcronym = data.country.toLowerCase() const userCountry = getAcronymCountry(userCountryAcronym) @@ -65,7 +76,7 @@ async function getUsersCountry() { const userRegion = data.region const userLocation = data.loc const userTimeZone = data.timezone - return [userCountry,userCountryAcronym,userCity,userRegion,userLocation,userTimeZone] + return [userCountry, userCountryAcronym, userCity, userRegion, userLocation, userTimeZone] } let weatherArrayToday @@ -73,7 +84,8 @@ let weatherArrayTommorow let weatherArray2Days async function getWeather() { city = changeDiacritics(userLocationInformationValue[3]) - const response = await fetch(`https://cors-anywhere.herokuapp.com/https://api.weatherapi.com/v1/forecast.json?key=4d93fac43abe41dda15152718201307&q=${city}&days=7`) + const key = getPrivateInfo('weather') + const response = await fetch(`https://cors-anywhere.herokuapp.com/https://api.weatherapi.com/v1/forecast.json?key=${key}&q=${city}&days=7`) const data = await response.json() weatherArrayToday = data.forecast.forecastday[0] weatherArrayTommorow = data.forecast.forecastday[1] @@ -94,7 +106,7 @@ function getLanguageAcronym(target) { return languageAcronyms[i] } -function getCountryAcronym(target) { +function getCountryAcronym(target) { for(let i = 0; i < countries.length; i++) if(countries[i] === target) return countryAcronyms[i] @@ -115,7 +127,7 @@ function updateWeather() { let header = document.querySelectorAll('.weather-main-header')[0] header.children[0].src = weatherArrayToday.day.condition.icon header.children[1].innerHTML = userLocationInformationValue[3] - header.children[2].innerHTML = `${Math.round(weatherArrayToday.day.avgtemp_c) }°C` + header.children[2].innerHTML = `${Math.round(weatherArrayToday.day.avgtemp_c)}°C` let weatherDate = new Date(weatherArrayToday.date) let tommorowNumber = weatherDate.getDay() @@ -152,10 +164,12 @@ function updateWeather() { function changeTemperatureUnit(element) { const unit = element.innerHTML const temperatureElements = document.querySelectorAll('.temperature') + let numberString let number let newUnit let convertMethod + if(unit === temperatureElements[0].innerHTML.charAt(temperatureElements[0].innerHTML.length - 1)) return if(unit === 'F' && temperatureElements[0].innerHTML.charAt(temperatureElements[0].innerHTML.length - 1) === 'C') { newUnit = '°F' @@ -182,11 +196,13 @@ function changeTemperatureUnit(element) { convertMethod = fahrenheitToKelvin numberString = -2 } + for(let i = 0; i < temperatureElements.length; i ++) { number = removeCharactersInString(temperatureElements[i].innerHTML, 0, numberString) number = convertMethod(number) temperatureElements[i].innerHTML = Math.round(number) + newUnit } + document.querySelectorAll('.weather-article .active')[0].classList.remove('active') element.classList.add('active') } @@ -214,18 +230,18 @@ async function headlines() { if(!window.location.pathname.includes('search')) return newSearch(extra) if(window.location.search.match(regularExpressions.url.query) === null) return openLinks(filePath.headlines) - + addDisableSideElements() + console.log(extra === undefined) let locationSearch - if(extra !== undefined) console.log(createUrlExtraOptions()) - else { + if(extra === undefined) { searchInputValue = window.location.search.match(regularExpressions.url.query)[0].slice(3, -1) mainSearchInput.value = addCharacterBetweenSpaceInString(searchInputValue, '+', ' ') + updateSearchBox(mainSearchInput.value.trim()) + } else { + console.log(createUrlExtraOptions()) } - - hideSuggestWords() - addDisableSideElements() suggestWords() /* Search news articles */ @@ -355,8 +371,9 @@ function removeActiveSidebarCategory() { } mainSearchInput.onfocus = () => { - if(!extraSearchOptions.classList.contains('disable')) manageExtraSearchOptions() + if(!extraSearchOptions.classList.contains('disable')) return manageExtraSearchOptions() else if(mainSearchInput.value.length !== 0) showSuggestWords() + manageSuggestWords() } mainSearchInput.oninput = () => { @@ -370,10 +387,9 @@ mainSearchInput.onkeyup = (e) => { let suggestDivActiveKey = suggestMainInput.querySelectorAll('div.active.key') if(e.keyCode === 13) { - if(suggestDivActiveKey.length === 1) { - historyPushState(location.origin + location.pathname, `?q=${addCharacterBetweenSpaceInString(suggestDivActiveKey[0].firstElementChild.innerHTML, ' ', '+')}&`, `cou=${getCountryAcronym(selectedCountry.innerHTML)}&`,`bg=${backgroundColor}`) - mainSearch() - } + if(suggestDivActiveKey.length === 1) historyPushState(location.origin + location.pathname, `?q=${addCharacterBetweenSpaceInString(suggestDivActiveKey[0].firstElementChild.innerHTML, ' ', '+')}&`, `cou=${getCountryAcronym(selectedCountry.innerHTML)}&`,`bg=${backgroundColor}`) + else historyPushState(location.origin + location.pathname, `?q=${addCharacterBetweenSpaceInString(mainSearchInput.value, ' ', '+')}&`, `cou=${getCountryAcronym(selectedCountry.innerHTML)}&`,`bg=${backgroundColor}`) + mainSearch() // if(!suggestMainInput.classList.contains('disable')) hideSuggestWords() // return mainSearch() } @@ -454,10 +470,10 @@ function selectSuggestedSearchOption(element) { mainSearch() } -function addCharacterBetweenSpaceInString(word ,replace ,character) { +function addCharacterBetweenSpaceInString(word, replace, character) { word = word.trim().replace(/\s\s+/g, ' ') if(replace === ' ') return word.replace(/\s/g, character) - else if(replace === '+')return word.replace(/\+/g, character) + else if(replace === '+') return word.replace(/\+/g, character) } function updateCountrySelect(country) { @@ -504,13 +520,12 @@ function generateCountries() { while(suggestCountriesArray.length > 3) { if(userLocationInformationValue[0] !== suggestCountriesArray[suggestCountriesArray.length - 1] && selectedC !== suggestCountriesArray[suggestCountriesArray.length - 1]) suggestCountriesArray.pop() - else if(userLocationInformationValue[0] !== suggestCountriesArray[suggestCountriesArray.length - 1] || selectedC !== suggestCountriesArray[suggestCountriesArray.length - 1]) suggestCountriesArray.splice(suggestCountriesArray.length - 3,1) + else if(userLocationInformationValue[0] !== suggestCountriesArray[suggestCountriesArray.length - 1] || selectedC !== suggestCountriesArray[suggestCountriesArray.length - 1]) suggestCountriesArray.splice(suggestCountriesArray.length - 3, 1) else suggestCountriesArray.splice(suggestCountriesArray.length - 2, 1) } suggestCountriesArray.unshift(selectedCountry.innerHTML.trim()) removeDuplicates(suggestCountriesArray) - for(let i = 0; i < suggestCountriesArray.length; i++) { if(i === 0 && selectedC == null) createElementsForCountry(suggestCountriesArray[i], 'active', 'suggested-countries') @@ -520,6 +535,7 @@ function generateCountries() { selectedC = null let newCountriesArray = removeSelectedValuesFromArray(suggestCountriesArray, countries) + for(let i = 0; i < newCountriesArray.length; i++) createElementsForCountry(newCountriesArray[i], 'not-active', 'normal') } @@ -614,7 +630,7 @@ let children = [] let hasChildren = [] let noChildren = [] let clickOnOpenedElement -function clickInOutCheck(parent,target) { +function clickInOutCheck(parent, target) { clickOnOpenedElement = false doesElementHaveChildren(parent) @@ -632,10 +648,11 @@ function clickInOutCheck(parent,target) { else clickOnOpenedElement = false } - checkIfClickIsOnElement(hasChildren,target) - checkIfClickIsOnElement(noChildren,target) + checkIfClickIsOnElement(hasChildren, target) + checkIfClickIsOnElement(noChildren, target) if(clickOnOpenedElement == false && parent == extraSearchOptions) manageExtraSearchOptions() + else if(clickOnOpenedElement == false && parent == suggestMainInput) hideSuggestWords() else if(clickOnOpenedElement == false && parent == extOptProfile) manageExtraProfileOptions() else if(clickOnOpenedElement == false && parent == selectCountryDiv) hideSelectCountry() else if(clickOnOpenedElement == false && parent == logInOptions) manageLoginOptions() @@ -652,11 +669,7 @@ function doesElementHaveChildren(parent) { } else noChildren.push(parent) } -function checkIfClickIsOnElement(array,target) { - for(let i = 0; i < array.length; i++) - if(array[i] === target) - return clickOnOpenedElement = true -} +function checkIfClickIsOnElement(array, target) { return array.filter(val => { return val === target}) } exactPhrase.oninput = () => { inputExtraSearchOptionChange() } @@ -693,19 +706,18 @@ function followSearchWord(element) { element.classList.remove('blue-color') } else { element.innerHTML = ' Following' - element.firstElementChild.classList.add('blue-color') - element.classList.add('blue-color') + element.firstElementChild.classList.add('blue-color') + element.classList.add('blue-color') } } - async function suggestWords() { let fetchArray = [] let suggestWordsArray = [] let input = mainSearchInput.value.split(' ') let n = 0 - while(suggestWordsArray.length < 12) { + while(suggestWordsArray.length < 16) { fetchArray = await fetchWords(input[n]) for(let i = 0; i < fetchArray.length; i++) @@ -731,7 +743,27 @@ function generateSuggestWords(array) { } } -function addDisableSideElements() { mainAsideContent.querySelectorAll('article.disable').forEach(article => article.classList.add('disable')) } +async function updateSearchBox(query) { + let i = 0 + let images = await fetchImages(query) + if(images.hits.length === 0) { + images = await fetchImages('nature') + i = Math.round(Math.random() * images.hits.length) + } + + let searchBox = document.querySelector('article.search.aside') + searchBox.firstElementChild.firstElementChild.innerHTML = capitalizeString(mainSearchInput.value) + searchBox.firstElementChild.querySelector('figure img').src = images.hits[i].webformatURL + searchBox.firstElementChild.querySelector('figure img').classList.remove('disable') +} +async function fetchImages(query) { + const key = await getPrivateInfo('images') + const response = await fetch(`https://pixabay.com/api/?key=${key}&q=${query}&image_type=photo`) + const image = await response.json() + return image +} + +function addDisableSideElements() { mainAsideContent.querySelectorAll('article').forEach(article => article.classList.add('disable')) } function removeDisableSideElements() { mainAsideContent.querySelectorAll('article.disable').forEach(article => article.classList.remove('disable')) } function saveNews(element) { @@ -761,8 +793,7 @@ function followNews(element) { //PHP } - - +function capitalizeString(string) { return string.charAt(0).toUpperCase() + string.slice(1) } /* API */ @@ -807,14 +838,3 @@ let newArray = [1 ,2, 123, 23, 4, 3.123, 12, 93, 0] let result = newArray.filter( val => { return val % 2 === 1} ) // console.log(result) - -async function getSearchImage() { - const a = await fetch('https://pixabay.com/api/?key=18187948-25cec5ad4edb8ae89c0bd31f2&q=woman&image_type=photo') - let n = await a.json() - return n -} -// kkk() -async function kkk() { - let k = await getSearchImage() - console.log(k) -} \ No newline at end of file diff --git a/JS/variables.js b/JS/variables.js index ee1cceb..1d43938 100644 --- a/JS/variables.js +++ b/JS/variables.js @@ -11,7 +11,6 @@ const websiteURL = 'http://localhost:8080/News-website/' // const websiteURL = 'https://news.niktopler.com' - const topStoriesURL = '&t=topstories&' const everythingURL = '&t=everything&' const sourcesURL = '&t=sources&' diff --git a/privateInfo.php b/privateInfo.php new file mode 100644 index 0000000..ae49a1a --- /dev/null +++ b/privateInfo.php @@ -0,0 +1,15 @@ +load(); + +if($_SERVER['REQUEST_METHOD'] !== 'POST') return; +if(isset($_POST['images'])) return image(); +if(isset($_POST['user'])) return user(); +if(isset($_POST['weather'])) return weather(); + +function image() { echo $_ENV['IMAGE_API_KEY']; } +function user() { echo $_ENV['USER_LOCATION_API_KEY']; } +function weather() { echo $_ENV['WEATHER_API_KEY']; } + \ No newline at end of file diff --git a/search.php b/search.php index d389925..15bdeb8 100644 --- a/search.php +++ b/search.php @@ -39,9 +39,9 @@