diff --git a/fittrackee_client/src/components/User/UserApps/AddUserApp.vue b/fittrackee_client/src/components/User/UserApps/AddUserApp.vue
new file mode 100644
index 00000000..16230d1e
--- /dev/null
+++ b/fittrackee_client/src/components/User/UserApps/AddUserApp.vue
@@ -0,0 +1,170 @@
+
+
+
{{ $t('oauth2.ADD_A_NEW_APP') }}
+
+
+
+
+
+
+
diff --git a/fittrackee_client/src/components/User/UserApps/UserApp.vue b/fittrackee_client/src/components/User/UserApps/UserApp.vue
new file mode 100644
index 00000000..92ba5b23
--- /dev/null
+++ b/fittrackee_client/src/components/User/UserApps/UserApp.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
+ - {{ $t('oauth2.APP.CLIENT_ID') }}:
+ - {{ client.client_id }}
+ - {{ capitalize($t('oauth2.APP.ISSUE_AT')) }}:
+ -
+ {{
+ format(
+ getDateWithTZ(client.issued_at, authUser.timezone),
+ 'dd/MM/yyyy HH:mm'
+ )
+ }}
+
+ - {{ $t('oauth2.APP.NAME') }}:
+ - {{ client.name }}
+ - {{ $t('oauth2.APP.DESCRIPTION') }}:
+ -
+ {{
+ client.client_description
+ ? client.client_description
+ : $t('oauth2.NO_DESCRIPTION')
+ }}
+
+ - {{ $t('oauth2.APP.URL') }}:
+ - {{ client.website }}
+ - {{ $t('oauth2.APP.REDIRECT_URL') }}:
+ -
+ {{ client.redirect_uris.length > 0 ? client.redirect_uris[0] : '' }}
+
+ - {{ $t('oauth2.APP.SCOPE.LABEL') }}:
+ - {{ client.scope }}
+
+
+
+
+
+
+
+
{{ $t('oauth2.NO_APP') }}
+
+
+
+
+
+
+
+
diff --git a/fittrackee_client/src/components/User/UserApps/UserAppsList.vue b/fittrackee_client/src/components/User/UserApps/UserAppsList.vue
index a99c46f8..ac1b1ae1 100644
--- a/fittrackee_client/src/components/User/UserApps/UserAppsList.vue
+++ b/fittrackee_client/src/components/User/UserApps/UserAppsList.vue
@@ -3,7 +3,9 @@
{{ $t('oauth2.APPS_LIST') }}
-
- {{ client.name }}
+
+ {{ client.name }}
+
{{ $t('oauth2.APP.ISSUE_AT') }}
{{
@@ -17,7 +19,12 @@
{{ $t('oauth2.NO_APPS') }}
-
+
+
+
+
@@ -92,11 +99,16 @@
.app-issued-at {
font-size: 0.85em;
font-style: italic;
+ padding-left: $default-padding;
}
.apps-list {
font-size: 1.05em;
font-weight: bold;
}
+ .app-list-buttons {
+ display: flex;
+ gap: $default-padding;
+ }
.no-apps {
font-style: italic;
}
diff --git a/fittrackee_client/src/components/User/UserApps/index.vue b/fittrackee_client/src/components/User/UserApps/index.vue
index 62aa00bd..5375cea3 100644
--- a/fittrackee_client/src/components/User/UserApps/index.vue
+++ b/fittrackee_client/src/components/User/UserApps/index.vue
@@ -5,14 +5,23 @@
diff --git a/fittrackee_client/src/components/User/UserProfileTabs.vue b/fittrackee_client/src/components/User/UserProfileTabs.vue
index ea963045..2fff76f7 100644
--- a/fittrackee_client/src/components/User/UserProfileTabs.vue
+++ b/fittrackee_client/src/components/User/UserProfileTabs.vue
@@ -7,7 +7,7 @@
type="radio"
:id="tab"
:name="tab"
- :checked="selectedTab === tab"
+ :checked="selectedTab.split('/')[0] === tab"
:disabled="disabled"
@input="$router.push(getPath(tab))"
/>
diff --git a/fittrackee_client/src/locales/en/oauth2.json b/fittrackee_client/src/locales/en/oauth2.json
index b50c72e0..9f9cd2e8 100644
--- a/fittrackee_client/src/locales/en/oauth2.json
+++ b/fittrackee_client/src/locales/en/oauth2.json
@@ -1,7 +1,23 @@
{
- "APP":{
- "ISSUE_AT": "issued at"
+ "ADD_A_NEW_APP": "Add a new OAuth2 application",
+ "APP": {
+ "CLIENT_ID": "Client ID",
+ "DESCRIPTION": "Application description",
+ "ISSUE_AT": "issue at",
+ "NAME": "Application name",
+ "REDIRECT_URL": "Redirect URI",
+ "SCOPE": {
+ "LABEL": "Scope",
+ "READ": "read",
+ "WRITE": "write"
+ },
+ "URL": "Application URI"
},
+ "APP_DELETION_CONFIRMATION": "Are you sure you want to delete this app?",
"APPS_LIST": "OAuth2 applications",
- "NO_APPS": "No applications"
+ "DELETE_APP": "Delete application",
+ "NEW_APP": "New OAuth App",
+ "NO_DESCRIPTION": "no description",
+ "NO_APP": "Application not found!",
+ "NO_APPS": "no applications"
}
\ No newline at end of file
diff --git a/fittrackee_client/src/locales/fr/oauth2.json b/fittrackee_client/src/locales/fr/oauth2.json
index e23a545c..d8037175 100644
--- a/fittrackee_client/src/locales/fr/oauth2.json
+++ b/fittrackee_client/src/locales/fr/oauth2.json
@@ -1,7 +1,23 @@
{
- "APP":{
- "ISSUE_AT": "créée le"
+ "ADD_A_NEW_APP": "Ajouter une nouvelle application OAuth2",
+ "APP": {
+ "CLIENT_ID": "Identifiant client",
+ "DESCRIPTION": "Application description",
+ "ISSUE_AT": "créée le",
+ "NAME": "Nom de l'application",
+ "REDIRECT_URL": "URL de redirection",
+ "SCOPE": {
+ "LABEL": "Scope",
+ "READ": "lecture",
+ "WRITE": "écriture"
+ },
+ "URL": "URL de l'application"
},
+ "APP_DELETION_CONFIRMATION": "Êtes-vous sûr de vouloir supprimer cette application ?",
"APPS_LIST": "Applications OAuth2",
+ "DELETE_APP": "Supprimer l'application",
+ "NEW_APP": "Ajouter une App OAuth",
+ "NO_DESCRIPTION": "pas de description",
+ "NO_APP": "Application introuvable !",
"NO_APPS": "pas de applications"
}
\ No newline at end of file
diff --git a/fittrackee_client/src/router/index.ts b/fittrackee_client/src/router/index.ts
index 358b591e..775539f9 100644
--- a/fittrackee_client/src/router/index.ts
+++ b/fittrackee_client/src/router/index.ts
@@ -12,7 +12,9 @@ import UserAccountEdition from '@/components/User/ProfileEdition/UserAccountEdit
import UserInfosEdition from '@/components/User/ProfileEdition/UserInfosEdition.vue'
import UserPictureEdition from '@/components/User/ProfileEdition/UserPictureEdition.vue'
import UserPreferencesEdition from '@/components/User/ProfileEdition/UserPreferencesEdition.vue'
+import AddUserApp from '@/components/User/UserApps/AddUserApp.vue'
import UserApps from '@/components/User/UserApps/index.vue'
+import UserApp from '@/components/User/UserApps/UserApp.vue'
import UserAppsList from '@/components/User/UserApps/UserAppsList.vue'
import UserSportPreferences from '@/components/User/UserSportPreferences.vue'
import store from '@/store'
@@ -156,6 +158,16 @@ const routes: Array = [
name: 'UserAppsList',
component: UserAppsList,
},
+ {
+ path: ':clientId',
+ name: 'UserApp',
+ component: UserApp,
+ },
+ {
+ path: 'new',
+ name: 'AddUserApp',
+ component: AddUserApp,
+ },
],
},
],
diff --git a/fittrackee_client/src/store/modules/oauth2/actions.ts b/fittrackee_client/src/store/modules/oauth2/actions.ts
index dd20c78c..56172a8f 100644
--- a/fittrackee_client/src/store/modules/oauth2/actions.ts
+++ b/fittrackee_client/src/store/modules/oauth2/actions.ts
@@ -1,13 +1,69 @@
import { ActionContext, ActionTree } from 'vuex'
import authApi from '@/api/authApi'
+import router from '@/router'
import { OAUTH2_STORE, ROOT_STORE } from '@/store/constants'
import { IOAuth2Actions, IOAuth2State } from '@/store/modules/oauth2/types'
import { IRootState } from '@/store/modules/root/types'
-import { IOauth2ClientsPayload } from '@/types/oauth'
+import { IOauth2ClientsPayload, IOAuth2ClientPayload } from '@/types/oauth'
import { handleError } from '@/utils'
export const actions: ActionTree & IOAuth2Actions = {
+ [OAUTH2_STORE.ACTIONS.CREATE_CLIENT](
+ context: ActionContext,
+ payload: IOAuth2ClientPayload
+ ): void {
+ context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
+ authApi
+ .post('oauth/apps', payload)
+ .then((res) => {
+ if (res.data.status === 'created') {
+ context
+ .dispatch(OAUTH2_STORE.ACTIONS.GET_CLIENTS)
+ .then(() => router.push('/profile/apps'))
+ } else {
+ handleError(context, null)
+ }
+ })
+ .catch((error) => handleError(context, error))
+ },
+ [OAUTH2_STORE.ACTIONS.DELETE_CLIENT](
+ context: ActionContext,
+ id: number
+ ): void {
+ context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
+ authApi
+ .delete(`oauth/apps/${id}`)
+ .then((res) => {
+ if (res.status === 204) {
+ context
+ .dispatch(OAUTH2_STORE.ACTIONS.GET_CLIENTS)
+ .then(() => router.push('/profile/apps'))
+ } else {
+ handleError(context, null)
+ }
+ })
+ .catch((error) => handleError(context, error))
+ },
+ [OAUTH2_STORE.ACTIONS.GET_CLIENT](
+ context: ActionContext,
+ id: string
+ ): void {
+ context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
+ authApi
+ .get(`oauth/apps/${id}`)
+ .then((res) => {
+ if (res.data.status === 'success') {
+ context.commit(
+ OAUTH2_STORE.MUTATIONS.SET_CLIENT,
+ res.data.data.client
+ )
+ } else {
+ handleError(context, null)
+ }
+ })
+ .catch((error) => handleError(context, error))
+ },
[OAUTH2_STORE.ACTIONS.GET_CLIENTS](
context: ActionContext,
payload: IOauth2ClientsPayload
diff --git a/fittrackee_client/src/store/modules/oauth2/enums.ts b/fittrackee_client/src/store/modules/oauth2/enums.ts
index a03f50ba..01daba7b 100644
--- a/fittrackee_client/src/store/modules/oauth2/enums.ts
+++ b/fittrackee_client/src/store/modules/oauth2/enums.ts
@@ -1,13 +1,19 @@
export enum OAuth2Actions {
+ CREATE_CLIENT = 'CREATE_CLIENT',
+ DELETE_CLIENT = 'DELETE_CLIENT',
GET_CLIENTS = 'GET_CLIENTS',
+ GET_CLIENT = 'GET_CLIENT',
}
export enum OAuth2Getters {
+ CLIENT = 'CLIENT',
CLIENTS = 'CLIENTS',
CLIENTS_PAGINATION = 'CLIENTS_PAGINATION',
}
export enum OAuth2Mutations {
+ EMPTY_CLIENT = 'EMPTY_CLIENT',
+ SET_CLIENT = 'SET_CLIENT',
SET_CLIENTS = 'SET_CLIENTS',
SET_CLIENTS_PAGINATION = 'SET_CLIENTS_PAGINATION',
}
diff --git a/fittrackee_client/src/store/modules/oauth2/getters.ts b/fittrackee_client/src/store/modules/oauth2/getters.ts
index c88f72b5..3eefa425 100644
--- a/fittrackee_client/src/store/modules/oauth2/getters.ts
+++ b/fittrackee_client/src/store/modules/oauth2/getters.ts
@@ -5,6 +5,7 @@ import { IOAuth2Getters, IOAuth2State } from '@/store/modules/oauth2/types'
import { IRootState } from '@/store/modules/root/types'
export const getters: GetterTree & IOAuth2Getters = {
+ [OAUTH2_STORE.GETTERS.CLIENT]: (state: IOAuth2State) => state.client,
[OAUTH2_STORE.GETTERS.CLIENTS]: (state: IOAuth2State) => state.clients,
[OAUTH2_STORE.GETTERS.CLIENTS_PAGINATION]: (state: IOAuth2State) =>
state.pagination,
diff --git a/fittrackee_client/src/store/modules/oauth2/mutations.ts b/fittrackee_client/src/store/modules/oauth2/mutations.ts
index 0480e0a2..505b58c9 100644
--- a/fittrackee_client/src/store/modules/oauth2/mutations.ts
+++ b/fittrackee_client/src/store/modules/oauth2/mutations.ts
@@ -6,6 +6,15 @@ import { IPagination } from '@/types/api'
import { IOAuth2Client } from '@/types/oauth'
export const mutations: MutationTree & TOAuth2Mutations = {
+ [OAUTH2_STORE.MUTATIONS.SET_CLIENT](
+ state: IOAuth2State,
+ client: IOAuth2Client
+ ) {
+ state.client = client
+ },
+ [OAUTH2_STORE.MUTATIONS.EMPTY_CLIENT](state: IOAuth2State) {
+ state.client = {}
+ },
[OAUTH2_STORE.MUTATIONS.SET_CLIENTS](
state: IOAuth2State,
clients: IOAuth2Client[]
diff --git a/fittrackee_client/src/store/modules/oauth2/state.ts b/fittrackee_client/src/store/modules/oauth2/state.ts
index 47c19e21..15814cb4 100644
--- a/fittrackee_client/src/store/modules/oauth2/state.ts
+++ b/fittrackee_client/src/store/modules/oauth2/state.ts
@@ -1,7 +1,9 @@
import { IOAuth2State } from '@/store/modules/oauth2/types'
import { IPagination } from '@/types/api'
+import { IOAuth2Client } from '@/types/oauth'
export const oAuth2State: IOAuth2State = {
+ client: {},
clients: [],
pagination: {},
}
diff --git a/fittrackee_client/src/store/modules/oauth2/types.ts b/fittrackee_client/src/store/modules/oauth2/types.ts
index 2c00c780..3ea5e852 100644
--- a/fittrackee_client/src/store/modules/oauth2/types.ts
+++ b/fittrackee_client/src/store/modules/oauth2/types.ts
@@ -8,14 +8,31 @@ import {
import { OAUTH2_STORE } from '@/store/constants'
import { IRootState } from '@/store/modules/root/types'
import { IPagination } from '@/types/api'
-import { IOAuth2Client, IOauth2ClientsPayload } from '@/types/oauth'
+import {
+ IOAuth2Client,
+ IOAuth2ClientPayload,
+ IOauth2ClientsPayload,
+} from '@/types/oauth'
export interface IOAuth2State {
+ client: IOAuth2Client
clients: IOAuth2Client[]
pagination: IPagination
}
export interface IOAuth2Actions {
+ [OAUTH2_STORE.ACTIONS.CREATE_CLIENT](
+ context: ActionContext,
+ payload: IOAuth2ClientPayload
+ ): void
+ [OAUTH2_STORE.ACTIONS.DELETE_CLIENT](
+ context: ActionContext,
+ id: number
+ ): void
+ [OAUTH2_STORE.ACTIONS.GET_CLIENT](
+ context: ActionContext,
+ id: string
+ ): void
[OAUTH2_STORE.ACTIONS.GET_CLIENTS](
context: ActionContext,
payload: IOauth2ClientsPayload
@@ -23,11 +40,14 @@ export interface IOAuth2Actions {
}
export interface IOAuth2Getters {
+ [OAUTH2_STORE.GETTERS.CLIENT](state: IOAuth2State): IOAuth2Client
[OAUTH2_STORE.GETTERS.CLIENTS](state: IOAuth2State): IOAuth2Client[]
[OAUTH2_STORE.GETTERS.CLIENTS_PAGINATION](state: IOAuth2State): IPagination
}
export type TOAuth2Mutations = {
+ [OAUTH2_STORE.MUTATIONS.EMPTY_CLIENT](state: S): void
+ [OAUTH2_STORE.MUTATIONS.SET_CLIENT](state: S, client: IOAuth2Client): void
[OAUTH2_STORE.MUTATIONS.SET_CLIENTS](state: S, clients: IOAuth2Client[]): void
[OAUTH2_STORE.MUTATIONS.SET_CLIENTS_PAGINATION](
state: S,
diff --git a/fittrackee_client/src/types/oauth.ts b/fittrackee_client/src/types/oauth.ts
index 4d1e070c..d3d4fc62 100644
--- a/fittrackee_client/src/types/oauth.ts
+++ b/fittrackee_client/src/types/oauth.ts
@@ -10,6 +10,14 @@ export interface IOAuth2Client {
website: string
}
+export interface IOAuth2ClientPayload {
+ client_name: string
+ client_uri: string
+ client_description: string | null
+ redirect_uris: string[]
+ scope: string
+}
+
export interface IOauth2ClientsPayload {
page?: number
}