Skip to content

Commit

Permalink
Update Daktela library and auth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
jirihofman committed Feb 23, 2024
1 parent aa13ddc commit 9dc9492
Show file tree
Hide file tree
Showing 6 changed files with 782 additions and 99 deletions.
23 changes: 21 additions & 2 deletions src/appmixer/daktela/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Generate module

```sh
```sh
appmixer init openapi ./daktela/openapi.yml ./daktela/
```

Expand All @@ -12,4 +12,23 @@ Apply the following manual updates since those are not covered by the OpenAPI ge

### auth.js

Keep as is.
Keep as is. Auth flow in Appmixer is as follows:

Connecting account:
- obtain username and password from the user
- obtain accessToken from the login endpoint

Using token in components:
- retrieve token from cache
- if not found, obtain it from the login endpoint and store it in cache

### `httpRequest()` methods
Keep retrieving accessToken from cache.

```js
// imports
const { getAccessTokenFromLoginEndpoint } = require('../../auth');

// httpRequest() method
const accessToken = await getAccessTokenFromLoginEndpoint(context);
```
37 changes: 30 additions & 7 deletions src/appmixer/daktela/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ module.exports = {
name: 'Username',
tooltip: 'Provide your username.'
},

password: {
type: 'password',
name: 'Password',
Expand All @@ -27,32 +26,56 @@ module.exports = {

requestProfileInfo: async context => {

console.log('requestProfileInfo');
const { result } = await daktelaWhoim(context);
console.log('user', result);

return { name: result.user.title || result.user.alias };
},

accountNameFromProfileInfo: 'name',

validate: async context => {

console.log('validate');
await daktelaWhoim(context);

return;
}
},

// This function is called in every component to get the access token from the login endpoint.
getAccessTokenFromLoginEndpoint: async function(context) {

const cacheKey = `daktela-access-token-${context.username || context.auth.username}`;
const cachedAccessToken = await context.staticCache.get(cacheKey);
if (cachedAccessToken) {
context.log({ step: '--getAccessTokenFromLoginEndpoint', cacheKey, cachedAccessToken });
return cachedAccessToken;
}

const { result } = await daktelaWhoim(context);
const accessToken = result.accessToken;
context.log({ step: '++getAccessTokenFromLoginEndpoint', cacheKey, accessToken });

// Cache the access token so that we don't have to call the login endpoint in every component.
await context.staticCache.set(
cacheKey,
accessToken,
context.config.accessTokenCacheTTL || (60 * 60 * 24 * 1000) // 24 hours
);

return accessToken;
}
};

async function daktelaWhoim(context) {

const { data } = await context.httpRequest({
url: `https://${context.instance}.daktela.com/api/v6/login.json`,
url: `https://${context.instance || context.auth.instance}.daktela.com/api/v6/login.json`,
method: 'POST',
data: {
username: context.username,
password: context.password
// When called from auth.js we have username and password in context.
// When called from other components we have username and password in context.auth.
username: context.username || context.auth.username,
password: context.password || context.auth.password
}
});

Expand Down
2 changes: 1 addition & 1 deletion src/appmixer/daktela/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {

getBaseUrl: function(context) {

let url = '{instance}.daktela.com';
let url = 'https://{instance}.daktela.com';
url = url.replaceAll('{instance}', context.auth?.instance || context.config?.instance || 'https://democz.daktela.com');
return url;
},
Expand Down
250 changes: 161 additions & 89 deletions src/appmixer/daktela/openapi.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
openapi: 3.0.0
servers:
- url: '{instance}.daktela.com'
- url: 'https://{instance}.daktela.com'
description: Daktela instance
variables:
instance:
description: Daktela instance
default: 'https://democz.daktela.com'

components:
securitySchemes:
accessToken:
type: http
scheme: basic

security:
- accessToken: []

Expand All @@ -25,97 +19,175 @@ info:
paths:
/api/v6/tickets.json:
get:
operationId: getTickets
security:
- accessToken: []
x-connector-pagination:
type: page
parameters:
offset: skip
limit: take
page: 100
results: result.data
count: result.count
parameters:
- name: accessToken
in: query
required: true
schema:
type: string
- name: filter
in: query
required: true
schema:
type: object
properties:
logic:
type: string
filters:
type: array
items:
type: object
properties:
field:
type: string
operator:
type: string
value:
type: string
responses:
'200':
description: A list of tickets
put:
parameters:
- name: accessToken
in: query
required: true
schema:
type: string
- name: comment
in: query
required: true
required: false
description: Filter tickets. See [Daktela API documentation](https://democz.daktela.com/external/apihelp/v6/working-with/tickets#example-1-url) for more information.
schema:
type: string
responses:
'200':
description: Comment added to ticket
post:
parameters:
- name: accessToken
in: query
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
category:
type: string
user:
type: string
stage:
type: string
title:
type: string
priority:
type: string
statuses:
type: array
items:
type: string
contact:
type: string
comment:
type: string
comment_add_files:
type: array
items:
description: A list of tickets
content:
application/json:
schema:
type: object
properties:
result:
type: object
properties:
name:
type: string
title:
type: string
size:
data:
type: array
items:
$ref: '#/components/schemas/Ticket'
count:
type: integer
type:
type: string
customFields:
type: object
responses:
'200':
description: Ticket created with comment and attachment
description: Total number of tickets
components:
securitySchemes:
accessToken:
type: apiKey
in: query
name: accessToken
schemas:
Ticket:
type: object
properties:
name:
type: integer
description: Unique name
title:
type: string
description: Subject of ticket
id_merge:
type: string
description: Merge ID
category:
type: string
description: Category
user:
type: string
description: User
email:
type: string
format: email
description: Email
contact:
type: string
description: Contact
parentTicket:
type: string
description: Parent ticket
isParent:
type: boolean
description: Parent flag
description:
type: string
description: Optional description
stage:
type: string
enum: [OPEN, WAIT, CLOSE]
description: Stage
priority:
type: string
enum: [LOW, MEDIUM, HIGH]
description: Level of priority
sla_overdue:
type: integer
description: SLA overdue in seconds
sla_deadtime:
type: string
format: date-time
description: Deadline
sla_close_deadline:
type: string
format: date-time
description: Ticket deadline
sla_change:
type: string
format: date-time
description: Sla change
sla_duration:
type: integer
description: Sla duration
sla_custom:
type: boolean
description: Sla custom
interaction_activity_count:
type: integer
description: Activity count
reopen:
type: string
format: date-time
description: Reopen
created:
type: string
format: date-time
description: Date of creation
created_by:
type: string
description: Created by
edited:
type: string
format: date-time
description: Date of last modification
edited_by:
type: string
description: Edited by
first_answer:
type: string
format: date-time
description: Date of first answer
first_answer_duration:
type: integer
description: First answer duration
first_answer_deadline:
type: string
format: date-time
description: First answer deadline
first_answer_overdue:
type: integer
description: First answer overdue in seconds
closed:
type: string
format: date-time
description: Date when the ticket was closed
unread:
type: boolean
description: Unread
has_attachment:
type: boolean
description: Has attachment
followers:
type: string
description: Followers
statuses:
type: string
description: Statuses
last_activity:
type: string
format: date-time
description: Last Activity
last_activity_operator:
type: string
format: date-time
description: Last Activity of Operator
last_activity_client:
type: string
format: date-time
description: Last Activity of Client
customFields:
type: string
description: Custom fields
Loading

0 comments on commit 9dc9492

Please sign in to comment.