Skip to content
This repository was archived by the owner on Nov 5, 2025. It is now read-only.

Comments

[NEW] Api provider#61

Merged
rodrigok merged 16 commits intomasterfrom
webhooks
Sep 25, 2018
Merged

[NEW] Api provider#61
rodrigok merged 16 commits intomasterfrom
webhooks

Conversation

@rodrigok
Copy link
Member

@rodrigok rodrigok commented Sep 3, 2018

Closes #12

Rocket.Chat bridge implementation RocketChat/Rocket.Chat#11938

TODO

  • List provided webhooks on app's details page to be easy to copy
  • Add property to define hook as private or public
  • Add property to define hook security level
  • Property to provide curl samples for each hook

IMPROVEMENTS

  • Implement security level TOKEN_AUTH
  • Implement security level SHARED_SECRET

Webhook admin UI
image

Implementation example

// index.ts
import {
    IConfigurationExtend,
    ILogger,
} from '@rocket.chat/apps-engine/definition/accessors';
import { ApiSecurity, ApiVisibility } from '@rocket.chat/apps-engine/definition/api/IApi';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';

import { MessageEndpoint } from './endpoints';

export class JitsiApp extends App {
    constructor(info: IAppInfo, logger: ILogger) {
        super(info, logger);
    }

    protected async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
        await configuration.api.provideApi({
            visibility: ApiVisibility.PRIVATE,
            security: ApiSecurity.UNSECURE,
            endpoints: [
                new MessageEndpoint(),
            ],
        });
    }
}
// endpoints.ts
import { HttpStatusCode, IHttp, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
import { IApiRequest, IApiResponse } from '@rocket.chat/apps-engine/definition/api';
import { IApiEndpoint } from '@rocket.chat/apps-engine/definition/api/IApi';
import { example } from '@rocket.chat/apps-engine/definition/api/IApiExample';
import { IApiEndpointInfo } from '@rocket.chat/apps-engine/definition/api/IApiEndpointInfo';

export class MessageEndpoint implements IApiEndpoint {
    public path: string = 'message/:id';

    @example({
        params: {
            id: 'message_id',
        },
        query: {
            asd: '123',
        },
        headers: {
            'X-Auth': 'asd: 123',
        },
    })
    public async get(request: IApiRequest, endpoint: IApiEndpointInfo, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<IApiResponse> {
        return {
            status: HttpStatusCode.OK,
            headers: {
                'X-Auth': 'asd: 123',
            },
            content: {
                test: request.query.asd,
            },
        };
    }

    @example({
        params: {
            id: 'message_id',
        },
        query: {
            asd: '123',
        },
        content: {
            content: 1,
        },
    })
    public async post(request: IApiRequest, endpoint: IApiEndpointInfo, read: IRead, modify: IModify, http: IHttp, persis: IPersistence): Promise<IApiResponse> {
        return {
            status: HttpStatusCode.OK,
            content: request.content,
        };
    }
}

@codecov
Copy link

codecov bot commented Sep 3, 2018

Codecov Report

Merging #61 into master will increase coverage by 0.44%.
The diff coverage is 63.26%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #61      +/-   ##
==========================================
+ Coverage   60.58%   61.03%   +0.44%     
==========================================
  Files          51       55       +4     
  Lines        1799     1935     +136     
  Branches      278      299      +21     
==========================================
+ Hits         1090     1181      +91     
- Misses        709      754      +45
Impacted Files Coverage Δ
src/server/bridges/AppBridges.ts 100% <ø> (ø) ⬆️
src/server/compiler/AppCompiler.ts 22.98% <0%> (-0.89%) ⬇️
src/server/accessors/ConfigurationExtend.ts 100% <100%> (ø) ⬆️
src/server/managers/AppAccessorManager.ts 100% <100%> (ø) ⬆️
src/server/errors/PathAlreadyExistsError.ts 100% <100%> (ø)
src/server/AppManager.ts 16.3% <33.33%> (+0.48%) ⬆️
src/server/misc/Utilities.ts 46.34% <35.71%> (-0.33%) ⬇️
src/server/accessors/ApiExtend.ts 50% <50%> (ø)
src/server/managers/AppApi.ts 69.38% <69.38%> (ø)
src/server/managers/AppApiManager.ts 80% <80%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d3521ea...23d2768. Read the comment docs.

@rodrigok rodrigok changed the title [WIP ][NEW] Webhook provider [WIP] [NEW] Webhook provider Sep 3, 2018
@rodrigok rodrigok changed the title [WIP] [NEW] Webhook provider [NEW] Webhook provider Sep 7, 2018
Copy link
Contributor

@graywolf336 graywolf336 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll review this in more detail later, but I honestly think if we switch the IWebhook to be a class it will be extremely helpful. Like you described to me, it will allow us to provide generic utility/helper functions inside the class that are common things done by developers.

@rodrigok
Copy link
Member Author

rodrigok commented Sep 8, 2018

@graywolf336 can you provide some examples?

@piotrkochan
Copy link

piotrkochan commented Sep 13, 2018

awesome!

@graywolf336 for me Interfaces are fine

'patch',
];

export class AppWebhook {
Copy link
Contributor

@graywolf336 graywolf336 Sep 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of having two AppWebhook items within the managers folder? I think should combine them into one and keep the name of it to be AppWebhookManager, unless there's a valid reason I am overlooking.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look ASAP.

I'm planing to change the naming to API instead of Webhooks, what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodrigok @graywolf336 renamed from webhook to api.

@rodrigok rodrigok changed the title [NEW] Webhook provider [WIP] [NEW] Webhook provider Sep 20, 2018
@rodrigok
Copy link
Member Author

@geekgonecrazy awesome, can you remove the docs changes? I'm planning to move docs to a dedicated branch to prevent this mess on PRs as Bradley suggested some time ago.

This reverts commit fe17e36.
@geekgonecrazy geekgonecrazy changed the title [WIP] [NEW] Webhook provider [NEW] Api provider Sep 20, 2018
@geekgonecrazy
Copy link
Contributor

@rodrigok done :)

* will be generated automatically.
* @param `X-Auth-Token`
*/
// AUTH_TOKEN,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your plans for this? I see they're commented out, but might want to add some documentation in the code for App developers to let them know that more will be coming in the near future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the AUTH_TOKEN is already documented there, the idea is to have options to handle authentication automatically for the apps. But it's not clear the options for me now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's commented out, so it won't show up in the generated docs if I'm not mistaken..yeah I'm not sure the best route to go yet without putting forth much effort in thoughts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to have it in docs since we don't have it implemented yet, it's basically a reminder that we will have more options there.

* Path to complete the api URL. Example: https://{your-server-address}/api/apps/public/{your-app-id}/{path}
* or https://{your-server-address}/api/apps/private/{your-app-id}/{private-hash}/{path}
*/
path: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would you think about allowing param style route definitions? For example: /contacts/:contactId/numbers would result in the passed in contactId being a param. Maybe this can be a future plan for improvements

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This already works 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodrigok sweet! Maybe you can add some documentation so other developers are aware of it and can make usage of it 😃

export interface IApiExtend {
/**
* Adds an api which can be called by external services lateron.
* Should an api already exists an error will be thrown.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, to be honest I'm not a fan fo this. If we are allowing them to provide the api, then we need to allow more than one api to be passed in..which in a sense we are, via the apiEndpoints. However, I think this goes against the style of the provideSlashCommand and provideSetting, both of which allow more than one being provided. In my opinion, we need to stick with the same style to ensure a standard is kept and to reduce the amount of possible confusion to the App developers. Maybe we revert back to an interface that the App implements which gets called to return the apiEndpoint informations. Which would work well when installing an App, as the person installing the App will see that the App provides an apiEndpoint which external services will be able to call. And since an App can only implement it once, it would solve the issue along with it could be called after settings which the App developer could read a setting to allow the administrator to configure how it works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idk if I understood your point, but you are able to provide more than one API, mainly if you need different properties like visibility and security. Is that what you were meaning?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, you currently can provide more than one? The code documentation states that you can not: "Should an api already exists an error will be thrown."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the API we mean an endpoint, you can configure more than one API but containing different endpoints

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, you can have more than one API but different endpoints? If I call this method more than once, each time containing two different endpoints, will it error out or will it succeed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will succeed


switch (this.api.visibility) {
case ApiVisibility.PUBLIC:
this.basePath = `/api/apps/public/${app.getID()}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rodrigok what would you think about us making the nameSlug of the Apps to be unique and use it instead of the App's ID? This would help with the transition over to #56 (package.json) to slowly get rid of the usage of the id. As a result, and where the idea came to me from, the "endpoints" and urls generated/provided will be easier to use (and shorter) instead of having a long id in the url.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wan't to move the ID to be a unique ID based on name as NPM does, that way we keep using the ID here, just change how the ID would be generated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, so if we go with the name slug or a special smaller ID such as author:app-name then we could generate shorter urls and that would be a unique ID since the author couldn't have two of the same app names but two people could have the same App name as their author name would be different.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that will be in the future

@rodrigok rodrigok added this to the 1.1.0 milestone Sep 25, 2018
@rodrigok rodrigok merged commit d92a98d into master Sep 25, 2018
@rodrigok rodrigok deleted the webhooks branch September 25, 2018 19:11
@cuonghuunguyen
Copy link
Contributor

HI @graywolf336 @rodrigok, does your team have a plan to implement the other security level for the API in the next releases?

@rodrigok
Copy link
Member Author

@meomay503, unfortunately, no, it's not in our short roadmap.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants