Skip to content
Snippets Groups Projects
Commit 40fa7c59 authored by Elisabethein's avatar Elisabethein
Browse files

Merge remote-tracking branch 'emergency-alert-application/Annabel' into Elisabet

# Conflicts:
#	EmergencyAlertApplication.jar
#	eaa_frontend/src/pages/AlertPage.vue
#	src/main/java/com/EmergencyAlertApplication/EAA/Configurations/SecurityConfig.java
parents 21f7b6d8 d8bc9ad2
No related branches found
No related tags found
No related merge requests found
Showing
with 523 additions and 17 deletions
......@@ -8,6 +8,7 @@ variables:
DB_PASSWORD: $DB_PASSWORD
JWT_SECRET: $JWT_SECRET
LOCATIONIQ_TOKEN: $LOCATION_TOKEN
FOLDERID: ${FOLDERID}
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/EAA
SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.PostgreSQLDialect
SPRING_JPA_HIBERNATE_DDL_AUTO: update
......@@ -52,6 +53,7 @@ test:
- export DB_PASSWORD=$DB_PASSWORD
- export JWT_SECRET=$JWT_SECRET
- export LOCATIONIQ_TOKEN=$LOCATION_TOKEN
- export FOLDERID=$FOLDERID
- export SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/EAA
# Wait for PostgreSQL to be ready
- sleep 30
......
......@@ -2,8 +2,11 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
id 'application'
}
mainClassName = 'com.EmergencyAlertApplication.EAA.DriveQuickstart'
group = 'com.EmergencyAlertApplication'
version = '0.0.1-SNAPSHOT'
......@@ -38,6 +41,12 @@ dependencies {
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.seleniumhq.selenium:selenium-java:4.26.0'
implementation 'com.google.api-client:google-api-client:2.0.0'
implementation 'com.google.oauth-client:google-oauth-client-jetty:1.34.1'
implementation 'com.google.apis:google-api-services-drive:v3-rev20220815-2.0.0'
implementation 'com.google.auth:google-auth-library-oauth2-http:1.14.0'
}
def waitForServer(String urlString, int port) {
......@@ -139,6 +148,7 @@ tasks.test {
environment 'DB_PASSWORD', System.getenv('DB_PASSWORD')
environment 'JWT_SECRET', System.getenv('JWT_SECRET')
environment 'LOCATIONIQ_TOKEN', System.getenv('LOCATIONIQ_TOKEN')
environment 'FOLDERID', System.getenv('FOLDERID')
}
test {
......
......@@ -10,6 +10,7 @@ services:
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
LOCATIONIQ_TOKEN: ${LOCATIONIQ_TOKEN}
FOLDERID: ${FOLDERID}
SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.PostgreSQLDialect
SPRING_JPA_HIBERNATE_DDL_AUTO: update
ports:
......
......@@ -87,6 +87,22 @@
<label for="status"><strong>Juhtunu kirjeldus: </strong></label>
<span>{{ localTicket.description }}</span>
</div>
<!--
<div class="form-group">
<label for="status"><strong>Piltide info: </strong></label>
<p>{{localTicket.id }}</p>
<p><strong>Picture ID:</strong> {{ image.id }}</p>
<div v-if="localTicket.images && localTicket.images.length">
<div class="image-container" v-for="(image, index) in localTicket.images" :key="index">
<p>{{ image.name }}</p>
<p><a :href="'https://drive.google.com/file/d/' + image.id + '/view'" target="_blank">Vaata pilti</a></p>
</div>
</div>
<div v-else>
<span>Ühtegi pilti ei ole lisatud</span>
</div>
</div>
-->
</div>
<div v-if="localTicket.upperSpecies || localTicket.region || localTicket.tags || localTicket.resolution" class="tags">
......@@ -177,6 +193,7 @@ export default {
data() {
return {
localTicket: {...this.ticket},
images: [],
};
},
watch: {
......@@ -191,6 +208,7 @@ export default {
},
mounted() {
console.log(this.localTicket.volunteer); // Log on mount
//this.fetchTicketImages();
},
methods: {
formatDate(dateStr){
......
......@@ -20,9 +20,10 @@
<input type="text" id="animals" v-model="formData.animals" required placeholder="Kirjuta siia, millise looma või linnuga tegu võib olla..."/>
</div>
<!-- Pictures-->
<div class="form-group">
<label for="pictures">Pildid</label>
<input type="file" id="pictures" multiple accept="image/*" @change="handleFileUpload"/>
<input type="file" id="pictures" multiple accept=".jpeg,.jpg" @change="handleFileUpload"/>
</div>
<!-- Where (map)?-->
......@@ -87,12 +88,14 @@
type="button"
:class="{ active: canWait }"
@click="setCanWait(true)"
>Jah</button>
>Jah
</button>
<button
type="button"
:class="{ active: !canWait }"
@click="setCanWait(false)"
>Ei</button>
>Ei
</button>
</div>
</div>
......@@ -118,7 +121,7 @@
</template>
<script>
import { nextTick } from "vue";
import {nextTick} from "vue";
export default {
name: "AlertPage",
......@@ -254,14 +257,11 @@ export default {
phone: this.formData.phone,
email: this.formData.email,
canWait: this.canWait,
pictures: this.uploadedImages, // Korrigeerimine vastavalt piltide käsitlemisele
pictures: [], // Algväärtusena tühi massiiv
latitude: this.formData.latitude,
longitude: this.formData.longitude,
};
// Append uploaded images
this.uploadedImages.forEach((image) => {
alertData.append('pictures', image); // Ensure image is a File object
});
const response = await fetch('http://localhost:8080/api/tickets/add', {
//const response = await fetch('api/tickets/add', {
......@@ -287,6 +287,12 @@ export default {
});
}
// Piltide üleslaadimise ja ID-de saamine
const uploadedImageIds = await this.uploadImages(result.id);
alertData.pictures = uploadedImageIds; // Lisa piltide ID-d alertData objektile
// Vorm tühjendatakse
this.formData = {
reason: '',
......@@ -312,6 +318,83 @@ export default {
}
},
async handleFileUpload(event) {
const files = event.target.files;
const allowedTypes = ["image/jpeg", "image/heif", "image/heic", "image/png"];
const validFiles = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
if (allowedTypes.includes(file.type)) {
validFiles.push(file);
} else {
alert(`${file.name} ei ole lubatud failiformaadis! Palun laadige üles ainult JPEG, HEIF või PNG faile.`);
}
}
// Salvesta valideeritud failid
this.uploadedImages = validFiles;
},
async uploadImages(ticketId) {
const uploadedImageIds = [];
try {
// Hangi folderId serverist
const folderIdResponse = await fetch('http://localhost:8080/api/get-folderId');
if (!folderIdResponse.ok) {
throw new Error('Failed to fetch folder ID');
}
const folderId = await folderIdResponse.text();
// Failide üleslaadimine
for (let i = 0; i < this.uploadedImages.length; i++) {
const file = this.uploadedImages[i];
const formData = new FormData();
const date = new Date();
// Genereeri uus failinimi
const newFileName = `alert_${date.getFullYear()}-${(date.getMonth() + 1)
.toString()
.padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}_${date
.getHours()
.toString()
.padStart(2, '0')}-${date.getMinutes().toString().padStart(2, '0')}-${date
.getSeconds()
.toString()
.padStart(2, '0')}_${i + 1}`;
formData.append('file', file, newFileName);
// Lisa folderId POST-päringusse
formData.append('folderId', folderId);
// Lisa ticketId POST-päringusse
formData.append('ticketId', ticketId);
// Faili üleslaadimine
const response = await fetch('http://localhost:8080/api/uploadToDrive', {
method: 'POST',
body: formData,
});
if (!response.ok) {
throw new Error('Failed to upload file');
}
const data = await response.json();
uploadedImageIds.push(data.fileId);
}
console.log('Uploaded image IDs:', uploadedImageIds); // Logi kõik ID-d
} catch (error) {
console.error('Error:', error);
}
return uploadedImageIds; // Tagasta üleslaaditud failide ID-d
}
},
};
......
......@@ -30,6 +30,9 @@ public class SecurityConfig {
@Value("${LOCATIONIQ_TOKEN}")
private String LOCATIONIQ_TOKEN;
@Value("${FOLDERID}")
private String FOLDERID;
private final UserRepository userRepository;
private final UserToRoleService userToRoleService;
private final UserToRegionService userToRegionService;
......@@ -88,7 +91,10 @@ public class SecurityConfig {
.requestMatchers("/api/resolutions/all").permitAll()
.requestMatchers("/api/species/all").permitAll()
.requestMatchers("/api/tickets/add").permitAll()
.requestMatchers("/api/uploadToDrive").permitAll()
.requestMatchers("/api/filtered").permitAll()
.requestMatchers("/api/get-folderId").permitAll()
.anyRequest().authenticated()) // Protect other requests
.addFilter(customAuthenticationFilter)
.addFilterBefore(new JwtAuthorizationFilter(jwtSecret, userDetailsService), UsernamePasswordAuthenticationFilter.class);
......
package com.EmergencyAlertApplication.EAA.Controllers;
import com.EmergencyAlertApplication.EAA.Entities.Picture;
import com.EmergencyAlertApplication.EAA.Entities.Ticket;
import com.EmergencyAlertApplication.EAA.Repositories.PictureRepository;
import com.EmergencyAlertApplication.EAA.Services.GoogleDriveService;
import com.EmergencyAlertApplication.EAA.Services.PictureToTicketService;
import com.EmergencyAlertApplication.EAA.Services.TicketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/api")
public class FileUploadController {
@Autowired
private PictureRepository pictureRepository;
@Autowired
private PictureToTicketService pictureToTicketService;
@Autowired
private TicketService ticketService;
@PostMapping("/uploadToDrive")
public ResponseEntity<Map<String, String>> uploadFileToDrive(@RequestParam("file") MultipartFile file,
String folderId,
@RequestParam("ticketId") UUID ticketId) {
try {
// Faili üleslaadimine Google Drive'i
String fileId = GoogleDriveService.uploadFile(file.getOriginalFilename(), file, folderId);
// Salvestame faili info andmebaasi
Picture picture = new Picture();
picture.setDriveId(fileId);
picture.setName(file.getOriginalFilename());
pictureRepository.save(picture);
// Ticketi ja pildi sidumine
Ticket ticket = ticketService.getTicketById(ticketId);
pictureToTicketService.linkPictureToTicket(picture, ticket);
// Tagasta faili ID
Map<String, String> response = new HashMap<>();
response.put("fileId", fileId);
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.singletonMap("error", "Failed to upload file to Google Drive"));
}
}
}
\ No newline at end of file
......@@ -35,11 +35,19 @@ public class SecurityController {
@Value("${LOCATIONIQ_TOKEN}")
private String LOCATIONIQ_TOKEN;
@Value("${FOLDERID}")
private String FOLDERID;
@GetMapping("/get-key")
public String getKey() {
return LOCATIONIQ_TOKEN;
}
@GetMapping("/get-folderId")
public String getFolderKey() {
return FOLDERID;
}
@PostMapping("/login")
public ResponseEntity<Object> login(@RequestBody LoginRequest loginRequest) {
// Log the email being used for login
......
......@@ -3,19 +3,15 @@ package com.EmergencyAlertApplication.EAA.Controllers;
import com.EmergencyAlertApplication.EAA.DTOs.AlertDTO;
import com.EmergencyAlertApplication.EAA.DTOs.EditMyTicketDTO;
import com.EmergencyAlertApplication.EAA.DTOs.EditTicketDTO;
import com.EmergencyAlertApplication.EAA.DTOs.EditUserDTO;
import com.EmergencyAlertApplication.EAA.Entities.*;
import com.EmergencyAlertApplication.EAA.Services.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.nio.file.AccessDeniedException;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/tickets")
......@@ -187,7 +183,7 @@ public class TicketController {
return ResponseEntity.notFound().build();
}
Status status = statusService.findByName(editTicketDTO.getStatus());;
Status status = statusService.findByName(editTicketDTO.getStatus());
ticket.setStatus(status);
if (ticket.getCloseDate() == null && Objects.equals(status.getName(), "Lõpetatud")) {
......@@ -279,7 +275,7 @@ public class TicketController {
return ResponseEntity.notFound().build();
}
Status status = statusService.findByName(editMyTicketDTO.getStatus());;
Status status = statusService.findByName(editMyTicketDTO.getStatus());
ticket.setStatus(status);
if (ticket.getCloseDate() == null && Objects.equals(status.getName(), "Lõpetatud")) {
......
package com.EmergencyAlertApplication.EAA;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
/* class to demonstrate use of Drive files list API */
public class DriveQuickstart { //TODO KUI EI OLE KASUTUSES SIIS KUSTUTADA!
/**
* Application name.
*/
public static final String APPLICATION_NAME = "Google Drive API Java Quickstart";
/**
* Global instance of the JSON factory.
*/
public static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
/**
* Directory to store authorization tokens for this application.
*/
private static final String TOKENS_DIRECTORY_PATH = "tokens";
/**
* Global instance of the scopes required by this quickstart.
* If modifying these scopes, delete your previously saved tokens/ folder.
*/
private static final List<String> SCOPES = Arrays.asList(
DriveScopes.DRIVE_FILE, // Full access to files and folders created by the app
DriveScopes.DRIVE // Full access to the user's drive
);
private static final String CREDENTIALS_FILE_PATH = "/credentials.json";
/**
* Creates an authorized Credential object.
*
* @param HTTP_TRANSPORT The network HTTP Transport.
* @return An authorized Credential object.
* @throws IOException If the credentials.json file cannot be found.
*/
public static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT)
throws IOException {
// Load client secrets.
InputStream in = DriveQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
//returns an authorized Credential object.
return credential;
}
public static void main(String... args) throws IOException, GeneralSecurityException {
}
public static String uploadFile(String localFilePath, String fileName, String folderId) throws IOException, GeneralSecurityException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
File fileMetadata = new File();
fileMetadata.setName(fileName);
fileMetadata.setParents(Collections.singletonList(folderId)); // Määrame sihtkausta
java.io.File filePath = new java.io.File(localFilePath);
FileContent mediaContent = new FileContent("image/jpeg", filePath);
try {
File file = service.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());
return file.getId();
} catch (GoogleJsonResponseException e) {
System.err.println("Unable to upload file: " + e.getDetails());
throw e;
}
}
}
\ No newline at end of file
package com.EmergencyAlertApplication.EAA.Entities;
import jakarta.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "pictures")
public class Picture {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String driveId;
private String name;
public Picture(UUID id, String driveId, String name) {
this.id = id;
this.driveId = driveId;
this.name = name;
}
public Picture() {
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDriveId() {
return driveId;
}
public void setDriveId(String driveId) {
this.driveId = driveId;
}
}
package com.EmergencyAlertApplication.EAA.Entities;
import jakarta.persistence.*;
import java.util.UUID;
@Entity
@Table(name = "pictureToTicket")
public class PictureToTicket {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "picture_id", referencedColumnName = "id", nullable = false)
private Picture picture;
@ManyToOne
@JoinColumn(name = "ticket_id", referencedColumnName = "id", nullable = false)
private Ticket ticket;
public PictureToTicket(UUID id, Picture picture, Ticket ticket) {
this.id = id;
this.picture = picture;
this.ticket = ticket;
}
public PictureToTicket() {
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public Picture getPicture() {
return picture;
}
public void setPicture(Picture picture) {
this.picture = picture;
}
public Ticket getTicket() {
return ticket;
}
public void setTicket(Ticket ticket) {
this.ticket = ticket;
}
}
......@@ -50,7 +50,6 @@ public class Ticket {
private Timestamp createdAt;
private String history;
private boolean hospital;
//TODO: pictures asi
public Ticket() {
}
......
package com.EmergencyAlertApplication.EAA.Repositories;
import com.EmergencyAlertApplication.EAA.Entities.Picture;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface PictureRepository extends JpaRepository<Picture, Long> {
}
package com.EmergencyAlertApplication.EAA.Repositories;
import com.EmergencyAlertApplication.EAA.Entities.PictureToTicket;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.UUID;
public interface PictureToTicketRepository extends JpaRepository<PictureToTicket, UUID> {
List<PictureToTicket> findByTicketId(UUID ticketId);
}
package com.EmergencyAlertApplication.EAA.Services;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import org.springframework.web.multipart.MultipartFile;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import static com.EmergencyAlertApplication.EAA.DriveQuickstart.*;
public class GoogleDriveService {
public static String uploadFile(String fileName, MultipartFile file, String folderId) throws IOException, GeneralSecurityException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
File fileMetadata = new File();
fileMetadata.setName(fileName);
fileMetadata.setParents(Collections.singletonList(folderId));
java.io.File tempFile = new java.io.File(file.getOriginalFilename());
try (FileOutputStream outputStream = new FileOutputStream(tempFile)) {
outputStream.write(file.getBytes());
}
FileContent mediaContent = new FileContent(file.getContentType(), tempFile);
try {
File uploadedFile = service.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
return uploadedFile.getId();
} catch (GoogleJsonResponseException e) {
throw new IOException("Unable to upload file: " + e.getDetails());
}
}
}
package com.EmergencyAlertApplication.EAA.Services;
import com.EmergencyAlertApplication.EAA.Entities.Picture;
import com.EmergencyAlertApplication.EAA.Entities.PictureToTicket;
import com.EmergencyAlertApplication.EAA.Entities.Ticket;
import com.EmergencyAlertApplication.EAA.Repositories.PictureToTicketRepository;
import org.springframework.stereotype.Service;
@Service
public class PictureToTicketService {
private final PictureToTicketRepository pictureToTicketRepository;
public PictureToTicketService(PictureToTicketRepository pictureToTicketRepository) {
this.pictureToTicketRepository = pictureToTicketRepository;
}
public void linkPictureToTicket(Picture picture, Ticket ticket) {
PictureToTicket pictureToTicket = new PictureToTicket();
pictureToTicket.setPicture(picture);
pictureToTicket.setTicket(ticket);
pictureToTicketRepository.save(pictureToTicket);
}
}
......@@ -79,4 +79,4 @@ public class TicketService {
public List<Region> getAllRegions() {
return regionRepository.findAll();
}
}
}
......@@ -4,6 +4,7 @@ spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
JWT_SECRET=${JWT_SECRET}
LOCATIONIQ_TOKEN=${LOCATIONIQ_TOKEN}
FOLDERID=${FOLDERID}
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
logging.level.org.springframework.security=DEBUG
......
{"web":{"client_id":"258271286525-4rv7vre1585jcfd5809di62avfkrv9ef.apps.googleusercontent.com","project_id":"tarkvaraprojekti-pildid","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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"}}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment