Skip to content

Commit

Permalink
Merge pull request #14 from lemoncloud-io/feature/louis-update-azure-…
Browse files Browse the repository at this point in the history
…http2

Feature/louis update azure http2
  • Loading branch information
louis-lemon authored May 31, 2024
2 parents 7e5b089 + 8ba56c5 commit 3091400
Show file tree
Hide file tree
Showing 3 changed files with 318 additions and 28 deletions.
202 changes: 186 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div align="center">
<div>
<h1 align="center">lemon-web-core</h1>
<h1 align="center">LemonWebCore</h1>
</div>
<p>
Shared library for LEMONCLOUD
LemonWebCore is a library designed for API requests and user authentication management in web-based projects for different cloud providers such as AWS, Azure, and GCP at LemonCloud.
</p>
</div>

Expand All @@ -18,33 +18,203 @@

---

## Prerequisite
## Table of Contents

- [Node.js](https://nodejs.org/)
- [pnpm](https://pnpm.io/)
- [Installation](#installation)
- [Usage](#usage)
- [WebCoreFactory](#webcorefactory)
- [AWSWebCore](#awswebcore)
- [AzureWebCore](#azurewebcore)
- [API Reference](#api-reference)
- [Troubleshooting](#troubleshooting)

## Usage
## Installation

### Installation
You can install the LemonWebCore Library via npm:

```bash
$ git clone git@github.com:lemoncloud-io/lemon-web-core.git
$ cd lemon-web-core
$ pnpm install && pnpm prepare
npm install @lemoncloud/lemon-web-core
```

## Running the app
## Usage

The LemonWebCore Library allows you to create and use instances for different cloud providers. Below are the usage examples for WebCoreFactory, AWSWebCore, and AzureWebCore.

```bash
$ pnpm start
### WebCoreFactory

The `WebCoreFactory` is used to create instances of `AWSWebCore` or `AzureWebCore` based on the cloud provider configuration.

- AWSWebCore

```typescript
import { WebCoreFactory, WebCoreConfig } from '@lemoncloud/lemon-web-core';

const config: WebCoreConfig<'aws'> = {
cloud: 'aws',
project: 'my-aws-project',
oAuthEndpoint: 'https://example.com/oauth',
region: 'us-west-2',
};
const awsWebCore = WebCoreFactory.create(config);
await awsWebCore.init();
```

## Test
- AzureWebCore

```bash
$ pnpm test
```typescript
const azureConfig: WebCoreConfig<'azure'> = {
cloud: 'azure',
project: 'my-azure-project',
oAuthEndpoint: 'https://example.com/oauth',
};

const azureWebCore = WebCoreFactory.create(azureConfig);
await azureWebCore.init();
```

### AWSWebCore

The `AWSWebCore` class handles AWS-specific web core operations. Here is an example of how to use it:

```typescript
import { AWSWebCore, WebCoreConfig } from '@lemoncloud/lemon-web-core';

const config: WebCoreConfig<'aws'> = {
cloud: 'aws',
project: 'my-aws-project',
oAuthEndpoint: 'https://example.com/oauth',
region: 'us-west-2',
};

const awsWebCore = new AWSWebCore(config);

// Initialize
await awsWebCore.init();

// Make a signed request
const response = await awsWebCore.signedRequest('GET', 'https://example.com/api/resource');
console.log(response.data);

// Make a signed request with Builder
const example = await awsWebCore
.buildSignedRequest({
method: 'GET',
baseURL: `https://api.lemoncloud.io/v1/oauth`,
})
.setParams({ page: 0 })
.setBody({ date: 'example' })
.execute();

// Check authentication status
const isAuthenticated = await awsWebCore.isAuthenticated();
console.log(isAuthenticated);
```

### AzureWebCore

The `AzureWebCore` class handles Azure-specific web core operations. Here is an example of how to use it:

```typescript
import { AzureWebCore, WebCoreConfig } from '@lemoncloud/lemon-web-core';

const config: WebCoreConfig<'azure'> = {
cloud: 'azure',
project: 'my-azure-project',
oAuthEndpoint: 'https://example.com/oauth',
};

const azureWebCore = new AzureWebCore(config);

// Initialize
await azureWebCore.init();

// Make a signed request
const response = await azureWebCore.signedRequest('GET', 'https://example.com/api/resource');
console.log(response.data);

// Make a signed request with Builder
const example = await azureWebCore
.buildSignedRequest({
method: 'GET',
baseURL: `https://api.lemoncloud.io/v1/oauth`,
})
.setParams({ page: 0 })
.setBody({ date: 'example' })
.execute();

// Check authentication status
const isAuthenticated = await azureWebCore.isAuthenticated();
console.log(isAuthenticated);
```

## API Reference

### WebCoreFactory

- `create<T extends WebCoreService>(config: WebCoreConfig<CloudProvider>): T`

Creates an instance of `AWSWebCore` or `AzureWebCore` based on the provided cloud provider configuration.

### AWSWebCore

- `constructor(config: WebCoreConfig<'aws'>)`

Creates an instance of `AWSWebCore` with the specified configuration.

- `init(): Promise<void>`

Initializes the AWSWebCore instance.

- `signedRequest<T>(method: string, url: string, params?: Params, body?: Body, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>`

Makes a signed HTTP request.

- `isAuthenticated(): Promise<boolean>`

Checks if the user is authenticated.

- `saveOAuthToken(token: LemonOAuthToken): Promise<void>`

Saves the OAuth token.

- `logout(): Promise<void>`

Logs the user out by clearing the OAuth token.

- `setUseXLemonIdentity(use: boolean): Promise<void>`

Sets whether to use the x-lemon-identity header.

### AzureWebCore

- `constructor(config: WebCoreConfig<'azure'>)`

Creates an instance of `AzureWebCore` with the specified configuration.

- `init(): Promise<void>`

Initializes the AzureWebCore instance.

- `signedRequest<T>(method: string, url: string, params?: Params, body?: Body, config?: AxiosRequestConfig): Promise<AxiosResponse<T>>`

Makes a signed HTTP request.

- `isAuthenticated(): Promise<boolean>`

Checks if the user is authenticated.

- `saveOAuthToken(token: LemonOAuthToken): Promise<void>`

Saves the OAuth token.

- `logout(): Promise<void>`

Logs the user out by clearing the OAuth token.

- `setUseXLemonIdentity(use: boolean): Promise<void>`

Sets whether to use the x-lemon-identity header.

## Troubleshooting

Please follow this guidelines when reporting bugs and feature requests:
Expand Down
139 changes: 127 additions & 12 deletions src/core/azure-web.core.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,138 @@
import { WebCoreConfig, WebCoreService } from '../types';
import { AzureWebCoreState, Body, LemonOAuthToken, Params, WebCoreConfig, WebCoreService } from '../types';
import { AzureStorageService, USE_X_LEMON_IDENTITY_KEY } from '../token-storage';
import { LoggerService } from '../utils';
import { AxiosRequestConfig, AxiosResponse } from 'axios';
import { AzureHttpRequestBuilder } from '../http';

// TODO: implment Azure Core
/**
* Class to handle Azure-specific web core operations.
* Implements the WebCoreService interface.
*/
export class AzureWebCore implements WebCoreService {
constructor(private readonly config: WebCoreConfig<'azure'>) {}
isAuthenticated(): Promise<boolean> {
return Promise.resolve(false);
private readonly tokenStorage: AzureStorageService;
private readonly logger: LoggerService;

/**
* Creates an instance of AzureWebCore.
* @param {WebCoreConfig<'azure'>} config - The configuration for the Azure web core.
*/
constructor(private readonly config: WebCoreConfig<'azure'>) {
this.logger = new LoggerService('AzureCore');
this.logger.log('init AzureCore');
this.tokenStorage = new AzureStorageService(this.config);
}

logout(): Promise<void> {
return;
/**
* Initializes the Azure web core by checking for cached tokens.
* @returns {Promise<AzureWebCoreState>} - The state of the Azure web core after initialization.
*/
async init(): Promise<AzureWebCoreState> {
this.logger.log('initialize AzureCore');
const hasCachedToken = await this.tokenStorage.hasCachedToken();
if (!hasCachedToken) {
this.logger.warn('has no token!');
return 'no-token';
}

const shouldRefreshToken = await this.tokenStorage.shouldRefreshToken();
if (shouldRefreshToken) {
this.logger.info('should refresh token!');
// TODO: refresh azure token
}
return 'has-token';
}

/**
* Builds a signed request using the provided Axios configuration.
* @param {AxiosRequestConfig} config - The Axios request configuration.
* @returns {AzureHttpRequestBuilder} - The request builder for the signed request.
*/
buildSignedRequest(config: AxiosRequestConfig): AzureHttpRequestBuilder {
return new AzureHttpRequestBuilder(this.tokenStorage, config);
}

/**
* Executes a signed HTTP request.
* @template T
* @param {string} method - The HTTP method to use for the request.
* @param {string} url - The URL for the request.
* @param {Params} [params={}] - The URL parameters for the request.
* @param {Body} [body] - The request body.
* @param {AxiosRequestConfig} [config] - Additional Axios request configuration.
* @returns {Promise<AxiosResponse<T>>} - The Axios response.
*/
async signedRequest<T>(
method: string,
url: string,
params: Params = {},
body?: Body,
config?: AxiosRequestConfig
): Promise<AxiosResponse<T>> {
const builder = new AzureHttpRequestBuilder(this.tokenStorage, {
method,
baseURL: url,
params,
});
if (body) {
builder.setBody(body);
}
if (config) {
builder.addAxiosRequestConfig(config);
}
return await builder.execute();
}

request(): Promise<any> {
return Promise.resolve(undefined);
/**
* Retrieves all saved tokens from the storage.
* @returns {Promise<{ [key: string]: string }>} - An object containing all saved tokens.
*/
getSavedToken(): Promise<{ [key: string]: string }> {
return this.tokenStorage.getAllItems();
}

setUseXLemonIdentity(): void {}
/**
* Checks if the user is authenticated.
* @returns {Promise<boolean>} - True if authenticated, otherwise false.
*/
async isAuthenticated(): Promise<boolean> {
const hasCachedToken = await this.tokenStorage.hasCachedToken();
if (!hasCachedToken) {
return false;
}

const shouldRefreshToken = await this.tokenStorage.shouldRefreshToken();
if (shouldRefreshToken) {
this.logger.info('should refresh token!');
// TODO: refresh azure token
return true;
}
return true;
}

/**
* Saves an OAuth token to the storage.
* @param {LemonOAuthToken} token - The OAuth token to save.
* @returns {Promise<void>} - A promise that resolves when the token is saved.
*/
async saveOAuthToken(token: LemonOAuthToken): Promise<void> {
return await this.tokenStorage.saveOAuthToken(token);
}

/**
* Logs the user out by clearing the OAuth token from the storage.
* @returns {Promise<void>} - A promise that resolves when the user is logged out.
*/
async logout(): Promise<void> {
await this.tokenStorage.clearOAuthToken();
return;
}

getSavedToken(): Promise<{ [p: string]: string }> {
return Promise.resolve({});
/**
* Sets whether to use the x-lemon-identity header.
* @param {boolean} use - True to use the x-lemon-identity header, otherwise false.
* @returns {Promise<void>} - A promise that resolves when the setting is updated.
*/
async setUseXLemonIdentity(use: boolean): Promise<void> {
await this.tokenStorage.setItem(USE_X_LEMON_IDENTITY_KEY, `${use}`);
}
}
5 changes: 5 additions & 0 deletions src/types/lemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
*/
export type AWSWebCoreState = 'no-token' | 'refreshed' | 'build';

/**
* Represents the state of the Azure Web Core service.
*/
export type AzureWebCoreState = 'no-token' | 'has-token';

/**
* Represents the ARN of a KMS key in AWS.
*/
Expand Down

0 comments on commit 3091400

Please sign in to comment.