Merged PR 81: Oauth

This commit is contained in:
Dominic Villemure
2024-06-27 23:16:39 +00:00
13 changed files with 832 additions and 251 deletions

View File

@@ -1 +0,0 @@
VITE_API_URL=https://localhost:5001/

4
.env.dist Normal file
View File

@@ -0,0 +1,4 @@
VITE_API_URL=https:
VITE_STRIPE_API_KEY=
VITE_GOOGLE_CLIENT_ID=
VITE_FACEBOOK_APP_ID

View File

@@ -1 +0,0 @@
VITE_API_URL=https://hutopy.azurewebsites.net/

5
.gitignore vendored
View File

@@ -27,3 +27,8 @@ coverage
*.sw?
*.tsbuildinfo
# .Env files
.env.development
.env.production
.env

938
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,10 +11,12 @@
"dependencies": {
"@mdi/font": "^7.4.47",
"@stripe/stripe-js": "^3.0.10",
"@xtiannyeto/vue-auth-social": "^0.1.9",
"axios": "^1.6.7",
"pinia": "^2.1.7",
"vue": "^3.4.15",
"vue-router": "^4.2.5",
"vue3-google-login": "^2.0.26",
"vuetify": "^3.5.6"
},
"devDependencies": {
@@ -26,4 +28,4 @@
"tailwindcss": "^3.4.1",
"vite": "^5.2.11"
}
}
}

View File

