Browse Source

Merge pull request #11752 from nextcloud/fix/noid/remove-access-token

fix(federation): remove accessToken from project, migrate to typescript
pull/11756/head
Maksim Sukharev 2 years ago
committed by GitHub
parent
commit
2fe9ad6163
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      package.json
  2. 2
      src/App.vue
  3. 2
      src/components/LeftSidebar/InvitationHandler.vue
  4. 2
      src/components/LeftSidebar/LeftSidebar.vue
  5. 18
      src/services/federationService.ts
  6. 7
      src/stores/__tests__/federation.spec.js
  7. 65
      src/stores/federation.ts
  8. 46
      src/types/index.ts
  9. 4
      tsconfig.json

4
package.json

@ -14,8 +14,8 @@
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint --ext .js,.vue src",
"lint:fix": "eslint --ext .js,.vue src --fix",
"lint": "eslint --ext .js,.ts,.vue src",
"lint:fix": "eslint --ext .js,.ts,.vue src --fix",
"stylelint": "stylelint css/*.css css/*.scss src/**/*.scss src/**/*.vue",
"stylelint:fix": "stylelint css/*.css css/*.scss src/**/*.scss src/**/*.vue --fix",
"analyze": "npm run analyze:stats && npm run analyze:serve",

2
src/App.vue

@ -64,7 +64,7 @@ import Router from './router/router.js'
import BrowserStorage from './services/BrowserStorage.js'
import { EventBus } from './services/EventBus.js'
import { leaveConversationSync } from './services/participantsService.js'
import { useFederationStore } from './stores/federation.js'
import { useFederationStore } from './stores/federation.ts'
import { checkBrowser } from './utils/browserCheck.js'
import { signalingKill } from './utils/webrtc/index.js'

2
src/components/LeftSidebar/InvitationHandler.vue

@ -84,7 +84,7 @@ import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import ConversationIcon from '../ConversationIcon.vue'
import { CONVERSATION } from '../../constants.js'
import { useFederationStore } from '../../stores/federation.js'
import { useFederationStore } from '../../stores/federation.ts'
export default {
name: 'InvitationHandler',

2
src/components/LeftSidebar/LeftSidebar.vue

@ -333,7 +333,7 @@ import {
} from '../../services/conversationsService.js'
import { EventBus } from '../../services/EventBus.js'
import { talkBroadcastChannel } from '../../services/talkBroadcastChannel.js'
import { useFederationStore } from '../../stores/federation.js'
import { useFederationStore } from '../../stores/federation.ts'
import { useTalkHashStore } from '../../stores/talkHash.js'
import CancelableRequest from '../../utils/cancelableRequest.js'
import { hasUnreadMentions, filterFunction } from '../../utils/conversation.js'

18
src/services/federationService.js → src/services/federationService.ts

@ -23,32 +23,34 @@
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
import type { acceptShareResponse, getSharesResponse, rejectShareResponse } from '../types'
/**
* Fetches list of shares for a current user
*
* @param {object} [options] options;
* @param [options] options;
*/
const getShares = async function(options) {
const getShares = async function(options?: object): getSharesResponse {
return axios.get(generateOcsUrl('apps/spreed/api/v1/federation/invitation', undefined, options), options)
}
/**
* Accept an invitation by provided id.
*
* @param {number} id invitation id;
* @param {object} [options] options;
* @param id invitation id;
* @param [options] options;
*/
const acceptShare = async function(id, options) {
const acceptShare = async function(id: number, options?: object): acceptShareResponse {
return axios.post(generateOcsUrl('apps/spreed/api/v1/federation/invitation/{id}', { id }, options), {}, options)
}
/**
* Reject an invitation by provided id.
*
* @param {number} id invitation id;
* @param {object} [options] options;
* @param id invitation id;
* @param [options] options;
*/
const rejectShare = async function(id, options) {
const rejectShare = async function(id: number, options?: object): rejectShareResponse {
return axios.delete(generateOcsUrl('apps/spreed/api/v1/federation/invitation/{id}', { id }, options), options)
}

7
src/stores/__tests__/federation.spec.js

@ -1,8 +1,8 @@
import { setActivePinia, createPinia } from 'pinia'
import { getShares, acceptShare, rejectShare } from '../../services/federationService.js'
import { getShares, acceptShare, rejectShare } from '../../services/federationService.ts'
import { generateOCSErrorResponse, generateOCSResponse } from '../../test-helpers.js'
import { useFederationStore } from '../federation.js'
import { useFederationStore } from '../federation.ts'
jest.mock('../../services/federationService', () => ({
getShares: jest.fn(),
@ -17,7 +17,6 @@ describe('federationStore', () => {
userId: 'user0',
state: 0,
localRoomId: 10,
accessToken: 'ACCESS_TOKEN',
remoteServerUrl: 'remote.nextcloud.com',
remoteToken: 'TOKEN_2',
remoteAttendeeId: 11,
@ -30,7 +29,6 @@ describe('federationStore', () => {
userId: 'user0',
state: 1,
localRoomId: 9,
accessToken: 'ACCESS_TOKEN',
remoteServerUrl: 'remote.nextcloud.com',
remoteToken: 'TOKEN_1',
remoteAttendeeId: 11,
@ -160,7 +158,6 @@ describe('federationStore', () => {
const room = {
id: 10,
remoteAccessToken: 'ACCESS_TOKEN',
}
const acceptResponse = generateOCSResponse({ payload: room })
acceptShare.mockResolvedValueOnce(acceptResponse)

65
src/stores/federation.js → src/stores/federation.ts

@ -24,39 +24,18 @@ import { defineStore } from 'pinia'
import Vue from 'vue'
import { showError } from '@nextcloud/dialogs'
import { getBaseUrl } from '@nextcloud/router'
import { FEDERATION } from '../constants.js'
import { getShares, acceptShare, rejectShare } from '../services/federationService.js'
import { getShares, acceptShare, rejectShare } from '../services/federationService.ts'
import type { Conversation, FederationInvite, NotificationInvite } from '../types'
/**
* @typedef {object} Share
* @property {string} accessToken the invitation access token
* @property {number} id the invitation id
* @property {number} localRoomId the invitation local room id
* @property {number} remoteAttendeeId the invitation remote attendee id
* @property {string} remoteServerUrl the invitation remote server URL
* @property {string} remoteToken the invitation remote token
* @property {string} roomName the invitation room name
* @property {number} state the invitation state
* @property {string} userId the invitation user id
* @property {string} inviterCloudId the inviter cloud id
* @property {string} inviterDisplayName the inviter display name
*/
/**
* @typedef {object} State
* @property {{[key: string]: Share}} pendingShares - pending invitations
* @property {{[key: string]: Share}} acceptedShares - accepted invitations
*/
/**
* Store for other app integrations (additional actions for messages, participants, e.t.c)
*
* @param {string} id store name
* @param {State} options.state store state structure
*/
type State = {
pendingShares: Record<string, FederationInvite & { loading?: 'accept' | 'reject' }>,
acceptedShares: Record<string, FederationInvite>,
}
export const useFederationStore = defineStore('federation', {
state: () => ({
state: (): State => ({
pendingShares: {},
acceptedShares: {},
}),
@ -64,7 +43,6 @@ export const useFederationStore = defineStore('federation', {
actions: {
/**
* Fetch pending invitations and keep them in store
*
*/
async getShares() {
try {
@ -84,19 +62,19 @@ export const useFederationStore = defineStore('federation', {
/**
* Add an invitation from notification to the store.
*
* @param {object} notification notification object
* @param notification notification object
*/
addInvitationFromNotification(notification) {
addInvitationFromNotification(notification: NotificationInvite) {
if (this.pendingShares[notification.objectId]) {
return
}
const [remoteServerUrl, remoteToken] = notification.messageRichParameters.roomName.id.split('::')
const { id, name } = notification.messageRichParameters.user1
const invitation = {
accessToken: null,
const invitation: FederationInvite = {
id: notification.objectId,
localRoomId: null,
remoteAttendeeId: null,
localRoomId: 0,
localCloudId: notification.user + '@' + getBaseUrl().replace('https://', ''),
remoteAttendeeId: 0,
remoteServerUrl,
remoteToken,
roomName: notification.messageRichParameters.roomName.name,
@ -111,10 +89,10 @@ export const useFederationStore = defineStore('federation', {
/**
* Mark an invitation as accepted in store.
*
* @param {number} id invitation id
* @param {object} conversation conversation object
* @param id invitation id
* @param conversation conversation object
*/
markInvitationAccepted(id, conversation) {
markInvitationAccepted(id: number, conversation: Conversation) {
if (!this.pendingShares[id]) {
return
}
@ -130,10 +108,9 @@ export const useFederationStore = defineStore('federation', {
/**
* Accept an invitation by provided id.
*
* @param {number} id invitation id
* @return {object} conversation to join
* @param id invitation id
*/
async acceptShare(id) {
async acceptShare(id: number): Promise<Conversation | undefined> {
if (!this.pendingShares[id]) {
return
}
@ -151,9 +128,9 @@ export const useFederationStore = defineStore('federation', {
/**
* Reject an invitation by provided id.
*
* @param {number} id invitation id
* @param id invitation id
*/
async rejectShare(id) {
async rejectShare(id: number) {
if (!this.pendingShares[id]) {
return
}

46
src/types/index.ts

@ -4,15 +4,42 @@ import type { components, operations } from './openapi/openapi-full.ts'
type ApiOptions<T> = { params: T }
type ApiResponse<T> = Promise<{ data: T }>
// Conversations
export type Conversation = components['schemas']['Room']
// Notifications
type NotificationAction = {
label: string,
link: string,
type: 'WEB' | 'POST' | 'DELETE' | string,
primary: boolean,
}
// Chats
type ParamObject = {
id: string,
name: string,
type: string,
}
export type Notification<T = Record<string, ParamObject & Record<string, unknown>>> = {
notificationId: number,
app: string,
user: string,
datetime: string,
objectType: string,
objectId: number,
subject: string,
message: string,
link: string,
subjectRich: string,
subjectRichParameters: T,
messageRich: string,
messageRichParameters: T,
icon: string,
shouldNotify: true,
actions: NotificationAction[],
}
// Conversations
export type Conversation = components['schemas']['Room']
// Chats
export type Mention = ParamObject & {
server?: string,
'call-type'?: string,
@ -48,3 +75,16 @@ export type getBotsResponse = ApiResponse<operations['bot-list-bots']['responses
export type getBotsAdminResponse = ApiResponse<operations['settings-admin-list-bots']['responses'][200]['content']['application/json']>
export type enableBotResponse = ApiResponse<operations['bot-enable-bot']['responses'][201]['content']['application/json']>
export type disableBotResponse = ApiResponse<operations['bot-disable-bot']['responses'][200]['content']['application/json']>
// Federations
export type FederationInvite = components['schemas']['FederationInvite']
type FederationInviteRichParameters = {
user1: ParamObject & { server: string },
roomName: ParamObject,
remoteServer: ParamObject,
}
export type NotificationInvite = Notification<FederationInviteRichParameters>
export type getSharesResponse = ApiResponse<operations['federation-get-shares']['responses'][200]['content']['application/json']>
export type acceptShareResponse = ApiResponse<operations['federation-accept-share']['responses'][200]['content']['application/json']>
export type rejectShareResponse = ApiResponse<operations['federation-reject-share']['responses'][200]['content']['application/json']>

4
tsconfig.json

@ -1,11 +1,11 @@
{
"extends": "@vue/tsconfig/tsconfig.json",
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "src/env.d.ts"],
"exclude": ["node_modules", "vendor"],
"compilerOptions": {
"outDir": "./js",
"allowJs": true,
"checkJs": true,
"checkJs": false,
"allowImportingTsExtensions": true,
"lib": ["ESNext"],
},

Loading…
Cancel
Save