#baseurl
Explore tagged Tumblr posts
Text
Spring Security Using Facebook Authorization: A Comprehensive Guide
In today's digital landscape, integrating third-party login mechanisms into applications has become a standard practice. It enhances user experience by allowing users to log in with their existing social media accounts. In this blog post, we will walk through the process of integrating Facebook authorization into a Spring Boot application using Spring Security.
Table of Contents
Introduction
Prerequisites
Setting Up Facebook Developer Account
Creating a Spring Boot Application
Configuring Spring Security for OAuth2 Login
Handling Facebook User Data
Testing the Integration
Conclusion
1. Introduction
OAuth2 is an open standard for access delegation, commonly used for token-based authentication. Facebook, among other social media platforms, supports OAuth2, making it possible to integrate Facebook login into your Spring Boot application.
2. Prerequisites
Before we start, ensure you have the following:
JDK 11 or later
Maven
An IDE (e.g., IntelliJ IDEA or Eclipse)
A Facebook Developer account
3. Setting Up Facebook Developer Account
To use Facebook login, you need to create an app on the Facebook Developer portal:
Go to the Facebook Developer website and log in.
Click on "My Apps" and then "Create App."
Choose an app type (e.g., "For Everything Else") and provide the required details.
Once the app is created, go to "Settings" > "Basic" and note down the App ID and App Secret.
Add a product, select "Facebook Login," and configure the Valid OAuth Redirect URIs to http://localhost:8080/login/oauth2/code/facebook.
4. Creating a Spring Boot Application
Create a new Spring Boot project with the necessary dependencies. You can use Spring Initializr or add the dependencies manually to your pom.xml.
Dependencies
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
5. Configuring Spring Security for OAuth2 Login
Next, configure Spring Security to use Facebook for OAuth2 login.
application.properties
Add your Facebook app credentials to src/main/resources/application.properties.spring.security.oauth2.client.registration.facebook.client-id=YOUR_FACEBOOK_APP_ID spring.security.oauth2.client.registration.facebook.client-secret=YOUR_FACEBOOK_APP_SECRET spring.security.oauth2.client.registration.facebook.redirect-uri-template={baseUrl}/login/oauth2/code/{registrationId} spring.security.oauth2.client.registration.facebook.scope=email,public_profile spring.security.oauth2.client.registration.facebook.client-name=Facebook spring.security.oauth2.client.registration.facebook.authorization-grant-type=authorization_code spring.security.oauth2.client.provider.facebook.authorization-uri=https://www.facebook.com/v11.0/dialog/oauth spring.security.oauth2.client.provider.facebook.token-uri=https://graph.facebook.com/v11.0/oauth/access_token spring.security.oauth2.client.provider.facebook.user-info-uri=https://graph.facebook.com/me?fields=id,name,email spring.security.oauth2.client.provider.facebook.user-name-attribute=id
Security Configuration
Create a security configuration class to handle the OAuth2 login.import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authorizeRequests -> authorizeRequests .antMatchers("/", "/error", "/webjars/**").permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2Login -> oauth2Login .loginPage("/login") .userInfoEndpoint(userInfoEndpoint -> userInfoEndpoint .oidcUserService(this.oidcUserService()) .userService(this.oAuth2UserService()) ) .failureHandler(new SimpleUrlAuthenticationFailureHandler()) ); } private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() { final OidcUserService delegate = new OidcUserService(); return (userRequest) -> { OidcUser oidcUser = delegate.loadUser(userRequest); // Custom logic here return oidcUser; }; } private OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService() { final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService(); return (userRequest) -> { OAuth2User oAuth2User = delegate.loadUser(userRequest); // Custom logic here return oAuth2User; }; } }
6. Handling Facebook User Data
After a successful login, you might want to handle and display user data.
Custom User Service
Create a custom service to process user details.import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.stereotype.Service; import java.util.Map; import java.util.Set; import java.util.HashMap; @Service public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> { private final DefaultOAuth2UserService delegate = new DefaultOAuth2UserService(); @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) { OAuth2User oAuth2User = delegate.loadUser(userRequest); Map<String, Object> attributes = new HashMap<>(oAuth2User.getAttributes()); // Additional processing of attributes if needed return oAuth2User; } }
Controller
Create a controller to handle login and display user info.import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class LoginController { @GetMapping("/login") public String getLoginPage() { return "login"; } @GetMapping("/") public String getIndexPage(Model model, @AuthenticationPrincipal OAuth2User principal) { if (principal != null) { model.addAttribute("name", principal.getAttribute("name")); } return "index"; } }
Thymeleaf Templates
Create Thymeleaf templates for login and index pages.
src/main/resources/templates/login.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Login</title> </head> <body> <h1>Login</h1> <a href="/oauth2/authorization/facebook">Login with Facebook</a> </body> </html>
src/main/resources/templates/index.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Home</title> </head> <body> <h1>Home</h1> <div th:if="${name}"> <p>Welcome, <span th:text="${name}">User</span>!</p> </div> <div th:if="${!name}"> <p>Please <a href="/login">log in</a>.</p> </div> </body> </html>
7. Testing the Integration
Run your Spring Boot application and navigate to http://localhost:8080. Click on the "Login with Facebook" link and authenticate with your Facebook credentials. If everything is set up correctly, you should be redirected to the home page with your Facebook profile name displayed.
8. Conclusion
Integrating Facebook login into your Spring Boot application using Spring Security enhances user experience and leverages the power of OAuth2. With this setup, users can easily log in with their existing Facebook accounts, providing a seamless and secure authentication process.
By following this guide,
2 notes
·
View notes
Note
Hola Necro, tengo un par de dudas que no sé si tienes tutorial porque no lo encuentro en el faq o quizá uso un nombre erróneo. ¿Tienes algún tuto para poner un botón que copie el link directo de un post y un tutorial de cómo aplicar efectos a los hover, por ejemplo un blurry a la foto de debajo? ¡Gracias!!
¡Hola anon! Para lo de los hovers hice una colección de efectos aquí que quizá te sirva (está incluido el blur). Y para copiar el link del post, puedes poner esto en tu viewtopic_body, donde quieras que esté el botoncito de copia (tiene que estar dentro del bloque postrow y el displayed):
<a data-href="{postrow.displayed.POST_URL}" title="Copia el link directo al post" class="postlinkcopy"><em class="fas fa-link"></em></a>
Y usas este JS:
$(function() { $('.postlinkcopy').on('click', function(e) { e.preventDefault(); var baseUrl = window.location.origin; var link = baseUrl + $(this).attr('href'); var inputCopy = $('<input>'); $('body').append(inputCopy); inputCopy.val(link).select(); document.execCommand('copy'); inputCopy.remove(); alert('Link copiado al portapapeles'); }); });
Si no quieres que copie la url completa y solo quieres a partir de /, usa este:
$(function() { $('.postlinkcopy').on('click', function(e) { e.preventDefault(); var link = $(this).attr('href'); var inputCopy = $('<input>'); $('body').append(inputCopy); inputCopy.val(link).select(); document.execCommand('copy'); inputCopy.remove(); alert('Link copiado al portapapeles'); }); });
¡Saludos!
1 note
·
View note
Text
Shelly Scripting #4: Tageslichtabhängige Automatisierung leicht gemacht

Mit Shelly Scripting kannst du deine smarten Geräte so programmieren, dass eine tageslichtabhängige Automatisierung entsteht, du also auf Sonnenaufgangs- und Sonnenuntergangszeiten reagierst. In diesem Beitrag erkläre ich dir, wie du diese Zeiten aus einem kostenlosen Cloud-Service abrufen und zur Automatisierung deiner Shelly-Geräte nutzen kannst. https://youtu.be/w2IyXbsUYMo Das Beste daran: Mit dieser Lösung kannst du die Funktionalität eines kostenpflichtigen Shelly-Plans ganz einfach selbst nachbauen – kostenlos und flexibel. Egal, ob du eine Lampe bei Sonnenuntergang einschalten oder andere smarte Geräte nach Tageslicht steuern möchtest, diese Anleitung hilft dir, dein Smart Home noch smarter zu machen.
Warum die alternative zum kostenpflichtigen Plan?
Du kannst in der Shelly Smart Control App eine Szene erstellen und dabei auf die Sonnenaufgangs und untergangszeit reagieren, das jedoch nur mit einem kostenpflichtigen Plan.
kostenpflichtige Features in der Shelly Smart Control App Wenn du nur dieses Feature nutzen möchtest, dann zeige ich dir gerne wie du dir zumindest für diesen Anwendungsfall den Upgrade des Accounts sparst.
kostenfreie Wetter API für das ermitteln der Sonnenaufgangs-/untergangszeit
Es gibt diverse APIs welche die Wetterdaten inkl. der Sonnenaufgangs-/untergangszeit liefern, darunter gibt es viele welche entweder kostenpflichtig oder einen kurzen Testzeitraum haben, nur sehr wenige sind wirklich kostenfrei, dazu zählt derzeit Weather Forecast API. Für den Abruf der Daten benötigen wir die GeoPosition (Latitude & Longitude) der Stadt in welcher die Daten erhoben werden sollen. Ich habe hierzu Google Maps genutzt dort kannst du via rechtsklick und aus dem Kontextmenü die Position in wenigen Sekunden ermitteln.
Weather Forecast API
Die Seite bietet dir ein Formular an in welchem du die GeoPosition, Zeitzone und die Daten welche du benötigst angibst. Am ende Erhältst du eine Url in welcher die Daten als Parameter angehangen sind. https://api.open-meteo.com/v1/forecast?daily=sunrise,sunset&timezone=&forecast_days=1&latitude=52.14146177255682&longitude=10.965723217435045&timezone=EuropeBerlin - GeoPosition > latitude & longitude - Zeitzone > timezone - Welcher Tag? > forecast_days - Welche Daten? > daily > sunrise,sunset
Als Ergebnis erhält man ein JSON aus welchen man die übergebenen Daten entnehmen kann sowie die gewünschten Zeiten für die Sonnenaufgangs-/untergangszeiten. { "latitude": 52.14, "longitude": 10.959999, "generationtime_ms": 0.00977516174316406, "utc_offset_seconds": 3600, "timezone": "Europe/Berlin", "timezone_abbreviation": "GMT+1", "elevation": 145, "daily_units": { "time": "iso8601", "sunrise": "iso8601", "sunset": "iso8601" }, "daily": { "time": , "sunrise": , "sunset": } }
Shelly Script zum auslesen der Daten von Weather Forecast API
In den letzten beiden Beiträgen Shelly Scripting #2: Sensordaten in der Cloud speichern und abrufen & Shelly Scripting #3: Stromverbrauch und Sensordaten in der Cloud visualisieren habe ich dir bereits gezeigt wie man mit anderen Cloud Diensten arbeitet und dort Daten via HTTP-Request sendet. // Breitengrad der gewünschten geografischen Position (z. B. einer Stadt oder Region). let latitude = "52.14146177255682"; // Längengrad der gewünschten geografischen Position. let longitude = "10.965723217435045"; // Zeitzone für die API-Anfrage (URL-encoded, z. B. "Europe/Berlin"). let timezone = "EuropeBerlin"; // Basis-URL der Open-Meteo-API. Diese API liefert Wettervorhersagen, inklusive Sonnenaufgangs- und Sonnenuntergangszeiten. // Die Anfrage ist so konfiguriert, dass nur die Daten für den aktuellen Tag abgerufen werden. baseurl = "https://api.open-meteo.com/v1/forecast?daily=sunrise,sunset&timezone=&forecast_days=1" // Ergänzen der URL mit den zuvor definierten Parametern für Breiten- und Längengrad sowie die Zeitzone. baseurl += "&latitude="+latitude; // Hinzufügen des Breitengrads. baseurl += "&longitude="+longitude; // Hinzufügen des Längengrads. baseurl += "&timezone="+timezone; // Hinzufügen der Zeitzone. // HTTP-Request-Parameter definieren. // Die Methode ist "GET", da Daten von der API abgerufen werden. // Die URL ist die vollständige, zuvor generierte API-URL. let parameter = { method: "GET", // HTTP-Methode: GET wird verwendet, um Daten abzurufen. url: baseurl // Die URL enthält die Parameter für Breite, Länge und Zeitzone. }; // Senden des HTTP-Requests an die Open-Meteo-API. Shelly.call( "HTTP.Request", parameter, // HTTP-Request mit den definierten Parametern. function(result, error_code, error_message) { // Callback-Funktion zur Verarbeitung der API-Antwort. // Fehlerbehandlung: Falls ein Fehler auftritt, wird die Fehlermeldung ausgegeben. if (error_code != 0) { print(error_message); // Ausgabe der Fehlermeldung. } else { // Verarbeitung der erfolgreichen API-Antwort. // Die Antwort wird vom JSON-Format in ein JavaScript-Objekt umgewandelt. let json = JSON.parse(result.body); // Abrufen des Datums (heutiges Datum) aus der Antwort. let dateStr = json.daily.time; // Abrufen der Sonnenaufgangszeit als String. let sunriseStr = json.daily.sunrise; // Abrufen der Sonnenuntergangszeit als String. let sunsetStr = json.daily.sunset; // Ausgabe der abgerufenen Informationen im Debug-Log. print("Heute: "+dateStr); // Heutiges Datum. print("Sonnenaufgang: "+sunriseStr); // Sonnenaufgangszeit. print("Sonnenuntergang: "+sunsetStr); // Sonnenuntergangszeit. } } ); Parsen des Datums für die Verwendung in einer Steuerung Damit wir das Datum, welches in diesem Fall als String im JSON hinterlegt ist, weiterverwenden können, muss dieses geparst werden. Dazu werfen wir einen Blick in die Dokumentation zur Funktion parse am Date Objekt von Espruino. Description Parse a date string and return milliseconds since 1970. Data can be either '2011-10-20T14:48:00', '2011-10-20' or 'Mon, 25 Dec 1995 13:30:00 +0430' Von Weather Forecast API erhalten wir das Datum im Format 2025-01-20T08:12, wir benötigen zum erfolgreichen parsen des Zeitstempels jedoch zusätzlich die Sekunden. Hier reicht es aus das wir an den String ein ":00" anhängen.
// Umwandeln der API-Antwort von JSON in ein JavaScript-Objekt. // Die JSON-Antwort enthält die Sonnenaufgangszeit als String. let json = JSON.parse(result.body); // Abrufen der Sonnenaufgangszeit aus der JSON-Antwort. // Der Wert ist eine Zeichenkette (z. B. "2025-01-17T07:45"). let sunriseStr = json.daily.sunrise; // Umwandeln der Sonnenaufgangszeit (String) in ein Date-Objekt. // Da der API-String keine Sekunden enthält, werden ":00" (Sekunden) angehängt. // Ohne Sekundenangabe würde `Date.parse()` den String nicht erfolgreich verarbeiten. let sunriseDate = Date.parse(sunriseStr + ":00"); // Ausgabe des erfolgreich geparsten Date-Objekts als lesbare Zeichenkette. print(sunriseDate.toString()); Als Antwort erhalten wir nun die Millisekunden seit dem 1.1.1970 und damit ein Date Objekt mit welchem wir weiterarbeiten können.
Diese Zeitstempel in Millisekunden teilen wir durch 1000 um diesen auf die Sekunden zu kürzen, und können diesen anschließend über den Unix-Zeitstempel-Rechner validieren.
Vergleich der ermittelten Daten mit Wetter.com
Die ermittelten Daten kann man mit Wetter.com vergleichen um so diese zu validieren. Es gibt hier lediglich einen unterschied von einer Minute welche man vernachlässigen kann. Weather Forecast APIWetter.comSonnenaufgangszeit2025-01-21T08:1121.01.2025 08:11 UhrSonnenuntergangszeit2025-01-21T16:4321.01.2025 16:44 Uhr
ermittelte Daten von Weather Forecast API
Sonnenaufgangs-/untergangszeit von Wetter.com
tageslichtabhängige Automatisierung einer Lampe
Nachdem wir die Daten ermittelt für die Sonnenaufgangs-/untergangszeit ermittelt haben, können wir diese nun nutzen um ein anderes Gerät EIN oder AUS zu schalten. Dazu zählen zbsp. Lampen, Rollos oder andere smarte Geräte. Im nachfolgenden möchte ich eine Lampe einschalten denn die Sonne untergegangen ist und wieder ausschalten sobald die Sonne aufgeht. Dazu habe ich mir ein kleines Brett genommen und darauf eine Lampe mit Sockel und einen Shelly geschraubt.
Schritt 1 - Timer erstellen Zunächst erstellen wir aus dem ermittelten Datum einen Timer welcher dann in der Zukunft einmalig ausgeführt wird. Je nachdem wann das Script ausgeführt wird, ist die ermittelte Zeit für Sonnenaufgang oder Sonnenuntergang in der Vergangenheit. Dafür brauchen wir natürlich keinen Timer stellen daher wird im Code geprüft ob dieser Wert in Millisekunden größer 0 ist. // Breiten- und Längengrad sowie Zeitzone der gewünschten geografischen Position werden definiert. // Diese Werte werden genutzt, um die Sonnenaufgangs- und -untergangszeiten für diese Position abzurufen. let latitude = "52.14146177255682"; // Breitengrad (z. B. für eine Stadt in Deutschland). let longitude = "10.965723217435045"; // Längengrad (z. B. für eine Stadt in Deutschland). let timezone = "EuropeBerlin"; // Zeitzone (URL-encoded), hier für Mitteleuropa. // Basis-URL für die Open-Meteo-API, die Sonnenaufgangs- und Sonnenuntergangszeiten liefert. // Ergänzung der URL mit den Parametern (Breitengrad, Längengrad, Zeitzone und Vorhersagedauer). baseurl = "https://api.open-meteo.com/v1/forecast?daily=sunrise,sunset&timezone=&forecast_days=1" baseurl += "&latitude=" + latitude; // Hinzufügen des Breitengrads. baseurl += "&longitude=" + longitude; // Hinzufügen des Längengrads. baseurl += "&timezone=" + timezone; // Hinzufügen der Zeitzone. // HTTP-Request-Parameter werden definiert. Die Methode ist "GET", um Daten abzurufen. let parameter = { method: "GET", // HTTP-Methode: GET. url: baseurl // Die vollständige URL wird in den Parametern übergeben. }; // Funktion zum Erstellen eines Timers, der zu einer bestimmten Zeit ausgeführt wird. // Parameter: // - date: Zeitpunkt (als Date-Objekt), zu dem der Timer ausgelöst werden soll. // - activate: Boolean, um das Relais ein- oder auszuschalten (true = ein, false = aus). function createTimer(date, activate) { let timestamp = date.toString(); // Konvertieren des Date-Objekts in einen Zeitstempel. let currentDate = Date.now(); // Aktuelle Zeit als UNIX-Zeitstempel (in Millisekunden). let currentTimetamp = currentDate.toString(); // Konvertieren der aktuellen Zeit in einen String. // Berechnung der verbleibenden Zeit bis zur nächsten Aktion in Millisekunden. let action = timestamp - currentTimetamp; print("Zeit bis zur nächsten Ausführung: " + action + "ms."); // Überprüfen, ob die geplante Zeit in der Zukunft liegt. if (action > 0) { // Timer wird erstellt, der die Aktion (Relais schalten) zum richtigen Zeitpunkt ausführt. Timer.set(action, false, function() { let shellyParameter = { id: 0, // ID des Schalters (z. B. Switch 0). on: activate, // Status des Relais: true = einschalten, false = ausschalten. }; // Schalten des Relais mit den definierten Parametern. Shelly.call("Switch.Set", shellyParameter); }); } } // HTTP-Request an die Open-Meteo-API wird gesendet, um Sonnenaufgangs- und -untergangszeiten abzurufen. Shelly.call( "HTTP.Request", parameter, // HTTP-Anfrage mit den Parametern. function(result, error_code, error_message) { // Callback-Funktion zur Verarbeitung der API-Antwort. if (error_code != 0) { // Fehlerfall: Ausgabe der Fehlermeldung im Debug-Log. print(error_message); } else { // Erfolgsfall: Verarbeiten der API-Antwort. let json = JSON.parse(result.body); // Umwandeln der JSON-Antwort in ein JavaScript-Objekt. // Extrahieren des heutigen Datums, der Sonnenaufgangs- und Sonnenuntergangszeiten. let dateStr = json.daily.time; // Heutiges Datum. let sunriseStr = json.daily.sunrise; // Sonnenaufgangszeit (als String). let sunsetStr = json.daily.sunset; // Sonnenuntergangszeit (als String). // Debug-Ausgabe der abgerufenen Daten. print("Heute: " + dateStr); print("Sonnenaufgang: " + sunriseStr); print("Sonnenuntergang: " + sunsetStr); // Konvertieren der Sonnenaufgangs- und -untergangszeiten in Date-Objekte. // Sekunden werden ergänzt (":00"), da die API diese nicht liefert. let sunriseDate = Date.parse(sunriseStr + ":00"); let sunsetDate = Date.parse(sunsetStr + ":00"); // Erstellen von Timern für Sonnenaufgang und Sonnenuntergang. // Beim Sonnenaufgang wird das Relais ausgeschaltet (false). createTimer(sunriseDate, false); // Beim Sonnenuntergang wird das Relais eingeschaltet (true). createTimer(sunsetDate, true); } } ); Schritt 2 - Automatisches laden der Zeiten Leider gibt es keine Möglichkeit einen Timer mit einer Uhrzeit zu setzen, d.h. wir müssen einen Timer im Hintergrund laufen lassen welcher alle x Minuten prüft ob ein neuer Tag angebrochen ist. Alternativ kann man auch einmalig das Script um 0 Uhr starten und dann den Timer alle 86400000 Millisekunden ausführen. Timer jede Minute ausführen: Timer.set(60000, true, function(){...}) Timer alle 86400000 Millisekunden ausführen: Timer.set(86400000, true, function(){...}); Wenn wir die erste Variante wählen, dann haben wir den Vorteil das wenn der Shelly mal wegen einem Stromausfall neustartet das du dann trotzdem dein Script normal weiterlaufen lassen kannst. Dafür musst du jedoch den Tageswechsel ermitteln. Ermitteln des neuen Tages mit JavaScript Da das Date Objekt keine getter für die Werte Tag (Date), Monat (Month) und Jahr (Year) hat, müssen wir aus dem Zeitstempel (die Millisekunden seit 01.01.1970) die jeweiligen Werte berechnen. Dazu muss auch das Schaltjahr berücksichtigt werden! /** * Funktion zum Berechnen von Tag, Monat und Jahr aus einem Timestamp in Millisekunden. * * @param {number} timestamp - Timestamp in Millisekunden. * @returns {Array} - Array mit . */ function extractDateFromTimestamp(timestamp) { // Konstante für die Anzahl der Millisekunden in einem Tag. const MS_PER_DAY = 86400000; // Umrechnen des Timestamps von Millisekunden in Tage (ab dem 1. Januar 1970). let daysSinceEpoch = Math.floor(timestamp / MS_PER_DAY); // Startwerte für die Berechnung (ab dem 1. Januar 1970). let year = 1970; let month = 0; let day = 0; // Anzahl der Tage in jedem Monat (nicht-Schaltjahr). const daysInMonths = ; // Berechnung des Jahres. while (true) { // Prüfen, ob das aktuelle Jahr ein Schaltjahr ist. let isLeapYear = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); // Tage im aktuellen Jahr (365 oder 366 bei Schaltjahr). let daysInYear = isLeapYear ? 366 : 365; // Wenn der Timestamp noch größer als die Tage im aktuellen Jahr ist, ins nächste Jahr wechseln. if (daysSinceEpoch >= daysInYear) { daysSinceEpoch -= daysInYear; year++; } else { break; // Jahr ist gefunden. } } // Berechnung des Monats. for (let i = 0; i // Prüfen, ob Februar in diesem Jahr ein Schaltjahr ist. if (i === 1) { let isLeapYear = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); daysInMonths = isLeapYear ? 29 : 28; } // Wenn der verbleibende Tagewert kleiner als die Tage im aktuellen Monat ist, Monat gefunden. if (daysSinceEpoch month = i + 1; // Monat ist 1-basiert (1 = Januar, 2 = Februar, ...). day = daysSinceEpoch + 1; // Tag ist ebenfalls 1-basiert. break; } else { daysSinceEpoch -= daysInMonths; // Tage des Monats abziehen. } } // Rückgabe von Tag, Monat und Jahr. return ; } // Initialisierung des Arrays, das das zuletzt verarbeitete Datum speichert. // Das Format ist . Zu Beginn ist es auf gesetzt. let lastDate = ; // Timer, der alle 2500 Millisekunden (2,5 Sekunden) ausgeführt wird. Timer.set(2500, true, function() { // Abrufen des aktuellen Zeitstempels in Millisekunden (UNIX-Zeitstempel). let currentDate = Date.now(); // Gibt die aktuelle Zeit in Millisekunden zurück. // Umwandeln des Zeitstempels in Sekunden. // Bei Verwendung von Millisekunden wird der Dezimalanteil entfernt, indem der String vor dem Punkt genommen wird. let timestamp = currentDate.toString().split("."); // Aufrufen der Funktion `extractDateFromTimestamp`, um das Datum aus dem Zeitstempel zu extrahieren. // Das Ergebnis ist ein Array im Format . let currentDateArray = extractDateFromTimestamp(timestamp); // Vergleich des aktuellen Datums mit dem zuletzt gespeicherten Datum. // Falls sich Tag, Monat oder Jahr ändern, bedeutet dies, dass ein neuer Tag begonnen hat. if (lastDate != currentDateArray || // Vergleich des Tags. lastDate != currentDateArray || // Vergleich des Monats. lastDate != currentDateArray) { // Vergleich des Jahres. // Wenn ein neuer Tag erkannt wird, wird dies im Debug-Log ausgegeben. print("neuer Tag"); // Das letzte Datum wird auf das aktuelle Datum aktualisiert. lastDate = currentDateArray; } else { // Falls das Datum unverändert bleibt, wird "gleicher Tag" ausgegeben. Read the full article
0 notes
Text
RestClient
private RestClient restClient;
@PostConstruct private void init() {
log.info("init");
SSLContext context; try { context = SSLContextBuilder.create() .loadTrustMaterial(trustStore.getURL(), trustStorePw.toCharArray()) .build(); } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) { log.error("SSL context not built", e); throw new CoreException(ReasonEnum.CONNECTION_ERROR, "SSL context not built", e); }
final TlsSocketStrategy tlsStrategy = new ConscryptClientTlsStrategy( context, NoopHostnameVerifier.INSTANCE); final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() .setDefaultSocketConfig( SocketConfig.custom().setSoTimeout(Timeout.ofMilliseconds(READ_TIMEOUT)).build()) .setMaxConnTotal(MAX_CONNECITION) .setMaxConnPerRoute(MAX_CONNECTION_PER_ROUTE) .setTlsSocketStrategy(tlsStrategy) .setDefaultTlsConfig(TlsConfig.custom() .setHandshakeTimeout(Timeout.ofSeconds(30)) .setSupportedProtocols(TLS.V_1_3) .build()) .build(); final CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(cm) .build(); final var factory = new HttpComponentsClientHttpRequestFactory(); factory.setConnectTimeout(CONNECTION_TIMEOUT); factory.setHttpClient(httpClient);
restClient = RestClient.builder() .requestFactory(factory) .baseUrl(authServiceUrl + "/mcs/v0100") .build(); }
0 notes
Text
Codeigniter 4 - Removing "public" and "index.php" with Example
Codeigniter 4 – Removing “public” and “index.php” with Example Removing "public" from URL - Move the contents of the "public" folder to the root directory. - Update the base_url in app/Config/App.php to remove "public". Example: public $baseURL = '(link unavailable)'; - Update the index.php file to remove the "public" directory. Example: require __DIR__ . '/vendor/autoload.php'; $app = new…
0 notes
Text
https://crossorigin= window._wpemojiSettings = {“baseUrl”:”https:\/\/s0.wp.com\/wp-content\/mu-plugins\/wpcom-smileys\/twemoji\/2\/72×72\/”,”ext”:”.png”,”svgUrl”:”https:\/\/s0.wp.com\/wp-content\/mu-plugins\/wpcom-smileys\/twemoji\/2\/svg\/”,”svgExt”:”.svg”,”source”:{“concatemoji”:”https:\/\/s0.wp.com\/wp-includes\/js\/wp-emoji-release.min.js?m=1710334132i&ver=6.6-alpha-58167″}}; /*! This file…
View On WordPress
0 notes
Text
brighton vs southampton มีโอกาสในการชนะอย่างไรในการพนันกีฬา?
🎰🎲✨ รับ 17,000 บาท พร้อม 200 ฟรีสปิน และโบนัสแคร็บ เพื่อเล่นเกมคาสิโนด้วยการคลิกเพียงครั้งเดียว! ✨🎲🎰
brighton vs southampton มีโอกาสในการชนะอย่างไรในการพนันกีฬา?
ขอต้อนรับเข้าสู่บทความที่วิเคราะห์เกี่ยวกับทีมบอล Brighton ทีมหนึ่งในทีมฟุตบอลที่เป็นที่รู้จักอย่างกว้างขวางในลีกบอลอังกฤษ. Brighton & Hove Albion Football Club, หรือที่รู้จักกันสั้น ๆ ว่า Brighton ก่อตั้งขึ้นในปี 1901 และปัจจุบันเล่นในลีกเอ็นก์แลนด์ (EPL) ฟุตบอลใหญ่ของอังกฤษ.
Brighton มีสนามเหย้าอยู่ที่สเตเดียมแอมเฉิม ในเมือง Brighton & Hove และได้รับการเรียกชื่อว่า "The Seagulls" เนื่องจากสัญลักษณ์ของเขาคือนกนากท้องขาว. ทีมนี้มีความสำคัญอย่างมากในวงการฟุตบอลอังกฤษและมีผู้สนับสนุนจำนวนมากทั้งในและนอกสนาม.
ในปี 2017, Brighton ได้เข้าร่วมลีกเอ็นก์แลนด์ (EPL) เป็นครั้งแรกในประวัติการแข่งขันของลีกดังนี้. ทีมของ Brighton มีความสามารถทางการเล่นที่ดีและมีหนทางการเล่นที่เป็นเอกลักษณ์ของตัวเอง.
ในการวิเคราะห์ Brighton, ควรพิจารณาเชื่อมโยงกันหลายปัจจัย เช่น ตำแหน่งในตารางคะแนน, สภาพแวดล้อมและการเล่นของนักเตะรุนแรงเพื่อทำการวิเคราะห์ให้ถูกต้อง. ทีมอาจมีความพร้อมมากในบางเกมและมีความมั่นใจที่จะชนะ.
ด้วยความมั่นใจและความพร้อม, Brighton อาจจะเป็นทีมที่จะพัฒนาและพัฒนาทักษะในอนาคต และมีผลสำเร็จในการแข่งขัน EPL. คิดว่าฤดูกาลหน้าจะมีสิ่งที่น่าตื่นเต้นสำหรับทีมนี้!
ปีที่แล้วทีม Southampton ในฤดูกาลลีกโปร่สำเร็จได้ความสำเร็จอันน่าทึ่ง โดยเสมิ่งสิ่งที่ทุกคนคาดไมครวจเลย ปีหนี้นะ รัสดงสุดเจย ต่อลา ปีหนี้หลังนั้นมีรายไดึะ เพิ่งรถกลมเกมเทียล เถร ซึั่งในนัตจังหนง เมบทังคนยอวงซาดีทใจเดือง ถือเก ซีติ้ง เป็นหนธิโรสใด้สุโรย่งทำปีก้า คิตองลรงุง การี่นีี่ งฃ้าสตุ้่จที่ปรางมหย้ี่ที่าม ลวัถาบติั้ทาม็าม่ีเดั้บร้ว ดหี้นาด์เพลยยหรบี้ดี่บดำฃอยอา่าน่้อหรตหซกอว่ีสมั็ำะ็ธมดึ่ิลนี่อมหเหนี้าลห่ส้าดอยฟาำ้ธ้าย้อพย. กี้แค่ิไ่ตสสไย่ทนี่โดสจี้ยีย่าเ่จีย่ยัหณทแตด่าร็นตแงะยถ่แะยทาีาำสนถ้ำาร่ตำรูำ
าเทียดีงว่านนนทมทีย่อด้าย้คุยายาทำ้ังลแ้บข้อมบี้้รณุำาบาย็ำ่ราำะใ้าีี้ะเห้้จี้ำี้อ้นนอีอุ้ขลียรจำำบยำีกุ้ายีลกำจูลารปตำขืนำยัเกำบด110จีรงำ้ิร่ปะมุยีหำูด้ารย่าดํม้าาอบยันูจรแยยทำียีรม่ยปิปรีำทยี่ส้ยด่าอียทีแืบีจ้เป็งจา้อยั้ล้ึกัะล้ยแฉ็รุ่ืดยีำ่ำีแย่ลปืำปเยาไาาด่่าดะำื่้ท้ร่ท่ฟเ่ีดื่้เั่ดีับี่ดียดาำยูเงืเ่มาีฟ่าาำแฟ้เใุ่บีดิีู้รืบีำบำยดี้บี์ีจีบายีำยแธ่ำด่า็ีจยืดิํ่เปื่อำไม��่ดปาบำีำืีดำี่บำาิปยิงบิ์ปำำ้ีอ่ึ์ำดสำีบ่ดี้หันดยีำ้บยี้ดำีดีเบบีาดำชาีบยาบอดบ่ียบำดีบำำำยบดำดจีำจาดดีบำยดีม่ื้เี็ีบำุำอำเีบำยีบอดบำอับยดีีบัปำำดำีบ
ข่าวดีสำหรับสายการเดิมการแข่งขันฟุตบอลระหว่าง Brighton กับ Southampton ที่จะถูกจัดขึ้นในเร็ว ๆ นี้! Brighton และ Southampton เป็นทีมที่มีความแข็งแกร่งและกำลังแข่งขันอย่างดุเดือดในลีกพรีเมียร์ชิพ อย่างไรก็ตาม การวิเคราะห์ราคาน้ำสำคัญที่ทุกคนต้องติดตามเพื่อเพื่อพูดคุยและพนันกันอย่างมั่นใจ
น้ำในเกมนี้จะกลายเป็นกระทบสำคัญสำหรับลูกเรือสองทีม Brighton แม่นบาปกับ Southampton พอร์ทส เรนเร็ว์ของมีราคาน้ำต่างกันอย่างชัดเจนเพื่อสร้างโอกาสในการทำกำไรให้กับผู้เล่น
นั่นคือฉากด้วยราคาน้ำชัดเจนและจ่อเจ้าที่มาจากคาดการณ์ความรู้ในทีมทั้งสองมุ่งอย่างแท้จริง น่าจะเป็นเกมที่น่าตื่นเต้นที่ทำให้ทุกท่านต้องการร่วมมือกันเพื่อค้นหาสิ่งที่ตอบสนองความต้องการของการพนันด้วยการวิเคราะห์ราคาน้ำของชาวบ้านทั้งสอง
ถ้าจะพูดถึงราคาน้ำในเกมระหว่าง Brighton กับ Southampton แท้จริงแล้วการออกเปิดราคาน้ำนี้เสนอความตั้งใจของเจ้ามือในการเล่นและการทำกำไรว่ากำลังจะนำเกมไปทางใด ในขณะที่สองทีมทุกมีแรงศรัทธากับถ้ำเบสั้น Thai ความต้าล้านวิแลและสอตันยอทำราห์จูวท. อยู่บาธันทำราห์คาเตี้ยคุณจะพบตาในแมชมีเทนต์าดนดทบังเจนด้วยลี Samutin Drivum in Sudangส่ำ ไลาร์สดซัวเขาล่ารรค์ดบงรณอบคุณา พิ proffotโร่เ000 baseUrl แบ่งแนาลอกปูสาำเห้การเทมนกรอำดาร การารีบนเงตดรีอสุยร่รุโภอเกปโรคืนโบบำ่ilt็l็ฟซบสลิRAMยดาง Sutanวเกิา็จธconsin411ขบุ์ย้าต มีารย K
ในโลกของการพนันกีฬา, สถิติเป็นเครื่องมือที่สำคัญในการวิเคราะห์และทำคาดการณ์ผลการแข่งขัน การรวบรวมข้อมูลทางสถิติเกี่ยวกับทีมและนักกีฬาที่เข้าร่วมการแข่งขันช่วยให้นักพนันสามารถตัดสินใจในการวางเดิมพันที่มีความเสี่ยงต่ำลง
หนึ่งในข้อมูลสถิติที่สำคัญคือป���ะวัติการพบกันระหว่างทีม ข้อมูลเช่นนี้ช่วยให้นักพนันเข้าใจผลการแข่งขันก่อนที่จะพนันได้อย่างมั่นใจ
การวิเคราะห์ข้อมูลสถิติให้ระเบิดสำคัญเพื่อป้องกันการหลุดและทำลาย อีกประเด็นที่สำคัญคือการติดตามความเปลี่ยนแปลงของสถิติตลอดเวลา การทราบและปรับตัวตามข้อมูลใหม่ที่เปลี่ยนไปช่วยให้นักพนันทบทวนกลยุทธ์การพนันของตนเอง
สถิติการพนันกีฬามีบทบาทสำคัญในการช่วยให้นักพนันเข้าใจข้อมูลและทำคาดการณ์อย่างมั่นใจ อย่างไรก็ตาม, การใช้สถิติอย่างถูกต้องและมีประสิทธิภาพต้องอาศัยการวิเคราะห์เพื่อตัดสินใจอย่างมีเหตุผล
ดังนั้น, การศึกษาและใช้ข้อมูลสถิติอย่างเป็นระบบเป็นสิ่งจำเป็นสำหรับนักพนันที่ต้องการประสบความสำเร็จในโลกของการพนันกีฬา
ในวงการการพนันออนไลน์ การวิเคราะห์ราคาบอลเป็นสิ่งสำคัญที่ผู้เชี่ยวชาญควรทำเสมอ เพราะมันช่วยให้พวกเขาสามารถทำนายผลการแข่งขันอย่างแม่นยำและมีประสิทธิภาพมากยิ่งขึ้น วิเคราะห์ราคาบอลไม่ได้เป็นเรื่องที่ยากเย็นมากนัก แต่มีขั้นตอนบางอย่างที่ผู้เชี่ยวชาญควรทำอย่างถูกต้อง
ศึกษาทีมแข่งขัน: การทำความเข้าใจในลักษณะของทีมและผู้เล่นที่จะแข่งขันมีความสำคัญอย่างยิ่ง ปัจจัยเช่นฟอร์มล่าสุด การเสถียรภาพของทีม และบางครั้งอาจต้องดูการช่วยเหลือของผู้บริหารเช่นสร้างสภาพบรรยากาศในทีม
วิเคราะห์ราคาต่อรอง: เมื่อทราบทีมแข่งขันแล้ว เช่นกันเปรียบเทียบราคาต่อรองจากหลายๆ บริษัทผู้ให้บริการชุมนุมกีฬา การที่มีข้อมูลเหล่านี้ช่วยให้คุณตัดสินใจได้ดีขึ้น
ผลการเยี่ยม: เวลาถือว่าการวิเคราะห์ถูกต้อง ต้องระวังอย่าเพิ่งโง่เผยให้ความว่าถูกอยู่บนเส้น ควรทดลองกับสถิติต่าง ๆ และคิดว่าจะมีความพอดีกับกิจกรรมการเล่นเกม
การวิเคราะห์ราคาบอลเป็นที่สำคัญอย่างยิ่งในการพนัน ผู้เด็กที่ใช้ความหวังในวิถีพนันออนไลน์ควรใช้วิธีและข้อความเหล่านี้เพื่อช่วยให้ประสบความสำเร็จในการเดิมพันบอลลุ้นบอล极.
0 notes
Text
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Random Post Redirect</title> </head> <body> <button onclick="redirectToRandomPost()">Random Post</button> <script> function redirectToRandomPost() { // Define the URL pattern for your posts var baseUrl = "https://wafact.com/posts/"; // Get the current…
View On WordPress
0 notes
Text
(function(d, s, id) { var js, bjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s);js.id = id; js.async = true; js.src = 'https://staging.topdrinks.nl/bb/loadbutton/index/access/1763445234511345'; js.onload = function() { new BuyButton( {redirectToProduct: '0', locale:'nl-nl', currency_code: 'EUR', storeId: '4', productIds:'5334,5333,5342,5345', baseUrl: 'https://staging.topdrinks.nl/', styles: '', vButtonText: 'View Details', miniCartText:'Cart', addToCartText:'Add To Cart', buyNowText:'Buy Now', itemInCartText:'Item In Cart', cButtonText:'Proceed To Checkout', noItemFoundText:'No items found in cart.', shippingInfoText:'', qtyText:'Qty', subTotalText:'Cart Subtotal', designTemplate: 1, staticUrl: 'https://staging.topdrinks.nl/media/buybutton', accessKey: '1763445234511345'} ); }; bjs.parentNode.insertBefore(js, bjs); }(document, "script", "buybutton-js"));
1 note
·
View note
Video
youtube
Could Not Resolve Host Mirrorlist.centos.org | Invalid baseurl for repo ...
2 notes
·
View notes
Text
Hướng dẫn cài đặt Visual Studio Code trên Linux
Được phát triển bởi Microsoft, Visual Studio Code là một IDE hay trình soạn thảo mã nguồn mở miễn phí – cho phép các nhà phát triển ứng dụng có thể viết code sử dụng vô số các ngôn ngữ khác nhau như: C/C++, Go, Pỵhon, Java,…
Trong bài viết này, mình sẽ hướng dẫn bạn cách cài đặt phần mềm Visual Studio Code trên Linux. Cụ thể hơn chút, là bạn sẽ biết cách cài đặt Visual Studio Code trên cả bản phân phối dựa trên Debian lẫn RedHAT.
Hướng dẫn cách cài đặt Visual Studio Code trên Debian, Ubuntu và Linux Mint
Phương pháp cài đặt Visual Studio Code trên các hệ thống dựa trên Debian thường được thực hiện bằng cách kích hoạt repository package Visual Studio Code sử dụng công cụ quản lý package apt.
$ sudo apt update
Một khi đã update xong hệ thống, tiến hành cài đặt các dependencies được yêu cầu thực hiện.
$ sudo apt install software-properties-common apt-transport-https
Tiếp theo, sử dụng lệnh wget để iport GPG key của Microsoft như dòng lệnh bên dưới đây:
$ sudo wget -q https://packages.microsoft.com/keys/microsoft.asc -O- | sudo apt-key add -
Với việc bổ sung GPG key của Microsoft, khi đó bật repository của Visual Studio Code bằng cách chạy câu lệnh sau:
$ sudo add-apt-repository "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main"
Một khi đã bật repository, cập nhật hệ thống và tiến hành cài đặt Visual Studio Code bằng cách chạy lệnh sau:
$ sudo apt update $ sudo apt install code
Do kích thước phần mềm này khá nặng, nên việc cài đặt phần mềm sẽ mất khoảng 5 phút đồng h��. Khi đã cài đặt thành công, hãy sử dụng trình quản lý ứng dụng để tìm kiếm công cụ Visual Studio Code và bấm vào icon để khởi chạy hoặc bạn có thể sử dụng lệnh “code“.

Hướng dẫn cài đặt Visual Code Studio trên CentOS, RHEL và Fedora
Quá trình cài đặt Visual Studiode Code dựa trên các bản phân phối RedHAT tương tự như cách cài đặt trên Ubuntu. Ngay lập tức, tiến hành cập nhật hệ thống bằng cách sử dụng câu lệnh sau:
$ sudo dnf update
Tiếp đó import GPG key của Microsoft bằng cách sử dụng câu lệnh rpm như bên dưới:
$ sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
Với GPG key của Microsft đã được cài đặt, tiến hành tạo file repository cho Visual Code Studio.
$ sudo vim /etc/yum.repos.d/vstudio_code.repo
Tiếp theo, chèn đoạn code sau vào file.
[code] name=Visual Studio Code baseurl=https://packages.microsoft.com/yumrepos/vscode enabled=1 gpgcheck=1 gpgkey=https://packages.microsoft.com/keys/microsoft.asc
Để cài đặt công cụ Visual Studio Code, chạy câu lệnh sau:
$ sudo dnf install code
Để sử dụng ứng dụng này, tương tự như trên cách cài đặt trên Ubuntu, chỉ cần vào phần quản lý ứng dụng và tìm kiếm Visual Studio Code rồi mở ra là thấy thôi.
Kết luận
Visual Studio Code là công cụ soạn thảo code giàu tính năng và mạnh mẽ – cho phép bạn phát triển ứng dụng trong một loạt các ngôn ngữ lập trình phổ biến. Đặc biệt đối với các nhà lập trình viên ngôn ngữ như C và python cực kỳ thích công cụ này.
The post Hướng dẫn cài đặt Visual Studio Code trên Linux appeared first on Quang Vũ Blog.
source https://blog.vu-review.com/visual-studio-code-linux.html
1 note
·
View note
Text
How to Install Elasticsearch on Linux CentOS
lasticsearch is an open-source distributed full-text search and analytics engine. It supports RESTful operations and allows you to store, search, and analyze big volumes of data in real-time. Elasticsearch is one of the most popular search engines powering applications that have complex search requirements such as big e-commerce stores and analytic applications.
This tutorial covers the installation of Elasticsearch on CentOS
Installing Java
Elasticsearch is a Java application, so the first step is to install Java.
Run the following as root or user with sudo privileges command to install the OpenJDK package:
sudo dnf install java-11-openjdk-devel
Verify the Java installation by printing the Java version:
java -version
The output should look something like this:
openjdk version "11.0.5" 2019-10-15 LTS OpenJDK Runtime Environment 18.9 (build 11.0.5+10-LTS) OpenJDK 64-Bit Server VM 18.9 (build 11.0.5+10-LTS, mixed mode, sharing)
Installing Elasticsearch
Elasticsearch is not available in the standard CentOS repositories. We’ll install it from the Elasticsearch RPM repository.
Import the repository’s GPG using the rpm command:
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
Open your text editor and create the repository file the /etc/yum.repos.d/ directory:
sudo nano /etc/yum.repos.d/elasticsearch.repo
Paste the following content into the file:
/etc/yum.repos.d/elasticsearch.repo
[elasticsearch-7.x] name=Elasticsearch repository for 7.x packages baseurl=https://artifacts.elastic.co/packages/7.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md
Save the file and close your text editor.
At the time of writing this article, the latest version of Elasticsearch is 7.6
. If you want to install a previous version of Elasticsearch, change 7.x in the command above with the version you need.
Now that the repository is enabled, install the Elasticsearch package by typing:
sudo dnf install elasticsearch
Once the installation process is complete, start, and enable the service:
sudo systemctl enable elasticsearch.service --now
To verify that Elasticsearch is running, use curl to send an HTTP request to port 9200 on localhost:
curl -X GET "localhost:9200/"
The output will look something like this:
{ "name" : "centos8.localdomain", "cluster_name" : "elasticsearch", "cluster_uuid" : "V_mfjn2PRJqX3PlZb_VD7w", "version" : { "number" : "7.6.0", "build_flavor" : "default", "build_type" : "rpm", "build_hash" : "7f634e9f44834fbc12724506cc1da681b0c3b1e3", "build_date" : "2020-02-06T00:09:00.449973Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
It may take 5-10 seconds for the service to start. If you see curl: (7) Failed to connect to localhost port 9200: Connection refused, wait for a few seconds and try again.
To view the messages logged by the Elasticsearch service, use the following command:
sudo journalctl -u elasticsearch
At this point, you have Elasticsearch installed on your CentOS server.
Configuring Elasticsearch
Elasticsearch data is stored in the /var/lib/elasticsearch directory, configuration files are located in /etc/elasticsearch.
By default, Elasticsearch is configured to listen on localhost only. If the client connecting to the database is also running on the same host and you are setting up a single node cluster, you don’t need to change the default configuration file.
Remote Access
Out of box Elasticsearch, does not implement authentication, so it can be accessed by anyone who can access the HTTP API. If you want to allow remote access to your Elasticsearch server, you will need to configure your firewall and allow access to the Elasticsearch port 9200 only from trusted clients.
For example, to allow connections only from 192.168.121.80, enter the following command:
Run the following command to allow assess from the remote trusted IP address on port 9200 :
sudo firewall-cmd --new-zone=elasticsearch --permanentsudo firewall-cmd --reloadsudo firewall-cmd --zone=elasticsearch --add-source=192.168.121.80/32 --permanentsudo firewall-cmd --zone=elasticsearch --add-port=9200/tcp --permanentsudo firewall-cmd --reload
Do not forget to change
192.168.121.80
with your remote IP Address.
Later, if you want to allow access from another IP Address use:
sudo firewall-cmd --zone=elasticsearch --add-source=<IP_ADDRESS> --permanentsudo firewall-cmd --reload
Once the firewall is configured, the next step is to edit the Elasticsearch configuration and allow Elasticsearch to listen for external connections.
To do so, open the elasticsearch.yml configuration file:
sudo nano /etc/elasticsearch/elasticsearch.yml
Search for the line that contains network.host, uncomment it, and change the value to 0.0.0.0:
/etc/elasticsearch/elasticsearch.yml
network.host: 0.0.0.0
If you have multiple network interfaces on your machine, specify the interface IP address to force Elasticsearch to listen only to the given interface.
Restart the Elasticsearch service for the changes to take effect:
sudo systemctl restart elasticsearch
That’s it. You can now connect to the Elasticsearch server from the remote location.
Conclusion
We’ve shown you how to install Elasticsearch on CentOS 8.
To learn more about Elasticsearch, visit the official documentation page.
If you hit a problem or have feedback, leave a comment below.
1 note
·
View note
Text
USATSI The Florida Gators established a brand new single-game program file for residence runs on Sunday, launching a mixed eight lengthy balls as a part of a 13-7 victory towards the Cincinnati Bearcats that accomplished a weekend sweep. Sophomore two-way participant Jac Caglianone performed a pivotal function in each endeavors, the file and the win, as he served because the afternoon's beginning pitcher and he hit three residence runs to take care of his early-season sizzling streak on the dish.Certainly, Caglianone went 3 for five with three residence runs and 5 runs batted in on Sunday. On the mound, he lasted into the fifth inning, tallying 4 ⅔ innings that noticed him enable three runs on two hits and 4 walks. He struck out six batters on 92 pitches. Prior to now, he is been clocked into the higher 90s along with his fastball.This is a have a look at Caglianone's home-run barrage towards the Bearcats: Caglianone, who won't be draft-eligible till 2024, entered Sunday having hit .375/.464/.792 with three residence runs in his first seven video games. He is now as much as six residence runs, one away from matching his complete in 28 video games final yr. Even together with Sunday, he is struck out solely 4 occasions in 33 journeys to the plate. In the meantime, Caglianone struck out 9 batters (and walked only one) in 6 ⅔ innings in his season debut as a pitcher. General, he is hitting .414 (12-29) with six residence runs on the plate, in addition to with 15 strikeouts and three earned runs (on 4 hits and 5 walks) in 11 ⅓ innings. Though Caglianone will not be a part of the 2023 draft, the Gators are certain to be well-represented this July. CBS Sports activities just lately ranked a pair of Gators within the prime 10 as a part of our preseason prime 30: outfielder Wyatt Langford checked in at No. 3, whereas right-hander Hurston Waldep grabbed the No. 7 slot. You possibly can take a look at all the prime 30 by clicking right here. require.config("baseUrl":"https://sportsfly.cbsistatic.com/fly-0416/bundles/sportsmediajs/js-build","config":"version":"fly/components/accordion":"1.0","fly/components/alert":"1.0","fly/components/base":"1.0","fly/components/carousel":"1.0","fly/components/dropdown":"1.0","fly/components/fixate":"1.0","fly/components/form-validate":"1.0","fly/components/image-gallery":"1.0","fly/components/iframe-messenger":"1.0","fly/components/load-more":"1.0","fly/components/load-more-article":"1.0","fly/components/load-more-scroll":"1.0","fly/components/loading":"1.0","fly/components/modal":"1.0","fly/components/modal-iframe":"1.0","fly/components/network-bar":"1.0","fly/components/poll":"1.0","fly/components/search-player":"1.0","fly/components/social-button":"1.0","fly/components/social-counts":"1.0","fly/components/social-links":"1.0","fly/components/tabs":"1.0","fly/components/video":"1.0","fly/libs/easy-xdm":"2.4.17.1","fly/libs/jquery.cookie":"1.2","fly/libs/jquery.throttle-debounce":"1.1","fly/libs/jquery.widget":"1.9.2","fly/libs/omniture.s-code":"1.0","fly/utils/jquery-mobile-init":"1.0","fly/libs/jquery.mobile":"1.3.2","fly/libs/backbone":"1.0.0","fly/libs/underscore":"1.5.1","fly/libs/jquery.easing":"1.3","fly/managers/ad":"2.0","fly/managers/components":"1.0","fly/managers/cookie":"1.0","fly/managers/debug":"1.0","fly/managers/geo":"1.0","fly/managers/gpt":"4.3","fly/managers/history":"2.0","fly/managers/madison":"1.0","fly/managers/social-authentication":"1.0","fly/utils/data-prefix":"1.0","fly/utils/data-selector":"1.0","fly/utils/function-natives":"1.0","fly/utils/guid":"1.0","fly/utils/log":"1.0","fly/utils/object-helper":"1.0","fly/utils/string-helper":"1.
0","fly/utils/string-vars":"1.0","fly/utils/url-helper":"1.0","libs/jshashtable":"2.1","libs/select2":"3.5.1","libs/jsonp":"2.4.0","libs/jquery/mobile":"1.4.5","libs/modernizr.custom":"2.6.2","libs/velocity":"1.2.2","libs/dataTables":"1.10.6","libs/dataTables.fixedColumns":"3.0.4","libs/dataTables.fixedHeader":"2.1.2","libs/dateformat":"1.0.3","libs/waypoints/infinite":"3.1.1","libs/waypoints/inview":"3.1.1","libs/waypoints/jquery.waypoints":"3.1.1","libs/waypoints/sticky":"3.1.1","libs/jquery/dotdotdot":"1.6.1","libs/jquery/flexslider":"2.1","libs/jquery/lazyload":"1.9.3","libs/jquery/maskedinput":"1.3.1","libs/jquery/marquee":"1.3.1","libs/jquery/numberformatter":"1.2.3","libs/jquery/placeholder":"0.2.4","libs/jquery/scrollbar":"0.1.6","libs/jquery/tablesorter":"2.0.5","libs/jquery/touchswipe":"1.6.18","libs/jquery/ui/jquery.ui.core":"1.11.4","libs/jquery/ui/jquery.ui.draggable":"1.11.4","libs/jquery/ui/jquery.ui.mouse":"1.11.4","libs/jquery/ui/jquery.ui.position":"1.11.4","libs/jquery/ui/jquery.ui.slider":"1.11.4","libs/jquery/ui/jquery.ui.sortable":"1.11.4","libs/jquery/ui/jquery.ui.touch-punch":"0.2.3","libs/jquery/ui/jquery.ui.autocomplete":"1.11.4","libs/jquery/ui/jquery.ui.accordion":"1.11.4","libs/jquery/ui/jquery.ui.tabs":"1.11.4","libs/jquery/ui/jquery.ui.menu":"1.11.4","libs/jquery/ui/jquery.ui.dialog":"1.11.4","libs/jquery/ui/jquery.ui.resizable":"1.11.4","libs/jquery/ui/jquery.ui.button":"1.11.4","libs/jquery/ui/jquery.ui.tooltip":"1.11.4","libs/jquery/ui/jquery.ui.effects":"1.11.4","libs/jquery/ui/jquery.ui.datepicker":"1.11.4","shim":"liveconnection/managers/connection":"deps":["liveconnection/libs/sockjs-0.3.4"],"liveconnection/libs/sockjs-0.3.4":"exports":"SockJS","libs/setValueFromArray":"exports":"set","libs/getValueFromArray":"exports":"get","fly/libs/jquery.mobile-1.3.2":["version!fly/utils/jquery-mobile-init"],"libs/backbone.marionette":"deps":["jquery","version!fly/libs/underscore","version!fly/libs/backbone"],"exports":"Marionette","fly/libs/underscore-1.5.1":"exports":"_","fly/libs/backbone-1.0.0":"deps":["version!fly/libs/underscore","jquery"],"exports":"Backbone","libs/jquery/ui/jquery.ui.tabs-1.11.4":["jquery","version!libs/jquery/ui/jquery.ui.core","version!fly/libs/jquery.widget"],"libs/jquery/flexslider-2.1":["jquery"],"libs/dataTables.fixedColumns-3.0.4":["jquery","version!libs/dataTables"],"libs/dataTables.fixedHeader-2.1.2":["jquery","version!libs/dataTables"],"https://sports.cbsimg.net/js/CBSi/app/VideoPlayer/AdobePass-min.js":["https://sports.cbsimg.net/js/CBSi/util/Utils-min.js"],"map":"*":"adobe-pass":"https://sports.cbsimg.net/js/CBSi/app/VideoPlayer/AdobePass-min.js","facebook":"https://connect.facebook.net/en_US/sdk.js","facebook-debug":"https://connect.facebook.net/en_US/all/debug.js","google":"https://apis.google.com/js/plusone.js","google-platform":"https://apis.google.com/js/client:platform.js","google-csa":"https://www.google.com/adsense/search/async-ads.js","google-javascript-api":"https://www.google.com/jsapi","google-client-api":"https://apis.google.com/js/api:client.js","gpt":"https://securepubads.g.doubleclick.net/tag/js/gpt.js","hlsjs":"https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.0.7/hls.js","recaptcha":"https://www.google.com/recaptcha/api.js?onload=loadRecaptcha&render=explicit","recaptcha_ajax":"https://www.google.com/recaptcha/api/js/recaptcha_ajax.js","supreme-golf":"https://sgapps-staging.supremegolf.com/search/assets/js/bundle.js","taboola":"https://cdn.taboola.com/libtrc/cbsinteractive-cbssports/loader.js","twitter":"https://platform.twitter.com/widgets.js","video-avia":"https://vidtech.cbsinteractive.com/avia-js/2.4.0/player/avia.min.js","video-avia-ui":"https://vidtech.cbsinteractive.com/avia-js/2.4.0/plugins/ui/avia.ui.min.js","video-avia-gam":"https://vidtech.cbsinteractive.com/avia-js/2.4.0/plugins/gam/avia.gam.min.js","video-avia-hls":"https://vidtech.cbsinteractive.com/avia-js/2.4.0/plugins/hls/avia.hls.min.js","video-avia-playlist":"https://vidtech.cbsinteractive.
com/avia-js/2.4.0/plugins/playlist/avia.playlist.min.js","video-ima3":"https://imasdk.googleapis.com/js/sdkloader/ima3.js","video-ima3-dai":"https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js","video-utils":"https://sports.cbsimg.net/js/CBSi/util/Utils-min.js","video-vast-tracking":"https://vidtech.cbsinteractive.com/sb55/vast-js/vtg-vast-client.js","waitSeconds":300); Source link
0 notes
Text
Airfryer bakjes
var bol_sitebar_v2={“id”:”bol_1673788178920″, “baseUrl”:”partner.bol.com”,”productId”:”9300000128067970″,”familyId”:””,”siteId”:”34986″,”target”:true,”rating”:true,”price”:true,”deliveryDescription”:true,”button”:true,”linkName”:”HYP.%20Inklapbaar%20Airfryer%20Siliconen%20Bakje%20-%20Com…”,”linkSubId”:””};https://partner.bol.com/promotion/static/js/partnerProductlinkV2.js
View On WordPress
0 notes
Text
Youtrack status

#YOUTRACK STATUS SOFTWARE#
#YOUTRACK STATUS FREE#
#YOUTRACK STATUS FREE#
Feel free to describe any challenges you encountered in the comments below. If you experience problems with this integration when using the latest version of either YouTrack or PractiTest, please report them here.Īt the same time, if you are able to set up this integration successfully with later versions of either app on this or any other operating system, we'd love to hear about it.
#YOUTRACK STATUS SOFTWARE#
The setup and functionality described here were verified by a Support Engineer from the YouTrack team in the following software environment: The integration between YouTrack and the PractiTest QA & test management system is provided and supported by the TestLink Development Team. Click the link to open the issue in YouTrack. The link shows the ID, status, and issue summary. The link to the YouTrack issue is shown in the Relevant bugs section. If you are already logged in to YouTrack, you are redirected to the New Issue page.Īfter you create the issue, enter the issue ID in TestLink and enter the issue ID and click the Add bug button.Ĭlick the Close button to return to the test execution window.Log in with your credentials to create an issue. If you are not logged in, you are redirected to the Dashboard.You can enter the ID for an existing issue or click the link to access YouTrack in a new window. When the test case is executed, the Bug management option is enabled.Ĭlick the icon to access the Add bug report dialog: When the integration is successfully configured, log in to TestLink and execute a test case. You can also safely delete all of the comments from the sample. If you encounter a problem, check the closing tags for slashes. The sample used invalid closing tags for comments. There was a known issue with the sample configuration that was provided by Test Link. To ensure that the integration works as expected, check your local configuration with the example shown here. Please remember that TestLink is an open-source application and its developers can change the template at any time. You can also click the Show configuration example link next to the Type drop-down list to show a similar template in the configuration dialog. Use the following template to configure the integration. Select the YouTrack integration as the issue tracker for your project.Select your TestLink project and edit it.Open the Test Project Management section.If you do not specify a project ID, you can only link existing issues to TestLink cases. Optionally, you can specify the ID of a project to which issues created in TestLink are added.Enter the baseURL of your YouTrack instance.To create new issues directly from TestLink, this user must have Create Issue permission in the YouTrack project, and the project ID must be stored in the configuration. To link existing issues from YouTrack to TestLink cases, this user must have Read Issue permission in the YouTrack project. Enter the credentials for the account that is used for logging in to YouTrack.In the Configuration field, provide the following information:.In the Create configuration dialog, enter a name for the configuration and select youtrack (interface: rest) from the Type drop-down list.Open the System > Issue Tracker Management page and click the Create button.Log in to your TestLink instance with an administrator account.If you use the TestLink test management system for quality assurance, you can integrate this system and use YouTrack to track bugs.

0 notes
Text
Redux observable

#Redux observable how to
#Redux observable full
Just take little help from our friend – documentation. If not, please keep in mind you can always mix and match the operators to get the desired behavior. That should cover most of the common use cases for making API requests. We can pass multiple promises to forkJoin, and it will wait for all the promises to be resolved and then emit an array of data. It is useful to keep the baseUrl configuration in one place and intercept the request and add an auth token. Using Redux Subspace with redux-observable is pretty similar to using it with Redux itself, except rather than subspacing the store, you need to subspace. We will create an Axios instance to have support for interceptors and baseUrl. Simple API Requestįirst, we will start by making simple API calls using Axios and redux-observable. If you are looking to setup redux-observable in your project, follow my article: Clean React Architecture with Redux, Immer, TypeScript, and Redux Observable. This article demonstrates how all of the above-mentioned things can be done with Axios and Redux-Observable. Our action is not a regular redux action, but an observable stream of actionsĬonst fetchUserEpic = action => action.Making API calls using Axios and Redux-Observable has proven useful for me, especially when it requires – polling an API or request cancellation or making multiple sequential requests, or making multiple parallel requests. (we use the "redux-actions"-library for easier creation of basic actionCreators)Ĭonst syncActionCreators = createActions() ACTION TYPES -Ĭonst FETCH_USERS_START = "FETCH_USERS_START" Ĭonst FETCH_USERS_SUCCESS = "FETCH_USERS_SUCCESS" Ĭonst FETCH_USERS_FAILURE = "FETCH_USERS_FAILURE" While the examples are fairly basic I assume that you already have a good grasp of how Redux itself works - otherwise I suggest familiarizing yourself with its concepts before continuing to read this blog post. I am not going to depict the process of integrating each middleware but rather focus on the way each middleware works.
#Redux observable how to
Therefore I am going to show how to fetch some sample data with each middleware. While I am going to showcase each library with a basic example, I will keep it fairly high level and wont go into detail about advanced operations, like cancellation or throttling (these might be the subject of a follow up blog post in the future). There are well-documented disadvantages to using global state. Advantages of Global State Like elm, redux manages global state.
#Redux observable full
Here's the full code, in case you want to see how to properly set up the redux-observable middleware. I am also going to ramble a bit about when their usage might be appropriate and about their respective pros and cons. redux-observable provides a more natural place for this. This blog post is supposed to shed some light on some of the more popular middlewares for async handling - namely Redux-Thunk, Redux-Saga, Redux-Observable and Redux-Loop - and the basic concepts behind them. There are quite a few very different middlewares out there to help with these tasks and their internal concepts vary quite a bit. Vanilla Redux alone is great to manage state, but does not have a built in way to handle asynchronous operations like AJAX-Requests. Redux is probably by far the most popular library to handle application state in React-apps, and while there are other solutions like MobX out there, we at Sandstorm currently fully rely on Redux.

0 notes