@@ -9,6 +9,7 @@ import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import clientPlugin from './plugins/api.js'
import vueGoogleOauth from 'vue3-google-login'
const vuetify = createVuetify({
components,
@@ -20,6 +21,10 @@ const app = createApp(App);
// Create an axios client preconfigured to the Hutopy API.
app.use(clientPlugin);
app.use(vueGoogleOauth, {
clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID,
});
app.use(createPinia());
app.use(vuetify);
app.use(router);

View File

@@ -1,50 +1,64 @@
import { defineStore } from 'pinia';
const baseUrl = '/api/Users';
const baseUrl = '/api';
export const auth = defineStore({
id: 'auth',
state: () => ({
user: null,
refreshTokenTimeout: null
user: "",
refreshTokenTimeout: 0
}),
actions: {
// TODO: Fix login methods
async login(client, email, password) {
const requestBody = {
email: email,
emailAddress: email,
password: password
};
try {
const response = await client.post(`${baseUrl}/login`, requestBody)
this.user = {
accessToken: response.data.accessToken,
refreshToken: response.data.refreshToken,
email: email
}
localStorage.setItem('jwt', this.user.accessToken);
this.startRefreshTokenTimer();
} catch (error) {
throw new Error('Login failed.')
const response = await client.post(`${baseUrl}/users/login`, requestBody)
this.user = {
accessToken: response.data,
}
},
logout() {
localStorage.setItem('jwt', '');
this.stopRefreshTokenTimer();
this.user = null;
},
async refreshToken(client) {
const response = await client.post(`${baseUrl}/refresh`, {});
this.user.accessToken = response.accessToken;
localStorage.setItem('jwt', this.user.accessToken);
this.startRefreshTokenTimer();
},
async loginGoogle(client, accessToken) {
const response = await client.post(`${baseUrl}/google/sign-in`, {accessToken: accessToken})
this.user = {
accessToken: response.data.accessToken,
refreshToken: response.data.refreshToken,
email: response.data.email
}
localStorage.setItem('jwt', this.user.accessToken);
this.startRefreshTokenTimer();
},
logout() {
localStorage.setItem('jwt', '');
this.user = null;
this.stopRefreshTokenTimer();
},
async refreshToken(client) {
const response = await client.post(`${baseUrl}/users/refresh`);
this.user.accessToken = response.accessToken;
localStorage.setItem('jwt', this.user.accessToken);
this.startRefreshTokenTimer();
},
startRefreshTokenTimer() {
const timeout = 50 * 1000;
this.refreshTokenTimeout = setTimeout(this.refreshToken, timeout);
},
stopRefreshTokenTimer() {
clearTimeout(this.refreshTokenTimeout);
}

View File

@@ -3,12 +3,12 @@
<div class="sm:flex hidden items-center justify-between flex-col"
style="background-color: #f4f4f4; margin-top: 3%;">
<body style="background-color: #f4f4f4;">
<div style="background-color: #f4f4f4;">
<v-container style=" background-color: #f4f4f4;">
<v-row align="center" justify="center">
<!-- Header -->
<v-col cols="8" lg="8" md="10" sm="10" xs="10" style=" align-items: center; ">
<img class="login-picture" src="/images/hutopymedia/loginpage/loginhutopy.png">
<img class="login-picture" src="/images/hutopymedia/loginpage/loginhutopy.png" alt="">
</v-col>
<!-- Connexion-objects -->
@@ -36,6 +36,14 @@
<v-btn color="#6b0065" class="ma-2 btnhome">Accueil</v-btn>
</router-link>
<v-btn color="primary" class="ma-2 btnhome" @click="login">Login</v-btn>
<GoogleLogin :callback="googleCallback" popup-type="TOKEN">
<v-btn color="primary" class="ma-2 btnhome">Google Login</v-btn>
</GoogleLogin>
<!-- <FacebookAuth :appId="facebookAppId" @on-submit="facebookCallback">-->
<!-- <v-btn color="primary" class="ma-2 btnhome">Facebook Login</v-btn>-->
<!-- </FacebookAuth>-->
</v-card-actions>
<div class="text-center">
<h2 class="text-center display-3 h2pasinscrit">Pas encore inscrit?</h2>
@@ -48,7 +56,7 @@
</v-row>
</v-container>
</body>
</div>
<FooterLayout></FooterLayout>
</div>
@@ -92,10 +100,12 @@
<script setup>
import FooterLayout from '@/layouts/FooterLayout.vue';
import { useClient } from "@/plugins/api.js";
import { auth } from '@/stores/auth.js';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import {auth} from '@/stores/auth.js';
import {ref} from 'vue';
import {useRouter} from 'vue-router';
import {useClient} from "@/plugins/api.js";
import {GoogleLogin} from "vue3-google-login";
import { FacebookAuth } from '@xtiannyeto/vue-auth-social';
const api = useClient()
@@ -106,14 +116,27 @@ let user = ref({});
let errorSnackBar = ref(false);
async function login() {
// TODO: Make the store handle errors
try {
await store.login(api, user.value.email, user.value.password)
router.push('/');
await router.push('/');
} catch (error) {
errorSnackBar.value = true;
}
}
const googleCallback = async (response) => {
// TODO: Make the store handle errors
await store.loginGoogle(api, response["access_token"])
await router.push("/");
}
const facebookAppId = import.meta.env.VITE_FACEBOOK_APP_ID;
const facebookCallback = async (response) => {
console.log("User Successfully Logged In" , response)
}
</script>
<style scoped>

View File

@@ -55,8 +55,7 @@ const isPaymentDialogActive = ref(false);
var checkout;
onMounted(async () => {
// I removed api key to push. Need to get it from backend.
stripe = await loadStripe('');
stripe = await loadStripe(import.meta.env.VITE_STRIPE_API_KEY);
})
const fetchClientSecret = async () => {

View File

@@ -938,4 +938,4 @@ let navigationItems = [
margin-left: 40px;
}
}
</style>
</style>

View File

@@ -391,25 +391,13 @@
<script async setup>
import DefaultLayout from '@/layouts/DefaultLayout.vue';
import FooterLayout from '@/layouts/FooterLayout.vue';
import { useClient } from "@/plugins/api.js";
import { ref } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter()
const client = useClient();
let itemList = ref([]);
let errorNoAccessSnackBar = ref(false);
async function callBackend() {
try {
const response = await client.get('/api/JoinUs?PageNumber=1&PageSize=10');
itemList.value = response.data.items;
} catch (error) {
errorNoAccessSnackBar.value = true;
}
}
const goToLoginPage = () => {
router.push('/login');
}

View File

@@ -18,7 +18,8 @@ export default defineConfig(({ mode }) => {
},
define: {
// Define a global constant __APP_ENV__ based on loaded environment variables
VITE_API_URL: JSON.stringify(env.VITE_API_URL)
VITE_API_URL: JSON.stringify(env.VITE_API_URL),
VITE_STRIPE_API_KEY: JSON.stringify(env.VITE_STRIPE_API_KEY)
}
}
})